2020-12-04 19:13:29 -05:00
|
|
|
/* printf.c -- format and print data */
|
|
|
|
/* Copyright (c) 2020 Renaud Fivet */
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "system.h" /* kputc(), kputs() */
|
|
|
|
|
2020-12-16 22:03:48 -05:00
|
|
|
static int kputu( unsigned u, unsigned d, int padlen, char fmt) {
|
2020-12-04 19:13:29 -05:00
|
|
|
char s[ 12] ; /* room for 11 octal digit + EOS */
|
|
|
|
char *p = &s[ sizeof s - 1] ; /* point to last byte */
|
|
|
|
|
|
|
|
*p = 0 ; /* null terminated string */
|
2020-12-16 22:03:48 -05:00
|
|
|
fmt = fmt & 0x20 ; /* set uppercase bit */
|
2020-12-04 19:13:29 -05:00
|
|
|
do {
|
|
|
|
unsigned r = u % d ;
|
|
|
|
u /= d ;
|
2020-12-16 22:03:48 -05:00
|
|
|
*--p = "0123456789ABCDEF"[ r] | fmt ;
|
|
|
|
padlen -= 1 ;
|
2020-12-04 19:13:29 -05:00
|
|
|
} while( u) ;
|
|
|
|
|
2020-12-16 22:03:48 -05:00
|
|
|
while( padlen-- > 0) {
|
|
|
|
kputc( '0') ;
|
|
|
|
u += 1 ; /* use u to calculate output length */
|
|
|
|
}
|
|
|
|
|
|
|
|
return u + kputs( p) ;
|
2020-12-04 19:13:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
static int kputi( int i) {
|
|
|
|
int flag = i < 0 ;
|
|
|
|
if( flag) {
|
|
|
|
i = -i ;
|
|
|
|
kputc( '-') ;
|
|
|
|
}
|
|
|
|
|
2020-12-16 22:03:48 -05:00
|
|
|
return flag + kputu( i, 10, 0, 'u') ;
|
2020-12-04 19:13:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
int printf( const char *fmt, ...) {
|
|
|
|
va_list ap ;
|
|
|
|
int cnt = 0 ;
|
|
|
|
int c ; /* current char in format string */
|
|
|
|
|
|
|
|
va_start( ap, fmt) ;
|
|
|
|
while( ( c = *fmt++) != 0)
|
|
|
|
if( c != '%') {
|
|
|
|
cnt += 1 ; kputc( c) ;
|
2020-12-16 22:03:48 -05:00
|
|
|
} else {
|
|
|
|
int len = 0 ;
|
|
|
|
|
|
|
|
c = *fmt++ ;
|
|
|
|
while( c >= '0' && c <= '9') {
|
|
|
|
len = len * 10 + ( c - '0') ;
|
|
|
|
c = *fmt++ ;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( c == 0)
|
|
|
|
break ;
|
|
|
|
|
2020-12-04 19:13:29 -05:00
|
|
|
switch( c) {
|
|
|
|
case 'c':
|
|
|
|
cnt += 1 ; kputc( va_arg( ap, int /* char */)) ;
|
|
|
|
break ;
|
|
|
|
case 'o':
|
2020-12-16 22:03:48 -05:00
|
|
|
cnt += kputu( va_arg( ap, unsigned), 8, len, c) ;
|
2020-12-04 19:13:29 -05:00
|
|
|
break ;
|
|
|
|
case 'u':
|
2020-12-16 22:03:48 -05:00
|
|
|
cnt += kputu( va_arg( ap, unsigned), 10, len, c) ;
|
2020-12-04 19:13:29 -05:00
|
|
|
break ;
|
|
|
|
case 'x':
|
|
|
|
case 'X':
|
2020-12-16 22:03:48 -05:00
|
|
|
cnt += kputu( va_arg( ap, unsigned), 16, len, c) ;
|
2020-12-04 19:13:29 -05:00
|
|
|
break ;
|
|
|
|
case 'i':
|
|
|
|
case 'd':
|
|
|
|
cnt += kputi( va_arg( ap, int)) ;
|
|
|
|
break ;
|
|
|
|
case 's':
|
|
|
|
cnt += kputs( va_arg( ap, char *)) ;
|
|
|
|
break ;
|
|
|
|
default:
|
|
|
|
cnt += 1 ; kputc( '%') ;
|
|
|
|
/* fallthrough */
|
|
|
|
case '%':
|
|
|
|
cnt += 1 ; kputc( c) ;
|
|
|
|
}
|
2020-12-16 22:03:48 -05:00
|
|
|
}
|
2020-12-04 19:13:29 -05:00
|
|
|
|
|
|
|
va_end( ap) ;
|
|
|
|
return cnt ;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* end of printf.c */
|