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