Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(682)

Side by Side Diff: fusl/src/stdio/vfprintf.c

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

Powered by Google App Engine
This is Rietveld 408576698