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
pop_arg(union arg * arg,int type,va_list * ap)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
out(FILE * f,const char * s,size_t l)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
pad(FILE * f,char c,int w,int l,int fl)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
fmt_x(uintmax_t x,char * s,int lower)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
fmt_o(uintmax_t x,char * s)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
fmt_u(uintmax_t x,char * s)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
fmt_fp(FILE * f,long double y,int w,int p,int fl,int t)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
getint(char ** s)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
printf_core(FILE * f,const char * fmt,va_list * ap,union arg * nl_arg,int * nl_type)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
vfprintf(FILE * restrict f,const char * restrict fmt,va_list ap)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
vsnprintf(char * restrict s,size_t n,const char * restrict fmt,va_list ap)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__ */
vfprintf(FILE * restrict f,const char * restrict fmt,va_list ap)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