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 * 4. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#if defined(LIBC_SCCS) && !defined(lint)
34static char sccsid[] = "@(#)vfprintf.c	8.1 (Berkeley) 6/4/93";
35#endif /* LIBC_SCCS and not lint */
36#include <sys/cdefs.h>
37__FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
38
39#include "xlocale_private.h"
40
41/*
42 * Actual printf innards.
43 *
44 * This code is large and complicated...
45 */
46
47#include "namespace.h"
48#include <sys/types.h>
49
50#include <ctype.h>
51#include <limits.h>
52#include <locale.h>
53#include <stddef.h>
54#include <stdint.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58#include <wchar.h>
59#if 0 // xprintf pending API review
60#include <printf.h>
61#endif
62#include <errno.h>
63
64#include <stdarg.h>
65#include "un-namespace.h"
66
67#include "libc_private.h"
68#include "local.h"
69#include "fvwrite.h"
70#include "printflocal.h"
71
72static int	__sprint(FILE *, locale_t, struct __suio *);
73#if 0
74static int	__sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
75#endif
76static char	*__wcsconv(wchar_t *, int, locale_t);
77
78__private_extern__ const char *__fix_nogrouping(const char *);
79
80#define	CHAR	char
81#include "printfcommon.h"
82
83struct grouping_state {
84	char *thousands_sep;	/* locale-specific thousands separator */
85	int thousep_len;	/* length of thousands_sep */
86	const char *grouping;	/* locale-specific numeric grouping rules */
87	int lead;		/* sig figs before decimal or group sep */
88	int nseps;		/* number of group separators with ' */
89	int nrepeats;		/* number of repeats of the last group */
90};
91
92/*
93 * Initialize the thousands' grouping state in preparation to print a
94 * number with ndigits digits. This routine returns the total number
95 * of bytes that will be needed.
96 */
97static int
98grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
99{
100	struct lconv *locale;
101
102	locale = localeconv_l(loc);
103	gs->grouping = __fix_nogrouping(locale->grouping);
104	gs->thousands_sep = locale->thousands_sep;
105	gs->thousep_len = strlen(gs->thousands_sep);
106
107	gs->nseps = gs->nrepeats = 0;
108	gs->lead = ndigits;
109	while (*gs->grouping != CHAR_MAX) {
110		if (gs->lead <= *gs->grouping)
111			break;
112		gs->lead -= *gs->grouping;
113		if (*(gs->grouping+1)) {
114			gs->nseps++;
115			gs->grouping++;
116		} else
117			gs->nrepeats++;
118	}
119	return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
120}
121
122/*
123 * Print a number with thousands' separators.
124 */
125static int
126grouping_print(struct grouping_state *gs, struct io_state *iop,
127	       const CHAR *cp, const CHAR *ep, locale_t loc)
128{
129	const CHAR *cp0 = cp;
130
131	if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
132		return (-1);
133	cp += gs->lead;
134	while (gs->nseps > 0 || gs->nrepeats > 0) {
135		if (gs->nrepeats > 0)
136			gs->nrepeats--;
137		else {
138			gs->grouping--;
139			gs->nseps--;
140		}
141		if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
142			return (-1);
143		if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
144			return (-1);
145		cp += *gs->grouping;
146	}
147	if (cp > ep)
148		cp = ep;
149	return (cp - cp0);
150}
151
152/*
153 * Flush out all the vectors defined by the given uio,
154 * then reset it so that it can be reused.
155 */
156static int
157__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
158{
159	int err;
160
161	if (uio->uio_resid == 0) {
162		uio->uio_iovcnt = 0;
163		return (0);
164	}
165	err = __sfvwrite(fp, uio);
166	uio->uio_resid = 0;
167	uio->uio_iovcnt = 0;
168	return (err);
169}
170
171#if 0
172/*
173 * Helper function for `fprintf to unbuffered unix file': creates a
174 * temporary buffer.  We only work on write-only files; this avoids
175 * worries about ungetc buffers and so forth.
176 */
177static int
178__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap)
179{
180	int ret;
181	FILE fake;
182	unsigned char buf[BUFSIZ];
183	struct __sFILEX ext;
184	fake._extra = &ext;
185	INITEXTRA(&fake);
186
187	/* XXX This is probably not needed. */
188	if (prepwrite(fp) != 0)
189		return (EOF);
190
191	/* copy the important variables */
192	fake._flags = fp->_flags & ~__SNBF;
193	fake._file = fp->_file;
194	fake._cookie = fp->_cookie;
195	fake._write = fp->_write;
196	fake._orientation = fp->_orientation;
197	fake._mbstate = fp->_mbstate;
198
199	/* set up the buffer */
200	fake._bf._base = fake._p = buf;
201	fake._bf._size = fake._w = sizeof(buf);
202	fake._lbfsize = 0;	/* not actually used, but Just In Case */
203
204	/* do the work, then copy any error status */
205	ret = __vfprintf(&fake, loc, fmt, ap);
206	if (ret >= 0 && __fflush(&fake))
207		ret = EOF;
208	if (fake._flags & __SERR)
209		fp->_flags |= __SERR;
210	return (ret);
211}
212#endif
213
214/*
215 * Convert a wide character string argument for the %ls format to a multibyte
216 * string representation. If not -1, prec specifies the maximum number of
217 * bytes to output, and also means that we can't assume that the wide char.
218 * string ends is null-terminated.
219 */
220static char *
221__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
222{
223	static const mbstate_t initial;
224	mbstate_t mbs;
225	char buf[MB_LEN_MAX];
226	wchar_t *p;
227	char *convbuf;
228	size_t clen, nbytes;
229
230	/* Allocate space for the maximum number of bytes we could output. */
231	if (prec < 0) {
232		p = wcsarg;
233		mbs = initial;
234		nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
235		if (nbytes == (size_t)-1)
236			return (NULL);
237	} else {
238		/*
239		 * Optimisation: if the output precision is small enough,
240		 * just allocate enough memory for the maximum instead of
241		 * scanning the string.
242		 */
243		if (prec < 128)
244			nbytes = prec;
245		else {
246			nbytes = 0;
247			p = wcsarg;
248			mbs = initial;
249			for (;;) {
250				clen = wcrtomb_l(buf, *p++, &mbs, loc);
251				if (clen == 0 || clen == (size_t)-1 ||
252				    nbytes + clen > prec)
253					break;
254				nbytes += clen;
255			}
256		}
257	}
258	if ((convbuf = malloc(nbytes + 1)) == NULL)
259		return (NULL);
260
261	/* Fill the output buffer. */
262	p = wcsarg;
263	mbs = initial;
264	if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
265	    nbytes, &mbs, loc)) == (size_t)-1) {
266		free(convbuf);
267		return (NULL);
268	}
269	convbuf[nbytes] = '\0';
270	return (convbuf);
271}
272
273/*
274 * MT-safe version
275 */
276int
277vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
278
279{
280	int ret;
281
282	FLOCKFILE(fp);
283	ret = __xvprintf(XPRINTF_PLAIN, NULL, fp, loc, fmt0, ap);
284	FUNLOCKFILE(fp);
285	return (ret);
286}
287
288int
289vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
290
291{
292	int ret;
293
294	FLOCKFILE(fp);
295	ret = __xvprintf(XPRINTF_PLAIN, NULL, fp, __current_locale(), fmt0, ap);
296	FUNLOCKFILE(fp);
297	return ret;
298}
299
300/*
301 * The size of the buffer we use as scratch space for integer
302 * conversions, among other things.  We need enough space to
303 * write a uintmax_t in octal (plus one byte).
304 */
305#if UINTMAX_MAX <= UINT64_MAX
306#define	BUF	32
307#else
308#error "BUF must be large enough to format a uintmax_t"
309#endif
310
311/*
312 * Non-MT-safe version
313 */
314__private_extern__ int
315__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
316{
317	char *fmt;		/* format string */
318	int ch;			/* character from fmt */
319	int n, n2;		/* handy integer (short term usage) */
320	char *cp;		/* handy char pointer (short term usage) */
321	int flags;		/* flags as above */
322	int ret;		/* return value accumulator */
323	int width;		/* width from format (%8d), or 0 */
324	int prec;		/* precision from format; <0 for N/A */
325	char sign;		/* sign prefix (' ', '+', '-', or \0) */
326	struct grouping_state gs; /* thousands' grouping info */
327
328#ifndef NO_FLOATING_POINT
329	/*
330	 * We can decompose the printed representation of floating
331	 * point numbers into several parts, some of which may be empty:
332	 *
333	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
334	 *    A       B     ---C---      D       E   F
335	 *
336	 * A:	'sign' holds this value if present; '\0' otherwise
337	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
338	 * C:	cp points to the string MMMNNN.  Leading and trailing
339	 *	zeros are not in the string and must be added.
340	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
341	 * F:	at least two digits for decimal, at least one digit for hex
342	 */
343	char *decimal_point;	/* locale specific decimal point */
344	int decpt_len;		/* length of decimal_point */
345	int signflag;		/* true if float is negative */
346	union {			/* floating point arguments %[aAeEfFgG] */
347		double dbl;
348		long double ldbl;
349	} fparg;
350	int expt;		/* integer value of exponent */
351	char expchar;		/* exponent character: [eEpP\0] */
352	char *dtoaend;		/* pointer to end of converted digits */
353	int expsize;		/* character count for expstr */
354	int ndig;		/* actual number of digits returned by dtoa */
355	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
356	char *dtoaresult;	/* buffer allocated by dtoa */
357#endif
358#ifdef VECTORS
359	union arg vval;		/* Vector argument. */
360	char *pct;		/* Pointer to '%' at beginning of specifier. */
361	char vsep;		/* Vector separator character. */
362#endif
363	u_long	ulval;		/* integer arguments %[diouxX] */
364	uintmax_t ujval;	/* %j, %ll, %q, %t, %z integers */
365	int base;		/* base for [diouxX] conversion */
366	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
367	int realsz;		/* field size expanded by dprec, sign, etc */
368	int size;		/* size of converted field or string */
369	int prsize;             /* max size of printed field */
370	const char *xdigs;     	/* digits for %[xX] conversion */
371	struct io_state io;	/* I/O buffering state */
372	char buf[BUF];		/* buffer with space for digits of uintmax_t */
373	char ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
374	union arg *argtable;    /* args, built due to positional arg */
375	union arg statargtable [STATIC_ARG_TBL_SIZE];
376	int nextarg;            /* 1-based argument index */
377	va_list orgap;          /* original argument pointer */
378	char *convbuf;		/* wide to multibyte conversion result */
379
380	static const char xdigs_lower[16] = "0123456789abcdef";
381	static const char xdigs_upper[16] = "0123456789ABCDEF";
382
383	/* BEWARE, these `goto error' on error. */
384#define	PRINT(ptr, len) { \
385	if (io_print(&io, (ptr), (len), loc))	\
386		goto error; \
387}
388#define	PAD(howmany, with) { \
389	if (io_pad(&io, (howmany), (with), loc)) \
390		goto error; \
391}
392#define	PRINTANDPAD(p, ep, len, with) {	\
393	if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
394		goto error; \
395}
396#define	FLUSH() { \
397	if (io_flush(&io, loc)) \
398		goto error; \
399}
400
401	/*
402	 * Get the argument indexed by nextarg.   If the argument table is
403	 * built, use it to get the argument.  If its not, get the next
404	 * argument (and arguments must be gotten sequentially).
405	 */
406#define GETARG(type) \
407	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
408	    (nextarg++, va_arg(ap, type)))
409
410	/*
411	 * To extend shorts properly, we need both signed and unsigned
412	 * argument extraction methods.
413	 */
414#define	SARG() \
415	(flags&LONGINT ? GETARG(long) : \
416	    flags&SHORTINT ? (long)(short)GETARG(int) : \
417	    flags&CHARINT ? (long)(signed char)GETARG(int) : \
418	    (long)GETARG(int))
419#define	UARG() \
420	(flags&LONGINT ? GETARG(u_long) : \
421	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
422	    flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
423	    (u_long)GETARG(u_int))
424#define	INTMAX_SIZE	(INTMAXT|SIZET|PTRDIFFT|LLONGINT)
425#define SJARG() \
426	(flags&INTMAXT ? GETARG(intmax_t) : \
427	    flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
428	    flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
429	    (intmax_t)GETARG(long long))
430#define	UJARG() \
431	(flags&INTMAXT ? GETARG(uintmax_t) : \
432	    flags&SIZET ? (uintmax_t)GETARG(size_t) : \
433	    flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
434	    (uintmax_t)GETARG(unsigned long long))
435
436	/*
437	 * Get * arguments, including the form *nn$.  Preserve the nextarg
438	 * that the argument can be gotten once the type is determined.
439	 */
440#define GETASTER(val) \
441	n2 = 0; \
442	cp = fmt; \
443	while (is_digit(*cp)) { \
444		n2 = 10 * n2 + to_digit(*cp); \
445		cp++; \
446	} \
447	if (*cp == '$') { \
448		int hold = nextarg; \
449		if (argtable == NULL) { \
450			argtable = statargtable; \
451			if (__find_arguments (fmt0, orgap, &argtable)) { \
452				ret = EOF; \
453				goto error; \
454			} \
455		} \
456		nextarg = n2; \
457		val = GETARG (int); \
458		nextarg = hold; \
459		fmt = ++cp; \
460	} else { \
461		val = GETARG (int); \
462	}
463
464	/* The following has been moved to __v2printf() */
465#if 0
466	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
467	if (prepwrite(fp) != 0) {
468		errno = EBADF;
469		return (EOF);
470	}
471	ORIENT(fp, -1);
472#endif
473
474	convbuf = NULL;
475	fmt = (char *)fmt0;
476	argtable = NULL;
477	nextarg = 1;
478	va_copy(orgap, ap);
479	io_init(&io, fp);
480	ret = 0;
481#ifndef NO_FLOATING_POINT
482	dtoaresult = NULL;
483	decimal_point = localeconv_l(loc)->decimal_point;
484	/* The overwhelmingly common case is decpt_len == 1. */
485	decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
486#endif
487
488	/*
489	 * Scan the format for conversions (`%' character).
490	 */
491	for (;;) {
492		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
493			/* void */;
494		if ((n = fmt - cp) != 0) {
495			if ((unsigned)ret + n > INT_MAX) {
496				ret = EOF;
497				goto error;
498			}
499			PRINT(cp, n);
500			ret += n;
501		}
502		if (ch == '\0')
503			goto done;
504#ifdef VECTORS
505		pct = fmt;
506#endif /* VECTORS */
507		fmt++;		/* skip over '%' */
508
509		flags = 0;
510		dprec = 0;
511		width = 0;
512		prec = -1;
513		gs.grouping = NULL;
514		sign = '\0';
515		ox[1] = '\0';
516#ifdef VECTORS
517		vsep = 'X'; /* Illegal value, changed to defaults later. */
518#endif /* VECTORS */
519
520rflag:		ch = *fmt++;
521reswitch:	switch (ch) {
522		case ' ':
523			/*-
524			 * ``If the space and + flags both appear, the space
525			 * flag will be ignored.''
526			 *	-- ANSI X3J11
527			 */
528			if (!sign)
529				sign = ' ';
530			goto rflag;
531		case '#':
532			flags |= ALT;
533			goto rflag;
534#ifdef VECTORS
535		case ',': case ';': case ':': case '_':
536			vsep = ch;
537			goto rflag;
538#endif /* VECTORS */
539		case '*':
540			/*-
541			 * ``A negative field width argument is taken as a
542			 * - flag followed by a positive field width.''
543			 *	-- ANSI X3J11
544			 * They don't exclude field widths read from args.
545			 */
546			GETASTER (width);
547			if (width >= 0)
548				goto rflag;
549			width = -width;
550			/* FALLTHROUGH */
551		case '-':
552			flags |= LADJUST;
553			goto rflag;
554		case '+':
555			sign = '+';
556			goto rflag;
557		case '\'':
558			flags |= GROUPING;
559			goto rflag;
560		case '.':
561			if ((ch = *fmt++) == '*') {
562				GETASTER (prec);
563				goto rflag;
564			}
565			prec = 0;
566			while (is_digit(ch)) {
567				prec = 10 * prec + to_digit(ch);
568				ch = *fmt++;
569			}
570			goto reswitch;
571		case '0':
572			/*-
573			 * ``Note that 0 is taken as a flag, not as the
574			 * beginning of a field width.''
575			 *	-- ANSI X3J11
576			 */
577			flags |= ZEROPAD;
578			goto rflag;
579		case '1': case '2': case '3': case '4':
580		case '5': case '6': case '7': case '8': case '9':
581			n = 0;
582			do {
583				n = 10 * n + to_digit(ch);
584				ch = *fmt++;
585			} while (is_digit(ch));
586			if (ch == '$') {
587				nextarg = n;
588				if (argtable == NULL) {
589					argtable = statargtable;
590					if (__find_arguments (fmt0, orgap,
591							      &argtable)) {
592						ret = EOF;
593						goto error;
594					}
595				}
596				goto rflag;
597			}
598			width = n;
599			goto reswitch;
600#ifndef NO_FLOATING_POINT
601		case 'L':
602			flags |= LONGDBL;
603			goto rflag;
604#endif
605		case 'h':
606			if (flags & SHORTINT) {
607				flags &= ~SHORTINT;
608				flags |= CHARINT;
609			} else
610				flags |= SHORTINT;
611			goto rflag;
612		case 'j':
613			flags |= INTMAXT;
614			goto rflag;
615		case 'l':
616			if (flags & LONGINT) {
617				flags &= ~LONGINT;
618				flags |= LLONGINT;
619			} else
620				flags |= LONGINT;
621			goto rflag;
622		case 'q':
623			flags |= LLONGINT;	/* not necessarily */
624			goto rflag;
625		case 't':
626			flags |= PTRDIFFT;
627			goto rflag;
628		case 'z':
629			flags |= SIZET;
630			goto rflag;
631		case 'C':
632			flags |= LONGINT;
633			/*FALLTHROUGH*/
634		case 'c':
635#ifdef VECTORS
636			if (flags & VECTOR)
637				break;
638#endif /* VECTORS */
639			if (flags & LONGINT) {
640				static const mbstate_t initial;
641				mbstate_t mbs;
642				size_t mbseqlen;
643
644				mbs = initial;
645				mbseqlen = wcrtomb_l(cp = buf,
646				    (wchar_t)GETARG(wint_t), &mbs, loc);
647				if (mbseqlen == (size_t)-1) {
648					fp->_flags |= __SERR;
649					goto error;
650				}
651				size = (int)mbseqlen;
652			} else {
653				*(cp = buf) = GETARG(int);
654				size = 1;
655			}
656			sign = '\0';
657			break;
658		case 'D':
659			flags |= LONGINT;
660			/*FALLTHROUGH*/
661		case 'd':
662		case 'i':
663#ifdef VECTORS
664			if (flags & VECTOR)
665				break;
666#endif /* VECTORS */
667			if (flags & INTMAX_SIZE) {
668				ujval = SJARG();
669				if ((intmax_t)ujval < 0) {
670					ujval = -ujval;
671					sign = '-';
672				}
673			} else {
674				ulval = SARG();
675				if ((long)ulval < 0) {
676					ulval = -ulval;
677					sign = '-';
678				}
679			}
680			base = 10;
681			goto number;
682#ifndef NO_FLOATING_POINT
683		case 'a':
684		case 'A':
685#ifdef VECTORS
686			if (flags & VECTOR) {
687				flags |= FPT;
688				break;
689			}
690#endif /* VECTORS */
691			if (ch == 'a') {
692				ox[1] = 'x';
693				xdigs = xdigs_lower;
694				expchar = 'p';
695			} else {
696				ox[1] = 'X';
697				xdigs = xdigs_upper;
698				expchar = 'P';
699			}
700			if (prec >= 0)
701				prec++;
702			if (dtoaresult != NULL)
703				freedtoa(dtoaresult);
704			if (flags & LONGDBL) {
705				fparg.ldbl = GETARG(long double);
706				dtoaresult = cp =
707				    __hldtoa(fparg.ldbl, xdigs, prec,
708				    &expt, &signflag, &dtoaend);
709			} else {
710				fparg.dbl = GETARG(double);
711				dtoaresult = cp =
712				    __hdtoa(fparg.dbl, xdigs, prec,
713				    &expt, &signflag, &dtoaend);
714			}
715			if (prec < 0)
716				prec = dtoaend - cp;
717			if (expt == INT_MAX)
718				ox[1] = '\0';
719			goto fp_common;
720		case 'e':
721		case 'E':
722#ifdef VECTORS
723			if (flags & VECTOR) {
724				flags |= FPT;
725				break;
726			}
727#endif /* VECTORS */
728			expchar = ch;
729			if (prec < 0)	/* account for digit before decpt */
730				prec = DEFPREC + 1;
731			else
732				prec++;
733			goto fp_begin;
734		case 'f':
735		case 'F':
736#ifdef VECTORS
737			if (flags & VECTOR) {
738				flags |= FPT;
739				break;
740			}
741#endif /* VECTORS */
742			expchar = '\0';
743			goto fp_begin;
744		case 'g':
745		case 'G':
746#ifdef VECTORS
747			if (flags & VECTOR) {
748				flags |= FPT;
749				break;
750			}
751#endif /* VECTORS */
752			expchar = ch - ('g' - 'e');
753			if (prec == 0)
754				prec = 1;
755fp_begin:
756			if (prec < 0)
757				prec = DEFPREC;
758			if (dtoaresult != NULL)
759				freedtoa(dtoaresult);
760			if (flags & LONGDBL) {
761				fparg.ldbl = GETARG(long double);
762				dtoaresult = cp =
763				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
764				    &expt, &signflag, &dtoaend);
765			} else {
766				fparg.dbl = GETARG(double);
767				dtoaresult = cp =
768				    dtoa(fparg.dbl, expchar ? 2 : 3, prec,
769				    &expt, &signflag, &dtoaend);
770				if (expt == 9999)
771					expt = INT_MAX;
772			}
773fp_common:
774			if (signflag)
775				sign = '-';
776			if (expt == INT_MAX) {	/* inf or nan */
777				if (*cp == 'N') {
778					cp = (ch >= 'a') ? "nan" : "NAN";
779					sign = '\0';
780				} else
781					cp = (ch >= 'a') ? "inf" : "INF";
782				size = 3;
783				flags &= ~ZEROPAD;
784				break;
785			}
786			flags |= FPT;
787			ndig = dtoaend - cp;
788			if (ch == 'g' || ch == 'G') {
789				if (expt > -4 && expt <= prec) {
790					/* Make %[gG] smell like %[fF] */
791					expchar = '\0';
792					if (flags & ALT)
793						prec -= expt;
794					else
795						prec = ndig - expt;
796					if (prec < 0)
797						prec = 0;
798				} else {
799					/*
800					 * Make %[gG] smell like %[eE], but
801					 * trim trailing zeroes if no # flag.
802					 */
803					if (!(flags & ALT))
804						prec = ndig;
805				}
806			}
807			if (expchar) {
808				expsize = exponent(expstr, expt - 1, expchar);
809				size = expsize + prec;
810				if (prec > 1 || flags & ALT)
811					size += decpt_len;
812			} else {
813				/* space for digits before decimal point */
814				if (expt > 0)
815					size = expt;
816				else	/* "0" */
817					size = 1;
818				/* space for decimal pt and following digits */
819				if (prec || flags & ALT)
820					size += prec + decpt_len;
821				if ((flags & GROUPING) && expt > 0)
822					size += grouping_init(&gs, expt, loc);
823			}
824			break;
825#endif /* !NO_FLOATING_POINT */
826		case 'n':
827		{
828			/*
829			 * Assignment-like behavior is specified if the
830			 * value overflows or is otherwise unrepresentable.
831			 * C99 says to use `signed char' for %hhn conversions.
832			 */
833			void *ptr = GETARG(void *);
834			if (ptr == NULL)
835				continue;
836			else if (flags & LLONGINT)
837				*(long long *)ptr = ret;
838			else if (flags & SIZET)
839				*(ssize_t *)ptr = (ssize_t)ret;
840			else if (flags & PTRDIFFT)
841				*(ptrdiff_t *)ptr = ret;
842			else if (flags & INTMAXT)
843				*(intmax_t *)ptr = ret;
844			else if (flags & LONGINT)
845				*(long *)ptr = ret;
846			else if (flags & SHORTINT)
847				*(short *)ptr = ret;
848			else if (flags & CHARINT)
849				*(signed char *)ptr = ret;
850			else
851				*(int *)ptr = ret;
852			continue;	/* no output */
853		}
854		case 'O':
855			flags |= LONGINT;
856			/*FALLTHROUGH*/
857		case 'o':
858#ifdef VECTORS
859			if (flags & VECTOR)
860				break;
861#endif /* VECTORS */
862			if (flags & INTMAX_SIZE)
863				ujval = UJARG();
864			else
865				ulval = UARG();
866			base = 8;
867			goto nosign;
868		case 'p':
869			/*-
870			 * ``The argument shall be a pointer to void.  The
871			 * value of the pointer is converted to a sequence
872			 * of printable characters, in an implementation-
873			 * defined manner.''
874			 *	-- ANSI X3J11
875			 */
876#ifdef VECTORS
877			if (flags & VECTOR)
878				break;
879#endif /* VECTORS */
880			ujval = (uintmax_t)(uintptr_t)GETARG(void *);
881			base = 16;
882			xdigs = xdigs_lower;
883			flags = flags | INTMAXT;
884			ox[1] = 'x';
885			goto nosign;
886		case 'S':
887			flags |= LONGINT;
888			/*FALLTHROUGH*/
889		case 's':
890			if (flags & LONGINT) {
891				wchar_t *wcp;
892
893				if (convbuf != NULL)
894					free(convbuf);
895				if ((wcp = GETARG(wchar_t *)) == NULL)
896					cp = "(null)";
897				else {
898					convbuf = __wcsconv(wcp, prec, loc);
899					if (convbuf == NULL) {
900						fp->_flags |= __SERR;
901						goto error;
902					}
903					cp = convbuf;
904				}
905			} else if ((cp = GETARG(char *)) == NULL)
906				cp = "(null)";
907			size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
908			sign = '\0';
909			break;
910		case 'U':
911			flags |= LONGINT;
912			/*FALLTHROUGH*/
913		case 'u':
914#ifdef VECTORS
915			if (flags & VECTOR)
916				break;
917#endif /* VECTORS */
918			if (flags & INTMAX_SIZE)
919				ujval = UJARG();
920			else
921				ulval = UARG();
922			base = 10;
923			goto nosign;
924		case 'X':
925			xdigs = xdigs_upper;
926			goto hex;
927		case 'x':
928			xdigs = xdigs_lower;
929hex:
930#ifdef VECTORS
931			if (flags & VECTOR)
932				break;
933#endif /* VECTORS */
934			if (flags & INTMAX_SIZE)
935				ujval = UJARG();
936			else
937				ulval = UARG();
938			base = 16;
939			/* leading 0x/X only if non-zero */
940			if (flags & ALT &&
941			    (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
942				ox[1] = ch;
943
944			flags &= ~GROUPING;
945			/* unsigned conversions */
946nosign:			sign = '\0';
947			/*-
948			 * ``... diouXx conversions ... if a precision is
949			 * specified, the 0 flag will be ignored.''
950			 *	-- ANSI X3J11
951			 * except for %#.0o and zero value
952			 */
953number:			if ((dprec = prec) >= 0)
954				flags &= ~ZEROPAD;
955
956			/*-
957			 * ``The result of converting a zero value with an
958			 * explicit precision of zero is no characters.''
959			 *	-- ANSI X3J11
960			 *
961			 * ``The C Standard is clear enough as is.  The call
962			 * printf("%#.0o", 0) should print 0.''
963			 *	-- Defect Report #151
964			 */
965			cp = buf + BUF;
966			if (flags & INTMAX_SIZE) {
967				if (ujval != 0 || prec != 0 ||
968				    (flags & ALT && base == 8))
969					cp = __ujtoa(ujval, cp, base,
970					    flags & ALT, xdigs);
971			} else {
972				if (ulval != 0 || prec != 0 ||
973				    (flags & ALT && base == 8))
974					cp = __ultoa(ulval, cp, base,
975					    flags & ALT, xdigs);
976			}
977			size = buf + BUF - cp;
978			if (size > BUF)	/* should never happen */
979				LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
980			if ((flags & GROUPING) && size != 0)
981				size += grouping_init(&gs, size, loc);
982			break;
983#ifdef VECTORS
984		case 'v':
985			flags |= VECTOR;
986			goto rflag;
987#endif /* VECTORS */
988		default:	/* "%?" prints ?, unless ? is NUL */
989			if (ch == '\0')
990				goto done;
991			/* pretend it was %c with argument ch */
992			cp = buf;
993			*cp = ch;
994			size = 1;
995			sign = '\0';
996			break;
997		}
998
999#ifdef VECTORS
1000		if (flags & VECTOR) {
1001			/*
1002			 * Do the minimum amount of work necessary to construct
1003			 * a format specifier that can be used to recursively
1004			 * call vfprintf() for each element in the vector.
1005			 */
1006			int i, j;	/* Counter. */
1007			int vcnt;	/* Number of elements in vector. */
1008			char *vfmt;	/* Pointer to format specifier. */
1009#define EXTRAHH 2
1010			char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
1011			int vwidth = 0;	/* Width specified via '*'. */
1012			int vprec = 0;	/* Precision specified via '*'. */
1013			char *vstr;	/* Used for asprintf(). */
1014			int vlen;	/* Length returned by asprintf(). */
1015			enum {
1016			    V_CHAR, V_SHORT, V_INT,
1017			    V_PCHAR, V_PSHORT, V_PINT,
1018			    V_FLOAT,
1019#ifdef V64TYPE
1020			    V_LONGLONG, V_PLONGLONG,
1021			    V_DOUBLE,
1022#endif /* V64TYPE */
1023			} vtype;
1024
1025			vval.vectorarg = GETARG(VECTORTYPE);
1026			/*
1027			 * Set vfmt.  If vfmt_buf may not be big enough,
1028			 * malloc() space, taking care to free it later.
1029			 * (EXTRAHH is for possible extra "hh")
1030			 */
1031			if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
1032				vfmt = vfmt_buf;
1033			else
1034				vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
1035
1036			/* Set the separator character, if not specified. */
1037			if (vsep == 'X') {
1038				if (ch == 'c')
1039					vsep = '\0';
1040				else
1041					vsep = ' ';
1042			}
1043
1044			/* Create the format specifier. */
1045			for (i = j = 0; i < &fmt[-1] - pct; i++) {
1046				switch (pct[i]) {
1047				case ',': case ';': case ':': case '_':
1048				case 'v': case 'h': case 'l':
1049					/* Ignore. */
1050					break;
1051				case '*':
1052					if (pct[i - 1] != '.')
1053						vwidth = 1;
1054					else
1055						vprec = 1;
1056					/* FALLTHROUGH */
1057				default:
1058					vfmt[j++] = pct[i];
1059				}
1060			}
1061
1062			/*
1063			 * Determine the number of elements in the vector and
1064			 * finish up the format specifier.
1065			 */
1066			if (flags & SHORTINT) {
1067				switch (ch) {
1068				case 'c':
1069					vtype = V_SHORT;
1070					break;
1071				case 'p':
1072					vtype = V_PSHORT;
1073					break;
1074				default:
1075					vfmt[j++] = 'h';
1076					vtype = V_SHORT;
1077					break;
1078				}
1079				vcnt = 8;
1080			} else if (flags & LONGINT) {
1081				vcnt = 4;
1082				vtype = (ch == 'p') ? V_PINT : V_INT;
1083#ifdef V64TYPE
1084			} else if (flags & LLONGINT) {
1085				switch (ch) {
1086				case 'a':
1087				case 'A':
1088				case 'e':
1089				case 'E':
1090				case 'f':
1091				case 'g':
1092				case 'G':
1093					vcnt = 2;
1094					vtype = V_DOUBLE;
1095					break;
1096				case 'd':
1097				case 'i':
1098				case 'u':
1099				case 'o':
1100				case 'p':
1101				case 'x':
1102				case 'X':
1103					vfmt[j++] = 'l';
1104					vfmt[j++] = 'l';
1105					vcnt = 2;
1106					vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
1107					break;
1108				default:
1109					/*
1110					 * The default case should never
1111					 * happen.
1112					 */
1113				case 'c':
1114					vcnt = 16;
1115					vtype = V_CHAR;
1116				}
1117#endif /* V64TYPE */
1118			} else {
1119				switch (ch) {
1120				case 'a':
1121				case 'A':
1122				case 'e':
1123				case 'E':
1124				case 'f':
1125				case 'g':
1126				case 'G':
1127					vcnt = 4;
1128					vtype = V_FLOAT;
1129					break;
1130				default:
1131					/*
1132					 * The default case should never
1133					 * happen.
1134					 */
1135				case 'd':
1136				case 'i':
1137				case 'u':
1138				case 'o':
1139				case 'x':
1140				case 'X':
1141					vfmt[j++] = 'h';
1142					vfmt[j++] = 'h';
1143					/* drop through */
1144				case 'p':
1145				case 'c':
1146					vcnt = 16;
1147					vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
1148				}
1149			}
1150			vfmt[j++] = ch;
1151			vfmt[j++] = '\0';
1152
1153/* Get a vector element. */
1154#ifdef V64TYPE
1155#define VPRINT(type, ind, args...) do {					\
1156	switch (type) {							\
1157	case V_CHAR:							\
1158		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1159		break;							\
1160	case V_PCHAR:							\
1161		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1162		break;							\
1163	case V_SHORT:							\
1164		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1165		break;							\
1166	case V_PSHORT:							\
1167		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1168		break;							\
1169	case V_INT:							\
1170		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1171		break;							\
1172	case V_PINT:							\
1173		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1174		break;							\
1175	case V_LONGLONG:						\
1176		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
1177		break;							\
1178	case V_PLONGLONG:						\
1179		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
1180		break;							\
1181	case V_FLOAT:							\
1182		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1183		break;							\
1184	case V_DOUBLE:							\
1185		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
1186		break;							\
1187	}								\
1188	ret += vlen;							\
1189	PRINT(vstr, vlen);						\
1190	FLUSH();							\
1191	free(vstr);							\
1192} while (0)
1193#else /* !V64TYPE */
1194#define VPRINT(type, ind, args...) do {					\
1195	switch (type) {							\
1196	case V_CHAR:							\
1197		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
1198		break;							\
1199	case V_PCHAR:							\
1200		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
1201		break;							\
1202	case V_SHORT:							\
1203		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
1204		break;							\
1205	case V_PSHORT:							\
1206		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
1207		break;							\
1208	case V_INT:							\
1209		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
1210		break;							\
1211	case V_PINT:							\
1212		vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
1213		break;							\
1214	case V_FLOAT:							\
1215		vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
1216		break;							\
1217	}								\
1218	ret += vlen;							\
1219	PRINT(vstr, vlen);						\
1220	FLUSH();							\
1221	free(vstr);							\
1222} while (0)
1223#endif /* V64TYPE */
1224
1225			/* Actually print. */
1226			if (vwidth == 0) {
1227				if (vprec == 0) {
1228					/* First element. */
1229					VPRINT(vtype, 0);
1230					for (i = 1; i < vcnt; i++) {
1231						/* Separator. */
1232						if(vsep)
1233							PRINT(&vsep, 1);
1234
1235						/* Element. */
1236						VPRINT(vtype, i);
1237					}
1238				} else {
1239					/* First element. */
1240					VPRINT(vtype, 0, prec);
1241					for (i = 1; i < vcnt; i++) {
1242						/* Separator. */
1243						if(vsep)
1244							PRINT(&vsep, 1);
1245
1246						/* Element. */
1247						VPRINT(vtype, i, prec);
1248					}
1249				}
1250			} else {
1251				if (vprec == 0) {
1252					/* First element. */
1253					VPRINT(vtype, 0, width);
1254					for (i = 1; i < vcnt; i++) {
1255						/* Separator. */
1256						if(vsep)
1257							PRINT(&vsep, 1);
1258
1259						/* Element. */
1260						VPRINT(vtype, i, width);
1261					}
1262				} else {
1263					/* First element. */
1264					VPRINT(vtype, 0, width, prec);
1265					for (i = 1; i < vcnt; i++) {
1266						/* Separator. */
1267						if(vsep)
1268							PRINT(&vsep, 1);
1269
1270						/* Element. */
1271						VPRINT(vtype, i, width, prec);
1272					}
1273				}
1274			}
1275#undef VPRINT
1276
1277			if (vfmt != vfmt_buf)
1278				free(vfmt);
1279
1280			continue;
1281		}
1282#endif /* VECTORS */
1283		/*
1284		 * All reasonable formats wind up here.  At this point, `cp'
1285		 * points to a string which (if not flags&LADJUST) should be
1286		 * padded out to `width' places.  If flags&ZEROPAD, it should
1287		 * first be prefixed by any sign or other prefix; otherwise,
1288		 * it should be blank padded before the prefix is emitted.
1289		 * After any left-hand padding and prefixing, emit zeroes
1290		 * required by a decimal [diouxX] precision, then print the
1291		 * string proper, then emit zeroes required by any leftover
1292		 * floating precision; finally, if LADJUST, pad with blanks.
1293		 *
1294		 * Compute actual size, so we know how much to pad.
1295		 * size excludes decimal prec; realsz includes it.
1296		 */
1297		realsz = dprec > size ? dprec : size;
1298		if (sign)
1299			realsz++;
1300		if (ox[1])
1301			realsz += 2;
1302
1303		prsize = width > realsz ? width : realsz;
1304		if ((unsigned)ret + prsize > INT_MAX) {
1305			ret = EOF;
1306			goto error;
1307		}
1308
1309		/* right-adjusting blank padding */
1310		if ((flags & (LADJUST|ZEROPAD)) == 0)
1311			PAD(width - realsz, blanks);
1312
1313		/* prefix */
1314		if (sign)
1315			PRINT(&sign, 1);
1316
1317		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
1318			ox[0] = '0';
1319			PRINT(ox, 2);
1320		}
1321
1322		/* right-adjusting zero padding */
1323		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
1324			PAD(width - realsz, zeroes);
1325
1326		/* the string or number proper */
1327#ifndef NO_FLOATING_POINT
1328		if ((flags & FPT) == 0) {
1329#endif
1330			/* leading zeroes from decimal precision */
1331			PAD(dprec - size, zeroes);
1332			if (gs.grouping) {
1333				if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
1334					goto error;
1335			} else {
1336				PRINT(cp, size);
1337			}
1338#ifndef NO_FLOATING_POINT
1339		} else {	/* glue together f_p fragments */
1340			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
1341				if (expt <= 0) {
1342					PRINT(zeroes, 1);
1343					if (prec || flags & ALT)
1344						PRINT(decimal_point,decpt_len);
1345					PAD(-expt, zeroes);
1346					/* already handled initial 0's */
1347					prec += expt;
1348				} else {
1349					if (gs.grouping) {
1350						n = grouping_print(&gs, &io,
1351						    cp, dtoaend, loc);
1352						if (n < 0)
1353							goto error;
1354						cp += n;
1355					} else {
1356						PRINTANDPAD(cp, dtoaend,
1357						    expt, zeroes);
1358						cp += expt;
1359					}
1360					if (prec || flags & ALT)
1361						PRINT(decimal_point,decpt_len);
1362				}
1363				PRINTANDPAD(cp, dtoaend, prec, zeroes);
1364			} else {	/* %[eE] or sufficiently long %[gG] */
1365				if (prec > 1 || flags & ALT) {
1366					PRINT(cp++, 1);
1367					PRINT(decimal_point, decpt_len);
1368					PRINT(cp, ndig-1);
1369					PAD(prec - ndig, zeroes);
1370				} else	/* XeYYY */
1371					PRINT(cp, 1);
1372				PRINT(expstr, expsize);
1373			}
1374		}
1375#endif
1376		/* left-adjusting padding (always blank) */
1377		if (flags & LADJUST)
1378			PAD(width - realsz, blanks);
1379
1380		/* finally, adjust ret */
1381		ret += prsize;
1382
1383		FLUSH();	/* copy out the I/O vectors */
1384	}
1385done:
1386	FLUSH();
1387error:
1388	va_end(orgap);
1389#ifndef NO_FLOATING_POINT
1390	if (dtoaresult != NULL)
1391		freedtoa(dtoaresult);
1392#endif
1393	if (convbuf != NULL)
1394		free(convbuf);
1395	if (__sferror(fp))
1396		ret = EOF;
1397	if ((argtable != NULL) && (argtable != statargtable))
1398		free (argtable);
1399	return (ret);
1400	/* NOTREACHED */
1401}
1402
1403