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 
     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