github.com/afumu/libc@v0.0.6/musl/src/stdio/vfprintf.c (about)

     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  /* Some useful macros */
    15  
    16  #define MAX(a,b) ((a)>(b) ? (a) : (b))
    17  #define MIN(a,b) ((a)<(b) ? (a) : (b))
    18  
    19  /* Convenient bit representation for modifier flags, which all fall
    20   * within 31 codepoints of the space character. */
    21  
    22  #define ALT_FORM   (1U<<'#'-' ')
    23  #define ZERO_PAD   (1U<<'0'-' ')
    24  #define LEFT_ADJ   (1U<<'-'-' ')
    25  #define PAD_POS    (1U<<' '-' ')
    26  #define MARK_POS   (1U<<'+'-' ')
    27  #define GROUPED    (1U<<'\''-' ')
    28  
    29  #define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
    30  
    31  /* State machine to accept length modifiers + conversion specifiers.
    32   * Result is 0 on failure, or an argument type to pop on success. */
    33  
    34  enum {
    35  	BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
    36  	ZTPRE, JPRE,
    37  	STOP,
    38  	PTR, INT, UINT, ULLONG,
    39  	LONG, ULONG,
    40  	SHORT, USHORT, CHAR, UCHAR,
    41  	LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
    42  	DBL, LDBL,
    43  	NOARG,
    44  	MAXSTATE
    45  };
    46  
    47  #define S(x) [(x)-'A']
    48  
    49  static const unsigned char states[]['z'-'A'+1] = {
    50  	{ /* 0: bare types */
    51  		S('d') = INT, S('i') = INT,
    52  		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
    53  		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
    54  		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
    55  		S('c') = CHAR, S('C') = INT,
    56  		S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
    57  		S('m') = NOARG,
    58  		S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
    59  		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
    60  	}, { /* 1: l-prefixed */
    61  		S('d') = LONG, S('i') = LONG,
    62  		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
    63  		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
    64  		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
    65  		S('c') = INT, S('s') = PTR, S('n') = PTR,
    66  		S('l') = LLPRE,
    67  	}, { /* 2: ll-prefixed */
    68  		S('d') = LLONG, S('i') = LLONG,
    69  		S('o') = ULLONG, S('u') = ULLONG,
    70  		S('x') = ULLONG, S('X') = ULLONG,
    71  		S('n') = PTR,
    72  	}, { /* 3: h-prefixed */
    73  		S('d') = SHORT, S('i') = SHORT,
    74  		S('o') = USHORT, S('u') = USHORT,
    75  		S('x') = USHORT, S('X') = USHORT,
    76  		S('n') = PTR,
    77  		S('h') = HHPRE,
    78  	}, { /* 4: hh-prefixed */
    79  		S('d') = CHAR, S('i') = CHAR,
    80  		S('o') = UCHAR, S('u') = UCHAR,
    81  		S('x') = UCHAR, S('X') = UCHAR,
    82  		S('n') = PTR,
    83  	}, { /* 5: L-prefixed */
    84  		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
    85  		S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
    86  		S('n') = PTR,
    87  	}, { /* 6: z- or t-prefixed (assumed to be same size) */
    88  		S('d') = PDIFF, S('i') = PDIFF,
    89  		S('o') = SIZET, S('u') = SIZET,
    90  		S('x') = SIZET, S('X') = SIZET,
    91  		S('n') = PTR,
    92  	}, { /* 7: j-prefixed */
    93  		S('d') = IMAX, S('i') = IMAX,
    94  		S('o') = UMAX, S('u') = UMAX,
    95  		S('x') = UMAX, S('X') = UMAX,
    96  		S('n') = PTR,
    97  	}
    98  };
    99  
   100  #define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
   101  
   102  union arg
   103  {
   104  	uintmax_t i;
   105  	long double f;
   106  	void *p;
   107  };
   108  
   109  static void pop_arg(union arg *arg, int type, va_list *ap)
   110  {
   111  	switch (type) {
   112  	       case PTR:	arg->p = va_arg(*ap, void *);
   113  	break; case INT:	arg->i = va_arg(*ap, int);
   114  	break; case UINT:	arg->i = va_arg(*ap, unsigned int);
   115  	break; case LONG:	arg->i = va_arg(*ap, long);
   116  	break; case ULONG:	arg->i = va_arg(*ap, unsigned long);
   117  	break; case ULLONG:	arg->i = va_arg(*ap, unsigned long long);
   118  	break; case SHORT:	arg->i = (short)va_arg(*ap, int);
   119  	break; case USHORT:	arg->i = (unsigned short)va_arg(*ap, int);
   120  	break; case CHAR:	arg->i = (signed char)va_arg(*ap, int);
   121  	break; case UCHAR:	arg->i = (unsigned char)va_arg(*ap, int);
   122  	break; case LLONG:	arg->i = va_arg(*ap, long long);
   123  	break; case SIZET:	arg->i = va_arg(*ap, size_t);
   124  	break; case IMAX:	arg->i = va_arg(*ap, intmax_t);
   125  	break; case UMAX:	arg->i = va_arg(*ap, uintmax_t);
   126  	break; case PDIFF:	arg->i = va_arg(*ap, ptrdiff_t);
   127  	break; case UIPTR:	arg->i = (uintptr_t)va_arg(*ap, void *);
   128  	break; case DBL:	arg->f = va_arg(*ap, double);
   129  	break; case LDBL:	arg->f = va_arg(*ap, long double);
   130  	}
   131  }
   132  
   133  static void out(FILE *f, const char *s, size_t l)
   134  {
   135  	if (!(f->flags & F_ERR)) __fwritex((void *)s, l, f);
   136  }
   137  
   138  static void pad(FILE *f, char c, int w, int l, int fl)
   139  {
   140  	char pad[256];
   141  	if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
   142  	l = w - l;
   143  	memset(pad, c, l>sizeof pad ? sizeof pad : l);
   144  	for (; l >= sizeof pad; l -= sizeof pad)
   145  		out(f, pad, sizeof pad);
   146  	out(f, pad, l);
   147  }
   148  
   149  static const char xdigits[16] = {
   150  	"0123456789ABCDEF"
   151  };
   152  
   153  static char *fmt_x(uintmax_t x, char *s, int lower)
   154  {
   155  	for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
   156  	return s;
   157  }
   158  
   159  static char *fmt_o(uintmax_t x, char *s)
   160  {
   161  	for (; x; x>>=3) *--s = '0' + (x&7);
   162  	return s;
   163  }
   164  
   165  static char *fmt_u(uintmax_t x, char *s)
   166  {
   167  	unsigned long y;
   168  	for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
   169  	for (y=x;           y; y/=10) *--s = '0' + y%10;
   170  	return s;
   171  }
   172  
   173  /* Do not override this check. The floating point printing code below
   174   * depends on the float.h constants being right. If they are wrong, it
   175   * may overflow the stack. */
   176  #if LDBL_MANT_DIG == 53
   177  typedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
   178  #endif
   179  
   180  static int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
   181  {
   182  	uint32_t big[(LDBL_MANT_DIG+28)/29 + 1          // mantissa expansion
   183  		+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
   184  	uint32_t *a, *d, *r, *z;
   185  	int e2=0, e, i, j, l;
   186  	char buf[9+LDBL_MANT_DIG/4], *s;
   187  	const char *prefix="-0X+0X 0X-0x+0x 0x";
   188  	int pl;
   189  	char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
   190  
   191  	pl=1;
   192  	if (signbit(y)) {
   193  		y=-y;
   194  	} else if (fl & MARK_POS) {
   195  		prefix+=3;
   196  	} else if (fl & PAD_POS) {
   197  		prefix+=6;
   198  	} else prefix++, pl=0;
   199  
   200  	if (!isfinite(y)) {
   201  		char *s = (t&32)?"inf":"INF";
   202  		if (y!=y) s=(t&32)?"nan":"NAN";
   203  		pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
   204  		out(f, prefix, pl);
   205  		out(f, s, 3);
   206  		pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
   207  		return MAX(w, 3+pl);
   208  	}
   209  
   210  	y = frexpl(y, &e2) * 2;
   211  	if (y) e2--;
   212  
   213  	if ((t|32)=='a') {
   214  		long double round = 8.0;
   215  		int re;
   216  
   217  		if (t&32) prefix += 9;
   218  		pl += 2;
   219  
   220  		if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
   221  		else re=LDBL_MANT_DIG/4-1-p;
   222  
   223  		if (re) {
   224  			round *= 1<<(LDBL_MANT_DIG%4);
   225  			while (re--) round*=16;
   226  			if (*prefix=='-') {
   227  				y=-y;
   228  				y-=round;
   229  				y+=round;
   230  				y=-y;
   231  			} else {
   232  				y+=round;
   233  				y-=round;
   234  			}
   235  		}
   236  
   237  		estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
   238  		if (estr==ebuf) *--estr='0';
   239  		*--estr = (e2<0 ? '-' : '+');
   240  		*--estr = t+('p'-'a');
   241  
   242  		s=buf;
   243  		do {
   244  			int x=y;
   245  			*s++=xdigits[x]|(t&32);
   246  			y=16*(y-x);
   247  			if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
   248  		} while (y);
   249  
   250  		if (p > INT_MAX-2-(ebuf-estr)-pl)
   251  			return -1;
   252  		if (p && s-buf-2 < p)
   253  			l = (p+2) + (ebuf-estr);
   254  		else
   255  			l = (s-buf) + (ebuf-estr);
   256  
   257  		pad(f, ' ', w, pl+l, fl);
   258  		out(f, prefix, pl);
   259  		pad(f, '0', w, pl+l, fl^ZERO_PAD);
   260  		out(f, buf, s-buf);
   261  		pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
   262  		out(f, estr, ebuf-estr);
   263  		pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
   264  		return MAX(w, pl+l);
   265  	}
   266  	if (p<0) p=6;
   267  
   268  	if (y) y *= 0x1p28, e2-=28;
   269  
   270  	if (e2<0) a=r=z=big;
   271  	else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
   272  
   273  	do {
   274  		*z = y;
   275  		y = 1000000000*(y-*z++);
   276  	} while (y);
   277  
   278  	while (e2>0) {
   279  		uint32_t carry=0;
   280  		int sh=MIN(29,e2);
   281  		for (d=z-1; d>=a; d--) {
   282  			uint64_t x = ((uint64_t)*d<<sh)+carry;
   283  			*d = x % 1000000000;
   284  			carry = x / 1000000000;
   285  		}
   286  		if (carry) *--a = carry;
   287  		while (z>a && !z[-1]) z--;
   288  		e2-=sh;
   289  	}
   290  	while (e2<0) {
   291  		uint32_t carry=0, *b;
   292  		int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9;
   293  		for (d=a; d<z; d++) {
   294  			uint32_t rm = *d & (1<<sh)-1;
   295  			*d = (*d>>sh) + carry;
   296  			carry = (1000000000>>sh) * rm;
   297  		}
   298  		if (!*a) a++;
   299  		if (carry) *z++ = carry;
   300  		/* Avoid (slow!) computation past requested precision */
   301  		b = (t|32)=='f' ? r : a;
   302  		if (z-b > need) z = b+need;
   303  		e2+=sh;
   304  	}
   305  
   306  	if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
   307  	else e=0;
   308  
   309  	/* Perform rounding: j is precision after the radix (possibly neg) */
   310  	j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
   311  	if (j < 9*(z-r-1)) {
   312  		uint32_t x;
   313  		/* We avoid C's broken division of negative numbers */
   314  		d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP);
   315  		j += 9*LDBL_MAX_EXP;
   316  		j %= 9;
   317  		for (i=10, j++; j<9; i*=10, j++);
   318  		x = *d % i;
   319  		/* Are there any significant digits past j? */
   320  		if (x || d+1!=z) {
   321  			long double round = 2/LDBL_EPSILON;
   322  			long double small;
   323  			if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1)))
   324  				round += 2;
   325  			if (x<i/2) small=0x0.8p0;
   326  			else if (x==i/2 && d+1==z) small=0x1.0p0;
   327  			else small=0x1.8p0;
   328  			if (pl && *prefix=='-') round*=-1, small*=-1;
   329  			*d -= x;
   330  			/* Decide whether to round by probing round+small */
   331  			if (round+small != round) {
   332  				*d = *d + i;
   333  				while (*d > 999999999) {
   334  					*d--=0;
   335  					if (d<a) *--a=0;
   336  					(*d)++;
   337  				}
   338  				for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
   339  			}
   340  		}
   341  		if (z>d+1) z=d+1;
   342  	}
   343  	for (; z>a && !z[-1]; z--);
   344  	
   345  	if ((t|32)=='g') {
   346  		if (!p) p++;
   347  		if (p>e && e>=-4) {
   348  			t--;
   349  			p-=e+1;
   350  		} else {
   351  			t-=2;
   352  			p--;
   353  		}
   354  		if (!(fl&ALT_FORM)) {
   355  			/* Count trailing zeros in last place */
   356  			if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
   357  			else j=9;
   358  			if ((t|32)=='f')
   359  				p = MIN(p,MAX(0,9*(z-r-1)-j));
   360  			else
   361  				p = MIN(p,MAX(0,9*(z-r-1)+e-j));
   362  		}
   363  	}
   364  	if (p > INT_MAX-1-(p || (fl&ALT_FORM)))
   365  		return -1;
   366  	l = 1 + p + (p || (fl&ALT_FORM));
   367  	if ((t|32)=='f') {
   368  		if (e > INT_MAX-l) return -1;
   369  		if (e>0) l+=e;
   370  	} else {
   371  		estr=fmt_u(e<0 ? -e : e, ebuf);
   372  		while(ebuf-estr<2) *--estr='0';
   373  		*--estr = (e<0 ? '-' : '+');
   374  		*--estr = t;
   375  		if (ebuf-estr > INT_MAX-l) return -1;
   376  		l += ebuf-estr;
   377  	}
   378  
   379  	if (l > INT_MAX-pl) return -1;
   380  	pad(f, ' ', w, pl+l, fl);
   381  	out(f, prefix, pl);
   382  	pad(f, '0', w, pl+l, fl^ZERO_PAD);
   383  
   384  	if ((t|32)=='f') {
   385  		if (a>r) a=r;
   386  		for (d=a; d<=r; d++) {
   387  			char *s = fmt_u(*d, buf+9);
   388  			if (d!=a) while (s>buf) *--s='0';
   389  			else if (s==buf+9) *--s='0';
   390  			out(f, s, buf+9-s);
   391  		}
   392  		if (p || (fl&ALT_FORM)) out(f, ".", 1);
   393  		for (; d<z && p>0; d++, p-=9) {
   394  			char *s = fmt_u(*d, buf+9);
   395  			while (s>buf) *--s='0';
   396  			out(f, s, MIN(9,p));
   397  		}
   398  		pad(f, '0', p+9, 9, 0);
   399  	} else {
   400  		if (z<=a) z=a+1;
   401  		for (d=a; d<z && p>=0; d++) {
   402  			char *s = fmt_u(*d, buf+9);
   403  			if (s==buf+9) *--s='0';
   404  			if (d!=a) while (s>buf) *--s='0';
   405  			else {
   406  				out(f, s++, 1);
   407  				if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
   408  			}
   409  			out(f, s, MIN(buf+9-s, p));
   410  			p -= buf+9-s;
   411  		}
   412  		pad(f, '0', p+18, 18, 0);
   413  		out(f, estr, ebuf-estr);
   414  	}
   415  
   416  	pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
   417  
   418  	return MAX(w, pl+l);
   419  }
   420  
   421  static int getint(char **s) {
   422  	int i;
   423  	for (i=0; isdigit(**s); (*s)++) {
   424  		if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
   425  		else i = 10*i + (**s-'0');
   426  	}
   427  	return i;
   428  }
   429  
   430  static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type)
   431  {
   432  	char *a, *z, *s=(char *)fmt;
   433  	unsigned l10n=0, fl;
   434  	int w, p, xp;
   435  	union arg arg;
   436  	int argpos;
   437  	unsigned st, ps;
   438  	int cnt=0, l=0;
   439  	size_t i;
   440  	char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
   441  	const char *prefix;
   442  	int t, pl;
   443  	wchar_t wc[2], *ws;
   444  	char mb[4];
   445  
   446  	for (;;) {
   447  		/* This error is only specified for snprintf, but since it's
   448  		 * unspecified for other forms, do the same. Stop immediately
   449  		 * on overflow; otherwise %n could produce wrong results. */
   450  		if (l > INT_MAX - cnt) goto overflow;
   451  
   452  		/* Update output count, end loop when fmt is exhausted */
   453  		cnt += l;
   454  		if (!*s) break;
   455  
   456  		/* Handle literal text and %% format specifiers */
   457  		for (a=s; *s && *s!='%'; s++);
   458  		for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
   459  		if (z-a > INT_MAX-cnt) goto overflow;
   460  		l = z-a;
   461  		if (f) out(f, a, l);
   462  		if (l) continue;
   463  
   464  		if (isdigit(s[1]) && s[2]=='$') {
   465  			l10n=1;
   466  			argpos = s[1]-'0';
   467  			s+=3;
   468  		} else {
   469  			argpos = -1;
   470  			s++;
   471  		}
   472  
   473  		/* Read modifier flags */
   474  		for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
   475  			fl |= 1U<<*s-' ';
   476  
   477  		/* Read field width */
   478  		if (*s=='*') {
   479  			if (isdigit(s[1]) && s[2]=='$') {
   480  				l10n=1;
   481  				nl_type[s[1]-'0'] = INT;
   482  				w = nl_arg[s[1]-'0'].i;
   483  				s+=3;
   484  			} else if (!l10n) {
   485  				w = f ? va_arg(*ap, int) : 0;
   486  				s++;
   487  			} else goto inval;
   488  			if (w<0) fl|=LEFT_ADJ, w=-w;
   489  		} else if ((w=getint(&s))<0) goto overflow;
   490  
   491  		/* Read precision */
   492  		if (*s=='.' && s[1]=='*') {
   493  			if (isdigit(s[2]) && s[3]=='$') {
   494  				nl_type[s[2]-'0'] = INT;
   495  				p = nl_arg[s[2]-'0'].i;
   496  				s+=4;
   497  			} else if (!l10n) {
   498  				p = f ? va_arg(*ap, int) : 0;
   499  				s+=2;
   500  			} else goto inval;
   501  			xp = (p>=0);
   502  		} else if (*s=='.') {
   503  			s++;
   504  			p = getint(&s);
   505  			xp = 1;
   506  		} else {
   507  			p = -1;
   508  			xp = 0;
   509  		}
   510  
   511  		/* Format specifier state machine */
   512  		st=0;
   513  		do {
   514  			if (OOB(*s)) goto inval;
   515  			ps=st;
   516  			st=states[st]S(*s++);
   517  		} while (st-1<STOP);
   518  		if (!st) goto inval;
   519  
   520  		/* Check validity of argument type (nl/normal) */
   521  		if (st==NOARG) {
   522  			if (argpos>=0) goto inval;
   523  		} else {
   524  			if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
   525  			else if (f) pop_arg(&arg, st, ap);
   526  			else return 0;
   527  		}
   528  
   529  		if (!f) continue;
   530  
   531  		z = buf + sizeof(buf);
   532  		prefix = "-+   0X0x";
   533  		pl = 0;
   534  		t = s[-1];
   535  
   536  		/* Transform ls,lc -> S,C */
   537  		if (ps && (t&15)==3) t&=~32;
   538  
   539  		/* - and 0 flags are mutually exclusive */
   540  		if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
   541  
   542  		switch(t) {
   543  		case 'n':
   544  			switch(ps) {
   545  			case BARE: *(int *)arg.p = cnt; break;
   546  			case LPRE: *(long *)arg.p = cnt; break;
   547  			case LLPRE: *(long long *)arg.p = cnt; break;
   548  			case HPRE: *(unsigned short *)arg.p = cnt; break;
   549  			case HHPRE: *(unsigned char *)arg.p = cnt; break;
   550  			case ZTPRE: *(size_t *)arg.p = cnt; break;
   551  			case JPRE: *(uintmax_t *)arg.p = cnt; break;
   552  			}
   553  			continue;
   554  		case 'p':
   555  			p = MAX(p, 2*sizeof(void*));
   556  			t = 'x';
   557  			fl |= ALT_FORM;
   558  		case 'x': case 'X':
   559  			a = fmt_x(arg.i, z, t&32);
   560  			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
   561  			if (0) {
   562  		case 'o':
   563  			a = fmt_o(arg.i, z);
   564  			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
   565  			} if (0) {
   566  		case 'd': case 'i':
   567  			pl=1;
   568  			if (arg.i>INTMAX_MAX) {
   569  				arg.i=-arg.i;
   570  			} else if (fl & MARK_POS) {
   571  				prefix++;
   572  			} else if (fl & PAD_POS) {
   573  				prefix+=2;
   574  			} else pl=0;
   575  		case 'u':
   576  			a = fmt_u(arg.i, z);
   577  			}
   578  			if (xp && p<0) goto overflow;
   579  			if (xp) fl &= ~ZERO_PAD;
   580  			if (!arg.i && !p) {
   581  				a=z;
   582  				break;
   583  			}
   584  			p = MAX(p, z-a + !arg.i);
   585  			break;
   586  		case 'c':
   587  			*(a=z-(p=1))=arg.i;
   588  			fl &= ~ZERO_PAD;
   589  			break;
   590  		case 'm':
   591  			if (1) a = strerror(errno); else
   592  		case 's':
   593  			a = arg.p ? arg.p : "(null)";
   594  			z = a + strnlen(a, p<0 ? INT_MAX : p);
   595  			if (p<0 && *z) goto overflow;
   596  			p = z-a;
   597  			fl &= ~ZERO_PAD;
   598  			break;
   599  		case 'C':
   600  			wc[0] = arg.i;
   601  			wc[1] = 0;
   602  			arg.p = wc;
   603  			p = -1;
   604  		case 'S':
   605  			ws = arg.p;
   606  			for (i=l=0; i<p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=p-i; i+=l);
   607  			if (l<0) return -1;
   608  			if (i > INT_MAX) goto overflow;
   609  			p = i;
   610  			pad(f, ' ', w, p, fl);
   611  			ws = arg.p;
   612  			for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
   613  				out(f, mb, l);
   614  			pad(f, ' ', w, p, fl^LEFT_ADJ);
   615  			l = w>p ? w : p;
   616  			continue;
   617  		case 'e': case 'f': case 'g': case 'a':
   618  		case 'E': case 'F': case 'G': case 'A':
   619  			if (xp && p<0) goto overflow;
   620  			l = fmt_fp(f, arg.f, w, p, fl, t);
   621  			if (l<0) goto overflow;
   622  			continue;
   623  		}
   624  
   625  		if (p < z-a) p = z-a;
   626  		if (p > INT_MAX-pl) goto overflow;
   627  		if (w < pl+p) w = pl+p;
   628  		if (w > INT_MAX-cnt) goto overflow;
   629  
   630  		pad(f, ' ', w, pl+p, fl);
   631  		out(f, prefix, pl);
   632  		pad(f, '0', w, pl+p, fl^ZERO_PAD);
   633  		pad(f, '0', p, z-a, 0);
   634  		out(f, a, z-a);
   635  		pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
   636  
   637  		l = w;
   638  	}
   639  
   640  	if (f) return cnt;
   641  	if (!l10n) return 0;
   642  
   643  	for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
   644  		pop_arg(nl_arg+i, nl_type[i], ap);
   645  	for (; i<=NL_ARGMAX && !nl_type[i]; i++);
   646  	if (i<=NL_ARGMAX) goto inval;
   647  	return 1;
   648  
   649  inval:
   650  	errno = EINVAL;
   651  	return -1;
   652  overflow:
   653  	errno = EOVERFLOW;
   654  	return -1;
   655  }
   656  
   657  int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
   658  {
   659  	va_list ap2;
   660  	int nl_type[NL_ARGMAX+1] = {0};
   661  	union arg nl_arg[NL_ARGMAX+1];
   662  	unsigned char internal_buf[80], *saved_buf = 0;
   663  	int olderr;
   664  	int ret;
   665  
   666  	/* the copy allows passing va_list* even if va_list is an array */
   667  	va_copy(ap2, ap);
   668  	if (printf_core(0, fmt, &ap2, nl_arg, nl_type) < 0) {
   669  		va_end(ap2);
   670  		return -1;
   671  	}
   672  
   673  	FLOCK(f);
   674  	olderr = f->flags & F_ERR;
   675  	if (f->mode < 1) f->flags &= ~F_ERR;
   676  	if (!f->buf_size) {
   677  		saved_buf = f->buf;
   678  		f->buf = internal_buf;
   679  		f->buf_size = sizeof internal_buf;
   680  		f->wpos = f->wbase = f->wend = 0;
   681  	}
   682  	if (!f->wend && __towrite(f)) ret = -1;
   683  	else ret = printf_core(f, fmt, &ap2, nl_arg, nl_type);
   684  	if (saved_buf) {
   685  		f->write(f, 0, 0);
   686  		if (!f->wpos) ret = -1;
   687  		f->buf = saved_buf;
   688  		f->buf_size = 0;
   689  		f->wpos = f->wbase = f->wend = 0;
   690  	}
   691  	if (f->flags & F_ERR) ret = -1;
   692  	f->flags |= olderr;
   693  	FUNLOCK(f);
   694  	va_end(ap2);
   695  	return ret;
   696  }