diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2008-05-16 14:28:54 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2008-05-16 14:28:54 +0000 |
commit | 6551b450ddb66727e4efb13a70e0741746a88bab (patch) | |
tree | 2ebf5595362f1a99703805d47e708e80f5c449e2 /lib/libc/stdio/vfprintf.c | |
parent | fd6a8b6e4f9e65f5ddb29f7906a32457887461c3 (diff) |
C99 says that for each va_copy() there must be a matching va_end().
Replace the non-portable hackery in __find_arguments() with a union.
From FreeBSD.
Diffstat (limited to 'lib/libc/stdio/vfprintf.c')
-rw-r--r-- | lib/libc/stdio/vfprintf.c | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index ea0082acb37..28659486d59 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfprintf.c,v 1.45 2008/05/13 18:52:25 millert Exp $ */ +/* $OpenBSD: vfprintf.c,v 1.46 2008/05/16 14:28:53 millert Exp $ */ /*- * Copyright (c) 1990 The Regents of the University of California. * All rights reserved. @@ -53,7 +53,35 @@ #include "local.h" #include "fvwrite.h" -static int __find_arguments(const char *fmt0, va_list ap, va_list **argtable, +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; + size_t ssizearg; + 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 *pssizearg; + intmax_t *pintmaxarg; +#ifdef FLOATING_POINT + double doublearg; + long double longdoublearg; +#endif +}; + +static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable, size_t *argtablesiz); static int __grow_type_table(unsigned char **typetable, int *tablesize); @@ -192,8 +220,8 @@ vfprintf(FILE *fp, const char *fmt0, __va_list ap) struct __siov iov[NIOV];/* ... and individual io vectors */ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ char ox[2]; /* space for 0x hex-prefix */ - va_list *argtable; /* args, built due to positional arg */ - va_list statargtable[STATIC_ARG_TBL_SIZE]; + union arg *argtable; /* args, built due to positional arg */ + union arg statargtable[STATIC_ARG_TBL_SIZE]; size_t argtablesiz; int nextarg; /* 1-based argument index */ va_list orgap; /* original argument pointer */ @@ -305,8 +333,8 @@ vfprintf(FILE *fp, const char *fmt0, __va_list ap) * argument (and arguments must be gotten sequentially). */ #define GETARG(type) \ - (((argtable != NULL) ? (void)(ap = argtable[nextarg]) : (void)0), \ - nextarg++, va_arg(ap, type)) + ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \ + (nextarg++, va_arg(ap, type))) _SET_ORIENTATION(fp, -1); /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ @@ -874,7 +902,7 @@ finish: * problematic since we have nested functions..) */ static int -__find_arguments(const char *fmt0, va_list ap, va_list **argtable, +__find_arguments(const char *fmt0, va_list ap, union arg **argtable, size_t *argtablesiz) { char *fmt; /* format string */ @@ -1096,7 +1124,7 @@ done: * Build the argument table. */ if (tablemax >= STATIC_ARG_TBL_SIZE) { - *argtablesiz = sizeof (va_list) * (tablemax + 1); + *argtablesiz = sizeof(union arg) * (tablemax + 1); *argtable = mmap(NULL, *argtablesiz, PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0); if (*argtable == MAP_FAILED) @@ -1105,10 +1133,9 @@ done: #if 0 /* XXX is this required? */ - (*argtable) [0] = NULL; + (*argtable)[0].intarg = 0; #endif for (n = 1; n <= tablemax; n++) { - va_copy((*argtable)[n], ap); switch (typetable[n]) { case T_UNUSED: case T_CHAR: @@ -1116,64 +1143,66 @@ done: case T_SHORT: case T_U_SHORT: case T_INT: - (void) va_arg(ap, int); + (*argtable)[n].intarg = va_arg(ap, int); break; case TP_SHORT: - (void) va_arg(ap, short *); + (*argtable)[n].pshortarg = va_arg(ap, short *); break; case T_U_INT: - (void) va_arg(ap, unsigned int); + (*argtable)[n].uintarg = va_arg(ap, unsigned int); break; case TP_INT: - (void) va_arg(ap, int *); + (*argtable)[n].pintarg = va_arg(ap, int *); break; case T_LONG: - (void) va_arg(ap, long); + (*argtable)[n].longarg = va_arg(ap, long); break; case T_U_LONG: - (void) va_arg(ap, unsigned long); + (*argtable)[n].ulongarg = va_arg(ap, unsigned long); break; case TP_LONG: - (void) va_arg(ap, long *); + (*argtable)[n].plongarg = va_arg(ap, long *); break; case T_LLONG: - (void) va_arg(ap, long long); + (*argtable)[n].longlongarg = va_arg(ap, long long); break; case T_U_LLONG: - (void) va_arg(ap, unsigned long long); + (*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long); break; case TP_LLONG: - (void) va_arg(ap, long long *); + (*argtable)[n].plonglongarg = va_arg(ap, long long *); break; +#ifdef FLOATING_POINT case T_DOUBLE: - (void) va_arg(ap, double); + (*argtable)[n].doublearg = va_arg(ap, double); break; case T_LONG_DOUBLE: - (void) va_arg(ap, long double); + (*argtable)[n].longdoublearg = va_arg(ap, long double); break; +#endif case TP_CHAR: - (void) va_arg(ap, char *); + (*argtable)[n].pchararg = va_arg(ap, char *); break; case TP_VOID: - (void) va_arg(ap, void *); + (*argtable)[n].pvoidarg = va_arg(ap, void *); break; case T_PTRINT: - (void) va_arg(ap, ptrdiff_t); + (*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t); break; case TP_PTRINT: - (void) va_arg(ap, ptrdiff_t *); + (*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *); break; case T_SIZEINT: - (void) va_arg(ap, size_t); + (*argtable)[n].sizearg = va_arg(ap, size_t); break; case T_SSIZEINT: - (void) va_arg(ap, ssize_t); + (*argtable)[n].ssizearg = va_arg(ap, ssize_t); break; case TP_SSIZEINT: - (void) va_arg(ap, ssize_t *); + (*argtable)[n].pssizearg = va_arg(ap, ssize_t *); break; case TP_MAXINT: - (void) va_arg(ap, intmax_t *); + (*argtable)[n].intmaxarg = va_arg(ap, intmax_t); break; } } |