diff options
-rw-r--r-- | newlib/ChangeLog | 9 | ||||
-rw-r--r-- | newlib/Makefile.am | 1 | ||||
-rw-r--r-- | newlib/Makefile.in | 2 | ||||
-rw-r--r-- | newlib/libc/stdio/vfscanf.c | 39 | ||||
-rw-r--r-- | newlib/libc/stdlib/strtod.c | 31 |
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 |