1570af302Sopenharmony_ci#include "stdio_impl.h"
2570af302Sopenharmony_ci#include <errno.h>
3570af302Sopenharmony_ci#include <ctype.h>
4570af302Sopenharmony_ci#include <limits.h>
5570af302Sopenharmony_ci#include <string.h>
6570af302Sopenharmony_ci#include <stdarg.h>
7570af302Sopenharmony_ci#include <stddef.h>
8570af302Sopenharmony_ci#include <stdlib.h>
9570af302Sopenharmony_ci#include <wchar.h>
10570af302Sopenharmony_ci#include <inttypes.h>
11570af302Sopenharmony_ci#include <math.h>
12570af302Sopenharmony_ci#include <float.h>
13570af302Sopenharmony_ci
14570af302Sopenharmony_ci/* Some useful macros */
15570af302Sopenharmony_ci
16570af302Sopenharmony_ci#define MAX(a,b) ((a)>(b) ? (a) : (b))
17570af302Sopenharmony_ci#define MIN(a,b) ((a)<(b) ? (a) : (b))
18570af302Sopenharmony_ci
19570af302Sopenharmony_ci/* Convenient bit representation for modifier flags, which all fall
20570af302Sopenharmony_ci * within 31 codepoints of the space character. */
21570af302Sopenharmony_ci
22570af302Sopenharmony_ci#define ALT_FORM   (1U<<'#'-' ')
23570af302Sopenharmony_ci#define ZERO_PAD   (1U<<'0'-' ')
24570af302Sopenharmony_ci#define LEFT_ADJ   (1U<<'-'-' ')
25570af302Sopenharmony_ci#define PAD_POS    (1U<<' '-' ')
26570af302Sopenharmony_ci#define MARK_POS   (1U<<'+'-' ')
27570af302Sopenharmony_ci#define GROUPED    (1U<<'\''-' ')
28570af302Sopenharmony_ci
29570af302Sopenharmony_ci#define FLAGMASK (ALT_FORM|ZERO_PAD|LEFT_ADJ|PAD_POS|MARK_POS|GROUPED)
30570af302Sopenharmony_ci
31570af302Sopenharmony_ci/* State machine to accept length modifiers + conversion specifiers.
32570af302Sopenharmony_ci * Result is 0 on failure, or an argument type to pop on success. */
33570af302Sopenharmony_ci
34570af302Sopenharmony_cienum {
35570af302Sopenharmony_ci	BARE, LPRE, LLPRE, HPRE, HHPRE, BIGLPRE,
36570af302Sopenharmony_ci	ZTPRE, JPRE,
37570af302Sopenharmony_ci	STOP,
38570af302Sopenharmony_ci	PTR, INT, UINT, ULLONG,
39570af302Sopenharmony_ci	LONG, ULONG,
40570af302Sopenharmony_ci	SHORT, USHORT, CHAR, UCHAR,
41570af302Sopenharmony_ci	LLONG, SIZET, IMAX, UMAX, PDIFF, UIPTR,
42570af302Sopenharmony_ci	DBL, LDBL,
43570af302Sopenharmony_ci	NOARG,
44570af302Sopenharmony_ci	MAXSTATE
45570af302Sopenharmony_ci};
46570af302Sopenharmony_ci
47570af302Sopenharmony_ci#define S(x) [(x)-'A']
48570af302Sopenharmony_ci
49570af302Sopenharmony_cistatic const unsigned char states[]['z'-'A'+1] = {
50570af302Sopenharmony_ci	{ /* 0: bare types */
51570af302Sopenharmony_ci		S('d') = INT, S('i') = INT,
52570af302Sopenharmony_ci		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
53570af302Sopenharmony_ci		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
54570af302Sopenharmony_ci		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
55570af302Sopenharmony_ci		S('c') = INT, S('C') = UINT,
56570af302Sopenharmony_ci		S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
57570af302Sopenharmony_ci		S('m') = NOARG,
58570af302Sopenharmony_ci		S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
59570af302Sopenharmony_ci		S('z') = ZTPRE, S('j') = JPRE, S('t') = ZTPRE,
60570af302Sopenharmony_ci	}, { /* 1: l-prefixed */
61570af302Sopenharmony_ci		S('d') = LONG, S('i') = LONG,
62570af302Sopenharmony_ci		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
63570af302Sopenharmony_ci		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
64570af302Sopenharmony_ci		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
65570af302Sopenharmony_ci		S('c') = UINT, S('s') = PTR, S('n') = PTR,
66570af302Sopenharmony_ci		S('l') = LLPRE,
67570af302Sopenharmony_ci	}, { /* 2: ll-prefixed */
68570af302Sopenharmony_ci		S('d') = LLONG, S('i') = LLONG,
69570af302Sopenharmony_ci		S('o') = ULLONG, S('u') = ULLONG,
70570af302Sopenharmony_ci		S('x') = ULLONG, S('X') = ULLONG,
71570af302Sopenharmony_ci		S('n') = PTR,
72570af302Sopenharmony_ci	}, { /* 3: h-prefixed */
73570af302Sopenharmony_ci		S('d') = SHORT, S('i') = SHORT,
74570af302Sopenharmony_ci		S('o') = USHORT, S('u') = USHORT,
75570af302Sopenharmony_ci		S('x') = USHORT, S('X') = USHORT,
76570af302Sopenharmony_ci		S('n') = PTR,
77570af302Sopenharmony_ci		S('h') = HHPRE,
78570af302Sopenharmony_ci	}, { /* 4: hh-prefixed */
79570af302Sopenharmony_ci		S('d') = CHAR, S('i') = CHAR,
80570af302Sopenharmony_ci		S('o') = UCHAR, S('u') = UCHAR,
81570af302Sopenharmony_ci		S('x') = UCHAR, S('X') = UCHAR,
82570af302Sopenharmony_ci		S('n') = PTR,
83570af302Sopenharmony_ci	}, { /* 5: L-prefixed */
84570af302Sopenharmony_ci		S('e') = LDBL, S('f') = LDBL, S('g') = LDBL, S('a') = LDBL,
85570af302Sopenharmony_ci		S('E') = LDBL, S('F') = LDBL, S('G') = LDBL, S('A') = LDBL,
86570af302Sopenharmony_ci		S('n') = PTR,
87570af302Sopenharmony_ci	}, { /* 6: z- or t-prefixed (assumed to be same size) */
88570af302Sopenharmony_ci		S('d') = PDIFF, S('i') = PDIFF,
89570af302Sopenharmony_ci		S('o') = SIZET, S('u') = SIZET,
90570af302Sopenharmony_ci		S('x') = SIZET, S('X') = SIZET,
91570af302Sopenharmony_ci		S('n') = PTR,
92570af302Sopenharmony_ci	}, { /* 7: j-prefixed */
93570af302Sopenharmony_ci		S('d') = IMAX, S('i') = IMAX,
94570af302Sopenharmony_ci		S('o') = UMAX, S('u') = UMAX,
95570af302Sopenharmony_ci		S('x') = UMAX, S('X') = UMAX,
96570af302Sopenharmony_ci		S('n') = PTR,
97570af302Sopenharmony_ci	}
98570af302Sopenharmony_ci};
99570af302Sopenharmony_ci
100570af302Sopenharmony_ci#define OOB(x) ((unsigned)(x)-'A' > 'z'-'A')
101570af302Sopenharmony_ci
102570af302Sopenharmony_ciunion arg
103570af302Sopenharmony_ci{
104570af302Sopenharmony_ci	uintmax_t i;
105570af302Sopenharmony_ci	long double f;
106570af302Sopenharmony_ci	void *p;
107570af302Sopenharmony_ci};
108570af302Sopenharmony_ci
109570af302Sopenharmony_cistatic void pop_arg(union arg *arg, int type, va_list *ap)
110570af302Sopenharmony_ci{
111570af302Sopenharmony_ci	switch (type) {
112570af302Sopenharmony_ci	       case PTR:	arg->p = va_arg(*ap, void *);
113570af302Sopenharmony_ci	break; case INT:	arg->i = va_arg(*ap, int);
114570af302Sopenharmony_ci	break; case UINT:	arg->i = va_arg(*ap, unsigned int);
115570af302Sopenharmony_ci	break; case LONG:	arg->i = va_arg(*ap, long);
116570af302Sopenharmony_ci	break; case ULONG:	arg->i = va_arg(*ap, unsigned long);
117570af302Sopenharmony_ci	break; case ULLONG:	arg->i = va_arg(*ap, unsigned long long);
118570af302Sopenharmony_ci	break; case SHORT:	arg->i = (short)va_arg(*ap, int);
119570af302Sopenharmony_ci	break; case USHORT:	arg->i = (unsigned short)va_arg(*ap, int);
120570af302Sopenharmony_ci	break; case CHAR:	arg->i = (signed char)va_arg(*ap, int);
121570af302Sopenharmony_ci	break; case UCHAR:	arg->i = (unsigned char)va_arg(*ap, int);
122570af302Sopenharmony_ci	break; case LLONG:	arg->i = va_arg(*ap, long long);
123570af302Sopenharmony_ci	break; case SIZET:	arg->i = va_arg(*ap, size_t);
124570af302Sopenharmony_ci	break; case IMAX:	arg->i = va_arg(*ap, intmax_t);
125570af302Sopenharmony_ci	break; case UMAX:	arg->i = va_arg(*ap, uintmax_t);
126570af302Sopenharmony_ci	break; case PDIFF:	arg->i = va_arg(*ap, ptrdiff_t);
127570af302Sopenharmony_ci	break; case UIPTR:	arg->i = (uintptr_t)va_arg(*ap, void *);
128570af302Sopenharmony_ci	break; case DBL:	arg->f = va_arg(*ap, double);
129570af302Sopenharmony_ci	break; case LDBL:	arg->f = va_arg(*ap, long double);
130570af302Sopenharmony_ci	}
131570af302Sopenharmony_ci}
132570af302Sopenharmony_ci
133570af302Sopenharmony_cistatic void out(FILE *f, const char *s, size_t l)
134570af302Sopenharmony_ci{
135570af302Sopenharmony_ci	if (!l) return;
136570af302Sopenharmony_ci
137570af302Sopenharmony_ci	/* write to file buffer if flag F_PBUF is available */
138570af302Sopenharmony_ci	if (!ferror(f) && !(f->flags & F_PBUF)) {
139570af302Sopenharmony_ci		__fwritex((void *)s, l, f);
140570af302Sopenharmony_ci		return;
141570af302Sopenharmony_ci	}
142570af302Sopenharmony_ci
143570af302Sopenharmony_ci	/* otherwise, copy to buffer directly */
144570af302Sopenharmony_ci	f->write(f, (void *)s, l);
145570af302Sopenharmony_ci}
146570af302Sopenharmony_ci
147570af302Sopenharmony_cistatic void pad(FILE *f, char c, int w, int l, int fl)
148570af302Sopenharmony_ci{
149570af302Sopenharmony_ci	char pad[16];
150570af302Sopenharmony_ci	if (fl & (LEFT_ADJ | ZERO_PAD) || l >= w) return;
151570af302Sopenharmony_ci	l = w - l;
152570af302Sopenharmony_ci	__builtin_memset(pad, c, sizeof pad);
153570af302Sopenharmony_ci	for (; l >= sizeof pad; l -= sizeof pad)
154570af302Sopenharmony_ci		out(f, pad, sizeof pad);
155570af302Sopenharmony_ci	out(f, pad, l);
156570af302Sopenharmony_ci}
157570af302Sopenharmony_ci
158570af302Sopenharmony_cistatic const char xdigits[16] = {
159570af302Sopenharmony_ci	"0123456789ABCDEF"
160570af302Sopenharmony_ci};
161570af302Sopenharmony_ci
162570af302Sopenharmony_cistatic char *fmt_x(uintmax_t x, char *s, int lower)
163570af302Sopenharmony_ci{
164570af302Sopenharmony_ci	for (; x; x>>=4) *--s = xdigits[(x&15)]|lower;
165570af302Sopenharmony_ci	return s;
166570af302Sopenharmony_ci}
167570af302Sopenharmony_ci
168570af302Sopenharmony_cistatic char *fmt_o(uintmax_t x, char *s)
169570af302Sopenharmony_ci{
170570af302Sopenharmony_ci	for (; x; x>>=3) *--s = '0' + (x&7);
171570af302Sopenharmony_ci	return s;
172570af302Sopenharmony_ci}
173570af302Sopenharmony_ci
174570af302Sopenharmony_cistatic char *fmt_u(uintmax_t x, char *s)
175570af302Sopenharmony_ci{
176570af302Sopenharmony_ci	unsigned long y;
177570af302Sopenharmony_ci	for (   ; x>ULONG_MAX; x/=10) *--s = '0' + x%10;
178570af302Sopenharmony_ci	for (y=x;           y; y/=10) *--s = '0' + y%10;
179570af302Sopenharmony_ci	return s;
180570af302Sopenharmony_ci}
181570af302Sopenharmony_ci
182570af302Sopenharmony_ci/* Do not override this check. The floating point printing code below
183570af302Sopenharmony_ci * depends on the float.h constants being right. If they are wrong, it
184570af302Sopenharmony_ci * may overflow the stack. */
185570af302Sopenharmony_ci#if LDBL_MANT_DIG == 53
186570af302Sopenharmony_citypedef char compiler_defines_long_double_incorrectly[9-(int)sizeof(long double)];
187570af302Sopenharmony_ci#endif
188570af302Sopenharmony_ci
189570af302Sopenharmony_cistatic int fmt_fp(FILE *f, long double y, int w, int p, int fl, int t)
190570af302Sopenharmony_ci{
191570af302Sopenharmony_ci	uint32_t big[(LDBL_MANT_DIG+28)/29 + 1          // mantissa expansion
192570af302Sopenharmony_ci		+ (LDBL_MAX_EXP+LDBL_MANT_DIG+28+8)/9]; // exponent expansion
193570af302Sopenharmony_ci	uint32_t *a, *d, *r, *z;
194570af302Sopenharmony_ci	int e2=0, e, i, j, l;
195570af302Sopenharmony_ci	char buf[9+LDBL_MANT_DIG/4], *s;
196570af302Sopenharmony_ci	const char *prefix="-0X+0X 0X-0x+0x 0x";
197570af302Sopenharmony_ci	int pl;
198570af302Sopenharmony_ci	char ebuf0[3*sizeof(int)], *ebuf=&ebuf0[3*sizeof(int)], *estr;
199570af302Sopenharmony_ci
200570af302Sopenharmony_ci	pl=1;
201570af302Sopenharmony_ci	if (signbit(y)) {
202570af302Sopenharmony_ci		y=-y;
203570af302Sopenharmony_ci	} else if (fl & MARK_POS) {
204570af302Sopenharmony_ci		prefix+=3;
205570af302Sopenharmony_ci	} else if (fl & PAD_POS) {
206570af302Sopenharmony_ci		prefix+=6;
207570af302Sopenharmony_ci	} else prefix++, pl=0;
208570af302Sopenharmony_ci
209570af302Sopenharmony_ci	if (!isfinite(y)) {
210570af302Sopenharmony_ci		char *s = (t&32)?"inf":"INF";
211570af302Sopenharmony_ci		if (y!=y) s=(t&32)?"nan":"NAN";
212570af302Sopenharmony_ci		pad(f, ' ', w, 3+pl, fl&~ZERO_PAD);
213570af302Sopenharmony_ci		out(f, prefix, pl);
214570af302Sopenharmony_ci		out(f, s, 3);
215570af302Sopenharmony_ci		pad(f, ' ', w, 3+pl, fl^LEFT_ADJ);
216570af302Sopenharmony_ci		return MAX(w, 3+pl);
217570af302Sopenharmony_ci	}
218570af302Sopenharmony_ci
219570af302Sopenharmony_ci	y = frexpl(y, &e2) * 2;
220570af302Sopenharmony_ci	if (y) e2--;
221570af302Sopenharmony_ci
222570af302Sopenharmony_ci	if ((t|32)=='a') {
223570af302Sopenharmony_ci		long double round = 8.0;
224570af302Sopenharmony_ci		int re;
225570af302Sopenharmony_ci
226570af302Sopenharmony_ci		if (t&32) prefix += 9;
227570af302Sopenharmony_ci		pl += 2;
228570af302Sopenharmony_ci
229570af302Sopenharmony_ci		if (p<0 || p>=LDBL_MANT_DIG/4-1) re=0;
230570af302Sopenharmony_ci		else re=LDBL_MANT_DIG/4-1-p;
231570af302Sopenharmony_ci
232570af302Sopenharmony_ci		if (re) {
233570af302Sopenharmony_ci			round *= 1<<(LDBL_MANT_DIG%4);
234570af302Sopenharmony_ci			while (re--) round*=16;
235570af302Sopenharmony_ci			if (*prefix=='-') {
236570af302Sopenharmony_ci				y=-y;
237570af302Sopenharmony_ci				y-=round;
238570af302Sopenharmony_ci				y+=round;
239570af302Sopenharmony_ci				y=-y;
240570af302Sopenharmony_ci			} else {
241570af302Sopenharmony_ci				y+=round;
242570af302Sopenharmony_ci				y-=round;
243570af302Sopenharmony_ci			}
244570af302Sopenharmony_ci		}
245570af302Sopenharmony_ci
246570af302Sopenharmony_ci		estr=fmt_u(e2<0 ? -e2 : e2, ebuf);
247570af302Sopenharmony_ci		if (estr==ebuf) *--estr='0';
248570af302Sopenharmony_ci		*--estr = (e2<0 ? '-' : '+');
249570af302Sopenharmony_ci		*--estr = t+('p'-'a');
250570af302Sopenharmony_ci
251570af302Sopenharmony_ci		s=buf;
252570af302Sopenharmony_ci		do {
253570af302Sopenharmony_ci			int x=y;
254570af302Sopenharmony_ci			*s++=xdigits[x]|(t&32);
255570af302Sopenharmony_ci			y=16*(y-x);
256570af302Sopenharmony_ci			if (s-buf==1 && (y||p>0||(fl&ALT_FORM))) *s++='.';
257570af302Sopenharmony_ci		} while (y);
258570af302Sopenharmony_ci
259570af302Sopenharmony_ci		if (p > INT_MAX-2-(ebuf-estr)-pl)
260570af302Sopenharmony_ci			return -1;
261570af302Sopenharmony_ci		if (p && s-buf-2 < p)
262570af302Sopenharmony_ci			l = (p+2) + (ebuf-estr);
263570af302Sopenharmony_ci		else
264570af302Sopenharmony_ci			l = (s-buf) + (ebuf-estr);
265570af302Sopenharmony_ci
266570af302Sopenharmony_ci		pad(f, ' ', w, pl+l, fl);
267570af302Sopenharmony_ci		out(f, prefix, pl);
268570af302Sopenharmony_ci		pad(f, '0', w, pl+l, fl^ZERO_PAD);
269570af302Sopenharmony_ci		out(f, buf, s-buf);
270570af302Sopenharmony_ci		pad(f, '0', l-(ebuf-estr)-(s-buf), 0, 0);
271570af302Sopenharmony_ci		out(f, estr, ebuf-estr);
272570af302Sopenharmony_ci		pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
273570af302Sopenharmony_ci		return MAX(w, pl+l);
274570af302Sopenharmony_ci	}
275570af302Sopenharmony_ci	if (p<0) p=6;
276570af302Sopenharmony_ci
277570af302Sopenharmony_ci	if (y) y *= 0x1p28, e2-=28;
278570af302Sopenharmony_ci
279570af302Sopenharmony_ci	if (e2<0) a=r=z=big;
280570af302Sopenharmony_ci	else a=r=z=big+sizeof(big)/sizeof(*big) - LDBL_MANT_DIG - 1;
281570af302Sopenharmony_ci
282570af302Sopenharmony_ci	do {
283570af302Sopenharmony_ci		*z = y;
284570af302Sopenharmony_ci		y = 1000000000*(y-*z++);
285570af302Sopenharmony_ci	} while (y);
286570af302Sopenharmony_ci
287570af302Sopenharmony_ci	while (e2>0) {
288570af302Sopenharmony_ci		uint32_t carry=0;
289570af302Sopenharmony_ci		int sh=MIN(29,e2);
290570af302Sopenharmony_ci		for (d=z-1; d>=a; d--) {
291570af302Sopenharmony_ci			uint64_t x = ((uint64_t)*d<<sh)+carry;
292570af302Sopenharmony_ci			*d = x % 1000000000;
293570af302Sopenharmony_ci			carry = x / 1000000000;
294570af302Sopenharmony_ci		}
295570af302Sopenharmony_ci		if (carry) *--a = carry;
296570af302Sopenharmony_ci		while (z>a && !z[-1]) z--;
297570af302Sopenharmony_ci		e2-=sh;
298570af302Sopenharmony_ci	}
299570af302Sopenharmony_ci	while (e2<0) {
300570af302Sopenharmony_ci		uint32_t carry=0, *b;
301570af302Sopenharmony_ci		int sh=MIN(9,-e2), need=1+(p+LDBL_MANT_DIG/3U+8)/9;
302570af302Sopenharmony_ci		for (d=a; d<z; d++) {
303570af302Sopenharmony_ci			uint32_t rm = *d & (1<<sh)-1;
304570af302Sopenharmony_ci			*d = (*d>>sh) + carry;
305570af302Sopenharmony_ci			carry = (1000000000>>sh) * rm;
306570af302Sopenharmony_ci		}
307570af302Sopenharmony_ci		if (!*a) a++;
308570af302Sopenharmony_ci		if (carry) *z++ = carry;
309570af302Sopenharmony_ci		/* Avoid (slow!) computation past requested precision */
310570af302Sopenharmony_ci		b = (t|32)=='f' ? r : a;
311570af302Sopenharmony_ci		if (z-b > need) z = b+need;
312570af302Sopenharmony_ci		e2+=sh;
313570af302Sopenharmony_ci	}
314570af302Sopenharmony_ci
315570af302Sopenharmony_ci	if (a<z) for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
316570af302Sopenharmony_ci	else e=0;
317570af302Sopenharmony_ci
318570af302Sopenharmony_ci	/* Perform rounding: j is precision after the radix (possibly neg) */
319570af302Sopenharmony_ci	j = p - ((t|32)!='f')*e - ((t|32)=='g' && p);
320570af302Sopenharmony_ci	if (j < 9*(z-r-1)) {
321570af302Sopenharmony_ci		uint32_t x;
322570af302Sopenharmony_ci		/* We avoid C's broken division of negative numbers */
323570af302Sopenharmony_ci		d = r + 1 + ((j+9*LDBL_MAX_EXP)/9 - LDBL_MAX_EXP);
324570af302Sopenharmony_ci		j += 9*LDBL_MAX_EXP;
325570af302Sopenharmony_ci		j %= 9;
326570af302Sopenharmony_ci		for (i=10, j++; j<9; i*=10, j++);
327570af302Sopenharmony_ci		x = *d % i;
328570af302Sopenharmony_ci		/* Are there any significant digits past j? */
329570af302Sopenharmony_ci		if (x || d+1!=z) {
330570af302Sopenharmony_ci			long double round = 2/LDBL_EPSILON;
331570af302Sopenharmony_ci			long double small;
332570af302Sopenharmony_ci			if ((*d/i & 1) || (i==1000000000 && d>a && (d[-1]&1)))
333570af302Sopenharmony_ci				round += 2;
334570af302Sopenharmony_ci			if (x<i/2) small=0x0.8p0;
335570af302Sopenharmony_ci			else if (x==i/2 && d+1==z) small=0x1.0p0;
336570af302Sopenharmony_ci			else small=0x1.8p0;
337570af302Sopenharmony_ci			if (pl && *prefix=='-') round*=-1, small*=-1;
338570af302Sopenharmony_ci			*d -= x;
339570af302Sopenharmony_ci			/* Decide whether to round by probing round+small */
340570af302Sopenharmony_ci			if (round+small != round) {
341570af302Sopenharmony_ci				*d = *d + i;
342570af302Sopenharmony_ci				while (*d > 999999999) {
343570af302Sopenharmony_ci					*d--=0;
344570af302Sopenharmony_ci					if (d<a) *--a=0;
345570af302Sopenharmony_ci					(*d)++;
346570af302Sopenharmony_ci				}
347570af302Sopenharmony_ci				for (i=10, e=9*(r-a); *a>=i; i*=10, e++);
348570af302Sopenharmony_ci			}
349570af302Sopenharmony_ci		}
350570af302Sopenharmony_ci		if (z>d+1) z=d+1;
351570af302Sopenharmony_ci	}
352570af302Sopenharmony_ci	for (; z>a && !z[-1]; z--);
353570af302Sopenharmony_ci
354570af302Sopenharmony_ci	if ((t|32)=='g') {
355570af302Sopenharmony_ci		if (!p) p++;
356570af302Sopenharmony_ci		if (p>e && e>=-4) {
357570af302Sopenharmony_ci			t--;
358570af302Sopenharmony_ci			p-=e+1;
359570af302Sopenharmony_ci		} else {
360570af302Sopenharmony_ci			t-=2;
361570af302Sopenharmony_ci			p--;
362570af302Sopenharmony_ci		}
363570af302Sopenharmony_ci		if (!(fl&ALT_FORM)) {
364570af302Sopenharmony_ci			/* Count trailing zeros in last place */
365570af302Sopenharmony_ci			if (z>a && z[-1]) for (i=10, j=0; z[-1]%i==0; i*=10, j++);
366570af302Sopenharmony_ci			else j=9;
367570af302Sopenharmony_ci			if ((t|32)=='f')
368570af302Sopenharmony_ci				p = MIN(p,MAX(0,9*(z-r-1)-j));
369570af302Sopenharmony_ci			else
370570af302Sopenharmony_ci				p = MIN(p,MAX(0,9*(z-r-1)+e-j));
371570af302Sopenharmony_ci		}
372570af302Sopenharmony_ci	}
373570af302Sopenharmony_ci	if (p > INT_MAX-1-(p || (fl&ALT_FORM)))
374570af302Sopenharmony_ci		return -1;
375570af302Sopenharmony_ci	l = 1 + p + (p || (fl&ALT_FORM));
376570af302Sopenharmony_ci	if ((t|32)=='f') {
377570af302Sopenharmony_ci		if (e > INT_MAX-l) return -1;
378570af302Sopenharmony_ci		if (e>0) l+=e;
379570af302Sopenharmony_ci	} else {
380570af302Sopenharmony_ci		estr=fmt_u(e<0 ? -e : e, ebuf);
381570af302Sopenharmony_ci		while(ebuf-estr<2) *--estr='0';
382570af302Sopenharmony_ci		*--estr = (e<0 ? '-' : '+');
383570af302Sopenharmony_ci		*--estr = t;
384570af302Sopenharmony_ci		if (ebuf-estr > INT_MAX-l) return -1;
385570af302Sopenharmony_ci		l += ebuf-estr;
386570af302Sopenharmony_ci	}
387570af302Sopenharmony_ci
388570af302Sopenharmony_ci	if (l > INT_MAX-pl) return -1;
389570af302Sopenharmony_ci	pad(f, ' ', w, pl+l, fl);
390570af302Sopenharmony_ci	out(f, prefix, pl);
391570af302Sopenharmony_ci	pad(f, '0', w, pl+l, fl^ZERO_PAD);
392570af302Sopenharmony_ci
393570af302Sopenharmony_ci	if ((t|32)=='f') {
394570af302Sopenharmony_ci		if (a>r) a=r;
395570af302Sopenharmony_ci		for (d=a; d<=r; d++) {
396570af302Sopenharmony_ci			char *s = fmt_u(*d, buf+9);
397570af302Sopenharmony_ci			if (d!=a) while (s>buf) *--s='0';
398570af302Sopenharmony_ci			else if (s==buf+9) *--s='0';
399570af302Sopenharmony_ci			out(f, s, buf+9-s);
400570af302Sopenharmony_ci		}
401570af302Sopenharmony_ci		if (p || (fl&ALT_FORM)) out(f, ".", 1);
402570af302Sopenharmony_ci		for (; d<z && p>0; d++, p-=9) {
403570af302Sopenharmony_ci			char *s = fmt_u(*d, buf+9);
404570af302Sopenharmony_ci			while (s>buf) *--s='0';
405570af302Sopenharmony_ci			out(f, s, MIN(9,p));
406570af302Sopenharmony_ci		}
407570af302Sopenharmony_ci		pad(f, '0', p+9, 9, 0);
408570af302Sopenharmony_ci	} else {
409570af302Sopenharmony_ci		if (z<=a) z=a+1;
410570af302Sopenharmony_ci		for (d=a; d<z && p>=0; d++) {
411570af302Sopenharmony_ci			char *s = fmt_u(*d, buf+9);
412570af302Sopenharmony_ci			if (s==buf+9) *--s='0';
413570af302Sopenharmony_ci			if (d!=a) while (s>buf) *--s='0';
414570af302Sopenharmony_ci			else {
415570af302Sopenharmony_ci				out(f, s++, 1);
416570af302Sopenharmony_ci				if (p>0||(fl&ALT_FORM)) out(f, ".", 1);
417570af302Sopenharmony_ci			}
418570af302Sopenharmony_ci			out(f, s, MIN(buf+9-s, p));
419570af302Sopenharmony_ci			p -= buf+9-s;
420570af302Sopenharmony_ci		}
421570af302Sopenharmony_ci		pad(f, '0', p+18, 18, 0);
422570af302Sopenharmony_ci		out(f, estr, ebuf-estr);
423570af302Sopenharmony_ci	}
424570af302Sopenharmony_ci
425570af302Sopenharmony_ci	pad(f, ' ', w, pl+l, fl^LEFT_ADJ);
426570af302Sopenharmony_ci
427570af302Sopenharmony_ci	return MAX(w, pl+l);
428570af302Sopenharmony_ci}
429570af302Sopenharmony_ci
430570af302Sopenharmony_cistatic int getint(char **s) {
431570af302Sopenharmony_ci	int i;
432570af302Sopenharmony_ci	for (i=0; isdigit(**s); (*s)++) {
433570af302Sopenharmony_ci		if (i > INT_MAX/10U || **s-'0' > INT_MAX-10*i) i = -1;
434570af302Sopenharmony_ci		else i = 10*i + (**s-'0');
435570af302Sopenharmony_ci	}
436570af302Sopenharmony_ci	return i;
437570af302Sopenharmony_ci}
438570af302Sopenharmony_ci
439570af302Sopenharmony_cistatic int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg, int *nl_type, char nl_arg_filled)
440570af302Sopenharmony_ci{
441570af302Sopenharmony_ci	char *a, *z, *s=(char *)fmt;
442570af302Sopenharmony_ci	unsigned l10n=0, fl;
443570af302Sopenharmony_ci	int w, p, xp;
444570af302Sopenharmony_ci	union arg arg;
445570af302Sopenharmony_ci	int argpos;
446570af302Sopenharmony_ci	unsigned st, ps;
447570af302Sopenharmony_ci	int cnt=0, l=0;
448570af302Sopenharmony_ci	size_t i;
449570af302Sopenharmony_ci	const char *prefix;
450570af302Sopenharmony_ci	int t, pl;
451570af302Sopenharmony_ci	wchar_t wc[2], *ws;
452570af302Sopenharmony_ci	char mb[4];
453570af302Sopenharmony_ci
454570af302Sopenharmony_ci	for (;;) {
455570af302Sopenharmony_ci		/* This error is only specified for snprintf, but since it's
456570af302Sopenharmony_ci		 * unspecified for other forms, do the same. Stop immediately
457570af302Sopenharmony_ci		 * on overflow; otherwise %n could produce wrong results. */
458570af302Sopenharmony_ci		if (l > INT_MAX - cnt) goto overflow;
459570af302Sopenharmony_ci
460570af302Sopenharmony_ci		/* Update output count, end loop when fmt is exhausted */
461570af302Sopenharmony_ci		cnt += l;
462570af302Sopenharmony_ci		if (!*s) break;
463570af302Sopenharmony_ci
464570af302Sopenharmony_ci		/* Handle literal text and %% format specifiers */
465570af302Sopenharmony_ci		for (a=s; *s && *s!='%'; s++);
466570af302Sopenharmony_ci		for (z=s; s[0]=='%' && s[1]=='%'; z++, s+=2);
467570af302Sopenharmony_ci		if (z-a > INT_MAX-cnt) goto overflow;
468570af302Sopenharmony_ci		l = z-a;
469570af302Sopenharmony_ci		if (f) out(f, a, l);
470570af302Sopenharmony_ci		if (l) continue;
471570af302Sopenharmony_ci
472570af302Sopenharmony_ci		if (isdigit(s[1]) && s[2]=='$') {
473570af302Sopenharmony_ci			if (!nl_arg_filled) {
474570af302Sopenharmony_ci				va_list ap_copy;
475570af302Sopenharmony_ci				va_copy(ap_copy, *ap);
476570af302Sopenharmony_ci				if (printf_core(0, fmt, &ap_copy, nl_arg, nl_type, 1) < 0) {
477570af302Sopenharmony_ci					return -1;
478570af302Sopenharmony_ci				}
479570af302Sopenharmony_ci				va_end(ap_copy);
480570af302Sopenharmony_ci			}
481570af302Sopenharmony_ci			l10n=1;
482570af302Sopenharmony_ci			argpos = s[1]-'0';
483570af302Sopenharmony_ci			s+=3;
484570af302Sopenharmony_ci		} else {
485570af302Sopenharmony_ci			argpos = -1;
486570af302Sopenharmony_ci			s++;
487570af302Sopenharmony_ci		}
488570af302Sopenharmony_ci
489570af302Sopenharmony_ci		/* Read modifier flags */
490570af302Sopenharmony_ci		for (fl=0; (unsigned)*s-' '<32 && (FLAGMASK&(1U<<*s-' ')); s++)
491570af302Sopenharmony_ci			fl |= 1U<<*s-' ';
492570af302Sopenharmony_ci
493570af302Sopenharmony_ci		/* Read field width */
494570af302Sopenharmony_ci		if (*s=='*') {
495570af302Sopenharmony_ci			if (isdigit(s[1]) && s[2]=='$') {
496570af302Sopenharmony_ci				l10n=1;
497570af302Sopenharmony_ci				if (!f) nl_type[s[1]-'0'] = INT, w = 0;
498570af302Sopenharmony_ci				else w = nl_arg[s[1]-'0'].i;
499570af302Sopenharmony_ci				s+=3;
500570af302Sopenharmony_ci			} else if (!l10n) {
501570af302Sopenharmony_ci				w = f ? va_arg(*ap, int) : 0;
502570af302Sopenharmony_ci				s++;
503570af302Sopenharmony_ci			} else goto inval;
504570af302Sopenharmony_ci			if (w<0) fl|=LEFT_ADJ, w=-w;
505570af302Sopenharmony_ci		} else if ((w=getint(&s))<0) goto overflow;
506570af302Sopenharmony_ci
507570af302Sopenharmony_ci		/* Read precision */
508570af302Sopenharmony_ci		if (*s=='.' && s[1]=='*') {
509570af302Sopenharmony_ci			if (isdigit(s[2]) && s[3]=='$') {
510570af302Sopenharmony_ci				if (!f) nl_type[s[2]-'0'] = INT, p = 0;
511570af302Sopenharmony_ci				else p = nl_arg[s[2]-'0'].i;
512570af302Sopenharmony_ci				s+=4;
513570af302Sopenharmony_ci			} else if (!l10n) {
514570af302Sopenharmony_ci				p = f ? va_arg(*ap, int) : 0;
515570af302Sopenharmony_ci				s+=2;
516570af302Sopenharmony_ci			} else goto inval;
517570af302Sopenharmony_ci			xp = (p>=0);
518570af302Sopenharmony_ci		} else if (*s=='.') {
519570af302Sopenharmony_ci			s++;
520570af302Sopenharmony_ci			p = getint(&s);
521570af302Sopenharmony_ci			xp = 1;
522570af302Sopenharmony_ci		} else {
523570af302Sopenharmony_ci			p = -1;
524570af302Sopenharmony_ci			xp = 0;
525570af302Sopenharmony_ci		}
526570af302Sopenharmony_ci
527570af302Sopenharmony_ci		/* Format specifier state machine */
528570af302Sopenharmony_ci		st=0;
529570af302Sopenharmony_ci		do {
530570af302Sopenharmony_ci			if (OOB(*s)) goto inval;
531570af302Sopenharmony_ci			ps=st;
532570af302Sopenharmony_ci			st=states[st]S(*s++);
533570af302Sopenharmony_ci		} while (st-1<STOP);
534570af302Sopenharmony_ci		if (!st) goto inval;
535570af302Sopenharmony_ci
536570af302Sopenharmony_ci		/* Check validity of argument type (nl/normal) */
537570af302Sopenharmony_ci		if (st==NOARG) {
538570af302Sopenharmony_ci			if (argpos>=0) goto inval;
539570af302Sopenharmony_ci		} else {
540570af302Sopenharmony_ci			if (argpos>=0) {
541570af302Sopenharmony_ci				if (!f) nl_type[argpos]=st;
542570af302Sopenharmony_ci				else arg=nl_arg[argpos];
543570af302Sopenharmony_ci			} else if (f) pop_arg(&arg, st, ap);
544570af302Sopenharmony_ci			else return 0;
545570af302Sopenharmony_ci		}
546570af302Sopenharmony_ci
547570af302Sopenharmony_ci		if (!f) continue;
548570af302Sopenharmony_ci
549570af302Sopenharmony_ci		/* Do not process any new directives once in error state. */
550570af302Sopenharmony_ci		if (ferror(f)) return -1;
551570af302Sopenharmony_ci
552570af302Sopenharmony_ci		/* Do not process any new directives once in error state. */
553570af302Sopenharmony_ci		if (ferror(f)) return -1;
554570af302Sopenharmony_ci
555570af302Sopenharmony_ci		char buf[sizeof(uintmax_t)*3];
556570af302Sopenharmony_ci		z = buf + sizeof(buf);
557570af302Sopenharmony_ci		prefix = "-+   0X0x";
558570af302Sopenharmony_ci		pl = 0;
559570af302Sopenharmony_ci		t = s[-1];
560570af302Sopenharmony_ci
561570af302Sopenharmony_ci		/* Transform ls,lc -> S,C */
562570af302Sopenharmony_ci		if (ps && (t&15)==3) t&=~32;
563570af302Sopenharmony_ci
564570af302Sopenharmony_ci		/* - and 0 flags are mutually exclusive */
565570af302Sopenharmony_ci		if (fl & LEFT_ADJ) fl &= ~ZERO_PAD;
566570af302Sopenharmony_ci
567570af302Sopenharmony_ci		switch(t) {
568570af302Sopenharmony_ci		case 'n':
569570af302Sopenharmony_ci			switch(ps) {
570570af302Sopenharmony_ci			case BARE: *(int *)arg.p = cnt; break;
571570af302Sopenharmony_ci			case LPRE: *(long *)arg.p = cnt; break;
572570af302Sopenharmony_ci			case LLPRE: *(long long *)arg.p = cnt; break;
573570af302Sopenharmony_ci			case HPRE: *(unsigned short *)arg.p = cnt; break;
574570af302Sopenharmony_ci			case HHPRE: *(unsigned char *)arg.p = cnt; break;
575570af302Sopenharmony_ci			case ZTPRE: *(size_t *)arg.p = cnt; break;
576570af302Sopenharmony_ci			case JPRE: *(uintmax_t *)arg.p = cnt; break;
577570af302Sopenharmony_ci			}
578570af302Sopenharmony_ci			continue;
579570af302Sopenharmony_ci		case 'p':
580570af302Sopenharmony_ci			p = MAX(p, 2*sizeof(void*));
581570af302Sopenharmony_ci			t = 'x';
582570af302Sopenharmony_ci			fl |= ALT_FORM;
583570af302Sopenharmony_ci		case 'x': case 'X':
584570af302Sopenharmony_ci			a = fmt_x(arg.i, z, t&32);
585570af302Sopenharmony_ci			if (arg.i && (fl & ALT_FORM)) prefix+=(t>>4), pl=2;
586570af302Sopenharmony_ci			if (0) {
587570af302Sopenharmony_ci		case 'o':
588570af302Sopenharmony_ci			a = fmt_o(arg.i, z);
589570af302Sopenharmony_ci			if ((fl&ALT_FORM) && p<z-a+1) p=z-a+1;
590570af302Sopenharmony_ci			} if (0) {
591570af302Sopenharmony_ci		case 'd': case 'i':
592570af302Sopenharmony_ci			pl=1;
593570af302Sopenharmony_ci			if (arg.i>INTMAX_MAX) {
594570af302Sopenharmony_ci				arg.i=-arg.i;
595570af302Sopenharmony_ci			} else if (fl & MARK_POS) {
596570af302Sopenharmony_ci				prefix++;
597570af302Sopenharmony_ci			} else if (fl & PAD_POS) {
598570af302Sopenharmony_ci				prefix+=2;
599570af302Sopenharmony_ci			} else pl=0;
600570af302Sopenharmony_ci		case 'u':
601570af302Sopenharmony_ci			a = fmt_u(arg.i, z);
602570af302Sopenharmony_ci			}
603570af302Sopenharmony_ci			if (xp && p<0) goto overflow;
604570af302Sopenharmony_ci			if (xp) fl &= ~ZERO_PAD;
605570af302Sopenharmony_ci			if (!arg.i && !p) {
606570af302Sopenharmony_ci				a=z;
607570af302Sopenharmony_ci				break;
608570af302Sopenharmony_ci			}
609570af302Sopenharmony_ci			p = MAX(p, z-a + !arg.i);
610570af302Sopenharmony_ci			break;
611570af302Sopenharmony_ci		narrow_c:
612570af302Sopenharmony_ci		case 'c':
613570af302Sopenharmony_ci			*(a=z-(p=1))=arg.i;
614570af302Sopenharmony_ci			fl &= ~ZERO_PAD;
615570af302Sopenharmony_ci			break;
616570af302Sopenharmony_ci		case 'm':
617570af302Sopenharmony_ci			if (1) a = strerror(errno); else
618570af302Sopenharmony_ci		case 's':
619570af302Sopenharmony_ci			a = arg.p ? arg.p : "(null)";
620570af302Sopenharmony_ci			z = a + strnlen(a, p<0 ? INT_MAX : p);
621570af302Sopenharmony_ci			if (p<0 && *z) goto overflow;
622570af302Sopenharmony_ci			p = z-a;
623570af302Sopenharmony_ci			fl &= ~ZERO_PAD;
624570af302Sopenharmony_ci			break;
625570af302Sopenharmony_ci		case 'C':
626570af302Sopenharmony_ci			if (!arg.i) goto narrow_c;
627570af302Sopenharmony_ci			wc[0] = arg.i;
628570af302Sopenharmony_ci			wc[1] = 0;
629570af302Sopenharmony_ci			arg.p = wc;
630570af302Sopenharmony_ci			p = -1;
631570af302Sopenharmony_ci		case 'S':
632570af302Sopenharmony_ci			ws = arg.p;
633570af302Sopenharmony_ci			for (i=l=0; i<p && *ws && (l=wctomb(mb, *ws++))>=0 && l<=p-i; i+=l);
634570af302Sopenharmony_ci			if (l<0) return -1;
635570af302Sopenharmony_ci			if (i > INT_MAX) goto overflow;
636570af302Sopenharmony_ci			p = i;
637570af302Sopenharmony_ci			pad(f, ' ', w, p, fl);
638570af302Sopenharmony_ci			ws = arg.p;
639570af302Sopenharmony_ci			for (i=0; i<0U+p && *ws && i+(l=wctomb(mb, *ws++))<=p; i+=l)
640570af302Sopenharmony_ci				out(f, mb, l);
641570af302Sopenharmony_ci			pad(f, ' ', w, p, fl^LEFT_ADJ);
642570af302Sopenharmony_ci			l = w>p ? w : p;
643570af302Sopenharmony_ci			continue;
644570af302Sopenharmony_ci		case 'e': case 'f': case 'g': case 'a':
645570af302Sopenharmony_ci		case 'E': case 'F': case 'G': case 'A':
646570af302Sopenharmony_ci			if (xp && p<0) goto overflow;
647570af302Sopenharmony_ci			l = fmt_fp(f, arg.f, w, p, fl, t);
648570af302Sopenharmony_ci			if (l<0) goto overflow;
649570af302Sopenharmony_ci			continue;
650570af302Sopenharmony_ci		}
651570af302Sopenharmony_ci
652570af302Sopenharmony_ci		if (p < z-a) p = z-a;
653570af302Sopenharmony_ci		if (p > INT_MAX-pl) goto overflow;
654570af302Sopenharmony_ci		if (w < pl+p) w = pl+p;
655570af302Sopenharmony_ci		if (w > INT_MAX-cnt) goto overflow;
656570af302Sopenharmony_ci
657570af302Sopenharmony_ci		pad(f, ' ', w, pl+p, fl);
658570af302Sopenharmony_ci		out(f, prefix, pl);
659570af302Sopenharmony_ci		pad(f, '0', w, pl+p, fl^ZERO_PAD);
660570af302Sopenharmony_ci		pad(f, '0', p, z-a, 0);
661570af302Sopenharmony_ci		out(f, a, z-a);
662570af302Sopenharmony_ci		pad(f, ' ', w, pl+p, fl^LEFT_ADJ);
663570af302Sopenharmony_ci
664570af302Sopenharmony_ci		l = w;
665570af302Sopenharmony_ci	}
666570af302Sopenharmony_ci
667570af302Sopenharmony_ci	if (f) return cnt;
668570af302Sopenharmony_ci	if (!l10n) return 0;
669570af302Sopenharmony_ci
670570af302Sopenharmony_ci	for (i=1; i<=NL_ARGMAX && nl_type[i]; i++)
671570af302Sopenharmony_ci		pop_arg(nl_arg+i, nl_type[i], ap);
672570af302Sopenharmony_ci	for (; i<=NL_ARGMAX && !nl_type[i]; i++);
673570af302Sopenharmony_ci	if (i<=NL_ARGMAX) goto inval;
674570af302Sopenharmony_ci	return 1;
675570af302Sopenharmony_ci
676570af302Sopenharmony_ciinval:
677570af302Sopenharmony_ci	errno = EINVAL;
678570af302Sopenharmony_ci	return -1;
679570af302Sopenharmony_cioverflow:
680570af302Sopenharmony_ci	errno = EOVERFLOW;
681570af302Sopenharmony_ci	return -1;
682570af302Sopenharmony_ci}
683570af302Sopenharmony_ci
684570af302Sopenharmony_ciint vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
685570af302Sopenharmony_ci{
686570af302Sopenharmony_ci	va_list ap2;
687570af302Sopenharmony_ci	int nl_type[NL_ARGMAX+1] = {0};
688570af302Sopenharmony_ci	union arg nl_arg[NL_ARGMAX+1];
689570af302Sopenharmony_ci	unsigned char internal_buf[80], *saved_buf = 0;
690570af302Sopenharmony_ci	int olderr;
691570af302Sopenharmony_ci	int ret;
692570af302Sopenharmony_ci
693570af302Sopenharmony_ci	/* the copy allows passing va_list* even if va_list is an array */
694570af302Sopenharmony_ci	va_copy(ap2, ap);
695570af302Sopenharmony_ci
696570af302Sopenharmony_ci	FLOCK(f);
697570af302Sopenharmony_ci	olderr = f->flags & F_ERR;
698570af302Sopenharmony_ci	f->flags &= ~F_ERR;
699570af302Sopenharmony_ci
700570af302Sopenharmony_ci	if (!f->buf_size && f->buf != NULL) {
701570af302Sopenharmony_ci		saved_buf = f->buf;
702570af302Sopenharmony_ci		f->buf = internal_buf;
703570af302Sopenharmony_ci		f->buf_size = sizeof internal_buf;
704570af302Sopenharmony_ci		f->wpos = f->wbase = f->wend = 0;
705570af302Sopenharmony_ci	}
706570af302Sopenharmony_ci	if (!f->wend && __towrite(f)) ret = -1;
707570af302Sopenharmony_ci	else {
708570af302Sopenharmony_ci		ret = printf_core(f, fmt, &ap2, nl_arg, nl_type, 0);
709570af302Sopenharmony_ci	}
710570af302Sopenharmony_ci	if (saved_buf) {
711570af302Sopenharmony_ci		if (!(f->flags & F_PBUF)) {
712570af302Sopenharmony_ci			f->write(f, 0, 0);
713570af302Sopenharmony_ci		} else {
714570af302Sopenharmony_ci			*saved_buf = '\0';
715570af302Sopenharmony_ci		}
716570af302Sopenharmony_ci		if (!f->wpos) ret = -1;
717570af302Sopenharmony_ci		f->buf = saved_buf;
718570af302Sopenharmony_ci		f->buf_size = 0;
719570af302Sopenharmony_ci		f->wpos = f->wbase = f->wend = 0;
720570af302Sopenharmony_ci	} else {
721570af302Sopenharmony_ci		if (f->flags & F_PBUF) {
722570af302Sopenharmony_ci			*f->wpos = '\0';
723570af302Sopenharmony_ci		}
724570af302Sopenharmony_ci	}
725570af302Sopenharmony_ci	if (ferror(f)) ret = -1;
726570af302Sopenharmony_ci	f->flags |= olderr;
727570af302Sopenharmony_ci	FUNLOCK(f);
728570af302Sopenharmony_ci	va_end(ap2);
729570af302Sopenharmony_ci	return ret;
730570af302Sopenharmony_ci}
731