]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfprintf.c.patch
Libc-594.9.5.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfprintf.c.patch
CommitLineData
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;