1 --- vfprintf.c.orig 2008-09-07 11:37:54.000000000 -0700
2 +++ vfprintf.c 2008-09-07 17:33:16.000000000 -0700
3 @@ -40,6 +40,8 @@ static char sccsid[] = "@(#)vfprintf.c 8
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.
12 @@ -58,6 +60,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
19 #include "un-namespace.h"
20 @@ -66,6 +69,13 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
25 +typedef __attribute__ ((vector_size(16))) unsigned char VECTORTYPE;
28 +#endif /* __SSE2__ */
34 @@ -93,6 +103,21 @@ union arg {
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];
56 @@ -103,16 +128,20 @@ enum typeid {
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 *);
79 @@ -141,7 +170,7 @@ __sprint(FILE *fp, struct __suio *uio)
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)
88 @@ -160,7 +189,7 @@ __sbprintf(FILE *fp, const char *fmt, va
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)
97 @@ -252,7 +281,7 @@ __ultoa(u_long val, char *endp, int base
102 + LIBC_ABORT("base = %d", base);
106 @@ -324,7 +353,7 @@ __ujtoa(uintmax_t val, char *endp, int b
111 + LIBC_ABORT("base = %d", base);
115 @@ -336,14 +365,14 @@ __ujtoa(uintmax_t val, char *endp, int b
116 * that the wide char. string ends in a null character.
119 -__wcsconv(wchar_t *wcsarg, int prec)
120 +__wcsconv(wchar_t *wcsarg, int prec, locale_t loc)
122 static const mbstate_t initial;
124 char buf[MB_LEN_MAX];
127 - size_t clen, nbytes;
128 + size_t clen = 0, nbytes;
131 * Determine the number of bytes to output and allocate space for
132 @@ -354,7 +383,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
136 - clen = wcrtomb(buf, *p++, &mbs);
137 + clen = wcrtomb_l(buf, *p++, &mbs, loc);
138 if (clen == 0 || clen == (size_t)-1 ||
139 nbytes + clen > prec)
141 @@ -363,7 +392,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
145 - nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
146 + nbytes = wcsrtombs_l(NULL, (const wchar_t **)&p, 0, &mbs, loc);
147 if (nbytes == (size_t)-1)
150 @@ -378,7 +407,7 @@ __wcsconv(wchar_t *wcsarg, int prec)
153 while (mbp - convbuf < nbytes) {
154 - clen = wcrtomb(mbp, *p++, &mbs);
155 + clen = wcrtomb_l(mbp, *p++, &mbs, loc);
156 if (clen == 0 || clen == (size_t)-1)
159 @@ -395,6 +424,8 @@ __wcsconv(wchar_t *wcsarg, int prec)
163 +__private_extern__ const char *__fix_nogrouping(const char *);
166 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
168 @@ -402,7 +433,21 @@ vfprintf(FILE * __restrict fp, const cha
172 - ret = __vfprintf(fp, fmt0, ap);
173 + ret = __vfprintf(fp, __current_locale(), fmt0, ap);
179 +vfprintf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0,
185 + NORMALIZE_LOCALE(loc);
187 + ret = __vfprintf(fp, loc, fmt0, ap);
191 @@ -451,12 +496,15 @@ static int exponent(char *, int, int);
192 #define PTRDIFFT 0x800 /* ptrdiff_t */
193 #define INTMAXT 0x1000 /* intmax_t */
194 #define CHARINT 0x2000 /* print char using int format */
196 +#define VECTOR 0x4000 /* Altivec or SSE vector */
197 +#endif /* VECTORS */
200 * Non-MT-safe version
203 -__vfprintf(FILE *fp, const char *fmt0, va_list ap)
204 +__private_extern__ int
205 +__vfprintf(FILE *fp, locale_t loc, const char *fmt0, va_list ap)
207 char *fmt; /* format string */
208 int ch; /* character from fmt */
209 @@ -502,6 +550,11 @@ __vfprintf(FILE *fp, const char *fmt0, v
210 int nseps; /* number of group separators with ' */
211 int nrepeats; /* number of repeats of the last group */
214 + union arg vval; /* Vector argument. */
215 + char *pct; /* Pointer to '%' at beginning of specifier. */
216 + char vsep; /* Vector separator character. */
218 u_long ulval; /* integer arguments %[diouxX] */
219 uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
220 int base; /* base for [diouxX] conversion */
221 @@ -599,13 +652,13 @@ __vfprintf(FILE *fp, const char *fmt0, v
222 #define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
224 (flags&INTMAXT ? GETARG(intmax_t) : \
225 - flags&SIZET ? (intmax_t)GETARG(size_t) : \
226 + flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
227 flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
228 (intmax_t)GETARG(long long))
230 (flags&INTMAXT ? GETARG(uintmax_t) : \
231 flags&SIZET ? (uintmax_t)GETARG(size_t) : \
232 - flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
233 + flags&PTRDIFFT ? (uintmax_t)(unsigned)GETARG(ptrdiff_t) : \
234 (uintmax_t)GETARG(unsigned long long))
237 @@ -633,22 +686,24 @@ __vfprintf(FILE *fp, const char *fmt0, v
238 val = GETARG (int); \
242 thousands_sep = '\0';
245 #ifndef NO_FLOATING_POINT
247 - decimal_point = localeconv()->decimal_point;
248 + decimal_point = localeconv_l(loc)->decimal_point;
250 /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
251 - if (prepwrite(fp) != 0)
252 + if (prepwrite(fp) != 0) {
258 /* optimise fprintf(stderr) (and other unbuffered Unix files) */
259 if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
261 - return (__sbprintf(fp, fmt0, ap));
262 + return (__sbprintf(fp, loc, fmt0, ap));
266 @@ -675,6 +730,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
272 +#endif /* VECTORS */
273 fmt++; /* skip over '%' */
276 @@ -683,6 +741,9 @@ __vfprintf(FILE *fp, const char *fmt0, v
281 + vsep = 'X'; /* Illegal value, changed to defaults later. */
282 +#endif /* VECTORS */
285 reswitch: switch (ch) {
286 @@ -698,6 +759,11 @@ reswitch: switch (ch) {
291 + case ',': case ';': case ':': case '_':
294 +#endif /* VECTORS */
297 * ``A negative field width argument is taken as a
298 @@ -718,8 +784,8 @@ reswitch: switch (ch) {
302 - thousands_sep = *(localeconv()->thousands_sep);
303 - grouping = localeconv()->grouping;
304 + thousands_sep = *(localeconv_l(loc)->thousands_sep);
305 + grouping = __fix_nogrouping(localeconv_l(loc)->grouping);
308 if ((ch = *fmt++) == '*') {
309 @@ -793,14 +859,18 @@ reswitch: switch (ch) {
314 + if (flags & VECTOR)
316 +#endif /* VECTORS */
317 if (flags & LONGINT) {
318 static const mbstate_t initial;
323 - mbseqlen = wcrtomb(cp = buf,
324 - (wchar_t)GETARG(wint_t), &mbs);
325 + mbseqlen = wcrtomb_l(cp = buf,
326 + (wchar_t)GETARG(wint_t), &mbs, loc);
327 if (mbseqlen == (size_t)-1) {
328 fp->_flags |= __SERR;
330 @@ -817,6 +887,10 @@ reswitch: switch (ch) {
335 + if (flags & VECTOR)
337 +#endif /* VECTORS */
338 if (flags & INTMAX_SIZE) {
340 if ((intmax_t)ujval < 0) {
341 @@ -835,6 +909,12 @@ reswitch: switch (ch) {
342 #ifndef NO_FLOATING_POINT
346 + if (flags & VECTOR) {
350 +#endif /* VECTORS */
354 @@ -848,6 +928,12 @@ reswitch: switch (ch) {
356 if (dtoaresult != NULL)
357 freedtoa(dtoaresult);
359 + fparg.dbl = GETARG(double);
361 + __hdtoa(fparg.dbl, xdigs, prec,
362 + &expt, &signflag, &dtoaend);
363 +#else /* !LDBL_COMPAT */
364 if (flags & LONGDBL) {
365 fparg.ldbl = GETARG(long double);
367 @@ -859,6 +945,7 @@ reswitch: switch (ch) {
368 __hdtoa(fparg.dbl, xdigs, prec,
369 &expt, &signflag, &dtoaend);
371 +#endif /* LDBL_COMPAT */
375 @@ -866,6 +953,12 @@ reswitch: switch (ch) {
380 + if (flags & VECTOR) {
384 +#endif /* VECTORS */
386 if (prec < 0) /* account for digit before decpt */
388 @@ -874,10 +967,22 @@ reswitch: switch (ch) {
393 + if (flags & VECTOR) {
397 +#endif /* VECTORS */
403 + if (flags & VECTOR) {
407 +#endif /* VECTORS */
408 expchar = ch - ('g' - 'e');
411 @@ -886,6 +991,14 @@ fp_begin:
413 if (dtoaresult != NULL)
414 freedtoa(dtoaresult);
416 + fparg.dbl = GETARG(double);
418 + dtoa(fparg.dbl, expchar ? 2 : 3, prec,
419 + &expt, &signflag, &dtoaend);
422 +#else /* !LDBL_COMPAT */
423 if (flags & LONGDBL) {
424 fparg.ldbl = GETARG(long double);
426 @@ -899,6 +1012,7 @@ fp_begin:
430 +#endif /* LDBL_COMPAT */
434 @@ -993,6 +1107,10 @@ fp_common:
439 + if (flags & VECTOR)
441 +#endif /* VECTORS */
442 if (flags & INTMAX_SIZE)
445 @@ -1007,6 +1125,10 @@ fp_common:
450 + if (flags & VECTOR)
452 +#endif /* VECTORS */
453 ujval = (uintmax_t)(uintptr_t)GETARG(void *);
456 @@ -1025,7 +1147,7 @@ fp_common:
457 if ((wcp = GETARG(wchar_t *)) == NULL)
460 - convbuf = __wcsconv(wcp, prec);
461 + convbuf = __wcsconv(wcp, prec, loc);
462 if (convbuf == NULL) {
463 fp->_flags |= __SERR;
465 @@ -1056,6 +1178,10 @@ fp_common:
470 + if (flags & VECTOR)
472 +#endif /* VECTORS */
473 if (flags & INTMAX_SIZE)
476 @@ -1068,6 +1194,10 @@ fp_common:
481 + if (flags & VECTOR)
483 +#endif /* VECTORS */
484 if (flags & INTMAX_SIZE)
487 @@ -1093,6 +1223,7 @@ number: if ((dprec = prec) >= 0)
488 * ``The result of converting a zero value with an
489 * explicit precision of zero is no characters.''
491 + * except for %#.0o and zero value
494 if (flags & INTMAX_SIZE) {
495 @@ -1102,7 +1233,7 @@ number: if ((dprec = prec) >= 0)
496 flags & GROUPING, thousands_sep,
499 - if (ulval != 0 || prec != 0)
500 + if (ulval != 0 || prec != 0 || (flags & ALT))
501 cp = __ultoa(ulval, cp, base,
503 flags & GROUPING, thousands_sep,
504 @@ -1110,8 +1241,13 @@ number: if ((dprec = prec) >= 0)
506 size = buf + BUF - cp;
507 if (size > BUF) /* should never happen */
509 + LIBC_ABORT("size %d > BUF %d", size, BUF);
515 +#endif /* VECTORS */
516 default: /* "%?" prints ?, unless ? is NUL */
519 @@ -1123,6 +1259,290 @@ number: if ((dprec = prec) >= 0)
524 + if (flags & VECTOR) {
526 + * Do the minimum amount of work necessary to construct
527 + * a format specifier that can be used to recursively
528 + * call vfprintf() for each element in the vector.
530 + int i, j; /* Counter. */
531 + int vcnt; /* Number of elements in vector. */
532 + char *vfmt; /* Pointer to format specifier. */
534 + char vfmt_buf[32 + EXTRAHH]; /* Static buffer for format spec. */
535 + int vwidth = 0; /* Width specified via '*'. */
536 + int vprec = 0; /* Precision specified via '*'. */
537 + char *vstr; /* Used for asprintf(). */
538 + int vlen; /* Length returned by asprintf(). */
540 + V_CHAR, V_SHORT, V_INT,
541 + V_PCHAR, V_PSHORT, V_PINT,
544 + V_LONGLONG, V_PLONGLONG,
546 +#endif /* V64TYPE */
549 + vval.vectorarg = GETARG(VECTORTYPE);
551 + * Set vfmt. If vfmt_buf may not be big enough,
552 + * malloc() space, taking care to free it later.
553 + * (EXTRAHH is for possible extra "hh")
555 + if (&fmt[-1] - pct + EXTRAHH < sizeof(vfmt_buf))
558 + vfmt = (char *)malloc(&fmt[-1] - pct + EXTRAHH + 1);
560 + /* Set the separator character, if not specified. */
568 + /* Create the format specifier. */
569 + for (i = j = 0; i < &fmt[-1] - pct; i++) {
571 + case ',': case ';': case ':': case '_':
572 + case 'v': case 'h': case 'l':
576 + if (pct[i - 1] != '.')
582 + vfmt[j++] = pct[i];
587 + * Determine the number of elements in the vector and
588 + * finish up the format specifier.
590 + if (flags & SHORTINT) {
604 + } else if (flags & LONGINT) {
606 + vtype = (ch == 'p') ? V_PINT : V_INT;
608 + } else if (flags & LLONGINT) {
630 + vtype = (ch == 'p') ? V_PLONGLONG : V_LONGLONG;
634 + * The default case should never
641 +#endif /* V64TYPE */
656 + * The default case should never
671 + vtype = (ch == 'p') ? V_PCHAR : V_CHAR;
677 +/* Get a vector element. */
679 +#define VPRINT(type, ind, args...) do { \
682 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
685 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
688 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
691 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
694 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
697 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
700 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vulonglongarg[ind]); \
702 + case V_PLONGLONG: \
703 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vulonglongarg[ind]); \
706 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
709 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vdoublearg[ind]); \
713 + PRINT(vstr, vlen); \
717 +#else /* !V64TYPE */
718 +#define VPRINT(type, ind, args...) do { \
721 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuchararg[ind]); \
724 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuchararg[ind]); \
727 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vushortarg[ind]); \
730 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vushortarg[ind]); \
733 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vuintarg[ind]); \
736 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, (void *)(long)vval.vuintarg[ind]); \
739 + vlen = asprintf_l(&vstr, loc, vfmt , ## args, vval.vfloatarg[ind]); \
743 + PRINT(vstr, vlen); \
747 +#endif /* V64TYPE */
749 + /* Actually print. */
752 + /* First element. */
754 + for (i = 1; i < vcnt; i++) {
763 + /* First element. */
764 + VPRINT(vtype, 0, prec);
765 + for (i = 1; i < vcnt; i++) {
771 + VPRINT(vtype, i, prec);
776 + /* First element. */
777 + VPRINT(vtype, 0, width);
778 + for (i = 1; i < vcnt; i++) {
784 + VPRINT(vtype, i, width);
787 + /* First element. */
788 + VPRINT(vtype, 0, width, prec);
789 + for (i = 1; i < vcnt; i++) {
795 + VPRINT(vtype, i, width, prec);
801 + if (vfmt != vfmt_buf)
806 +#endif /* VECTORS */
808 * All reasonable formats wind up here. At this point, `cp'
809 * points to a string which (if not flags&LADJUST) should be
810 @@ -1178,7 +1598,7 @@ number: if ((dprec = prec) >= 0)
813 if (prec || flags & ALT)
814 - PRINT(decimal_point, 1);
815 + PRINT(decimal_point, strlen(decimal_point));
817 /* already handled initial 0's */
819 @@ -1203,14 +1623,14 @@ number: if ((dprec = prec) >= 0)
822 if (prec || flags & ALT)
823 - PRINT(decimal_point,1);
824 + PRINT(decimal_point, strlen(decimal_point));
826 PRINTANDPAD(cp, dtoaend, prec, zeroes);
827 } else { /* %[eE] or sufficiently long %[gG] */
828 if (prec > 1 || flags & ALT) {
830 - buf[1] = *decimal_point;
833 + PRINT(decimal_point, strlen(decimal_point));
835 PAD(prec - ndig, zeroes);
837 @@ -1406,6 +1826,11 @@ reswitch: switch (ch) {
842 + if (flags & VECTOR)
845 +#endif /* VECTORS */
849 @@ -1413,6 +1838,11 @@ reswitch: switch (ch) {
854 + if (flags & VECTOR)
860 #ifndef NO_FLOATING_POINT
861 @@ -1421,8 +1851,14 @@ reswitch: switch (ch) {
869 + if (flags & VECTOR)
872 +#endif /* VECTORS */
874 ADDTYPE(T_LONG_DOUBLE);
876 @@ -1451,9 +1887,19 @@ reswitch: switch (ch) {
881 + if (flags & VECTOR)
884 +#endif /* VECTORS */
889 + if (flags & VECTOR)
892 +#endif /* VECTORS */
896 @@ -1471,6 +1917,11 @@ reswitch: switch (ch) {
901 + if (flags & VECTOR)
904 +#endif /* VECTORS */
907 default: /* "%?" prints ?, unless ? is NUL */
908 @@ -1537,7 +1988,7 @@ done:
909 (*argtable) [n].sizearg = va_arg (ap, size_t);
912 - (*argtable) [n].psizearg = va_arg (ap, ssize_t *);
913 + (*argtable) [n].psizearg = va_arg (ap, size_t *);
916 (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
917 @@ -1556,6 +2007,11 @@ done:
918 (*argtable) [n].longdoublearg = va_arg (ap, long double);
923 + (*argtable) [n].vectorarg = va_arg (ap, VECTORTYPE);
925 +#endif /* VECTORS */
927 (*argtable) [n].pchararg = va_arg (ap, char *);
929 @@ -1590,12 +2046,12 @@ __grow_type_table (int nextarg, enum typ
930 newsize = nextarg + 1;
931 if (oldsize == STATIC_ARG_TBL_SIZE) {
932 if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
933 - abort(); /* XXX handle better */
934 + LIBC_ABORT("malloc: %s", strerror(errno)); /* XXX handle better */
935 bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
937 newtable = reallocf(oldtable, newsize * sizeof(enum typeid));
938 if (newtable == NULL)
939 - abort(); /* XXX handle better */
940 + LIBC_ABORT("reallocf: %s", strerror(errno)); /* XXX handle better */
942 for (n = oldsize; n < newsize; n++)
943 newtable[n] = T_UNUSED;