X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX1+uFHkDz3KutOhzPEfZDAHO6DKmasvKhtn/DwA1Nx 6NLMJk6m0cZ9MA Message-ID: <51C5E568.7060005@gmx.de> Date: Sat, 22 Jun 2013 19:56:56 +0200 From: Juan Manuel Guerrero User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2 MIME-Version: 1.0 To: djgpp-workers AT delorie DOT com Subject: Some strto[d|f|ld] issues. Content-Type: text/plain; charset=ISO-8859-15; format=flowed Content-Transfer-Encoding: 7bit X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com While I was trying to port the latest Lua, I have found the following issues: s endptr value 1) .... ... 0 numeric values is correct but endptr points to the second non numeric char. Should point to first dot. 2) +1eNNN NNN 1 numeric values is correct but endptr points to first 'N'. Should point to 'e'. 3) +0xa.aP+NNN NNN 10.625 numeric values is correct but endptr points to first 'N'. Should point to 'P'. 4) ' ' 0 numeric values is correct but endptr points to end of white space string. Should point to first white space char. This issue concerns only the repository versions of strto[d|f|ld] not the ones in djdev204.zip available in the /beta directory. The patch below will fix all these issues. Regards, Juan M. Guerrero Logging in to :pserver:anonymous AT cvs DOT delorie DOT com:2401/cvs/djgpp Index: djgpp/src/libc/ansi/stdlib/strtod.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtod.c,v retrieving revision 1.12 diff -p -U 5 -r1.12 strtod.c --- djgpp/src/libc/ansi/stdlib/strtod.c 19 Jun 2013 19:38:02 -0000 1.12 +++ djgpp/src/libc/ansi/stdlib/strtod.c 22 Jun 2013 15:30:27 -0000 @@ -33,19 +33,25 @@ strtod(const char *s, char **sret) { long double r = 0; /* result */ int e = 0; /* exponent */ long double d; /* scale */ int sign = 1; /* +- 1.0 */ - int esign = 1; + int esign = 0; /* 0: no valid exponent after [eEpP] */ int i; int flags = 0; char decimal_point = localeconv()->decimal_point[0]; + if (sret) + *sret = unconst(s, char *); + while (isspace((unsigned char) *s)) s++; + if (!*s) + return 0.0; + /* Handle leading sign. */ if (*s == '+') s++; else if (*s == '-') { @@ -62,11 +68,11 @@ strtod(const char *s, char **sret) *sret = unconst((&s[8]), char *); else *sret = unconst((&s[3]), char *); } - return (0 > sign) ? -INFINITY : INFINITY; + return (sign < 0) ? -INFINITY : INFINITY; } /* Handle NAN and NAN(). */ if (!strnicmp("NAN", s, 3)) { @@ -179,14 +185,18 @@ strtod(const char *s, char **sret) for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--) bit >>= 1; } } - if (!flags) + if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0L; } if (mantissa) @@ -217,26 +227,40 @@ strtod(const char *s, char **sret) if (IS_EXPONENT(s)) { long int exponent = 0.0; s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { esign = -1; s++; } - while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + if (!*s) { - exponent *= 10; - exponent += *s - '0'; - s++; + /* Mantissa followed by [pP] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + { + exponent *= 10; + exponent += *s - '0'; + s++; + } + bin_exponent += esign * exponent; /* 2**bin_exponent. */ + while (IS_DEC_DIGIT(*s)) + s++; /* Discart rest of exponent. */ } - bin_exponent += esign * exponent; /* 2**bin_exponent. */ - while (IS_DEC_DIGIT(*s)) - s++; /* Discart rest of exponent. */ } if (sret) *sret = unconst(s, char *); @@ -285,29 +309,49 @@ strtod(const char *s, char **sret) } } if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } + errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0; } if ((*s == 'e') || (*s == 'E')) { s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { - s++; esign = -1; + s++; } - while (IS_DEC_DIGIT(*s)) + + if (!*s) { - e *= 10; - e += *s - '0'; - s++; + /* Mantissa followed by [eE] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while (IS_DEC_DIGIT(*s)) + { + e *= 10; + e += *s - '0'; + s++; + } } } /* Detect overflow. */ if (e < 0) @@ -346,7 +390,8 @@ strtod(const char *s, char **sret) } } if (sret) *sret = unconst(s, char *); + return r * sign; } Index: djgpp/src/libc/ansi/stdlib/strtold.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/ansi/stdlib/strtold.c,v retrieving revision 1.12 diff -p -U 5 -r1.12 strtold.c --- djgpp/src/libc/ansi/stdlib/strtold.c 19 Jun 2013 19:38:05 -0000 1.12 +++ djgpp/src/libc/ansi/stdlib/strtold.c 22 Jun 2013 15:30:28 -0000 @@ -35,19 +35,26 @@ long double strtold(const char *s, char **sret) { long double r = 0.0L; /* result */ int e = 0, ne = 0; /* exponent */ int sign = 1; /* +- 1.0 */ - int esign = 1; + int esign = 0; /* 0: no valid exponent after [eEpP] */ int flags = 0; int l2powm1; char decimal_point = localeconv()->decimal_point[0]; + if (sret) + *sret = unconst(s, char *); + while(*s && isspace((unsigned char)*s)) s++; + if (!*s) + return 0.0; + + /* Handle leading sign. */ if (*s == '+') s++; else if (*s == '-') { sign = -1; @@ -63,11 +70,11 @@ strtold(const char *s, char **sret) *sret = unconst((&s[8]), char *); else *sret = unconst((&s[3]), char *); } - return (0 > sign) ? -INFINITY : INFINITY; + return (sign < 0) ? -INFINITY : INFINITY; } /* Handle NAN and NAN(). */ if (!strnicmp("NAN", s, 3)) { @@ -185,14 +192,18 @@ strtold(const char *s, char **sret) for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--) bit >>= 1; } } - if (!flags) + if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0L; } if (mantissa) @@ -243,26 +254,40 @@ strtold(const char *s, char **sret) if (IS_EXPONENT(s)) { long long int exponent = 0.0L; s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { esign = -1; s++; } - while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + if (!*s) { - exponent *= 10; - exponent += *s - '0'; - s++; + /* Mantissa followed by [pP] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + { + exponent *= 10; + exponent += *s - '0'; + s++; + } + bin_exponent += esign * exponent; /* 2**bin_exponent. */ + while (IS_DEC_DIGIT(*s)) + s++; /* Discart rest of exponent. */ } - bin_exponent += esign * exponent; /* 2**bin_exponent. */ - while (IS_DEC_DIGIT(*s)) - s++; /* Discart rest of exponent. */ } if (sret) *sret = unconst(s, char *); if (mantissa) @@ -310,30 +335,49 @@ strtold(const char *s, char **sret) } } if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0L; } if ((*s == 'e') || (*s == 'E')) { s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { - s++; esign = -1; + s++; } - while (IS_DEC_DIGIT(*s)) + + if (!*s) { - e *= 10; - e += *s - '0'; - s++; + /* Mantissa followed by [eE] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while (IS_DEC_DIGIT(*s)) + { + e *= 10; + e += *s - '0'; + s++; + } } } if (esign < 0) { esign = -esign; @@ -367,9 +411,11 @@ strtold(const char *s, char **sret) if (esign > 0) r *= d; else r /= d; } + if (sret) *sret = unconst(s, char *); + return r * sign; } Index: djgpp/src/libc/c99/stdlib/strtof.c =================================================================== RCS file: /cvs/djgpp/djgpp/src/libc/c99/stdlib/strtof.c,v retrieving revision 1.10 diff -p -U 5 -r1.10 strtof.c --- djgpp/src/libc/c99/stdlib/strtof.c 19 Jun 2013 19:38:03 -0000 1.10 +++ djgpp/src/libc/c99/stdlib/strtof.c 22 Jun 2013 15:30:28 -0000 @@ -35,20 +35,27 @@ strtof(const char *s, char **sret) { long double r = 0; /* result */ int e = 0; /* exponent */ long double d; /* scale */ int sign = 1; /* +- 1.0 */ - int esign = 1; + int esign = 0; /* 0: no valid exponent after [eEpP] */ int i; int flags = 0; int overflow = 0; char decimal_point = localeconv()->decimal_point[0]; + if (sret) + *sret = unconst(s, char *); + while (isspace((unsigned char) *s)) s++; + if (!*s) + return 0.0; + + /* Handle leading sign. */ if (*s == '+') s++; else if (*s == '-') { sign = -1; @@ -64,11 +71,11 @@ strtof(const char *s, char **sret) *sret = unconst((&s[8]), char *); else *sret = unconst((&s[3]), char *); } - return (0 > sign) ? -INFINITY : INFINITY; + return (sign < 0) ? -INFINITY : INFINITY; } /* Handle NAN and NAN(). */ if (!strnicmp("NAN", s, 3)) { @@ -179,14 +186,18 @@ strtof(const char *s, char **sret) for (bit <<= (digits * HEX_DIGIT_SIZE + bin_exponent); !(mantissa & bit); bin_exponent--) bit >>= 1; } } - if (!flags) + if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0; } if (mantissa) @@ -217,26 +228,40 @@ strtof(const char *s, char **sret) if (IS_EXPONENT(s)) { int exponent = 0.0; s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { esign = -1; s++; } - while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + if (!*s) { - exponent *= 10; - exponent += *s - '0'; - s++; + /* Mantissa followed by [pP] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while ((esign * exponent + bin_exponent) < (MAX_BIN_EXPONENT + 1) && IS_DEC_DIGIT(*s)) + { + exponent *= 10; + exponent += *s - '0'; + s++; + } + bin_exponent += esign * exponent; /* 2**bin_exponent. */ + while (IS_DEC_DIGIT(*s)) + s++; /* Discart rest of exponent. */ } - bin_exponent += esign * exponent; /* 2**bin_exponent. */ - while (IS_DEC_DIGIT(*s)) - s++; /* Discart rest of exponent. */ } if (sret) *sret = unconst(s, char *); @@ -284,29 +309,49 @@ strtof(const char *s, char **sret) } } if (flags == 0) { if (sret) + { + if (!r) + s--; /* A dot without leading numbers. */ *sret = unconst(s, char *); + } + errno = EINVAL; /* No valid mantissa, no convertion could be performed. */ return 0.0; } if ((*s == 'e') || (*s == 'E')) { s++; if (*s == '+') + { + esign = +1; s++; + } else if (*s == '-') { - s++; esign = -1; + s++; } - while (IS_DEC_DIGIT(*s)) + + if (!*s) { - e *= 10; - e += *s - '0'; - s++; + /* Mantissa followed by [eE] with/out + a sign but without exponent. */ + s--; + if (esign) + s--; + } + else + { + while (IS_DEC_DIGIT(*s)) + { + e *= 10; + e += *s - '0'; + s++; + } } } /* Detect overflow. */ if (e < 0)