1 --- vfwprintf.c.orig 2004-11-25 11:38:36.000000000 -0800
2 +++ vfwprintf.c 2005-11-08 22:46:07.000000000 -0800
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 + int mb_cur_max = MB_CUR_MAX_L(loc);
138 while (nchars != (size_t)prec) {
139 - nconv = mbrlen(p, MB_CUR_MAX, &mbs);
140 + nconv = mbrlen_l(p, mb_cur_max, &mbs, loc);
141 if (nconv == 0 || nconv == (size_t)-1 ||
147 while (insize != 0) {
148 - nconv = mbrtowc(wcp, p, insize, &mbs);
149 + nconv = mbrtowc_l(wcp, p, insize, &mbs, loc);
150 if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
157 - ret = __vfwprintf(fp, fmt0, ap);
158 + ret = __vfwprintf(fp, __current_locale(), fmt0, ap);
164 +vfwprintf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt0,
170 + NORMALIZE_LOCALE(loc);
172 + ret = __vfwprintf(fp, loc, fmt0, ap);
176 @@ -474,12 +518,15 @@
177 #define PTRDIFFT 0x800 /* ptrdiff_t */
178 #define INTMAXT 0x1000 /* intmax_t */
179 #define CHARINT 0x2000 /* print char using int format */
181 +#define VECTOR 0x4000 /* Altivec or SSE vector */
182 +#endif /* VECTORS */
185 * Non-MT-safe version
188 -__vfwprintf(FILE *fp, const wchar_t *fmt0, va_list ap)
189 +__private_extern__ int
190 +__vfwprintf(FILE *fp, locale_t loc, const wchar_t *fmt0, va_list ap)
192 wchar_t *fmt; /* format string */
193 wchar_t ch; /* character from fmt */
195 int nseps; /* number of group separators with ' */
196 int nrepeats; /* number of repeats of the last group */
199 + union arg vval; /* Vector argument. */
200 + wchar_t *pct; /* Pointer to '%' at beginning of specifier. */
201 + wchar_t vsep; /* Vector separator character. */
203 u_long ulval; /* integer arguments %[diouxX] */
204 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
205 int base; /* base for [diouxX] conversion */
208 #define PRINT(ptr, len) do { \
209 for (n3 = 0; n3 < (len); n3++) \
210 - __xfputwc((ptr)[n3], fp); \
211 + __xfputwc((ptr)[n3], fp, loc); \
213 #define PAD(howmany, with) do { \
214 if ((n = (howmany)) > 0) { \
215 @@ -640,21 +692,22 @@
216 val = GETARG (int); \
220 thousands_sep = '\0';
222 #ifndef NO_FLOATING_POINT
223 - decimal_point = localeconv()->decimal_point;
224 + decimal_point = localeconv_l(loc)->decimal_point;
227 /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
228 - if (prepwrite(fp) != 0)
229 + if (prepwrite(fp) != 0) {
234 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
235 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
237 - return (__sbprintf(fp, fmt0, ap));
238 + return (__sbprintf(fp, loc, fmt0, ap));
240 fmt = (wchar_t *)fmt0;
248 +#endif /* VECTORS */
249 fmt++; /* skip over '%' */
257 + vsep = 'X'; /* Illegal value, changed to defaults later. */
258 +#endif /* VECTORS */
261 reswitch: switch (ch) {
267 + case ',': case ';': case ':': case '_':
270 +#endif /* VECTORS */
273 * ``A negative field width argument is taken as a
278 - thousands_sep = *(localeconv()->thousands_sep);
279 - grouping = localeconv()->grouping;
280 + thousands_sep = *(localeconv_l(loc)->thousands_sep);
281 + grouping = localeconv_l(loc)->grouping;
284 if ((ch = *fmt++) == '*') {
285 @@ -796,10 +860,14 @@
290 + if (flags & VECTOR)
292 +#endif /* VECTORS */
294 *(cp = buf) = (wchar_t)GETARG(wint_t);
296 - *(cp = buf) = (wchar_t)btowc(GETARG(int));
297 + *(cp = buf) = (wchar_t)btowc_l(GETARG(int), loc);
306 + if (flags & VECTOR)
308 +#endif /* VECTORS */
309 if (flags & INTMAX_SIZE) {
311 if ((intmax_t)ujval < 0) {
313 #ifndef NO_FLOATING_POINT
317 + if (flags & VECTOR) {
321 +#endif /* VECTORS */
330 + fparg.dbl = GETARG(double);
332 + __hdtoa(fparg.dbl, xdigs, prec,
333 + &expt, &signflag, &dtoaend);
334 +#else /* !LDBL_COMPAT */
335 if (flags & LONGDBL) {
336 fparg.ldbl = GETARG(long double);
339 __hdtoa(fparg.dbl, xdigs, prec,
340 &expt, &signflag, &dtoaend);
342 +#endif /* LDBL_COMPAT */
344 prec = dtoaend - dtoaresult;
346 @@ -855,11 +940,17 @@
349 ndig = dtoaend - dtoaresult;
350 - cp = convbuf = __mbsconv(dtoaresult, -1);
351 + cp = convbuf = __mbsconv(dtoaresult, -1, loc);
352 freedtoa(dtoaresult);
357 + if (flags & VECTOR) {
361 +#endif /* VECTORS */
363 if (prec < 0) /* account for digit before decpt */
365 @@ -868,10 +959,22 @@
370 + if (flags & VECTOR) {
374 +#endif /* VECTORS */
380 + if (flags & VECTOR) {
384 +#endif /* VECTORS */
385 expchar = ch - ('g' - 'e');
393 + fparg.dbl = GETARG(double);
395 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
396 + &expt, &signflag, &dtoaend);
399 +#else /* !LDBL_COMPAT */
400 if (flags & LONGDBL) {
401 fparg.ldbl = GETARG(long double);
407 +#endif /* LDBL_COMPAT */
408 ndig = dtoaend - dtoaresult;
409 - cp = convbuf = __mbsconv(dtoaresult, -1);
410 + cp = convbuf = __mbsconv(dtoaresult, -1, loc);
411 freedtoa(dtoaresult);
414 @@ -989,6 +1101,10 @@
419 + if (flags & VECTOR)
421 +#endif /* VECTORS */
422 if (flags & INTMAX_SIZE)
425 @@ -1003,6 +1119,10 @@
430 + if (flags & VECTOR)
432 +#endif /* VECTORS */
433 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
436 @@ -1024,7 +1144,7 @@
437 if ((mbp = GETARG(char *)) == NULL)
440 - convbuf = __mbsconv(mbp, prec);
441 + convbuf = __mbsconv(mbp, prec, loc);
442 if (convbuf == NULL) {
443 fp->_flags |= __SERR;
445 @@ -1055,6 +1175,10 @@
450 + if (flags & VECTOR)
452 +#endif /* VECTORS */
453 if (flags & INTMAX_SIZE)
456 @@ -1067,6 +1191,10 @@
461 + if (flags & VECTOR)
463 +#endif /* VECTORS */
464 if (flags & INTMAX_SIZE)
467 @@ -1111,6 +1239,11 @@
468 if (size > BUF) /* should never happen */
475 +#endif /* VECTORS */
476 default: /* "%?" prints ?, unless ? is NUL */
479 @@ -1122,6 +1255,288 @@
484 + if (flags & VECTOR) {
486 + * Do the minimum amount of work necessary to construct
487 + * a format specifier that can be used to recursively
488 + * call vfprintf() for each element in the vector.
490 + int i, j; /* Counter. */
491 + int vcnt; /* Number of elements in vector. */
492 + char *vfmt; /* Pointer to format specifier. */
494 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
495 + int vwidth = 0; /* Width specified via '*'. */
496 + int vprec = 0; /* Precision specified via '*'. */
497 + char *vstr; /* Used for asprintf(). */
498 + int vlen; /* Length returned by asprintf(). */
500 + V_CHAR, V_SHORT, V_INT,
501 + V_PCHAR, V_PSHORT, V_PINT,
504 + V_LONGLONG, V_PLONGLONG,
506 +#endif /* V64TYPE */
509 + vval.vectorarg = GETARG(VECTORTYPE);
511 + * Set vfmt. If vfmt_buf may not be big enough,
512 + * malloc() space, taking care to free it later.
513 + * (EXTRAHH is for possible extra "hh")
515 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
518 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
520 + /* Set the separator character, if not specified. */
528 + /* Create the format specifier. */
529 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
531 + case ',': case ';': case ':': case '_':
532 + case 'v': case 'h': case 'l':
536 + if (pct[i - 1] != '.')
542 + vfmt[j++] = pct[i];
547 + * Determine the number of elements in the vector and
548 + * finish up the format specifier.
550 + if (flags & SHORTINT) {
564 + } else if (flags & LONGINT) {
566 + vtype = (ch == 'p') ? V_PINT : V_INT;
568 + } else if (flags & LLONGINT) {
590 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
594 + * The default case should never
601 +#endif /* V64TYPE */
616 + * The default case should never
631 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
637 +/* Get a vector element. */
639 +#define VPRINT(type, ind, args...) do { \
642 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
645 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
648 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
651 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
654 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
657 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
660 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
662 + case V_PLONGLONG: \
663 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
666 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
669 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
673 + PRINT(vstr, vlen); \
676 +#else /* !V64TYPE */
677 +#define VPRINT(type, ind, args...) do { \
680 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
683 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
686 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
689 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
692 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
695 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
698 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
702 + PRINT(vstr, vlen); \
705 +#endif /* V64TYPE */
707 + /* Actually print. */
710 + /* First element. */
712 + for (i = 1; i < vcnt; i++) {
721 + /* First element. */
722 + VPRINT(vtype, 0, prec);
723 + for (i = 1; i < vcnt; i++) {
729 + VPRINT(vtype, i, prec);
734 + /* First element. */
735 + VPRINT(vtype, 0, width);
736 + for (i = 1; i < vcnt; i++) {
742 + VPRINT(vtype, i, width);
745 + /* First element. */
746 + VPRINT(vtype, 0, width, prec);
747 + for (i = 1; i < vcnt; i++) {
753 + VPRINT(vtype, i, width, prec);
759 + if (vfmt != vfmt_buf)
764 +#endif /* VECTORS */
766 * All reasonable formats wind up here. At this point, `cp'
767 * points to a string which (if not flags&LADJUST) should be
768 @@ -1401,6 +1816,11 @@
773 + if (flags & VECTOR)
776 +#endif /* VECTORS */
780 @@ -1408,6 +1828,11 @@
785 + if (flags & VECTOR)
788 +#endif /* VECTORS */
791 #ifndef NO_FLOATING_POINT
792 @@ -1418,6 +1843,11 @@
797 + if (flags & VECTOR)
800 +#endif /* VECTORS */
802 ADDTYPE(T_LONG_DOUBLE);
804 @@ -1446,9 +1876,19 @@
809 + if (flags & VECTOR)
812 +#endif /* VECTORS */
817 + if (flags & VECTOR)
820 +#endif /* VECTORS */
824 @@ -1466,6 +1906,11 @@
829 + if (flags & VECTOR)
832 +#endif /* VECTORS */
835 default: /* "%?" prints ?, unless ? is NUL */
836 @@ -1532,7 +1977,7 @@
837 (*argtable) [n].sizearg = va_arg (ap, size_t);
840 - (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
841 + (*argtable) [n].psizearg = va_arg (ap, size_t *);
844 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
845 @@ -1551,6 +1996,11 @@
846 (*argtable) [n].longdoublearg = va_arg (ap, long double);
851 + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
853 +#endif /* VECTORS */
855 (*argtable) [n].pchararg = va_arg (ap, char *);