diff options
author | das <das@FreeBSD.org> | 2009-01-19 06:19:51 +0000 |
---|---|---|
committer | das <das@FreeBSD.org> | 2009-01-19 06:19:51 +0000 |
commit | 97494c6c591e709d63c82a2b4cc7fd06df6a540f (patch) | |
tree | 5c8e24a9f6796b29eb3e538fd7acb9c2956fc8a7 /lib/libc/stdio/vfwscanf.c | |
parent | df3bc34671810c7f72a3bcd6c81d9a53ff3607da (diff) | |
download | FreeBSD-src-97494c6c591e709d63c82a2b4cc7fd06df6a540f.zip FreeBSD-src-97494c6c591e709d63c82a2b4cc7fd06df6a540f.tar.gz |
- Add support for multibyte decimal_point encodings, e.g., U+066B.
A forthcoming gdtoa import is needed to make this fully work.
- Improve the way "nan(...)" is parsed.
Diffstat (limited to 'lib/libc/stdio/vfwscanf.c')
-rw-r--r-- | lib/libc/stdio/vfwscanf.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c index 8a62a8f7..60c7c71 100644 --- a/lib/libc/stdio/vfwscanf.c +++ b/lib/libc/stdio/vfwscanf.c @@ -103,6 +103,8 @@ static int parsefloat(FILE *, wchar_t *, wchar_t *); (cclcompl ? (wmemchr(ccls, (_c), ccle - ccls) == NULL) : \ (wmemchr(ccls, (_c), ccle - ccls) != NULL)) +static const mbstate_t initial_mbs; + /* * MT-safe version. */ @@ -142,7 +144,6 @@ __vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap) char *mbp; /* multibyte string pointer for %c %s %[ */ size_t nconv; /* number of bytes in mb. conversion */ char mbbuf[MB_LEN_MAX]; /* temporary mb. character buffer */ - static const mbstate_t initial; mbstate_t mbs; /* `basefix' is used to avoid `if' tests in the integer scanner */ @@ -375,7 +376,7 @@ literal: if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); n = 0; - mbs = initial; + mbs = initial_mbs; while (width != 0 && (wi = __fgetwc(fp)) != WEOF) { if (width >= MB_CUR_MAX && @@ -440,7 +441,7 @@ literal: if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); n = 0; - mbs = initial; + mbs = initial_mbs; while ((wi = __fgetwc(fp)) != WEOF && width != 0 && INCCL(wi)) { if (width >= MB_CUR_MAX && @@ -501,7 +502,7 @@ literal: } else { if (!(flags & SUPPRESS)) mbp = va_arg(ap, char *); - mbs = initial; + mbs = initial_mbs; while ((wi = __fgetwc(fp)) != WEOF && width != 0 && !iswspace(wi)) { @@ -721,16 +722,23 @@ match_failure: static int parsefloat(FILE *fp, wchar_t *buf, wchar_t *end) { + mbstate_t mbs; + size_t nconv; wchar_t *commit, *p; int infnanpos = 0; enum { - S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX, + S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX, S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; wchar_t c; - wchar_t decpt = (wchar_t)(unsigned char)*localeconv()->decimal_point; + wchar_t decpt; _Bool gotmantdig = 0, ishex = 0; + mbs = initial_mbs; + nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs); + if (nconv == (size_t)-1 || nconv == (size_t)-2) + decpt = '.'; /* failsafe */ + /* * We set commit = p whenever the string we have read so far * constitutes a valid representation of a floating point @@ -783,8 +791,6 @@ reswitch: break; case S_NAN: switch (infnanpos) { - case -1: /* XXX kludge to deal with nan(...) */ - goto parsedone; case 0: if (c != 'A' && c != 'a') goto parsedone; @@ -802,13 +808,15 @@ reswitch: default: if (c == ')') { commit = p; - infnanpos = -2; + state = S_DONE; } else if (!iswalnum(c) && c != '_') goto parsedone; break; } infnanpos++; break; + case S_DONE: + goto parsedone; case S_MAYBEHEX: state = S_DIGITS; if (c == 'X' || c == 'x') { |