diff --git a/src/stdio/vfprintf.c b/src/stdio/vfprintf.c index a712d80f..a9e4d638 100644 --- a/src/stdio/vfprintf.c +++ b/src/stdio/vfprintf.c @@ -33,7 +33,7 @@ enum { BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE, - ZTPRE, JPRE, + ZTPRE, JPRE, PLAIN, STOP, PTR, INT, UINT, ULLONG, LONG, ULONG, @@ -44,9 +44,10 @@ enum { MAXSTATE }; -#define S(x) [(x)-'A'] +#define ST_BASE 'A' +#define S(x) [(x)-ST_BASE] -static const unsigned char states[]['z'-'A'+1] = { +static const unsigned char states[]['z'-ST_BASE+1] = { { /* 0: bare types */ S('d') = INT, S('i') = INT, S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, @@ -94,10 +95,15 @@ static const unsigned char states[]['z'-'A'+1] = { S('o') = UMAX, S('u') = UMAX, S('x') = UMAX, S('X') = UMAX, S('n') = PTR, + }, { /* 8: explicit-width-prefixed bare equivalent */ + S('d') = INT, S('i') = INT, + S('o') = UINT, S('u') = UINT, + S('x') = UINT, S('X') = UINT, + S('n') = PTR, } }; -#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A') +#define OOB(x) ((unsigned)(x)-ST_BASE > 'z'-ST_BASE) union arg { @@ -510,6 +516,13 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, /* Format specifier state machine */ st=0; + if (*s=='w' && s[1]-'1'<9u) switch (getint(&s)) { + case 8: st = HHPRE; break; + case 16: st = HPRE; break; + case 32: st = PLAIN; break; + case 64: st = LLONG_MAX > LONG_MAX ? LLPRE : LPRE; break; + default: goto inval; + } do { if (OOB(*s)) goto inval; ps=st; @@ -547,6 +560,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, switch(t) { case 'n': switch(ps) { + case PLAIN: case BARE: *(int *)arg.p = cnt; break; case LPRE: *(long *)arg.p = cnt; break; case LLPRE: *(long long *)arg.p = cnt; break;