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