1#include "stdio_impl.h"
2#include <errno.h>
3#include <ctype.h>
4#include <limits.h>
5#include <string.h>
6#include <stdarg.h>
7#include <wchar.h>
8#include <inttypes.h>
9#include <math.h>
10#include <float.h>
11
12/* Some useful macros */
13
14#define MAX(a,b) ((a)>(b) ? (a) : (b))
15#define MIN(a,b) ((a)<(b) ? (a) : (b))
16
17/* Convenient bit representation for modifier flags, which all fall
18 * within 31 codepoints of the space character. */
19
20#define ALT_FORM   (1U<<'#'-' ')
21#define ZERO_PAD   (1U<<'0'-' ')
22#define LEFT_ADJ   (1U<<'-'-' ')
23#define PAD_POS    (1U<<' '-' ')
24#define MARK_POS   (1U<<'+'-' ')
25#define GROUPED    (1U<<'\''-' ')
26
27#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
28
29#if UINT_MAX == ULONG_MAX
30#define LONG_IS_INT
31#endif
32
33#if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX
34#define ODD_TYPES
35#endif
36
37/* State machine to accept length modifiers + conversion specifiers.
38 * Result is 0 on failure, or an argument type to pop on success. */
39
40enum {
41	BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
42	ZTPRE, JPRE,
43	STOP,
44	PTR, INT, UINT, ULLONG,
45#ifndef LONG_IS_INT
46	LONG, ULONG,
47#else
48#define LONG INT
49#define ULONG UINT
50#endif
51	SHORT, USHORT, CHAR, UCHAR,
52#ifdef ODD_TYPES
53	LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
54#else
55#define LLONG ULLONG
56#define SIZET ULONG
57#define IMAX LLONG
58#define UMAX ULLONG
59#define PDIFF LONG
60#define UIPTR ULONG
61#endif
62	DBL, LDBL,
63	NOARG,
64	MAXSTATE
65};
66
67#define S(x) [(x)-'A']
68
69static const unsigned char states[]['z'-'A'+1] = {
70	{ /* 0: bare types */
71		S('d') = INT, S('i') = INT,
72		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
73		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
74		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
75		S('c') = CHAR, S('C') = INT,
76		S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
77		S('m') = NOARG,
78		S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
79		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
80	}, { /* 1: l-prefixed */
81		S('d') = LONG, S('i') = LONG,
82		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
83		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
84		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
85		S('c') = INT, S('s') = PTR, S('n') = PTR,
86		S('l') = LLPRE,
87	}, { /* 2: ll-prefixed */
88		S('d') = LLONG, S('i') = LLONG,
89		S('o') = ULLONG, S('u') = ULLONG,
90		S('x') = ULLONG, S('X') = ULLONG,
91		S('n') = PTR,
92	}, { /* 3: h-prefixed */
93		S('d') = SHORT, S('i') = SHORT,
94		S('o') = USHORT, S('u') = USHORT,
95		S('x') = USHORT, S('X') = USHORT,
96		S('n') = PTR,
97		S('h') = HHPRE,
98	}, { /* 4: hh-prefixed */
99		S('d') = CHAR, S('i') = CHAR,
100		S('o') = UCHAR, S('u') = UCHAR,
101		S('x') = UCHAR, S('X') = UCHAR,
102		S('n') = PTR,
103	}, { /* 5: L-prefixed */
104		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
105		S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
106		S('n') = PTR,
107	}, { /* 6: z- or t-prefixed (assumed to be same size) */
108		S('d') = PDIFF, S('i') = PDIFF,
109		S('o') = SIZET, S('u') = SIZET,
110		S('x') = SIZET, S('X') = SIZET,
111		S('n') = PTR,
112	}, { /* 7: j-prefixed */
113		S('d') = IMAX, S('i') = IMAX,
114		S('o') = UMAX, S('u') = UMAX,
115		S('x') = UMAX, S('X') = UMAX,
116		S('n') = PTR,
117	}
118};
119
120#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
121
122union arg
123{
124	uintmax_t i;
125	long double f;
126	void *p;
127};
128
129static void pop_arg(union arg *arg, int type, va_list *ap)
130{
131	/* Give the compiler a hint for optimizing the switch. */
132	if ((unsigned)type > MAXSTATE) return;
133	switch (type) {
134	       case PTR:	arg->p = va_arg(*ap, void *);
135	break; case INT:	arg->i = va_arg(*ap, int);
136	break; case UINT:	arg->i = va_arg(*ap, unsigned int);
137#ifndef LONG_IS_INT
138	break; case LONG:	arg->i = va_arg(*ap, long);
139	break; case ULONG:	arg->i = va_arg(*ap, unsigned long);
140#endif
141	break; case ULLONG:	arg->i = va_arg(*ap, unsigned long long);
142	break; case SHORT:	arg->i = (short)va_arg(*ap, int);
143	break; case USHORT:	arg->i = (unsigned short)va_arg(*ap, int);
144	break; case CHAR:	arg->i = (signed char)va_arg(*ap, int);
145	break; case UCHAR:	arg->i = (unsigned char)va_arg(*ap, int);
146#ifdef ODD_TYPES
147	break; case LLONG:	arg->i = va_arg(*ap, long long);
148	break; case SIZET:	arg->i = va_arg(*ap, size_t);
149	break; case IMAX:	arg->i = va_arg(*ap, intmax_t);
150	break; case UMAX:	arg->i = va_arg(*ap, uintmax_t);
151	break; case PDIFF:	arg->i = va_arg(*ap, ptrdiff_t);
152	break; case UIPTR:	arg->i = (uintptr_t)va_arg(*ap, void *);
153#endif
154	break; case DBL:	arg->f = va_arg(*ap, double);
155	break; case LDBL:	arg->f = va_arg(*ap, long double);
156	}
157}
158
159static void out(FILE *f, const char *s, size_t l)
160{
161	if (!(f->flags & F_ERR)) __fwritex((void *)s, l, f);
162}
163
164static void pad(FILE *f, char c, int w, int l, int fl)
165{
166	char pad[256];
167	if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
168	l = w - l;
169	memset(pad, c, l>sizeof pad ? sizeof pad : l);
170	for (; l >= sizeof pad; l -= sizeof pad)
171		out(f, pad, sizeof pad);
172	out(f, pad, l);
173}
174
175static const char xdigits[16] = {
176	"0123456789ABCDEF"
177};
178
179static char *fmt_x(uintmax_t x, char *s, int lower)
180{
181	for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
182	return s;
183}
184
185static char *fmt_o(uintmax_t x, char *s)
186{
187	for (; x; x>>=3) *--s = '0' + (x&7);
188	return s;
189}
190
191static char *fmt_u(uintmax_t x, char *s)
192{
193	unsigned long y;
194	for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
195	for (y=x;           y; y/=10) *--s = '0' + y%10;
196	return s;
197}
198
199/* Do not override this check. The floating point printing code below
200 * depends on the float.h constants being right. If they are wrong, it
201 * may overflow the stack. */
202#if LDBL_MANT_DIG == 53
203typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
204#endif
205
206static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
207{
208	uint32_t big[(LDBL_MANT_DIG+28)/29 + 1          // mantissa expansion
209		+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
210	uint32_t *a, *d, *r, *z;
211	int e2=0, e, i, j, l;
212	char buf[9+LDBL_MANT_DIG/4], *s;
213	const char *prefix="-0X+0X 0X-0x+0x 0x";
214	int pl;
215	char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
216
217	pl=1;
218	if (signbit(y)) {
219		y=-y;
220	} else if (fl & MARK_POS) {
221		prefix+=3;
222	} else if (fl & PAD_POS) {
223		prefix+=6;
224	} else prefix++, pl=0;
225
226	if (!isfinite(y)) {
227		char *s = (t&32)?"inf":"INF";
228		if (y!=y) s=(t&32)?"nan":"NAN";
229		pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
230		out(f, prefix, pl);
231		out(f, s, 3);
232		pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
233		return MAX(w, 3+pl);
234	}
235
236	y = frexpl(y, &e2) * 2;
237	if (y) e2--;
238
239	if ((t|32)=='a') {
240		long double round = 8.0;
241		int re;
242
243		if (t&32) prefix += 9;
244		pl += 2;
245
246		if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
247		else re=LDBL_MANT_DIG/4-1-p;
248
249		if (re) {
250			while (re--) round*=16;
251			if (*prefix=='-') {
252				y=-y;
253				y-=round;
254				y+=round;
255				y=-y;
256			} else {
257				y+=round;
258				y-=round;
259			}
260		}
261
262		estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
263		if (estr==ebuf) *--estr='0';
264		*--estr = (e2<0 ? '-' : '+');
265		*--estr = t+('p'-'a');
266
267		s=buf;
268		do {
269			int x=y;
270			*s++=xdigits[x]|(t&32);
271			y=16*(y-x);
272			if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
273		} while (y);
274
275		if (p > INT_MAX-2-(ebuf-estr)-pl)
276			return -1;
277		if (p && s-buf-2 < p)
278			l = (p+2) + (ebuf-estr);
279		else
280			l = (s-buf) + (ebuf-estr);
281
282		pad(f, ' ', w, pl+l, fl);
283		out(f, prefix, pl);
284		pad(f, '0', w, pl+l, fl^ZERO_PAD);
285		out(f, buf, s-buf);
286		pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
287		out(f, estr, ebuf-estr);
288		pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
289		return MAX(w, pl+l);
290	}
291	if (p<0) p=6;
292
293	if (y) y *= 0x1p28, e2-=28;
294
295	if (e2<0) a=r=z=big;
296	else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
297
298	do {
299		*z = y;
300		y = 1000000000*(y-*z++);
301	} while (y);
302
303	while (e2>0) {
304		uint32_t carry=0;
305		int sh=MIN(29,e2);
306		for (d=z-1; d>=a; d--) {
307			uint64_t x = ((uint64_t)*d<<sh)+carry;
308			*d = x % 1000000000;
309			carry = x / 1000000000;
310		}
311		if (carry) *--a = carry;
312		while (z>a && !z[-1]) z--;
313		e2-=sh;
314	}
315	while (e2<0) {
316		uint32_t carry=0, *b;
317		int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9;
318		for (d=a; d<z; d++) {
319			uint32_t rm = *d & (1<<sh)-1;
320			*d = (*d>>sh) + carry;
321			carry = (1000000000>>sh) * rm;
322		}
323		if (!*a) a++;
324		if (carry) *z++ = carry;
325		/* Avoid (slow!) computation past requested precision */
326		b = (t|32)=='f' ? r : a;
327		if (z-b > need) z = b+need;
328		e2+=sh;
329	}
330
331	if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
332	else e=0;
333
334	/* Perform rounding: j is precision after the radix (possibly neg) */
335	j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
336	if (j < 9*(z-r-1)) {
337		uint32_t x;
338		/* We avoid C's broken division of negative numbers */
339		d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP);
340		j += 9*LDBL_MAX_EXP;
341		j %= 9;
342		for (i=10, j++; j<9; i*=10, j++);
343		x = *d % i;
344		/* Are there any significant digits past j? */
345		if (x || d+1!=z) {
346			long double round = 2/LDBL_EPSILON;
347			long double small;
348			if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1)))
349				round += 2;
350			if (x<i/2) small=0x0.8p0;
351			else if (x==i/2 && d+1==z) small=0x1.0p0;
352			else small=0x1.8p0;
353			if (pl && *prefix=='-') round*=-1, small*=-1;
354			*d -= x;
355			/* Decide whether to round by probing round+small */
356			if (round+small != round) {
357				*d = *d + i;
358				while (*d > 999999999) {
359					*d--=0;
360					if (d<a) *--a=0;
361					(*d)++;
362				}
363				for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
364			}
365		}
366		if (z>d+1) z=d+1;
367	}
368	for (; z>a && !z[-1]; z--);
369
370	if ((t|32)=='g') {
371		if (!p) p++;
372		if (p>e && e>=-4) {
373			t--;
374			p-=e+1;
375		} else {
376			t-=2;
377			p--;
378		}
379		if (!(fl&ALT_FORM)) {
380			/* Count trailing zeros in last place */
381			if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
382			else j=9;
383			if ((t|32)=='f')
384				p = MIN(p,MAX(0,9*(z-r-1)-j));
385			else
386				p = MIN(p,MAX(0,9*(z-r-1)+e-j));
387		}
388	}
389	if (p > INT_MAX-1-(p || (fl&ALT_FORM)))
390		return -1;
391	l = 1 + p + (p || (fl&ALT_FORM));
392	if ((t|32)=='f') {
393		if (e > INT_MAX-l) return -1;
394		if (e>0) l+=e;
395	} else {
396		estr=fmt_u(e<0 ? -e : e, ebuf);
397		while(ebuf-estr<2) *--estr='0';
398		*--estr = (e<0 ? '-' : '+');
399		*--estr = t;
400		if (ebuf-estr > INT_MAX-l) return -1;
401		l += ebuf-estr;
402	}
403
404	if (l > INT_MAX-pl) return -1;
405	pad(f, ' ', w, pl+l, fl);
406	out(f, prefix, pl);
407	pad(f, '0', w, pl+l, fl^ZERO_PAD);
408
409	if ((t|32)=='f') {
410		if (a>r) a=r;
411		for (d=a; d<=r; d++) {
412			char *s = fmt_u(*d, buf+9);
413			if (d!=a) while (s>buf) *--s='0';
414			else if (s==buf+9) *--s='0';
415			out(f, s, buf+9-s);
416		}
417		if (p || (fl&ALT_FORM)) out(f, ".", 1);
418		for (; d<z && p>0; d++, p-=9) {
419			char *s = fmt_u(*d, buf+9);
420			while (s>buf) *--s='0';
421			out(f, s, MIN(9,p));
422		}
423		pad(f, '0', p+9, 9, 0);
424	} else {
425		if (z<=a) z=a+1;
426		for (d=a; d<z && p>=0; d++) {
427			char *s = fmt_u(*d, buf+9);
428			if (s==buf+9) *--s='0';
429			if (d!=a) while (s>buf) *--s='0';
430			else {
431				out(f, s++, 1);
432				if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
433			}
434			out(f, s, MIN(buf+9-s, p));
435			p -= buf+9-s;
436		}
437		pad(f, '0', p+18, 18, 0);
438		out(f, estr, ebuf-estr);
439	}
440
441	pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
442
443	return MAX(w, pl+l);
444}
445
446static int getint(char **s) {
447	int i;
448	for (i=0; isdigit(**s); (*s)++) {
449		if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
450		else i = 10*i + (**s-'0');
451	}
452	return i;
453}
454
455static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
456{
457	char *a, *z, *s=(char *)fmt;
458	unsigned l10n=0, fl;
459	int w, p, xp;
460	union arg arg;
461	int argpos;
462	unsigned st, ps;
463	int cnt=0, l=0;
464	size_t i;
465	char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
466	const char *prefix;
467	int t, pl;
468	wchar_t wc[2], *ws;
469	char mb[4];
470
471	for (;;) {
472		/* This error is only specified for snprintf, but since it's
473		 * unspecified for other forms, do the same. Stop immediately
474		 * on overflow; otherwise %n could produce wrong results. */
475		if (l > INT_MAX - cnt) goto overflow;
476
477		/* Update output count, end loop when fmt is exhausted */
478		cnt += l;
479		if (!*s) break;
480
481		/* Handle literal text and %% format specifiers */
482		for (a=s; *s && *s!='%'; s++);
483		for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
484		if (z-a > INT_MAX-cnt) goto overflow;
485		l = z-a;
486		if (f) out(f, a, l);
487		if (l) continue;
488
489		if (isdigit(s[1]) && s[2]=='$') {
490			l10n=1;
491			argpos = s[1]-'0';
492			s+=3;
493		} else {
494			argpos = -1;
495			s++;
496		}
497
498		/* Read modifier flags */
499		for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
500			fl |= 1U<<*s-' ';
501
502		/* Read field width */
503		if (*s=='*') {
504			if (isdigit(s[1]) && s[2]=='$') {
505				l10n=1;
506				nl_type[s[1]-'0'] = INT;
507				w = nl_arg[s[1]-'0'].i;
508				s+=3;
509			} else if (!l10n) {
510				w = f ? va_arg(*ap, int) : 0;
511				s++;
512			} else goto inval;
513			if (w<0) fl|=LEFT_ADJ, w=-w;
514		} else if ((w=getint(&s))<0) goto overflow;
515
516		/* Read precision */
517		if (*s=='.' && s[1]=='*') {
518			if (isdigit(s[2]) && s[3]=='$') {
519				nl_type[s[2]-'0'] = INT;
520				p = nl_arg[s[2]-'0'].i;
521				s+=4;
522			} else if (!l10n) {
523				p = f ? va_arg(*ap, int) : 0;
524				s+=2;
525			} else goto inval;
526			xp = (p>=0);
527		} else if (*s=='.') {
528			s++;
529			p = getint(&s);
530			xp = 1;
531		} else {
532			p = -1;
533			xp = 0;
534		}
535
536		/* Format specifier state machine */
537		st=0;
538		do {
539			if (OOB(*s)) goto inval;
540			ps=st;
541			st=states[st]S(*s++);
542		} while (st-1<STOP);
543		if (!st) goto inval;
544
545		/* Check validity of argument type (nl/normal) */
546		if (st==NOARG) {
547			if (argpos>=0) goto inval;
548		} else {
549			if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
550			else if (f) pop_arg(&arg, st, ap);
551			else return 0;
552		}
553
554		if (!f) continue;
555
556		z = buf + sizeof(buf);
557		prefix = "-+   0X0x";
558		pl = 0;
559		t = s[-1];
560
561		/* Transform ls,lc -> S,C */
562		if (ps && (t&15)==3) t&=~32;
563
564		/* - and 0 flags are mutually exclusive */
565		if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
566
567		switch(t) {
568		case 'n':
569			switch(ps) {
570			case BARE: *(int *)arg.p = cnt; break;
571			case LPRE: *(long *)arg.p = cnt; break;
572			case LLPRE: *(long long *)arg.p = cnt; break;
573			case HPRE: *(unsigned short *)arg.p = cnt; break;
574			case HHPRE: *(unsigned char *)arg.p = cnt; break;
575			case ZTPRE: *(size_t *)arg.p = cnt; break;
576			case JPRE: *(uintmax_t *)arg.p = cnt; break;
577			}
578			continue;
579		case 'p':
580			p = MAX(p, 2*sizeof(void*));
581			t = 'x';
582			fl |= ALT_FORM;
583		case 'x': case 'X':
584			a = fmt_x(arg.i, z, t&32);
585			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
586			if (0) {
587		case 'o':
588			a = fmt_o(arg.i, z);
589			if ((fl&ALT_FORM) && p<z-a+1) prefix+=5, pl=1;
590			} if (0) {
591		case 'd': case 'i':
592			pl=1;
593			if (arg.i>INTMAX_MAX) {
594				arg.i=-arg.i;
595			} else if (fl & MARK_POS) {
596				prefix++;
597			} else if (fl & PAD_POS) {
598				prefix+=2;
599			} else pl=0;
600		case 'u':
601			a = fmt_u(arg.i, z);
602			}
603			if (xp && p<0) goto overflow;
604			if (p>=0) fl &= ~ZERO_PAD;
605			if (!arg.i && !p) {
606				a=z;
607				break;
608			}
609			p = MAX(p, z-a + !arg.i);
610			break;
611		case 'c':
612			*(a=z-(p=1))=arg.i;
613			fl &= ~ZERO_PAD;
614			break;
615		case 'm':
616			if (1) a = strerror(errno); else
617		case 's':
618			a = arg.p ? arg.p : "(null)";
619			z = a + strnlen(a, p<0 ? INT_MAX : p);
620			if (p<0 && *z) goto overflow;
621			p = z-a;
622			fl &= ~ZERO_PAD;
623			break;
624		case 'C':
625			wc[0] = arg.i;
626			wc[1] = 0;
627			arg.p = wc;
628			p = -1;
629		case 'S':
630			ws = arg.p;
631			for (i=l=0; i<p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=p-i; i+=l);
632			if (l<0) return -1;
633			if (i > INT_MAX) goto overflow;
634			p = i;
635			pad(f, ' ', w, p, fl);
636			ws = arg.p;
637			for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
638				out(f, mb, l);
639			pad(f, ' ', w, p, fl^LEFT_ADJ);
640			l = w>p ? w : p;
641			continue;
642		case 'e': case 'f': case 'g': case 'a':
643		case 'E': case 'F': case 'G': case 'A':
644			if (xp && p<0) goto overflow;
645			l = fmt_fp(f, arg.f, w, p, fl, t);
646			if (l<0) goto overflow;
647			continue;
648		}
649
650		if (p < z-a) p = z-a;
651		if (p > INT_MAX-pl) goto overflow;
652		if (w < pl+p) w = pl+p;
653		if (w > INT_MAX-cnt) goto overflow;
654
655		pad(f, ' ', w, pl+p, fl);
656		out(f, prefix, pl);
657		pad(f, '0', w, pl+p, fl^ZERO_PAD);
658		pad(f, '0', p, z-a, 0);
659		out(f, a, z-a);
660		pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
661
662		l = w;
663	}
664
665	if (f) return cnt;
666	if (!l10n) return 0;
667
668	for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
669		pop_arg(nl_arg+i, nl_type[i], ap);
670	for (; i<=NL_ARGMAX && !nl_type[i]; i++);
671	if (i<=NL_ARGMAX) goto inval;
672	return 1;
673
674inval:
675	errno = EINVAL;
676	return -1;
677overflow:
678	errno = EOVERFLOW;
679	return -1;
680}
681
682int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
683{
684	va_list ap2;
685	int nl_type[NL_ARGMAX+1] = {0};
686	union arg nl_arg[NL_ARGMAX+1];
687	unsigned char internal_buf[80], *saved_buf = 0;
688	int olderr;
689	int ret;
690
691	/* the copy allows passing va_list* even if va_list is an array */
692	va_copy(ap2, ap);
693	if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) {
694		va_end(ap2);
695		return -1;
696	}
697
698	FLOCK(f);
699	olderr = f->flags & F_ERR;
700	if (f->mode < 1) f->flags &= ~F_ERR;
701	if (!f->buf_size) {
702		saved_buf = f->buf;
703		f->wpos = f->wbase = f->buf = internal_buf;
704		f->buf_size = sizeof internal_buf;
705		f->wend = internal_buf + sizeof internal_buf;
706	}
707	ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
708	if (saved_buf) {
709		f->write(f, 0, 0);
710		if (!f->wpos) ret = -1;
711		f->buf = saved_buf;
712		f->buf_size = 0;
713		f->wpos = f->wbase = f->wend = 0;
714	}
715	if (f->flags & F_ERR) ret = -1;
716	f->flags |= olderr;
717	FUNLOCK(f);
718	va_end(ap2);
719	return ret;
720}
721