1 --- vfscanf.c.orig 2004-11-25 11:38:35.000000000 -0800
2 +++ vfscanf.c 2005-05-20 00:46:37.000000000 -0700
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"
13 #define CT_INT 3 /* %[dioupxX] conversion */
14 #define CT_FLOAT 4 /* %[efgEFG] conversion */
16 -static const u_char *__sccl(char *, const u_char *);
17 -static int parsefloat(FILE *, char *, char *);
18 +static const u_char *__sccl(char *, const u_char *, locale_t);
19 +#ifndef NO_FLOATING_POINT
20 +static int parsefloat(FILE *, char **, size_t, locale_t);
21 +#endif /* !NO_FLOATING_POINT */
24 + * For ppc, we need to have the 64-bit long double version defining storage for
25 + * __scanfdebug, to be compatible with 10.3. For ppc64 and i386, we want the
26 + * storage defined in the only version.
28 +#if defined(__ppc__) && !defined(BUILDING_VARIANT)
29 +extern int __scanfdebug;
30 +#else /* !__ppc__ || BUILDING_VARIANT */
32 +#endif /* __ppc__ && !BUILDING_VARIANT */
34 __weak_reference(__vfscanf, vfscanf);
37 * __vfscanf - MT-safe version
40 -__vfscanf(FILE *fp, char const *fmt0, va_list ap)
41 +__vfscanf(FILE * __restrict fp, char const * __restrict fmt0, va_list ap)
46 + ret = __svfscanf_l(fp, __current_locale(), fmt0, ap);
52 +vfscanf_l(FILE * __restrict fp, locale_t loc, char const * __restrict fmt0, va_list ap)
56 + NORMALIZE_LOCALE(loc);
58 - ret = __svfscanf(fp, fmt0, ap);
59 + ret = __svfscanf_l(fp, loc, fmt0, ap);
65 * __svfscanf - non-MT-safe version of __vfscanf
68 -__svfscanf(FILE *fp, const char *fmt0, va_list ap)
69 +__private_extern__ int
70 +__svfscanf_l(FILE * __restrict fp, locale_t loc, const char * __restrict fmt0, va_list ap)
72 const u_char *fmt = (const u_char *)fmt0;
73 int c; /* character from format, or conversion */
75 int flags; /* flags as defined above */
76 char *p0; /* saves original value of p when necessary */
77 int nassigned; /* number of fields assigned */
78 - int nconversions; /* number of conversions */
79 int nread; /* number of characters consumed from fp */
80 int base; /* base argument to conversion function */
81 char ccltab[256]; /* character class table for %[...] */
83 wchar_t *wcp; /* handy wide character pointer */
84 wchar_t *wcp0; /* saves original value of wcp */
85 size_t nconv; /* length of multibyte sequence converted */
86 + int index; /* %index$, zero if unset */
87 + va_list ap_orig; /* to reset ap to first argument */
88 static const mbstate_t initial;
92 /* `basefix' is used to avoid `if' tests in the integer scanner */
93 static short basefix[17] =
94 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
96 + NORMALIZE_LOCALE(loc);
97 + mb_cur_max = MB_CUR_MAX_L(loc);
103 + va_copy(ap_orig, ap);
109 - while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
110 + if (isspace_l(c, loc)) {
111 + while ((fp->_r > 0 || __srefill(fp) == 0) && isspace_l(*fp->_p, loc))
112 nread++, fp->_r--, fp->_p++;
121 + if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
122 + goto input_failure;
126 + va_copy(ap, ap_orig); /* reset to %1$ */
127 + for (; index > 1; index--) {
138 - fmt = __sccl(ccltab, fmt);
139 + fmt = __sccl(ccltab, fmt, loc);
148 if (flags & SUPPRESS) /* ??? */
150 if (flags & SHORTSHORT)
152 * that suppress this.
154 if ((flags & NOSKIP) == 0) {
155 - while (isspace(*fp->_p)) {
156 + while (isspace_l(*fp->_p, loc)) {
164 - if (n == MB_CUR_MAX) {
165 + if (n == mb_cur_max) {
166 fp->_flags |= __SERR;
173 - nconv = mbrtowc(wcp, buf, n, &mbs);
174 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
175 if (nconv == (size_t)-1) {
176 fp->_flags |= __SERR;
190 - if (n == MB_CUR_MAX) {
191 + if (n == mb_cur_max) {
192 fp->_flags |= __SERR;
199 - nconv = mbrtowc(wcp, buf, n, &mbs);
200 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
201 if (nconv == (size_t)-1) {
202 fp->_flags |= __SERR;
207 if (nconv != (size_t)-2) {
208 - if (wctob(*wcp) != EOF &&
209 - !ccltab[wctob(*wcp)]) {
210 + if (wctob_l(*wcp, loc) != EOF &&
211 + !ccltab[wctob_l(*wcp, loc)]) {
227 - while (!isspace(*fp->_p) && width != 0) {
228 - if (n == MB_CUR_MAX) {
229 + while (width != 0) {
230 + if (n == mb_cur_max) {
231 fp->_flags |= __SERR;
238 - nconv = mbrtowc(wcp, buf, n, &mbs);
239 + nconv = mbrtowc_l(wcp, buf, n, &mbs, loc);
240 if (nconv == (size_t)-1) {
241 fp->_flags |= __SERR;
246 if (nconv != (size_t)-2) {
247 - if (iswspace(*wcp)) {
248 + if (iswspace_l(*wcp, loc)) {
254 } else if (flags & SUPPRESS) {
256 - while (!isspace(*fp->_p)) {
257 + while (!isspace_l(*fp->_p, loc)) {
258 n++, fp->_r--, fp->_p++;
264 p0 = p = va_arg(ap, char *);
265 - while (!isspace(*fp->_p)) {
266 + while (!isspace_l(*fp->_p, loc)) {
281 if ((flags & UNSIGNED) == 0)
282 - res = strtoimax(buf, (char **)NULL, base);
283 + res = strtoimax_l(buf, (char **)NULL, base, loc);
285 - res = strtoumax(buf, (char **)NULL, base);
286 + res = strtoumax_l(buf, (char **)NULL, base, loc);
288 *va_arg(ap, void **) =
289 (void *)(uintptr_t)res;
290 @@ -763,43 +800,48 @@
297 #ifndef NO_FLOATING_POINT
301 /* scan a floating point number as if by strtod */
302 - if (width == 0 || width > sizeof(buf) - 1)
303 - width = sizeof(buf) - 1;
304 - if ((width = parsefloat(fp, buf, buf + width)) == 0)
305 + if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
307 if ((flags & SUPPRESS) == 0) {
308 if (flags & LONGDBL) {
309 - long double res = strtold(buf, &p);
310 + long double res = strtold_l(pbuf, &p, loc);
311 *va_arg(ap, long double *) = res;
312 } else if (flags & LONG) {
313 - double res = strtod(buf, &p);
314 + double res = strtod_l(pbuf, &p, loc);
315 *va_arg(ap, double *) = res;
317 - float res = strtof(buf, &p);
318 + float res = strtof_l(pbuf, &p, loc);
319 *va_arg(ap, float *) = res;
321 - if (__scanfdebug && p - buf != width)
322 + if (__scanfdebug && p - pbuf != width)
330 #endif /* !NO_FLOATING_POINT */
334 - return (nconversions != 0 ? nassigned : EOF);
335 + return (nassigned ? nassigned : EOF);
341 +__svfscanf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
343 + return __svfscanf_l(fp, __current_locale(), fmt0, ap);
347 * Fill in the given table from the scanset at the given format
348 * (just after `['). Return a pointer to the character past the
350 * considered part of the scanset.
352 static const u_char *
354 +__sccl(tab, fmt, loc)
367 * A scanset of the form
373 - || (__collate_load_error ? n < c :
374 - __collate_range_cmp (n, c) < 0
375 + || (loc->__collate_load_error ? n < c :
376 + __collate_range_cmp (n, c, loc) < 0
380 @@ -874,14 +918,14 @@
383 /* fill in the range */
384 - if (__collate_load_error) {
385 + if (loc->__collate_load_error) {
390 for (i = 0; i < 256; i ++)
391 - if ( __collate_range_cmp (c, i) < 0
392 - && __collate_range_cmp (i, n) <= 0
393 + if ( __collate_range_cmp (c, i, loc) < 0
394 + && __collate_range_cmp (i, n, loc) <= 0
404 case ']': /* end of scanset */
407 @@ -915,18 +959,42 @@
409 #ifndef NO_FLOATING_POINT
411 -parsefloat(FILE *fp, char *buf, char *end)
412 +parsefloat(FILE *fp, char **buf, size_t width, locale_t loc)
417 S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX,
418 - S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
419 + S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS, S_DECIMAL_POINT
422 - char decpt = *localeconv()->decimal_point;
423 + unsigned char *decpt = (unsigned char *)localeconv_l(loc)->decimal_point;
425 _Bool gotmantdig = 0, ishex = 0;
427 + static char *b = NULL;
428 + static size_t bsiz = 0;
433 + b = (char *)malloc(BUF);
440 + s = (width == 0 ? BUF : (width + 1));
442 + b = (char *)reallocf(b, s);
452 * We set commit = p whenever the string we have read so far
453 * constitutes a valid representation of a floating point
455 * always necessary to read at least one character that doesn't
456 * match; thus, we can't short-circuit "infinity" or "nan(...)".
459 - for (p = buf; p < end; ) {
461 + for (p = b; width == 0 || p < e; ) {
469 - } else if (!isalnum(c) && c != '_')
470 + } else if (!isalnum_l(c, loc) && c != '_')
474 @@ -1013,16 +1081,33 @@
478 - if ((ishex && isxdigit(c)) || isdigit(c))
479 + if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc))
485 + state = S_DECIMAL_POINT;
492 + case S_DECIMAL_POINT:
501 + /* not decimal point */
503 + if (decpt_start == p)
505 + while (decpt_start < --p)
506 + __ungetc(*(u_char *)p, fp);
510 if (((c == 'E' || c == 'e') && !ishex) ||
511 ((c == 'P' || c == 'p') && ishex)) {
512 @@ -1030,7 +1115,7 @@
516 - } else if ((ishex && isxdigit(c)) || isdigit(c)) {
517 + } else if ((ishex && isxdigit_l(c, loc)) || isdigit_l(c, loc)) {
521 @@ -1043,7 +1128,7 @@
526 + if (isdigit_l(c, loc))
530 @@ -1051,6 +1136,21 @@
535 + ssize_t diff = (p - b);
536 + ssize_t com = (commit - b);
538 + b = (char *)reallocf(b, s);
552 @@ -1062,6 +1162,7 @@
554 __ungetc(*(u_char *)p, fp);
556 - return (commit - buf);
558 + return (commit - b);