xref: /dragonfly/lib/libc/stdio/vfprintf.c (revision 606a6e92)
1 /*-
2  * Copyright (c) 1990, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Chris Torek.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  *
36  * @(#)vfprintf.c	8.1 (Berkeley) 6/4/93
37  * $FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.22.2.5 2002/10/12 10:46:37 schweikh Exp $
38  * $DragonFly: src/lib/libc/stdio/vfprintf.c,v 1.5 2004/06/07 20:35:41 hmp Exp $
39  */
40 
41 /*
42  * Actual printf innards.
43  *
44  * This code is large and complicated...
45  */
46 
47 #include <sys/types.h>
48 
49 #include <limits.h>
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 
54 #include <stdarg.h>
55 
56 #include "libc_private.h"
57 #include "local.h"
58 #include "fvwrite.h"
59 
60 /* Define FLOATING_POINT to get floating point. */
61 #define	FLOATING_POINT
62 
63 static int	__sprint (FILE *, struct __suio *);
64 static int	__sbprintf (FILE *, const char *, va_list);
65 static char *	__ultoa (u_long, char *, int, int, char *);
66 static char *	__uqtoa (u_quad_t, char *, int, int, char *);
67 static void	__find_arguments (const char *, va_list, void ***);
68 static void	__grow_type_table (int, unsigned char **, int *);
69 
70 /*
71  * Flush out all the vectors defined by the given uio,
72  * then reset it so that it can be reused.
73  */
74 static int
75 __sprint(FILE *fp, struct __suio *uio)
76 {
77 	int err;
78 
79 	if (uio->uio_resid == 0) {
80 		uio->uio_iovcnt = 0;
81 		return (0);
82 	}
83 	err = __sfvwrite(fp, uio);
84 	uio->uio_resid = 0;
85 	uio->uio_iovcnt = 0;
86 	return (err);
87 }
88 
89 /*
90  * Helper function for `fprintf to unbuffered unix file': creates a
91  * temporary buffer.  We only work on write-only files; this avoids
92  * worries about ungetc buffers and so forth.
93  */
94 static int
95 __sbprintf(FILE *fp, const char *fmt, va_list ap)
96 {
97 	int ret;
98 	FILE fake;
99 	unsigned char buf[BUFSIZ];
100 
101 	/* copy the important variables */
102 	fake._flags = fp->_flags & ~__SNBF;
103 	fake._file = fp->_file;
104 	fake._cookie = fp->_cookie;
105 	fake._write = fp->_write;
106 
107 	/* set up the buffer */
108 	fake._bf._base = fake._p = buf;
109 	fake._bf._size = fake._w = sizeof(buf);
110 	fake._lbfsize = 0;	/* not actually used, but Just In Case */
111 
112 	/* do the work, then copy any error status */
113 	ret = vfprintf(&fake, fmt, ap);
114 	if (ret >= 0 && fflush(&fake))
115 		ret = EOF;
116 	if (fake._flags & __SERR)
117 		fp->_flags |= __SERR;
118 	return (ret);
119 }
120 
121 /*
122  * Macros for converting digits to letters and vice versa
123  */
124 #define	to_digit(c)	((c) - '0')
125 #define is_digit(c)	((unsigned)to_digit(c) <= 9)
126 #define	to_char(n)	((n) + '0')
127 
128 /*
129  * Convert an unsigned long to ASCII for printf purposes, returning
130  * a pointer to the first character of the string representation.
131  * Octal numbers can be forced to have a leading zero; hex numbers
132  * use the given digits.
133  */
134 static char *
135 __ultoa(u_long val, char *endp, int base, int octzero, char *xdigs)
136 {
137 	char *cp = endp;
138 	long sval;
139 
140 	/*
141 	 * Handle the three cases separately, in the hope of getting
142 	 * better/faster code.
143 	 */
144 	switch (base) {
145 	case 10:
146 		if (val < 10) {	/* many numbers are 1 digit */
147 			*--cp = to_char(val);
148 			return (cp);
149 		}
150 		/*
151 		 * On many machines, unsigned arithmetic is harder than
152 		 * signed arithmetic, so we do at most one unsigned mod and
153 		 * divide; this is sufficient to reduce the range of
154 		 * the incoming value to where signed arithmetic works.
155 		 */
156 		if (val > LONG_MAX) {
157 			*--cp = to_char(val % 10);
158 			sval = val / 10;
159 		} else
160 			sval = val;
161 		do {
162 			*--cp = to_char(sval % 10);
163 			sval /= 10;
164 		} while (sval != 0);
165 		break;
166 
167 	case 8:
168 		do {
169 			*--cp = to_char(val & 7);
170 			val >>= 3;
171 		} while (val);
172 		if (octzero && *cp != '0')
173 			*--cp = '0';
174 		break;
175 
176 	case 16:
177 		do {
178 			*--cp = xdigs[val & 15];
179 			val >>= 4;
180 		} while (val);
181 		break;
182 
183 	default:			/* oops */
184 		abort();
185 	}
186 	return (cp);
187 }
188 
189 /* Identical to __ultoa, but for quads. */
190 static char *
191 __uqtoa(u_quad_t val, char *endp, int base, int octzero, char *xdigs)
192 {
193 	char *cp = endp;
194 	quad_t sval;
195 
196 	/* quick test for small values; __ultoa is typically much faster */
197 	/* (perhaps instead we should run until small, then call __ultoa?) */
198 	if (val <= ULONG_MAX)
199 		return (__ultoa((u_long)val, endp, base, octzero, xdigs));
200 	switch (base) {
201 	case 10:
202 		if (val < 10) {
203 			*--cp = to_char(val % 10);
204 			return (cp);
205 		}
206 		if (val > QUAD_MAX) {
207 			*--cp = to_char(val % 10);
208 			sval = val / 10;
209 		} else
210 			sval = val;
211 		do {
212 			*--cp = to_char(sval % 10);
213 			sval /= 10;
214 		} while (sval != 0);
215 		break;
216 
217 	case 8:
218 		do {
219 			*--cp = to_char(val & 7);
220 			val >>= 3;
221 		} while (val);
222 		if (octzero && *cp != '0')
223 			*--cp = '0';
224 		break;
225 
226 	case 16:
227 		do {
228 			*--cp = xdigs[val & 15];
229 			val >>= 4;
230 		} while (val);
231 		break;
232 
233 	default:
234 		abort();
235 	}
236 	return (cp);
237 }
238 
239 #ifdef FLOATING_POINT
240 #include <locale.h>
241 #include <math.h>
242 #include "floatio.h"
243 
244 #define	BUF		(MAXEXP+MAXFRACT+1)	/* + decimal point */
245 #define	DEFPREC		6
246 
247 static char *cvt (double, int, int, char *, int *, int, int *, char **);
248 static int exponent (char *, int, int);
249 
250 #else /* no FLOATING_POINT */
251 
252 #define	BUF		68
253 
254 #endif /* FLOATING_POINT */
255 
256 #define STATIC_ARG_TBL_SIZE 8           /* Size of static argument table. */
257 
258 /*
259  * Flags used during conversion.
260  */
261 #define	ALT		0x001		/* alternate form */
262 #define	HEXPREFIX	0x002		/* add 0x or 0X prefix */
263 #define	LADJUST		0x004		/* left adjustment */
264 #define	LONGDBL		0x008		/* long double */
265 #define	LONGINT		0x010		/* long integer */
266 #define	QUADINT		0x020		/* quad integer */
267 #define	SHORTINT	0x040		/* short integer */
268 #define	ZEROPAD		0x080		/* zero (as opposed to blank) pad */
269 #define FPT		0x100		/* Floating point number */
270 int
271 vfprintf(FILE *fp, const char *fmt0, va_list ap)
272 {
273 	char *fmt;		/* format string */
274 	int ch;			/* character from fmt */
275 	int n, n2;		/* handy integer (short term usage) */
276 	char *cp;		/* handy char pointer (short term usage) */
277 	struct __siov *iovp;	/* for PRINT macro */
278 	int flags;		/* flags as above */
279 	int ret;		/* return value accumulator */
280 	int width;		/* width from format (%8d), or 0 */
281 	int prec;		/* precision from format (%.3d), or -1 */
282 	char sign;		/* sign prefix (' ', '+', '-', or \0) */
283 #ifdef FLOATING_POINT
284 	char *decimal_point = localeconv()->decimal_point;
285 	char softsign;		/* temporary negative sign for floats */
286 	double _double;		/* double precision arguments %[eEfgG] */
287 	int expt;		/* integer value of exponent */
288 	int expsize;		/* character count for expstr */
289 	int ndig;		/* actual number of digits returned by cvt */
290 	char expstr[7];		/* buffer for exponent string */
291 	char *dtoaresult;	/* buffer allocated by dtoa */
292 #endif
293 	u_long	ulval;		/* integer arguments %[diouxX] */
294 	u_quad_t uqval;		/* %q integers */
295 	int base;		/* base for [diouxX] conversion */
296 	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
297 	int realsz;		/* field size expanded by dprec, sign, etc */
298 	int size;		/* size of converted field or string */
299 	int prsize;             /* max size of printed field */
300 	char *xdigs;		/* digits for [xX] conversion */
301 #define NIOV 8
302 	struct __suio uio;	/* output information: summary */
303 	struct __siov iov[NIOV];/* ... and individual io vectors */
304 	char buf[BUF];		/* space for %c, %[diouxX], %[eEfgG] */
305 	char ox[2];		/* space for 0x hex-prefix */
306         void **argtable;        /* args, built due to positional arg */
307         void *statargtable [STATIC_ARG_TBL_SIZE];
308         int nextarg;            /* 1-based argument index */
309         va_list orgap;          /* original argument pointer */
310 
311 	/*
312 	 * Choose PADSIZE to trade efficiency vs. size.  If larger printf
313 	 * fields occur frequently, increase PADSIZE and make the initialisers
314 	 * below longer.
315 	 */
316 #define	PADSIZE	16		/* pad chunk size */
317 	static char blanks[PADSIZE] =
318 	 {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
319 	static char zeroes[PADSIZE] =
320 	 {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
321 
322 	/*
323 	 * BEWARE, these `goto error' on error, and PAD uses `n'.
324 	 */
325 #define	PRINT(ptr, len) { \
326 	iovp->iov_base = (ptr); \
327 	iovp->iov_len = (len); \
328 	uio.uio_resid += (len); \
329 	iovp++; \
330 	if (++uio.uio_iovcnt >= NIOV) { \
331 		if (__sprint(fp, &uio)) \
332 			goto error; \
333 		iovp = iov; \
334 	} \
335 }
336 #define	PAD(howmany, with) { \
337 	if ((n = (howmany)) > 0) { \
338 		while (n > PADSIZE) { \
339 			PRINT(with, PADSIZE); \
340 			n -= PADSIZE; \
341 		} \
342 		PRINT(with, n); \
343 	} \
344 }
345 #define	FLUSH() { \
346 	if (uio.uio_resid && __sprint(fp, &uio)) \
347 		goto error; \
348 	uio.uio_iovcnt = 0; \
349 	iovp = iov; \
350 }
351 
352         /*
353          * Get the argument indexed by nextarg.   If the argument table is
354          * built, use it to get the argument.  If its not, get the next
355          * argument (and arguments must be gotten sequentially).
356          */
357 #define GETARG(type) \
358         ((argtable != NULL) ? *((type*)(argtable[nextarg++])) : \
359             (nextarg++, va_arg(ap, type)))
360 
361 	/*
362 	 * To extend shorts properly, we need both signed and unsigned
363 	 * argument extraction methods.
364 	 */
365 #define	SARG() \
366 	(flags&LONGINT ? GETARG(long) : \
367 	    flags&SHORTINT ? (long)(short)GETARG(int) : \
368 	    (long)GETARG(int))
369 #define	UARG() \
370 	(flags&LONGINT ? GETARG(u_long) : \
371 	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
372 	    (u_long)GETARG(u_int))
373 
374         /*
375          * Get * arguments, including the form *nn$.  Preserve the nextarg
376          * that the argument can be gotten once the type is determined.
377          */
378 #define GETASTER(val) \
379         n2 = 0; \
380         cp = fmt; \
381         while (is_digit(*cp)) { \
382                 n2 = 10 * n2 + to_digit(*cp); \
383                 cp++; \
384         } \
385         if (*cp == '$') { \
386             	int hold = nextarg; \
387                 if (argtable == NULL) { \
388                         argtable = statargtable; \
389                         __find_arguments (fmt0, orgap, &argtable); \
390                 } \
391                 nextarg = n2; \
392                 val = GETARG (int); \
393                 nextarg = hold; \
394                 fmt = ++cp; \
395         } else { \
396 		val = GETARG (int); \
397         }
398 
399 
400 #ifdef FLOATING_POINT
401 	dtoaresult = NULL;
402 #endif
403 	FLOCKFILE(fp);
404 	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
405 	if (cantwrite(fp)) {
406 		FUNLOCKFILE(fp);
407 		return (EOF);
408 	}
409 
410 	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
411 	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
412 	    fp->_file >= 0) {
413 		FUNLOCKFILE(fp);
414 		return (__sbprintf(fp, fmt0, ap));
415 	}
416 
417 	fmt = (char *)fmt0;
418         argtable = NULL;
419         nextarg = 1;
420         orgap = ap;
421 	uio.uio_iov = iovp = iov;
422 	uio.uio_resid = 0;
423 	uio.uio_iovcnt = 0;
424 	ret = 0;
425 
426 	/*
427 	 * Scan the format for conversions (`%' character).
428 	 */
429 	for (;;) {
430 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
431 			/* void */;
432 		if ((n = fmt - cp) != 0) {
433 			if ((unsigned)ret + n > INT_MAX) {
434 				ret = EOF;
435 				goto error;
436 			}
437 			PRINT(cp, n);
438 			ret += n;
439 		}
440 		if (ch == '\0')
441 			goto done;
442 		fmt++;		/* skip over '%' */
443 
444 		flags = 0;
445 		dprec = 0;
446 		width = 0;
447 		prec = -1;
448 		sign = '\0';
449 
450 rflag:		ch = *fmt++;
451 reswitch:	switch (ch) {
452 		case ' ':
453 			/*
454 			 * ``If the space and + flags both appear, the space
455 			 * flag will be ignored.''
456 			 *	-- ANSI X3J11
457 			 */
458 			if (!sign)
459 				sign = ' ';
460 			goto rflag;
461 		case '#':
462 			flags |= ALT;
463 			goto rflag;
464 		case '*':
465 			/*
466 			 * ``A negative field width argument is taken as a
467 			 * - flag followed by a positive field width.''
468 			 *	-- ANSI X3J11
469 			 * They don't exclude field widths read from args.
470 			 */
471 			GETASTER (width);
472 			if (width >= 0)
473 				goto rflag;
474 			width = -width;
475 			/* FALLTHROUGH */
476 		case '-':
477 			flags |= LADJUST;
478 			goto rflag;
479 		case '+':
480 			sign = '+';
481 			goto rflag;
482 		case '.':
483 			if ((ch = *fmt++) == '*') {
484 				GETASTER (n);
485 				prec = n < 0 ? -1 : n;
486 				goto rflag;
487 			}
488 			n = 0;
489 			while (is_digit(ch)) {
490 				n = 10 * n + to_digit(ch);
491 				ch = *fmt++;
492 			}
493 			prec = n < 0 ? -1 : n;
494 			goto reswitch;
495 		case '0':
496 			/*
497 			 * ``Note that 0 is taken as a flag, not as the
498 			 * beginning of a field width.''
499 			 *	-- ANSI X3J11
500 			 */
501 			flags |= ZEROPAD;
502 			goto rflag;
503 		case '1': case '2': case '3': case '4':
504 		case '5': case '6': case '7': case '8': case '9':
505 			n = 0;
506 			do {
507 				n = 10 * n + to_digit(ch);
508 				ch = *fmt++;
509 			} while (is_digit(ch));
510 			if (ch == '$') {
511 				nextarg = n;
512                         	if (argtable == NULL) {
513                                 	argtable = statargtable;
514                                 	__find_arguments (fmt0, orgap,
515 						&argtable);
516 				}
517 				goto rflag;
518                         }
519 			width = n;
520 			goto reswitch;
521 #ifdef FLOATING_POINT
522 		case 'L':
523 			flags |= LONGDBL;
524 			goto rflag;
525 #endif
526 		case 'h':
527 			flags |= SHORTINT;
528 			goto rflag;
529 		case 'l':
530 			if (flags & LONGINT)
531 				flags |= QUADINT;
532 			else
533 				flags |= LONGINT;
534 			goto rflag;
535 		case 'q':
536 			flags |= QUADINT;
537 			goto rflag;
538 		case 'c':
539 			*(cp = buf) = GETARG(int);
540 			size = 1;
541 			sign = '\0';
542 			break;
543 		case 'D':
544 			flags |= LONGINT;
545 			/*FALLTHROUGH*/
546 		case 'd':
547 		case 'i':
548 			if (flags & QUADINT) {
549 				uqval = GETARG(quad_t);
550 				if ((quad_t)uqval < 0) {
551 					uqval = -uqval;
552 					sign = '-';
553 				}
554 			} else {
555 				ulval = SARG();
556 				if ((long)ulval < 0) {
557 					ulval = -ulval;
558 					sign = '-';
559 				}
560 			}
561 			base = 10;
562 			goto number;
563 #ifdef FLOATING_POINT
564 		case 'e':
565 		case 'E':
566 		case 'f':
567 			goto fp_begin;
568 		case 'g':
569 		case 'G':
570 			if (prec == 0)
571 				prec = 1;
572 fp_begin:		if (prec == -1)
573 				prec = DEFPREC;
574 			if (flags & LONGDBL)
575 				/* XXX this loses precision. */
576 				_double = (double)GETARG(long double);
577 			else
578 				_double = GETARG(double);
579 			/* do this before tricky precision changes */
580 			if (isinf(_double)) {
581 				if (_double < 0)
582 					sign = '-';
583 				cp = "Inf";
584 				size = 3;
585 				break;
586 			}
587 			if (isnan(_double)) {
588 				cp = "NaN";
589 				size = 3;
590 				break;
591 			}
592 			flags |= FPT;
593 			if (dtoaresult != NULL) {
594 				free(dtoaresult);
595 				dtoaresult = NULL;
596 			}
597 			cp = cvt(_double, prec, flags, &softsign,
598 				&expt, ch, &ndig, &dtoaresult);
599 			if (ch == 'g' || ch == 'G') {
600 				if (expt <= -4 || expt > prec)
601 					ch = (ch == 'g') ? 'e' : 'E';
602 				else
603 					ch = 'g';
604 			}
605 			if (ch <= 'e') {	/* 'e' or 'E' fmt */
606 				--expt;
607 				expsize = exponent(expstr, expt, ch);
608 				size = expsize + ndig;
609 				if (ndig > 1 || flags & ALT)
610 					++size;
611 			} else if (ch == 'f') {		/* f fmt */
612 				if (expt > 0) {
613 					size = expt;
614 					if (prec || flags & ALT)
615 						size += prec + 1;
616 				} else	/* "0.X" */
617 					size = prec + 2;
618 			} else if (expt >= ndig) {	/* fixed g fmt */
619 				size = expt;
620 				if (flags & ALT)
621 					++size;
622 			} else
623 				size = ndig + (expt > 0 ?
624 					1 : 2 - expt);
625 
626 			if (softsign)
627 				sign = '-';
628 			break;
629 #endif /* FLOATING_POINT */
630 		case 'n':
631 			if (flags & QUADINT)
632 				*GETARG(quad_t *) = ret;
633 			else if (flags & LONGINT)
634 				*GETARG(long *) = ret;
635 			else if (flags & SHORTINT)
636 				*GETARG(short *) = ret;
637 			else
638 				*GETARG(int *) = ret;
639 			continue;	/* no output */
640 		case 'O':
641 			flags |= LONGINT;
642 			/*FALLTHROUGH*/
643 		case 'o':
644 			if (flags & QUADINT)
645 				uqval = GETARG(u_quad_t);
646 			else
647 				ulval = UARG();
648 			base = 8;
649 			goto nosign;
650 		case 'p':
651 			/*
652 			 * ``The argument shall be a pointer to void.  The
653 			 * value of the pointer is converted to a sequence
654 			 * of printable characters, in an implementation-
655 			 * defined manner.''
656 			 *	-- ANSI X3J11
657 			 */
658 			ulval = (u_long)GETARG(void *);
659 			base = 16;
660 			xdigs = "0123456789abcdef";
661 			flags = (flags & ~QUADINT) | HEXPREFIX;
662 			ch = 'x';
663 			goto nosign;
664 		case 's':
665 			if ((cp = GETARG(char *)) == NULL)
666 				cp = "(null)";
667 			if (prec >= 0) {
668 				/*
669 				 * can't use strlen; can only look for the
670 				 * NUL in the first `prec' characters, and
671 				 * strlen() will go further.
672 				 */
673 				char *p = memchr(cp, 0, (size_t)prec);
674 
675 				if (p != NULL) {
676 					size = p - cp;
677 					if (size > prec)
678 						size = prec;
679 				} else
680 					size = prec;
681 			} else
682 				size = strlen(cp);
683 			sign = '\0';
684 			break;
685 		case 'U':
686 			flags |= LONGINT;
687 			/*FALLTHROUGH*/
688 		case 'u':
689 			if (flags & QUADINT)
690 				uqval = GETARG(u_quad_t);
691 			else
692 				ulval = UARG();
693 			base = 10;
694 			goto nosign;
695 		case 'X':
696 			xdigs = "0123456789ABCDEF";
697 			goto hex;
698 		case 'x':
699 			xdigs = "0123456789abcdef";
700 hex:			if (flags & QUADINT)
701 				uqval = GETARG(u_quad_t);
702 			else
703 				ulval = UARG();
704 			base = 16;
705 			/* leading 0x/X only if non-zero */
706 			if (flags & ALT &&
707 			    (flags & QUADINT ? uqval != 0 : ulval != 0))
708 				flags |= HEXPREFIX;
709 
710 			/* unsigned conversions */
711 nosign:			sign = '\0';
712 			/*
713 			 * ``... diouXx conversions ... if a precision is
714 			 * specified, the 0 flag will be ignored.''
715 			 *	-- ANSI X3J11
716 			 */
717 number:			if ((dprec = prec) >= 0)
718 				flags &= ~ZEROPAD;
719 
720 			/*
721 			 * ``The result of converting a zero value with an
722 			 * explicit precision of zero is no characters.''
723 			 *	-- ANSI X3J11
724 			 */
725 			cp = buf + BUF;
726 			if (flags & QUADINT) {
727 				if (uqval != 0 || prec != 0)
728 					cp = __uqtoa(uqval, cp, base,
729 					    flags & ALT, xdigs);
730 			} else {
731 				if (ulval != 0 || prec != 0)
732 					cp = __ultoa(ulval, cp, base,
733 					    flags & ALT, xdigs);
734 			}
735 			size = buf + BUF - cp;
736 			break;
737 		default:	/* "%?" prints ?, unless ? is NUL */
738 			if (ch == '\0')
739 				goto done;
740 			/* pretend it was %c with argument ch */
741 			cp = buf;
742 			*cp = ch;
743 			size = 1;
744 			sign = '\0';
745 			break;
746 		}
747 
748 		/*
749 		 * All reasonable formats wind up here.  At this point, `cp'
750 		 * points to a string which (if not flags&LADJUST) should be
751 		 * padded out to `width' places.  If flags&ZEROPAD, it should
752 		 * first be prefixed by any sign or other prefix; otherwise,
753 		 * it should be blank padded before the prefix is emitted.
754 		 * After any left-hand padding and prefixing, emit zeroes
755 		 * required by a decimal [diouxX] precision, then print the
756 		 * string proper, then emit zeroes required by any leftover
757 		 * floating precision; finally, if LADJUST, pad with blanks.
758 		 *
759 		 * Compute actual size, so we know how much to pad.
760 		 * size excludes decimal prec; realsz includes it.
761 		 */
762 		realsz = dprec > size ? dprec : size;
763 		if (sign)
764 			realsz++;
765 		else if (flags & HEXPREFIX)
766 			realsz += 2;
767 
768 		prsize = width > realsz ? width : realsz;
769 		if ((unsigned)ret + prsize > INT_MAX) {
770 			ret = EOF;
771 			goto error;
772 		}
773 
774 		/* right-adjusting blank padding */
775 		if ((flags & (LADJUST|ZEROPAD)) == 0)
776 			PAD(width - realsz, blanks);
777 
778 		/* prefix */
779 		if (sign) {
780 			PRINT(&sign, 1);
781 		} else if (flags & HEXPREFIX) {
782 			ox[0] = '0';
783 			ox[1] = ch;
784 			PRINT(ox, 2);
785 		}
786 
787 		/* right-adjusting zero padding */
788 		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
789 			PAD(width - realsz, zeroes);
790 
791 		/* leading zeroes from decimal precision */
792 		PAD(dprec - size, zeroes);
793 
794 		/* the string or number proper */
795 #ifdef FLOATING_POINT
796 		if ((flags & FPT) == 0) {
797 			PRINT(cp, size);
798 		} else {	/* glue together f_p fragments */
799 			if (ch >= 'f') {	/* 'f' or 'g' */
800 				if (_double == 0) {
801 					/* kludge for __dtoa irregularity */
802 					PRINT("0", 1);
803 					if (expt < ndig || (flags & ALT) != 0) {
804 						PRINT(decimal_point, 1);
805 						PAD(ndig - 1, zeroes);
806 					}
807 				} else if (expt <= 0) {
808 					PRINT("0", 1);
809 					PRINT(decimal_point, 1);
810 					PAD(-expt, zeroes);
811 					PRINT(cp, ndig);
812 				} else if (expt >= ndig) {
813 					PRINT(cp, ndig);
814 					PAD(expt - ndig, zeroes);
815 					if (flags & ALT)
816 						PRINT(decimal_point, 1);
817 				} else {
818 					PRINT(cp, expt);
819 					cp += expt;
820 					PRINT(decimal_point, 1);
821 					PRINT(cp, ndig-expt);
822 				}
823 			} else {	/* 'e' or 'E' */
824 				if (ndig > 1 || flags & ALT) {
825 					ox[0] = *cp++;
826 					ox[1] = *decimal_point;
827 					PRINT(ox, 2);
828 					if (_double) {
829 						PRINT(cp, ndig-1);
830 					} else	/* 0.[0..] */
831 						/* __dtoa irregularity */
832 						PAD(ndig - 1, zeroes);
833 				} else	/* XeYYY */
834 					PRINT(cp, 1);
835 				PRINT(expstr, expsize);
836 			}
837 		}
838 #else
839 		PRINT(cp, size);
840 #endif
841 		/* left-adjusting padding (always blank) */
842 		if (flags & LADJUST)
843 			PAD(width - realsz, blanks);
844 
845 		/* finally, adjust ret */
846 		ret += prsize;
847 
848 		FLUSH();	/* copy out the I/O vectors */
849 	}
850 done:
851 	FLUSH();
852 error:
853 #ifdef FLOATING_POINT
854 	if (dtoaresult != NULL)
855 		free(dtoaresult);
856 #endif
857 	if (__sferror(fp))
858 		ret = EOF;
859 	FUNLOCKFILE(fp);
860         if ((argtable != NULL) && (argtable != statargtable))
861                 free (argtable);
862 	return (ret);
863 	/* NOTREACHED */
864 }
865 
866 /*
867  * Type ids for argument type table.
868  */
869 #define T_UNUSED	0
870 #define T_SHORT		1
871 #define T_U_SHORT	2
872 #define TP_SHORT	3
873 #define T_INT		4
874 #define T_U_INT		5
875 #define TP_INT		6
876 #define T_LONG		7
877 #define T_U_LONG	8
878 #define TP_LONG		9
879 #define T_QUAD		10
880 #define T_U_QUAD	11
881 #define TP_QUAD		12
882 #define T_DOUBLE	13
883 #define T_LONG_DOUBLE	14
884 #define TP_CHAR		15
885 #define TP_VOID		16
886 
887 /*
888  * Find all arguments when a positional parameter is encountered.  Returns a
889  * table, indexed by argument number, of pointers to each arguments.  The
890  * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
891  * It will be replaces with a malloc-ed one if it overflows.
892  */
893 static void
894 __find_arguments (const char *fmt0, va_list ap, void ***argtable)
895 {
896 	char *fmt;		/* format string */
897 	int ch;			/* character from fmt */
898 	int n, n2;		/* handy integer (short term usage) */
899 	char *cp;		/* handy char pointer (short term usage) */
900 	int flags;		/* flags as above */
901 	int width;		/* width from format (%8d), or 0 */
902 	unsigned char *typetable; /* table of types */
903 	unsigned char stattypetable [STATIC_ARG_TBL_SIZE];
904 	int tablesize;		/* current size of type table */
905 	int tablemax;		/* largest used index in table */
906 	int nextarg;		/* 1-based argument index */
907 
908 	/*
909 	 * Add an argument type to the table, expanding if necessary.
910 	 */
911 #define ADDTYPE(type) \
912 	((nextarg >= tablesize) ? \
913 		__grow_type_table(nextarg, &typetable, &tablesize) : 0, \
914 	(nextarg > tablemax) ? tablemax = nextarg : 0, \
915 	typetable[nextarg++] = type)
916 
917 #define	ADDSARG() \
918 	((flags&LONGINT) ? ADDTYPE(T_LONG) : \
919 		((flags&SHORTINT) ? ADDTYPE(T_SHORT) : ADDTYPE(T_INT)))
920 
921 #define	ADDUARG() \
922 	((flags&LONGINT) ? ADDTYPE(T_U_LONG) : \
923 		((flags&SHORTINT) ? ADDTYPE(T_U_SHORT) : ADDTYPE(T_U_INT)))
924 
925 	/*
926 	 * Add * arguments to the type array.
927 	 */
928 #define ADDASTER() \
929 	n2 = 0; \
930 	cp = fmt; \
931 	while (is_digit(*cp)) { \
932 		n2 = 10 * n2 + to_digit(*cp); \
933 		cp++; \
934 	} \
935 	if (*cp == '$') { \
936 		int hold = nextarg; \
937 		nextarg = n2; \
938 		ADDTYPE (T_INT); \
939 		nextarg = hold; \
940 		fmt = ++cp; \
941 	} else { \
942 		ADDTYPE (T_INT); \
943 	}
944 	fmt = (char *)fmt0;
945 	typetable = stattypetable;
946 	tablesize = STATIC_ARG_TBL_SIZE;
947 	tablemax = 0;
948 	nextarg = 1;
949 	memset (typetable, T_UNUSED, STATIC_ARG_TBL_SIZE);
950 
951 	/*
952 	 * Scan the format for conversions (`%' character).
953 	 */
954 	for (;;) {
955 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
956 			/* void */;
957 		if (ch == '\0')
958 			goto done;
959 		fmt++;		/* skip over '%' */
960 
961 		flags = 0;
962 		width = 0;
963 
964 rflag:		ch = *fmt++;
965 reswitch:	switch (ch) {
966 		case ' ':
967 		case '#':
968 			goto rflag;
969 		case '*':
970 			ADDASTER ();
971 			goto rflag;
972 		case '-':
973 		case '+':
974 			goto rflag;
975 		case '.':
976 			if ((ch = *fmt++) == '*') {
977 				ADDASTER ();
978 				goto rflag;
979 			}
980 			while (is_digit(ch)) {
981 				ch = *fmt++;
982 			}
983 			goto reswitch;
984 		case '0':
985 			goto rflag;
986 		case '1': case '2': case '3': case '4':
987 		case '5': case '6': case '7': case '8': case '9':
988 			n = 0;
989 			do {
990 				n = 10 * n + to_digit(ch);
991 				ch = *fmt++;
992 			} while (is_digit(ch));
993 			if (ch == '$') {
994 				nextarg = n;
995 				goto rflag;
996 			}
997 			width = n;
998 			goto reswitch;
999 #ifdef FLOATING_POINT
1000 		case 'L':
1001 			flags |= LONGDBL;
1002 			goto rflag;
1003 #endif
1004 		case 'h':
1005 			flags |= SHORTINT;
1006 			goto rflag;
1007 		case 'l':
1008 			if (flags & LONGINT)
1009 				flags |= QUADINT;
1010 			else
1011 				flags |= LONGINT;
1012 			goto rflag;
1013 		case 'q':
1014 			flags |= QUADINT;
1015 			goto rflag;
1016 		case 'c':
1017 			ADDTYPE(T_INT);
1018 			break;
1019 		case 'D':
1020 			flags |= LONGINT;
1021 			/*FALLTHROUGH*/
1022 		case 'd':
1023 		case 'i':
1024 			if (flags & QUADINT) {
1025 				ADDTYPE(T_QUAD);
1026 			} else {
1027 				ADDSARG();
1028 			}
1029 			break;
1030 #ifdef FLOATING_POINT
1031 		case 'e':
1032 		case 'E':
1033 		case 'f':
1034 		case 'g':
1035 		case 'G':
1036 			if (flags & LONGDBL)
1037 				ADDTYPE(T_LONG_DOUBLE);
1038 			else
1039 				ADDTYPE(T_DOUBLE);
1040 			break;
1041 #endif /* FLOATING_POINT */
1042 		case 'n':
1043 			if (flags & QUADINT)
1044 				ADDTYPE(TP_QUAD);
1045 			else if (flags & LONGINT)
1046 				ADDTYPE(TP_LONG);
1047 			else if (flags & SHORTINT)
1048 				ADDTYPE(TP_SHORT);
1049 			else
1050 				ADDTYPE(TP_INT);
1051 			continue;	/* no output */
1052 		case 'O':
1053 			flags |= LONGINT;
1054 			/*FALLTHROUGH*/
1055 		case 'o':
1056 			if (flags & QUADINT)
1057 				ADDTYPE(T_U_QUAD);
1058 			else
1059 				ADDUARG();
1060 			break;
1061 		case 'p':
1062 			ADDTYPE(TP_VOID);
1063 			break;
1064 		case 's':
1065 			ADDTYPE(TP_CHAR);
1066 			break;
1067 		case 'U':
1068 			flags |= LONGINT;
1069 			/*FALLTHROUGH*/
1070 		case 'u':
1071 			if (flags & QUADINT)
1072 				ADDTYPE(T_U_QUAD);
1073 			else
1074 				ADDUARG();
1075 			break;
1076 		case 'X':
1077 		case 'x':
1078 			if (flags & QUADINT)
1079 				ADDTYPE(T_U_QUAD);
1080 			else
1081 				ADDUARG();
1082 			break;
1083 		default:	/* "%?" prints ?, unless ? is NUL */
1084 			if (ch == '\0')
1085 				goto done;
1086 			break;
1087 		}
1088 	}
1089 done:
1090 	/*
1091 	 * Build the argument table.
1092 	 */
1093 	if (tablemax >= STATIC_ARG_TBL_SIZE) {
1094 		*argtable = (void **)
1095 		    malloc (sizeof (void *) * (tablemax + 1));
1096 	}
1097 
1098 	(*argtable) [0] = NULL;
1099 	for (n = 1; n <= tablemax; n++) {
1100 		switch (typetable [n]) {
1101 		    case T_UNUSED:
1102 			(*argtable) [n] = (void *) &va_arg (ap, int);
1103 			break;
1104 		    case T_SHORT:
1105 			(*argtable) [n] = (void *) &va_arg (ap, int);
1106 			break;
1107 		    case T_U_SHORT:
1108 			(*argtable) [n] = (void *) &va_arg (ap, int);
1109 			break;
1110 		    case TP_SHORT:
1111 			(*argtable) [n] = (void *) &va_arg (ap, short *);
1112 			break;
1113 		    case T_INT:
1114 			(*argtable) [n] = (void *) &va_arg (ap, int);
1115 			break;
1116 		    case T_U_INT:
1117 			(*argtable) [n] = (void *) &va_arg (ap, unsigned int);
1118 			break;
1119 		    case TP_INT:
1120 			(*argtable) [n] = (void *) &va_arg (ap, int *);
1121 			break;
1122 		    case T_LONG:
1123 			(*argtable) [n] = (void *) &va_arg (ap, long);
1124 			break;
1125 		    case T_U_LONG:
1126 			(*argtable) [n] = (void *) &va_arg (ap, unsigned long);
1127 			break;
1128 		    case TP_LONG:
1129 			(*argtable) [n] = (void *) &va_arg (ap, long *);
1130 			break;
1131 		    case T_QUAD:
1132 			(*argtable) [n] = (void *) &va_arg (ap, quad_t);
1133 			break;
1134 		    case T_U_QUAD:
1135 			(*argtable) [n] = (void *) &va_arg (ap, u_quad_t);
1136 			break;
1137 		    case TP_QUAD:
1138 			(*argtable) [n] = (void *) &va_arg (ap, quad_t *);
1139 			break;
1140 		    case T_DOUBLE:
1141 			(*argtable) [n] = (void *) &va_arg (ap, double);
1142 			break;
1143 		    case T_LONG_DOUBLE:
1144 			(*argtable) [n] = (void *) &va_arg (ap, long double);
1145 			break;
1146 		    case TP_CHAR:
1147 			(*argtable) [n] = (void *) &va_arg (ap, char *);
1148 			break;
1149 		    case TP_VOID:
1150 			(*argtable) [n] = (void *) &va_arg (ap, void *);
1151 			break;
1152 		}
1153 	}
1154 
1155 	if ((typetable != NULL) && (typetable != stattypetable))
1156 		free (typetable);
1157 }
1158 
1159 /*
1160  * Increase the size of the type table.
1161  */
1162 static void
1163 __grow_type_table (int nextarg, unsigned char **typetable, int *tablesize)
1164 {
1165 	unsigned char *const oldtable = *typetable;
1166 	const int oldsize = *tablesize;
1167 	unsigned char *newtable;
1168 	int newsize = oldsize * 2;
1169 
1170 	if (newsize < nextarg + 1)
1171 		newsize = nextarg + 1;
1172 	if (oldsize == STATIC_ARG_TBL_SIZE) {
1173 		if ((newtable = malloc(newsize)) == NULL)
1174 			abort();			/* XXX handle better */
1175 		bcopy(oldtable, newtable, oldsize);
1176 	} else {
1177 		if ((newtable = reallocf(oldtable, newsize)) == NULL)
1178 			abort();			/* XXX handle better */
1179 	}
1180 	memset(&newtable[oldsize], T_UNUSED, newsize - oldsize);
1181 
1182 	*typetable = newtable;
1183 	*tablesize = newsize;
1184 }
1185 
1186 
1187 #ifdef FLOATING_POINT
1188 
1189 extern char *__dtoa (double, int, int, int *, int *, char **, char **);
1190 
1191 static char *
1192 cvt(double value, int ndigits, int flags, char *sign, int *decpt,
1193     int ch, int *length, char **dtoaresultp)
1194 {
1195 	int mode, dsgn;
1196 	char *digits, *bp, *rve;
1197 
1198 	if (ch == 'f')
1199 		mode = 3;		/* ndigits after the decimal point */
1200 	else {
1201 		/*
1202 		 * To obtain ndigits after the decimal point for the 'e'
1203 		 * and 'E' formats, round to ndigits + 1 significant
1204 		 * figures.
1205 		 */
1206 		if (ch == 'e' || ch == 'E')
1207 			ndigits++;
1208 		mode = 2;		/* ndigits significant digits */
1209 	}
1210 	digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve, dtoaresultp);
1211 	*sign = dsgn != 0;
1212 	if ((ch != 'g' && ch != 'G') || flags & ALT) {
1213 		/* print trailing zeros */
1214 		bp = digits + ndigits;
1215 		if (ch == 'f') {
1216 			if (*digits == '0' && value)
1217 				*decpt = -ndigits + 1;
1218 			bp += *decpt;
1219 		}
1220 		if (value == 0)	/* kludge for __dtoa irregularity */
1221 			rve = bp;
1222 		while (rve < bp)
1223 			*rve++ = '0';
1224 	}
1225 	*length = rve - digits;
1226 	return (digits);
1227 }
1228 
1229 static int
1230 exponent(char *p0, int exp, int fmtch)
1231 {
1232 	char *p, *t;
1233 	char expbuf[MAXEXP];
1234 
1235 	p = p0;
1236 	*p++ = fmtch;
1237 	if (exp < 0) {
1238 		exp = -exp;
1239 		*p++ = '-';
1240 	}
1241 	else
1242 		*p++ = '+';
1243 	t = expbuf + MAXEXP;
1244 	if (exp > 9) {
1245 		do {
1246 			*--t = to_char(exp % 10);
1247 		} while ((exp /= 10) > 9);
1248 		*--t = to_char(exp);
1249 		for (; t < expbuf + MAXEXP; *p++ = *t++);
1250 	}
1251 	else {
1252 		*p++ = '0';
1253 		*p++ = to_char(exp);
1254 	}
1255 	return (p - p0);
1256 }
1257 #endif /* FLOATING_POINT */
1258