From 1f9122f229fcae6ceb374ecb2d835c229b6ce054 Mon Sep 17 00:00:00 2001 From: Chris Pressey Date: Mon, 14 Feb 2005 23:15:51 +0000 Subject: [PATCH] Partial merge with FreeBSD: revisions 1.23 through 1.34. Highlights: - Support C99 format specifiers %z, %t, %j, %hh. - Support locale-sensitive "thousands" seperators. - Some internal cleanup. --- lib/libc/stdio/vfprintf.c | 511 ++++++++++++++++++++++++++------------ 1 file changed, 349 insertions(+), 162 deletions(-) diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index 8bc8cb97d3..c24906687e 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -34,8 +34,8 @@ * SUCH DAMAGE. * * @(#)vfprintf.c 8.1 (Berkeley) 6/4/93 - * $FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.22.2.5 2002/10/12 10:46:37 schweikh Exp $ - * $DragonFly: src/lib/libc/stdio/vfprintf.c,v 1.6 2005/01/31 22:29:40 dillon Exp $ + * $FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.34 2001/12/13 19:45:41 phantom Exp $ + * $DragonFly: src/lib/libc/stdio/vfprintf.c,v 1.7 2005/02/14 23:15:51 cpressey Exp $ */ /* @@ -47,7 +47,11 @@ #include "namespace.h" #include +#include #include +#include +#include +#include #include #include #include @@ -62,12 +66,61 @@ /* Define FLOATING_POINT to get floating point. */ #define FLOATING_POINT -static int __sprint (FILE *, struct __suio *); -static int __sbprintf (FILE *, const char *, va_list); -static char * __ultoa (u_long, char *, int, int, char *); -static char * __uqtoa (u_quad_t, char *, int, int, char *); -static void __find_arguments (const char *, va_list, void ***); -static void __grow_type_table (int, unsigned char **, int *); +/* Borrowed from sys/systm.h, which is _KERNEL-only: */ +#define CTASSERT(x) _CTASSERT(x, __LINE__) +#define _CTASSERT(x, y) __CTASSERT(x, y) +#define __CTASSERT(x, y) typedef char __assert ## y[(x) ? 1 : -1] + +/* This code assumes that a quad_t can fit in a long long: */ +CTASSERT(sizeof(quad_t) == sizeof(long long)); + +union arg { + int intarg; + unsigned int uintarg; + long longarg; + unsigned long ulongarg; + long long longlongarg; + unsigned long long ulonglongarg; + ptrdiff_t ptrdiffarg; + size_t sizearg; + intmax_t intmaxarg; + uintmax_t uintmaxarg; + void *pvoidarg; + char *pchararg; + signed char *pschararg; + short *pshortarg; + int *pintarg; + long *plongarg; + long long *plonglongarg; + ptrdiff_t *pptrdiffarg; + size_t *psizearg; + intmax_t *pintmaxarg; +#ifdef FLOATING_POINT + double doublearg; + long double longdoublearg; +#endif +}; + +/* + * Type ids for argument type table. + */ +enum typeid { + T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT, + T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, + T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET, + T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, + T_DOUBLE, T_LONG_DOUBLE +}; + +static int __sprint(FILE *, struct __suio *); +static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); +static char * __ujtoa(uintmax_t, char *, int, int, char *, int, + char, const char *); +static char * __ultoa(u_long, char *, int, int, char *, int, + char, const char *); +static char * __uqtoa(u_quad_t, char *, int, int, char *); +static void __find_arguments(const char *, va_list, union arg **); +static void __grow_type_table(int, enum typeid **, int *); /* * Flush out all the vectors defined by the given uio, @@ -134,10 +187,12 @@ __sbprintf(FILE *fp, const char *fmt, va_list ap) * use the given digits. */ static char * -__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) +__ultoa(u_long val, char *endp, int base, int octzero, char *xdigs, + int needgrp, char thousep, const char *grp) { char *cp = endp; long sval; + int ndig; /* * Handle the three cases separately, in the hope of getting @@ -149,6 +204,7 @@ __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) *--cp = to_char(val); return (cp); } + ndig = 0; /* * On many machines, unsigned arithmetic is harder than * signed arithmetic, so we do at most one unsigned mod and @@ -157,11 +213,29 @@ __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) */ if (val > LONG_MAX) { *--cp = to_char(val % 10); + ndig++; sval = val / 10; } else sval = val; do { *--cp = to_char(sval % 10); + ndig++; + /* + * If (*grp == CHAR_MAX) then no more grouping + * should be performed. + */ + if (needgrp && ndig == *grp && *grp != CHAR_MAX && + sval > 9) { + *--cp = thousep; + ndig = 0; + /* + * If (*(grp+1) == '\0') then we have to + * use *grp character (last grouping rule) + * for all next cases + */ + if (*(grp + 1) != '\0') + grp++; + } sval /= 10; } while (sval != 0); break; @@ -188,32 +262,54 @@ __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs) return (cp); } -/* Identical to __ultoa, but for quads. */ +/* Identical to __ultoa, but for intmax_t. */ static char * -__uqtoa(u_quad_t val, char *endp, int base, int octzero, char *xdigs) +__ujtoa(u_quad_t val, char *endp, int base, int octzero, char *xdigs, + int needgrp, char thousep, const char *grp) { char *cp = endp; - quad_t sval; + intmax_t sval; + int ndig; /* quick test for small values; __ultoa is typically much faster */ /* (perhaps instead we should run until small, then call __ultoa?) */ if (val <= ULONG_MAX) - return (__ultoa((u_long)val, endp, base, octzero, xdigs)); + return (__ultoa((u_long)val, endp, base, octzero, xdigs, + needgrp, thousep, grp)); switch (base) { case 10: if (val < 10) { *--cp = to_char(val % 10); return (cp); } - if (val > QUAD_MAX) { + ndig = 0; + if (val > INTMAX_MAX) { *--cp = to_char(val % 10); + ndig++; sval = val / 10; } else sval = val; - do { - *--cp = to_char(sval % 10); - sval /= 10; - } while (sval != 0); + do { + *--cp = to_char(sval % 10); + ndig++; + /* + * If (*grp == CHAR_MAX) then no more grouping + * should be performed. + */ + if (needgrp && *grp != CHAR_MAX && ndig == *grp && + sval > 9) { + *--cp = thousep; + ndig = 0; + /* + * If (*(grp+1) == '\0') then we have to + * use *grp character (last grouping rule) + * for all next cases + */ + if (*(grp + 1) != '\0') + grp++; + } + sval /= 10; + } while (sval != 0); break; case 8: @@ -253,11 +349,10 @@ vfprintf(FILE *fp, const char *fmt0, va_list ap) } #ifdef FLOATING_POINT -#include #include #include "floatio.h" -#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ +#define BUF ((MAXEXP * 2) + MAXFRACT + 1) /* + decimal point */ #define DEFPREC 6 static char *cvt (double, int, int, char *, int *, int, int *, char **); @@ -265,7 +360,7 @@ static int exponent (char *, int, int); #else /* no FLOATING_POINT */ -#define BUF 68 +#define BUF 136 #endif /* FLOATING_POINT */ @@ -279,10 +374,16 @@ static int exponent (char *, int, int); #define LADJUST 0x004 /* left adjustment */ #define LONGDBL 0x008 /* long double */ #define LONGINT 0x010 /* long integer */ -#define QUADINT 0x020 /* quad integer */ +#define LLONGINT 0x020 /* long long integer */ #define SHORTINT 0x040 /* short integer */ #define ZEROPAD 0x080 /* zero (as opposed to blank) pad */ -#define FPT 0x100 /* Floating point number */ +#define FPT 0x100 /* Floating point number */ +#define GROUPING 0x200 /* use grouping ("'" flag) */ + /* C99 additional size modifiers: */ +#define SIZET 0x400 /* size_t */ +#define PTRDIFFT 0x800 /* ptrdiff_t */ +#define INTMAXT 0x1000 /* intmax_t */ +#define CHARINT 0x2000 /* print char using int format */ /* * Non-MT-safe version */ @@ -299,8 +400,10 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) int width; /* width from format (%8d), or 0 */ int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ -#ifdef FLOATING_POINT - char *decimal_point = localeconv()->decimal_point; + char thousands_sep; /* locale specific thousands separator */ + const char *grouping; /* locale specific numeric grouping rules */ + #ifdef FLOATING_POINT + char *decimal_point; /* locale specific decimal point */ char softsign; /* temporary negative sign for floats */ double _double; /* double precision arguments %[eEfgG] */ int expt; /* integer value of exponent */ @@ -310,7 +413,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) char *dtoaresult; /* buffer allocated by dtoa */ #endif u_long ulval; /* integer arguments %[diouxX] */ - u_quad_t uqval; /* %q integers */ + uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ int base; /* base for [diouxX] conversion */ int dprec; /* a copy of prec if [diouxX], 0 otherwise */ int realsz; /* field size expanded by dprec, sign, etc */ @@ -320,10 +423,10 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) #define NIOV 8 struct __suio uio; /* output information: summary */ struct __siov iov[NIOV];/* ... and individual io vectors */ - char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ - char ox[2]; /* space for 0x hex-prefix */ - void **argtable; /* args, built due to positional arg */ - void *statargtable [STATIC_ARG_TBL_SIZE]; + char buf[BUF]; /* space for %c, %[diouxX], %[eEfFgG] */ + char ox[2]; /* space for 0x hex-prefix */ + union arg *argtable; /* args, built due to positional arg */ + union arg statargtable[STATIC_ARG_TBL_SIZE]; int nextarg; /* 1-based argument index */ va_list orgap; /* original argument pointer */ @@ -374,7 +477,7 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) * argument (and arguments must be gotten sequentially). */ #define GETARG(type) \ - ((argtable != NULL) ? *((type*)(argtable[nextarg++])) : \ + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ (nextarg++, va_arg(ap, type))) /* @@ -384,11 +487,24 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) #define SARG() \ (flags&LONGINT ? GETARG(long) : \ flags&SHORTINT ? (long)(short)GETARG(int) : \ + flags&CHARINT ? (long)(signed char)GETARG(int) : \ (long)GETARG(int)) #define UARG() \ (flags&LONGINT ? GETARG(u_long) : \ flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \ + flags&CHARINT ? (u_long)(u_char)GETARG(int) : \ (u_long)GETARG(u_int)) +#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) +#define SJARG() \ + (flags&INTMAXT ? GETARG(intmax_t) : \ + flags&SIZET ? (intmax_t)GETARG(size_t) : \ + flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ + (intmax_t)GETARG(long long)) +#define UJARG() \ + (flags&INTMAXT ? GETARG(uintmax_t) : \ + flags&SIZET ? (uintmax_t)GETARG(size_t) : \ + flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ + (uintmax_t)GETARG(unsigned long long)) /* * Get * arguments, including the form *nn$. Preserve the nextarg @@ -414,10 +530,13 @@ __vfprintf(FILE *fp, const char *fmt0, va_list ap) } else { \ val = GETARG (int); \ } - + + thousands_sep = '\0'; + grouping = NULL; #ifdef FLOATING_POINT dtoaresult = NULL; + decimal_point = localeconv()->decimal_point; #endif /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ if (cantwrite(fp)) { @@ -495,6 +614,11 @@ reswitch: switch (ch) { case '+': sign = '+'; goto rflag; + case '\'': + flags |= GROUPING; + thousands_sep = *(localeconv()->thousands_sep); + grouping = localeconv()->grouping; + goto rflag; case '.': if ((ch = *fmt++) == '*') { GETASTER (n); @@ -540,16 +664,30 @@ reswitch: switch (ch) { goto rflag; #endif case 'h': - flags |= SHORTINT; + if (flags & SHORTINT) { + flags &= ~SHORTINT; + flags |= CHARINT; + } else + flags |= SHORTINT; + goto rflag; + case 'j': + flags |= INTMAXT; goto rflag; case 'l': - if (flags & LONGINT) - flags |= QUADINT; - else + if (flags & LONGINT) { + flags &= ~LONGINT; + flags |= LLONGINT; + } else flags |= LONGINT; goto rflag; case 'q': - flags |= QUADINT; + flags |= LLONGINT; + goto rflag; + case 't': + flags |= PTRDIFFT; + goto rflag; + case 'z': + flags |= SIZET; goto rflag; case 'c': *(cp = buf) = GETARG(int); @@ -561,10 +699,10 @@ reswitch: switch (ch) { /*FALLTHROUGH*/ case 'd': case 'i': - if (flags & QUADINT) { - uqval = GETARG(quad_t); - if ((quad_t)uqval < 0) { - uqval = -uqval; + if (flags & INTMAX_SIZE) { + ujval = SJARG(); + if ((intmax_t)ujval < 0) { + ujval = -ujval; sign = '-'; } } else { @@ -577,9 +715,22 @@ reswitch: switch (ch) { base = 10; goto number; #ifdef FLOATING_POINT +#ifdef HEXFLOAT + case 'a': + case 'A': +#endif case 'e': case 'E': + /* + * Grouping apply to %i, %d, %u, %f, %F, %g, %G + * conversion specifiers only. For other conversions + * behavior is undefined. + * -- POSIX + */ + flags &= ~GROUPING; + /*FALLTHROUGH*/ case 'f': + case 'F': goto fp_begin; case 'g': case 'G': @@ -596,12 +747,18 @@ fp_begin: if (prec == -1) if (isinf(_double)) { if (_double < 0) sign = '-'; - cp = "Inf"; + if (isupper(ch)) + cp = "INF"; + else + cp = "inf"; size = 3; break; } if (isnan(_double)) { - cp = "NaN"; + if (isupper(ch)) + cp = "NAN"; + else + cp = "nan"; size = 3; break; } @@ -618,13 +775,13 @@ fp_begin: if (prec == -1) else ch = 'g'; } - if (ch <= 'e') { /* 'e' or 'E' fmt */ + if (ch == 'e' || ch == 'E') { --expt; expsize = exponent(expstr, expt, ch); size = expsize + ndig; if (ndig > 1 || flags & ALT) ++size; - } else if (ch == 'f') { /* f fmt */ + } else if (ch == 'f' || ch == 'F') { if (expt > 0) { size = expt; if (prec || flags & ALT) @@ -644,12 +801,25 @@ fp_begin: if (prec == -1) break; #endif /* FLOATING_POINT */ case 'n': - if (flags & QUADINT) - *GETARG(quad_t *) = ret; + /* + * Assignment-like behavior is specified if the + * value overflows or is otherwise unrepresentable. + * C99 says to use `signed char' for %hhn conversions. + */ + if (flags & LLONGINT) + *GETARG(long long *) = ret; + else if (flags & SIZET) + *GETARG(ssize_t *) = (ssize_t)ret; + else if (flags & PTRDIFFT) + *GETARG(ptrdiff_t *) = ret; + else if (flags & INTMAXT) + *GETARG(intmax_t *) = ret; else if (flags & LONGINT) *GETARG(long *) = ret; else if (flags & SHORTINT) *GETARG(short *) = ret; + else if (flags & CHARINT) + *GETARG(signed char *) = ret; else *GETARG(int *) = ret; continue; /* no output */ @@ -657,8 +827,8 @@ fp_begin: if (prec == -1) flags |= LONGINT; /*FALLTHROUGH*/ case 'o': - if (flags & QUADINT) - uqval = GETARG(u_quad_t); + if (flags & INTMAX_SIZE) + ujval = UJARG(); else ulval = UARG(); base = 8; @@ -671,10 +841,10 @@ fp_begin: if (prec == -1) * defined manner.'' * -- ANSI X3J11 */ - ulval = (u_long)GETARG(void *); + ujval = (uintmax_t)(uintptr_t)GETARG(void *); base = 16; xdigs = "0123456789abcdef"; - flags = (flags & ~QUADINT) | HEXPREFIX; + flags = flags | INTMAXT | HEXPREFIX; ch = 'x'; goto nosign; case 's': @@ -702,8 +872,8 @@ fp_begin: if (prec == -1) flags |= LONGINT; /*FALLTHROUGH*/ case 'u': - if (flags & QUADINT) - uqval = GETARG(u_quad_t); + if (flags & INTMAX_SIZE) + ujval = UJARG(); else ulval = UARG(); base = 10; @@ -713,16 +883,18 @@ fp_begin: if (prec == -1) goto hex; case 'x': xdigs = "0123456789abcdef"; -hex: if (flags & QUADINT) - uqval = GETARG(u_quad_t); +hex: + if (flags & INTMAX_SIZE) + ujval = UJARG(); else ulval = UARG(); base = 16; /* leading 0x/X only if non-zero */ if (flags & ALT && - (flags & QUADINT ? uqval != 0 : ulval != 0)) + (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0)) flags |= HEXPREFIX; + flags &= ~GROUPING; /* unsigned conversions */ nosign: sign = '\0'; /* @@ -739,15 +911,19 @@ number: if ((dprec = prec) >= 0) * -- ANSI X3J11 */ cp = buf + BUF; - if (flags & QUADINT) { - if (uqval != 0 || prec != 0) - cp = __uqtoa(uqval, cp, base, - flags & ALT, xdigs); - } else { - if (ulval != 0 || prec != 0) - cp = __ultoa(ulval, cp, base, - flags & ALT, xdigs); - } + if (flags & INTMAX_SIZE) { + if (ujval != 0 || prec != 0) + cp = __ujtoa(ujval, cp, base, + flags & ALT, xdigs, + flags & GROUPING, thousands_sep, + grouping); + } else { + if (ulval != 0 || prec != 0) + cp = __ultoa(ulval, cp, base, + flags & ALT, xdigs, + flags & GROUPING, thousands_sep, + grouping); + } size = buf + BUF - cp; break; default: /* "%?" prints ?, unless ? is NUL */ @@ -878,27 +1054,6 @@ error: /* NOTREACHED */ } -/* - * Type ids for argument type table. - */ -#define T_UNUSED 0 -#define T_SHORT 1 -#define T_U_SHORT 2 -#define TP_SHORT 3 -#define T_INT 4 -#define T_U_INT 5 -#define TP_INT 6 -#define T_LONG 7 -#define T_U_LONG 8 -#define TP_LONG 9 -#define T_QUAD 10 -#define T_U_QUAD 11 -#define TP_QUAD 12 -#define T_DOUBLE 13 -#define T_LONG_DOUBLE 14 -#define TP_CHAR 15 -#define TP_VOID 16 - /* * Find all arguments when a positional parameter is encountered. Returns a * table, indexed by argument number, of pointers to each arguments. The @@ -906,7 +1061,7 @@ error: * It will be replaces with a malloc-ed one if it overflows. */ static void -__find_arguments (const char *fmt0, va_list ap, void ***argtable) +__find_arguments (const char *fmt0, va_list ap, union arg **argtable) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -914,8 +1069,8 @@ __find_arguments (const char *fmt0, va_list ap, void ***argtable) char *cp; /* handy char pointer (short term usage) */ int flags; /* flags as above */ int width; /* width from format (%8d), or 0 */ - unsigned char *typetable; /* table of types */ - unsigned char stattypetable [STATIC_ARG_TBL_SIZE]; + enum typeid *typetable; /* table of types */ + enum typeid stattypetable[STATIC_ARG_TBL_SIZE]; int tablesize; /* current size of type table */ int tablemax; /* largest used index in table */ int nextarg; /* 1-based argument index */ @@ -930,12 +1085,18 @@ __find_arguments (const char *fmt0, va_list ap, void ***argtable) typetable[nextarg++] = type) #define ADDSARG() \ - ((flags&LONGINT) ? ADDTYPE(T_LONG) : \ - ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT))) + ((flags&INTMAXT) ? ADDTYPE(T_INTMAXT) : \ + ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ + ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ + ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \ + ((flags&LONGINT) ? ADDTYPE(T_LONG) : ADDTYPE(T_INT)))))) #define ADDUARG() \ - ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \ - ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT))) + ((flags&INTMAXT) ? ADDTYPE(T_UINTMAXT) : \ + ((flags&SIZET) ? ADDTYPE(T_SIZET) : \ + ((flags&PTRDIFFT) ? ADDTYPE(T_PTRDIFFT) : \ + ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \ + ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : ADDTYPE(T_U_INT)))))) /* * Add * arguments to the type array. @@ -986,6 +1147,7 @@ reswitch: switch (ch) { goto rflag; case '-': case '+': + case '\'': goto rflag; case '.': if ((ch = *fmt++) == '*') { @@ -1016,18 +1178,32 @@ reswitch: switch (ch) { flags |= LONGDBL; goto rflag; #endif - case 'h': - flags |= SHORTINT; + case 'h': + if (flags & SHORTINT) { + flags &= ~SHORTINT; + flags |= CHARINT; + } else + flags |= SHORTINT; goto rflag; - case 'l': - if (flags & LONGINT) - flags |= QUADINT; - else - flags |= LONGINT; + case 'j': + flags |= INTMAXT; goto rflag; - case 'q': - flags |= QUADINT; + case 'l': + if (flags & LONGINT) { + flags &= ~LONGINT; + flags |= LLONGINT; + } else + flags |= LONGINT; + goto rflag; + case 'q': + flags |= LLONGINT; goto rflag; + case 't': + flags |= PTRDIFFT; + goto rflag; + case 'z': + flags |= SIZET; + goto rflag; case 'c': ADDTYPE(T_INT); break; @@ -1035,14 +1211,14 @@ reswitch: switch (ch) { flags |= LONGINT; /*FALLTHROUGH*/ case 'd': - case 'i': - if (flags & QUADINT) { - ADDTYPE(T_QUAD); - } else { - ADDSARG(); - } - break; + case 'i': + ADDSARG(); + break; #ifdef FLOATING_POINT +#ifdef HEXFLOAT + case 'a': + case 'A': +#endif case 'e': case 'E': case 'f': @@ -1055,12 +1231,20 @@ reswitch: switch (ch) { break; #endif /* FLOATING_POINT */ case 'n': - if (flags & QUADINT) - ADDTYPE(TP_QUAD); + if (flags & INTMAXT) + ADDTYPE(TP_INTMAXT); + else if (flags & PTRDIFFT) + ADDTYPE(TP_PTRDIFFT); + else if (flags & SIZET) + ADDTYPE(TP_SIZET); + else if (flags & LLONGINT) + ADDTYPE(TP_LLONG); else if (flags & LONGINT) ADDTYPE(TP_LONG); else if (flags & SHORTINT) ADDTYPE(TP_SHORT); + else if (flags & CHARINT) + ADDTYPE(TP_SCHAR); else ADDTYPE(TP_INT); continue; /* no output */ @@ -1068,10 +1252,7 @@ reswitch: switch (ch) { flags |= LONGINT; /*FALLTHROUGH*/ case 'o': - if (flags & QUADINT) - ADDTYPE(T_U_QUAD); - else - ADDUARG(); + ADDUARG(); break; case 'p': ADDTYPE(TP_VOID); @@ -1082,19 +1263,11 @@ reswitch: switch (ch) { case 'U': flags |= LONGINT; /*FALLTHROUGH*/ - case 'u': - if (flags & QUADINT) - ADDTYPE(T_U_QUAD); - else - ADDUARG(); - break; - case 'X': - case 'x': - if (flags & QUADINT) - ADDTYPE(T_U_QUAD); - else - ADDUARG(); - break; + case 'u': + case 'X': + case 'x': + ADDUARG(); + break; default: /* "%?" prints ?, unless ? is NUL */ if (ch == '\0') goto done; @@ -1106,63 +1279,77 @@ done: * Build the argument table. */ if (tablemax >= STATIC_ARG_TBL_SIZE) { - *argtable = (void **) - malloc (sizeof (void *) * (tablemax + 1)); + *argtable = (union arg *) + malloc(sizeof(union arg) * (tablemax + 1)); } - - (*argtable) [0] = NULL; + (*argtable)[0].intarg = 0; for (n = 1; n <= tablemax; n++) { switch (typetable [n]) { - case T_UNUSED: - (*argtable) [n] = (void *) &va_arg (ap, int); - break; - case T_SHORT: - (*argtable) [n] = (void *) &va_arg (ap, int); - break; - case T_U_SHORT: - (*argtable) [n] = (void *) &va_arg (ap, int); + case T_UNUSED: /* "whoops" */ + case T_INT: + (*argtable)[n].intarg = va_arg(ap, int); break; + case TP_SCHAR: + (*argtable) [n].pschararg = va_arg (ap, signed char *); case TP_SHORT: - (*argtable) [n] = (void *) &va_arg (ap, short *); - break; - case T_INT: - (*argtable) [n] = (void *) &va_arg (ap, int); + (*argtable)[n].pshortarg = va_arg(ap, short *); break; case T_U_INT: - (*argtable) [n] = (void *) &va_arg (ap, unsigned int); + (*argtable)[n].uintarg = va_arg(ap, unsigned int); break; case TP_INT: - (*argtable) [n] = (void *) &va_arg (ap, int *); + (*argtable)[n].pintarg = va_arg(ap, int *); break; case T_LONG: - (*argtable) [n] = (void *) &va_arg (ap, long); + (*argtable)[n].longarg = va_arg(ap, long); break; case T_U_LONG: - (*argtable) [n] = (void *) &va_arg (ap, unsigned long); + (*argtable)[n].ulongarg = va_arg(ap, unsigned long); break; case TP_LONG: - (*argtable) [n] = (void *) &va_arg (ap, long *); + (*argtable)[n].plongarg = va_arg(ap, long *); + break; + case T_LLONG: + (*argtable)[n].longlongarg = va_arg(ap, long long); + break; + case T_U_LLONG: + (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long); + break; + case TP_LLONG: + (*argtable)[n].plonglongarg = va_arg(ap, long long *); + break; + case T_PTRDIFFT: + (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t); + break; + case TP_PTRDIFFT: + (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *); + break; + case T_SIZET: + (*argtable)[n].sizearg = va_arg(ap, size_t); break; - case T_QUAD: - (*argtable) [n] = (void *) &va_arg (ap, quad_t); + case TP_SIZET: + (*argtable)[n].psizearg = va_arg(ap, ssize_t *); break; - case T_U_QUAD: - (*argtable) [n] = (void *) &va_arg (ap, u_quad_t); + case T_INTMAXT: + (*argtable)[n].intmaxarg = va_arg(ap, intmax_t); + break; + case T_UINTMAXT: + (*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t); break; - case TP_QUAD: - (*argtable) [n] = (void *) &va_arg (ap, quad_t *); + case TP_INTMAXT: + (*argtable)[n].pintmaxarg = va_arg (ap, intmax_t *); break; case T_DOUBLE: - (*argtable) [n] = (void *) &va_arg (ap, double); + (*argtable)[n].doublearg = va_arg(ap, double); break; case T_LONG_DOUBLE: - (*argtable) [n] = (void *) &va_arg (ap, long double); + (*argtable)[n].longdoublearg = va_arg(ap, long double); break; case TP_CHAR: - (*argtable) [n] = (void *) &va_arg (ap, char *); + (*argtable)[n].pchararg = va_arg(ap, char *); break; case TP_VOID: - (*argtable) [n] = (void *) &va_arg (ap, void *); + (*argtable)[n].pvoidarg = va_arg(ap, void *); break; } } @@ -1175,11 +1362,11 @@ done: * Increase the size of the type table. */ static void -__grow_type_table (int nextarg, unsigned char **typetable, int *tablesize) +__grow_type_table(int nextarg, enum typeid **typetable, int *tablesize) { - unsigned char *const oldtable = *typetable; + enum typeid * const oldtable = *typetable; const int oldsize = *tablesize; - unsigned char *newtable; + enum typeid *newtable; int newsize = oldsize * 2; if (newsize < nextarg + 1) -- 2.41.0