vfprintf.c revision 187369
1219182Sglebius/*-
2219182Sglebius * Copyright (c) 1990, 1993
3219182Sglebius *	The Regents of the University of California.  All rights reserved.
4219182Sglebius *
5219182Sglebius * This code is derived from software contributed to Berkeley by
6219182Sglebius * Chris Torek.
7219182Sglebius *
8219182Sglebius * Redistribution and use in source and binary forms, with or without
9219182Sglebius * modification, are permitted provided that the following conditions
10219182Sglebius * are met:
11219182Sglebius * 1. Redistributions of source code must retain the above copyright
12219182Sglebius *    notice, this list of conditions and the following disclaimer.
13219182Sglebius * 2. Redistributions in binary form must reproduce the above copyright
14219182Sglebius *    notice, this list of conditions and the following disclaimer in the
15219182Sglebius *    documentation and/or other materials provided with the distribution.
16219182Sglebius * 4. Neither the name of the University nor the names of its contributors
17219182Sglebius *    may be used to endorse or promote products derived from this software
18219182Sglebius *    without specific prior written permission.
19219182Sglebius *
20219182Sglebius * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21219182Sglebius * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22219182Sglebius * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23219182Sglebius * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24219182Sglebius * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25219182Sglebius * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26219182Sglebius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27219182Sglebius * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28219182Sglebius * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29219182Sglebius * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30219182Sglebius * SUCH DAMAGE.
31219182Sglebius */
32219182Sglebius
33219182Sglebius#if defined(LIBC_SCCS) && !defined(lint)
34219182Sglebiusstatic char sccsid[] = "@(#)vfprintf.c	8.1 (Berkeley) 6/4/93";
35219182Sglebius#endif /* LIBC_SCCS and not lint */
36219182Sglebius#include <sys/cdefs.h>
37219182Sglebius__FBSDID("$FreeBSD: head/lib/libc/stdio/vfprintf.c 187369 2009-01-17 18:57:12Z das $");
38219182Sglebius
39219182Sglebius/*
40219182Sglebius * Actual printf innards.
41219182Sglebius *
42219182Sglebius * This code is large and complicated...
43219182Sglebius */
44219182Sglebius
45219182Sglebius#include "namespace.h"
46219182Sglebius#include <sys/types.h>
47219182Sglebius
48219182Sglebius#include <ctype.h>
49219182Sglebius#include <limits.h>
50219182Sglebius#include <locale.h>
51219182Sglebius#include <stddef.h>
52219182Sglebius#include <stdint.h>
53219182Sglebius#include <stdio.h>
54219182Sglebius#include <stdlib.h>
55219182Sglebius#include <string.h>
56219182Sglebius#include <wchar.h>
57219182Sglebius#include <printf.h>
58219182Sglebius
59219182Sglebius#include <stdarg.h>
60219182Sglebius#include "un-namespace.h"
61219182Sglebius
62219182Sglebius#include "libc_private.h"
63219182Sglebius#include "local.h"
64219182Sglebius#include "fvwrite.h"
65219182Sglebius#include "printflocal.h"
66219182Sglebius
67219182Sglebiusstatic int	__sprint(FILE *, struct __suio *);
68219182Sglebiusstatic int	__sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
69219182Sglebius	__noinline;
70219182Sglebiusstatic char	*__wcsconv(wchar_t *, int);
71219182Sglebius
72219182Sglebius#define	CHAR	char
73219182Sglebius#include "printfcommon.h"
74219182Sglebius
75219182Sglebius/*
76219182Sglebius * Flush out all the vectors defined by the given uio,
77219182Sglebius * then reset it so that it can be reused.
78219182Sglebius */
79219182Sglebiusstatic int
80219182Sglebius__sprint(FILE *fp, struct __suio *uio)
81219182Sglebius{
82219182Sglebius	int err;
83219182Sglebius
84219182Sglebius	if (uio->uio_resid == 0) {
85219182Sglebius		uio->uio_iovcnt = 0;
86219182Sglebius		return (0);
87219182Sglebius	}
88219182Sglebius	err = __sfvwrite(fp, uio);
89219182Sglebius	uio->uio_resid = 0;
90219182Sglebius	uio->uio_iovcnt = 0;
91219182Sglebius	return (err);
92219182Sglebius}
93219182Sglebius
94219182Sglebius/*
95219182Sglebius * Helper function for `fprintf to unbuffered unix file': creates a
96219182Sglebius * temporary buffer.  We only work on write-only files; this avoids
97219182Sglebius * worries about ungetc buffers and so forth.
98219182Sglebius */
99219182Sglebiusstatic int
100219182Sglebius__sbprintf(FILE *fp, const char *fmt, va_list ap)
101219182Sglebius{
102219182Sglebius	int ret;
103219182Sglebius	FILE fake;
104219182Sglebius	unsigned char buf[BUFSIZ];
105219182Sglebius
106219182Sglebius	/* XXX This is probably not needed. */
107219182Sglebius	if (prepwrite(fp) != 0)
108219182Sglebius		return (EOF);
109219182Sglebius
110219182Sglebius	/* copy the important variables */
111219182Sglebius	fake._flags = fp->_flags & ~__SNBF;
112219182Sglebius	fake._file = fp->_file;
113219182Sglebius	fake._cookie = fp->_cookie;
114219182Sglebius	fake._write = fp->_write;
115219182Sglebius	fake._orientation = fp->_orientation;
116219182Sglebius	fake._mbstate = fp->_mbstate;
117219182Sglebius
118219182Sglebius	/* set up the buffer */
119219182Sglebius	fake._bf._base = fake._p = buf;
120219182Sglebius	fake._bf._size = fake._w = sizeof(buf);
121219182Sglebius	fake._lbfsize = 0;	/* not actually used, but Just In Case */
122219182Sglebius
123219182Sglebius	/* do the work, then copy any error status */
124219182Sglebius	ret = __vfprintf(&fake, fmt, ap);
125219182Sglebius	if (ret >= 0 && __fflush(&fake))
126219182Sglebius		ret = EOF;
127219182Sglebius	if (fake._flags & __SERR)
128219182Sglebius		fp->_flags |= __SERR;
129219182Sglebius	return (ret);
130219182Sglebius}
131219182Sglebius
132219182Sglebius/*
133219182Sglebius * Convert a wide character string argument for the %ls format to a multibyte
134219182Sglebius * string representation. If not -1, prec specifies the maximum number of
135219182Sglebius * bytes to output, and also means that we can't assume that the wide char.
136219182Sglebius * string ends is null-terminated.
137219182Sglebius */
138219182Sglebiusstatic char *
139219182Sglebius__wcsconv(wchar_t *wcsarg, int prec)
140219182Sglebius{
141219182Sglebius	static const mbstate_t initial;
142219182Sglebius	mbstate_t mbs;
143219182Sglebius	char buf[MB_LEN_MAX];
144219182Sglebius	wchar_t *p;
145219182Sglebius	char *convbuf;
146219182Sglebius	size_t clen, nbytes;
147219182Sglebius
148219182Sglebius	/* Allocate space for the maximum number of bytes we could output. */
149219182Sglebius	if (prec < 0) {
150219182Sglebius		p = wcsarg;
151219182Sglebius		mbs = initial;
152219182Sglebius		nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
153219182Sglebius		if (nbytes == (size_t)-1)
154219182Sglebius			return (NULL);
155219182Sglebius	} else {
156219182Sglebius		/*
157219182Sglebius		 * Optimisation: if the output precision is small enough,
158219182Sglebius		 * just allocate enough memory for the maximum instead of
159219182Sglebius		 * scanning the string.
160219182Sglebius		 */
161219182Sglebius		if (prec < 128)
162219182Sglebius			nbytes = prec;
163219182Sglebius		else {
164219182Sglebius			nbytes = 0;
165219182Sglebius			p = wcsarg;
166219182Sglebius			mbs = initial;
167219182Sglebius			for (;;) {
168219182Sglebius				clen = wcrtomb(buf, *p++, &mbs);
169219182Sglebius				if (clen == 0 || clen == (size_t)-1 ||
170219182Sglebius				    nbytes + clen > prec)
171219182Sglebius					break;
172219182Sglebius				nbytes += clen;
173219182Sglebius			}
174219182Sglebius		}
175219182Sglebius	}
176219182Sglebius	if ((convbuf = malloc(nbytes + 1)) == NULL)
177219182Sglebius		return (NULL);
178219182Sglebius
179219182Sglebius	/* Fill the output buffer. */
180219182Sglebius	p = wcsarg;
181219182Sglebius	mbs = initial;
182219182Sglebius	if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
183219182Sglebius	    nbytes, &mbs)) == (size_t)-1) {
184219182Sglebius		free(convbuf);
185219182Sglebius		return (NULL);
186219182Sglebius	}
187219182Sglebius	convbuf[nbytes] = '\0';
188219182Sglebius	return (convbuf);
189219182Sglebius}
190219182Sglebius
191219182Sglebius/*
192219182Sglebius * MT-safe version
193219182Sglebius */
194219182Sglebiusint
195219182Sglebiusvfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
196219182Sglebius
197219182Sglebius{
198219182Sglebius	int ret;
199219182Sglebius
200219182Sglebius	FLOCKFILE(fp);
201219182Sglebius	/* optimise fprintf(stderr) (and other unbuffered Unix files) */
202219182Sglebius	if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
203219182Sglebius	    fp->_file >= 0)
204219182Sglebius		ret = __sbprintf(fp, fmt0, ap);
205219182Sglebius	else
206219182Sglebius		ret = __vfprintf(fp, fmt0, ap);
207219182Sglebius	FUNLOCKFILE(fp);
208219182Sglebius	return (ret);
209219182Sglebius}
210219182Sglebius
211219182Sglebius/*
212219182Sglebius * The size of the buffer we use as scratch space for integer
213219182Sglebius * conversions, among other things.  Technically, we would need the
214219182Sglebius * most space for base 10 conversions with thousands' grouping
215219182Sglebius * characters between each pair of digits.  100 bytes is a
216219182Sglebius * conservative overestimate even for a 128-bit uintmax_t.
217219182Sglebius */
218219182Sglebius#define	BUF	100
219219182Sglebius
220219182Sglebius/*
221219182Sglebius * Non-MT-safe version
222219182Sglebius */
223219182Sglebiusint
224219182Sglebius__vfprintf(FILE *fp, const char *fmt0, va_list ap)
225238295Smelifaro{
226219182Sglebius	char *fmt;		/* format string */
227219182Sglebius	int ch;			/* character from fmt */
228219182Sglebius	int n, n2;		/* handy integer (short term usage) */
229219182Sglebius	char *cp;		/* handy char pointer (short term usage) */
230219182Sglebius	int flags;		/* flags as above */
231219182Sglebius	int ret;		/* return value accumulator */
232219182Sglebius	int width;		/* width from format (%8d), or 0 */
233219182Sglebius	int prec;		/* precision from format; <0 for N/A */
234219182Sglebius	char sign;		/* sign prefix (' ', '+', '-', or \0) */
235219182Sglebius	char thousands_sep;	/* locale specific thousands separator */
236219182Sglebius	const char *grouping;	/* locale specific numeric grouping rules */
237219182Sglebius
238219182Sglebius#ifndef NO_FLOATING_POINT
239219182Sglebius	/*
240219182Sglebius	 * We can decompose the printed representation of floating
241219182Sglebius	 * point numbers into several parts, some of which may be empty:
242219182Sglebius	 *
243219182Sglebius	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
244219182Sglebius	 *    A       B     ---C---      D       E   F
245219182Sglebius	 *
246219182Sglebius	 * A:	'sign' holds this value if present; '\0' otherwise
247219182Sglebius	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
248219182Sglebius	 * C:	cp points to the string MMMNNN.  Leading and trailing
249219182Sglebius	 *	zeros are not in the string and must be added.
250219182Sglebius	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
251219182Sglebius	 * F:	at least two digits for decimal, at least one digit for hex
252219182Sglebius	 */
253219182Sglebius	char *decimal_point;	/* locale specific decimal point */
254219182Sglebius	int signflag;		/* true if float is negative */
255219182Sglebius	union {			/* floating point arguments %[aAeEfFgG] */
256219182Sglebius		double dbl;
257219182Sglebius		long double ldbl;
258219182Sglebius	} fparg;
259219229Sbz	int expt;		/* integer value of exponent */
260219182Sglebius	char expchar;		/* exponent character: [eEpP\0] */
261219229Sbz	char *dtoaend;		/* pointer to end of converted digits */
262219182Sglebius	int expsize;		/* character count for expstr */
263219182Sglebius	int lead;		/* sig figs before decimal or group sep */
264219182Sglebius	int ndig;		/* actual number of digits returned by dtoa */
265219182Sglebius	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
266219182Sglebius	char *dtoaresult;	/* buffer allocated by dtoa */
267219182Sglebius	int nseps;		/* number of group separators with ' */
268219182Sglebius	int nrepeats;		/* number of repeats of the last group */
269219182Sglebius#endif
270219182Sglebius	u_long	ulval;		/* integer arguments %[diouxX] */
271219182Sglebius	uintmax_t ujval;	/* %j, %ll, %q, %t, %z integers */
272219182Sglebius	int base;		/* base for [diouxX] conversion */
273219182Sglebius	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
274219182Sglebius	int realsz;		/* field size expanded by dprec, sign, etc */
275219182Sglebius	int size;		/* size of converted field or string */
276219182Sglebius	int prsize;             /* max size of printed field */
277219182Sglebius	const char *xdigs;     	/* digits for %[xX] conversion */
278219182Sglebius	struct io_state io;	/* I/O buffering state */
279219182Sglebius	char buf[BUF];		/* buffer with space for digits of uintmax_t */
280219182Sglebius	char ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
281219182Sglebius	union arg *argtable;    /* args, built due to positional arg */
282219182Sglebius	union arg statargtable [STATIC_ARG_TBL_SIZE];
283219182Sglebius	int nextarg;            /* 1-based argument index */
284219182Sglebius	va_list orgap;          /* original argument pointer */
285219182Sglebius	char *convbuf;		/* wide to multibyte conversion result */
286219182Sglebius
287219182Sglebius	static const char xdigs_lower[16] = "0123456789abcdef";
288219182Sglebius	static const char xdigs_upper[16] = "0123456789ABCDEF";
289219182Sglebius
290219182Sglebius	/* BEWARE, these `goto error' on error. */
291219182Sglebius#define	PRINT(ptr, len) { \
292219182Sglebius	if (io_print(&io, (ptr), (len)))	\
293219182Sglebius		goto error; \
294219182Sglebius}
295219182Sglebius#define	PAD(howmany, with) { \
296219182Sglebius	if (io_pad(&io, (howmany), (with))) \
297219182Sglebius		goto error; \
298219182Sglebius}
299219182Sglebius#define	PRINTANDPAD(p, ep, len, with) {	\
300219182Sglebius	if (io_printandpad(&io, (p), (ep), (len), (with))) \
301219182Sglebius		goto error; \
302219182Sglebius}
303219182Sglebius#define	FLUSH() { \
304219182Sglebius	if (io_flush(&io)) \
305219182Sglebius		goto error; \
306219182Sglebius}
307219182Sglebius
308219182Sglebius	/*
309219182Sglebius	 * Get the argument indexed by nextarg.   If the argument table is
310219182Sglebius	 * built, use it to get the argument.  If its not, get the next
311219182Sglebius	 * argument (and arguments must be gotten sequentially).
312219182Sglebius	 */
313219182Sglebius#define GETARG(type) \
314219182Sglebius	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
315219182Sglebius	    (nextarg++, va_arg(ap, type)))
316219182Sglebius
317219182Sglebius	/*
318219182Sglebius	 * To extend shorts properly, we need both signed and unsigned
319219182Sglebius	 * argument extraction methods.
320219182Sglebius	 */
321219182Sglebius#define	SARG() \
322219182Sglebius	(flags&LONGINT ? GETARG(long) : \
323219182Sglebius	    flags&SHORTINT ? (long)(short)GETARG(int) : \
324219182Sglebius	    flags&CHARINT ? (long)(signed char)GETARG(int) : \
325219182Sglebius	    (long)GETARG(int))
326219182Sglebius#define	UARG() \
327219182Sglebius	(flags&LONGINT ? GETARG(u_long) : \
328219182Sglebius	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
329219182Sglebius	    flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
330219182Sglebius	    (u_long)GETARG(u_int))
331219182Sglebius#define	INTMAX_SIZE	(INTMAXT|SIZET|PTRDIFFT|LLONGINT)
332219182Sglebius#define SJARG() \
333219182Sglebius	(flags&INTMAXT ? GETARG(intmax_t) : \
334219182Sglebius	    flags&SIZET ? (intmax_t)GETARG(size_t) : \
335219182Sglebius	    flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
336219182Sglebius	    (intmax_t)GETARG(long long))
337219182Sglebius#define	UJARG() \
338219182Sglebius	(flags&INTMAXT ? GETARG(uintmax_t) : \
339219182Sglebius	    flags&SIZET ? (uintmax_t)GETARG(size_t) : \
340219182Sglebius	    flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
341219182Sglebius	    (uintmax_t)GETARG(unsigned long long))
342219182Sglebius
343219182Sglebius	/*
344219182Sglebius	 * Get * arguments, including the form *nn$.  Preserve the nextarg
345219182Sglebius	 * that the argument can be gotten once the type is determined.
346219182Sglebius	 */
347219182Sglebius#define GETASTER(val) \
348219182Sglebius	n2 = 0; \
349219182Sglebius	cp = fmt; \
350219182Sglebius	while (is_digit(*cp)) { \
351219182Sglebius		n2 = 10 * n2 + to_digit(*cp); \
352219182Sglebius		cp++; \
353219182Sglebius	} \
354219182Sglebius	if (*cp == '$') { \
355219182Sglebius		int hold = nextarg; \
356219182Sglebius		if (argtable == NULL) { \
357219182Sglebius			argtable = statargtable; \
358219182Sglebius			if (__find_arguments (fmt0, orgap, &argtable)) { \
359219182Sglebius				ret = EOF; \
360219182Sglebius				goto error; \
361219182Sglebius			} \
362219182Sglebius		} \
363219182Sglebius		nextarg = n2; \
364219182Sglebius		val = GETARG (int); \
365219182Sglebius		nextarg = hold; \
366219182Sglebius		fmt = ++cp; \
367219182Sglebius	} else { \
368219182Sglebius		val = GETARG (int); \
369219182Sglebius	}
370219182Sglebius
371219182Sglebius	if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
372219182Sglebius		__use_xprintf = 1;
373219182Sglebius	if (__use_xprintf > 0)
374219182Sglebius		return (__xvprintf(fp, fmt0, ap));
375219182Sglebius
376219182Sglebius	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
377219182Sglebius	if (prepwrite(fp) != 0)
378219182Sglebius		return (EOF);
379219182Sglebius
380219182Sglebius	thousands_sep = '\0';
381219182Sglebius	grouping = NULL;
382219182Sglebius	convbuf = NULL;
383219182Sglebius	fmt = (char *)fmt0;
384219182Sglebius	argtable = NULL;
385219182Sglebius	nextarg = 1;
386219182Sglebius	va_copy(orgap, ap);
387219182Sglebius	io_init(&io, fp);
388219182Sglebius	ret = 0;
389219182Sglebius#ifndef NO_FLOATING_POINT
390219182Sglebius	dtoaresult = NULL;
391219182Sglebius	decimal_point = localeconv()->decimal_point;
392219182Sglebius#endif
393219182Sglebius
394219182Sglebius	/*
395219182Sglebius	 * Scan the format for conversions (`%' character).
396219182Sglebius	 */
397219182Sglebius	for (;;) {
398219182Sglebius		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
399219182Sglebius			/* void */;
400219182Sglebius		if ((n = fmt - cp) != 0) {
401219182Sglebius			if ((unsigned)ret + n > INT_MAX) {
402219182Sglebius				ret = EOF;
403219182Sglebius				goto error;
404219182Sglebius			}
405219182Sglebius			PRINT(cp, n);
406219182Sglebius			ret += n;
407219182Sglebius		}
408219182Sglebius		if (ch == '\0')
409219182Sglebius			goto done;
410219182Sglebius		fmt++;		/* skip over '%' */
411219182Sglebius
412219182Sglebius		flags = 0;
413219182Sglebius		dprec = 0;
414219182Sglebius		width = 0;
415219182Sglebius		prec = -1;
416219182Sglebius		sign = '\0';
417219182Sglebius		ox[1] = '\0';
418219182Sglebius
419219182Sglebiusrflag:		ch = *fmt++;
420219182Sglebiusreswitch:	switch (ch) {
421238295Smelifaro		case ' ':
422219182Sglebius			/*-
423219182Sglebius			 * ``If the space and + flags both appear, the space
424238295Smelifaro			 * flag will be ignored.''
425238295Smelifaro			 *	-- ANSI X3J11
426238295Smelifaro			 */
427219182Sglebius			if (!sign)
428219182Sglebius				sign = ' ';
429219182Sglebius			goto rflag;
430219182Sglebius		case '#':
431219182Sglebius			flags |= ALT;
432219182Sglebius			goto rflag;
433219182Sglebius		case '*':
434219182Sglebius			/*-
435219182Sglebius			 * ``A negative field width argument is taken as a
436219182Sglebius			 * - flag followed by a positive field width.''
437219182Sglebius			 *	-- ANSI X3J11
438219182Sglebius			 * They don't exclude field widths read from args.
439219182Sglebius			 */
440219182Sglebius			GETASTER (width);
441219182Sglebius			if (width >= 0)
442219182Sglebius				goto rflag;
443219182Sglebius			width = -width;
444219182Sglebius			/* FALLTHROUGH */
445219182Sglebius		case '-':
446219182Sglebius			flags |= LADJUST;
447219182Sglebius			goto rflag;
448219182Sglebius		case '+':
449219182Sglebius			sign = '+';
450219182Sglebius			goto rflag;
451219182Sglebius		case '\'':
452219182Sglebius			flags |= GROUPING;
453219182Sglebius			thousands_sep = *(localeconv()->thousands_sep);
454219182Sglebius			grouping = localeconv()->grouping;
455219182Sglebius			goto rflag;
456219182Sglebius		case '.':
457219182Sglebius			if ((ch = *fmt++) == '*') {
458219182Sglebius				GETASTER (prec);
459219182Sglebius				goto rflag;
460219182Sglebius			}
461219182Sglebius			prec = 0;
462219182Sglebius			while (is_digit(ch)) {
463219182Sglebius				prec = 10 * prec + to_digit(ch);
464219182Sglebius				ch = *fmt++;
465219182Sglebius			}
466219182Sglebius			goto reswitch;
467219182Sglebius		case '0':
468219182Sglebius			/*-
469219182Sglebius			 * ``Note that 0 is taken as a flag, not as the
470219182Sglebius			 * beginning of a field width.''
471219182Sglebius			 *	-- ANSI X3J11
472219182Sglebius			 */
473219182Sglebius			flags |= ZEROPAD;
474219182Sglebius			goto rflag;
475219182Sglebius		case '1': case '2': case '3': case '4':
476219182Sglebius		case '5': case '6': case '7': case '8': case '9':
477219182Sglebius			n = 0;
478219182Sglebius			do {
479219182Sglebius				n = 10 * n + to_digit(ch);
480219182Sglebius				ch = *fmt++;
481219182Sglebius			} while (is_digit(ch));
482219182Sglebius			if (ch == '$') {
483				nextarg = n;
484				if (argtable == NULL) {
485					argtable = statargtable;
486					if (__find_arguments (fmt0, orgap,
487							      &argtable)) {
488						ret = EOF;
489						goto error;
490					}
491				}
492				goto rflag;
493			}
494			width = n;
495			goto reswitch;
496#ifndef NO_FLOATING_POINT
497		case 'L':
498			flags |= LONGDBL;
499			goto rflag;
500#endif
501		case 'h':
502			if (flags & SHORTINT) {
503				flags &= ~SHORTINT;
504				flags |= CHARINT;
505			} else
506				flags |= SHORTINT;
507			goto rflag;
508		case 'j':
509			flags |= INTMAXT;
510			goto rflag;
511		case 'l':
512			if (flags & LONGINT) {
513				flags &= ~LONGINT;
514				flags |= LLONGINT;
515			} else
516				flags |= LONGINT;
517			goto rflag;
518		case 'q':
519			flags |= LLONGINT;	/* not necessarily */
520			goto rflag;
521		case 't':
522			flags |= PTRDIFFT;
523			goto rflag;
524		case 'z':
525			flags |= SIZET;
526			goto rflag;
527		case 'C':
528			flags |= LONGINT;
529			/*FALLTHROUGH*/
530		case 'c':
531			if (flags & LONGINT) {
532				static const mbstate_t initial;
533				mbstate_t mbs;
534				size_t mbseqlen;
535
536				mbs = initial;
537				mbseqlen = wcrtomb(cp = buf,
538				    (wchar_t)GETARG(wint_t), &mbs);
539				if (mbseqlen == (size_t)-1) {
540					fp->_flags |= __SERR;
541					goto error;
542				}
543				size = (int)mbseqlen;
544			} else {
545				*(cp = buf) = GETARG(int);
546				size = 1;
547			}
548			sign = '\0';
549			break;
550		case 'D':
551			flags |= LONGINT;
552			/*FALLTHROUGH*/
553		case 'd':
554		case 'i':
555			if (flags & INTMAX_SIZE) {
556				ujval = SJARG();
557				if ((intmax_t)ujval < 0) {
558					ujval = -ujval;
559					sign = '-';
560				}
561			} else {
562				ulval = SARG();
563				if ((long)ulval < 0) {
564					ulval = -ulval;
565					sign = '-';
566				}
567			}
568			base = 10;
569			goto number;
570#ifndef NO_FLOATING_POINT
571		case 'a':
572		case 'A':
573			if (ch == 'a') {
574				ox[1] = 'x';
575				xdigs = xdigs_lower;
576				expchar = 'p';
577			} else {
578				ox[1] = 'X';
579				xdigs = xdigs_upper;
580				expchar = 'P';
581			}
582			if (prec >= 0)
583				prec++;
584			if (dtoaresult != NULL)
585				freedtoa(dtoaresult);
586			if (flags & LONGDBL) {
587				fparg.ldbl = GETARG(long double);
588				dtoaresult = cp =
589				    __hldtoa(fparg.ldbl, xdigs, prec,
590				    &expt, &signflag, &dtoaend);
591			} else {
592				fparg.dbl = GETARG(double);
593				dtoaresult = cp =
594				    __hdtoa(fparg.dbl, xdigs, prec,
595				    &expt, &signflag, &dtoaend);
596			}
597			if (prec < 0)
598				prec = dtoaend - cp;
599			if (expt == INT_MAX)
600				ox[1] = '\0';
601			goto fp_common;
602		case 'e':
603		case 'E':
604			expchar = ch;
605			if (prec < 0)	/* account for digit before decpt */
606				prec = DEFPREC + 1;
607			else
608				prec++;
609			goto fp_begin;
610		case 'f':
611		case 'F':
612			expchar = '\0';
613			goto fp_begin;
614		case 'g':
615		case 'G':
616			expchar = ch - ('g' - 'e');
617			if (prec == 0)
618				prec = 1;
619fp_begin:
620			if (prec < 0)
621				prec = DEFPREC;
622			if (dtoaresult != NULL)
623				freedtoa(dtoaresult);
624			if (flags & LONGDBL) {
625				fparg.ldbl = GETARG(long double);
626				dtoaresult = cp =
627				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
628				    &expt, &signflag, &dtoaend);
629			} else {
630				fparg.dbl = GETARG(double);
631				dtoaresult = cp =
632				    dtoa(fparg.dbl, expchar ? 2 : 3, prec,
633				    &expt, &signflag, &dtoaend);
634				if (expt == 9999)
635					expt = INT_MAX;
636			}
637fp_common:
638			if (signflag)
639				sign = '-';
640			if (expt == INT_MAX) {	/* inf or nan */
641				if (*cp == 'N') {
642					cp = (ch >= 'a') ? "nan" : "NAN";
643					sign = '\0';
644				} else
645					cp = (ch >= 'a') ? "inf" : "INF";
646				size = 3;
647				flags &= ~ZEROPAD;
648				break;
649			}
650			flags |= FPT;
651			ndig = dtoaend - cp;
652			if (ch == 'g' || ch == 'G') {
653				if (expt > -4 && expt <= prec) {
654					/* Make %[gG] smell like %[fF] */
655					expchar = '\0';
656					if (flags & ALT)
657						prec -= expt;
658					else
659						prec = ndig - expt;
660					if (prec < 0)
661						prec = 0;
662				} else {
663					/*
664					 * Make %[gG] smell like %[eE], but
665					 * trim trailing zeroes if no # flag.
666					 */
667					if (!(flags & ALT))
668						prec = ndig;
669				}
670			}
671			if (expchar) {
672				expsize = exponent(expstr, expt - 1, expchar);
673				size = expsize + prec;
674				if (prec > 1 || flags & ALT)
675					++size;
676			} else {
677				/* space for digits before decimal point */
678				if (expt > 0)
679					size = expt;
680				else	/* "0" */
681					size = 1;
682				/* space for decimal pt and following digits */
683				if (prec || flags & ALT)
684					size += prec + 1;
685				if (grouping && expt > 0) {
686					/* space for thousands' grouping */
687					nseps = nrepeats = 0;
688					lead = expt;
689					while (*grouping != CHAR_MAX) {
690						if (lead <= *grouping)
691							break;
692						lead -= *grouping;
693						if (*(grouping+1)) {
694							nseps++;
695							grouping++;
696						} else
697							nrepeats++;
698					}
699					size += nseps + nrepeats;
700				} else
701					lead = expt;
702			}
703			break;
704#endif /* !NO_FLOATING_POINT */
705		case 'n':
706			/*
707			 * Assignment-like behavior is specified if the
708			 * value overflows or is otherwise unrepresentable.
709			 * C99 says to use `signed char' for %hhn conversions.
710			 */
711			if (flags & LLONGINT)
712				*GETARG(long long *) = ret;
713			else if (flags & SIZET)
714				*GETARG(ssize_t *) = (ssize_t)ret;
715			else if (flags & PTRDIFFT)
716				*GETARG(ptrdiff_t *) = ret;
717			else if (flags & INTMAXT)
718				*GETARG(intmax_t *) = ret;
719			else if (flags & LONGINT)
720				*GETARG(long *) = ret;
721			else if (flags & SHORTINT)
722				*GETARG(short *) = ret;
723			else if (flags & CHARINT)
724				*GETARG(signed char *) = ret;
725			else
726				*GETARG(int *) = ret;
727			continue;	/* no output */
728		case 'O':
729			flags |= LONGINT;
730			/*FALLTHROUGH*/
731		case 'o':
732			if (flags & INTMAX_SIZE)
733				ujval = UJARG();
734			else
735				ulval = UARG();
736			base = 8;
737			goto nosign;
738		case 'p':
739			/*-
740			 * ``The argument shall be a pointer to void.  The
741			 * value of the pointer is converted to a sequence
742			 * of printable characters, in an implementation-
743			 * defined manner.''
744			 *	-- ANSI X3J11
745			 */
746			ujval = (uintmax_t)(uintptr_t)GETARG(void *);
747			base = 16;
748			xdigs = xdigs_lower;
749			flags = flags | INTMAXT;
750			ox[1] = 'x';
751			goto nosign;
752		case 'S':
753			flags |= LONGINT;
754			/*FALLTHROUGH*/
755		case 's':
756			if (flags & LONGINT) {
757				wchar_t *wcp;
758
759				if (convbuf != NULL)
760					free(convbuf);
761				if ((wcp = GETARG(wchar_t *)) == NULL)
762					cp = "(null)";
763				else {
764					convbuf = __wcsconv(wcp, prec);
765					if (convbuf == NULL) {
766						fp->_flags |= __SERR;
767						goto error;
768					}
769					cp = convbuf;
770				}
771			} else if ((cp = GETARG(char *)) == NULL)
772				cp = "(null)";
773			if (prec >= 0) {
774				/*
775				 * can't use strlen; can only look for the
776				 * NUL in the first `prec' characters, and
777				 * strlen() will go further.
778				 */
779				char *p = memchr(cp, 0, (size_t)prec);
780
781				if (p != NULL) {
782					size = p - cp;
783					if (size > prec)
784						size = prec;
785				} else
786					size = prec;
787			} else
788				size = strlen(cp);
789			sign = '\0';
790			break;
791		case 'U':
792			flags |= LONGINT;
793			/*FALLTHROUGH*/
794		case 'u':
795			if (flags & INTMAX_SIZE)
796				ujval = UJARG();
797			else
798				ulval = UARG();
799			base = 10;
800			goto nosign;
801		case 'X':
802			xdigs = xdigs_upper;
803			goto hex;
804		case 'x':
805			xdigs = xdigs_lower;
806hex:
807			if (flags & INTMAX_SIZE)
808				ujval = UJARG();
809			else
810				ulval = UARG();
811			base = 16;
812			/* leading 0x/X only if non-zero */
813			if (flags & ALT &&
814			    (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
815				ox[1] = ch;
816
817			flags &= ~GROUPING;
818			/* unsigned conversions */
819nosign:			sign = '\0';
820			/*-
821			 * ``... diouXx conversions ... if a precision is
822			 * specified, the 0 flag will be ignored.''
823			 *	-- ANSI X3J11
824			 */
825number:			if ((dprec = prec) >= 0)
826				flags &= ~ZEROPAD;
827
828			/*-
829			 * ``The result of converting a zero value with an
830			 * explicit precision of zero is no characters.''
831			 *	-- ANSI X3J11
832			 *
833			 * ``The C Standard is clear enough as is.  The call
834			 * printf("%#.0o", 0) should print 0.''
835			 *	-- Defect Report #151
836			 */
837			cp = buf + BUF;
838			if (flags & INTMAX_SIZE) {
839				if (ujval != 0 || prec != 0 ||
840				    (flags & ALT && base == 8))
841					cp = __ujtoa(ujval, cp, base,
842					    flags & ALT, xdigs,
843					    flags & GROUPING, thousands_sep,
844					    grouping);
845			} else {
846				if (ulval != 0 || prec != 0 ||
847				    (flags & ALT && base == 8))
848					cp = __ultoa(ulval, cp, base,
849					    flags & ALT, xdigs,
850					    flags & GROUPING, thousands_sep,
851					    grouping);
852			}
853			size = buf + BUF - cp;
854			if (size > BUF)	/* should never happen */
855				abort();
856			break;
857		default:	/* "%?" prints ?, unless ? is NUL */
858			if (ch == '\0')
859				goto done;
860			/* pretend it was %c with argument ch */
861			cp = buf;
862			*cp = ch;
863			size = 1;
864			sign = '\0';
865			break;
866		}
867
868		/*
869		 * All reasonable formats wind up here.  At this point, `cp'
870		 * points to a string which (if not flags&LADJUST) should be
871		 * padded out to `width' places.  If flags&ZEROPAD, it should
872		 * first be prefixed by any sign or other prefix; otherwise,
873		 * it should be blank padded before the prefix is emitted.
874		 * After any left-hand padding and prefixing, emit zeroes
875		 * required by a decimal [diouxX] precision, then print the
876		 * string proper, then emit zeroes required by any leftover
877		 * floating precision; finally, if LADJUST, pad with blanks.
878		 *
879		 * Compute actual size, so we know how much to pad.
880		 * size excludes decimal prec; realsz includes it.
881		 */
882		realsz = dprec > size ? dprec : size;
883		if (sign)
884			realsz++;
885		if (ox[1])
886			realsz += 2;
887
888		prsize = width > realsz ? width : realsz;
889		if ((unsigned)ret + prsize > INT_MAX) {
890			ret = EOF;
891			goto error;
892		}
893
894		/* right-adjusting blank padding */
895		if ((flags & (LADJUST|ZEROPAD)) == 0)
896			PAD(width - realsz, blanks);
897
898		/* prefix */
899		if (sign)
900			PRINT(&sign, 1);
901
902		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
903			ox[0] = '0';
904			PRINT(ox, 2);
905		}
906
907		/* right-adjusting zero padding */
908		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
909			PAD(width - realsz, zeroes);
910
911		/* leading zeroes from decimal precision */
912		PAD(dprec - size, zeroes);
913
914		/* the string or number proper */
915#ifndef NO_FLOATING_POINT
916		if ((flags & FPT) == 0) {
917			PRINT(cp, size);
918		} else {	/* glue together f_p fragments */
919			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
920				if (expt <= 0) {
921					PRINT(zeroes, 1);
922					if (prec || flags & ALT)
923						PRINT(decimal_point, 1);
924					PAD(-expt, zeroes);
925					/* already handled initial 0's */
926					prec += expt;
927				} else {
928					PRINTANDPAD(cp, dtoaend, lead, zeroes);
929					cp += lead;
930					if (grouping) {
931						while (nseps>0 || nrepeats>0) {
932							if (nrepeats > 0)
933								nrepeats--;
934							else {
935								grouping--;
936								nseps--;
937							}
938							PRINT(&thousands_sep,
939							    1);
940							PRINTANDPAD(cp,dtoaend,
941							    *grouping, zeroes);
942							cp += *grouping;
943						}
944						if (cp > dtoaend)
945							cp = dtoaend;
946					}
947					if (prec || flags & ALT)
948						PRINT(decimal_point,1);
949				}
950				PRINTANDPAD(cp, dtoaend, prec, zeroes);
951			} else {	/* %[eE] or sufficiently long %[gG] */
952				if (prec > 1 || flags & ALT) {
953					buf[0] = *cp++;
954					buf[1] = *decimal_point;
955					PRINT(buf, 2);
956					PRINT(cp, ndig-1);
957					PAD(prec - ndig, zeroes);
958				} else	/* XeYYY */
959					PRINT(cp, 1);
960				PRINT(expstr, expsize);
961			}
962		}
963#else
964		PRINT(cp, size);
965#endif
966		/* left-adjusting padding (always blank) */
967		if (flags & LADJUST)
968			PAD(width - realsz, blanks);
969
970		/* finally, adjust ret */
971		ret += prsize;
972
973		FLUSH();	/* copy out the I/O vectors */
974	}
975done:
976	FLUSH();
977error:
978	va_end(orgap);
979#ifndef NO_FLOATING_POINT
980	if (dtoaresult != NULL)
981		freedtoa(dtoaresult);
982#endif
983	if (convbuf != NULL)
984		free(convbuf);
985	if (__sferror(fp))
986		ret = EOF;
987	if ((argtable != NULL) && (argtable != statargtable))
988		free (argtable);
989	return (ret);
990	/* NOTREACHED */
991}
992
993