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