1 --- vfprintf.c.orig 2006-10-01 00:03:16.000000000 -0700
2 +++ vfprintf.c 2006-10-01 00:21:05.000000000 -0700
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;
106 char buf[MB_LEN_MAX];
109 - size_t clen, nbytes;
110 + size_t clen = 0, nbytes;
113 * Determine the number of bytes to output and allocate space for
118 - clen = wcrtomb(buf, *p++, &mbs);
119 + clen = wcrtomb_l(buf, *p++, &mbs, loc);
120 if (clen == 0 || clen == (size_t)-1 ||
121 nbytes + clen > prec)
127 - nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
128 + nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
129 if (nbytes == (size_t)-1)
135 while (mbp - convbuf < nbytes) {
136 - clen = wcrtomb(mbp, *p++, &mbs);
137 + clen = wcrtomb_l(mbp, *p++, &mbs, loc);
138 if (clen == 0 || clen == (size_t)-1)
145 +__private_extern__ const char *__fix_nogrouping(const char *);
148 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
154 - ret = __vfprintf(fp, fmt0, ap);
155 + ret = __vfprintf(fp, __current_locale(), fmt0, ap);
161 +vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0,
167 + NORMALIZE_LOCALE(loc);
169 + ret = __vfprintf(fp, loc, fmt0, ap);
173 @@ -451,12 +496,15 @@
174 #define PTRDIFFT 0x800 /* ptrdiff_t */
175 #define INTMAXT 0x1000 /* intmax_t */
176 #define CHARINT 0x2000 /* print char using int format */
178 +#define VECTOR 0x4000 /* Altivec or SSE vector */
179 +#endif /* VECTORS */
182 * Non-MT-safe version
185 -__vfprintf(FILE *fp, const char *fmt0, va_list ap)
186 +__private_extern__ int
187 +__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
189 char *fmt; /* format string */
190 int ch; /* character from fmt */
192 int nseps; /* number of group separators with ' */
193 int nrepeats; /* number of repeats of the last group */
196 + union arg vval; /* Vector argument. */
197 + char *pct; /* Pointer to '%' at beginning of specifier. */
198 + char vsep; /* Vector separator character. */
200 u_long ulval; /* integer arguments %[diouxX] */
201 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
202 int base; /* base for [diouxX] conversion */
204 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
206 (flags&INTMAXT ? GETARG(intmax_t) : \
207 - flags&SIZET ? (intmax_t)GETARG(size_t) : \
208 + flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
209 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
210 (intmax_t)GETARG(long long))
212 @@ -633,22 +686,24 @@
213 val = GETARG (int); \
217 thousands_sep = '\0';
220 #ifndef NO_FLOATING_POINT
222 - decimal_point = localeconv()->decimal_point;
223 + decimal_point = localeconv_l(loc)->decimal_point;
225 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
226 - if (prepwrite(fp) != 0)
227 + if (prepwrite(fp) != 0) {
233 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
234 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
236 - return (__sbprintf(fp, fmt0, ap));
237 + return (__sbprintf(fp, loc, fmt0, ap));
247 +#endif /* VECTORS */
248 fmt++; /* skip over '%' */
256 + vsep = 'X'; /* Illegal value, changed to defaults later. */
257 +#endif /* VECTORS */
260 reswitch: switch (ch) {
266 + case ',': case ';': case ':': case '_':
269 +#endif /* VECTORS */
272 * ``A negative field width argument is taken as a
277 - thousands_sep = *(localeconv()->thousands_sep);
278 - grouping = localeconv()->grouping;
279 + thousands_sep = *(localeconv_l(loc)->thousands_sep);
280 + grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
283 if ((ch = *fmt++) == '*') {
284 @@ -793,14 +859,18 @@
289 + if (flags & VECTOR)
291 +#endif /* VECTORS */
292 if (flags & LONGINT) {
293 static const mbstate_t initial;
298 - mbseqlen = wcrtomb(cp = buf,
299 - (wchar_t)GETARG(wint_t), &mbs);
300 + mbseqlen = wcrtomb_l(cp = buf,
301 + (wchar_t)GETARG(wint_t), &mbs, loc);
302 if (mbseqlen == (size_t)-1) {
303 fp->_flags |= __SERR;
310 + if (flags & VECTOR)
312 +#endif /* VECTORS */
313 if (flags & INTMAX_SIZE) {
315 if ((intmax_t)ujval < 0) {
317 #ifndef NO_FLOATING_POINT
321 + if (flags & VECTOR) {
325 +#endif /* VECTORS */
331 if (dtoaresult != NULL)
332 freedtoa(dtoaresult);
334 + fparg.dbl = GETARG(double);
336 + __hdtoa(fparg.dbl, xdigs, prec,
337 + &expt, &signflag, &dtoaend);
338 +#else /* !LDBL_COMPAT */
339 if (flags & LONGDBL) {
340 fparg.ldbl = GETARG(long double);
343 __hdtoa(fparg.dbl, xdigs, prec,
344 &expt, &signflag, &dtoaend);
346 +#endif /* LDBL_COMPAT */
355 + if (flags & VECTOR) {
359 +#endif /* VECTORS */
361 if (prec < 0) /* account for digit before decpt */
363 @@ -874,10 +967,22 @@
368 + if (flags & VECTOR) {
372 +#endif /* VECTORS */
378 + if (flags & VECTOR) {
382 +#endif /* VECTORS */
383 expchar = ch - ('g' - 'e');
388 if (dtoaresult != NULL)
389 freedtoa(dtoaresult);
391 + fparg.dbl = GETARG(double);
393 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
394 + &expt, &signflag, &dtoaend);
397 +#else /* !LDBL_COMPAT */
398 if (flags & LONGDBL) {
399 fparg.ldbl = GETARG(long double);
405 +#endif /* LDBL_COMPAT */
409 @@ -993,6 +1107,10 @@
414 + if (flags & VECTOR)
416 +#endif /* VECTORS */
417 if (flags & INTMAX_SIZE)
420 @@ -1007,6 +1125,10 @@
425 + if (flags & VECTOR)
427 +#endif /* VECTORS */
428 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
431 @@ -1025,7 +1147,7 @@
432 if ((wcp = GETARG(wchar_t *)) == NULL)
435 - convbuf = __wcsconv(wcp, prec);
436 + convbuf = __wcsconv(wcp, prec, loc);
437 if (convbuf == NULL) {
438 fp->_flags |= __SERR;
440 @@ -1056,6 +1178,10 @@
445 + if (flags & VECTOR)
447 +#endif /* VECTORS */
448 if (flags & INTMAX_SIZE)
451 @@ -1068,6 +1194,10 @@
456 + if (flags & VECTOR)
458 +#endif /* VECTORS */
459 if (flags & INTMAX_SIZE)
462 @@ -1093,6 +1223,7 @@
463 * ``The result of converting a zero value with an
464 * explicit precision of zero is no characters.''
466 + * except for %#.0o and zero value
469 if (flags & INTMAX_SIZE) {
470 @@ -1102,7 +1233,7 @@
471 flags & GROUPING, thousands_sep,
474 - if (ulval != 0 || prec != 0)
475 + if (ulval != 0 || prec != 0 || (flags & ALT))
476 cp = __ultoa(ulval, cp, base,
478 flags & GROUPING, thousands_sep,
479 @@ -1112,6 +1243,11 @@
480 if (size > BUF) /* should never happen */
487 +#endif /* VECTORS */
488 default: /* "%?" prints ?, unless ? is NUL */
491 @@ -1123,6 +1259,290 @@
496 + if (flags & VECTOR) {
498 + * Do the minimum amount of work necessary to construct
499 + * a format specifier that can be used to recursively
500 + * call vfprintf() for each element in the vector.
502 + int i, j; /* Counter. */
503 + int vcnt; /* Number of elements in vector. */
504 + char *vfmt; /* Pointer to format specifier. */
506 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
507 + int vwidth = 0; /* Width specified via '*'. */
508 + int vprec = 0; /* Precision specified via '*'. */
509 + char *vstr; /* Used for asprintf(). */
510 + int vlen; /* Length returned by asprintf(). */
512 + V_CHAR, V_SHORT, V_INT,
513 + V_PCHAR, V_PSHORT, V_PINT,
516 + V_LONGLONG, V_PLONGLONG,
518 +#endif /* V64TYPE */
521 + vval.vectorarg = GETARG(VECTORTYPE);
523 + * Set vfmt. If vfmt_buf may not be big enough,
524 + * malloc() space, taking care to free it later.
525 + * (EXTRAHH is for possible extra "hh")
527 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
530 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
532 + /* Set the separator character, if not specified. */
540 + /* Create the format specifier. */
541 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
543 + case ',': case ';': case ':': case '_':
544 + case 'v': case 'h': case 'l':
548 + if (pct[i - 1] != '.')
554 + vfmt[j++] = pct[i];
559 + * Determine the number of elements in the vector and
560 + * finish up the format specifier.
562 + if (flags & SHORTINT) {
576 + } else if (flags & LONGINT) {
578 + vtype = (ch == 'p') ? V_PINT : V_INT;
580 + } else if (flags & LLONGINT) {
602 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
606 + * The default case should never
613 +#endif /* V64TYPE */
628 + * The default case should never
643 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
649 +/* Get a vector element. */
651 +#define VPRINT(type, ind, args...) do { \
654 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
657 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
660 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
663 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
666 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
669 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
672 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
674 + case V_PLONGLONG: \
675 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
678 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
681 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
685 + PRINT(vstr, vlen); \
689 +#else /* !V64TYPE */
690 +#define VPRINT(type, ind, args...) do { \
693 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
696 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
699 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
702 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
705 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
708 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
711 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
715 + PRINT(vstr, vlen); \
719 +#endif /* V64TYPE */
721 + /* Actually print. */
724 + /* First element. */
726 + for (i = 1; i < vcnt; i++) {
735 + /* First element. */
736 + VPRINT(vtype, 0, prec);
737 + for (i = 1; i < vcnt; i++) {
743 + VPRINT(vtype, i, prec);
748 + /* First element. */
749 + VPRINT(vtype, 0, width);
750 + for (i = 1; i < vcnt; i++) {
756 + VPRINT(vtype, i, width);
759 + /* First element. */
760 + VPRINT(vtype, 0, width, prec);
761 + for (i = 1; i < vcnt; i++) {
767 + VPRINT(vtype, i, width, prec);
773 + if (vfmt != vfmt_buf)
778 +#endif /* VECTORS */
780 * All reasonable formats wind up here. At this point, `cp'
781 * points to a string which (if not flags&LADJUST) should be
782 @@ -1178,7 +1598,7 @@
785 if (prec || flags & ALT)
786 - PRINT(decimal_point, 1);
787 + PRINT(decimal_point, strlen(decimal_point));
789 /* already handled initial 0's */
791 @@ -1203,14 +1623,14 @@
794 if (prec || flags & ALT)
795 - PRINT(decimal_point,1);
796 + PRINT(decimal_point, strlen(decimal_point));
798 PRINTANDPAD(cp, dtoaend, prec, zeroes);
799 } else { /* %[eE] or sufficiently long %[gG] */
800 if (prec > 1 || flags & ALT) {
802 - buf[1] = *decimal_point;
805 + PRINT(decimal_point, strlen(decimal_point));
807 PAD(prec - ndig, zeroes);
809 @@ -1406,6 +1826,11 @@
814 + if (flags & VECTOR)
817 +#endif /* VECTORS */
821 @@ -1413,6 +1838,11 @@
826 + if (flags & VECTOR)
832 #ifndef NO_FLOATING_POINT
833 @@ -1421,8 +1851,14 @@
841 + if (flags & VECTOR)
844 +#endif /* VECTORS */
846 ADDTYPE(T_LONG_DOUBLE);
848 @@ -1451,9 +1887,19 @@
853 + if (flags & VECTOR)
856 +#endif /* VECTORS */
861 + if (flags & VECTOR)
864 +#endif /* VECTORS */
868 @@ -1471,6 +1917,11 @@
873 + if (flags & VECTOR)
876 +#endif /* VECTORS */
879 default: /* "%?" prints ?, unless ? is NUL */
880 @@ -1537,7 +1988,7 @@
881 (*argtable) [n].sizearg = va_arg (ap, size_t);
884 - (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
885 + (*argtable) [n].psizearg = va_arg (ap, size_t *);
888 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
889 @@ -1556,6 +2007,11 @@
890 (*argtable) [n].longdoublearg = va_arg (ap, long double);
895 + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
897 +#endif /* VECTORS */
899 (*argtable) [n].pchararg = va_arg (ap, char *);