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