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
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.90 2009/02/28 06:06:57 das Exp $");
7 +#include "xlocale_private.h"
10 * Actual printf innards.
12 @@ -54,7 +56,10 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
16 +#if 0 // xprintf pending API review
22 #include "un-namespace.h"
23 @@ -64,10 +69,11 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
25 #include "printflocal.h"
27 -static int __sprint(FILE *, struct __suio *);
28 -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0)
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);
35 +__private_extern__ const char *__fix_nogrouping(const char *);
38 #include "printfcommon.h"
39 @@ -87,12 +93,12 @@ struct grouping_state {
40 * of bytes that will be needed.
43 -grouping_init(struct grouping_state *gs, int ndigits)
44 +grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
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);
55 @@ -116,11 +122,11 @@ grouping_init(struct grouping_state *gs,
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)
64 - if (io_printandpad(iop, cp, ep, gs->lead, zeroes))
65 + if (io_printandpad(iop, cp, ep, gs->lead, zeroes, loc))
68 while (gs->nseps > 0 || gs->nrepeats > 0) {
69 @@ -130,9 +136,9 @@ grouping_print(struct grouping_state *gs
73 - if (io_print(iop, gs->thousands_sep, gs->thousep_len))
74 + if (io_print(iop, gs->thousands_sep, gs->thousep_len, loc))
76 - if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes))
77 + if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, loc))
81 @@ -146,7 +152,7 @@ grouping_print(struct grouping_state *gs
82 * then reset it so that it can be reused.
85 -__sprint(FILE *fp, struct __suio *uio)
86 +__sprint(FILE *fp, locale_t loc __unused, struct __suio *uio)
90 @@ -166,11 +172,14 @@ __sprint(FILE *fp, struct __suio *uio)
91 * worries about ungetc buffers and so forth.
94 -__sbprintf(FILE *fp, const char *fmt, va_list ap)
95 +__sbprintf(FILE *fp, locale_t loc, const char *fmt, va_list ap)
99 unsigned char buf[BUFSIZ];
100 + struct __sFILEX ext;
101 + fake._extra = &ext;
104 /* XXX This is probably not needed. */
105 if (prepwrite(fp) != 0)
106 @@ -190,7 +199,7 @@ __sbprintf(FILE *fp, const char *fmt, va
107 fake._lbfsize = 0; /* not actually used, but Just In Case */
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))
114 if (fake._flags & __SERR)
115 @@ -205,7 +214,7 @@ __sbprintf(FILE *fp, const char *fmt, va
116 * string ends is null-terminated.
119 -__wcsconv(wchar_t *wcsarg, int prec)
120 +__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
122 static const mbstate_t initial;
124 @@ -218,7 +227,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
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)
133 @@ -234,7 +243,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
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)
142 @@ -248,8 +257,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
143 /* Fill the output buffer. */
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) {
153 @@ -261,22 +270,30 @@ __wcsconv(wchar_t *wcsarg, int prec)
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)
163 + NORMALIZE_LOCALE(loc);
165 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
166 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
168 - ret = __sbprintf(fp, fmt0, ap);
169 + ret = __sbprintf(fp, loc, fmt0, ap);
171 - ret = __vfprintf(fp, fmt0, ap);
172 + ret = __vfprintf(fp, loc, fmt0, ap);
178 +vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
181 + return vfprintf_l(fp, __current_locale(), fmt0, ap);
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
189 * Non-MT-safe version
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)
196 char *fmt; /* format string */
197 int ch; /* character from fmt */
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 */
203 + union arg vval; /* Vector argument. */
204 + char *pct; /* Pointer to '%' at beginning of specifier. */
205 + char vsep; /* Vector separator character. */
207 u_long ulval; /* integer arguments %[diouxX] */
208 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
209 int base; /* base for [diouxX] conversion */
210 @@ -357,19 +379,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
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)) \
218 #define PAD(howmany, with) { \
219 - if (io_pad(&io, (howmany), (with))) \
220 + if (io_pad(&io, (howmany), (with), loc)) \
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)) \
229 - if (io_flush(&io)) \
230 + if (io_flush(&io, loc)) \
234 @@ -405,7 +427,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
236 (flags&INTMAXT ? GETARG(uintmax_t) : \
237 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
238 - flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
239 + flags&PTRDIFFT ? (uintmax_t)(unsigned long)GETARG(ptrdiff_t) : \
240 (uintmax_t)GETARG(unsigned long long))
243 @@ -436,14 +458,19 @@ __vfprintf(FILE *fp, const char *fmt0, v
244 val = GETARG (int); \
247 +#if 0 // xprintf pending API review
248 if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
250 if (__use_xprintf > 0)
251 - return (__xvprintf(fp, fmt0, ap));
252 + return (__xvprintf(fp, loc, fmt0, ap));
255 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
256 - if (prepwrite(fp) != 0)
257 + if (prepwrite(fp) != 0) {
265 @@ -454,7 +481,7 @@ __vfprintf(FILE *fp, const char *fmt0, v
267 #ifndef NO_FLOATING_POINT
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));
274 @@ -475,6 +502,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
280 +#endif /* VECTORS */
281 fmt++; /* skip over '%' */
284 @@ -484,6 +514,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
289 + vsep = 'X'; /* Illegal value, changed to defaults later. */
290 +#endif /* VECTORS */
293 reswitch: switch (ch) {
294 @@ -499,6 +532,11 @@ reswitch: switch (ch) {
299 + case ',': case ';': case ':': case '_':
302 +#endif /* VECTORS */
305 * ``A negative field width argument is taken as a
306 @@ -595,14 +633,18 @@ reswitch: switch (ch) {
311 + if (flags & VECTOR)
313 +#endif /* VECTORS */
314 if (flags & LONGINT) {
315 static const mbstate_t 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;
327 @@ -619,6 +661,10 @@ reswitch: switch (ch) {
332 + if (flags & VECTOR)
334 +#endif /* VECTORS */
335 if (flags & INTMAX_SIZE) {
337 if ((intmax_t)ujval < 0) {
338 @@ -637,6 +683,12 @@ reswitch: switch (ch) {
339 #ifndef NO_FLOATING_POINT
343 + if (flags & VECTOR) {
347 +#endif /* VECTORS */
351 @@ -650,6 +702,12 @@ reswitch: switch (ch) {
353 if (dtoaresult != NULL)
354 freedtoa(dtoaresult);
356 + fparg.dbl = GETARG(double);
358 + __hdtoa(fparg.dbl, xdigs, prec,
359 + &expt, &signflag, &dtoaend);
360 +#else /* !LDBL_COMPAT */
361 if (flags & LONGDBL) {
362 fparg.ldbl = GETARG(long double);
364 @@ -661,6 +719,7 @@ reswitch: switch (ch) {
365 __hdtoa(fparg.dbl, xdigs, prec,
366 &expt, &signflag, &dtoaend);
368 +#endif /* LDBL_COMPAT */
372 @@ -668,6 +727,12 @@ reswitch: switch (ch) {
377 + if (flags & VECTOR) {
381 +#endif /* VECTORS */
383 if (prec < 0) /* account for digit before decpt */
385 @@ -676,10 +741,22 @@ reswitch: switch (ch) {
390 + if (flags & VECTOR) {
394 +#endif /* VECTORS */
400 + if (flags & VECTOR) {
404 +#endif /* VECTORS */
405 expchar = ch - ('g' - 'e');
408 @@ -688,6 +765,14 @@ fp_begin:
410 if (dtoaresult != NULL)
411 freedtoa(dtoaresult);
413 + fparg.dbl = GETARG(double);
415 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
416 + &expt, &signflag, &dtoaend);
419 +#else /* !LDBL_COMPAT */
420 if (flags & LONGDBL) {
421 fparg.ldbl = GETARG(long double);
423 @@ -701,6 +786,7 @@ fp_begin:
427 +#endif /* LDBL_COMPAT */
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);
439 #endif /* !NO_FLOATING_POINT */
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.
447 - if (flags & LLONGINT)
448 - *GETARG(long long *) = ret;
449 + void *ptr = GETARG(void *);
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;
473 - *GETARG(int *) = ret;
475 continue; /* no output */
482 + if (flags & VECTOR)
484 +#endif /* VECTORS */
485 if (flags & INTMAX_SIZE)
488 @@ -795,6 +890,10 @@ fp_common:
493 + if (flags & VECTOR)
495 +#endif /* VECTORS */
496 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
499 @@ -813,7 +912,7 @@ fp_common:
500 if ((wcp = GETARG(wchar_t *)) == NULL)
503 - convbuf = __wcsconv(wcp, prec);
504 + convbuf = __wcsconv(wcp, prec, loc);
505 if (convbuf == NULL) {
506 fp->_flags |= __SERR;
508 @@ -829,6 +928,10 @@ fp_common:
513 + if (flags & VECTOR)
515 +#endif /* VECTORS */
516 if (flags & INTMAX_SIZE)
519 @@ -841,6 +944,10 @@ fp_common:
524 + if (flags & VECTOR)
526 +#endif /* VECTORS */
527 if (flags & INTMAX_SIZE)
530 @@ -858,6 +965,7 @@ nosign: sign = '\0';
531 * ``... diouXx conversions ... if a precision is
532 * specified, the 0 flag will be ignored.''
534 + * except for %#.0o and zero value
536 number: if ((dprec = prec) >= 0)
538 @@ -885,10 +993,15 @@ number: if ((dprec = prec) >= 0)
540 size = buf + BUF - cp;
541 if (size > BUF) /* should never happen */
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);
552 +#endif /* VECTORS */
553 default: /* "%?" prints ?, unless ? is NUL */
556 @@ -900,6 +1013,290 @@ number: if ((dprec = prec) >= 0)
561 + if (flags & VECTOR) {
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.
567 + int i, j; /* Counter. */
568 + int vcnt; /* Number of elements in vector. */
569 + char *vfmt; /* Pointer to format specifier. */
571 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
572 + int vwidth = 0; /* Width specified via '*'. */
573 + int vprec = 0; /* Precision specified via '*'. */
574 + char *vstr; /* Used for asprintf(). */
575 + int vlen; /* Length returned by asprintf(). */
577 + V_CHAR, V_SHORT, V_INT,
578 + V_PCHAR, V_PSHORT, V_PINT,
581 + V_LONGLONG, V_PLONGLONG,
583 +#endif /* V64TYPE */
586 + vval.vectorarg = GETARG(VECTORTYPE);
588 + * Set vfmt. If vfmt_buf may not be big enough,
589 + * malloc() space, taking care to free it later.
590 + * (EXTRAHH is for possible extra "hh")
592 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
595 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
597 + /* Set the separator character, if not specified. */
605 + /* Create the format specifier. */
606 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
608 + case ',': case ';': case ':': case '_':
609 + case 'v': case 'h': case 'l':
613 + if (pct[i - 1] != '.')
619 + vfmt[j++] = pct[i];
624 + * Determine the number of elements in the vector and
625 + * finish up the format specifier.
627 + if (flags & SHORTINT) {
641 + } else if (flags & LONGINT) {
643 + vtype = (ch == 'p') ? V_PINT : V_INT;
645 + } else if (flags & LLONGINT) {
667 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
671 + * The default case should never
678 +#endif /* V64TYPE */
693 + * The default case should never
708 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
714 +/* Get a vector element. */
716 +#define VPRINT(type, ind, args...) do { \
719 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
722 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
725 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
728 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
731 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
734 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
737 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
739 + case V_PLONGLONG: \
740 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vulonglongarg[ind]); \
743 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
746 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
750 + PRINT(vstr, vlen); \
754 +#else /* !V64TYPE */
755 +#define VPRINT(type, ind, args...) do { \
758 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
761 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuchararg[ind]); \
764 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
767 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vushortarg[ind]); \
770 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
773 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(uintptr_t)vval.vuintarg[ind]); \
776 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
780 + PRINT(vstr, vlen); \
784 +#endif /* V64TYPE */
786 + /* Actually print. */
789 + /* First element. */
791 + for (i = 1; i < vcnt; i++) {
800 + /* First element. */
801 + VPRINT(vtype, 0, prec);
802 + for (i = 1; i < vcnt; i++) {
808 + VPRINT(vtype, i, prec);
813 + /* First element. */
814 + VPRINT(vtype, 0, width);
815 + for (i = 1; i < vcnt; i++) {
821 + VPRINT(vtype, i, width);
824 + /* First element. */
825 + VPRINT(vtype, 0, width, prec);
826 + for (i = 1; i < vcnt; i++) {
832 + VPRINT(vtype, i, width, prec);
838 + if (vfmt != vfmt_buf)
843 +#endif /* VECTORS */
845 * All reasonable formats wind up here. At this point, `cp'
846 * points to a string which (if not flags&LADJUST) should be
847 @@ -950,7 +1347,7 @@ number: if ((dprec = prec) >= 0)
848 /* leading zeroes from decimal precision */
849 PAD(dprec - size, zeroes);
851 - if (grouping_print(&gs, &io, cp, buf+BUF) < 0)
852 + if (grouping_print(&gs, &io, cp, buf+BUF, loc) < 0)
856 @@ -968,7 +1365,7 @@ number: if ((dprec = prec) >= 0)
859 n = grouping_print(&gs, &io,