Skip site navigation (1)Skip section navigation (2)
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>