summaryrefslogtreecommitdiffstats
path: root/newlib/libc/stdlib/strtod.c
diff options
context:
space:
mode:
authorEric Blake <eblake@redhat.com>2008-02-21 17:14:14 +0000
committerEric Blake <eblake@redhat.com>2008-02-21 17:14:14 +0000
commit7a44c13ecb8b0b83367875e2db4add4a53ed9188 (patch)
treefc285cbae225c8e283c3babe42e50746dc01bc2c /newlib/libc/stdlib/strtod.c
parent1f71763a62630d4e4baf86f7fa90f1c9a3242cc6 (diff)
downloadcygnal-7a44c13ecb8b0b83367875e2db4add4a53ed9188.tar.gz
cygnal-7a44c13ecb8b0b83367875e2db4add4a53ed9188.tar.bz2
cygnal-7a44c13ecb8b0b83367875e2db4add4a53ed9188.zip
Fix strtod("-0x", NULL).
* libc/stdlib/strtod.c (_strtod_r): Fall back to 0 if hex parse fails.
Diffstat (limited to 'newlib/libc/stdlib/strtod.c')
-rw-r--r--newlib/libc/stdlib/strtod.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index e206d0587..80e5aacef 100644
--- a/newlib/libc/stdlib/strtod.c
+++ b/newlib/libc/stdlib/strtod.c
@@ -14,7 +14,7 @@ ANSI_SYNOPSIS
double strtod(const char *<[str]>, char **<[tail]>);
float strtof(const char *<[str]>, char **<[tail]>);
- double _strtod_r(void *<[reent]>,
+ double _strtod_r(void *<[reent]>,
const char *<[str]>, char **<[tail]>);
TRAD_SYNOPSIS
@@ -37,12 +37,19 @@ DESCRIPTION
producing a substring which can be converted to a double
value. The substring converted is the longest initial
subsequence of <[str]>, beginning with the first
- non-whitespace character, that has the format:
- .[+|-]<[digits]>[.][<[digits]>][(e|E)[+|-]<[digits]>]
+ non-whitespace character, that has one of these formats:
+ .[+|-]<[digits]>[.[<[digits]>]][(e|E)[+|-]<[digits]>]
+ .[+|-].<[digits]>[(e|E)[+|-]<[digits]>]
+ .[+|-](i|I)(n|N)(f|F)[(i|I)(n|N)(i|I)(t|T)(y|Y)]
+ .[+|-](n|N)(a|A)(n|N)[<(>[<[hexdigits]>]<)>]
+ .[+|-]0(x|X)<[hexdigits]>[.[<[hexdigits]>]][(p|P)[+|-]<[digits]>]
+ .[+|-]0(x|X).<[hexdigits]>[(p|P)[+|-]<[digits]>]
The substring contains no characters if <[str]> is empty, consists
entirely of whitespace, or if the first non-whitespace
character is something other than <<+>>, <<->>, <<.>>, or a
- digit. If the substring is empty, no conversion is done, and
+ digit, and cannot be parsed as infinity or NaN. If the platform
+ does not support NaN, then NaN is treated as an empty substring.
+ If the substring is empty, no conversion is done, and
the value of <[str]> is stored in <<*<[tail]>>>. Otherwise,
the substring is converted, and a pointer to the final string
(which will contain at least the terminating null character of
@@ -52,7 +59,8 @@ DESCRIPTION
This implementation returns the nearest machine number to the
input decimal string. Ties are broken by using the IEEE
- round-even rule.
+ round-even rule. However, <<strtof>> is currently subject to
+ double rounding errors.
The alternate function <<_strtod_r>> is a reentrant version.
The extra argument <[reent]> is a pointer to a reentrancy structure.
@@ -176,7 +184,7 @@ _DEFUN (ULtod, (L, bits, exp, k),
L[_0] |= 0x80000000L;
}
#endif /* !NO_HEX_FP */
-
+
#ifdef INFNAN_CHECK
static int
_DEFUN (match, (sp, t),
@@ -254,6 +262,9 @@ _DEFUN (_strtod_r, (ptr, s00, se),
switch(s[1]) {
case 'x':
case 'X':
+ /* If the number is not hex, then the parse of
+ 0 is still valid. */
+ s00 = s + 1;
{
#if defined(FE_DOWNWARD) && defined(FE_TONEAREST) && defined(FE_TOWARDZERO) && defined(FE_UPWARD)
FPI fpi1 = fpi;
@@ -268,7 +279,6 @@ _DEFUN (_strtod_r, (ptr, s00, se),
switch((i = gethex(ptr, &s, &fpi1, &exp, &bb, sign)) & STRTOG_Retmask) {
case STRTOG_NoNumber:
s = s00;
- sign = 0;
case STRTOG_Zero:
break;
default: