2 ===================================================================
3 --- vfwscanf.c (revision 55443)
4 +++ vfwscanf.c (working copy)
7 __FBSDID("$FreeBSD: src/lib/libc/stdio/vfwscanf.c,v 1.17 2009/01/19 06:19:51 das Exp $");
9 +#include "xlocale_private.h"
11 #include "namespace.h"
15 #define CT_FLOAT 4 /* %[efgEFG] conversion */
17 #ifndef NO_FLOATING_POINT
18 -static int parsefloat(FILE *, wchar_t *, wchar_t *);
19 +static int parsefloat(FILE *, wchar_t **, size_t, locale_t loc);
27 - ret = __vfwscanf(fp, fmt, ap);
28 + ret = __vfwscanf(fp, __current_locale(), fmt, ap);
34 +vfwscanf_l(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt,
39 + NORMALIZE_LOCALE(loc);
42 + ret = __vfwscanf(fp, loc, fmt, ap);
48 * Non-MT-safe version.
51 -__vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap)
52 +__private_extern__ int
53 +__vfwscanf(FILE * __restrict fp, locale_t loc, const wchar_t * __restrict fmt,
56 wint_t c; /* character from format, or conversion */
57 size_t width; /* field width, or 0 */
59 int flags; /* flags as defined above */
60 wchar_t *p0; /* saves original value of p when necessary */
61 int nassigned; /* number of fields assigned */
62 - int nconversions; /* number of conversions */
63 int nread; /* number of characters consumed from fp */
64 int base; /* base argument to conversion function */
65 wchar_t buf[BUF]; /* buffer for numeric conversions */
67 char *mbp; /* multibyte string pointer for %c %s %[ */
68 size_t nconv; /* number of bytes in mb. conversion */
69 char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */
70 + int index; /* for %index$ */
71 + va_list ap_orig; /* to reset ap to first argument */
73 + int mb_cur_max = MB_CUR_MAX_L(loc);
75 /* `basefix' is used to avoid `if' tests in the integer scanner */
76 static short basefix[17] =
77 { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
83 + va_copy(ap_orig, ap);
89 - while ((c = __fgetwc(fp)) != WEOF &&
91 + if (iswspace_l(c, loc)) {
92 + while ((c = __fgetwc(fp, loc)) != WEOF &&
97 + __ungetwc(c, fp, loc);
102 + if ((wi = __fgetwc(fp, loc)) == WEOF)
103 + goto input_failure;
109 @@ -177,16 +199,34 @@
113 + /* Consume leading white space */
115 + if ((wi = __fgetwc(fp, loc)) == WEOF)
116 + goto input_failure;
117 + if (!iswspace_l(wi, loc))
122 - if ((wi = __fgetwc(fp)) == WEOF)
123 - goto input_failure;
126 - goto input_failure;
127 + __ungetwc(wi, fp, loc);
128 + goto match_failure;
135 + if (index < 1 || index > NL_ARGMAX || fmt[-3] != '%') {
136 + goto input_failure;
140 + va_copy(ap, ap_orig); /* reset to %1$ */
141 + for (; index > 1; index--) {
148 @@ -305,27 +345,28 @@
153 - if (flags & SUPPRESS) /* ??? */
155 + void *ptr = va_arg(ap, void *);
156 + if ((ptr == NULL) || (flags & SUPPRESS)) /* ??? */
158 - if (flags & SHORTSHORT)
159 - *va_arg(ap, char *) = nread;
160 + else if (flags & SHORTSHORT)
161 + *(char *)ptr = nread;
162 else if (flags & SHORT)
163 - *va_arg(ap, short *) = nread;
164 + *(short *)ptr = nread;
165 else if (flags & LONG)
166 - *va_arg(ap, long *) = nread;
167 + *(long *)ptr = nread;
168 else if (flags & LONGLONG)
169 - *va_arg(ap, long long *) = nread;
170 + *(long long *)ptr = nread;
171 else if (flags & INTMAXT)
172 - *va_arg(ap, intmax_t *) = nread;
173 + *(intmax_t *)ptr = nread;
174 else if (flags & SIZET)
175 - *va_arg(ap, size_t *) = nread;
176 + *(size_t *)ptr = nread;
177 else if (flags & PTRDIFFT)
178 - *va_arg(ap, ptrdiff_t *) = nread;
179 + *(ptrdiff_t *)ptr = nread;
181 - *va_arg(ap, int *) = nread;
182 + *(int *)ptr = nread;
189 @@ -341,11 +382,11 @@
190 * that suppress this.
192 if ((flags & NOSKIP) == 0) {
193 - while ((wi = __fgetwc(fp)) != WEOF && iswspace(wi))
194 + while ((wi = __fgetwc(fp, loc)) != WEOF && iswspace_l(wi, loc))
199 + __ungetwc(wi, fp, loc);
204 p = va_arg(ap, wchar_t *);
206 while (width-- != 0 &&
207 - (wi = __fgetwc(fp)) != WEOF) {
208 + (wi = __fgetwc(fp, loc)) != WEOF) {
209 if (!(flags & SUPPRESS))
212 @@ -378,19 +419,19 @@
216 - (wi = __fgetwc(fp)) != WEOF) {
217 - if (width >= MB_CUR_MAX &&
218 + (wi = __fgetwc(fp, loc)) != WEOF) {
219 + if (width >= mb_cur_max &&
220 !(flags & SUPPRESS)) {
221 - nconv = wcrtomb(mbp, wi, &mbs);
222 + nconv = wcrtomb_l(mbp, wi, &mbs, loc);
223 if (nconv == (size_t)-1)
226 - nconv = wcrtomb(mbbuf, wi,
228 + nconv = wcrtomb_l(mbbuf, wi,
230 if (nconv == (size_t)-1)
234 + __ungetwc(wi, fp, loc);
237 if (!(flags & SUPPRESS))
239 if (!(flags & SUPPRESS))
246 @@ -418,20 +458,20 @@
247 /* take only those things in the class */
248 if ((flags & SUPPRESS) && (flags & LONG)) {
250 - while ((wi = __fgetwc(fp)) != WEOF &&
251 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
252 width-- != 0 && INCCL(wi))
256 + __ungetwc(wi, fp, loc);
259 } else if (flags & LONG) {
260 p0 = p = va_arg(ap, wchar_t *);
261 - while ((wi = __fgetwc(fp)) != WEOF &&
262 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
263 width-- != 0 && INCCL(wi))
267 + __ungetwc(wi, fp, loc);
271 @@ -442,16 +482,16 @@
272 mbp = va_arg(ap, char *);
275 - while ((wi = __fgetwc(fp)) != WEOF &&
276 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
277 width != 0 && INCCL(wi)) {
278 - if (width >= MB_CUR_MAX &&
279 + if (width >= mb_cur_max &&
280 !(flags & SUPPRESS)) {
281 - nconv = wcrtomb(mbp, wi, &mbs);
282 + nconv = wcrtomb_l(mbp, wi, &mbs, loc);
283 if (nconv == (size_t)-1)
286 - nconv = wcrtomb(mbbuf, wi,
288 + nconv = wcrtomb_l(mbbuf, wi,
290 if (nconv == (size_t)-1)
293 @@ -466,14 +506,15 @@
298 + __ungetwc(wi, fp, loc);
300 + goto match_failure;
301 if (!(flags & SUPPRESS)) {
311 @@ -481,39 +522,39 @@
314 if ((flags & SUPPRESS) && (flags & LONG)) {
315 - while ((wi = __fgetwc(fp)) != WEOF &&
316 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
319 + !iswspace_l(wi, loc))
323 + __ungetwc(wi, fp, loc);
324 } else if (flags & LONG) {
325 p0 = p = va_arg(ap, wchar_t *);
326 - while ((wi = __fgetwc(fp)) != WEOF &&
327 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
330 + !iswspace_l(wi, loc)) {
336 + __ungetwc(wi, fp, loc);
340 if (!(flags & SUPPRESS))
341 mbp = va_arg(ap, char *);
343 - while ((wi = __fgetwc(fp)) != WEOF &&
344 + while ((wi = __fgetwc(fp, loc)) != WEOF &&
347 - if (width >= MB_CUR_MAX &&
348 + !iswspace_l(wi, loc)) {
349 + if (width >= mb_cur_max &&
350 !(flags & SUPPRESS)) {
351 - nconv = wcrtomb(mbp, wi, &mbs);
352 + nconv = wcrtomb_l(mbp, wi, &mbs, loc);
353 if (nconv == (size_t)-1)
356 - nconv = wcrtomb(mbbuf, wi,
358 + nconv = wcrtomb_l(mbbuf, wi,
360 if (nconv == (size_t)-1)
363 @@ -528,13 +569,12 @@
368 + __ungetwc(wi, fp, loc);
369 if (!(flags & SUPPRESS)) {
379 width = sizeof(buf) / sizeof(*buf) - 1;
380 flags |= SIGNOK | NDIGITS | NZDIGITS;
381 for (p = buf; width; width--) {
383 + c = __fgetwc(fp, loc);
385 * Switch on the character; `goto ok'
386 * if we accept it as a part of number.
388 * for a number. Stop accumulating digits.
392 + __ungetwc(c, fp, loc);
396 @@ -644,22 +684,22 @@
398 if (flags & NDIGITS) {
400 - __ungetwc(*--p, fp);
401 + __ungetwc(*--p, fp, loc);
405 if (c == 'x' || c == 'X') {
408 + __ungetwc(c, fp, loc);
410 if ((flags & SUPPRESS) == 0) {
414 if ((flags & UNSIGNED) == 0)
415 - res = wcstoimax(buf, NULL, base);
416 + res = wcstoimax_l(buf, NULL, base, loc);
418 - res = wcstoumax(buf, NULL, base);
419 + res = wcstoumax_l(buf, NULL, base, loc);
421 *va_arg(ap, void **) =
422 (void *)(uintptr_t)res;
423 @@ -682,45 +722,45 @@
430 #ifndef NO_FLOATING_POINT
434 /* scan a floating point number as if by strtod */
435 - if (width == 0 || width > sizeof(buf) /
437 - width = sizeof(buf) / sizeof(*buf) - 1;
438 - if ((width = parsefloat(fp, buf, buf + width)) == 0)
439 + if ((width = parsefloat(fp, &pbuf, width, loc)) == 0)
441 if ((flags & SUPPRESS) == 0) {
442 if (flags & LONGDBL) {
443 - long double res = wcstold(buf, &p);
444 + long double res = wcstold_l(pbuf, &p, loc);
445 *va_arg(ap, long double *) = res;
446 } else if (flags & LONG) {
447 - double res = wcstod(buf, &p);
448 + double res = wcstod_l(pbuf, &p, loc);
449 *va_arg(ap, double *) = res;
451 - float res = wcstof(buf, &p);
452 + float res = wcstof_l(pbuf, &p, loc);
453 *va_arg(ap, float *) = res;
461 #endif /* !NO_FLOATING_POINT */
465 - return (nconversions != 0 ? nassigned : EOF);
466 + return (nassigned ? nassigned : EOF);
471 #ifndef NO_FLOATING_POINT
472 +extern char *__parsefloat_buf(size_t s); /* see vfscanf-fbsd.c */
475 -parsefloat(FILE *fp, wchar_t *buf, wchar_t *end)
476 +parsefloat(FILE *fp, wchar_t **buf, size_t width, locale_t loc)
480 @@ -733,12 +773,22 @@
483 _Bool gotmantdig = 0, ishex = 0;
489 - nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
491 + nconv = mbrtowc_l(&decpt, localeconv()->decimal_point, MB_CUR_MAX_L(loc), &mbs, loc);
492 if (nconv == (size_t)-1 || nconv == (size_t)-2)
493 - decpt = '.'; /* failsafe */
494 + decpt = '.'; /* failsafe */
496 + s = (width == 0 ? BUF : (width + 1));
497 + if ((b = (wchar_t *)__parsefloat_buf(s * sizeof(wchar_t))) == NULL) {
503 * We set commit = p whenever the string we have read so far
504 * constitutes a valid representation of a floating point
505 @@ -748,10 +798,10 @@
506 * always necessary to read at least one character that doesn't
507 * match; thus, we can't short-circuit "infinity" or "nan(...)".
512 - for (p = buf; p < end; ) {
513 - if ((c = __fgetwc(fp)) == WEOF)
514 + for (p = b; width == 0 || p < e; ) {
515 + if ((c = __fgetwc(fp, loc)) == WEOF)
523 - } else if (!iswalnum(c) && c != '_')
524 + } else if (!iswalnum_l(c, loc) && c != '_')
532 - if ((ishex && iswxdigit(c)) || iswdigit(c))
533 + if ((ishex && iswxdigit_l(c, loc)) || iswdigit_l(c, loc))
541 - } else if ((ishex && iswxdigit(c)) || iswdigit(c)) {
542 + } else if ((ishex && iswxdigit_l(c, loc)) || iswdigit_l(c, loc)) {
546 @@ -857,24 +907,38 @@
551 + if (iswdigit_l(c, loc))
558 + LIBC_ABORT("unknown state %d", state);
561 + ssize_t diff = (p - b);
562 + ssize_t com = (commit - b);
564 + b = (wchar_t *)__parsefloat_buf(s * sizeof(wchar_t));
580 + __ungetwc(c, fp, loc);
583 + __ungetwc(*p, fp, loc);
585 - return (commit - buf);
587 + return (commit - b);