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 26 #include <errno.h> 27 #include <ctype.h> 28 #include <limits.h> 29 #include <string.h> 30 #include <stdarg.h> 31 #include <stdlib.h> 32 #include <wchar.h> 33 #include <inttypes.h> 34 35 #include "stdio_impl.h" 36 37 /* Convenient bit representation for modifier flags, which all fall 38 * within 31 codepoints of the space character. */ 39 40 #define ALT_FORM (1U<<'#'-' ') 41 #define ZERO_PAD (1U<<'0'-' ') 42 #define LEFT_ADJ (1U<<'-'-' ') 43 #define PAD_POS (1U<<' '-' ') 44 #define MARK_POS (1U<<'+'-' ') 45 #define GROUPED (1U<<'\''-' ') 46 47 #define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED) 48 49 #if UINT_MAX == ULONG_MAX 50 #define LONG_IS_INT 51 #endif 52 53 #if SIZE_MAX != ULONG_MAX || UINTMAX_MAX != ULLONG_MAX 54 #define ODD_TYPES 55 #endif 56 57 /* State machine to accept length modifiers + conversion specifiers. 58 * Result is 0 on failure, or an argument type to pop on success. */ 59 60 enum { 61 BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE, 62 ZTPRE, JPRE, 63 STOP, 64 PTR, INT, UINT, ULLONG, 65 #ifndef LONG_IS_INT 66 LONG, ULONG, 67 #else 68 #define LONG INT 69 #define ULONG UINT 70 #endif 71 SHORT, USHORT, CHAR, UCHAR, 72 #ifdef ODD_TYPES 73 LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR, 74 #else 75 #define LLONG ULLONG 76 #define SIZET ULONG 77 #define IMAX LLONG 78 #define UMAX ULLONG 79 #define PDIFF LONG 80 #define UIPTR ULONG 81 #endif 82 DBL, LDBL, 83 NOARG, 84 MAXSTATE 85 }; 86 87 #define S(x) [(x)-'A'] 88 89 static const unsigned char states[]['z'-'A'+1] = { 90 { /* 0: bare types */ 91 S('d') = INT, S('i') = INT, 92 S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT, 93 S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL, 94 S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL, 95 S('c') = CHAR, S('C') = INT, 96 S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR, 97 S('m') = NOARG, 98 S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE, 99 S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE, 100 }, { /* 1: l-prefixed */ 101 S('d') = LONG, S('i') = LONG, 102 S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG, 103 S('c') = INT, S('s') = PTR, S('n') = PTR, 104 S('l') = LLPRE, 105 }, { /* 2: ll-prefixed */ 106 S('d') = LLONG, S('i') = LLONG, 107 S('o') = ULLONG, S('u') = ULLONG, 108 S('x') = ULLONG, S('X') = ULLONG, 109 S('n') = PTR, 110 }, { /* 3: h-prefixed */ 111 S('d') = SHORT, S('i') = SHORT, 112 S('o') = USHORT, S('u') = USHORT, 113 S('x') = USHORT, S('X') = USHORT, 114 S('n') = PTR, 115 S('h') = HHPRE, 116 }, { /* 4: hh-prefixed */ 117 S('d') = CHAR, S('i') = CHAR, 118 S('o') = UCHAR, S('u') = UCHAR, 119 S('x') = UCHAR, S('X') = UCHAR, 120 S('n') = PTR, 121 }, { /* 5: L-prefixed */ 122 S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL, 123 S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL, 124 S('n') = PTR, 125 }, { /* 6: z- or t-prefixed (assumed to be same size) */ 126 S('d') = PDIFF, S('i') = PDIFF, 127 S('o') = SIZET, S('u') = SIZET, 128 S('x') = SIZET, S('X') = SIZET, 129 S('n') = PTR, 130 }, { /* 7: j-prefixed */ 131 S('d') = IMAX, S('i') = IMAX, 132 S('o') = UMAX, S('u') = UMAX, 133 S('x') = UMAX, S('X') = UMAX, 134 S('n') = PTR, 135 } 136 }; 137 138 #define OOB(x) ((unsigned)(x)-'A' > 'z'-'A') 139 140 union arg 141 { 142 uintmax_t i; 143 long double f; 144 void *p; 145 }; 146 147 static void pop_arg(union arg *arg, int type, va_list *ap) 148 { 149 /* Give the compiler a hint for optimizing the switch. */ 150 if ((unsigned)type > MAXSTATE) return; 151 switch (type) { 152 case PTR: arg->p = va_arg(*ap, void *); 153 break; case INT: arg->i = va_arg(*ap, int); 154 break; case UINT: arg->i = va_arg(*ap, unsigned int); 155 #ifndef LONG_IS_INT 156 break; case LONG: arg->i = va_arg(*ap, long); 157 break; case ULONG: arg->i = va_arg(*ap, unsigned long); 158 #endif 159 break; case ULLONG: arg->i = va_arg(*ap, unsigned long long); 160 break; case SHORT: arg->i = (short)va_arg(*ap, int); 161 break; case USHORT: arg->i = (unsigned short)va_arg(*ap, int); 162 break; case CHAR: arg->i = (signed char)va_arg(*ap, int); 163 break; case UCHAR: arg->i = (unsigned char)va_arg(*ap, int); 164 #ifdef ODD_TYPES 165 break; case LLONG: arg->i = va_arg(*ap, long long); 166 break; case SIZET: arg->i = va_arg(*ap, size_t); 167 break; case IMAX: arg->i = va_arg(*ap, intmax_t); 168 break; case UMAX: arg->i = va_arg(*ap, uintmax_t); 169 break; case PDIFF: arg->i = va_arg(*ap, ptrdiff_t); 170 break; case UIPTR: arg->i = (uintptr_t)va_arg(*ap, void *); 171 #endif 172 break; case DBL: arg->f = va_arg(*ap, double); 173 break; case LDBL: arg->f = va_arg(*ap, long double); 174 } 175 } 176 177 static void out(FILE *f, const wchar_t *s, size_t l) 178 { 179 #if defined(__ANDROID__) 180 fake_file_outw(f, s, l); 181 #else 182 while (l--) fputwc(*s++, f); 183 #endif 184 } 185 186 static int getint(wchar_t **s) { 187 int i; 188 for (i=0; iswdigit(**s); (*s)++) 189 i = 10*i + (**s-'0'); 190 return i; 191 } 192 193 static const char sizeprefix['y'-'a'] = { 194 ['a'-'a']='L', ['e'-'a']='L', ['f'-'a']='L', ['g'-'a']='L', 195 ['d'-'a']='j', ['i'-'a']='j', ['o'-'a']='j', ['u'-'a']='j', ['x'-'a']='j', 196 ['p'-'a']='j' 197 }; 198 199 static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_arg, int *nl_type) 200 { 201 wchar_t *a, *z, *s=(wchar_t *)fmt, *s0; 202 unsigned l10n=0, litpct, fl; 203 int w, p; 204 union arg arg; 205 int argpos; 206 unsigned st, ps; 207 int cnt=0, l=0; 208 int i; 209 int t; 210 char *bs; 211 char charfmt[16]; 212 wchar_t wc; 213 214 for (;;) { 215 /* Update output count, end loop when fmt is exhausted */ 216 if (cnt >= 0) { 217 if (l > INT_MAX - cnt) { 218 if (!ferror(f)) errno = EOVERFLOW; 219 cnt = -1; 220 } else cnt += l; 221 } 222 if (!*s) break; 223 224 /* Handle literal text and %% format specifiers */ 225 for (a=s; *s && *s!='%'; s++); 226 litpct = wcsspn(s, L"%")/2; /* Optimize %%%% runs */ 227 z = s+litpct; 228 s += 2*litpct; 229 l = z-a; 230 if (f) out(f, a, l); 231 if (l) continue; 232 233 if (iswdigit(s[1]) && s[2]=='$') { 234 l10n=1; 235 argpos = s[1]-'0'; 236 s+=3; 237 } else { 238 argpos = -1; 239 s++; 240 } 241 242 /* Read modifier flags */ 243 for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++) 244 fl |= 1U<<*s-' '; 245 246 /* Read field width */ 247 if (*s=='*') { 248 if (iswdigit(s[1]) && s[2]=='$') { 249 l10n=1; 250 nl_type[s[1]-'0'] = INT; 251 w = nl_arg[s[1]-'0'].i; 252 s+=3; 253 } else if (!l10n) { 254 w = f ? va_arg(*ap, int) : 0; 255 s++; 256 } else return -1; 257 if (w<0) fl|=LEFT_ADJ, w=-w; 258 } else if ((w=getint(&s))<0) return -1; 259 260 /* Read precision */ 261 if (*s=='.' && s[1]=='*') { 262 if (isdigit(s[2]) && s[3]=='$') { 263 nl_type[s[2]-'0'] = INT; 264 p = nl_arg[s[2]-'0'].i; 265 s+=4; 266 } else if (!l10n) { 267 p = f ? va_arg(*ap, int) : 0; 268 s+=2; 269 } else return -1; 270 } else if (*s=='.') { 271 s++; 272 p = getint(&s); 273 } else p = -1; 274 275 /* Format specifier state machine */ 276 s0=s; 277 st=0; 278 do { 279 if (OOB(*s)) return -1; 280 ps=st; 281 st=states[st]S(*s++); 282 } while (st-1<STOP); 283 if (!st) return -1; 284 285 /* Check validity of argument type (nl/normal) */ 286 if (st==NOARG) { 287 if (argpos>=0) return -1; 288 else if (!f) continue; 289 } else { 290 if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos]; 291 else if (f) pop_arg(&arg, st, ap); 292 else return 0; 293 } 294 295 if (!f) continue; 296 t = s[-1]; 297 if (ps && (t&15)==3) t&=~32; 298 299 switch (t) { 300 case 'n': 301 #ifndef __ANDROID__ /* Disabled on Android for security reasons. */ 302 switch(ps) { 303 case BARE: *(int *)arg.p = cnt; break; 304 case LPRE: *(long *)arg.p = cnt; break; 305 case LLPRE: *(long long *)arg.p = cnt; break; 306 case HPRE: *(unsigned short *)arg.p = cnt; break; 307 case HHPRE: *(unsigned char *)arg.p = cnt; break; 308 case ZTPRE: *(size_t *)arg.p = cnt; break; 309 case JPRE: *(uintmax_t *)arg.p = cnt; break; 310 } 311 #endif /* !__ANDROID__ */ 312 continue; 313 case 'c': 314 fputwc(btowc(arg.i), f); 315 l = 1; 316 continue; 317 case 'C': 318 fputwc(arg.i, f); 319 l = 1; 320 continue; 321 case 'S': 322 a = arg.p; 323 z = wmemchr(a, 0, p); 324 if (!z) z=a+p; 325 else p=z-a; 326 if (w<p) w=p; 327 if (!(fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, ""); 328 out(f, a, p); 329 if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, ""); 330 l=w; 331 continue; 332 case 's': 333 bs = arg.p; 334 if (p<0) p = INT_MAX; 335 for (i=l=0; l<p && (i=mbtowc(&wc, bs, MB_LEN_MAX))>0; bs+=i, l++); 336 if (i<0) return -1; 337 p=l; 338 if (w<p) w=p; 339 if (!(fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, ""); 340 bs = arg.p; 341 while (l--) { 342 i=mbtowc(&wc, bs, MB_LEN_MAX); 343 bs+=i; 344 fputwc(wc, f); 345 } 346 if ((fl&LEFT_ADJ)) fprintf(f, "%.*s", w-p, ""); 347 l=w; 348 continue; 349 } 350 351 snprintf(charfmt, sizeof charfmt, "%%%s%s%s%s%s*.*%c%c", 352 "#"+!(fl & ALT_FORM), 353 "+"+!(fl & MARK_POS), 354 "-"+!(fl & LEFT_ADJ), 355 " "+!(fl & PAD_POS), 356 "0"+!(fl & ZERO_PAD), 357 sizeprefix[(t|32)-'a'], t); 358 359 switch (t|32) { 360 case 'a': case 'e': case 'f': case 'g': 361 l = fprintf(f, charfmt, w, p, arg.f); 362 break; 363 case 'd': case 'i': case 'o': case 'u': case 'x': case 'p': 364 l = fprintf(f, charfmt, w, p, arg.i); 365 break; 366 } 367 } 368 369 if (f) return cnt; 370 if (!l10n) return 0; 371 372 for (i=1; i<=NL_ARGMAX && nl_type[i]; i++) 373 pop_arg(nl_arg+i, nl_type[i], ap); 374 for (; i<=NL_ARGMAX && !nl_type[i]; i++); 375 if (i<=NL_ARGMAX) return -1; 376 return 1; 377 } 378 379 #ifdef __ANDROID__ 380 #undef FILE /* no longer needed */ 381 int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap) 382 { 383 va_list ap2; 384 int nl_type[NL_ARGMAX] = {0}; 385 union arg nl_arg[NL_ARGMAX]; 386 int ret; 387 FakeFILE out[1]; 388 fake_file_init_file(out, f); 389 va_copy(ap2, ap); 390 // Check for error in format string before writing anything to file. 391 if (wprintf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) { 392 va_end(ap2); 393 return -1; 394 } 395 ret = wprintf_core(out, fmt, &ap2, nl_arg, nl_type); 396 va_end(ap2); 397 return ret; 398 } 399 400 int vswprintf(wchar_t *restrict s, size_t l, const wchar_t *restrict fmt, va_list ap) 401 { 402 va_list ap2; 403 int nl_type[NL_ARGMAX] = {0}; 404 union arg nl_arg[NL_ARGMAX]; 405 int ret; 406 FakeFILE out[1]; 407 fake_file_init_wbuffer(out, s, l); 408 va_copy(ap2, ap); 409 ret = wprintf_core(out, fmt, &ap2, nl_arg, nl_type); 410 va_end(ap2); 411 if (fake_feof(out)) return -1; 412 return ret; 413 } 414 #else /* !__ANDROID__ */ 415 int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap) 416 { 417 va_list ap2; 418 int nl_type[NL_ARGMAX] = {0}; 419 union arg nl_arg[NL_ARGMAX]; 420 int ret; 421 422 va_copy(ap2, ap); 423 if (wprintf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) return -1; 424 425 FLOCK(f); 426 ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type); 427 FUNLOCK(f); 428 va_end(ap2); 429 return ret; 430 } 431 #endif /* !__ANDROID__ */ 432