]>
Commit | Line | Data |
---|---|---|
34e8f829 A |
1 | --- vfprintf.c.orig 2008-09-07 11:37:54.000000000 -0700 |
2 | +++ vfprintf.c 2008-09-07 17:33:16.000000000 -0700 | |
3 | @@ -40,6 +40,8 @@ static char sccsid[] = "@(#)vfprintf.c 8 | |
3d9156a7 A |
4 | #include <sys/cdefs.h> |
5 | __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $"); | |
6 | ||
7 | +#include "xlocale_private.h" | |
8 | + | |
9 | /* | |
10 | * Actual printf innards. | |
11 | * | |
34e8f829 | 12 | @@ -58,6 +60,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v |
51631861 A |
13 | #include <stdlib.h> |
14 | #include <string.h> | |
15 | #include <wchar.h> | |
16 | +#include <errno.h> | |
17 | ||
18 | #include <stdarg.h> | |
19 | #include "un-namespace.h" | |
34e8f829 | 20 | @@ -66,6 +69,13 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v |
9385eb3d A |
21 | #include "local.h" |
22 | #include "fvwrite.h" | |
23 | ||
eb1cde05 A |
24 | +#ifdef VECTORS |
25 | +typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE; | |
26 | +#ifdef __SSE2__ | |
27 | +#define V64TYPE | |
28 | +#endif /* __SSE2__ */ | |
29 | +#endif /* VECTORS */ | |
9385eb3d A |
30 | + |
31 | union arg { | |
32 | int intarg; | |
33 | u_int uintarg; | |
34e8f829 | 34 | @@ -93,6 +103,21 @@ union arg { |
9385eb3d A |
35 | #endif |
36 | wint_t wintarg; | |
37 | wchar_t *pwchararg; | |
eb1cde05 | 38 | +#ifdef VECTORS |
9385eb3d A |
39 | + VECTORTYPE vectorarg; |
40 | + unsigned char vuchararg[16]; | |
41 | + signed char vchararg[16]; | |
42 | + unsigned short vushortarg[8]; | |
43 | + signed short vshortarg[8]; | |
44 | + unsigned int vuintarg[4]; | |
45 | + signed int vintarg[4]; | |
46 | + float vfloatarg[4]; | |
eb1cde05 A |
47 | +#ifdef V64TYPE |
48 | + double vdoublearg[2]; | |
49 | + unsigned long long vulonglongarg[2]; | |
50 | + long long vlonglongarg[2]; | |
51 | +#endif /* V64TYPE */ | |
52 | +#endif /* VECTORS */ | |
9385eb3d A |
53 | }; |
54 | ||
55 | /* | |
34e8f829 | 56 | @@ -103,16 +128,20 @@ enum typeid { |
9385eb3d A |
57 | T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG, |
58 | T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET, | |
59 | T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR, | |
eb1cde05 | 60 | +#ifdef VECTORS |
9385eb3d | 61 | + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR |
eb1cde05 | 62 | +#else /* ! VECTORS */ |
9385eb3d | 63 | T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR |
eb1cde05 | 64 | +#endif /* VECTORS */ |
9385eb3d A |
65 | }; |
66 | ||
67 | static int __sprint(FILE *, struct __suio *); | |
3d9156a7 A |
68 | -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); |
69 | +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0); | |
70 | static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char, | |
71 | const char *); | |
72 | static char *__ultoa(u_long, char *, int, int, const char *, int, char, | |
73 | const char *); | |
74 | -static char *__wcsconv(wchar_t *, int); | |
75 | +static char *__wcsconv(wchar_t *, int, locale_t); | |
9385eb3d A |
76 | static void __find_arguments(const char *, va_list, union arg **); |
77 | static void __grow_type_table(int, enum typeid **, int *); | |
78 | ||
34e8f829 | 79 | @@ -141,7 +170,7 @@ __sprint(FILE *fp, struct __suio *uio) |
3d9156a7 A |
80 | * worries about ungetc buffers and so forth. |
81 | */ | |
82 | static int | |
83 | -__sbprintf(FILE *fp, const char *fmt, va_list ap) | |
84 | +__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap) | |
85 | { | |
86 | int ret; | |
87 | FILE fake; | |
34e8f829 | 88 | @@ -160,7 +189,7 @@ __sbprintf(FILE *fp, const char *fmt, va |
3d9156a7 A |
89 | fake._lbfsize = 0; /* not actually used, but Just In Case */ |
90 | ||
91 | /* do the work, then copy any error status */ | |
92 | - ret = __vfprintf(&fake, fmt, ap); | |
93 | + ret = __vfprintf(&fake, loc, fmt, ap); | |
94 | if (ret >= 0 && __fflush(&fake)) | |
95 | ret = EOF; | |
96 | if (fake._flags & __SERR) | |
34e8f829 A |
97 | @@ -252,7 +281,7 @@ __ultoa(u_long val, char *endp, int base |
98 | break; | |
99 | ||
100 | default: /* oops */ | |
101 | - abort(); | |
102 | + LIBC_ABORT("base = %d", base); | |
103 | } | |
104 | return (cp); | |
105 | } | |
106 | @@ -324,7 +353,7 @@ __ujtoa(uintmax_t val, char *endp, int b | |
107 | break; | |
108 | ||
109 | default: | |
110 | - abort(); | |
111 | + LIBC_ABORT("base = %d", base); | |
112 | } | |
113 | return (cp); | |
114 | } | |
115 | @@ -336,14 +365,14 @@ __ujtoa(uintmax_t val, char *endp, int b | |
3d9156a7 A |
116 | * that the wide char. string ends in a null character. |
117 | */ | |
118 | static char * | |
119 | -__wcsconv(wchar_t *wcsarg, int prec) | |
120 | +__wcsconv(wchar_t *wcsarg, int prec, locale_t loc) | |
121 | { | |
122 | static const mbstate_t initial; | |
123 | mbstate_t mbs; | |
224c7076 A |
124 | char buf[MB_LEN_MAX]; |
125 | wchar_t *p; | |
126 | char *convbuf, *mbp; | |
127 | - size_t clen, nbytes; | |
128 | + size_t clen = 0, nbytes; | |
129 | ||
130 | /* | |
131 | * Determine the number of bytes to output and allocate space for | |
34e8f829 | 132 | @@ -354,7 +383,7 @@ __wcsconv(wchar_t *wcsarg, int prec) |
3d9156a7 A |
133 | p = wcsarg; |
134 | mbs = initial; | |
135 | for (;;) { | |
136 | - clen = wcrtomb(buf, *p++, &mbs); | |
137 | + clen = wcrtomb_l(buf, *p++, &mbs, loc); | |
138 | if (clen == 0 || clen == (size_t)-1 || | |
139 | nbytes + clen > prec) | |
140 | break; | |
34e8f829 | 141 | @@ -363,7 +392,7 @@ __wcsconv(wchar_t *wcsarg, int prec) |
3d9156a7 A |
142 | } else { |
143 | p = wcsarg; | |
144 | mbs = initial; | |
145 | - nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs); | |
146 | + nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc); | |
147 | if (nbytes == (size_t)-1) | |
148 | return (NULL); | |
149 | } | |
34e8f829 | 150 | @@ -378,7 +407,7 @@ __wcsconv(wchar_t *wcsarg, int prec) |
3d9156a7 A |
151 | p = wcsarg; |
152 | mbs = initial; | |
153 | while (mbp - convbuf < nbytes) { | |
154 | - clen = wcrtomb(mbp, *p++, &mbs); | |
155 | + clen = wcrtomb_l(mbp, *p++, &mbs, loc); | |
156 | if (clen == 0 || clen == (size_t)-1) | |
157 | break; | |
158 | mbp += clen; | |
34e8f829 | 159 | @@ -395,6 +424,8 @@ __wcsconv(wchar_t *wcsarg, int prec) |
224c7076 A |
160 | /* |
161 | * MT-safe version | |
162 | */ | |
163 | +__private_extern__ const char *__fix_nogrouping(const char *); | |
164 | + | |
165 | int | |
166 | vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap) | |
167 | ||
34e8f829 | 168 | @@ -402,7 +433,21 @@ vfprintf(FILE * __restrict fp, const cha |
3d9156a7 A |
169 | int ret; |
170 | ||
171 | FLOCKFILE(fp); | |
172 | - ret = __vfprintf(fp, fmt0, ap); | |
173 | + ret = __vfprintf(fp, __current_locale(), fmt0, ap); | |
174 | + FUNLOCKFILE(fp); | |
175 | + return (ret); | |
176 | +} | |
177 | + | |
178 | +int | |
179 | +vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, | |
180 | + va_list ap) | |
181 | + | |
182 | +{ | |
183 | + int ret; | |
184 | + | |
185 | + NORMALIZE_LOCALE(loc); | |
186 | + FLOCKFILE(fp); | |
187 | + ret = __vfprintf(fp, loc, fmt0, ap); | |
188 | FUNLOCKFILE(fp); | |
189 | return (ret); | |
190 | } | |
34e8f829 | 191 | @@ -451,12 +496,15 @@ static int exponent(char *, int, int); |
9385eb3d A |
192 | #define PTRDIFFT 0x800 /* ptrdiff_t */ |
193 | #define INTMAXT 0x1000 /* intmax_t */ | |
194 | #define CHARINT 0x2000 /* print char using int format */ | |
eb1cde05 A |
195 | +#ifdef VECTORS |
196 | +#define VECTOR 0x4000 /* Altivec or SSE vector */ | |
197 | +#endif /* VECTORS */ | |
9385eb3d A |
198 | |
199 | /* | |
200 | * Non-MT-safe version | |
3d9156a7 A |
201 | */ |
202 | -int | |
203 | -__vfprintf(FILE *fp, const char *fmt0, va_list ap) | |
204 | +__private_extern__ int | |
205 | +__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap) | |
206 | { | |
207 | char *fmt; /* format string */ | |
208 | int ch; /* character from fmt */ | |
34e8f829 | 209 | @@ -502,6 +550,11 @@ __vfprintf(FILE *fp, const char *fmt0, v |
9385eb3d A |
210 | int nseps; /* number of group separators with ' */ |
211 | int nrepeats; /* number of repeats of the last group */ | |
212 | #endif | |
eb1cde05 | 213 | +#ifdef VECTORS |
9385eb3d A |
214 | + union arg vval; /* Vector argument. */ |
215 | + char *pct; /* Pointer to '%' at beginning of specifier. */ | |
216 | + char vsep; /* Vector separator character. */ | |
217 | +#endif | |
218 | u_long ulval; /* integer arguments %[diouxX] */ | |
219 | uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */ | |
220 | int base; /* base for [diouxX] conversion */ | |
34e8f829 | 221 | @@ -599,13 +652,13 @@ __vfprintf(FILE *fp, const char *fmt0, v |
224c7076 A |
222 | #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT) |
223 | #define SJARG() \ | |
224 | (flags&INTMAXT ? GETARG(intmax_t) : \ | |
225 | - flags&SIZET ? (intmax_t)GETARG(size_t) : \ | |
226 | + flags&SIZET ? (intmax_t)GETARG(ssize_t) : \ | |
227 | flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \ | |
228 | (intmax_t)GETARG(long long)) | |
229 | #define UJARG() \ | |
34e8f829 A |
230 | (flags&INTMAXT ? GETARG(uintmax_t) : \ |
231 | flags&SIZET ? (uintmax_t)GETARG(size_t) : \ | |
232 | - flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \ | |
233 | + flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \ | |
234 | (uintmax_t)GETARG(unsigned long long)) | |
235 | ||
236 | /* | |
237 | @@ -633,22 +686,24 @@ __vfprintf(FILE *fp, const char *fmt0, v | |
9385eb3d A |
238 | val = GETARG (int); \ |
239 | } | |
240 | ||
241 | - | |
242 | thousands_sep = '\0'; | |
243 | grouping = NULL; | |
244 | convbuf = NULL; | |
3d9156a7 A |
245 | #ifndef NO_FLOATING_POINT |
246 | dtoaresult = NULL; | |
247 | - decimal_point = localeconv()->decimal_point; | |
248 | + decimal_point = localeconv_l(loc)->decimal_point; | |
51631861 A |
249 | #endif |
250 | /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */ | |
3d9156a7 A |
251 | - if (prepwrite(fp) != 0) |
252 | + if (prepwrite(fp) != 0) { | |
51631861 A |
253 | + errno = EBADF; |
254 | return (EOF); | |
255 | + } | |
224c7076 | 256 | + ORIENT(fp, -1); |
51631861 A |
257 | |
258 | /* optimise fprintf(stderr) (and other unbuffered Unix files) */ | |
259 | if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && | |
3d9156a7 A |
260 | fp->_file >= 0) |
261 | - return (__sbprintf(fp, fmt0, ap)); | |
262 | + return (__sbprintf(fp, loc, fmt0, ap)); | |
263 | ||
264 | fmt = (char *)fmt0; | |
265 | argtable = NULL; | |
34e8f829 | 266 | @@ -675,6 +730,9 @@ __vfprintf(FILE *fp, const char *fmt0, v |
9385eb3d A |
267 | } |
268 | if (ch == '\0') | |
269 | goto done; | |
eb1cde05 | 270 | +#ifdef VECTORS |
9385eb3d | 271 | + pct = fmt; |
eb1cde05 | 272 | +#endif /* VECTORS */ |
9385eb3d A |
273 | fmt++; /* skip over '%' */ |
274 | ||
275 | flags = 0; | |
34e8f829 | 276 | @@ -683,6 +741,9 @@ __vfprintf(FILE *fp, const char *fmt0, v |
9385eb3d A |
277 | prec = -1; |
278 | sign = '\0'; | |
279 | ox[1] = '\0'; | |
eb1cde05 | 280 | +#ifdef VECTORS |
9385eb3d | 281 | + vsep = 'X'; /* Illegal value, changed to defaults later. */ |
eb1cde05 | 282 | +#endif /* VECTORS */ |
9385eb3d A |
283 | |
284 | rflag: ch = *fmt++; | |
285 | reswitch: switch (ch) { | |
34e8f829 | 286 | @@ -698,6 +759,11 @@ reswitch: switch (ch) { |
9385eb3d A |
287 | case '#': |
288 | flags |= ALT; | |
289 | goto rflag; | |
eb1cde05 | 290 | +#ifdef VECTORS |
9385eb3d A |
291 | + case ',': case ';': case ':': case '_': |
292 | + vsep = ch; | |
293 | + goto rflag; | |
eb1cde05 | 294 | +#endif /* VECTORS */ |
9385eb3d A |
295 | case '*': |
296 | /*- | |
297 | * ``A negative field width argument is taken as a | |
34e8f829 | 298 | @@ -718,8 +784,8 @@ reswitch: switch (ch) { |
3d9156a7 A |
299 | goto rflag; |
300 | case '\'': | |
301 | flags |= GROUPING; | |
302 | - thousands_sep = *(localeconv()->thousands_sep); | |
303 | - grouping = localeconv()->grouping; | |
304 | + thousands_sep = *(localeconv_l(loc)->thousands_sep); | |
224c7076 | 305 | + grouping = __fix_nogrouping(localeconv_l(loc)->grouping); |
3d9156a7 A |
306 | goto rflag; |
307 | case '.': | |
308 | if ((ch = *fmt++) == '*') { | |
34e8f829 | 309 | @@ -793,14 +859,18 @@ reswitch: switch (ch) { |
59e0d9fe A |
310 | flags |= LONGINT; |
311 | /*FALLTHROUGH*/ | |
312 | case 'c': | |
eb1cde05 A |
313 | +#ifdef VECTORS |
314 | + if (flags & VECTOR) | |
59e0d9fe | 315 | + break; |
eb1cde05 | 316 | +#endif /* VECTORS */ |
59e0d9fe A |
317 | if (flags & LONGINT) { |
318 | static const mbstate_t initial; | |
319 | mbstate_t mbs; | |
3d9156a7 A |
320 | size_t mbseqlen; |
321 | ||
322 | mbs = initial; | |
323 | - mbseqlen = wcrtomb(cp = buf, | |
324 | - (wchar_t)GETARG(wint_t), &mbs); | |
325 | + mbseqlen = wcrtomb_l(cp = buf, | |
326 | + (wchar_t)GETARG(wint_t), &mbs, loc); | |
327 | if (mbseqlen == (size_t)-1) { | |
328 | fp->_flags |= __SERR; | |
329 | goto error; | |
34e8f829 | 330 | @@ -817,6 +887,10 @@ reswitch: switch (ch) { |
9385eb3d A |
331 | /*FALLTHROUGH*/ |
332 | case 'd': | |
333 | case 'i': | |
eb1cde05 A |
334 | +#ifdef VECTORS |
335 | + if (flags & VECTOR) | |
9385eb3d | 336 | + break; |
eb1cde05 | 337 | +#endif /* VECTORS */ |
9385eb3d A |
338 | if (flags & INTMAX_SIZE) { |
339 | ujval = SJARG(); | |
340 | if ((intmax_t)ujval < 0) { | |
34e8f829 | 341 | @@ -835,6 +909,12 @@ reswitch: switch (ch) { |
59e0d9fe | 342 | #ifndef NO_FLOATING_POINT |
9385eb3d A |
343 | case 'a': |
344 | case 'A': | |
eb1cde05 | 345 | +#ifdef VECTORS |
9385eb3d A |
346 | + if (flags & VECTOR) { |
347 | + flags |= FPT; | |
9385eb3d A |
348 | + break; |
349 | + } | |
eb1cde05 | 350 | +#endif /* VECTORS */ |
9385eb3d A |
351 | if (ch == 'a') { |
352 | ox[1] = 'x'; | |
353 | xdigs = xdigs_lower; | |
34e8f829 | 354 | @@ -848,6 +928,12 @@ reswitch: switch (ch) { |
3d9156a7 A |
355 | prec++; |
356 | if (dtoaresult != NULL) | |
357 | freedtoa(dtoaresult); | |
358 | +#ifdef LDBL_COMPAT | |
359 | + fparg.dbl = GETARG(double); | |
360 | + dtoaresult = cp = | |
361 | + __hdtoa(fparg.dbl, xdigs, prec, | |
362 | + &expt, &signflag, &dtoaend); | |
363 | +#else /* !LDBL_COMPAT */ | |
364 | if (flags & LONGDBL) { | |
365 | fparg.ldbl = GETARG(long double); | |
366 | dtoaresult = cp = | |
34e8f829 | 367 | @@ -859,6 +945,7 @@ reswitch: switch (ch) { |
3d9156a7 A |
368 | __hdtoa(fparg.dbl, xdigs, prec, |
369 | &expt, &signflag, &dtoaend); | |
370 | } | |
371 | +#endif /* LDBL_COMPAT */ | |
372 | if (prec < 0) | |
373 | prec = dtoaend - cp; | |
374 | if (expt == INT_MAX) | |
34e8f829 | 375 | @@ -866,6 +953,12 @@ reswitch: switch (ch) { |
59e0d9fe | 376 | goto fp_common; |
9385eb3d A |
377 | case 'e': |
378 | case 'E': | |
eb1cde05 | 379 | +#ifdef VECTORS |
9385eb3d A |
380 | + if (flags & VECTOR) { |
381 | + flags |= FPT; | |
9385eb3d A |
382 | + break; |
383 | + } | |
eb1cde05 | 384 | +#endif /* VECTORS */ |
9385eb3d A |
385 | expchar = ch; |
386 | if (prec < 0) /* account for digit before decpt */ | |
387 | prec = DEFPREC + 1; | |
34e8f829 | 388 | @@ -874,10 +967,22 @@ reswitch: switch (ch) { |
9385eb3d A |
389 | goto fp_begin; |
390 | case 'f': | |
391 | case 'F': | |
eb1cde05 | 392 | +#ifdef VECTORS |
9385eb3d A |
393 | + if (flags & VECTOR) { |
394 | + flags |= FPT; | |
9385eb3d A |
395 | + break; |
396 | + } | |
eb1cde05 | 397 | +#endif /* VECTORS */ |
9385eb3d A |
398 | expchar = '\0'; |
399 | goto fp_begin; | |
400 | case 'g': | |
401 | case 'G': | |
eb1cde05 | 402 | +#ifdef VECTORS |
9385eb3d A |
403 | + if (flags & VECTOR) { |
404 | + flags |= FPT; | |
9385eb3d A |
405 | + break; |
406 | + } | |
eb1cde05 | 407 | +#endif /* VECTORS */ |
9385eb3d A |
408 | expchar = ch - ('g' - 'e'); |
409 | if (prec == 0) | |
410 | prec = 1; | |
34e8f829 | 411 | @@ -886,6 +991,14 @@ fp_begin: |
3d9156a7 A |
412 | prec = DEFPREC; |
413 | if (dtoaresult != NULL) | |
414 | freedtoa(dtoaresult); | |
415 | +#ifdef LDBL_COMPAT | |
416 | + fparg.dbl = GETARG(double); | |
417 | + dtoaresult = cp = | |
418 | + dtoa(fparg.dbl, expchar ? 2 : 3, prec, | |
419 | + &expt, &signflag, &dtoaend); | |
420 | + if (expt == 9999) | |
421 | + expt = INT_MAX; | |
422 | +#else /* !LDBL_COMPAT */ | |
423 | if (flags & LONGDBL) { | |
424 | fparg.ldbl = GETARG(long double); | |
425 | dtoaresult = cp = | |
34e8f829 | 426 | @@ -899,6 +1012,7 @@ fp_begin: |
3d9156a7 A |
427 | if (expt == 9999) |
428 | expt = INT_MAX; | |
429 | } | |
430 | +#endif /* LDBL_COMPAT */ | |
431 | fp_common: | |
432 | if (signflag) | |
433 | sign = '-'; | |
34e8f829 | 434 | @@ -993,6 +1107,10 @@ fp_common: |
9385eb3d A |
435 | flags |= LONGINT; |
436 | /*FALLTHROUGH*/ | |
437 | case 'o': | |
eb1cde05 A |
438 | +#ifdef VECTORS |
439 | + if (flags & VECTOR) | |
9385eb3d | 440 | + break; |
eb1cde05 | 441 | +#endif /* VECTORS */ |
9385eb3d A |
442 | if (flags & INTMAX_SIZE) |
443 | ujval = UJARG(); | |
444 | else | |
34e8f829 | 445 | @@ -1007,6 +1125,10 @@ fp_common: |
9385eb3d A |
446 | * defined manner.'' |
447 | * -- ANSI X3J11 | |
448 | */ | |
eb1cde05 A |
449 | +#ifdef VECTORS |
450 | + if (flags & VECTOR) | |
9385eb3d | 451 | + break; |
eb1cde05 | 452 | +#endif /* VECTORS */ |
9385eb3d A |
453 | ujval = (uintmax_t)(uintptr_t)GETARG(void *); |
454 | base = 16; | |
455 | xdigs = xdigs_lower; | |
34e8f829 | 456 | @@ -1025,7 +1147,7 @@ fp_common: |
3d9156a7 A |
457 | if ((wcp = GETARG(wchar_t *)) == NULL) |
458 | cp = "(null)"; | |
459 | else { | |
460 | - convbuf = __wcsconv(wcp, prec); | |
461 | + convbuf = __wcsconv(wcp, prec, loc); | |
462 | if (convbuf == NULL) { | |
463 | fp->_flags |= __SERR; | |
464 | goto error; | |
34e8f829 | 465 | @@ -1056,6 +1178,10 @@ fp_common: |
9385eb3d A |
466 | flags |= LONGINT; |
467 | /*FALLTHROUGH*/ | |
468 | case 'u': | |
eb1cde05 A |
469 | +#ifdef VECTORS |
470 | + if (flags & VECTOR) | |
9385eb3d | 471 | + break; |
eb1cde05 | 472 | +#endif /* VECTORS */ |
9385eb3d A |
473 | if (flags & INTMAX_SIZE) |
474 | ujval = UJARG(); | |
475 | else | |
34e8f829 | 476 | @@ -1068,6 +1194,10 @@ fp_common: |
9385eb3d A |
477 | case 'x': |
478 | xdigs = xdigs_lower; | |
479 | hex: | |
eb1cde05 A |
480 | +#ifdef VECTORS |
481 | + if (flags & VECTOR) | |
9385eb3d | 482 | + break; |
eb1cde05 | 483 | +#endif /* VECTORS */ |
9385eb3d A |
484 | if (flags & INTMAX_SIZE) |
485 | ujval = UJARG(); | |
486 | else | |
34e8f829 | 487 | @@ -1093,6 +1223,7 @@ number: if ((dprec = prec) >= 0) |
224c7076 A |
488 | * ``The result of converting a zero value with an |
489 | * explicit precision of zero is no characters.'' | |
490 | * -- ANSI X3J11 | |
491 | + * except for %#.0o and zero value | |
492 | */ | |
493 | cp = buf + BUF; | |
494 | if (flags & INTMAX_SIZE) { | |
34e8f829 | 495 | @@ -1102,7 +1233,7 @@ number: if ((dprec = prec) >= 0) |
224c7076 A |
496 | flags & GROUPING, thousands_sep, |
497 | grouping); | |
498 | } else { | |
499 | - if (ulval != 0 || prec != 0) | |
500 | + if (ulval != 0 || prec != 0 || (flags & ALT)) | |
501 | cp = __ultoa(ulval, cp, base, | |
502 | flags & ALT, xdigs, | |
503 | flags & GROUPING, thousands_sep, | |
34e8f829 A |
504 | @@ -1110,8 +1241,13 @@ number: if ((dprec = prec) >= 0) |
505 | } | |
506 | size = buf + BUF - cp; | |
9385eb3d | 507 | if (size > BUF) /* should never happen */ |
34e8f829 A |
508 | - abort(); |
509 | + LIBC_ABORT("size %d > BUF %d", size, BUF); | |
9385eb3d | 510 | break; |
eb1cde05 | 511 | +#ifdef VECTORS |
9385eb3d | 512 | + case 'v': |
eb1cde05 A |
513 | + flags |= VECTOR; |
514 | + goto rflag; | |
515 | +#endif /* VECTORS */ | |
9385eb3d A |
516 | default: /* "%?" prints ?, unless ? is NUL */ |
517 | if (ch == '\0') | |
518 | goto done; | |
34e8f829 | 519 | @@ -1123,6 +1259,290 @@ number: if ((dprec = prec) >= 0) |
9385eb3d A |
520 | break; |
521 | } | |
522 | ||
eb1cde05 | 523 | +#ifdef VECTORS |
9385eb3d A |
524 | + if (flags & VECTOR) { |
525 | + /* | |
526 | + * Do the minimum amount of work necessary to construct | |
527 | + * a format specifier that can be used to recursively | |
528 | + * call vfprintf() for each element in the vector. | |
529 | + */ | |
530 | + int i, j; /* Counter. */ | |
531 | + int vcnt; /* Number of elements in vector. */ | |
532 | + char *vfmt; /* Pointer to format specifier. */ | |
eb1cde05 A |
533 | +#define EXTRAHH 2 |
534 | + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */ | |
9385eb3d A |
535 | + int vwidth = 0; /* Width specified via '*'. */ |
536 | + int vprec = 0; /* Precision specified via '*'. */ | |
9385eb3d A |
537 | + char *vstr; /* Used for asprintf(). */ |
538 | + int vlen; /* Length returned by asprintf(). */ | |
eb1cde05 A |
539 | + enum { |
540 | + V_CHAR, V_SHORT, V_INT, | |
541 | + V_PCHAR, V_PSHORT, V_PINT, | |
542 | + V_FLOAT, | |
543 | +#ifdef V64TYPE | |
544 | + V_LONGLONG, V_PLONGLONG, | |
545 | + V_DOUBLE, | |
546 | +#endif /* V64TYPE */ | |
547 | + } vtype; | |
9385eb3d | 548 | + |
eb1cde05 | 549 | + vval.vectorarg = GETARG(VECTORTYPE); |
9385eb3d A |
550 | + /* |
551 | + * Set vfmt. If vfmt_buf may not be big enough, | |
552 | + * malloc() space, taking care to free it later. | |
eb1cde05 | 553 | + * (EXTRAHH is for possible extra "hh") |
9385eb3d | 554 | + */ |
eb1cde05 | 555 | + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf)) |
9385eb3d A |
556 | + vfmt = vfmt_buf; |
557 | + else | |
eb1cde05 | 558 | + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1); |
9385eb3d A |
559 | + |
560 | + /* Set the separator character, if not specified. */ | |
561 | + if (vsep == 'X') { | |
562 | + if (ch == 'c') | |
563 | + vsep = '\0'; | |
564 | + else | |
565 | + vsep = ' '; | |
566 | + } | |
567 | + | |
568 | + /* Create the format specifier. */ | |
569 | + for (i = j = 0; i < &fmt[-1] - pct; i++) { | |
570 | + switch (pct[i]) { | |
571 | + case ',': case ';': case ':': case '_': | |
572 | + case 'v': case 'h': case 'l': | |
573 | + /* Ignore. */ | |
574 | + break; | |
575 | + case '*': | |
576 | + if (pct[i - 1] != '.') | |
577 | + vwidth = 1; | |
578 | + else | |
579 | + vprec = 1; | |
580 | + /* FALLTHROUGH */ | |
581 | + default: | |
582 | + vfmt[j++] = pct[i]; | |
583 | + } | |
584 | + } | |
585 | + | |
586 | + /* | |
587 | + * Determine the number of elements in the vector and | |
588 | + * finish up the format specifier. | |
589 | + */ | |
590 | + if (flags & SHORTINT) { | |
eb1cde05 A |
591 | + switch (ch) { |
592 | + case 'c': | |
593 | + vtype = V_SHORT; | |
594 | + break; | |
595 | + case 'p': | |
596 | + vtype = V_PSHORT; | |
597 | + break; | |
598 | + default: | |
59e0d9fe | 599 | + vfmt[j++] = 'h'; |
eb1cde05 A |
600 | + vtype = V_SHORT; |
601 | + break; | |
602 | + } | |
9385eb3d A |
603 | + vcnt = 8; |
604 | + } else if (flags & LONGINT) { | |
f74c7596 | 605 | + vcnt = 4; |
eb1cde05 A |
606 | + vtype = (ch == 'p') ? V_PINT : V_INT; |
607 | +#ifdef V64TYPE | |
608 | + } else if (flags & LLONGINT) { | |
609 | + switch (ch) { | |
610 | + case 'a': | |
611 | + case 'A': | |
612 | + case 'e': | |
613 | + case 'E': | |
614 | + case 'f': | |
615 | + case 'g': | |
616 | + case 'G': | |
617 | + vcnt = 2; | |
618 | + vtype = V_DOUBLE; | |
619 | + break; | |
620 | + case 'd': | |
621 | + case 'i': | |
622 | + case 'u': | |
623 | + case 'o': | |
624 | + case 'p': | |
625 | + case 'x': | |
626 | + case 'X': | |
627 | + vfmt[j++] = 'l'; | |
628 | + vfmt[j++] = 'l'; | |
629 | + vcnt = 2; | |
630 | + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG; | |
631 | + break; | |
632 | + default: | |
633 | + /* | |
634 | + * The default case should never | |
635 | + * happen. | |
636 | + */ | |
637 | + case 'c': | |
638 | + vcnt = 16; | |
639 | + vtype = V_CHAR; | |
640 | + } | |
641 | +#endif /* V64TYPE */ | |
9385eb3d A |
642 | + } else { |
643 | + switch (ch) { | |
644 | + case 'a': | |
645 | + case 'A': | |
646 | + case 'e': | |
647 | + case 'E': | |
648 | + case 'f': | |
649 | + case 'g': | |
650 | + case 'G': | |
651 | + vcnt = 4; | |
eb1cde05 | 652 | + vtype = V_FLOAT; |
9385eb3d A |
653 | + break; |
654 | + default: | |
655 | + /* | |
656 | + * The default case should never | |
657 | + * happen. | |
658 | + */ | |
9385eb3d A |
659 | + case 'd': |
660 | + case 'i': | |
661 | + case 'u': | |
662 | + case 'o': | |
9385eb3d A |
663 | + case 'x': |
664 | + case 'X': | |
eb1cde05 A |
665 | + vfmt[j++] = 'h'; |
666 | + vfmt[j++] = 'h'; | |
667 | + /* drop through */ | |
668 | + case 'p': | |
669 | + case 'c': | |
9385eb3d | 670 | + vcnt = 16; |
eb1cde05 | 671 | + vtype = (ch == 'p') ? V_PCHAR : V_CHAR; |
9385eb3d A |
672 | + } |
673 | + } | |
674 | + vfmt[j++] = ch; | |
675 | + vfmt[j++] = '\0'; | |
676 | + | |
677 | +/* Get a vector element. */ | |
eb1cde05 A |
678 | +#ifdef V64TYPE |
679 | +#define VPRINT(type, ind, args...) do { \ | |
680 | + switch (type) { \ | |
681 | + case V_CHAR: \ | |
682 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \ | |
683 | + break; \ | |
684 | + case V_PCHAR: \ | |
685 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \ | |
686 | + break; \ | |
687 | + case V_SHORT: \ | |
688 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \ | |
689 | + break; \ | |
690 | + case V_PSHORT: \ | |
691 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \ | |
692 | + break; \ | |
693 | + case V_INT: \ | |
694 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \ | |
695 | + break; \ | |
696 | + case V_PINT: \ | |
697 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \ | |
698 | + break; \ | |
699 | + case V_LONGLONG: \ | |
700 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \ | |
701 | + break; \ | |
702 | + case V_PLONGLONG: \ | |
703 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \ | |
704 | + break; \ | |
705 | + case V_FLOAT: \ | |
706 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \ | |
707 | + break; \ | |
708 | + case V_DOUBLE: \ | |
709 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \ | |
710 | + break; \ | |
711 | + } \ | |
712 | + ret += vlen; \ | |
713 | + PRINT(vstr, vlen); \ | |
714 | + FLUSH(); \ | |
715 | + free(vstr); \ | |
716 | +} while (0) | |
717 | +#else /* !V64TYPE */ | |
718 | +#define VPRINT(type, ind, args...) do { \ | |
719 | + switch (type) { \ | |
720 | + case V_CHAR: \ | |
721 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \ | |
722 | + break; \ | |
723 | + case V_PCHAR: \ | |
724 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \ | |
725 | + break; \ | |
726 | + case V_SHORT: \ | |
727 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \ | |
728 | + break; \ | |
729 | + case V_PSHORT: \ | |
730 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \ | |
731 | + break; \ | |
732 | + case V_INT: \ | |
733 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \ | |
734 | + break; \ | |
735 | + case V_PINT: \ | |
736 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \ | |
737 | + break; \ | |
738 | + case V_FLOAT: \ | |
739 | + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \ | |
740 | + break; \ | |
9385eb3d A |
741 | + } \ |
742 | + ret += vlen; \ | |
743 | + PRINT(vstr, vlen); \ | |
744 | + FLUSH(); \ | |
745 | + free(vstr); \ | |
746 | +} while (0) | |
eb1cde05 | 747 | +#endif /* V64TYPE */ |
9385eb3d A |
748 | + |
749 | + /* Actually print. */ | |
750 | + if (vwidth == 0) { | |
751 | + if (vprec == 0) { | |
752 | + /* First element. */ | |
eb1cde05 | 753 | + VPRINT(vtype, 0); |
9385eb3d A |
754 | + for (i = 1; i < vcnt; i++) { |
755 | + /* Separator. */ | |
eb1cde05 A |
756 | + if(vsep) |
757 | + PRINT(&vsep, 1); | |
9385eb3d A |
758 | + |
759 | + /* Element. */ | |
eb1cde05 | 760 | + VPRINT(vtype, i); |
9385eb3d A |
761 | + } |
762 | + } else { | |
763 | + /* First element. */ | |
eb1cde05 | 764 | + VPRINT(vtype, 0, prec); |
9385eb3d A |
765 | + for (i = 1; i < vcnt; i++) { |
766 | + /* Separator. */ | |
eb1cde05 A |
767 | + if(vsep) |
768 | + PRINT(&vsep, 1); | |
9385eb3d A |
769 | + |
770 | + /* Element. */ | |
eb1cde05 | 771 | + VPRINT(vtype, i, prec); |
9385eb3d A |
772 | + } |
773 | + } | |
774 | + } else { | |
775 | + if (vprec == 0) { | |
776 | + /* First element. */ | |
eb1cde05 | 777 | + VPRINT(vtype, 0, width); |
9385eb3d A |
778 | + for (i = 1; i < vcnt; i++) { |
779 | + /* Separator. */ | |
eb1cde05 A |
780 | + if(vsep) |
781 | + PRINT(&vsep, 1); | |
9385eb3d A |
782 | + |
783 | + /* Element. */ | |
eb1cde05 | 784 | + VPRINT(vtype, i, width); |
9385eb3d A |
785 | + } |
786 | + } else { | |
787 | + /* First element. */ | |
eb1cde05 | 788 | + VPRINT(vtype, 0, width, prec); |
9385eb3d A |
789 | + for (i = 1; i < vcnt; i++) { |
790 | + /* Separator. */ | |
eb1cde05 A |
791 | + if(vsep) |
792 | + PRINT(&vsep, 1); | |
9385eb3d A |
793 | + |
794 | + /* Element. */ | |
eb1cde05 | 795 | + VPRINT(vtype, i, width, prec); |
9385eb3d A |
796 | + } |
797 | + } | |
798 | + } | |
799 | +#undef VPRINT | |
800 | + | |
801 | + if (vfmt != vfmt_buf) | |
802 | + free(vfmt); | |
803 | + | |
804 | + continue; | |
805 | + } | |
eb1cde05 | 806 | +#endif /* VECTORS */ |
9385eb3d A |
807 | /* |
808 | * All reasonable formats wind up here. At this point, `cp' | |
809 | * points to a string which (if not flags&LADJUST) should be | |
34e8f829 | 810 | @@ -1178,7 +1598,7 @@ number: if ((dprec = prec) >= 0) |
224c7076 A |
811 | if (expt <= 0) { |
812 | PRINT(zeroes, 1); | |
813 | if (prec || flags & ALT) | |
814 | - PRINT(decimal_point, 1); | |
815 | + PRINT(decimal_point, strlen(decimal_point)); | |
816 | PAD(-expt, zeroes); | |
817 | /* already handled initial 0's */ | |
818 | prec += expt; | |
34e8f829 | 819 | @@ -1203,14 +1623,14 @@ number: if ((dprec = prec) >= 0) |
224c7076 A |
820 | cp = dtoaend; |
821 | } | |
822 | if (prec || flags & ALT) | |
823 | - PRINT(decimal_point,1); | |
824 | + PRINT(decimal_point, strlen(decimal_point)); | |
825 | } | |
826 | PRINTANDPAD(cp, dtoaend, prec, zeroes); | |
827 | } else { /* %[eE] or sufficiently long %[gG] */ | |
828 | if (prec > 1 || flags & ALT) { | |
829 | buf[0] = *cp++; | |
830 | - buf[1] = *decimal_point; | |
831 | - PRINT(buf, 2); | |
832 | + PRINT(buf, 1); | |
833 | + PRINT(decimal_point, strlen(decimal_point)); | |
834 | PRINT(cp, ndig-1); | |
835 | PAD(prec - ndig, zeroes); | |
836 | } else /* XeYYY */ | |
34e8f829 | 837 | @@ -1406,6 +1826,11 @@ reswitch: switch (ch) { |
9385eb3d A |
838 | if (flags & LONGINT) |
839 | ADDTYPE(T_WINT); | |
840 | else | |
eb1cde05 | 841 | +#ifdef VECTORS |
9385eb3d A |
842 | + if (flags & VECTOR) |
843 | + ADDTYPE(T_VECTOR); | |
844 | + else | |
eb1cde05 | 845 | +#endif /* VECTORS */ |
9385eb3d A |
846 | ADDTYPE(T_INT); |
847 | break; | |
848 | case 'D': | |
34e8f829 | 849 | @@ -1413,6 +1838,11 @@ reswitch: switch (ch) { |
9385eb3d A |
850 | /*FALLTHROUGH*/ |
851 | case 'd': | |
852 | case 'i': | |
eb1cde05 | 853 | +#ifdef VECTORS |
9385eb3d A |
854 | + if (flags & VECTOR) |
855 | + ADDTYPE(T_VECTOR); | |
856 | + else | |
857 | +#endif | |
858 | ADDSARG(); | |
859 | break; | |
59e0d9fe | 860 | #ifndef NO_FLOATING_POINT |
34e8f829 | 861 | @@ -1421,8 +1851,14 @@ reswitch: switch (ch) { |
224c7076 A |
862 | case 'e': |
863 | case 'E': | |
9385eb3d | 864 | case 'f': |
224c7076 | 865 | + case 'F': |
9385eb3d A |
866 | case 'g': |
867 | case 'G': | |
eb1cde05 | 868 | +#ifdef VECTORS |
9385eb3d A |
869 | + if (flags & VECTOR) |
870 | + ADDTYPE(T_VECTOR); | |
871 | + else | |
eb1cde05 | 872 | +#endif /* VECTORS */ |
9385eb3d A |
873 | if (flags & LONGDBL) |
874 | ADDTYPE(T_LONG_DOUBLE); | |
875 | else | |
34e8f829 | 876 | @@ -1451,9 +1887,19 @@ reswitch: switch (ch) { |
9385eb3d A |
877 | flags |= LONGINT; |
878 | /*FALLTHROUGH*/ | |
879 | case 'o': | |
eb1cde05 | 880 | +#ifdef VECTORS |
9385eb3d A |
881 | + if (flags & VECTOR) |
882 | + ADDTYPE(T_VECTOR); | |
883 | + else | |
eb1cde05 | 884 | +#endif /* VECTORS */ |
9385eb3d A |
885 | ADDUARG(); |
886 | break; | |
887 | case 'p': | |
eb1cde05 | 888 | +#ifdef VECTORS |
9385eb3d A |
889 | + if (flags & VECTOR) |
890 | + ADDTYPE(T_VECTOR); | |
891 | + else | |
eb1cde05 | 892 | +#endif /* VECTORS */ |
9385eb3d A |
893 | ADDTYPE(TP_VOID); |
894 | break; | |
895 | case 'S': | |
34e8f829 | 896 | @@ -1471,6 +1917,11 @@ reswitch: switch (ch) { |
9385eb3d A |
897 | case 'u': |
898 | case 'X': | |
899 | case 'x': | |
eb1cde05 | 900 | +#ifdef VECTORS |
9385eb3d A |
901 | + if (flags & VECTOR) |
902 | + ADDTYPE(T_VECTOR); | |
903 | + else | |
eb1cde05 | 904 | +#endif /* VECTORS */ |
9385eb3d A |
905 | ADDUARG(); |
906 | break; | |
907 | default: /* "%?" prints ?, unless ? is NUL */ | |
34e8f829 | 908 | @@ -1537,7 +1988,7 @@ done: |
3d9156a7 A |
909 | (*argtable) [n].sizearg = va_arg (ap, size_t); |
910 | break; | |
911 | case TP_SIZET: | |
912 | - (*argtable) [n].psizearg = va_arg (ap, ssize_t *); | |
913 | + (*argtable) [n].psizearg = va_arg (ap, size_t *); | |
914 | break; | |
915 | case T_INTMAXT: | |
916 | (*argtable) [n].intmaxarg = va_arg (ap, intmax_t); | |
34e8f829 | 917 | @@ -1556,6 +2007,11 @@ done: |
9385eb3d A |
918 | (*argtable) [n].longdoublearg = va_arg (ap, long double); |
919 | break; | |
920 | #endif | |
eb1cde05 | 921 | +#ifdef VECTORS |
9385eb3d | 922 | + case T_VECTOR: |
eb1cde05 | 923 | + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE); |
9385eb3d | 924 | + break; |
eb1cde05 | 925 | +#endif /* VECTORS */ |
9385eb3d A |
926 | case TP_CHAR: |
927 | (*argtable) [n].pchararg = va_arg (ap, char *); | |
928 | break; | |
34e8f829 A |
929 | @@ -1590,12 +2046,12 @@ __grow_type_table (int nextarg, enum typ |
930 | newsize = nextarg + 1; | |
931 | if (oldsize == STATIC_ARG_TBL_SIZE) { | |
932 | if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL) | |
933 | - abort(); /* XXX handle better */ | |
934 | + LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */ | |
935 | bcopy(oldtable, newtable, oldsize * sizeof(enum typeid)); | |
936 | } else { | |
937 | newtable = reallocf(oldtable, newsize * sizeof(enum typeid)); | |
938 | if (newtable == NULL) | |
939 | - abort(); /* XXX handle better */ | |
940 | + LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */ | |
941 | } | |
942 | for (n = oldsize; n < newsize; n++) | |
943 | newtable[n] = T_UNUSED; |