1 --- vfscanf.c.orig 2010-07-15 10:03:36.000000000 -0700
2 +++ vfscanf.c 2010-07-15 10:18:58.000000000 -0700
3 @@ -36,6 +36,8 @@ static char sccsid[] = "@(#)vfscanf.c 8.
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.43 2009/01/19 06:19:51 das Exp $");
7 +#include "xlocale_private.h"
12 @@ -46,6 +48,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
17 #include "un-namespace.h"
20 @@ -93,9 +96,9 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
21 #define CT_INT 3 /* %[dioupxX] conversion */
22 #define CT_FLOAT 4 /* %[efgEFG] conversion */
24 -static const u_char *__sccl(char *, const u_char *);
25 +static const u_char *__sccl(char *, const u_char *, locale_t);
26 #ifndef NO_FLOATING_POINT
27 -static int parsefloat(FILE *, char *, char *);
28 +static int parsefloat(FILE *, char **, size_t, locale_t);
31 __weak_reference(__vfscanf, vfscanf);
32 @@ -104,12 +107,24 @@ __weak_reference(__vfscanf, vfscanf);
33 * __vfscanf - MT-safe version
36 -__vfscanf(FILE *fp, char const *fmt0, va_list ap)
37 +__vfscanf(FILE * __restrict fp, char const * __restrict fmt0, va_list ap)
42 - ret = __svfscanf(fp, fmt0, ap);
43 + ret = __svfscanf_l(fp, __current_locale(), fmt0, ap);
49 +vfscanf_l(FILE * __restrict fp, locale_t loc, char const * __restrict fmt0, va_list ap)
53 + NORMALIZE_LOCALE(loc);
55 + ret = __svfscanf_l(fp, loc, fmt0, ap);
59 @@ -117,8 +132,8 @@ __vfscanf(FILE *fp, char const *fmt0, va
61 * __svfscanf - non-MT-safe version of __vfscanf
64 -__svfscanf(FILE *fp, const char *fmt0, va_list ap)
65 +__private_extern__ int
66 +__svfscanf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
68 const u_char *fmt = (const u_char *)fmt0;
69 int c; /* character from format, or conversion */
70 @@ -128,36 +143,43 @@ __svfscanf(FILE *fp, const char *fmt0, v
71 int flags; /* flags as defined above */
72 char *p0; /* saves original value of p when necessary */
73 int nassigned; /* number of fields assigned */
74 - int nconversions; /* number of conversions */
75 int nread; /* number of characters consumed from fp */
76 int base; /* base argument to conversion function */
77 char ccltab[256]; /* character class table for %[...] */
78 char buf[BUF]; /* buffer for numeric and mb conversions */
79 wchar_t *wcp; /* handy wide character pointer */
80 size_t nconv; /* length of multibyte sequence converted */
81 + int index; /* %index$, zero if unset */
82 + va_list ap_orig; /* to reset ap to first argument */
83 static const mbstate_t initial;
87 /* `basefix' is used to avoid `if' tests in the integer scanner */
88 static short basefix[17] =
89 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
91 + NORMALIZE_LOCALE(loc);
92 + mb_cur_max = MB_CUR_MAX_L(loc);
98 + va_copy(ap_orig, ap);
104 - while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
105 + if (isspace_l(c, loc)) {
106 + while ((fp->_r > 0 || __srefill(fp) == 0) && isspace_l(*fp->_p, loc))
107 nread++, fp->_r--, fp->_p++;
112 + if (fp->_r <= 0 && __srefill(fp))
113 + goto input_failure;
119 @@ -167,15 +189,35 @@ __svfscanf(FILE *fp, const char *fmt0, v
123 + /* Consume leading white space */
125 + if (fp->_r <= 0 && __srefill(fp))
126 + goto input_failure;
127 + if (!isspace_l(*fp->_p, loc))
134 - if (fp->_r <= 0 && __srefill(fp))
135 - goto input_failure;
144 + if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
145 + goto input_failure;
149 + va_copy(ap, ap_orig); /* reset to %1$ */
150 + for (; index > 1; index--) {
157 @@ -262,7 +304,7 @@ literal:
161 - fmt = __sccl(ccltab, fmt);
162 + fmt = __sccl(ccltab, fmt, loc);
166 @@ -283,27 +325,28 @@ literal:
171 - if (flags & SUPPRESS) /* ??? */
173 + void *ptr = va_arg(ap, void *);
174 + if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
176 - if (flags & SHORTSHORT)
177 - *va_arg(ap, char *) = nread;
178 + else if (flags & SHORTSHORT)
179 + *(char *)ptr = nread;
180 else if (flags & SHORT)
181 - *va_arg(ap, short *) = nread;
182 + *(short *)ptr = nread;
183 else if (flags & LONG)
184 - *va_arg(ap, long *) = nread;
185 + *(long *)ptr = nread;
186 else if (flags & LONGLONG)
187 - *va_arg(ap, long long *) = nread;
188 + *(long long *)ptr = nread;
189 else if (flags & INTMAXT)
190 - *va_arg(ap, intmax_t *) = nread;
191 + *(intmax_t *)ptr = nread;
192 else if (flags & SIZET)
193 - *va_arg(ap, size_t *) = nread;
194 + *(size_t *)ptr = nread;
195 else if (flags & PTRDIFFT)
196 - *va_arg(ap, ptrdiff_t *) = nread;
197 + *(ptrdiff_t *)ptr = nread;
199 - *va_arg(ap, int *) = nread;
200 + *(int *)ptr = nread;
207 @@ -325,7 +368,7 @@ literal:
208 * that suppress this.
210 if ((flags & NOSKIP) == 0) {
211 - while (isspace(*fp->_p)) {
212 + while (isspace_l(*fp->_p, loc)) {
216 @@ -355,7 +398,7 @@ literal:
220 - if (n == MB_CUR_MAX) {
221 + if (n == mb_cur_max) {
222 fp->_flags |= __SERR;
225 @@ -363,7 +406,7 @@ literal:
229 - nconv = mbrtowc(wcp, buf, n, &mbs);
230 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
231 if (nconv == (size_t)-1) {
232 fp->_flags |= __SERR;
234 @@ -416,7 +459,6 @@ literal:
242 @@ -435,7 +477,7 @@ literal:
246 - if (n == MB_CUR_MAX) {
247 + if (n == mb_cur_max) {
248 fp->_flags |= __SERR;
251 @@ -443,7 +485,7 @@ literal:
255 - nconv = mbrtowc(wcp, buf, n, &mbs);
256 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
257 if (nconv == (size_t)-1) {
258 fp->_flags |= __SERR;
260 @@ -451,8 +493,8 @@ literal:
263 if (nconv != (size_t)-2) {
264 - if (wctob(*wcp) != EOF &&
265 - !ccltab[wctob(*wcp)]) {
266 + if (wctob_l(*wcp, loc) != EOF &&
267 + !ccltab[wctob_l(*wcp, loc)]) {
271 @@ -520,7 +562,6 @@ literal:
279 @@ -535,8 +576,8 @@ literal:
283 - while (!isspace(*fp->_p) && width != 0) {
284 - if (n == MB_CUR_MAX) {
285 + while (width != 0) {
286 + if (n == mb_cur_max) {
287 fp->_flags |= __SERR;
290 @@ -544,7 +585,7 @@ literal:
294 - nconv = mbrtowc(wcp, buf, n, &mbs);
295 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
296 if (nconv == (size_t)-1) {
297 fp->_flags |= __SERR;
299 @@ -552,7 +593,7 @@ literal:
302 if (nconv != (size_t)-2) {
303 - if (iswspace(*wcp)) {
304 + if (iswspace_l(*wcp, loc)) {
308 @@ -580,7 +621,7 @@ literal:
310 } else if (flags & SUPPRESS) {
312 - while (!isspace(*fp->_p)) {
313 + while (!isspace_l(*fp->_p, loc)) {
314 n++, fp->_r--, fp->_p++;
317 @@ -590,7 +631,7 @@ literal:
320 p0 = p = va_arg(ap, char *);
321 - while (!isspace(*fp->_p)) {
322 + while (!isspace_l(*fp->_p, loc)) {
326 @@ -602,7 +643,6 @@ literal:
334 @@ -733,9 +773,9 @@ literal:
337 if ((flags & UNSIGNED) == 0)
338 - res = strtoimax(buf, (char **)NULL, base);
339 + res = strtoimax_l(buf, (char **)NULL, base, loc);
341 - res = strtoumax(buf, (char **)NULL, base);
342 + res = strtoumax_l(buf, (char **)NULL, base, loc);
344 *va_arg(ap, void **) =
345 (void *)(uintptr_t)res;
346 @@ -758,41 +798,46 @@ literal:
353 #ifndef NO_FLOATING_POINT
357 /* scan a floating point number as if by strtod */
358 - if (width == 0 || width > sizeof(buf) - 1)
359 - width = sizeof(buf) - 1;
360 - if ((width = parsefloat(fp, buf, buf + width)) == 0)
361 + if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
363 if ((flags & SUPPRESS) == 0) {
364 if (flags & LONGDBL) {
365 - long double res = strtold(buf, &p);
366 + long double res = strtold_l(pbuf, &p, loc);
367 *va_arg(ap, long double *) = res;
368 } else if (flags & LONG) {
369 - double res = strtod(buf, &p);
370 + double res = strtod_l(pbuf, &p, loc);
371 *va_arg(ap, double *) = res;
373 - float res = strtof(buf, &p);
374 + float res = strtof_l(pbuf, &p, loc);
375 *va_arg(ap, float *) = res;
383 #endif /* !NO_FLOATING_POINT */
387 - return (nconversions != 0 ? nassigned : EOF);
388 + return (nassigned ? nassigned : EOF);
394 +__svfscanf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
396 + return __svfscanf_l(fp, __current_locale(), fmt0, ap);
400 * Fill in the given table from the scanset at the given format
401 * (just after `['). Return a pointer to the character past the
402 @@ -800,9 +845,10 @@ match_failure:
403 * considered part of the scanset.
405 static const u_char *
407 +__sccl(tab, fmt, loc)
414 @@ -838,6 +884,7 @@ doswitch:
420 * A scanset of the form
422 @@ -858,8 +905,8 @@ doswitch:
426 - || (__collate_load_error ? n < c :
427 - __collate_range_cmp (n, c) < 0
428 + || (loc->__collate_load_error ? n < c :
429 + __collate_range_cmp (n, c, loc) < 0
433 @@ -867,14 +914,14 @@ doswitch:
436 /* fill in the range */
437 - if (__collate_load_error) {
438 + if (loc->__collate_load_error) {
443 for (i = 0; i < 256; i ++)
444 - if ( __collate_range_cmp (c, i) < 0
445 - && __collate_range_cmp (i, n) <= 0
446 + if ( __collate_range_cmp (c, i, loc) < 0
447 + && __collate_range_cmp (i, n, loc) <= 0
451 @@ -894,7 +941,7 @@ doswitch:
457 case ']': /* end of scanset */
460 @@ -907,8 +954,54 @@ doswitch:
463 #ifndef NO_FLOATING_POINT
465 + * Maintain a per-thread parsefloat buffer, shared by __svfscanf_l and
468 +#ifdef BUILDING_VARIANT
469 +extern char *__parsefloat_buf(size_t s);
470 +#else /* !BUILDING_VARIANT */
471 +__private_extern__ char *
472 +__parsefloat_buf(size_t s)
475 + static pthread_key_t parsefloat_tsd_key = (pthread_key_t)-1;
476 + static pthread_mutex_t parsefloat_tsd_lock = PTHREAD_MUTEX_INITIALIZER;
477 + static size_t bsiz = 0;
479 + if (parsefloat_tsd_key == (pthread_key_t)-1) {
480 + pthread_mutex_lock(&parsefloat_tsd_lock);
481 + if (parsefloat_tsd_key == (pthread_key_t)-1) {
482 + parsefloat_tsd_key = __LIBC_PTHREAD_KEY_PARSEFLOAT;
483 + pthread_key_init_np(parsefloat_tsd_key, free);
485 + pthread_mutex_unlock(&parsefloat_tsd_lock);
487 + if ((b = (char *)pthread_getspecific(parsefloat_tsd_key)) == NULL) {
488 + bsiz = s > BUF ? s : BUF;
489 + b = (char *)malloc(bsiz);
494 + pthread_setspecific(parsefloat_tsd_key, b);
498 + b = (char *)reallocf(b, s);
499 + pthread_setspecific(parsefloat_tsd_key, b);
508 +#endif /* BUILDING_VARIANT */
511 -parsefloat(FILE *fp, char *buf, char *end)
512 +parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
515 int infnanpos = 0, decptpos = 0;
516 @@ -917,9 +1010,18 @@ parsefloat(FILE *fp, char *buf, char *en
517 S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
520 - const char *decpt = localeconv()->decimal_point;
521 + const char *decpt = localeconv_l(loc)->decimal_point;
522 _Bool gotmantdig = 0, ishex = 0;
528 + s = (width == 0 ? BUF : (width + 1));
529 + if ((b = __parsefloat_buf(s)) == NULL) {
535 * We set commit = p whenever the string we have read so far
536 * constitutes a valid representation of a floating point
537 @@ -929,8 +1031,8 @@ parsefloat(FILE *fp, char *buf, char *en
538 * always necessary to read at least one character that doesn't
539 * match; thus, we can't short-circuit "infinity" or "nan(...)".
542 - for (p = buf; p < end; ) {
544 + for (p = b; width == 0 || p < e; ) {
548 @@ -988,7 +1090,7 @@ reswitch:
552 - } else if (!isalnum(c) && c != '_')
553 + } else if (!isalnum_l(c, loc) && c != '_')
557 @@ -1006,7 +1108,7 @@ reswitch:
561 - if ((ishex && isxdigit(c)) || isdigit(c)) {
562 + if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
566 @@ -1041,7 +1143,7 @@ reswitch:
570 - } else if ((ishex && isxdigit(c)) || isdigit(c)) {
571 + } else if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
575 @@ -1054,13 +1156,26 @@ reswitch:
580 + if (isdigit_l(c, loc))
587 + LIBC_ABORT("unknown state %d", state);
590 + ssize_t diff = (p - b);
591 + ssize_t com = (commit - b);
593 + b = __parsefloat_buf(s);
604 @@ -1073,6 +1188,7 @@ parsedone:
606 __ungetc(*(u_char *)p, fp);
608 - return (commit - buf);
610 + return (commit - b);