Mail Archives: djgpp-workers/2013/06/22/14:10:05
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(<whatever>). */
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(<whatever>). */
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(<hex-number>). */
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)
- Raw text -