aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--newlib/ChangeLog9
-rw-r--r--newlib/Makefile.am1
-rw-r--r--newlib/Makefile.in2
-rw-r--r--newlib/libc/stdio/vfscanf.c39
-rw-r--r--newlib/libc/stdlib/strtod.c31
5 files changed, 73 insertions, 9 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 9fa9710..2ae9e06 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,12 @@
+2005-01-06 Jeff Johnston <jjohnstn@redhat.com>
+
+ * libc/stdlib/strtod.c (_strtod_r): Add NaN support.
+ * (strtof): Ditto.
+ * libc/stdio/vfscanf.c (__svfscanf_r): Ditto.
+ * Makefile.am (MATHOBJS_IN_LIBC): Add s_nan and sf_nan
+ functions for use by strtod and strtof.
+ * Makefile.in: Regenerated.
+
2005-01-06 Hans-Peter Nilsson <hp@axis.com>
* libc/stdio/ftell.c (ftell_r): Add parenthesis for __SWR
diff --git a/newlib/Makefile.am b/newlib/Makefile.am
index 07172e9..9ed5367 100644
--- a/newlib/Makefile.am
+++ b/newlib/Makefile.am
@@ -89,6 +89,7 @@ toollib_DATA = $(CRT0) $(CRT1)
MATHOBJS_IN_LIBC = \
s_isinf.$(oext) sf_isinf.$(oext) \
s_isnan.$(oext) sf_isnan.$(oext) \
+ s_nan.$(oext) sf_nan.$(oext) \
s_ldexp.$(oext) sf_ldexp.$(oext) \
s_frexp.$(oext) sf_frexp.$(oext) \
s_modf.$(oext) \
diff --git a/newlib/Makefile.in b/newlib/Makefile.in
index 76382e8..364d3ba 100644
--- a/newlib/Makefile.in
+++ b/newlib/Makefile.in
@@ -151,7 +151,7 @@ toollib_DATA = $(CRT0) $(CRT1)
# The functions ldexp, frexp and modf are traditionally supplied in
# both libc.a and libm.a. We build them in libm.a and copy them over,
# along with some required supporting routines.
-MATHOBJS_IN_LIBC = s_isinf.$(oext) sf_isinf.$(oext) s_isnan.$(oext) sf_isnan.$(oext) s_ldexp.$(oext) sf_ldexp.$(oext) s_frexp.$(oext) sf_frexp.$(oext) s_modf.$(oext) sf_modf.$(oext) s_scalbn.$(oext) sf_scalbn.$(oext) s_finite.$(oext) sf_finite.$(oext) s_copysign.$(oext) sf_copysign.$(oext) s_infconst.$(oext)
+MATHOBJS_IN_LIBC = s_isinf.$(oext) sf_isinf.$(oext) s_isnan.$(oext) sf_isnan.$(oext) s_nan.$(oext) sf_nan.$(oext) s_ldexp.$(oext) sf_ldexp.$(oext) s_frexp.$(oext) sf_frexp.$(oext) s_modf.$(oext) sf_modf.$(oext) s_scalbn.$(oext) sf_scalbn.$(oext) s_finite.$(oext) sf_finite.$(oext) s_copysign.$(oext) sf_copysign.$(oext) s_infconst.$(oext)
LIBC_OBJECTLISTS = $(POSIX_OBJECTLIST) $(SIGNAL_OBJECTLIST) $(SYSCALL_OBJECTLIST) $(UNIX_OBJECTLIST) $(STDIO64_OBJECTLIST) libc/argz/objectlist.awk.in libc/stdlib/objectlist.awk.in libc/time/objectlist.awk.in libc/ctype/objectlist.awk.in libc/search/objectlist.awk.in libc/string/objectlist.awk.in libc/locale/objectlist.awk.in libc/misc/objectlist.awk.in libc/reent/objectlist.awk.in libc/errno/objectlist.awk.in libc/stdio/objectlist.awk.in $(MACHINE_OBJECTLIST) $(SYS_OBJECTLIST) $(SYS_MACH_OBJECTLIST)
diff --git a/newlib/libc/stdio/vfscanf.c b/newlib/libc/stdio/vfscanf.c
index 9e04e2b..00dfb95 100644
--- a/newlib/libc/stdio/vfscanf.c
+++ b/newlib/libc/stdio/vfscanf.c
@@ -135,6 +135,7 @@ Supporting OS subroutines required:
#endif
#ifdef FLOATING_POINT
+#include <math.h>
#include <float.h>
/* Currently a test is made to see if long double processing is warranted.
@@ -985,6 +986,7 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
long zeroes, exp_adjust;
char *exp_start = NULL;
unsigned width_left = 0;
+ int nancount = 0;
#ifdef hardway
if (width == 0 || width > sizeof (buf) - 1)
#else
@@ -1007,7 +1009,6 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
*/
switch (c)
{
-
case '0':
if (flags & NDIGITS)
{
@@ -1030,8 +1031,12 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
case '7':
case '8':
case '9':
- flags &= ~(SIGNOK | NDIGITS);
- goto fok;
+ if (nancount == 0)
+ {
+ flags &= ~(SIGNOK | NDIGITS);
+ goto fok;
+ }
+ break;
case '+':
case '-':
@@ -1041,6 +1046,29 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
goto fok;
}
break;
+ case 'n':
+ case 'N':
+ if (nancount == 0
+ && (flags & (SIGNOK | NDIGITS | DPTOK | EXPOK)))
+ {
+ flags &= ~(SIGNOK | DPTOK | EXPOK | NDIGITS);
+ nancount = 1;
+ goto fok;
+ }
+ else if (nancount == 2)
+ {
+ nancount = 3;
+ goto fok;
+ }
+ break;
+ case 'a':
+ case 'A':
+ if (nancount == 1)
+ {
+ nancount = 2;
+ goto fok;
+ }
+ break;
case '.':
if (flags & DPTOK)
{
@@ -1163,7 +1191,10 @@ _DEFUN(__SVFSCANF_R, (rptr, fp, fmt0, ap),
else
{
flp = va_arg (ap, float *);
- *flp = res;
+ if (isnan (res))
+ *flp = nanf (NULL);
+ else
+ *flp = res;
}
nassigned++;
}
diff --git a/newlib/libc/stdlib/strtod.c b/newlib/libc/stdlib/strtod.c
index 19467f4..455389d 100644
--- a/newlib/libc/stdlib/strtod.c
+++ b/newlib/libc/stdlib/strtod.c
@@ -117,9 +117,10 @@ _DEFUN (_strtod_r, (ptr, s00, se),
unsigned long z;
__ULong y;
union double_union rv, rv0;
+ int nanflag;
_Bigint *bb, *bb1, *bd, *bd0, *bs, *delta;
- sign = nz0 = nz = 0;
+ sign = nz0 = nz = nanflag = 0;
rv.d = 0.;
for (s = s00;; s++)
switch (*s)
@@ -145,7 +146,23 @@ _DEFUN (_strtod_r, (ptr, s00, se),
goto break2;
}
break2:
- if (*s == '0')
+ if (*s == 'n' || *s == 'N')
+ {
+ ++s;
+ if (*s == 'a' || *s == 'A')
+ {
+ ++s;
+ if (*s == 'n' || *s == 'N')
+ {
+ nanflag = 1;
+ ++s;
+ goto ret;
+ }
+ }
+ s = s00;
+ goto ret;
+ }
+ else if (*s == '0')
{
nz0 = 1;
while (*++s == '0');
@@ -708,7 +725,10 @@ retfree:
ret:
if (se)
*se = (char *) s;
- return sign ? -rv.d : rv.d;
+
+ if (nanflag)
+ return nan (NULL);
+ return (sign && (s != s00)) ? -rv.d : rv.d;
}
#ifndef NO_REENT
@@ -725,7 +745,10 @@ _DEFUN (strtof, (s00, se),
_CONST char *s00 _AND
char **se)
{
- return (float)_strtod_r (_REENT, s00, se);
+ double retval = _strtod_r (_REENT, s00, se);
+ if (isnan (retval))
+ return nanf (NULL);
+ return (float)retval;
}
#endif