fix various bugs in new integer parser framework
authorRich Felker <dalias@aerifal.cx>
Fri, 15 Jul 2011 02:11:00 +0000 (22:11 -0400)
committerRich Felker <dalias@aerifal.cx>
Fri, 15 Jul 2011 02:11:00 +0000 (22:11 -0400)
1. my interpretation of subject sequence definition was wrong. adjust
parser to conform to the standard.

2. some code for handling tail overflow case was missing (forgot to
finish writing it).

3. typo (= instead of ==) caused ERANGE to wrongly behave like EINVAL

src/internal/intparse.c
src/stdlib/strtoimax.c
src/stdlib/strtoumax.c
src/stdlib/wcstoimax.c
src/stdlib/wcstoumax.c

index 21b07b749b1819c76384db3103a790d95d0f1201..fd403b589320633744d58fff0a17c3c7b366d9d4 100644 (file)
@@ -35,6 +35,7 @@ int __intparse(struct intparse *v, const void *buf, size_t n)
        v->cnt += n;
        for (; n; n--, s++) switch (v->state) {
        case 0:
+               v->err = EINVAL;
                v->state++;
                if (*s=='+' || *s=='-') {
                        v->neg = *s=='-';
@@ -49,6 +50,7 @@ int __intparse(struct intparse *v, const void *buf, size_t n)
        case 2:
                v->state++;
                if ((!b || b==16) && (*s|32) == 'x') {
+                       v->err = 0;
                        v->base = b = 16;
                        continue;
                }
@@ -57,10 +59,11 @@ int __intparse(struct intparse *v, const void *buf, size_t n)
        case 3:
        firstdigit:
                if (digits[*s] >= b) {
-                       v->err = EINVAL;
-                       return 0;
+                       n++;
+                       goto finished;
                }
        seconddigit:
+               v->err = 0;
                v->state++;
        case 4:
                if (b==10) {
@@ -92,11 +95,11 @@ int __intparse(struct intparse *v, const void *buf, size_t n)
                if (n && digits[*s]<b) {
                        v->err = ERANGE;
                        v->val = UINTMAX_MAX;
-
                        n--; s++;
+                       for (; n && digits[*s]<b; n--, s++);
                }
-               for (; n && digits[*s]<b; n--, s++);
                if (!n) return 1;
+               goto finished;
        }
        return 1;
 finished:
index 247f91d4105d2ae6bd948d15f74a73caf9d17d59..671aa287d68dcf345ce2ec5af1f8785384ebc8ed 100644 (file)
@@ -25,7 +25,7 @@ intmax_t strtoimax(const char *s1, char **p, int base)
 
        if (ip.err) {
                errno = ip.err;
-               if (ip.err = EINVAL) return 0;
+               if (ip.err == EINVAL) return 0;
                return ip.neg ? INTMAX_MIN : INTMAX_MAX;
        }
 
index a2bb4d7dd76393950414f8b5de1f9917a1aa7c76..a299dc045cd8fcafda41b689e82786aba9b4e129 100644 (file)
@@ -26,7 +26,7 @@ uintmax_t strtoumax(const char *s1, char **p, int base)
 
        if (ip.err) {
                errno = ip.err;
-               if (ip.err = EINVAL) return 0;
+               if (ip.err == EINVAL) return 0;
                return UINTMAX_MAX;
        }
 
index 50647f6223ee31db1f2d23d2fc8d337bebb8cacf..344fe3a3232e939eacdce33a4abb7db018f216a8 100644 (file)
@@ -6,6 +6,7 @@
 
 intmax_t wcstoimax(const wchar_t *s, wchar_t **p, int base)
 {
+       const wchar_t *s1 = s;
        struct intparse ip = {0};
 
        if (p) *p = (wchar_t *)s;
@@ -21,11 +22,11 @@ intmax_t wcstoimax(const wchar_t *s, wchar_t **p, int base)
        for (; __intparse(&ip, (char[]){(*s&-(*s<128U))}, 1); s++);
 
        if (p && ip.err != EINVAL)
-               *p = (wchar_t *)s;
+               *p = (wchar_t *)s1 + ip.cnt;
 
        if (ip.err) {
                errno = ip.err;
-               if (ip.err = EINVAL) return 0;
+               if (ip.err == EINVAL) return 0;
                return ip.neg ? INTMAX_MIN : INTMAX_MAX;
        }
 
index af7ba3dc9fe1b8deabc5e3009663d44e8f787217..cee5ff7f5c42410d911165bdd1e9fbb529efb952 100644 (file)
@@ -7,6 +7,7 @@
 
 uintmax_t wcstoumax(const wchar_t *s, wchar_t **p, int base)
 {
+       const wchar_t *s1 = s;
        struct intparse ip = {0};
 
        if (p) *p = (wchar_t *)s;
@@ -22,11 +23,11 @@ uintmax_t wcstoumax(const wchar_t *s, wchar_t **p, int base)
        for (; __intparse(&ip, (char[]){(*s&-(*s<128U))}, 1); s++);
 
        if (p && ip.err != EINVAL)
-               *p = (wchar_t *)s;
+               *p = (wchar_t *)s1 + ip.cnt;
 
        if (ip.err) {
                errno = ip.err;
-               if (ip.err = EINVAL) return 0;
+               if (ip.err == EINVAL) return 0;
                return UINTMAX_MAX;
        }