1 --- vfwprintf.c.orig 2006-10-01 00:03:16.000000000 -0700
2 +++ vfwprintf.c 2006-10-01 00:21:40.000000000 -0700
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwprintf.c,v 1.23 2004/08/26 06:25:28 des Exp $");
7 +#include "xlocale_private.h"
10 * Actual wprintf innards.
17 #include "un-namespace.h"
19 #include "libc_private.h"
24 +typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
27 +#endif /* __SSE2__ */
38 + VECTORTYPE vectorarg;
39 + unsigned char vuchararg[16];
40 + signed char vchararg[16];
41 + unsigned short vushortarg[8];
42 + signed short vshortarg[8];
43 + unsigned int vuintarg[4];
44 + signed int vintarg[4];
47 + double vdoublearg[2];
48 + unsigned long long vulonglongarg[2];
49 + long long vlonglongarg[2];
56 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
57 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
58 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
60 + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
61 +#else /* ! VECTORS */
62 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
66 -static int __sbprintf(FILE *, const wchar_t *, va_list);
67 -static wint_t __xfputwc(wchar_t, FILE *);
68 +static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list);
69 +static wint_t __xfputwc(wchar_t, FILE *, locale_t);
70 static wchar_t *__ujtoa(uintmax_t, wchar_t *, int, int, const char *, int,
72 static wchar_t *__ultoa(u_long, wchar_t *, int, int, const char *, int,
74 -static wchar_t *__mbsconv(char *, int);
75 +static wchar_t *__mbsconv(char *, int, locale_t);
76 static void __find_arguments(const wchar_t *, va_list, union arg **);
77 static void __grow_type_table(int, enum typeid **, int *);
80 * worries about ungetc buffers and so forth.
83 -__sbprintf(FILE *fp, const wchar_t *fmt, va_list ap)
84 +__sbprintf(FILE *fp, locale_t loc, const wchar_t *fmt, va_list ap)
89 fake._lbfsize = 0; /* not actually used, but Just In Case */
91 /* do the work, then copy any error status */
92 - ret = __vfwprintf(&fake, fmt, ap);
93 + ret = __vfwprintf(&fake, loc, fmt, ap);
94 if (ret >= 0 && __fflush(&fake))
96 if (fake._flags & __SERR)
98 * File must already be locked.
101 -__xfputwc(wchar_t wc, FILE *fp)
102 +__xfputwc(wchar_t wc, FILE *fp, locale_t loc)
104 static const mbstate_t initial;
106 @@ -167,10 +196,10 @@
109 if ((fp->_flags & __SSTR) == 0)
110 - return (__fputwc(wc, fp));
111 + return (__fputwc(wc, fp, loc));
114 - if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
115 + if ((len = wcrtomb_l(buf, wc, &mbs, loc)) == (size_t)-1) {
116 fp->_flags |= __SERR;
119 @@ -350,13 +379,14 @@
120 * that the multibyte char. string ends in a null character.
123 -__mbsconv(char *mbsarg, int prec)
124 +__mbsconv(char *mbsarg, int prec, locale_t loc)
126 static const mbstate_t initial;
128 wchar_t *convbuf, *wcp;
130 - size_t insize, nchars, nconv;
131 + size_t insize, nchars, nconv = 0;
132 + int mb_cur_max = MB_CUR_MAX_L(loc);
139 while (nchars != (size_t)prec) {
140 - nconv = mbrlen(p, MB_CUR_MAX, &mbs);
141 + nconv = mbrlen_l(p, mb_cur_max, &mbs, loc);
142 if (nconv == 0 || nconv == (size_t)-1 ||
148 while (insize != 0) {
149 - nconv = mbrtowc(wcp, p, insize, &mbs);
150 + nconv = mbrtowc_l(wcp, p, insize, &mbs, loc);
151 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
158 +__private_extern__ const char *__fix_nogrouping(const char *);
161 vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
167 - ret = __vfwprintf(fp, fmt0, ap);
168 + ret = __vfwprintf(fp, __current_locale(), fmt0, ap);
174 +vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0,
180 + NORMALIZE_LOCALE(loc);
182 + ret = __vfwprintf(fp, loc, fmt0, ap);
186 @@ -474,12 +520,15 @@
187 #define PTRDIFFT 0x800 /* ptrdiff_t */
188 #define INTMAXT 0x1000 /* intmax_t */
189 #define CHARINT 0x2000 /* print char using int format */
191 +#define VECTOR 0x4000 /* Altivec or SSE vector */
192 +#endif /* VECTORS */
195 * Non-MT-safe version
198 -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
199 +__private_extern__ int
200 +__vfwprintf(FILE *fp, locale_t loc, const wchar_t *fmt0, va_list ap)
202 wchar_t *fmt; /* format string */
203 wchar_t ch; /* character from fmt */
205 * D: expchar holds this character; '\0' if no exponent, e.g. %f
206 * F: at least two digits for decimal, at least one digit for hex
208 - char *decimal_point; /* locale specific decimal point */
209 + wchar_t decimal_point; /* locale specific decimal point */
210 + char *decimal_point_mb; /* multibyte decimal point */
211 int signflag; /* true if float is negative */
212 union { /* floating point arguments %[aAeEfFgG] */
215 int nseps; /* number of group separators with ' */
216 int nrepeats; /* number of repeats of the last group */
219 + union arg vval; /* Vector argument. */
220 + wchar_t *pct; /* Pointer to '%' at beginning of specifier. */
221 + wchar_t vsep; /* Vector separator character. */
223 u_long ulval; /* integer arguments %[diouxX] */
224 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
225 int base; /* base for [diouxX] conversion */
228 #define PRINT(ptr, len) do { \
229 for (n3 = 0; n3 < (len); n3++) \
230 - __xfputwc((ptr)[n3], fp); \
231 + __xfputwc((ptr)[n3], fp, loc); \
233 #define PAD(howmany, with) do { \
234 if ((n = (howmany)) > 0) { \
236 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
238 (flags&INTMAXT ? GETARG(intmax_t) : \
239 - flags&SIZET ? (intmax_t)GETARG(size_t) : \
240 + flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
241 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
242 (intmax_t)GETARG(long long))
244 @@ -640,21 +695,24 @@
245 val = GETARG (int); \
249 thousands_sep = '\0';
251 #ifndef NO_FLOATING_POINT
252 - decimal_point = localeconv()->decimal_point;
253 + decimal_point_mb = localeconv_l(loc)->decimal_point;
254 + mbtowc_l(&decimal_point, decimal_point_mb, strlen(decimal_point_mb), loc);
257 /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
258 - if (prepwrite(fp) != 0)
259 + if (prepwrite(fp) != 0) {
265 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
266 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
268 - return (__sbprintf(fp, fmt0, ap));
269 + return (__sbprintf(fp, loc, fmt0, ap));
271 fmt = (wchar_t *)fmt0;
279 +#endif /* VECTORS */
280 fmt++; /* skip over '%' */
288 + vsep = 'X'; /* Illegal value, changed to defaults later. */
289 +#endif /* VECTORS */
292 reswitch: switch (ch) {
298 + case ',': case ';': case ':': case '_':
301 +#endif /* VECTORS */
304 * ``A negative field width argument is taken as a
309 - thousands_sep = *(localeconv()->thousands_sep);
310 - grouping = localeconv()->grouping;
311 + thousands_sep = *(localeconv_l(loc)->thousands_sep);
312 + grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
315 if ((ch = *fmt++) == '*') {
316 @@ -796,10 +865,14 @@
321 + if (flags & VECTOR)
323 +#endif /* VECTORS */
325 *(cp = buf) = (wchar_t)GETARG(wint_t);
327 - *(cp = buf) = (wchar_t)btowc(GETARG(int));
328 + *(cp = buf) = (wchar_t)btowc_l(GETARG(int), loc);
337 + if (flags & VECTOR)
339 +#endif /* VECTORS */
340 if (flags & INTMAX_SIZE) {
342 if ((intmax_t)ujval < 0) {
344 #ifndef NO_FLOATING_POINT
348 + if (flags & VECTOR) {
352 +#endif /* VECTORS */
361 + fparg.dbl = GETARG(double);
363 + __hdtoa(fparg.dbl, xdigs, prec,
364 + &expt, &signflag, &dtoaend);
365 +#else /* !LDBL_COMPAT */
366 if (flags & LONGDBL) {
367 fparg.ldbl = GETARG(long double);
370 __hdtoa(fparg.dbl, xdigs, prec,
371 &expt, &signflag, &dtoaend);
373 +#endif /* LDBL_COMPAT */
375 prec = dtoaend - dtoaresult;
377 @@ -855,11 +945,17 @@
380 ndig = dtoaend - dtoaresult;
381 - cp = convbuf = __mbsconv(dtoaresult, -1);
382 + cp = convbuf = __mbsconv(dtoaresult, -1, loc);
383 freedtoa(dtoaresult);
388 + if (flags & VECTOR) {
392 +#endif /* VECTORS */
394 if (prec < 0) /* account for digit before decpt */
396 @@ -868,10 +964,22 @@
401 + if (flags & VECTOR) {
405 +#endif /* VECTORS */
411 + if (flags & VECTOR) {
415 +#endif /* VECTORS */
416 expchar = ch - ('g' - 'e');
424 + fparg.dbl = GETARG(double);
426 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
427 + &expt, &signflag, &dtoaend);
430 +#else /* !LDBL_COMPAT */
431 if (flags & LONGDBL) {
432 fparg.ldbl = GETARG(long double);
438 +#endif /* LDBL_COMPAT */
439 ndig = dtoaend - dtoaresult;
440 - cp = convbuf = __mbsconv(dtoaresult, -1);
441 + cp = convbuf = __mbsconv(dtoaresult, -1, loc);
442 freedtoa(dtoaresult);
445 @@ -989,6 +1106,10 @@
450 + if (flags & VECTOR)
452 +#endif /* VECTORS */
453 if (flags & INTMAX_SIZE)
456 @@ -1003,6 +1124,10 @@
461 + if (flags & VECTOR)
463 +#endif /* VECTORS */
464 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
467 @@ -1024,7 +1149,7 @@
468 if ((mbp = GETARG(char *)) == NULL)
471 - convbuf = __mbsconv(mbp, prec);
472 + convbuf = __mbsconv(mbp, prec, loc);
473 if (convbuf == NULL) {
474 fp->_flags |= __SERR;
476 @@ -1055,6 +1180,10 @@
481 + if (flags & VECTOR)
483 +#endif /* VECTORS */
484 if (flags & INTMAX_SIZE)
487 @@ -1067,6 +1196,10 @@
492 + if (flags & VECTOR)
494 +#endif /* VECTORS */
495 if (flags & INTMAX_SIZE)
498 @@ -1092,6 +1225,7 @@
499 * ``The result of converting a zero value with an
500 * explicit precision of zero is no characters.''
502 + * except for %#.0o and zero value
505 if (flags & INTMAX_SIZE) {
506 @@ -1101,7 +1235,7 @@
507 flags & GROUPING, thousands_sep,
510 - if (ulval != 0 || prec != 0)
511 + if (ulval != 0 || prec != 0 || (flags & ALT))
512 cp = __ultoa(ulval, cp, base,
514 flags & GROUPING, thousands_sep,
515 @@ -1111,6 +1245,11 @@
516 if (size > BUF) /* should never happen */
523 +#endif /* VECTORS */
524 default: /* "%?" prints ?, unless ? is NUL */
527 @@ -1122,6 +1261,288 @@
532 + if (flags & VECTOR) {
534 + * Do the minimum amount of work necessary to construct
535 + * a format specifier that can be used to recursively
536 + * call vfprintf() for each element in the vector.
538 + int i, j; /* Counter. */
539 + int vcnt; /* Number of elements in vector. */
540 + char *vfmt; /* Pointer to format specifier. */
542 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
543 + int vwidth = 0; /* Width specified via '*'. */
544 + int vprec = 0; /* Precision specified via '*'. */
545 + char *vstr; /* Used for asprintf(). */
546 + int vlen; /* Length returned by asprintf(). */
548 + V_CHAR, V_SHORT, V_INT,
549 + V_PCHAR, V_PSHORT, V_PINT,
552 + V_LONGLONG, V_PLONGLONG,
554 +#endif /* V64TYPE */
557 + vval.vectorarg = GETARG(VECTORTYPE);
559 + * Set vfmt. If vfmt_buf may not be big enough,
560 + * malloc() space, taking care to free it later.
561 + * (EXTRAHH is for possible extra "hh")
563 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
566 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
568 + /* Set the separator character, if not specified. */
576 + /* Create the format specifier. */
577 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
579 + case ',': case ';': case ':': case '_':
580 + case 'v': case 'h': case 'l':
584 + if (pct[i - 1] != '.')
590 + vfmt[j++] = pct[i];
595 + * Determine the number of elements in the vector and
596 + * finish up the format specifier.
598 + if (flags & SHORTINT) {
612 + } else if (flags & LONGINT) {
614 + vtype = (ch == 'p') ? V_PINT : V_INT;
616 + } else if (flags & LLONGINT) {
638 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
642 + * The default case should never
649 +#endif /* V64TYPE */
664 + * The default case should never
679 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
685 +/* Get a vector element. */
687 +#define VPRINT(type, ind, args...) do { \
690 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
693 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
696 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
699 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
702 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
705 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
708 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
710 + case V_PLONGLONG: \
711 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
714 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
717 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
721 + PRINT(vstr, vlen); \
724 +#else /* !V64TYPE */
725 +#define VPRINT(type, ind, args...) do { \
728 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
731 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
734 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
737 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
740 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
743 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
746 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
750 + PRINT(vstr, vlen); \
753 +#endif /* V64TYPE */
755 + /* Actually print. */
758 + /* First element. */
760 + for (i = 1; i < vcnt; i++) {
769 + /* First element. */
770 + VPRINT(vtype, 0, prec);
771 + for (i = 1; i < vcnt; i++) {
777 + VPRINT(vtype, i, prec);
782 + /* First element. */
783 + VPRINT(vtype, 0, width);
784 + for (i = 1; i < vcnt; i++) {
790 + VPRINT(vtype, i, width);
793 + /* First element. */
794 + VPRINT(vtype, 0, width, prec);
795 + for (i = 1; i < vcnt; i++) {
801 + VPRINT(vtype, i, width, prec);
807 + if (vfmt != vfmt_buf)
812 +#endif /* VECTORS */
814 * All reasonable formats wind up here. At this point, `cp'
815 * points to a string which (if not flags&LADJUST) should be
816 @@ -1177,7 +1598,7 @@
819 if (prec || flags & ALT)
820 - PRINT(decimal_point, 1);
821 + PRINT(&decimal_point, 1);
823 /* already handled initial 0's */
825 @@ -1203,15 +1624,14 @@
828 if (prec || flags & ALT) {
829 - buf[0] = *decimal_point;
831 + PRINT(&decimal_point, 1);
834 PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
835 } else { /* %[eE] or sufficiently long %[gG] */
836 if (prec > 1 || flags & ALT) {
838 - buf[1] = *decimal_point;
839 + buf[1] = decimal_point;
842 PAD(prec - ndig, zeroes);
843 @@ -1401,6 +1821,11 @@
848 + if (flags & VECTOR)
851 +#endif /* VECTORS */
855 @@ -1408,6 +1833,11 @@
860 + if (flags & VECTOR)
863 +#endif /* VECTORS */
866 #ifndef NO_FLOATING_POINT
867 @@ -1416,8 +1846,14 @@
875 + if (flags & VECTOR)
878 +#endif /* VECTORS */
880 ADDTYPE(T_LONG_DOUBLE);
882 @@ -1446,9 +1882,19 @@
887 + if (flags & VECTOR)
890 +#endif /* VECTORS */
895 + if (flags & VECTOR)
898 +#endif /* VECTORS */
902 @@ -1466,6 +1912,11 @@
907 + if (flags & VECTOR)
910 +#endif /* VECTORS */
913 default: /* "%?" prints ?, unless ? is NUL */
914 @@ -1532,7 +1983,7 @@
915 (*argtable) [n].sizearg = va_arg (ap, size_t);
918 - (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
919 + (*argtable) [n].psizearg = va_arg (ap, size_t *);
922 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
923 @@ -1551,6 +2002,11 @@
924 (*argtable) [n].longdoublearg = va_arg (ap, long double);
929 + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
931 +#endif /* VECTORS */
933 (*argtable) [n].pchararg = va_arg (ap, char *);