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