OLD | NEW |
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 } |
OLD | NEW |