Date: Mon, 19 Jan 2009 06:19:51 +0000 (UTC) From: David Schultz <das@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r187422 - head/lib/libc/stdio Message-ID: <200901190619.n0J6JpDQ099981@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: das Date: Mon Jan 19 06:19:51 2009 New Revision: 187422 URL: http://svn.freebsd.org/changeset/base/187422 Log: - 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. Modified: head/lib/libc/stdio/vfscanf.c head/lib/libc/stdio/vfwscanf.c Modified: head/lib/libc/stdio/vfscanf.c ============================================================================== --- head/lib/libc/stdio/vfscanf.c Mon Jan 19 06:19:38 2009 (r187421) +++ head/lib/libc/stdio/vfscanf.c Mon Jan 19 06:19:51 2009 (r187422) @@ -911,13 +911,13 @@ static int parsefloat(FILE *fp, char *buf, char *end) { char *commit, *p; - int infnanpos = 0; + int infnanpos = 0, decptpos = 0; enum { - S_START, S_GOTSIGN, S_INF, S_NAN, S_MAYBEHEX, - S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS + S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX, + S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS } state = S_START; unsigned char c; - char decpt = *localeconv()->decimal_point; + const char *decpt = localeconv()->decimal_point; _Bool gotmantdig = 0, ishex = 0; /* @@ -970,8 +970,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; @@ -989,13 +987,15 @@ reswitch: default: if (c == ')') { commit = p; - infnanpos = -2; + state = S_DONE; } else if (!isalnum(c) && c != '_') goto parsedone; break; } infnanpos++; break; + case S_DONE: + goto parsedone; case S_MAYBEHEX: state = S_DIGITS; if (c == 'X' || c == 'x') { @@ -1006,16 +1006,34 @@ reswitch: goto reswitch; } case S_DIGITS: - if ((ishex && isxdigit(c)) || isdigit(c)) + if ((ishex && isxdigit(c)) || isdigit(c)) { gotmantdig = 1; - else { + commit = p; + break; + } else { + state = S_DECPT; + goto reswitch; + } + case S_DECPT: + if (c == decpt[decptpos]) { + if (decpt[++decptpos] == '\0') { + /* We read the complete decpt seq. */ + state = S_FRAC; + if (gotmantdig) + commit = p; + } + break; + } else if (!decptpos) { + /* We didn't read any decpt characters. */ state = S_FRAC; - if (c != decpt) - goto reswitch; + goto reswitch; + } else { + /* + * We read part of a multibyte decimal point, + * but the rest is invalid, so bail. + */ + goto parsedone; } - if (gotmantdig) - commit = p; - break; case S_FRAC: if (((c == 'E' || c == 'e') && !ishex) || ((c == 'P' || c == 'p') && ishex)) { Modified: head/lib/libc/stdio/vfwscanf.c ============================================================================== --- head/lib/libc/stdio/vfwscanf.c Mon Jan 19 06:19:38 2009 (r187421) +++ head/lib/libc/stdio/vfwscanf.c Mon Jan 19 06:19:51 2009 (r187422) @@ -103,6 +103,8 @@ static int parsefloat(FILE *, 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 w 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') {
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901190619.n0J6JpDQ099981>