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 <stddef.h>
8 #include <stdlib.h>
9 #include <wchar.h>
10 #include <inttypes.h>
11 #include <math.h>
12 #include <float.h>
13
14 /*
15 * TRUSTY - long doubles are 128 bits on ARM 64, which drastically increases
16 * stack size and requires software emulation. To save resources, allow programs
17 * to specify the largest floating point type they will print with STDIO_FLOAT.
18 * 0: disabled
19 * 32: float
20 * 64: double
21 * 128: long double
22 * This is a bit of a lie. long doubles are not always 128 bits. This
23 * preprocessor does not make it easy to do this symbolically, however, so we
24 * lie.
25 */
26
27 /* Default */
28 #ifndef STDIO_FLOAT
29 #define STDIO_FLOAT 0
30 #endif
31
32 /* Sanity check. */
33 #if STDIO_FLOAT != 0 && STDIO_FLOAT != 32 && STDIO_FLOAT != 64 && STDIO_FLOAT != 128
34 #error Invalid STDIO_FLOAT
35 #endif
36
37 /* Define these names in all cases, even if STDIO_FLOAT is invalid. */
38 #if STDIO_FLOAT == 32
39 typedef float stdio_float;
40 #define STDIO_EPSILON FLT_EPSILON
41 #define STDIO_FREXP frexpf
42 #define STDIO_MAX_EXP FLT_MAX_EXP
43 #define STDIO_MANT_DIG FLT_MANT_DIG
44 #elif STDIO_FLOAT == 128
45 typedef long double stdio_float;
46 #define STDIO_EPSILON LDBL_EPSILON
47 #define STDIO_FREXP frexpl
48 #define STDIO_MAX_EXP LDBL_MAX_EXP
49 #define STDIO_MANT_DIG LDBL_MANT_DIG
50 #else
51 typedef double stdio_float;
52 #define STDIO_EPSILON DBL_EPSILON
53 #define STDIO_FREXP frexp
54 #define STDIO_MAX_EXP DBL_MAX_EXP
55 #define STDIO_MANT_DIG DBL_MANT_DIG
56 #endif
57
58 /* TRUSTY - GNU extention that calls stderr, which can increase rodata size. */
59 #ifndef STDIO_NO_FORMAT_M
60 #define STDIO_NO_FORMAT_M 1
61 #endif
62
63 /* TRUSTY - Nonstandard wide character formatting. */
64 #ifndef STDIO_NO_FORMAT_WIDE
65 #define STDIO_NO_FORMAT_WIDE 1
66 #endif
67
68 /* Some useful macros */
69
70 #ifndef MAX
71 #define MAX(a,b) ((a)>(b) ? (a) : (b))
72 #endif
73 #ifndef MIN
74 #define MIN(a,b) ((a)<(b) ? (a) : (b))
75 #endif
76
77 /*
78 * TRUSTY - Macro used to determine if an integer number should
79 * not be printed.
80 */
81 #define NUMBER_IN_FILTER_RANGE(num) (((num) > 4096) && ((num) < (uintptr_t)-4096))
82
83 /* Convenient bit representation for modifier flags, which all fall
84 * within 31 codepoints of the space character. */
85
86 #define ALT_FORM (1U<<'#'-' ')
87 #define ZERO_PAD (1U<<'0'-' ')
88 #define LEFT_ADJ (1U<<'-'-' ')
89 #define PAD_POS (1U<<' '-' ')
90 #define MARK_POS (1U<<'+'-' ')
91 #define GROUPED (1U<<'\''-' ')
92
93 #define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
94
95 /* State machine to accept length modifiers + conversion specifiers.
96 * Result is 0 on failure, or an argument type to pop on success. */
97
98 enum {
99 BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
100 ZTPRE, JPRE,
101 STOP,
102 PTR, INT, UINT, ULLONG,
103 LONG, ULONG,
104 SHORT, USHORT, CHAR, UCHAR,
105 LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
106 DBL, LDBL,
107 NOARG,
108 MAXSTATE
109 };
110
111 #define S(x) [(x)-'A']
112
113 static const unsigned char states[]['z'-'A'+1] = {
114 { /* 0: bare types */
115 S('d') = INT, S('i') = INT,
116 S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
117 S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
118 S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
119 S('c') = CHAR, S('C') = INT,
120 S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
121 S('m') = NOARG,
122 S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
123 S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
124 }, { /* 1: l-prefixed */
125 S('d') = LONG, S('i') = LONG,
126 S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
127 S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
128 S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
129 S('c') = INT, S('s') = PTR, S('n') = PTR,
130 S('l') = LLPRE,
131 }, { /* 2: ll-prefixed */
132 S('d') = LLONG, S('i') = LLONG,
133 S('o') = ULLONG, S('u') = ULLONG,
134 S('x') = ULLONG, S('X') = ULLONG,
135 S('n') = PTR,
136 }, { /* 3: h-prefixed */
137 S('d') = SHORT, S('i') = SHORT,
138 S('o') = USHORT, S('u') = USHORT,
139 S('x') = USHORT, S('X') = USHORT,
140 S('n') = PTR,
141 S('h') = HHPRE,
142 }, { /* 4: hh-prefixed */
143 S('d') = CHAR, S('i') = CHAR,
144 S('o') = UCHAR, S('u') = UCHAR,
145 S('x') = UCHAR, S('X') = UCHAR,
146 S('n') = PTR,
147 }, { /* 5: L-prefixed */
148 S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
149 S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
150 S('n') = PTR,
151 }, { /* 6: z- or t-prefixed (assumed to be same size) */
152 S('d') = PDIFF, S('i') = PDIFF,
153 S('o') = SIZET, S('u') = SIZET,
154 S('x') = SIZET, S('X') = SIZET,
155 S('n') = PTR,
156 }, { /* 7: j-prefixed */
157 S('d') = IMAX, S('i') = IMAX,
158 S('o') = UMAX, S('u') = UMAX,
159 S('x') = UMAX, S('X') = UMAX,
160 S('n') = PTR,
161 }
162 };
163
164 #define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
165
166 union arg
167 {
168 uintmax_t i;
169 stdio_float f;
170 void *p;
171 };
172
pop_arg(union arg * arg,int type,va_list * ap)173 static void pop_arg(union arg *arg, int type, va_list *ap)
174 {
175 switch (type) {
176 case PTR: arg->p = va_arg(*ap, void *);
177 break; case INT: arg->i = va_arg(*ap, int);
178 break; case UINT: arg->i = va_arg(*ap, unsigned int);
179 break; case LONG: arg->i = va_arg(*ap, long);
180 break; case ULONG: arg->i = va_arg(*ap, unsigned long);
181 break; case ULLONG: arg->i = va_arg(*ap, unsigned long long);
182 break; case SHORT: arg->i = (short)va_arg(*ap, int);
183 break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int);
184 break; case CHAR: arg->i = (signed char)va_arg(*ap, int);
185 break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int);
186 break; case LLONG: arg->i = va_arg(*ap, long long);
187 break; case SIZET: arg->i = va_arg(*ap, size_t);
188 break; case IMAX: arg->i = va_arg(*ap, intmax_t);
189 break; case UMAX: arg->i = va_arg(*ap, uintmax_t);
190 break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t);
191 break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *);
192 #if !WITH_NO_FP
193 break; case DBL: arg->f = (stdio_float)va_arg(*ap, double);
194 #if STDIO_FLOAT == 128
195 break; case LDBL: arg->f = va_arg(*ap, long double);
196 #else
197 /* Zero out to avoid software conversion. */
198 break; case LDBL: va_arg(*ap, long double); arg->f = 0;
199 #endif
200 #else
201 break; default: fputs("Floating point code is not supported\n", stderr);
202 abort();
203 #endif // !WITH_NO_FP
204 }
205 }
206
out(FILE * f,const char * s,size_t l)207 static void out(FILE *f, const char *s, size_t l)
208 {
209 if (!(f->flags & F_ERR)) __fwritex((void *)s, l, f);
210 }
211
pad(FILE * f,char c,int w,int l,int fl)212 static void pad(FILE *f, char c, int w, int l, int fl)
213 {
214 char pad[256];
215 if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
216 l = w - l;
217 memset(pad, c, l>sizeof pad ? sizeof pad : l);
218 for (; l >= sizeof pad; l -= sizeof pad)
219 out(f, pad, sizeof pad);
220 out(f, pad, l);
221 }
222
223 static const char xdigits[16] = {
224 "0123456789ABCDEF"
225 };
226
227 /*
228 * TRUSTY - This is the function used to return what will
229 * be printed if a number value shouldn't be shown.
230 */
fmt_filter(uintmax_t x,char * s)231 static char *fmt_filter(uintmax_t x, char *s)
232 {
233 /* ignoring x value on this
234 * implementation, always
235 * filtering with ***.*/
236 for (x = 0; x < 3; x++) *--s = '*';
237 return s;
238 }
239
fmt_x(uintmax_t x,char * s,int lower)240 static char *fmt_x(uintmax_t x, char *s, int lower)
241 {
242 for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
243 return s;
244 }
245
fmt_o(uintmax_t x,char * s)246 static char *fmt_o(uintmax_t x, char *s)
247 {
248 for (; x; x>>=3) *--s = '0' + (x&7);
249 return s;
250 }
251
fmt_u(uintmax_t x,char * s)252 static char *fmt_u(uintmax_t x, char *s)
253 {
254 unsigned long y;
255 for ( ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
256 for (y=x; y; y/=10) *--s = '0' + y%10;
257 return s;
258 }
259
260 /* Do not override this check. The floating point printing code below
261 * depends on the float.h constants being right. If they are wrong, it
262 * may overflow the stack. */
263 #if LDBL_MANT_DIG == 53
264 typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
265 #endif
266
267 #if !WITH_NO_FP
268 /* TRUSTY - noinline to save stack space when floats are not printed. */
269 __attribute__((__noinline__))
fmt_fp(FILE * f,stdio_float y,int w,int p,int fl,int t)270 static int fmt_fp(FILE *f, stdio_float y, int w, int p, int fl, int t)
271 {
272 uint32_t big[(STDIO_MANT_DIG+28)/29 + 1 // mantissa expansion
273 + (STDIO_MAX_EXP+STDIO_MANT_DIG+28+8)/9]; // exponent expansion
274 uint32_t *a, *d, *r, *z;
275 int e2=0, e, i, j, l;
276 char buf[9+STDIO_MANT_DIG/4], *s;
277 const char *prefix="-0X+0X 0X-0x+0x 0x";
278 int pl;
279 char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
280
281 pl=1;
282 if (signbit(y)) {
283 y=-y;
284 } else if (fl & MARK_POS) {
285 prefix+=3;
286 } else if (fl & PAD_POS) {
287 prefix+=6;
288 } else prefix++, pl=0;
289
290 if (!isfinite(y)) {
291 char *s = (t&32)?"inf":"INF";
292 if (y!=y) s=(t&32)?"nan":"NAN";
293 pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
294 out(f, prefix, pl);
295 out(f, s, 3);
296 pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
297 return MAX(w, 3+pl);
298 }
299
300 y = STDIO_FREXP(y, &e2) * 2;
301 if (y) e2--;
302
303 if ((t|32)=='a') {
304 stdio_float round = 8.0;
305 int re;
306
307 if (t&32) prefix += 9;
308 pl += 2;
309
310 if (p<0 || p>=STDIO_MANT_DIG/4-1) re=0;
311 else re=STDIO_MANT_DIG/4-1-p;
312
313 if (re) {
314 round *= 1<<(STDIO_MANT_DIG%4);
315 while (re--) round*=16;
316 if (*prefix=='-') {
317 y=-y;
318 y-=round;
319 y+=round;
320 y=-y;
321 } else {
322 y+=round;
323 y-=round;
324 }
325 }
326
327 estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
328 if (estr==ebuf) *--estr='0';
329 *--estr = (e2<0 ? '-' : '+');
330 *--estr = t+('p'-'a');
331
332 s=buf;
333 do {
334 int x=y;
335 *s++=xdigits[x]|(t&32);
336 y=16*(y-x);
337 if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
338 } while (y);
339
340 if (p > INT_MAX-2-(ebuf-estr)-pl)
341 return -1;
342 if (p && s-buf-2 < p)
343 l = (p+2) + (ebuf-estr);
344 else
345 l = (s-buf) + (ebuf-estr);
346
347 pad(f, ' ', w, pl+l, fl);
348 out(f, prefix, pl);
349 pad(f, '0', w, pl+l, fl^ZERO_PAD);
350 out(f, buf, s-buf);
351 pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
352 out(f, estr, ebuf-estr);
353 pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
354 return MAX(w, pl+l);
355 }
356 if (p<0) p=6;
357
358 if (y) y *= 0x1p28, e2-=28;
359
360 if (e2<0) a=r=z=big;
361 else a=r=z=big+sizeof(big)/sizeof(*big) - STDIO_MANT_DIG - 1;
362
363 do {
364 *z = y;
365 y = 1000000000*(y-*z++);
366 } while (y);
367
368 while (e2>0) {
369 uint32_t carry=0;
370 int sh=MIN(29,e2);
371 for (d=z-1; d>=a; d--) {
372 uint64_t x = ((uint64_t)*d<<sh)+carry;
373 *d = x % 1000000000;
374 carry = x / 1000000000;
375 }
376 if (carry) *--a = carry;
377 while (z>a && !z[-1]) z--;
378 e2-=sh;
379 }
380 while (e2<0) {
381 uint32_t carry=0, *b;
382 int sh=MIN(9,-e2), need=1+(p+STDIO_MANT_DIG/3U+8)/9;
383 for (d=a; d<z; d++) {
384 uint32_t rm = *d & (1<<sh)-1;
385 *d = (*d>>sh) + carry;
386 carry = (1000000000>>sh) * rm;
387 }
388 if (!*a) a++;
389 if (carry) *z++ = carry;
390 /* Avoid (slow!) computation past requested precision */
391 b = (t|32)=='f' ? r : a;
392 if (z-b > need) z = b+need;
393 e2+=sh;
394 }
395
396 if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
397 else e=0;
398
399 /* Perform rounding: j is precision after the radix (possibly neg) */
400 j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
401 if (j < 9*(z-r-1)) {
402 uint32_t x;
403 /* We avoid C's broken division of negative numbers */
404 d = r + 1 + ((j+9*STDIO_MAX_EXP)/9 - STDIO_MAX_EXP);
405 j += 9*STDIO_MAX_EXP;
406 j %= 9;
407 for (i=10, j++; j<9; i*=10, j++);
408 x = *d % i;
409 /* Are there any significant digits past j? */
410 if (x || d+1!=z) {
411 stdio_float round = 2/STDIO_EPSILON;
412 stdio_float small;
413 if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1)))
414 round += 2;
415 if (x<i/2) small=0x0.8p0;
416 else if (x==i/2 && d+1==z) small=0x1.0p0;
417 else small=0x1.8p0;
418 if (pl && *prefix=='-') round*=-1, small*=-1;
419 *d -= x;
420 /* Decide whether to round by probing round+small */
421 if (round+small != round) {
422 *d = *d + i;
423 while (*d > 999999999) {
424 *d--=0;
425 if (d<a) *--a=0;
426 (*d)++;
427 }
428 for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
429 }
430 }
431 if (z>d+1) z=d+1;
432 }
433 for (; z>a && !z[-1]; z--);
434
435 if ((t|32)=='g') {
436 if (!p) p++;
437 if (p>e && e>=-4) {
438 t--;
439 p-=e+1;
440 } else {
441 t-=2;
442 p--;
443 }
444 if (!(fl&ALT_FORM)) {
445 /* Count trailing zeros in last place */
446 if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
447 else j=9;
448 if ((t|32)=='f')
449 p = MIN(p,MAX(0,9*(z-r-1)-j));
450 else
451 p = MIN(p,MAX(0,9*(z-r-1)+e-j));
452 }
453 }
454 if (p > INT_MAX-1-(p || (fl&ALT_FORM)))
455 return -1;
456 l = 1 + p + (p || (fl&ALT_FORM));
457 if ((t|32)=='f') {
458 if (e > INT_MAX-l) return -1;
459 if (e>0) l+=e;
460 } else {
461 estr=fmt_u(e<0 ? -e : e, ebuf);
462 while(ebuf-estr<2) *--estr='0';
463 *--estr = (e<0 ? '-' : '+');
464 *--estr = t;
465 if (ebuf-estr > INT_MAX-l) return -1;
466 l += ebuf-estr;
467 }
468
469 if (l > INT_MAX-pl) return -1;
470 pad(f, ' ', w, pl+l, fl);
471 out(f, prefix, pl);
472 pad(f, '0', w, pl+l, fl^ZERO_PAD);
473
474 if ((t|32)=='f') {
475 if (a>r) a=r;
476 for (d=a; d<=r; d++) {
477 char *s = fmt_u(*d, buf+9);
478 if (d!=a) while (s>buf) *--s='0';
479 else if (s==buf+9) *--s='0';
480 out(f, s, buf+9-s);
481 }
482 if (p || (fl&ALT_FORM)) out(f, ".", 1);
483 for (; d<z && p>0; d++, p-=9) {
484 char *s = fmt_u(*d, buf+9);
485 while (s>buf) *--s='0';
486 out(f, s, MIN(9,p));
487 }
488 pad(f, '0', p+9, 9, 0);
489 } else {
490 if (z<=a) z=a+1;
491 for (d=a; d<z && p>=0; d++) {
492 char *s = fmt_u(*d, buf+9);
493 if (s==buf+9) *--s='0';
494 if (d!=a) while (s>buf) *--s='0';
495 else {
496 out(f, s++, 1);
497 if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
498 }
499 out(f, s, MIN(buf+9-s, p));
500 p -= buf+9-s;
501 }
502 pad(f, '0', p+18, 18, 0);
503 out(f, estr, ebuf-estr);
504 }
505
506 pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
507
508 return MAX(w, pl+l);
509 }
510 #endif
511
getint(char ** s)512 static int getint(char **s) {
513 int i;
514 for (i=0; isdigit(**s); (*s)++) {
515 if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
516 else i = 10*i + (**s-'0');
517 }
518 return i;
519 }
520
should_filter_number(uintmax_t number,char ** format_string,int filter_number,int use_filter_modifiers)521 static int should_filter_number(uintmax_t number, char **format_string, int filter_number, int use_filter_modifiers)
522 {
523 char currChar;
524
525 /* We only filter numbers on a certain range
526 * (a number outside of +/-4096 will be filtered).*/
527 filter_number = filter_number && NUMBER_IN_FILTER_RANGE(number);
528
529 /* We will check if we have an override filtering modifier.*/
530 currChar = **format_string;
531
532 /* This is a not filtered call, we should not "eat" the extra x.*/
533 if (!use_filter_modifiers) {
534 return filter_number;
535 }
536
537 if (currChar == 0) {
538 /* We were already at the end of the string.*/
539 return filter_number;
540 }
541 switch (currChar)
542 {
543 case 'x':
544 /* We really want to print this character.*/
545 filter_number = 0;
546 /* We are consuming this character, advance format string.*/
547 (*format_string)++;
548 break;
549 default:
550 /* We didn't understood the next character,
551 * normal parsing code will take care of it.*/
552 break;
553 }
554 return filter_number;
555 }
556
printf_core(FILE * f,const char * fmt,va_list * ap,union arg * nl_arg,int * nl_type,int filtered_on_release)557 static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type, int filtered_on_release)
558 {
559 char *a, *z, *s=(char *)fmt;
560 unsigned l10n=0, fl;
561 int w, p, xp;
562 union arg arg;
563 int argpos;
564 unsigned st, ps;
565 int cnt=0, l=0;
566 size_t i;
567 char buf[sizeof(uintmax_t)*3+3+STDIO_MANT_DIG/4];
568 const char *prefix;
569 int t, pl;
570 #if STDIO_NO_FORMAT_WIDE != 1
571 wchar_t wc[2], *ws;
572 char mb[4];
573 #endif
574 int use_filter_modifiers;
575
576 /* Keeping track if new filtering modifier (x) should be printed or not.*/
577 use_filter_modifiers = filtered_on_release;
578
579 #if RELEASE_BUILD == 0
580 /* We are not on a release build, do not filter.*/
581 filtered_on_release = 0;
582 #endif
583 for (;;) {
584 /* This error is only specified for snprintf, but since it's
585 * unspecified for other forms, do the same. Stop immediately
586 * on overflow; otherwise %n could produce wrong results. */
587 if (l > INT_MAX - cnt) goto overflow;
588
589 /* Update output count, end loop when fmt is exhausted */
590 cnt += l;
591 if (!*s) break;
592
593 /* Handle literal text and %% format specifiers */
594 for (a=s; *s && *s!='%'; s++);
595 for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
596 if (z-a > INT_MAX-cnt) goto overflow;
597 l = z-a;
598 if (f) out(f, a, l);
599 if (l) continue;
600
601 /* $ is a non C standard specifier to
602 * refer to an argument by position.*/
603 if (isdigit(s[1]) && s[2]=='$') {
604 l10n=1;
605 argpos = s[1]-'0';
606 s+=3;
607 } else {
608 argpos = -1;
609 s++;
610 }
611
612 /* Read modifier flags */
613 /* Code takes advantages that all flags fit on 32 bit to
614 * represent each flag as a bit on a word, it will iterate
615 * over the input until it cannot find another flag.*/
616 for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
617 fl |= 1U<<*s-' ';
618
619 /* Read field width */
620 if (*s=='*') {
621 if (isdigit(s[1]) && s[2]=='$') {
622 l10n=1;
623 nl_type[s[1]-'0'] = INT;
624 w = nl_arg[s[1]-'0'].i;
625 s+=3;
626 } else if (!l10n) {
627 w = f ? va_arg(*ap, int) : 0;
628 s++;
629 } else goto inval;
630 if (w<0) fl|=LEFT_ADJ, w=-w;
631 } else if ((w=getint(&s))<0) goto overflow;
632
633 /* Read precision */
634 if (*s=='.' && s[1]=='*') {
635 if (isdigit(s[2]) && s[3]=='$') {
636 nl_type[s[2]-'0'] = INT;
637 p = nl_arg[s[2]-'0'].i;
638 s+=4;
639 } else if (!l10n) {
640 p = f ? va_arg(*ap, int) : 0;
641 s+=2;
642 } else goto inval;
643 xp = (p>=0);
644 } else if (*s=='.') {
645 s++;
646 p = getint(&s);
647 xp = 1;
648 } else {
649 p = -1;
650 xp = 0;
651 }
652
653 /* Format specifier state machine */
654 /* Code uses a state machine to figure out how big a
655 * specific argument is depending on its specifiers;
656 * for example it is used to give different sizes if
657 * an argument is tagged as lu (ULONG) vs u (UINT).
658 * st = current state.
659 * ps = previous state. Mainly used to figure out
660 * the size of a pointer for n*/
661 st=0;
662 do {
663 if (OOB(*s)) goto inval;
664 ps=st;
665 st=states[st]S(*s++);
666 } while (st-1<STOP);
667 if (!st) goto inval;
668
669 /* Check validity of argument type (nl/normal) */
670 if (st==NOARG) {
671 if (argpos>=0) goto inval;
672 } else {
673 if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
674 else if (f) pop_arg(&arg, st, ap);
675 else return 0;
676 }
677
678 if (!f) continue;
679
680 z = buf + sizeof(buf);
681 prefix = "-+ 0X0x";
682 pl = 0;
683 t = s[-1];
684
685 /* Transform ls,lc -> S,C */
686 if (ps && (t&15)==3) t&=~32;
687
688 /* - and 0 flags are mutually exclusive */
689 if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
690
691 switch(t) {
692 case 'n':
693 switch(ps) {
694 case BARE: *(int *)arg.p = cnt; break;
695 case LPRE: *(long *)arg.p = cnt; break;
696 case LLPRE: *(long long *)arg.p = cnt; break;
697 case HPRE: *(unsigned short *)arg.p = cnt; break;
698 case HHPRE: *(unsigned char *)arg.p = cnt; break;
699 case ZTPRE: *(size_t *)arg.p = cnt; break;
700 case JPRE: *(uintmax_t *)arg.p = cnt; break;
701 }
702 continue;
703 case 'p':
704 p = MAX(p, 2*sizeof(void*));
705 t = 'x';
706 fl |= ALT_FORM;
707 case 'x': case 'X':
708 /*z is a reverse pointer to the char buffer 'buf'*/
709 if (should_filter_number(arg.i, &s, filtered_on_release, use_filter_modifiers)) {
710 a = fmt_filter(arg.i, z);
711 } else {
712 a = fmt_x(arg.i, z, t&32);
713 }
714 if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
715 if (0) {
716 case 'o':
717 if (should_filter_number(arg.i, &s, filtered_on_release, use_filter_modifiers)) {
718 a = fmt_filter(arg.i, z);
719 } else {
720 a = fmt_o(arg.i, z);
721 }
722 if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
723 } if (0) {
724 case 'd': case 'i':
725 pl=1;
726 if (arg.i>INTMAX_MAX) {
727 arg.i=-arg.i;
728 } else if (fl & MARK_POS) {
729 prefix++;
730 } else if (fl & PAD_POS) {
731 prefix+=2;
732 } else pl=0;
733 case 'u':
734 if (should_filter_number(arg.i, &s, filtered_on_release, use_filter_modifiers)) {
735 /* Removing any (i.e. negative) prefix on filtered
736 * int prints pl is the length of the prefix to be
737 * printed.*/
738 pl = 0;
739 a = fmt_filter(arg.i, z);
740 } else {
741 a = fmt_u(arg.i, z);
742 }
743 }
744 /*xp and p are set by the set precision code.
745 * xp: use precision
746 * p: precision*/
747 if (xp && p<0) goto overflow;
748 if (xp) fl &= ~ZERO_PAD;
749 if (!arg.i && !p) {
750 a=z;
751 break;
752 }
753 p = MAX(p, z-a + !arg.i);
754 break;
755 case 'c':
756 *(a=z-(p=1))=arg.i;
757 fl &= ~ZERO_PAD;
758 break;
759 case 'm':
760 #if STDIO_NO_FORMAT_M == 1
761 if (1) a = "(disabled)"; else
762 #else
763 if (1) a = strerror(errno); else
764 #endif
765 case 's':
766 a = arg.p ? arg.p : "(null)";
767 z = a + strnlen(a, p<0 ? INT_MAX : p);
768 if (p<0 && *z) goto overflow;
769 p = z-a;
770 fl &= ~ZERO_PAD;
771 break;
772 #if STDIO_NO_FORMAT_WIDE == 1
773 case 'C':
774 case 'S':
775 a = "(disabled)";
776 z = a + strnlen(a, p<0 ? INT_MAX : p);
777 if (p<0 && *z) goto overflow;
778 p = z-a;
779 fl &= ~ZERO_PAD;
780 break;
781 #else
782 case 'C':
783 wc[0] = arg.i;
784 wc[1] = 0;
785 arg.p = wc;
786 p = -1;
787 case 'S':
788 ws = arg.p;
789 for (i=l=0; i<p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=p-i; i+=l);
790 if (l<0) return -1;
791 if (i > INT_MAX) goto overflow;
792 p = i;
793 pad(f, ' ', w, p, fl);
794 ws = arg.p;
795 for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
796 out(f, mb, l);
797 pad(f, ' ', w, p, fl^LEFT_ADJ);
798 l = w>p ? w : p;
799 continue;
800 #endif
801 case 'e': case 'f': case 'g': case 'a':
802 case 'E': case 'F': case 'G': case 'A':
803 #if STDIO_FLOAT == 0
804 a = "(disabled)";
805 z = a + strnlen(a, p<0 ? INT_MAX : p);
806 if (p<0 && *z) goto overflow;
807 p = z-a;
808 fl &= ~ZERO_PAD;
809 break;
810 #else
811 if (xp && p<0) goto overflow;
812 #if !WITH_NO_FP
813 l = fmt_fp(f, arg.f, w, p, fl, t);
814 #else
815 fputs("Floating point code is not supported\n", stderr);
816 abort();
817 #endif
818 if (l<0) goto overflow;
819 continue;
820 #endif
821 }
822
823 if (p < z-a) p = z-a;
824 if (p > INT_MAX-pl) goto overflow;
825 if (w < pl+p) w = pl+p;
826 if (w > INT_MAX-cnt) goto overflow;
827
828 pad(f, ' ', w, pl+p, fl);
829 out(f, prefix, pl);
830 pad(f, '0', w, pl+p, fl^ZERO_PAD);
831 pad(f, '0', p, z-a, 0);
832 out(f, a, z-a);
833 pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
834
835 l = w;
836 }
837
838 if (f) return cnt;
839 if (!l10n) return 0;
840
841 for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
842 pop_arg(nl_arg+i, nl_type[i], ap);
843 for (; i<=NL_ARGMAX && !nl_type[i]; i++);
844 if (i<=NL_ARGMAX) goto inval;
845 return 1;
846
847 inval:
848 errno = EINVAL;
849 return -1;
850 overflow:
851 errno = EOVERFLOW;
852 return -1;
853 }
854
vfprintf_worker(FILE * restrict f,const char * restrict fmt,va_list ap,int filtered_on_release)855 int vfprintf_worker(FILE *restrict f, const char *restrict fmt, va_list ap, int filtered_on_release)
856 {
857 va_list ap2;
858 int nl_type[NL_ARGMAX+1] = {0};
859 union arg nl_arg[NL_ARGMAX+1];
860 unsigned char internal_buf[80], *saved_buf = 0;
861 int olderr;
862 int ret;
863
864 /* the copy allows passing va_list* even if va_list is an array */
865 va_copy(ap2, ap);
866 if (printf_core(0, fmt, &ap2, nl_arg, nl_type, filtered_on_release) < 0) {
867 va_end(ap2);
868 return -1;
869 }
870
871 FLOCK(f);
872 olderr = f->flags & F_ERR;
873 if (f->mode < 1) f->flags &= ~F_ERR;
874 if (!f->buf_size) {
875 saved_buf = f->buf;
876 f->buf = internal_buf;
877 f->buf_size = sizeof internal_buf;
878 f->wpos = f->wbase = f->wend = 0;
879 }
880 if (!f->wend && __towrite(f)) ret = -1;
881 else ret = printf_core(f, fmt, &ap2, nl_arg, nl_type, filtered_on_release);
882 if (saved_buf) {
883 f->write(f, 0, 0);
884 if (!f->wpos) ret = -1;
885 f->buf = saved_buf;
886 f->buf_size = 0;
887 f->wpos = f->wbase = f->wend = 0;
888 }
889 if (f->flags & F_ERR) ret = -1;
890 f->flags |= olderr;
891 FUNLOCK(f);
892 va_end(ap2);
893 return ret;
894 }
895