1 --- vfprintf.c.orig 2004-11-25 11:38:35.000000000 -0800
2 +++ vfprintf.c 2005-11-08 22:43:11.000000000 -0800
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfprintf.c,v 1.68 2004/08/26 06:25:28 des Exp $");
7 +#include "xlocale_private.h"
10 * Actual printf innards.
19 #include "un-namespace.h"
25 +typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
28 +#endif /* __SSE2__ */
39 + VECTORTYPE vectorarg;
40 + unsigned char vuchararg[16];
41 + signed char vchararg[16];
42 + unsigned short vushortarg[8];
43 + signed short vshortarg[8];
44 + unsigned int vuintarg[4];
45 + signed int vintarg[4];
48 + double vdoublearg[2];
49 + unsigned long long vulonglongarg[2];
50 + long long vlonglongarg[2];
57 T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
58 T_PTRDIFFT, TP_PTRDIFFT, T_SIZET, TP_SIZET,
59 T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
61 + T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR, T_VECTOR
62 +#else /* ! VECTORS */
63 T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
67 static int __sprint(FILE *, struct __suio *);
68 -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0);
69 +static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0);
70 static char *__ujtoa(uintmax_t, char *, int, int, const char *, int, char,
72 static char *__ultoa(u_long, char *, int, int, const char *, int, char,
74 -static char *__wcsconv(wchar_t *, int);
75 +static char *__wcsconv(wchar_t *, int, locale_t);
76 static void __find_arguments(const char *, 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 char *fmt, va_list ap)
84 +__sbprintf(FILE *fp, locale_t loc, const char *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 = __vfprintf(&fake, fmt, ap);
93 + ret = __vfprintf(&fake, loc, fmt, ap);
94 if (ret >= 0 && __fflush(&fake))
96 if (fake._flags & __SERR)
98 * that the wide char. string ends in a null character.
101 -__wcsconv(wchar_t *wcsarg, int prec)
102 +__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
104 static const mbstate_t initial;
110 - clen = wcrtomb(buf, *p++, &mbs);
111 + clen = wcrtomb_l(buf, *p++, &mbs, loc);
112 if (clen == 0 || clen == (size_t)-1 ||
113 nbytes + clen > prec)
119 - nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
120 + nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
121 if (nbytes == (size_t)-1)
127 while (mbp - convbuf < nbytes) {
128 - clen = wcrtomb(mbp, *p++, &mbs);
129 + clen = wcrtomb_l(mbp, *p++, &mbs, loc);
130 if (clen == 0 || clen == (size_t)-1)
137 - ret = __vfprintf(fp, fmt0, ap);
138 + ret = __vfprintf(fp, __current_locale(), fmt0, ap);
144 +vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0,
150 + NORMALIZE_LOCALE(loc);
152 + ret = __vfprintf(fp, loc, fmt0, ap);
156 @@ -451,12 +494,15 @@
157 #define PTRDIFFT 0x800 /* ptrdiff_t */
158 #define INTMAXT 0x1000 /* intmax_t */
159 #define CHARINT 0x2000 /* print char using int format */
161 +#define VECTOR 0x4000 /* Altivec or SSE vector */
162 +#endif /* VECTORS */
165 * Non-MT-safe version
168 -__vfprintf(FILE *fp, const char *fmt0, va_list ap)
169 +__private_extern__ int
170 +__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
172 char *fmt; /* format string */
173 int ch; /* character from fmt */
175 int nseps; /* number of group separators with ' */
176 int nrepeats; /* number of repeats of the last group */
179 + union arg vval; /* Vector argument. */
180 + char *pct; /* Pointer to '%' at beginning of specifier. */
181 + char vsep; /* Vector separator character. */
183 u_long ulval; /* integer arguments %[diouxX] */
184 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
185 int base; /* base for [diouxX] conversion */
186 @@ -633,22 +684,23 @@
187 val = GETARG (int); \
191 thousands_sep = '\0';
194 #ifndef NO_FLOATING_POINT
196 - decimal_point = localeconv()->decimal_point;
197 + decimal_point = localeconv_l(loc)->decimal_point;
199 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
200 - if (prepwrite(fp) != 0)
201 + if (prepwrite(fp) != 0) {
206 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
207 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
209 - return (__sbprintf(fp, fmt0, ap));
210 + return (__sbprintf(fp, loc, fmt0, ap));
220 +#endif /* VECTORS */
221 fmt++; /* skip over '%' */
229 + vsep = 'X'; /* Illegal value, changed to defaults later. */
230 +#endif /* VECTORS */
233 reswitch: switch (ch) {
239 + case ',': case ';': case ':': case '_':
242 +#endif /* VECTORS */
245 * ``A negative field width argument is taken as a
250 - thousands_sep = *(localeconv()->thousands_sep);
251 - grouping = localeconv()->grouping;
252 + thousands_sep = *(localeconv_l(loc)->thousands_sep);
253 + grouping = localeconv_l(loc)->grouping;
256 if ((ch = *fmt++) == '*') {
257 @@ -793,14 +856,18 @@
262 + if (flags & VECTOR)
264 +#endif /* VECTORS */
265 if (flags & LONGINT) {
266 static const mbstate_t initial;
271 - mbseqlen = wcrtomb(cp = buf,
272 - (wchar_t)GETARG(wint_t), &mbs);
273 + mbseqlen = wcrtomb_l(cp = buf,
274 + (wchar_t)GETARG(wint_t), &mbs, loc);
275 if (mbseqlen == (size_t)-1) {
276 fp->_flags |= __SERR;
283 + if (flags & VECTOR)
285 +#endif /* VECTORS */
286 if (flags & INTMAX_SIZE) {
288 if ((intmax_t)ujval < 0) {
290 #ifndef NO_FLOATING_POINT
294 + if (flags & VECTOR) {
298 +#endif /* VECTORS */
304 if (dtoaresult != NULL)
305 freedtoa(dtoaresult);
307 + fparg.dbl = GETARG(double);
309 + __hdtoa(fparg.dbl, xdigs, prec,
310 + &expt, &signflag, &dtoaend);
311 +#else /* !LDBL_COMPAT */
312 if (flags & LONGDBL) {
313 fparg.ldbl = GETARG(long double);
316 __hdtoa(fparg.dbl, xdigs, prec,
317 &expt, &signflag, &dtoaend);
319 +#endif /* LDBL_COMPAT */
328 + if (flags & VECTOR) {
332 +#endif /* VECTORS */
334 if (prec < 0) /* account for digit before decpt */
336 @@ -874,10 +964,22 @@
341 + if (flags & VECTOR) {
345 +#endif /* VECTORS */
351 + if (flags & VECTOR) {
355 +#endif /* VECTORS */
356 expchar = ch - ('g' - 'e');
361 if (dtoaresult != NULL)
362 freedtoa(dtoaresult);
364 + fparg.dbl = GETARG(double);
366 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
367 + &expt, &signflag, &dtoaend);
370 +#else /* !LDBL_COMPAT */
371 if (flags & LONGDBL) {
372 fparg.ldbl = GETARG(long double);
378 +#endif /* LDBL_COMPAT */
382 @@ -993,6 +1104,10 @@
387 + if (flags & VECTOR)
389 +#endif /* VECTORS */
390 if (flags & INTMAX_SIZE)
393 @@ -1007,6 +1122,10 @@
398 + if (flags & VECTOR)
400 +#endif /* VECTORS */
401 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
404 @@ -1025,7 +1144,7 @@
405 if ((wcp = GETARG(wchar_t *)) == NULL)
408 - convbuf = __wcsconv(wcp, prec);
409 + convbuf = __wcsconv(wcp, prec, loc);
410 if (convbuf == NULL) {
411 fp->_flags |= __SERR;
413 @@ -1056,6 +1175,10 @@
418 + if (flags & VECTOR)
420 +#endif /* VECTORS */
421 if (flags & INTMAX_SIZE)
424 @@ -1068,6 +1191,10 @@
429 + if (flags & VECTOR)
431 +#endif /* VECTORS */
432 if (flags & INTMAX_SIZE)
435 @@ -1112,6 +1239,11 @@
436 if (size > BUF) /* should never happen */
443 +#endif /* VECTORS */
444 default: /* "%?" prints ?, unless ? is NUL */
447 @@ -1123,6 +1255,290 @@
452 + if (flags & VECTOR) {
454 + * Do the minimum amount of work necessary to construct
455 + * a format specifier that can be used to recursively
456 + * call vfprintf() for each element in the vector.
458 + int i, j; /* Counter. */
459 + int vcnt; /* Number of elements in vector. */
460 + char *vfmt; /* Pointer to format specifier. */
462 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
463 + int vwidth = 0; /* Width specified via '*'. */
464 + int vprec = 0; /* Precision specified via '*'. */
465 + char *vstr; /* Used for asprintf(). */
466 + int vlen; /* Length returned by asprintf(). */
468 + V_CHAR, V_SHORT, V_INT,
469 + V_PCHAR, V_PSHORT, V_PINT,
472 + V_LONGLONG, V_PLONGLONG,
474 +#endif /* V64TYPE */
477 + vval.vectorarg = GETARG(VECTORTYPE);
479 + * Set vfmt. If vfmt_buf may not be big enough,
480 + * malloc() space, taking care to free it later.
481 + * (EXTRAHH is for possible extra "hh")
483 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
486 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
488 + /* Set the separator character, if not specified. */
496 + /* Create the format specifier. */
497 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
499 + case ',': case ';': case ':': case '_':
500 + case 'v': case 'h': case 'l':
504 + if (pct[i - 1] != '.')
510 + vfmt[j++] = pct[i];
515 + * Determine the number of elements in the vector and
516 + * finish up the format specifier.
518 + if (flags & SHORTINT) {
532 + } else if (flags & LONGINT) {
534 + vtype = (ch == 'p') ? V_PINT : V_INT;
536 + } else if (flags & LLONGINT) {
558 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
562 + * The default case should never
569 +#endif /* V64TYPE */
584 + * The default case should never
599 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
605 +/* Get a vector element. */
607 +#define VPRINT(type, ind, args...) do { \
610 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
613 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
616 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
619 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
622 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
625 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
628 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
630 + case V_PLONGLONG: \
631 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
634 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
637 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
641 + PRINT(vstr, vlen); \
645 +#else /* !V64TYPE */
646 +#define VPRINT(type, ind, args...) do { \
649 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
652 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
655 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
658 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
661 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
664 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
667 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
671 + PRINT(vstr, vlen); \
675 +#endif /* V64TYPE */
677 + /* Actually print. */
680 + /* First element. */
682 + for (i = 1; i < vcnt; i++) {
691 + /* First element. */
692 + VPRINT(vtype, 0, prec);
693 + for (i = 1; i < vcnt; i++) {
699 + VPRINT(vtype, i, prec);
704 + /* First element. */
705 + VPRINT(vtype, 0, width);
706 + for (i = 1; i < vcnt; i++) {
712 + VPRINT(vtype, i, width);
715 + /* First element. */
716 + VPRINT(vtype, 0, width, prec);
717 + for (i = 1; i < vcnt; i++) {
723 + VPRINT(vtype, i, width, prec);
729 + if (vfmt != vfmt_buf)
734 +#endif /* VECTORS */
736 * All reasonable formats wind up here. At this point, `cp'
737 * points to a string which (if not flags&LADJUST) should be
738 @@ -1406,6 +1822,11 @@
743 + if (flags & VECTOR)
746 +#endif /* VECTORS */
750 @@ -1413,6 +1834,11 @@
755 + if (flags & VECTOR)
761 #ifndef NO_FLOATING_POINT
762 @@ -1423,6 +1849,11 @@
767 + if (flags & VECTOR)
770 +#endif /* VECTORS */
772 ADDTYPE(T_LONG_DOUBLE);
774 @@ -1451,9 +1882,19 @@
779 + if (flags & VECTOR)
782 +#endif /* VECTORS */
787 + if (flags & VECTOR)
790 +#endif /* VECTORS */
794 @@ -1471,6 +1912,11 @@
799 + if (flags & VECTOR)
802 +#endif /* VECTORS */
805 default: /* "%?" prints ?, unless ? is NUL */
806 @@ -1537,7 +1983,7 @@
807 (*argtable) [n].sizearg = va_arg (ap, size_t);
810 - (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
811 + (*argtable) [n].psizearg = va_arg (ap, size_t *);
814 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
815 @@ -1556,6 +2002,11 @@
816 (*argtable) [n].longdoublearg = va_arg (ap, long double);
821 + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
823 +#endif /* VECTORS */
825 (*argtable) [n].pchararg = va_arg (ap, char *);