1 --- vfscanf.c.orig 2009-02-15 03:11:22.000000000 -0800
2 +++ vfscanf.c 2009-02-16 00:22:06.000000000 -0800
3 @@ -40,6 +40,8 @@ static char sccsid[] = "@(#)vfscanf.c 8.
5 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfscanf.c,v 1.37 2004/05/02 10:55:05 das Exp $");
7 +#include "xlocale_private.h"
12 @@ -50,6 +52,7 @@ __FBSDID("$FreeBSD: src/lib/libc/stdio/v
17 #include "un-namespace.h"
20 @@ -97,10 +100,21 @@ __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 int parsefloat(FILE *, char *, char *);
26 +static const u_char *__sccl(char *, const u_char *, locale_t);
27 +#ifndef NO_FLOATING_POINT
28 +static int parsefloat(FILE *, char **, size_t, locale_t);
29 +#endif /* !NO_FLOATING_POINT */
32 + * For ppc, we need to have the 64-bit long double version defining storage for
33 + * __scanfdebug, to be compatible with 10.3. For ppc64 and i386, we want the
34 + * storage defined in the only version.
36 +#if defined(__ppc__) && !defined(BUILDING_VARIANT)
37 +extern int __scanfdebug;
38 +#else /* !__ppc__ || BUILDING_VARIANT */
40 +#endif /* __ppc__ && !BUILDING_VARIANT */
42 __weak_reference(__vfscanf, vfscanf);
44 @@ -108,12 +122,24 @@ __weak_reference(__vfscanf, vfscanf);
45 * __vfscanf - MT-safe version
48 -__vfscanf(FILE *fp, char const *fmt0, va_list ap)
49 +__vfscanf(FILE * __restrict fp, char const * __restrict fmt0, va_list ap)
54 - ret = __svfscanf(fp, fmt0, ap);
55 + ret = __svfscanf_l(fp, __current_locale(), fmt0, ap);
61 +vfscanf_l(FILE * __restrict fp, locale_t loc, char const * __restrict fmt0, va_list ap)
65 + NORMALIZE_LOCALE(loc);
67 + ret = __svfscanf_l(fp, loc, fmt0, ap);
71 @@ -121,8 +147,8 @@ __vfscanf(FILE *fp, char const *fmt0, va
73 * __svfscanf - non-MT-safe version of __vfscanf
76 -__svfscanf(FILE *fp, const char *fmt0, va_list ap)
77 +__private_extern__ int
78 +__svfscanf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
80 const u_char *fmt = (const u_char *)fmt0;
81 int c; /* character from format, or conversion */
82 @@ -132,7 +158,6 @@ __svfscanf(FILE *fp, const char *fmt0, v
83 int flags; /* flags as defined above */
84 char *p0; /* saves original value of p when necessary */
85 int nassigned; /* number of fields assigned */
86 - int nconversions; /* number of conversions */
87 int nread; /* number of characters consumed from fp */
88 int base; /* base argument to conversion function */
89 char ccltab[256]; /* character class table for %[...] */
90 @@ -140,29 +165,37 @@ __svfscanf(FILE *fp, const char *fmt0, v
91 wchar_t *wcp; /* handy wide character pointer */
92 wchar_t *wcp0; /* saves original value of wcp */
93 size_t nconv; /* length of multibyte sequence converted */
94 + int index; /* %index$, zero if unset */
95 + va_list ap_orig; /* to reset ap to first argument */
96 static const mbstate_t initial;
100 /* `basefix' is used to avoid `if' tests in the integer scanner */
101 static short basefix[17] =
102 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
104 + NORMALIZE_LOCALE(loc);
105 + mb_cur_max = MB_CUR_MAX_L(loc);
111 + va_copy(ap_orig, ap);
117 - while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
118 + if (isspace_l(c, loc)) {
119 + while ((fp->_r > 0 || __srefill(fp) == 0) && isspace_l(*fp->_p, loc))
120 nread++, fp->_r--, fp->_p++;
125 + if (fp->_r <= 0 && __srefill(fp))
126 + goto input_failure;
132 @@ -172,15 +205,35 @@ __svfscanf(FILE *fp, const char *fmt0, v
136 + /* Consume leading white space */
138 + if (fp->_r <= 0 && __srefill(fp))
139 + goto input_failure;
140 + if (!isspace_l(*fp->_p, loc))
147 - if (fp->_r <= 0 && __srefill(fp))
148 - goto input_failure;
157 + if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
158 + goto input_failure;
162 + va_copy(ap, ap_orig); /* reset to %1$ */
163 + for (; index > 1; index--) {
170 @@ -267,7 +320,7 @@ literal:
174 - fmt = __sccl(ccltab, fmt);
175 + fmt = __sccl(ccltab, fmt, loc);
179 @@ -288,7 +341,6 @@ literal:
184 if (flags & SUPPRESS) /* ??? */
186 if (flags & SHORTSHORT)
187 @@ -330,7 +382,7 @@ literal:
188 * that suppress this.
190 if ((flags & NOSKIP) == 0) {
191 - while (isspace(*fp->_p)) {
192 + while (isspace_l(*fp->_p, loc)) {
196 @@ -360,7 +412,7 @@ literal:
200 - if (n == MB_CUR_MAX) {
201 + if (n == mb_cur_max) {
202 fp->_flags |= __SERR;
205 @@ -368,7 +420,7 @@ literal:
209 - nconv = mbrtowc(wcp, buf, n, &mbs);
210 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
211 if (nconv == (size_t)-1) {
212 fp->_flags |= __SERR;
214 @@ -421,7 +473,6 @@ literal:
222 @@ -440,7 +491,7 @@ literal:
226 - if (n == MB_CUR_MAX) {
227 + if (n == mb_cur_max) {
228 fp->_flags |= __SERR;
231 @@ -448,7 +499,7 @@ literal:
235 - nconv = mbrtowc(wcp, buf, n, &mbs);
236 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
237 if (nconv == (size_t)-1) {
238 fp->_flags |= __SERR;
240 @@ -456,8 +507,8 @@ literal:
243 if (nconv != (size_t)-2) {
244 - if (wctob(*wcp) != EOF &&
245 - !ccltab[wctob(*wcp)]) {
246 + if (wctob_l(*wcp, loc) != EOF &&
247 + !ccltab[wctob_l(*wcp, loc)]) {
251 @@ -525,7 +576,6 @@ literal:
259 @@ -540,8 +590,8 @@ literal:
263 - while (!isspace(*fp->_p) && width != 0) {
264 - if (n == MB_CUR_MAX) {
265 + while (width != 0) {
266 + if (n == mb_cur_max) {
267 fp->_flags |= __SERR;
270 @@ -549,7 +599,7 @@ literal:
274 - nconv = mbrtowc(wcp, buf, n, &mbs);
275 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
276 if (nconv == (size_t)-1) {
277 fp->_flags |= __SERR;
279 @@ -557,7 +607,7 @@ literal:
282 if (nconv != (size_t)-2) {
283 - if (iswspace(*wcp)) {
284 + if (iswspace_l(*wcp, loc)) {
288 @@ -585,7 +635,7 @@ literal:
290 } else if (flags & SUPPRESS) {
292 - while (!isspace(*fp->_p)) {
293 + while (!isspace_l(*fp->_p, loc)) {
294 n++, fp->_r--, fp->_p++;
297 @@ -595,7 +645,7 @@ literal:
300 p0 = p = va_arg(ap, char *);
301 - while (!isspace(*fp->_p)) {
302 + while (!isspace_l(*fp->_p, loc)) {
306 @@ -607,7 +657,6 @@ literal:
314 @@ -738,9 +787,9 @@ literal:
317 if ((flags & UNSIGNED) == 0)
318 - res = strtoimax(buf, (char **)NULL, base);
319 + res = strtoimax_l(buf, (char **)NULL, base, loc);
321 - res = strtoumax(buf, (char **)NULL, base);
322 + res = strtoumax_l(buf, (char **)NULL, base, loc);
324 *va_arg(ap, void **) =
325 (void *)(uintptr_t)res;
326 @@ -763,43 +812,48 @@ literal:
333 #ifndef NO_FLOATING_POINT
337 /* scan a floating point number as if by strtod */
338 - if (width == 0 || width > sizeof(buf) - 1)
339 - width = sizeof(buf) - 1;
340 - if ((width = parsefloat(fp, buf, buf + width)) == 0)
341 + if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
343 if ((flags & SUPPRESS) == 0) {
344 if (flags & LONGDBL) {
345 - long double res = strtold(buf, &p);
346 + long double res = strtold_l(pbuf, &p, loc);
347 *va_arg(ap, long double *) = res;
348 } else if (flags & LONG) {
349 - double res = strtod(buf, &p);
350 + double res = strtod_l(pbuf, &p, loc);
351 *va_arg(ap, double *) = res;
353 - float res = strtof(buf, &p);
354 + float res = strtof_l(pbuf, &p, loc);
355 *va_arg(ap, float *) = res;
357 - if (__scanfdebug && p - buf != width)
359 + if (__scanfdebug && p - pbuf != width)
360 + LIBC_ABORT("p - pbuf %ld != width %ld", (long)(p - pbuf), width);
367 #endif /* !NO_FLOATING_POINT */
371 - return (nconversions != 0 ? nassigned : EOF);
372 + return (nassigned ? nassigned : EOF);
378 +__svfscanf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
380 + return __svfscanf_l(fp, __current_locale(), fmt0, ap);
384 * Fill in the given table from the scanset at the given format
385 * (just after `['). Return a pointer to the character past the
386 @@ -807,9 +861,10 @@ match_failure:
387 * considered part of the scanset.
389 static const u_char *
391 +__sccl(tab, fmt, loc)
398 @@ -845,6 +900,7 @@ doswitch:
404 * A scanset of the form
406 @@ -865,8 +921,8 @@ doswitch:
410 - || (__collate_load_error ? n < c :
411 - __collate_range_cmp (n, c) < 0
412 + || (loc->__collate_load_error ? n < c :
413 + __collate_range_cmp (n, c, loc) < 0
417 @@ -874,14 +930,14 @@ doswitch:
420 /* fill in the range */
421 - if (__collate_load_error) {
422 + if (loc->__collate_load_error) {
427 for (i = 0; i < 256; i ++)
428 - if ( __collate_range_cmp (c, i) < 0
429 - && __collate_range_cmp (i, n) <= 0
430 + if ( __collate_range_cmp (c, i, loc) < 0
431 + && __collate_range_cmp (i, n, loc) <= 0
435 @@ -901,7 +957,7 @@ doswitch:
441 case ']': /* end of scanset */
444 @@ -914,19 +970,75 @@ doswitch:
447 #ifndef NO_FLOATING_POINT
449 + * Maintain a per-thread parsefloat buffer, shared by __svfscanf_l and
452 +#ifdef BUILDING_VARIANT
453 +extern char *__parsefloat_buf(size_t s);
454 +#else /* !BUILDING_VARIANT */
455 +__private_extern__ char *
456 +__parsefloat_buf(size_t s)
459 + static pthread_key_t parsefloat_tsd_key = (pthread_key_t)-1;
460 + static pthread_mutex_t parsefloat_tsd_lock = PTHREAD_MUTEX_INITIALIZER;
461 + static size_t bsiz = 0;
463 + if (parsefloat_tsd_key == (pthread_key_t)-1) {
464 + pthread_mutex_lock(&parsefloat_tsd_lock);
465 + if (parsefloat_tsd_key == (pthread_key_t)-1) {
466 + parsefloat_tsd_key = __LIBC_PTHREAD_KEY_PARSEFLOAT;
467 + pthread_key_init_np(parsefloat_tsd_key, free);
469 + pthread_mutex_unlock(&parsefloat_tsd_lock);
471 + if ((b = (char *)pthread_getspecific(parsefloat_tsd_key)) == NULL) {
472 + bsiz = s > BUF ? s : BUF;
473 + b = (char *)malloc(bsiz);
478 + pthread_setspecific(parsefloat_tsd_key, b);
482 + b = (char *)reallocf(b, s);
483 + pthread_setspecific(parsefloat_tsd_key, b);
492 +#endif /* BUILDING_VARIANT */
495 -parsefloat(FILE *fp, char *buf, char *end)
496 +parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
501 S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
502 - S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
503 + S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS, S_DECIMAL_POINT
506 - char decpt = *localeconv()->decimal_point;
507 + unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
509 _Bool gotmantdig = 0, ishex = 0;
515 + s = (width == 0 ? BUF : (width + 1));
516 + if ((b = __parsefloat_buf(s)) == NULL) {
522 * We set commit = p whenever the string we have read so far
523 * constitutes a valid representation of a floating point
524 @@ -936,8 +1048,8 @@ parsefloat(FILE *fp, char *buf, char *en
525 * always necessary to read at least one character that doesn't
526 * match; thus, we can't short-circuit "infinity" or "nan(...)".
529 - for (p = buf; p < end; ) {
531 + for (p = b; width == 0 || p < e; ) {
535 @@ -997,7 +1109,7 @@ reswitch:
539 - } else if (!isalnum(c) && c != '_')
540 + } else if (!isalnum_l(c, loc) && c != '_')
544 @@ -1013,16 +1125,33 @@ reswitch:
548 - if ((ishex && isxdigit(c)) || isdigit(c))
549 + if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
555 + state = S_DECIMAL_POINT;
562 + case S_DECIMAL_POINT:
571 + /* not decimal point */
573 + if (decpt_start == p)
575 + while (decpt_start < --p)
576 + __ungetc(*(u_char *)p, fp);
580 if (((c == 'E' || c == 'e') && !ishex) ||
581 ((c == 'P' || c == 'p') && ishex)) {
582 @@ -1030,7 +1159,7 @@ reswitch:
586 - } else if ((ishex && isxdigit(c)) || isdigit(c)) {
587 + } else if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
591 @@ -1043,13 +1172,26 @@ reswitch:
596 + if (isdigit_l(c, loc))
603 + LIBC_ABORT("unknown state %d", state);
606 + ssize_t diff = (p - b);
607 + ssize_t com = (commit - b);
609 + b = __parsefloat_buf(s);
620 @@ -1062,6 +1204,7 @@ parsedone:
622 __ungetc(*(u_char *)p, fp);
624 - return (commit - buf);
626 + return (commit - b);