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