Home | History | Annotate | Download | only in stdio
      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 
     68 enum {
     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 
     97 static 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 
    150 union arg
    151 {
    152 	uintmax_t i;
    153 	long double f;
    154 	void *p;
    155 };
    156 
    157 static 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 
    187 static 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 
    196 static 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 
    207 static const char xdigits[16] = {
    208 	"0123456789ABCDEF"
    209 };
    210 
    211 static 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 
    217 static char *fmt_o(uintmax_t x, char *s)
    218 {
    219 	for (; x; x>>=3) *--s = '0' + (x&7);
    220 	return s;
    221 }
    222 
    223 static 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 
    231 static 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 
    462 static 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 
    469 static 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 
    695 int 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 
    716 int 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__ */
    751 int 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