]> git.saurik.com Git - apple/libc.git/blame - stdio/FreeBSD/vfprintf.c.patch
Libc-763.11.tar.gz
[apple/libc.git] / stdio / FreeBSD / vfprintf.c.patch
CommitLineData
1f2f436a
A
1--- vfprintf.c.orig 2010-11-22 22:37:24.000000000 -0800
2+++ vfprintf.c 2010-11-22 22:38:38.000000000 -0800
3@@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
3d9156a7 4 #include <sys/cdefs.h>
1f2f436a 5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
3d9156a7
A
6
7+#include "xlocale_private.h"
8+
9 /*
10 * Actual printf innards.
11 *
1f2f436a 12@@ -54,7 +56,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
51631861
A
13 #include <stdlib.h>
14 #include <string.h>
15 #include <wchar.h>
1f2f436a
A
16+#if 0 // xprintf pending API review
17 #include <printf.h>
18+#endif
51631861
A
19+#include <errno.h>
20
21 #include <stdarg.h>
22 #include "un-namespace.h"
1f2f436a 23@@ -64,10 +69,11 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
9385eb3d 24 #include "fvwrite.h"
1f2f436a 25 #include "printflocal.h"
9385eb3d 26
1f2f436a
A
27-static int __sprint(FILE *, struct __suio *);
28-static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
29- __noinline;
30-static char *__wcsconv(wchar_t *, int);
31+static int __sprint(FILE *, locale_t, struct __suio *);
32+static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
33+static char *__wcsconv(wchar_t *, int, locale_t);
9385eb3d 34+
1f2f436a 35+__private_extern__ const char *__fix_nogrouping(const char *);
9385eb3d 36
1f2f436a
A
37 #define CHAR char
38 #include "printfcommon.h"
39@@ -87,12 +93,12 @@ struct grouping_state {
40 * of bytes that will be needed.
41 */
42 static int
43-grouping_init(struct grouping_state *gs, int ndigits)
44+grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
45 {
46 struct lconv *locale;
9385eb3d 47
1f2f436a
A
48- locale = localeconv();
49- gs->grouping = locale->grouping;
50+ locale = localeconv_l(loc);
51+ gs->grouping = __fix_nogrouping(locale->grouping);
52 gs->thousands_sep = locale->thousands_sep;
53 gs->thousep_len = strlen(gs->thousands_sep);
54
55@@ -116,11 +122,11 @@ grouping_init(struct grouping_state *gs,
56 */
57 static int
58 grouping_print(struct grouping_state *gs, struct io_state *iop,
59- const CHAR *cp, const CHAR *ep)
60+ const CHAR *cp, const CHAR *ep, locale_t loc)
61 {
62 const CHAR *cp0 = cp;
63
64- if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
65+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
66 return (-1);
67 cp += gs->lead;
68 while (gs->nseps > 0 || gs->nrepeats > 0) {
69@@ -130,9 +136,9 @@ grouping_print(struct grouping_state *gs
70 gs->grouping--;
71 gs->nseps--;
72 }
73- if (io_print(iop, gs->thousands_sep, gs->thousep_len))
74+ if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
75 return (-1);
76- if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
77+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
78 return (-1);
79 cp += *gs->grouping;
80 }
81@@ -146,7 +152,7 @@ grouping_print(struct grouping_state *gs
82 * then reset it so that it can be reused.
83 */
84 static int
85-__sprint(FILE *fp, struct __suio *uio)
86+__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
87 {
88 int err;
9385eb3d 89
1f2f436a 90@@ -166,11 +172,14 @@ __sprint(FILE *fp, struct __suio *uio)
3d9156a7
A
91 * worries about ungetc buffers and so forth.
92 */
93 static int
94-__sbprintf(FILE *fp, const char *fmt, va_list ap)
95+__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap)
96 {
97 int ret;
98 FILE fake;
1f2f436a
A
99 unsigned char buf[BUFSIZ];
100+ struct __sFILEX ext;
101+ fake._extra = &ext;
102+ INITEXTRA(&fake);
103
104 /* XXX This is probably not needed. */
105 if (prepwrite(fp) != 0)
106@@ -190,7 +199,7 @@ __sbprintf(FILE *fp, const char *fmt, va
3d9156a7
A
107 fake._lbfsize = 0; /* not actually used, but Just In Case */
108
109 /* do the work, then copy any error status */
110- ret = __vfprintf(&fake, fmt, ap);
111+ ret = __vfprintf(&fake, loc, fmt, ap);
112 if (ret >= 0 && __fflush(&fake))
113 ret = EOF;
114 if (fake._flags & __SERR)
1f2f436a
A
115@@ -205,7 +214,7 @@ __sbprintf(FILE *fp, const char *fmt, va
116 * string ends is null-terminated.
3d9156a7
A
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;
1f2f436a
A
124@@ -218,7 +227,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
125 if (prec < 0) {
3d9156a7
A
126 p = wcsarg;
127 mbs = initial;
128- nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
129+ nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
130 if (nbytes == (size_t)-1)
131 return (NULL);
1f2f436a
A
132 } else {
133@@ -234,7 +243,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
134 p = wcsarg;
135 mbs = initial;
136 for (;;) {
137- clen = wcrtomb(buf, *p++, &mbs);
138+ clen = wcrtomb_l(buf, *p++, &mbs, loc);
139 if (clen == 0 || clen == (size_t)-1 ||
140 nbytes + clen > prec)
141 break;
142@@ -248,8 +257,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
143 /* Fill the output buffer. */
3d9156a7
A
144 p = wcsarg;
145 mbs = initial;
1f2f436a
A
146- if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
147- nbytes, &mbs)) == (size_t)-1) {
148+ if ((nbytes = wcsrtombs_l(convbuf, (const wchar_t **)&p,
149+ nbytes, &mbs, loc)) == (size_t)-1) {
150 free(convbuf);
151 return (NULL);
152 }
153@@ -261,22 +270,30 @@ __wcsconv(wchar_t *wcsarg, int prec)
224c7076
A
154 * MT-safe version
155 */
224c7076 156 int
1f2f436a
A
157-vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
158+vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
224c7076 159
1f2f436a 160 {
3d9156a7
A
161 int ret;
162
3d9156a7 163+ NORMALIZE_LOCALE(loc);
1f2f436a
A
164 FLOCKFILE(fp);
165 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
166 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
167 fp->_file >= 0)
168- ret = __sbprintf(fp, fmt0, ap);
169+ ret = __sbprintf(fp, loc, fmt0, ap);
170 else
171- ret = __vfprintf(fp, fmt0, ap);
172+ ret = __vfprintf(fp, loc, fmt0, ap);
3d9156a7
A
173 FUNLOCKFILE(fp);
174 return (ret);
175 }
9385eb3d 176
1f2f436a
A
177+int
178+vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
179+
180+{
181+ return vfprintf_l(fp, __current_locale(), fmt0, ap);
182+}
183+
184 /*
185 * The size of the buffer we use as scratch space for integer
186 * conversions, among other things. We need enough space to
187@@ -291,8 +308,8 @@ vfprintf(FILE * __restrict fp, const cha
9385eb3d
A
188 /*
189 * Non-MT-safe version
3d9156a7
A
190 */
191-int
192-__vfprintf(FILE *fp, const char *fmt0, va_list ap)
193+__private_extern__ int
194+__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
195 {
196 char *fmt; /* format string */
197 int ch; /* character from fmt */
1f2f436a
A
198@@ -335,6 +352,11 @@ __vfprintf(FILE *fp, const char *fmt0, v
199 char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
200 char *dtoaresult; /* buffer allocated by dtoa */
9385eb3d 201 #endif
eb1cde05 202+#ifdef VECTORS
9385eb3d
A
203+ union arg vval; /* Vector argument. */
204+ char *pct; /* Pointer to '%' at beginning of specifier. */
205+ char vsep; /* Vector separator character. */
206+#endif
207 u_long ulval; /* integer arguments %[diouxX] */
208 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
209 int base; /* base for [diouxX] conversion */
1f2f436a
A
210@@ -357,19 +379,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
211
212 /* BEWARE, these `goto error' on error. */
213 #define PRINT(ptr, len) { \
214- if (io_print(&io, (ptr), (len))) \
215+ if (io_print(&io, (ptr), (len), loc)) \
216 goto error; \
217 }
218 #define PAD(howmany, with) { \
219- if (io_pad(&io, (howmany), (with))) \
220+ if (io_pad(&io, (howmany), (with), loc)) \
221 goto error; \
222 }
223 #define PRINTANDPAD(p, ep, len, with) { \
224- if (io_printandpad(&io, (p), (ep), (len), (with))) \
225+ if (io_printandpad(&io, (p), (ep), (len), (with), loc)) \
226 goto error; \
227 }
228 #define FLUSH() { \
229- if (io_flush(&io)) \
230+ if (io_flush(&io, loc)) \
231 goto error; \
232 }
233
234@@ -405,7 +427,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
224c7076 235 #define UJARG() \
34e8f829
A
236 (flags&INTMAXT ? GETARG(uintmax_t) : \
237 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
238- flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
1f2f436a 239+ flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
34e8f829
A
240 (uintmax_t)GETARG(unsigned long long))
241
242 /*
1f2f436a 243@@ -436,14 +458,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
9385eb3d
A
244 val = GETARG (int); \
245 }
246
1f2f436a
A
247+#if 0 // xprintf pending API review
248 if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
249 __use_xprintf = 1;
250 if (__use_xprintf > 0)
251- return (__xvprintf(fp, fmt0, ap));
252+ return (__xvprintf(fp, loc, fmt0, ap));
253+#endif
254
51631861 255 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
3d9156a7
A
256- if (prepwrite(fp) != 0)
257+ if (prepwrite(fp) != 0) {
51631861
A
258+ errno = EBADF;
259 return (EOF);
260+ }
224c7076 261+ ORIENT(fp, -1);
51631861 262
1f2f436a 263 convbuf = NULL;
3d9156a7 264 fmt = (char *)fmt0;
1f2f436a
A
265@@ -454,7 +481,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
266 ret = 0;
267 #ifndef NO_FLOATING_POINT
268 dtoaresult = NULL;
269- decimal_point = localeconv()->decimal_point;
270+ decimal_point = localeconv_l(loc)->decimal_point;
271 /* The overwhelmingly common case is decpt_len == 1. */
272 decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
273 #endif
274@@ -475,6 +502,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
9385eb3d
A
275 }
276 if (ch == '\0')
277 goto done;
eb1cde05 278+#ifdef VECTORS
9385eb3d 279+ pct = fmt;
eb1cde05 280+#endif /* VECTORS */
9385eb3d
A
281 fmt++; /* skip over '%' */
282
283 flags = 0;
1f2f436a
A
284@@ -484,6 +514,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
285 gs.grouping = NULL;
9385eb3d
A
286 sign = '\0';
287 ox[1] = '\0';
eb1cde05 288+#ifdef VECTORS
9385eb3d 289+ vsep = 'X'; /* Illegal value, changed to defaults later. */
eb1cde05 290+#endif /* VECTORS */
9385eb3d
A
291
292 rflag: ch = *fmt++;
293 reswitch: switch (ch) {
1f2f436a 294@@ -499,6 +532,11 @@ reswitch: switch (ch) {
9385eb3d
A
295 case '#':
296 flags |= ALT;
297 goto rflag;
eb1cde05 298+#ifdef VECTORS
9385eb3d
A
299+ case ',': case ';': case ':': case '_':
300+ vsep = ch;
301+ goto rflag;
eb1cde05 302+#endif /* VECTORS */
9385eb3d
A
303 case '*':
304 /*-
305 * ``A negative field width argument is taken as a
1f2f436a 306@@ -595,14 +633,18 @@ reswitch: switch (ch) {
59e0d9fe
A
307 flags |= LONGINT;
308 /*FALLTHROUGH*/
309 case 'c':
eb1cde05
A
310+#ifdef VECTORS
311+ if (flags & VECTOR)
59e0d9fe 312+ break;
eb1cde05 313+#endif /* VECTORS */
59e0d9fe
A
314 if (flags & LONGINT) {
315 static const mbstate_t initial;
316 mbstate_t mbs;
3d9156a7
A
317 size_t mbseqlen;
318
319 mbs = initial;
320- mbseqlen = wcrtomb(cp = buf,
321- (wchar_t)GETARG(wint_t), &mbs);
322+ mbseqlen = wcrtomb_l(cp = buf,
323+ (wchar_t)GETARG(wint_t), &mbs, loc);
324 if (mbseqlen == (size_t)-1) {
325 fp->_flags |= __SERR;
326 goto error;
1f2f436a 327@@ -619,6 +661,10 @@ reswitch: switch (ch) {
9385eb3d
A
328 /*FALLTHROUGH*/
329 case 'd':
330 case 'i':
eb1cde05
A
331+#ifdef VECTORS
332+ if (flags & VECTOR)
9385eb3d 333+ break;
eb1cde05 334+#endif /* VECTORS */
9385eb3d
A
335 if (flags & INTMAX_SIZE) {
336 ujval = SJARG();
337 if ((intmax_t)ujval < 0) {
1f2f436a 338@@ -637,6 +683,12 @@ reswitch: switch (ch) {
59e0d9fe 339 #ifndef NO_FLOATING_POINT
9385eb3d
A
340 case 'a':
341 case 'A':
eb1cde05 342+#ifdef VECTORS
9385eb3d
A
343+ if (flags & VECTOR) {
344+ flags |= FPT;
9385eb3d
A
345+ break;
346+ }
eb1cde05 347+#endif /* VECTORS */
9385eb3d
A
348 if (ch == 'a') {
349 ox[1] = 'x';
350 xdigs = xdigs_lower;
1f2f436a 351@@ -650,6 +702,12 @@ reswitch: switch (ch) {
3d9156a7
A
352 prec++;
353 if (dtoaresult != NULL)
354 freedtoa(dtoaresult);
355+#ifdef LDBL_COMPAT
356+ fparg.dbl = GETARG(double);
357+ dtoaresult = cp =
358+ __hdtoa(fparg.dbl, xdigs, prec,
359+ &expt, &signflag, &dtoaend);
360+#else /* !LDBL_COMPAT */
361 if (flags & LONGDBL) {
362 fparg.ldbl = GETARG(long double);
363 dtoaresult = cp =
1f2f436a 364@@ -661,6 +719,7 @@ reswitch: switch (ch) {
3d9156a7
A
365 __hdtoa(fparg.dbl, xdigs, prec,
366 &expt, &signflag, &dtoaend);
367 }
368+#endif /* LDBL_COMPAT */
369 if (prec < 0)
370 prec = dtoaend - cp;
371 if (expt == INT_MAX)
1f2f436a 372@@ -668,6 +727,12 @@ reswitch: switch (ch) {
59e0d9fe 373 goto fp_common;
9385eb3d
A
374 case 'e':
375 case 'E':
eb1cde05 376+#ifdef VECTORS
9385eb3d
A
377+ if (flags & VECTOR) {
378+ flags |= FPT;
9385eb3d
A
379+ break;
380+ }
eb1cde05 381+#endif /* VECTORS */
9385eb3d
A
382 expchar = ch;
383 if (prec < 0) /* account for digit before decpt */
384 prec = DEFPREC + 1;
1f2f436a 385@@ -676,10 +741,22 @@ reswitch: switch (ch) {
9385eb3d
A
386 goto fp_begin;
387 case 'f':
388 case 'F':
eb1cde05 389+#ifdef VECTORS
9385eb3d
A
390+ if (flags & VECTOR) {
391+ flags |= FPT;
9385eb3d
A
392+ break;
393+ }
eb1cde05 394+#endif /* VECTORS */
9385eb3d
A
395 expchar = '\0';
396 goto fp_begin;
397 case 'g':
398 case 'G':
eb1cde05 399+#ifdef VECTORS
9385eb3d
A
400+ if (flags & VECTOR) {
401+ flags |= FPT;
9385eb3d
A
402+ break;
403+ }
eb1cde05 404+#endif /* VECTORS */
9385eb3d
A
405 expchar = ch - ('g' - 'e');
406 if (prec == 0)
407 prec = 1;
1f2f436a 408@@ -688,6 +765,14 @@ fp_begin:
3d9156a7
A
409 prec = DEFPREC;
410 if (dtoaresult != NULL)
411 freedtoa(dtoaresult);
412+#ifdef LDBL_COMPAT
413+ fparg.dbl = GETARG(double);
414+ dtoaresult = cp =
415+ dtoa(fparg.dbl, expchar ? 2 : 3, prec,
416+ &expt, &signflag, &dtoaend);
417+ if (expt == 9999)
418+ expt = INT_MAX;
419+#else /* !LDBL_COMPAT */
420 if (flags & LONGDBL) {
421 fparg.ldbl = GETARG(long double);
422 dtoaresult = cp =
1f2f436a 423@@ -701,6 +786,7 @@ fp_begin:
3d9156a7
A
424 if (expt == 9999)
425 expt = INT_MAX;
426 }
427+#endif /* LDBL_COMPAT */
428 fp_common:
429 if (signflag)
430 sign = '-';
1f2f436a
A
431@@ -750,37 +836,46 @@ fp_common:
432 if (prec || flags & ALT)
433 size += prec + decpt_len;
434 if ((flags & GROUPING) && expt > 0)
435- size += grouping_init(&gs, expt);
436+ size += grouping_init(&gs, expt, loc);
437 }
438 break;
439 #endif /* !NO_FLOATING_POINT */
440 case 'n':
441+ {
442 /*
443 * Assignment-like behavior is specified if the
444 * value overflows or is otherwise unrepresentable.
445 * C99 says to use `signed char' for %hhn conversions.
446 */
447- if (flags & LLONGINT)
448- *GETARG(long long *) = ret;
449+ void *ptr = GETARG(void *);
450+ if (ptr == NULL)
451+ continue;
452+ else if (flags & LLONGINT)
453+ *(long long *)ptr = ret;
454 else if (flags & SIZET)
455- *GETARG(ssize_t *) = (ssize_t)ret;
456+ *(ssize_t *)ptr = (ssize_t)ret;
457 else if (flags & PTRDIFFT)
458- *GETARG(ptrdiff_t *) = ret;
459+ *(ptrdiff_t *)ptr = ret;
460 else if (flags & INTMAXT)
461- *GETARG(intmax_t *) = ret;
462+ *(intmax_t *)ptr = ret;
463 else if (flags & LONGINT)
464- *GETARG(long *) = ret;
465+ *(long *)ptr = ret;
466 else if (flags & SHORTINT)
467- *GETARG(short *) = ret;
468+ *(short *)ptr = ret;
469 else if (flags & CHARINT)
470- *GETARG(signed char *) = ret;
471+ *(signed char *)ptr = ret;
472 else
473- *GETARG(int *) = ret;
474+ *(int *)ptr = ret;
475 continue; /* no output */
476+ }
477 case 'O':
9385eb3d
A
478 flags |= LONGINT;
479 /*FALLTHROUGH*/
480 case 'o':
eb1cde05
A
481+#ifdef VECTORS
482+ if (flags & VECTOR)
9385eb3d 483+ break;
eb1cde05 484+#endif /* VECTORS */
9385eb3d
A
485 if (flags & INTMAX_SIZE)
486 ujval = UJARG();
487 else
1f2f436a 488@@ -795,6 +890,10 @@ fp_common:
9385eb3d
A
489 * defined manner.''
490 * -- ANSI X3J11
491 */
eb1cde05
A
492+#ifdef VECTORS
493+ if (flags & VECTOR)
9385eb3d 494+ break;
eb1cde05 495+#endif /* VECTORS */
9385eb3d
A
496 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
497 base = 16;
498 xdigs = xdigs_lower;
1f2f436a 499@@ -813,7 +912,7 @@ fp_common:
3d9156a7
A
500 if ((wcp = GETARG(wchar_t *)) == NULL)
501 cp = "(null)";
502 else {
503- convbuf = __wcsconv(wcp, prec);
504+ convbuf = __wcsconv(wcp, prec, loc);
505 if (convbuf == NULL) {
506 fp->_flags |= __SERR;
507 goto error;
1f2f436a 508@@ -829,6 +928,10 @@ fp_common:
9385eb3d
A
509 flags |= LONGINT;
510 /*FALLTHROUGH*/
511 case 'u':
eb1cde05
A
512+#ifdef VECTORS
513+ if (flags & VECTOR)
9385eb3d 514+ break;
eb1cde05 515+#endif /* VECTORS */
9385eb3d
A
516 if (flags & INTMAX_SIZE)
517 ujval = UJARG();
518 else
1f2f436a 519@@ -841,6 +944,10 @@ fp_common:
9385eb3d
A
520 case 'x':
521 xdigs = xdigs_lower;
522 hex:
eb1cde05
A
523+#ifdef VECTORS
524+ if (flags & VECTOR)
9385eb3d 525+ break;
eb1cde05 526+#endif /* VECTORS */
9385eb3d
A
527 if (flags & INTMAX_SIZE)
528 ujval = UJARG();
529 else
1f2f436a
A
530@@ -858,6 +965,7 @@ nosign: sign = '\0';
531 * ``... diouXx conversions ... if a precision is
532 * specified, the 0 flag will be ignored.''
224c7076
A
533 * -- ANSI X3J11
534+ * except for %#.0o and zero value
535 */
1f2f436a
A
536 number: if ((dprec = prec) >= 0)
537 flags &= ~ZEROPAD;
538@@ -885,10 +993,15 @@ number: if ((dprec = prec) >= 0)
34e8f829
A
539 }
540 size = buf + BUF - cp;
9385eb3d 541 if (size > BUF) /* should never happen */
34e8f829 542- abort();
1f2f436a
A
543+ LIBC_ABORT("size (%d) > BUF (%d)", size, BUF);
544 if ((flags & GROUPING) && size != 0)
545- size += grouping_init(&gs, size);
546+ size += grouping_init(&gs, size, loc);
9385eb3d 547 break;
eb1cde05 548+#ifdef VECTORS
9385eb3d 549+ case 'v':
eb1cde05
A
550+ flags |= VECTOR;
551+ goto rflag;
552+#endif /* VECTORS */
9385eb3d
A
553 default: /* "%?" prints ?, unless ? is NUL */
554 if (ch == '\0')
555 goto done;
1f2f436a 556@@ -900,6 +1013,290 @@ number: if ((dprec = prec) >= 0)
9385eb3d
A
557 break;
558 }
559
eb1cde05 560+#ifdef VECTORS
9385eb3d
A
561+ if (flags & VECTOR) {
562+ /*
563+ * Do the minimum amount of work necessary to construct
564+ * a format specifier that can be used to recursively
565+ * call vfprintf() for each element in the vector.
566+ */
567+ int i, j; /* Counter. */
568+ int vcnt; /* Number of elements in vector. */
569+ char *vfmt; /* Pointer to format specifier. */
eb1cde05
A
570+#define EXTRAHH 2
571+ char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
9385eb3d
A
572+ int vwidth = 0; /* Width specified via '*'. */
573+ int vprec = 0; /* Precision specified via '*'. */
9385eb3d
A
574+ char *vstr; /* Used for asprintf(). */
575+ int vlen; /* Length returned by asprintf(). */
eb1cde05
A
576+ enum {
577+ V_CHAR, V_SHORT, V_INT,
578+ V_PCHAR, V_PSHORT, V_PINT,
579+ V_FLOAT,
580+#ifdef V64TYPE
581+ V_LONGLONG, V_PLONGLONG,
582+ V_DOUBLE,
583+#endif /* V64TYPE */
584+ } vtype;
9385eb3d 585+
eb1cde05 586+ vval.vectorarg = GETARG(VECTORTYPE);
9385eb3d
A
587+ /*
588+ * Set vfmt. If vfmt_buf may not be big enough,
589+ * malloc() space, taking care to free it later.
eb1cde05 590+ * (EXTRAHH is for possible extra "hh")
9385eb3d 591+ */
eb1cde05 592+ if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
9385eb3d
A
593+ vfmt = vfmt_buf;
594+ else
eb1cde05 595+ vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
9385eb3d
A
596+
597+ /* Set the separator character, if not specified. */
598+ if (vsep == 'X') {
599+ if (ch == 'c')
600+ vsep = '\0';
601+ else
602+ vsep = ' ';
603+ }
604+
605+ /* Create the format specifier. */
606+ for (i = j = 0; i < &fmt[-1] - pct; i++) {
607+ switch (pct[i]) {
608+ case ',': case ';': case ':': case '_':
609+ case 'v': case 'h': case 'l':
610+ /* Ignore. */
611+ break;
612+ case '*':
613+ if (pct[i - 1] != '.')
614+ vwidth = 1;
615+ else
616+ vprec = 1;
617+ /* FALLTHROUGH */
618+ default:
619+ vfmt[j++] = pct[i];
620+ }
621+ }
622+
623+ /*
624+ * Determine the number of elements in the vector and
625+ * finish up the format specifier.
626+ */
627+ if (flags & SHORTINT) {
eb1cde05
A
628+ switch (ch) {
629+ case 'c':
630+ vtype = V_SHORT;
631+ break;
632+ case 'p':
633+ vtype = V_PSHORT;
634+ break;
635+ default:
59e0d9fe 636+ vfmt[j++] = 'h';
eb1cde05
A
637+ vtype = V_SHORT;
638+ break;
639+ }
9385eb3d
A
640+ vcnt = 8;
641+ } else if (flags & LONGINT) {
f74c7596 642+ vcnt = 4;
eb1cde05
A
643+ vtype = (ch == 'p') ? V_PINT : V_INT;
644+#ifdef V64TYPE
645+ } else if (flags & LLONGINT) {
646+ switch (ch) {
647+ case 'a':
648+ case 'A':
649+ case 'e':
650+ case 'E':
651+ case 'f':
652+ case 'g':
653+ case 'G':
654+ vcnt = 2;
655+ vtype = V_DOUBLE;
656+ break;
657+ case 'd':
658+ case 'i':
659+ case 'u':
660+ case 'o':
661+ case 'p':
662+ case 'x':
663+ case 'X':
664+ vfmt[j++] = 'l';
665+ vfmt[j++] = 'l';
666+ vcnt = 2;
667+ vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
668+ break;
669+ default:
670+ /*
671+ * The default case should never
672+ * happen.
673+ */
674+ case 'c':
675+ vcnt = 16;
676+ vtype = V_CHAR;
677+ }
678+#endif /* V64TYPE */
9385eb3d
A
679+ } else {
680+ switch (ch) {
681+ case 'a':
682+ case 'A':
683+ case 'e':
684+ case 'E':
685+ case 'f':
686+ case 'g':
687+ case 'G':
688+ vcnt = 4;
eb1cde05 689+ vtype = V_FLOAT;
9385eb3d
A
690+ break;
691+ default:
692+ /*
693+ * The default case should never
694+ * happen.
695+ */
9385eb3d
A
696+ case 'd':
697+ case 'i':
698+ case 'u':
699+ case 'o':
9385eb3d
A
700+ case 'x':
701+ case 'X':
eb1cde05
A
702+ vfmt[j++] = 'h';
703+ vfmt[j++] = 'h';
704+ /* drop through */
705+ case 'p':
706+ case 'c':
9385eb3d 707+ vcnt = 16;
eb1cde05 708+ vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
9385eb3d
A
709+ }
710+ }
711+ vfmt[j++] = ch;
712+ vfmt[j++] = '\0';
713+
714+/* Get a vector element. */
eb1cde05
A
715+#ifdef V64TYPE
716+#define VPRINT(type, ind, args...) do { \
717+ switch (type) { \
718+ case V_CHAR: \
719+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
720+ break; \
721+ case V_PCHAR: \
1f2f436a 722+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
eb1cde05
A
723+ break; \
724+ case V_SHORT: \
725+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
726+ break; \
727+ case V_PSHORT: \
1f2f436a 728+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
eb1cde05
A
729+ break; \
730+ case V_INT: \
731+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
732+ break; \
733+ case V_PINT: \
1f2f436a 734+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
eb1cde05
A
735+ break; \
736+ case V_LONGLONG: \
737+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
738+ break; \
739+ case V_PLONGLONG: \
1f2f436a 740+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
eb1cde05
A
741+ break; \
742+ case V_FLOAT: \
743+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
744+ break; \
745+ case V_DOUBLE: \
746+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
747+ break; \
748+ } \
749+ ret += vlen; \
750+ PRINT(vstr, vlen); \
751+ FLUSH(); \
752+ free(vstr); \
753+} while (0)
754+#else /* !V64TYPE */
755+#define VPRINT(type, ind, args...) do { \
756+ switch (type) { \
757+ case V_CHAR: \
758+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
759+ break; \
760+ case V_PCHAR: \
1f2f436a 761+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
eb1cde05
A
762+ break; \
763+ case V_SHORT: \
764+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
765+ break; \
766+ case V_PSHORT: \
1f2f436a 767+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
eb1cde05
A
768+ break; \
769+ case V_INT: \
770+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
771+ break; \
772+ case V_PINT: \
1f2f436a 773+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
eb1cde05
A
774+ break; \
775+ case V_FLOAT: \
776+ vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
777+ break; \
9385eb3d
A
778+ } \
779+ ret += vlen; \
780+ PRINT(vstr, vlen); \
781+ FLUSH(); \
782+ free(vstr); \
783+} while (0)
eb1cde05 784+#endif /* V64TYPE */
9385eb3d
A
785+
786+ /* Actually print. */
787+ if (vwidth == 0) {
788+ if (vprec == 0) {
789+ /* First element. */
eb1cde05 790+ VPRINT(vtype, 0);
9385eb3d
A
791+ for (i = 1; i < vcnt; i++) {
792+ /* Separator. */
eb1cde05
A
793+ if(vsep)
794+ PRINT(&vsep, 1);
9385eb3d
A
795+
796+ /* Element. */
eb1cde05 797+ VPRINT(vtype, i);
9385eb3d
A
798+ }
799+ } else {
800+ /* First element. */
eb1cde05 801+ VPRINT(vtype, 0, prec);
9385eb3d
A
802+ for (i = 1; i < vcnt; i++) {
803+ /* Separator. */
eb1cde05
A
804+ if(vsep)
805+ PRINT(&vsep, 1);
9385eb3d
A
806+
807+ /* Element. */
eb1cde05 808+ VPRINT(vtype, i, prec);
9385eb3d
A
809+ }
810+ }
811+ } else {
812+ if (vprec == 0) {
813+ /* First element. */
eb1cde05 814+ VPRINT(vtype, 0, width);
9385eb3d
A
815+ for (i = 1; i < vcnt; i++) {
816+ /* Separator. */
eb1cde05
A
817+ if(vsep)
818+ PRINT(&vsep, 1);
9385eb3d
A
819+
820+ /* Element. */
eb1cde05 821+ VPRINT(vtype, i, width);
9385eb3d
A
822+ }
823+ } else {
824+ /* First element. */
eb1cde05 825+ VPRINT(vtype, 0, width, prec);
9385eb3d
A
826+ for (i = 1; i < vcnt; i++) {
827+ /* Separator. */
eb1cde05
A
828+ if(vsep)
829+ PRINT(&vsep, 1);
9385eb3d
A
830+
831+ /* Element. */
eb1cde05 832+ VPRINT(vtype, i, width, prec);
9385eb3d
A
833+ }
834+ }
835+ }
836+#undef VPRINT
837+
838+ if (vfmt != vfmt_buf)
839+ free(vfmt);
840+
841+ continue;
842+ }
eb1cde05 843+#endif /* VECTORS */
9385eb3d
A
844 /*
845 * All reasonable formats wind up here. At this point, `cp'
846 * points to a string which (if not flags&LADJUST) should be
1f2f436a
A
847@@ -950,7 +1347,7 @@ number: if ((dprec = prec) >= 0)
848 /* leading zeroes from decimal precision */
849 PAD(dprec - size, zeroes);
850 if (gs.grouping) {
851- if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
852+ if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
853 goto error;
854 } else {
855 PRINT(cp, size);
856@@ -968,7 +1365,7 @@ number: if ((dprec = prec) >= 0)
857 } else {
858 if (gs.grouping) {
859 n = grouping_print(&gs, &io,
860- cp, dtoaend);
861+ cp, dtoaend, loc);
862 if (n < 0)
863 goto error;
864 cp += n;