xref: /openbsd/lib/libc/stdio/vfprintf.c (revision 55cc5ba3)
1 /*	$OpenBSD: vfprintf.c,v 1.79 2020/10/27 21:06:57 deraadt Exp $	*/
2 /*-
3  * Copyright (c) 1990 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Chris Torek.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 /*
35  * Actual printf innards.
36  *
37  * This code is large and complicated...
38  */
39 
40 #include <sys/types.h>
41 #include <sys/mman.h>
42 
43 #include <errno.h>
44 #include <langinfo.h>
45 #include <limits.h>
46 #include <stdarg.h>
47 #include <stddef.h>
48 #include <stdio.h>
49 #include <stdint.h>
50 #include <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53 #include <syslog.h>
54 #include <wchar.h>
55 
56 #include "local.h"
57 #include "fvwrite.h"
58 
59 static const char n_msg[] = ": *printf used %n: ";
60 static int n_report;
61 
62 union arg {
63 	int			intarg;
64 	unsigned int		uintarg;
65 	long			longarg;
66 	unsigned long		ulongarg;
67 	long long		longlongarg;
68 	unsigned long long	ulonglongarg;
69 	ptrdiff_t		ptrdiffarg;
70 	size_t			sizearg;
71 	ssize_t			ssizearg;
72 	intmax_t		intmaxarg;
73 	uintmax_t		uintmaxarg;
74 	void			*pvoidarg;
75 	char			*pchararg;
76 	signed char		*pschararg;
77 	short			*pshortarg;
78 	int			*pintarg;
79 	long			*plongarg;
80 	long long		*plonglongarg;
81 	ptrdiff_t		*pptrdiffarg;
82 	ssize_t			*pssizearg;
83 	intmax_t		*pintmaxarg;
84 #ifdef FLOATING_POINT
85 	double			doublearg;
86 	long double		longdoublearg;
87 #endif
88 #ifdef PRINTF_WIDE_CHAR
89 	wint_t			wintarg;
90 	wchar_t			*pwchararg;
91 #endif
92 };
93 
94 static int __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
95     size_t *argtablesiz);
96 static int __grow_type_table(unsigned char **typetable, int *tablesize);
97 
98 /*
99  * Flush out all the vectors defined by the given uio,
100  * then reset it so that it can be reused.
101  */
102 static int
103 __sprint(FILE *fp, struct __suio *uio)
104 {
105 	int err;
106 
107 	if (uio->uio_resid == 0) {
108 		uio->uio_iovcnt = 0;
109 		return (0);
110 	}
111 	err = __sfvwrite(fp, uio);
112 	uio->uio_resid = 0;
113 	uio->uio_iovcnt = 0;
114 	return (err);
115 }
116 
117 /*
118  * Helper function for `fprintf to unbuffered unix file': creates a
119  * temporary buffer.  We only work on write-only files; this avoids
120  * worries about ungetc buffers and so forth.
121  */
122 static int
123 __sbprintf(FILE *fp, const char *fmt, va_list ap)
124 {
125 	int ret;
126 	FILE fake;
127 	struct __sfileext fakeext;
128 	unsigned char buf[BUFSIZ];
129 
130 	_FILEEXT_SETUP(&fake, &fakeext);
131 	/* copy the important variables */
132 	fake._flags = fp->_flags & ~__SNBF;
133 	fake._file = fp->_file;
134 	fake._cookie = fp->_cookie;
135 	fake._write = fp->_write;
136 
137 	/* set up the buffer */
138 	fake._bf._base = fake._p = buf;
139 	fake._bf._size = fake._w = sizeof(buf);
140 	fake._lbfsize = 0;	/* not actually used, but Just In Case */
141 
142 	/* do the work, then copy any error status */
143 	ret = __vfprintf(&fake, fmt, ap);
144 	if (ret >= 0 && __sflush(&fake))
145 		ret = EOF;
146 	if (fake._flags & __SERR)
147 		fp->_flags |= __SERR;
148 	return (ret);
149 }
150 
151 #ifdef PRINTF_WIDE_CHAR
152 /*
153  * Convert a wide character string argument for the %ls format to a multibyte
154  * string representation. If not -1, prec specifies the maximum number of
155  * bytes to output, and also means that we can't assume that the wide char
156  * string is null-terminated.
157  */
158 static char *
159 __wcsconv(wchar_t *wcsarg, int prec)
160 {
161 	mbstate_t mbs;
162 	char buf[MB_LEN_MAX];
163 	wchar_t *p;
164 	char *convbuf;
165 	size_t clen, nbytes;
166 
167 	/* Allocate space for the maximum number of bytes we could output. */
168 	if (prec < 0) {
169 		memset(&mbs, 0, sizeof(mbs));
170 		p = wcsarg;
171 		nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
172 		if (nbytes == (size_t)-1)
173 			return (NULL);
174 	} else {
175 		/*
176 		 * Optimisation: if the output precision is small enough,
177 		 * just allocate enough memory for the maximum instead of
178 		 * scanning the string.
179 		 */
180 		if (prec < 128)
181 			nbytes = prec;
182 		else {
183 			nbytes = 0;
184 			p = wcsarg;
185 			memset(&mbs, 0, sizeof(mbs));
186 			for (;;) {
187 				clen = wcrtomb(buf, *p++, &mbs);
188 				if (clen == 0 || clen == (size_t)-1 ||
189 				    nbytes + clen > (size_t)prec)
190 					break;
191 				nbytes += clen;
192 			}
193 			if (clen == (size_t)-1)
194 				return (NULL);
195 		}
196 	}
197 	if ((convbuf = malloc(nbytes + 1)) == NULL)
198 		return (NULL);
199 
200 	/* Fill the output buffer. */
201 	p = wcsarg;
202 	memset(&mbs, 0, sizeof(mbs));
203 	if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
204 	    nbytes, &mbs)) == (size_t)-1) {
205 		free(convbuf);
206 		return (NULL);
207 	}
208 	convbuf[nbytes] = '\0';
209 	return (convbuf);
210 }
211 #endif
212 
213 #ifdef FLOATING_POINT
214 #include <float.h>
215 #include <locale.h>
216 #include <math.h>
217 #include "floatio.h"
218 #include "gdtoa.h"
219 
220 #define	DEFPREC		6
221 
222 static int exponent(char *, int, int);
223 #endif /* FLOATING_POINT */
224 
225 /*
226  * The size of the buffer we use as scratch space for integer
227  * conversions, among other things.  Technically, we would need the
228  * most space for base 10 conversions with thousands' grouping
229  * characters between each pair of digits.  100 bytes is a
230  * conservative overestimate even for a 128-bit uintmax_t.
231  */
232 #define BUF	100
233 
234 #define STATIC_ARG_TBL_SIZE 8	/* Size of static argument table. */
235 
236 
237 /*
238  * Macros for converting digits to letters and vice versa
239  */
240 #define	to_digit(c)	((c) - '0')
241 #define is_digit(c)	((unsigned)to_digit(c) <= 9)
242 #define	to_char(n)	((n) + '0')
243 
244 /*
245  * Flags used during conversion.
246  */
247 #define	ALT		0x0001		/* alternate form */
248 #define	LADJUST		0x0004		/* left adjustment */
249 #define	LONGDBL		0x0008		/* long double */
250 #define	LONGINT		0x0010		/* long integer */
251 #define	LLONGINT	0x0020		/* long long integer */
252 #define	SHORTINT	0x0040		/* short integer */
253 #define	ZEROPAD		0x0080		/* zero (as opposed to blank) pad */
254 #define FPT		0x0100		/* Floating point number */
255 #define PTRINT		0x0200		/* (unsigned) ptrdiff_t */
256 #define SIZEINT		0x0400		/* (signed) size_t */
257 #define CHARINT		0x0800		/* 8 bit integer */
258 #define MAXINT		0x1000		/* largest integer size (intmax_t) */
259 
260 int
261 vfprintf(FILE *fp, const char *fmt0, __va_list ap)
262 {
263 	int ret;
264 
265 	FLOCKFILE(fp);
266 	ret = __vfprintf(fp, fmt0, ap);
267 	FUNLOCKFILE(fp);
268 	return (ret);
269 }
270 DEF_STRONG(vfprintf);
271 
272 int
273 __vfprintf(FILE *fp, const char *fmt0, __va_list ap)
274 {
275 	char *fmt;		/* format string */
276 	int ch;			/* character from fmt */
277 	int n, n2;		/* handy integers (short term usage) */
278 	char *cp;		/* handy char pointer (short term usage) */
279 	struct __siov *iovp;	/* for PRINT macro */
280 	int flags;		/* flags as above */
281 	int ret;		/* return value accumulator */
282 	int width;		/* width from format (%8d), or 0 */
283 	int prec;		/* precision from format; <0 for N/A */
284 	char sign;		/* sign prefix (' ', '+', '-', or \0) */
285 #ifdef FLOATING_POINT
286 	/*
287 	 * We can decompose the printed representation of floating
288 	 * point numbers into several parts, some of which may be empty:
289 	 *
290 	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
291 	 *    A       B     ---C---      D       E   F
292 	 *
293 	 * A:	'sign' holds this value if present; '\0' otherwise
294 	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
295 	 * C:	cp points to the string MMMNNN.  Leading and trailing
296 	 *	zeros are not in the string and must be added.
297 	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
298 	 * F:	at least two digits for decimal, at least one digit for hex
299 	 */
300 	char *decimal_point = NULL;
301 	int signflag;		/* true if float is negative */
302 	union {			/* floating point arguments %[aAeEfFgG] */
303 		double dbl;
304 		long double ldbl;
305 	} fparg;
306 	int expt;		/* integer value of exponent */
307 	char expchar;		/* exponent character: [eEpP\0] */
308 	char *dtoaend;		/* pointer to end of converted digits */
309 	int expsize;		/* character count for expstr */
310 	int lead;		/* sig figs before decimal or group sep */
311 	int ndig;		/* actual number of digits returned by dtoa */
312 	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
313 	char *dtoaresult = NULL;
314 #endif
315 
316 	uintmax_t _umax;	/* integer arguments %[diouxX] */
317 	enum { OCT, DEC, HEX } base;	/* base for %[diouxX] conversion */
318 	int dprec;		/* a copy of prec if %[diouxX], 0 otherwise */
319 	int realsz;		/* field size expanded by dprec */
320 	int size;		/* size of converted field or string */
321 	const char *xdigs;	/* digits for %[xX] conversion */
322 #define NIOV 8
323 	struct __suio uio;	/* output information: summary */
324 	struct __siov iov[NIOV];/* ... and individual io vectors */
325 	char buf[BUF];		/* buffer with space for digits of uintmax_t */
326 	char ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
327 	union arg *argtable;	/* args, built due to positional arg */
328 	union arg statargtable[STATIC_ARG_TBL_SIZE];
329 	size_t argtablesiz;
330 	int nextarg;		/* 1-based argument index */
331 	va_list orgap;		/* original argument pointer */
332 #ifdef PRINTF_WIDE_CHAR
333 	char *convbuf;		/* buffer for wide to multi-byte conversion */
334 #endif
335 
336 	/*
337 	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
338 	 * fields occur frequently, increase PADSIZE and make the initialisers
339 	 * below longer.
340 	 */
341 #define	PADSIZE	16		/* pad chunk size */
342 	static char blanks[PADSIZE] =
343 	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
344 	static char zeroes[PADSIZE] =
345 	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
346 
347 	static const char xdigs_lower[16] = "0123456789abcdef";
348 	static const char xdigs_upper[16] = "0123456789ABCDEF";
349 
350 	/*
351 	 * BEWARE, these `goto error' on error, and PAD uses `n'.
352 	 */
353 #define	PRINT(ptr, len) do { \
354 	iovp->iov_base = (ptr); \
355 	iovp->iov_len = (len); \
356 	uio.uio_resid += (len); \
357 	iovp++; \
358 	if (++uio.uio_iovcnt >= NIOV) { \
359 		if (__sprint(fp, &uio)) \
360 			goto error; \
361 		iovp = iov; \
362 	} \
363 } while (0)
364 #define	PAD(howmany, with) do { \
365 	if ((n = (howmany)) > 0) { \
366 		while (n > PADSIZE) { \
367 			PRINT(with, PADSIZE); \
368 			n -= PADSIZE; \
369 		} \
370 		PRINT(with, n); \
371 	} \
372 } while (0)
373 #define	PRINTANDPAD(p, ep, len, with) do {	\
374 	n2 = (ep) - (p);       			\
375 	if (n2 > (len))				\
376 		n2 = (len);			\
377 	if (n2 > 0)				\
378 		PRINT((p), n2);			\
379 	PAD((len) - (n2 > 0 ? n2 : 0), (with));	\
380 } while(0)
381 #define	FLUSH() do { \
382 	if (uio.uio_resid && __sprint(fp, &uio)) \
383 		goto error; \
384 	uio.uio_iovcnt = 0; \
385 	iovp = iov; \
386 } while (0)
387 
388 	/*
389 	 * To extend shorts properly, we need both signed and unsigned
390 	 * argument extraction methods.
391 	 */
392 #define	SARG() \
393 	((intmax_t)(flags&MAXINT ? GETARG(intmax_t) : \
394 	    flags&LLONGINT ? GETARG(long long) : \
395 	    flags&LONGINT ? GETARG(long) : \
396 	    flags&PTRINT ? GETARG(ptrdiff_t) : \
397 	    flags&SIZEINT ? GETARG(ssize_t) : \
398 	    flags&SHORTINT ? (short)GETARG(int) : \
399 	    flags&CHARINT ? (signed char)GETARG(int) : \
400 	    GETARG(int)))
401 #define	UARG() \
402 	((uintmax_t)(flags&MAXINT ? GETARG(uintmax_t) : \
403 	    flags&LLONGINT ? GETARG(unsigned long long) : \
404 	    flags&LONGINT ? GETARG(unsigned long) : \
405 	    flags&PTRINT ? (uintptr_t)GETARG(ptrdiff_t) : /* XXX */ \
406 	    flags&SIZEINT ? GETARG(size_t) : \
407 	    flags&SHORTINT ? (unsigned short)GETARG(int) : \
408 	    flags&CHARINT ? (unsigned char)GETARG(int) : \
409 	    GETARG(unsigned int)))
410 
411 	/*
412 	 * Append a digit to a value and check for overflow.
413 	 */
414 #define APPEND_DIGIT(val, dig) do { \
415 	if ((val) > INT_MAX / 10) \
416 		goto overflow; \
417 	(val) *= 10; \
418 	if ((val) > INT_MAX - to_digit((dig))) \
419 		goto overflow; \
420 	(val) += to_digit((dig)); \
421 } while (0)
422 
423 	 /*
424 	  * Get * arguments, including the form *nn$.  Preserve the nextarg
425 	  * that the argument can be gotten once the type is determined.
426 	  */
427 #define GETASTER(val) \
428 	n2 = 0; \
429 	cp = fmt; \
430 	while (is_digit(*cp)) { \
431 		APPEND_DIGIT(n2, *cp); \
432 		cp++; \
433 	} \
434 	if (*cp == '$') { \
435 		int hold = nextarg; \
436 		if (argtable == NULL) { \
437 			argtable = statargtable; \
438 			if (__find_arguments(fmt0, orgap, &argtable, \
439 			    &argtablesiz) == -1) { \
440 				ret = -1; \
441 				goto error; \
442 			} \
443 		} \
444 		nextarg = n2; \
445 		val = GETARG(int); \
446 		nextarg = hold; \
447 		fmt = ++cp; \
448 	} else { \
449 		val = GETARG(int); \
450 	}
451 
452 /*
453 * Get the argument indexed by nextarg.   If the argument table is
454 * built, use it to get the argument.  If its not, get the next
455 * argument (and arguments must be gotten sequentially).
456 */
457 #define GETARG(type) \
458 	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
459 		(nextarg++, va_arg(ap, type)))
460 
461 	_SET_ORIENTATION(fp, -1);
462 	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
463 	if (cantwrite(fp)) {
464 		errno = EBADF;
465 		return (EOF);
466 	}
467 
468 	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
469 	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
470 	    fp->_file >= 0)
471 		return (__sbprintf(fp, fmt0, ap));
472 
473 	fmt = (char *)fmt0;
474 	argtable = NULL;
475 	nextarg = 1;
476 	va_copy(orgap, ap);
477 	uio.uio_iov = iovp = iov;
478 	uio.uio_resid = 0;
479 	uio.uio_iovcnt = 0;
480 	ret = 0;
481 #ifdef PRINTF_WIDE_CHAR
482 	convbuf = NULL;
483 #endif
484 
485 	/*
486 	 * Scan the format for conversions (`%' character).
487 	 */
488 	for (;;) {
489 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
490 			continue;
491 
492 		if (fmt != cp) {
493 			ptrdiff_t m = fmt - cp;
494 			if (m < 0 || m > INT_MAX - ret)
495 				goto overflow;
496 			PRINT(cp, m);
497 			ret += m;
498 		}
499 		if (ch == '\0')
500 			goto done;
501 		fmt++;		/* skip over '%' */
502 
503 		flags = 0;
504 		dprec = 0;
505 		width = 0;
506 		prec = -1;
507 		sign = '\0';
508 		ox[1] = '\0';
509 
510 rflag:		ch = *fmt++;
511 reswitch:	switch (ch) {
512 		case ' ':
513 			/*
514 			 * ``If the space and + flags both appear, the space
515 			 * flag will be ignored.''
516 			 *	-- ANSI X3J11
517 			 */
518 			if (!sign)
519 				sign = ' ';
520 			goto rflag;
521 		case '#':
522 			flags |= ALT;
523 			goto rflag;
524 		case '\'':
525 			/* grouping not implemented */
526 			goto rflag;
527 		case '*':
528 			/*
529 			 * ``A negative field width argument is taken as a
530 			 * - flag followed by a positive field width.''
531 			 *	-- ANSI X3J11
532 			 * They don't exclude field widths read from args.
533 			 */
534 			GETASTER(width);
535 			if (width >= 0)
536 				goto rflag;
537 			if (width == INT_MIN)
538 				goto overflow;
539 			width = -width;
540 			/* FALLTHROUGH */
541 		case '-':
542 			flags |= LADJUST;
543 			goto rflag;
544 		case '+':
545 			sign = '+';
546 			goto rflag;
547 		case '.':
548 			if ((ch = *fmt++) == '*') {
549 				GETASTER(n);
550 				prec = n < 0 ? -1 : n;
551 				goto rflag;
552 			}
553 			n = 0;
554 			while (is_digit(ch)) {
555 				APPEND_DIGIT(n, ch);
556 				ch = *fmt++;
557 			}
558 			if (ch == '$') {
559 				nextarg = n;
560 				if (argtable == NULL) {
561 					argtable = statargtable;
562 					if (__find_arguments(fmt0, orgap,
563 					    &argtable, &argtablesiz) == -1) {
564 						ret = -1;
565 						goto error;
566 					}
567 				}
568 				goto rflag;
569 			}
570 			prec = n;
571 			goto reswitch;
572 		case '0':
573 			/*
574 			 * ``Note that 0 is taken as a flag, not as the
575 			 * beginning of a field width.''
576 			 *	-- ANSI X3J11
577 			 */
578 			flags |= ZEROPAD;
579 			goto rflag;
580 		case '1': case '2': case '3': case '4':
581 		case '5': case '6': case '7': case '8': case '9':
582 			n = 0;
583 			do {
584 				APPEND_DIGIT(n, ch);
585 				ch = *fmt++;
586 			} while (is_digit(ch));
587 			if (ch == '$') {
588 				nextarg = n;
589 				if (argtable == NULL) {
590 					argtable = statargtable;
591 					if (__find_arguments(fmt0, orgap,
592 					    &argtable, &argtablesiz) == -1) {
593 						ret = -1;
594 						goto error;
595 					}
596 				}
597 				goto rflag;
598 			}
599 			width = n;
600 			goto reswitch;
601 #ifdef FLOATING_POINT
602 		case 'L':
603 			flags |= LONGDBL;
604 			goto rflag;
605 #endif
606 		case 'h':
607 			if (*fmt == 'h') {
608 				fmt++;
609 				flags |= CHARINT;
610 			} else {
611 				flags |= SHORTINT;
612 			}
613 			goto rflag;
614 		case 'j':
615 			flags |= MAXINT;
616 			goto rflag;
617 		case 'l':
618 			if (*fmt == 'l') {
619 				fmt++;
620 				flags |= LLONGINT;
621 			} else {
622 				flags |= LONGINT;
623 			}
624 			goto rflag;
625 		case 'q':
626 			flags |= LLONGINT;
627 			goto rflag;
628 		case 't':
629 			flags |= PTRINT;
630 			goto rflag;
631 		case 'z':
632 			flags |= SIZEINT;
633 			goto rflag;
634 		case 'c':
635 #ifdef PRINTF_WIDE_CHAR
636 			if (flags & LONGINT) {
637 				mbstate_t mbs;
638 				size_t mbseqlen;
639 
640 				memset(&mbs, 0, sizeof(mbs));
641 				mbseqlen = wcrtomb(buf,
642 				    (wchar_t)GETARG(wint_t), &mbs);
643 				if (mbseqlen == (size_t)-1) {
644 					ret = -1;
645 					goto error;
646 				}
647 				cp = buf;
648 				size = (int)mbseqlen;
649 			} else {
650 #endif
651 				*(cp = buf) = GETARG(int);
652 				size = 1;
653 #ifdef PRINTF_WIDE_CHAR
654 			}
655 #endif
656 			sign = '\0';
657 			break;
658 		case 'D':
659 			flags |= LONGINT;
660 			/*FALLTHROUGH*/
661 		case 'd':
662 		case 'i':
663 			_umax = SARG();
664 			if ((intmax_t)_umax < 0) {
665 				_umax = -_umax;
666 				sign = '-';
667 			}
668 			base = DEC;
669 			goto number;
670 #ifdef FLOATING_POINT
671 		case 'a':
672 		case 'A':
673 			if (ch == 'a') {
674 				ox[1] = 'x';
675 				xdigs = xdigs_lower;
676 				expchar = 'p';
677 			} else {
678 				ox[1] = 'X';
679 				xdigs = xdigs_upper;
680 				expchar = 'P';
681 			}
682 			if (prec >= 0)
683 				prec++;
684 			if (dtoaresult)
685 				__freedtoa(dtoaresult);
686 			if (flags & LONGDBL) {
687 				fparg.ldbl = GETARG(long double);
688 				dtoaresult = cp =
689 				    __hldtoa(fparg.ldbl, xdigs, prec,
690 				    &expt, &signflag, &dtoaend);
691 				if (dtoaresult == NULL) {
692 					errno = ENOMEM;
693 					goto error;
694 				}
695 			} else {
696 				fparg.dbl = GETARG(double);
697 				dtoaresult = cp =
698 				    __hdtoa(fparg.dbl, xdigs, prec,
699 				    &expt, &signflag, &dtoaend);
700 				if (dtoaresult == NULL) {
701 					errno = ENOMEM;
702 					goto error;
703 				}
704 			}
705 			if (prec < 0)
706 				prec = dtoaend - cp;
707 			if (expt == INT_MAX)
708 				ox[1] = '\0';
709 			goto fp_common;
710 		case 'e':
711 		case 'E':
712 			expchar = ch;
713 			if (prec < 0)	/* account for digit before decpt */
714 				prec = DEFPREC + 1;
715 			else
716 				prec++;
717 			goto fp_begin;
718 		case 'f':
719 		case 'F':
720 			expchar = '\0';
721 			goto fp_begin;
722 		case 'g':
723 		case 'G':
724 			expchar = ch - ('g' - 'e');
725  			if (prec == 0)
726  				prec = 1;
727 fp_begin:
728 			if (prec < 0)
729 				prec = DEFPREC;
730 			if (dtoaresult)
731 				__freedtoa(dtoaresult);
732 			if (flags & LONGDBL) {
733 				fparg.ldbl = GETARG(long double);
734 				dtoaresult = cp =
735 				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
736 				    &expt, &signflag, &dtoaend);
737 				if (dtoaresult == NULL) {
738 					errno = ENOMEM;
739 					goto error;
740 				}
741 			} else {
742 				fparg.dbl = GETARG(double);
743 				dtoaresult = cp =
744 				    __dtoa(fparg.dbl, expchar ? 2 : 3, prec,
745 				    &expt, &signflag, &dtoaend);
746 				if (dtoaresult == NULL) {
747 					errno = ENOMEM;
748 					goto error;
749 				}
750 				if (expt == 9999)
751 					expt = INT_MAX;
752  			}
753 fp_common:
754 			if (signflag)
755 				sign = '-';
756 			if (expt == INT_MAX) {	/* inf or nan */
757 				if (*cp == 'N')
758 					cp = (ch >= 'a') ? "nan" : "NAN";
759 				else
760 					cp = (ch >= 'a') ? "inf" : "INF";
761  				size = 3;
762 				flags &= ~ZEROPAD;
763  				break;
764  			}
765 			flags |= FPT;
766 			ndig = dtoaend - cp;
767  			if (ch == 'g' || ch == 'G') {
768 				if (expt > -4 && expt <= prec) {
769 					/* Make %[gG] smell like %[fF] */
770 					expchar = '\0';
771 					if (flags & ALT)
772 						prec -= expt;
773 					else
774 						prec = ndig - expt;
775 					if (prec < 0)
776 						prec = 0;
777 				} else {
778 					/*
779 					 * Make %[gG] smell like %[eE], but
780 					 * trim trailing zeroes if no # flag.
781 					 */
782 					if (!(flags & ALT))
783 						prec = ndig;
784 				}
785  			}
786 			if (expchar) {
787 				expsize = exponent(expstr, expt - 1, expchar);
788 				size = expsize + prec;
789 				if (prec > 1 || flags & ALT)
790  					++size;
791 			} else {
792 				/* space for digits before decimal point */
793 				if (expt > 0)
794 					size = expt;
795 				else	/* "0" */
796 					size = 1;
797 				/* space for decimal pt and following digits */
798 				if (prec || flags & ALT)
799 					size += prec + 1;
800 				lead = expt;
801 			}
802 			break;
803 #endif /* FLOATING_POINT */
804 #ifndef NO_PRINTF_PERCENT_N
805 		case 'n': {
806 			int maxprot = 0;
807 
808 #ifdef notyet
809 			if (mprotections(fmt0, strlen(fmt0) + 1,
810 			    &maxprot) == -1)
811 				maxprot = 0;
812 			maxprot &= ~PROT_READ;
813 #endif
814 
815 			if (n_report == 0 || maxprot) {
816 				char buf[1024], *p;
817 
818 				/* <10> is LOG_CRIT */
819 				strlcpy(buf, "<10>", sizeof buf);
820 
821 				/* XXX */
822 				if ((p = getenv("_THIS_PORT")) != NULL) {
823 					strlcat(buf, p, sizeof buf);
824 					strlcat(buf, " ", sizeof buf);
825 				}
826 
827 				/* Make sure progname does not fill the whole buffer */
828 				strlcat(buf, __progname, sizeof(buf) - sizeof n_msg);
829 				strlcat(buf, n_msg, sizeof buf);
830 				strlcat(buf, fmt0, sizeof buf);
831 				if ((p = strchr(buf, '\n')))
832 					*p = '\0';
833 				if (maxprot)
834 					strlcat(buf, ": aborting", sizeof buf);
835 				sendsyslog(buf, strlen(buf), LOG_CONS);
836 				n_report = 1;
837 			}
838 
839 			if (maxprot)
840 				abort();
841 
842 			if (flags & LLONGINT)
843 				*GETARG(long long *) = ret;
844 			else if (flags & LONGINT)
845 				*GETARG(long *) = ret;
846 			else if (flags & SHORTINT)
847 				*GETARG(short *) = ret;
848 			else if (flags & CHARINT)
849 				*GETARG(signed char *) = ret;
850 			else if (flags & PTRINT)
851 				*GETARG(ptrdiff_t *) = ret;
852 			else if (flags & SIZEINT)
853 				*GETARG(ssize_t *) = ret;
854 			else if (flags & MAXINT)
855 				*GETARG(intmax_t *) = ret;
856 			else
857 				*GETARG(int *) = ret;
858 			continue;	/* no output */
859 			}
860 #endif /* NO_PRINTF_PERCENT_N */
861 		case 'O':
862 			flags |= LONGINT;
863 			/*FALLTHROUGH*/
864 		case 'o':
865 			_umax = UARG();
866 			base = OCT;
867 			goto nosign;
868 		case 'p':
869 			/*
870 			 * ``The argument shall be a pointer to void.  The
871 			 * value of the pointer is converted to a sequence
872 			 * of printable characters, in an implementation-
873 			 * defined manner.''
874 			 *	-- ANSI X3J11
875 			 */
876 			_umax = (u_long)GETARG(void *);
877 			base = HEX;
878 			xdigs = xdigs_lower;
879 			ox[1] = 'x';
880 			goto nosign;
881 		case 's': {
882 			size_t len;
883 
884 #ifdef PRINTF_WIDE_CHAR
885 			if (flags & LONGINT) {
886 				wchar_t *wcp;
887 
888 				free(convbuf);
889 				convbuf = NULL;
890 				if ((wcp = GETARG(wchar_t *)) == NULL) {
891 					struct syslog_data sdata = SYSLOG_DATA_INIT;
892 					int save_errno = errno;
893 
894 					syslog_r(LOG_CRIT | LOG_CONS, &sdata,
895 					    "vfprintf %%ls NULL in \"%s\"", fmt0);
896 					errno = save_errno;
897 
898 					cp = "(null)";
899 				} else {
900 					convbuf = __wcsconv(wcp, prec);
901 					if (convbuf == NULL) {
902 						ret = -1;
903 						goto error;
904 					}
905 					cp = convbuf;
906 				}
907 			} else
908 #endif /* PRINTF_WIDE_CHAR */
909 
910 			if ((cp = GETARG(char *)) == NULL) {
911 				struct syslog_data sdata = SYSLOG_DATA_INIT;
912 				int save_errno = errno;
913 
914 				syslog_r(LOG_CRIT | LOG_CONS, &sdata,
915 				    "vfprintf %%s NULL in \"%s\"", fmt0);
916 				errno = save_errno;
917 
918 				cp = "(null)";
919 			}
920 			len = prec >= 0 ? strnlen(cp, prec) : strlen(cp);
921 			if (len > INT_MAX)
922 				goto overflow;
923 			size = (int)len;
924 			sign = '\0';
925 			}
926 			break;
927 		case 'U':
928 			flags |= LONGINT;
929 			/*FALLTHROUGH*/
930 		case 'u':
931 			_umax = UARG();
932 			base = DEC;
933 			goto nosign;
934 		case 'X':
935 			xdigs = xdigs_upper;
936 			goto hex;
937 		case 'x':
938 			xdigs = xdigs_lower;
939 hex:			_umax = UARG();
940 			base = HEX;
941 			/* leading 0x/X only if non-zero */
942 			if (flags & ALT && _umax != 0)
943 				ox[1] = ch;
944 
945 			/* unsigned conversions */
946 nosign:			sign = '\0';
947 			/*
948 			 * ``... diouXx conversions ... if a precision is
949 			 * specified, the 0 flag will be ignored.''
950 			 *	-- ANSI X3J11
951 			 */
952 number:			if ((dprec = prec) >= 0)
953 				flags &= ~ZEROPAD;
954 
955 			/*
956 			 * ``The result of converting a zero value with an
957 			 * explicit precision of zero is no characters.''
958 			 *	-- ANSI X3J11
959 			 */
960 			cp = buf + BUF;
961 			if (_umax != 0 || prec != 0) {
962 				/*
963 				 * Unsigned mod is hard, and unsigned mod
964 				 * by a constant is easier than that by
965 				 * a variable; hence this switch.
966 				 */
967 				switch (base) {
968 				case OCT:
969 					do {
970 						*--cp = to_char(_umax & 7);
971 						_umax >>= 3;
972 					} while (_umax);
973 					/* handle octal leading 0 */
974 					if (flags & ALT && *cp != '0')
975 						*--cp = '0';
976 					break;
977 
978 				case DEC:
979 					/* many numbers are 1 digit */
980 					while (_umax >= 10) {
981 						*--cp = to_char(_umax % 10);
982 						_umax /= 10;
983 					}
984 					*--cp = to_char(_umax);
985 					break;
986 
987 				case HEX:
988 					do {
989 						*--cp = xdigs[_umax & 15];
990 						_umax >>= 4;
991 					} while (_umax);
992 					break;
993 
994 				default:
995 					cp = "bug in vfprintf: bad base";
996 					size = strlen(cp);
997 					goto skipsize;
998 				}
999 			}
1000 			size = buf + BUF - cp;
1001 			if (size > BUF)	/* should never happen */
1002 				abort();
1003 		skipsize:
1004 			break;
1005 		default:	/* "%?" prints ?, unless ? is NUL */
1006 			if (ch == '\0')
1007 				goto done;
1008 			/* pretend it was %c with argument ch */
1009 			cp = buf;
1010 			*cp = ch;
1011 			size = 1;
1012 			sign = '\0';
1013 			break;
1014 		}
1015 
1016 		/*
1017 		 * All reasonable formats wind up here.  At this point, `cp'
1018 		 * points to a string which (if not flags&LADJUST) should be
1019 		 * padded out to `width' places.  If flags&ZEROPAD, it should
1020 		 * first be prefixed by any sign or other prefix; otherwise,
1021 		 * it should be blank padded before the prefix is emitted.
1022 		 * After any left-hand padding and prefixing, emit zeroes
1023 		 * required by a decimal %[diouxX] precision, then print the
1024 		 * string proper, then emit zeroes required by any leftover
1025 		 * floating precision; finally, if LADJUST, pad with blanks.
1026 		 *
1027 		 * Compute actual size, so we know how much to pad.
1028 		 * size excludes decimal prec; realsz includes it.
1029 		 */
1030 		realsz = dprec > size ? dprec : size;
1031 		if (sign)
1032 			realsz++;
1033 		if (ox[1])
1034 			realsz+= 2;
1035 
1036 		/* right-adjusting blank padding */
1037 		if ((flags & (LADJUST|ZEROPAD)) == 0)
1038 			PAD(width - realsz, blanks);
1039 
1040 		/* prefix */
1041 		if (sign)
1042 			PRINT(&sign, 1);
1043 		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
1044 			ox[0] = '0';
1045 			PRINT(ox, 2);
1046 		}
1047 
1048 		/* right-adjusting zero padding */
1049 		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1050 			PAD(width - realsz, zeroes);
1051 
1052 		/* leading zeroes from decimal precision */
1053 		PAD(dprec - size, zeroes);
1054 
1055 		/* the string or number proper */
1056 #ifdef FLOATING_POINT
1057 		if ((flags & FPT) == 0) {
1058 			PRINT(cp, size);
1059 		} else {	/* glue together f_p fragments */
1060 			if (decimal_point == NULL)
1061 				decimal_point = nl_langinfo(RADIXCHAR);
1062 			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
1063 				if (expt <= 0) {
1064 					PRINT(zeroes, 1);
1065 					if (prec || flags & ALT)
1066 						PRINT(decimal_point, 1);
1067 					PAD(-expt, zeroes);
1068 					/* already handled initial 0's */
1069 					prec += expt;
1070  				} else {
1071 					PRINTANDPAD(cp, dtoaend, lead, zeroes);
1072 					cp += lead;
1073 					if (prec || flags & ALT)
1074 						PRINT(decimal_point, 1);
1075 				}
1076 				PRINTANDPAD(cp, dtoaend, prec, zeroes);
1077 			} else {	/* %[eE] or sufficiently long %[gG] */
1078 				if (prec > 1 || flags & ALT) {
1079 					buf[0] = *cp++;
1080 					buf[1] = *decimal_point;
1081 					PRINT(buf, 2);
1082 					PRINT(cp, ndig-1);
1083 					PAD(prec - ndig, zeroes);
1084 				} else { /* XeYYY */
1085 					PRINT(cp, 1);
1086 				}
1087 				PRINT(expstr, expsize);
1088 			}
1089 		}
1090 #else
1091 		PRINT(cp, size);
1092 #endif
1093 		/* left-adjusting padding (always blank) */
1094 		if (flags & LADJUST)
1095 			PAD(width - realsz, blanks);
1096 
1097 		/* finally, adjust ret */
1098 		if (width < realsz)
1099 			width = realsz;
1100 		if (width > INT_MAX - ret)
1101 			goto overflow;
1102 		ret += width;
1103 
1104 		FLUSH();	/* copy out the I/O vectors */
1105 	}
1106 done:
1107 	FLUSH();
1108 error:
1109 	va_end(orgap);
1110 	if (__sferror(fp))
1111 		ret = -1;
1112 	goto finish;
1113 
1114 overflow:
1115 	errno = EOVERFLOW;
1116 	ret = -1;
1117 
1118 finish:
1119 #ifdef PRINTF_WIDE_CHAR
1120 	free(convbuf);
1121 #endif
1122 #ifdef FLOATING_POINT
1123 	if (dtoaresult)
1124 		__freedtoa(dtoaresult);
1125 #endif
1126 	if (argtable != NULL && argtable != statargtable) {
1127 		munmap(argtable, argtablesiz);
1128 		argtable = NULL;
1129 	}
1130 	return (ret);
1131 }
1132 
1133 /*
1134  * Type ids for argument type table.
1135  */
1136 #define T_UNUSED	0
1137 #define T_SHORT		1
1138 #define T_U_SHORT	2
1139 #define TP_SHORT	3
1140 #define T_INT		4
1141 #define T_U_INT		5
1142 #define TP_INT		6
1143 #define T_LONG		7
1144 #define T_U_LONG	8
1145 #define TP_LONG		9
1146 #define T_LLONG		10
1147 #define T_U_LLONG	11
1148 #define TP_LLONG	12
1149 #define T_DOUBLE	13
1150 #define T_LONG_DOUBLE	14
1151 #define TP_CHAR		15
1152 #define TP_VOID		16
1153 #define T_PTRINT	17
1154 #define TP_PTRINT	18
1155 #define T_SIZEINT	19
1156 #define T_SSIZEINT	20
1157 #define TP_SSIZEINT	21
1158 #define T_MAXINT	22
1159 #define T_MAXUINT	23
1160 #define TP_MAXINT	24
1161 #define T_CHAR		25
1162 #define T_U_CHAR	26
1163 #define T_WINT		27
1164 #define TP_WCHAR	28
1165 
1166 /*
1167  * Find all arguments when a positional parameter is encountered.  Returns a
1168  * table, indexed by argument number, of pointers to each arguments.  The
1169  * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
1170  * It will be replaced with a mmap-ed one if it overflows (malloc cannot be
1171  * used since we are attempting to make snprintf thread safe, and alloca is
1172  * problematic since we have nested functions..)
1173  */
1174 static int
1175 __find_arguments(const char *fmt0, va_list ap, union arg **argtable,
1176     size_t *argtablesiz)
1177 {
1178 	char *fmt;		/* format string */
1179 	int ch;			/* character from fmt */
1180 	int n, n2;		/* handy integer (short term usage) */
1181 	char *cp;		/* handy char pointer (short term usage) */
1182 	int flags;		/* flags as above */
1183 	unsigned char *typetable; /* table of types */
1184 	unsigned char stattypetable[STATIC_ARG_TBL_SIZE];
1185 	int tablesize;		/* current size of type table */
1186 	int tablemax;		/* largest used index in table */
1187 	int nextarg;		/* 1-based argument index */
1188 	int ret = 0;		/* return value */
1189 
1190 	/*
1191 	 * Add an argument type to the table, expanding if necessary.
1192 	 */
1193 #define ADDTYPE(type) \
1194 	((nextarg >= tablesize) ? \
1195 		__grow_type_table(&typetable, &tablesize) : 0, \
1196 	(nextarg > tablemax) ? tablemax = nextarg : 0, \
1197 	typetable[nextarg++] = type)
1198 
1199 #define	ADDSARG() \
1200         ((flags&MAXINT) ? ADDTYPE(T_MAXINT) : \
1201 	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1202 	    ((flags&SIZEINT) ? ADDTYPE(T_SSIZEINT) : \
1203 	    ((flags&LLONGINT) ? ADDTYPE(T_LLONG) : \
1204 	    ((flags&LONGINT) ? ADDTYPE(T_LONG) : \
1205 	    ((flags&SHORTINT) ? ADDTYPE(T_SHORT) : \
1206 	    ((flags&CHARINT) ? ADDTYPE(T_CHAR) : ADDTYPE(T_INT))))))))
1207 
1208 #define	ADDUARG() \
1209         ((flags&MAXINT) ? ADDTYPE(T_MAXUINT) : \
1210 	    ((flags&PTRINT) ? ADDTYPE(T_PTRINT) : \
1211 	    ((flags&SIZEINT) ? ADDTYPE(T_SIZEINT) : \
1212 	    ((flags&LLONGINT) ? ADDTYPE(T_U_LLONG) : \
1213 	    ((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
1214 	    ((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : \
1215 	    ((flags&CHARINT) ? ADDTYPE(T_U_CHAR) : ADDTYPE(T_U_INT))))))))
1216 
1217 	/*
1218 	 * Add * arguments to the type array.
1219 	 */
1220 #define ADDASTER() \
1221 	n2 = 0; \
1222 	cp = fmt; \
1223 	while (is_digit(*cp)) { \
1224 		APPEND_DIGIT(n2, *cp); \
1225 		cp++; \
1226 	} \
1227 	if (*cp == '$') { \
1228 		int hold = nextarg; \
1229 		nextarg = n2; \
1230 		ADDTYPE(T_INT); \
1231 		nextarg = hold; \
1232 		fmt = ++cp; \
1233 	} else { \
1234 		ADDTYPE(T_INT); \
1235 	}
1236 	fmt = (char *)fmt0;
1237 	typetable = stattypetable;
1238 	tablesize = STATIC_ARG_TBL_SIZE;
1239 	tablemax = 0;
1240 	nextarg = 1;
1241 	memset(typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
1242 
1243 	/*
1244 	 * Scan the format for conversions (`%' character).
1245 	 */
1246 	for (;;) {
1247 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
1248 			continue;
1249 		if (ch == '\0')
1250 			goto done;
1251 		fmt++;		/* skip over '%' */
1252 
1253 		flags = 0;
1254 
1255 rflag:		ch = *fmt++;
1256 reswitch:	switch (ch) {
1257 		case ' ':
1258 		case '#':
1259 		case '\'':
1260 			goto rflag;
1261 		case '*':
1262 			ADDASTER();
1263 			goto rflag;
1264 		case '-':
1265 		case '+':
1266 			goto rflag;
1267 		case '.':
1268 			if ((ch = *fmt++) == '*') {
1269 				ADDASTER();
1270 				goto rflag;
1271 			}
1272 			while (is_digit(ch)) {
1273 				ch = *fmt++;
1274 			}
1275 			goto reswitch;
1276 		case '0':
1277 			goto rflag;
1278 		case '1': case '2': case '3': case '4':
1279 		case '5': case '6': case '7': case '8': case '9':
1280 			n = 0;
1281 			do {
1282 				APPEND_DIGIT(n ,ch);
1283 				ch = *fmt++;
1284 			} while (is_digit(ch));
1285 			if (ch == '$') {
1286 				nextarg = n;
1287 				goto rflag;
1288 			}
1289 			goto reswitch;
1290 #ifdef FLOATING_POINT
1291 		case 'L':
1292 			flags |= LONGDBL;
1293 			goto rflag;
1294 #endif
1295 		case 'h':
1296 			if (*fmt == 'h') {
1297 				fmt++;
1298 				flags |= CHARINT;
1299 			} else {
1300 				flags |= SHORTINT;
1301 			}
1302 			goto rflag;
1303 		case 'j':
1304 			flags |= MAXINT;
1305 			goto rflag;
1306 		case 'l':
1307 			if (*fmt == 'l') {
1308 				fmt++;
1309 				flags |= LLONGINT;
1310 			} else {
1311 				flags |= LONGINT;
1312 			}
1313 			goto rflag;
1314 		case 'q':
1315 			flags |= LLONGINT;
1316 			goto rflag;
1317 		case 't':
1318 			flags |= PTRINT;
1319 			goto rflag;
1320 		case 'z':
1321 			flags |= SIZEINT;
1322 			goto rflag;
1323 		case 'c':
1324 #ifdef PRINTF_WIDE_CHAR
1325 			if (flags & LONGINT)
1326 				ADDTYPE(T_WINT);
1327 			else
1328 #endif
1329 				ADDTYPE(T_INT);
1330 			break;
1331 		case 'D':
1332 			flags |= LONGINT;
1333 			/*FALLTHROUGH*/
1334 		case 'd':
1335 		case 'i':
1336 			ADDSARG();
1337 			break;
1338 #ifdef FLOATING_POINT
1339 		case 'a':
1340 		case 'A':
1341 		case 'e':
1342 		case 'E':
1343 		case 'f':
1344 		case 'F':
1345 		case 'g':
1346 		case 'G':
1347 			if (flags & LONGDBL)
1348 				ADDTYPE(T_LONG_DOUBLE);
1349 			else
1350 				ADDTYPE(T_DOUBLE);
1351 			break;
1352 #endif /* FLOATING_POINT */
1353 #ifndef NO_PRINTF_PERCENT_N
1354 		case 'n':
1355 			if (flags & LLONGINT)
1356 				ADDTYPE(TP_LLONG);
1357 			else if (flags & LONGINT)
1358 				ADDTYPE(TP_LONG);
1359 			else if (flags & SHORTINT)
1360 				ADDTYPE(TP_SHORT);
1361 			else if (flags & PTRINT)
1362 				ADDTYPE(TP_PTRINT);
1363 			else if (flags & SIZEINT)
1364 				ADDTYPE(TP_SSIZEINT);
1365 			else if (flags & MAXINT)
1366 				ADDTYPE(TP_MAXINT);
1367 			else
1368 				ADDTYPE(TP_INT);
1369 			continue;	/* no output */
1370 #endif /* NO_PRINTF_PERCENT_N */
1371 		case 'O':
1372 			flags |= LONGINT;
1373 			/*FALLTHROUGH*/
1374 		case 'o':
1375 			ADDUARG();
1376 			break;
1377 		case 'p':
1378 			ADDTYPE(TP_VOID);
1379 			break;
1380 		case 's':
1381 #ifdef PRINTF_WIDE_CHAR
1382 			if (flags & LONGINT)
1383 				ADDTYPE(TP_WCHAR);
1384 			else
1385 #endif
1386 				ADDTYPE(TP_CHAR);
1387 			break;
1388 		case 'U':
1389 			flags |= LONGINT;
1390 			/*FALLTHROUGH*/
1391 		case 'u':
1392 		case 'X':
1393 		case 'x':
1394 			ADDUARG();
1395 			break;
1396 		default:	/* "%?" prints ?, unless ? is NUL */
1397 			if (ch == '\0')
1398 				goto done;
1399 			break;
1400 		}
1401 	}
1402 done:
1403 	/*
1404 	 * Build the argument table.
1405 	 */
1406 	if (tablemax >= STATIC_ARG_TBL_SIZE) {
1407 		*argtablesiz = sizeof(union arg) * (tablemax + 1);
1408 		*argtable = mmap(NULL, *argtablesiz,
1409 		    PROT_WRITE|PROT_READ, MAP_ANON|MAP_PRIVATE, -1, 0);
1410 		if (*argtable == MAP_FAILED)
1411 			return (-1);
1412 	}
1413 
1414 	for (n = 1; n <= tablemax; n++) {
1415 		switch (typetable[n]) {
1416 		case T_UNUSED:
1417 		case T_CHAR:
1418 		case T_U_CHAR:
1419 		case T_SHORT:
1420 		case T_U_SHORT:
1421 		case T_INT:
1422 			(*argtable)[n].intarg = va_arg(ap, int);
1423 			break;
1424 		case TP_SHORT:
1425 			(*argtable)[n].pshortarg = va_arg(ap, short *);
1426 			break;
1427 		case T_U_INT:
1428 			(*argtable)[n].uintarg = va_arg(ap, unsigned int);
1429 			break;
1430 		case TP_INT:
1431 			(*argtable)[n].pintarg = va_arg(ap, int *);
1432 			break;
1433 		case T_LONG:
1434 			(*argtable)[n].longarg = va_arg(ap, long);
1435 			break;
1436 		case T_U_LONG:
1437 			(*argtable)[n].ulongarg = va_arg(ap, unsigned long);
1438 			break;
1439 		case TP_LONG:
1440 			(*argtable)[n].plongarg = va_arg(ap, long *);
1441 			break;
1442 		case T_LLONG:
1443 			(*argtable)[n].longlongarg = va_arg(ap, long long);
1444 			break;
1445 		case T_U_LLONG:
1446 			(*argtable)[n].ulonglongarg = va_arg(ap, unsigned long long);
1447 			break;
1448 		case TP_LLONG:
1449 			(*argtable)[n].plonglongarg = va_arg(ap, long long *);
1450 			break;
1451 #ifdef FLOATING_POINT
1452 		case T_DOUBLE:
1453 			(*argtable)[n].doublearg = va_arg(ap, double);
1454 			break;
1455 		case T_LONG_DOUBLE:
1456 			(*argtable)[n].longdoublearg = va_arg(ap, long double);
1457 			break;
1458 #endif
1459 		case TP_CHAR:
1460 			(*argtable)[n].pchararg = va_arg(ap, char *);
1461 			break;
1462 		case TP_VOID:
1463 			(*argtable)[n].pvoidarg = va_arg(ap, void *);
1464 			break;
1465 		case T_PTRINT:
1466 			(*argtable)[n].ptrdiffarg = va_arg(ap, ptrdiff_t);
1467 			break;
1468 		case TP_PTRINT:
1469 			(*argtable)[n].pptrdiffarg = va_arg(ap, ptrdiff_t *);
1470 			break;
1471 		case T_SIZEINT:
1472 			(*argtable)[n].sizearg = va_arg(ap, size_t);
1473 			break;
1474 		case T_SSIZEINT:
1475 			(*argtable)[n].ssizearg = va_arg(ap, ssize_t);
1476 			break;
1477 		case TP_SSIZEINT:
1478 			(*argtable)[n].pssizearg = va_arg(ap, ssize_t *);
1479 			break;
1480 		case T_MAXINT:
1481 			(*argtable)[n].intmaxarg = va_arg(ap, intmax_t);
1482 			break;
1483 		case T_MAXUINT:
1484 			(*argtable)[n].uintmaxarg = va_arg(ap, uintmax_t);
1485 			break;
1486 		case TP_MAXINT:
1487 			(*argtable)[n].pintmaxarg = va_arg(ap, intmax_t *);
1488 			break;
1489 #ifdef PRINTF_WIDE_CHAR
1490 		case T_WINT:
1491 			(*argtable)[n].wintarg = va_arg(ap, wint_t);
1492 			break;
1493 		case TP_WCHAR:
1494 			(*argtable)[n].pwchararg = va_arg(ap, wchar_t *);
1495 			break;
1496 #endif
1497 		}
1498 	}
1499 	goto finish;
1500 
1501 overflow:
1502 	errno = EOVERFLOW;
1503 	ret = -1;
1504 
1505 finish:
1506 	if (typetable != NULL && typetable != stattypetable) {
1507 		munmap(typetable, *argtablesiz);
1508 		typetable = NULL;
1509 	}
1510 	return (ret);
1511 }
1512 
1513 /*
1514  * Increase the size of the type table.
1515  */
1516 static int
1517 __grow_type_table(unsigned char **typetable, int *tablesize)
1518 {
1519 	unsigned char *oldtable = *typetable;
1520 	int newsize = *tablesize * 2;
1521 
1522 	if (newsize < getpagesize())
1523 		newsize = getpagesize();
1524 
1525 	if (*tablesize == STATIC_ARG_TBL_SIZE) {
1526 		*typetable = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
1527 		    MAP_ANON|MAP_PRIVATE, -1, 0);
1528 		if (*typetable == MAP_FAILED)
1529 			return (-1);
1530 		bcopy(oldtable, *typetable, *tablesize);
1531 	} else {
1532 		unsigned char *new = mmap(NULL, newsize, PROT_WRITE|PROT_READ,
1533 		    MAP_ANON|MAP_PRIVATE, -1, 0);
1534 		if (new == MAP_FAILED)
1535 			return (-1);
1536 		memmove(new, *typetable, *tablesize);
1537 		munmap(*typetable, *tablesize);
1538 		*typetable = new;
1539 	}
1540 	memset(*typetable + *tablesize, T_UNUSED, (newsize - *tablesize));
1541 
1542 	*tablesize = newsize;
1543 	return (0);
1544 }
1545 
1546 
1547 #ifdef FLOATING_POINT
1548 static int
1549 exponent(char *p0, int exp, int fmtch)
1550 {
1551 	char *p, *t;
1552 	char expbuf[MAXEXPDIG];
1553 
1554 	p = p0;
1555 	*p++ = fmtch;
1556 	if (exp < 0) {
1557 		exp = -exp;
1558 		*p++ = '-';
1559 	} else
1560 		*p++ = '+';
1561 	t = expbuf + MAXEXPDIG;
1562 	if (exp > 9) {
1563 		do {
1564 			*--t = to_char(exp % 10);
1565 		} while ((exp /= 10) > 9);
1566 		*--t = to_char(exp);
1567 		for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
1568 			/* nothing */;
1569 	} else {
1570 		/*
1571 		 * Exponents for decimal floating point conversions
1572 		 * (%[eEgG]) must be at least two characters long,
1573 		 * whereas exponents for hexadecimal conversions can
1574 		 * be only one character long.
1575 		 */
1576 		if (fmtch == 'e' || fmtch == 'E')
1577 			*p++ = '0';
1578 		*p++ = to_char(exp);
1579 	}
1580 	return (p - p0);
1581 }
1582 #endif /* FLOATING_POINT */
1583