Fix precedence of printf flags

This commit is contained in:
Renaud 2021-06-14 15:51:46 +08:00
parent 77253914e1
commit d2836ddd55
1 changed files with 54 additions and 46 deletions

100
printf.c
View File

@ -17,9 +17,8 @@ size_t strlen( const char *s) {
return end - s ; return end - s ;
} }
#define ZEROPAD (1 << 3) #define LEFTALIGN (1 << 3)
#define LEFTALIGN (3 << 2) #define ZEROPAD (1 << 2)
#define LEFTMASK 4
#define PLUSSIGN (1 << 1) #define PLUSSIGN (1 << 1)
#define BLANKSIGN (1 << 0) #define BLANKSIGN (1 << 0)
@ -41,52 +40,62 @@ static int kputpad( char c, int len) {
kputc( c) ; kputc( c) ;
} else } else
cnt = 0 ; cnt = 0 ;
return cnt ;
}
static int kputwidth( char *s, int left_aligned, int width) {
int cnt = left_aligned ? 0 : kputpad( ' ', width - strlen( s)) ;
int size = kputs( s) ;
cnt += size ;
if( left_aligned)
cnt += kputpad( ' ', width - size) ;
return cnt ; return cnt ;
} }
static int kputu( unsigned u, int padlen, char fmt) { static int kputu( unsigned u, int flags, int width, char fmt) {
char s[ 12] ; /* room for 11 octal digit + EOS */ #define MAXDIGITS 11
char s[ MAXDIGITS + 1] ; /* room for 11 octal digit + EOS */
/* octal 37777777777, decimal -2147483647 */
char *p = &s[ sizeof s - 1] ; /* point to last byte */ char *p = &s[ sizeof s - 1] ; /* point to last byte */
char signprefix ; char signprefix ;
*p = 0 ; /* null terminated string */ *p = 0 ; /* null terminated string */
if( fmt != 'i')
int flags = padlen >> 28 ; /* ouxX (d has been converted to i) */
padlen &= 0x0FFFFFFF ; /* clear flags */ signprefix = 0 ;
if( fmt == 'i' && (0 > (int) u)) { else if( 0 > (int) u) {
u = - (int) u ; u = - (int) u ;
signprefix = '-' ; signprefix = '-' ;
} else } else
signprefix = signs[ flags & 3] ; signprefix = signs[ flags & 3] ;
if( signprefix)
padlen -= 1 ;
unsigned d = base[ fmt & 3] ; unsigned d = base[ fmt & 3] ;
fmt = fmt & 0x20 ; /* set uppercase bit */ fmt = fmt & 0x20 ; /* set uppercase bit */
do { do {
*--p = "0123456789ABCDEF"[ u % d] | fmt ; *--p = "0123456789ABCDEF"[ u % d] | fmt ;
padlen -= 1 ;
u /= d ; u /= d ;
} while( u) ; } while( u) ;
/* reuse u to calculate output length */ if( signprefix)
flags >>= 2 ; *--p = signprefix ;
if( !flags) /* Right align */
u += kputpad( ' ', padlen) ;
if( signprefix) { int size = MAXDIGITS - (p - s) ; /* string length */
kputc( signprefix) ; /* reuse u to return output length */
u += 1 ; if( width <= size)
} u = kputs( p) ;
else if( (flags & 0x0C) == ZEROPAD) { /* LEFTALIGN precedence over ZEROPAD */
/* handle zero padding */
if( signprefix)
kputc( *p++) ;
if( flags == (ZEROPAD >> 2)) kputpad( '0', width - size) ;
u += kputpad( '0', padlen) ; kputs( p) ;
u = width ;
u += kputs( p) ; } else
if( flags == (LEFTALIGN >> 2)) /* handle left and right alignment */
u += kputpad( ' ', padlen) ; u = kputwidth( p, flags >> 3, width) ;
return u ; return u ;
} }
@ -95,6 +104,7 @@ int printf( const char *fmt, ...) {
va_list ap ; va_list ap ;
int cnt = 0 ; int cnt = 0 ;
int c ; /* current char in format string */ int c ; /* current char in format string */
char *sp ;
va_start( ap, fmt) ; va_start( ap, fmt) ;
while( ( c = *fmt++) != 0) while( ( c = *fmt++) != 0)
@ -141,13 +151,14 @@ int printf( const char *fmt, ...) {
switch( c) { switch( c) {
case 'c': case 'c':
flags >>= 2 ; c = va_arg( ap, int) ;
if( !flags) /* right aligned */ if( width > 1) {
cnt += kputpad( ' ', width - 1) ; /* handle left and right alignment */
sp = (char *) &c ;
cnt += 1 ; kputc( va_arg( ap, int /* char */)) ; goto s_width ;
if( flags == (LEFTALIGN >> 2)) } else {
cnt += kputpad( ' ', width - 1) ; cnt += 1 ; kputc( c) ;
}
break ; break ;
case 'd': case 'd':
@ -158,19 +169,16 @@ int printf( const char *fmt, ...) {
case 'u': case 'u':
case 'x': case 'x':
case 'X': case 'X':
cnt += kputu( va_arg( ap, unsigned), width | flags << 28, c) ; cnt += kputu( va_arg( ap, unsigned), flags, width, c) ;
break ; break ;
case 's': { case 's':
char *argp = va_arg( ap, char *) ; sp = va_arg( ap, char *) ;
flags >>= 2 ; if( width)
if( !flags) /* right aligned */ /* handle left and right alignment */
cnt += kputpad( ' ', width - strlen( argp)) ; s_width:
cnt += kputwidth( sp, flags >> 3, width) ;
int size = kputs( argp) ; else
cnt += size ; cnt += kputs( sp) ;
if( flags == (LEFTMASK >> 2))
cnt += kputpad( ' ', width - size) ;
}
break ; break ;
default: default: