summaryrefslogtreecommitdiff
path: root/lib/libc/stdio/vfprintf.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2008-05-16 14:28:54 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2008-05-16 14:28:54 +0000
commit6551b450ddb66727e4efb13a70e0741746a88bab (patch)
tree2ebf5595362f1a99703805d47e708e80f5c449e2 /lib/libc/stdio/vfprintf.c
parentfd6a8b6e4f9e65f5ddb29f7906a32457887461c3 (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.c89
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;
}
}