diff options
| author | Ulrich Drepper <drepper@redhat.com> | 2004-03-14 21:12:06 +0000 |
|---|---|---|
| committer | Ulrich Drepper <drepper@redhat.com> | 2004-03-14 21:12:06 +0000 |
| commit | ccadf7b5346a3e21c692dfcbfcf38a63433bc36a (patch) | |
| tree | a1e826af3345eee581925387513b1b6c76629c31 /stdlib/strtod.c | |
| parent | 3bc9b83f49805969b7d139b52ef6b003e5136354 (diff) | |
| download | glibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.tar.xz glibc-ccadf7b5346a3e21c692dfcbfcf38a63433bc36a.zip | |
Update.
2004-03-14 Ulrich Drepper <drepper@redhat.com>
Make the non-_l functions wrappers around the _l functions.
* include/monetary.h: Declare __vstrmon_l.
* include/string.h: Add libc_hidden_proto for __strcoll_l and
__strxfrm_l.
* include/time.h: Define ptime_locale_status. Declare
__strptime_internal.
* include/wchar.h: Add libc_hidden_proto for __wcscoll_l and
__wcsxfrm_l.
* stdlib/strfmon.c: Move the code to strfmon_l.c. Add little
wrapper around __vstrfmon_l.
* stdlib/strfmon_l.c: Add real implementation. Split into new
function __vstrfmon_l to allow calling it from strfmon.
* stdlib/strtod.c: Move real code to strtod_l.c and add wrapper.
* stdlib/strtod_l.c: Add real implementation.
* stdlib/strtof.c: Adjust to changed strtod.c.
* stdlib/strtof_l.c: Include strtod_l.c now.
* stdlib/strtold.c: New file.
* stdlib/strtold_l.c: Removed.
* string/strcoll.c: Move real code to strcoll_l.c: Add wrapper.
* string/strcoll_l.c: Add real implementation.
* string/strxfrm.c: Move real code to strxfrm_l.c: Add wrapper.
* string/strxfrm_l.c: Add real implementation.
* sysdeps/generic/strtol.c: Move real implementation to strtol_l.c.
Add wrappers.
* sysdeps/generic/strtol_l.c: Add real implementation.
* sysdeps/generic/strtold.c: Removed.
* sysdeps/generic/strtold_l.c: New file.
* sysdeps/generic/strtoll_l.c: Include strtol_l.c now. Adjust
#defines.
* sysdeps/generic/strtoul_l.c: Likewise.
* sysdeps/generic/strtoull_l.c: Likewise.
* sysdeps/generic/wcstol_l.c: Likewise.
* sysdeps/generic/wcstoll_l.c: Likewise.
* sysdeps/generic/wcstoul_l.c: Likewise.
* sysdeps/generic/wcstoull_l.c: Likewise.
* sysdeps/ieee754/ldbl-128/strtold.c: Removed.
* sysdeps/ieee754/ldbl-128/strtold_l.c: New file.
* sysdeps/ieee754/ldbl-96/strtold.c: Removed.
* sysdeps/ieee754/ldbl-96/strtold_l.c: New file.
* sysdeps/m68k/strtold.c: Removed.
* sysdeps/m68k/strtold_l.c: New file.
* time/strftime.c: Move real code to strftime_l.c. Add wrapper.
* time/strftime_l.c: Add real implementation.
* time/strptime.c: Move real code to strptime_l.c. Add wrapper.
* time/strptime_l.c: Add real implementation.
* time/wcsftime.c: Simplify since only wrappers are defined in
strftime.c.
* time/wcsftime_l.c: Include strftime_l.c.
* wcsmbs/wcscoll.c: Simplify since the file is not used by wcscoll_l.c
anymore.
* wcsmbs/wcscoll_l.c: Include strcoll_l.c.
* wcsmbs/wcsxfrm.c: Simplify since the file is not used by wcsxfrm_l.c
anymore.
* wcsmbs/wcsxfrm_l.c: Include strxfrm_l.c.
* wcsmbs/wcstod.c: Prepare to include new strtod.c.
* wcsmbs/wcstod_l.c: Include strtod_l.c.
* wcsmbs/wcstof.c: Prepare to include new strtof.c.
* wcsmbs/wcstof_l.c: Include strtof_l.c.
* wcsmbs/wcstold.c: Prepare to include new strtold.c.
* wcsmbs/wcstold_l.c: Include strtold_l.c.
* locale/uselocale.c: Use _NL_CURRENT_LOCALE instead of __libc_tsd_get.
* sysdeps/generic/strcasecmp.c: Optimize a bit. It's better to get
a reference to the current locale and then use the _l functions.
* sysdeps/generic/strncase.c: Likewise.
Diffstat (limited to 'stdlib/strtod.c')
| -rw-r--r-- | stdlib/strtod.c | 1560 |
1 files changed, 17 insertions, 1543 deletions
diff --git a/stdlib/strtod.c b/stdlib/strtod.c index 63d7a4d5bb..1d4e4a4c29 100644 --- a/stdlib/strtod.c +++ b/stdlib/strtod.c @@ -1,6 +1,6 @@ /* Read decimal floating point numbers. This file is part of the GNU C Library. - Copyright (C) 1995-2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1995-2002, 2003, 2004 Free Software Foundation, Inc. Contributed by Ulrich Drepper <drepper@gnu.org>, 1995. The GNU C Library is free software; you can redistribute it and/or @@ -18,1579 +18,53 @@ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -/* Configuration part. These macros are defined by `strtold.c', - `strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the - `long double' and `float' versions of the reader. */ +#include <stdlib.h> +#include <wchar.h> +#include <locale/localeinfo.h> + + #ifndef FLOAT -# define FLOAT double -# define FLT DBL +# define FLOAT double # ifdef USE_WIDE_CHAR -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __wcstod_l -# else -# define STRTOF wcstod -# endif +# define STRTOF wcstod +# define STRTOF_L __wcstod_l # else -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define STRTOF __strtod_l -# else -# define STRTOF strtod -# endif +# define STRTOF strtod +# define STRTOF_L __strtod_l # endif -# define MPN2FLOAT __mpn_construct_double -# define FLOAT_HUGE_VAL HUGE_VAL -# define SET_MANTISSA(flt, mant) \ - do { union ieee754_double u; \ - u.d = (flt); \ - if ((mant & 0xfffffffffffffULL) == 0) \ - mant = 0x8000000000000ULL; \ - u.ieee.mantissa0 = ((mant) >> 32) & 0xfffff; \ - u.ieee.mantissa1 = (mant) & 0xffffffff; \ - (flt) = u.d; \ - } while (0) -#endif -/* End of configuration part. */ - -#include <ctype.h> -#include <errno.h> -#include <float.h> -#include <ieee754.h> -#include "../locale/localeinfo.h" -#include <locale.h> -#include <math.h> -#include <stdlib.h> -#include <string.h> - -/* The gmp headers need some configuration frobs. */ -#define HAVE_ALLOCA 1 - -/* Include gmp-mparam.h first, such that definitions of _SHORT_LIMB - and _LONG_LONG_LIMB in it can take effect into gmp.h. */ -#include <gmp-mparam.h> -#include <gmp.h> -#include <gmp-impl.h> -#include <longlong.h> -#include "fpioconst.h" - -#define NDEBUG 1 -#include <assert.h> - - -/* We use this code also for the extended locale handling where the - function gets as an additional argument the locale which has to be - used. To access the values we have to redefine the _NL_CURRENT - macro. */ -#ifdef USE_IN_EXTENDED_LOCALE_MODEL -# undef _NL_CURRENT -# define _NL_CURRENT(category, item) \ - (current->values[_NL_ITEM_INDEX (item)].string) -# define LOCALE_PARAM , loc -# define LOCALE_PARAM_DECL __locale_t loc; -#else -# define LOCALE_PARAM -# define LOCALE_PARAM_DECL -#endif - -#if defined _LIBC || defined HAVE_WCHAR_H -# include <wchar.h> #endif #ifdef USE_WIDE_CHAR # include <wctype.h> # define STRING_TYPE wchar_t -# define CHAR_TYPE wint_t -# define L_(Ch) L##Ch -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __iswspace_l ((Ch), loc) -# define ISDIGIT(Ch) __iswdigit_l ((Ch), loc) -# define ISXDIGIT(Ch) __iswxdigit_l ((Ch), loc) -# define TOLOWER(Ch) __towlower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __wcsncasecmp_l ((S1), (S2), (N), loc) -# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc) -# else -# define ISSPACE(Ch) iswspace (Ch) -# define ISDIGIT(Ch) iswdigit (Ch) -# define ISXDIGIT(Ch) iswxdigit (Ch) -# define TOLOWER(Ch) towlower (Ch) -# define STRNCASECMP(S1, S2, N) __wcsncasecmp ((S1), (S2), (N)) -# define STRTOULL(S, E, B) __wcstoull_internal ((S), (E), (B), 0) -# endif #else # define STRING_TYPE char -# define CHAR_TYPE char -# define L_(Ch) Ch -# ifdef USE_IN_EXTENDED_LOCALE_MODEL -# define ISSPACE(Ch) __isspace_l ((Ch), loc) -# define ISDIGIT(Ch) __isdigit_l ((Ch), loc) -# define ISXDIGIT(Ch) __isxdigit_l ((Ch), loc) -# define TOLOWER(Ch) __tolower_l ((Ch), loc) -# define STRNCASECMP(S1, S2, N) __strncasecmp_l ((S1), (S2), (N), loc) -# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc) -# else -# define ISSPACE(Ch) isspace (Ch) -# define ISDIGIT(Ch) isdigit (Ch) -# define ISXDIGIT(Ch) isxdigit (Ch) -# define TOLOWER(Ch) tolower (Ch) -# define STRNCASECMP(S1, S2, N) __strncasecmp ((S1), (S2), (N)) -# define STRTOULL(S, E, B) __strtoull_internal ((S), (E), 0, (B)) -# endif -#endif - - -/* Constants we need from float.h; select the set for the FLOAT precision. */ -#define MANT_DIG PASTE(FLT,_MANT_DIG) -#define DIG PASTE(FLT,_DIG) -#define MAX_EXP PASTE(FLT,_MAX_EXP) -#define MIN_EXP PASTE(FLT,_MIN_EXP) -#define MAX_10_EXP PASTE(FLT,_MAX_10_EXP) -#define MIN_10_EXP PASTE(FLT,_MIN_10_EXP) - -/* Extra macros required to get FLT expanded before the pasting. */ -#define PASTE(a,b) PASTE1(a,b) -#define PASTE1(a,b) a##b - -/* Function to construct a floating point number from an MP integer - containing the fraction bits, a base 2 exponent, and a sign flag. */ -extern FLOAT MPN2FLOAT (mp_srcptr mpn, int exponent, int negative); - -/* Definitions according to limb size used. */ -#if BITS_PER_MP_LIMB == 32 -# define MAX_DIG_PER_LIMB 9 -# define MAX_FAC_PER_LIMB 1000000000UL -#elif BITS_PER_MP_LIMB == 64 -# define MAX_DIG_PER_LIMB 19 -# define MAX_FAC_PER_LIMB 10000000000000000000ULL -#else -# error "mp_limb_t size " BITS_PER_MP_LIMB "not accounted for" #endif - -/* Local data structure. */ -static const mp_limb_t _tens_in_limb[MAX_DIG_PER_LIMB + 1] = -{ 0, 10, 100, - 1000, 10000, 100000L, - 1000000L, 10000000L, 100000000L, - 1000000000L -#if BITS_PER_MP_LIMB > 32 - , 10000000000ULL, 100000000000ULL, - 1000000000000ULL, 10000000000000ULL, 100000000000000ULL, - 1000000000000000ULL, 10000000000000000ULL, 100000000000000000ULL, - 1000000000000000000ULL, 10000000000000000000ULL -#endif -#if BITS_PER_MP_LIMB > 64 - #error "Need to expand tens_in_limb table to" MAX_DIG_PER_LIMB -#endif -}; - -#ifndef howmany -#define howmany(x,y) (((x)+((y)-1))/(y)) -#endif -#define SWAP(x, y) ({ typeof(x) _tmp = x; x = y; y = _tmp; }) - -#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG) -#define HEXNDIG ((MAX_EXP - MIN_EXP + 7) / 8 + 2 * MANT_DIG) -#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB) - -#define RETURN(val,end) \ - do { if (endptr != NULL) *endptr = (STRING_TYPE *) (end); \ - return val; } while (0) - -/* Maximum size necessary for mpn integers to hold floating point numbers. */ -#define MPNSIZE (howmany (MAX_EXP + 2 * MANT_DIG, BITS_PER_MP_LIMB) \ - + 2) -/* Declare an mpn integer variable that big. */ -#define MPN_VAR(name) mp_limb_t name[MPNSIZE]; mp_size_t name##size -/* Copy an mpn integer value. */ -#define MPN_ASSIGN(dst, src) \ - memcpy (dst, src, (dst##size = src##size) * sizeof (mp_limb_t)) - - -/* Return a floating point number of the needed type according to the given - multi-precision number after possible rounding. */ -static FLOAT -round_and_return (mp_limb_t *retval, int exponent, int negative, - mp_limb_t round_limb, mp_size_t round_bit, int more_bits) -{ - if (exponent < MIN_EXP - 1) - { - mp_size_t shift = MIN_EXP - 1 - exponent; - - if (shift > MANT_DIG) - { - __set_errno (EDOM); - return 0.0; - } - - more_bits |= (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0; - if (shift == MANT_DIG) - /* This is a special case to handle the very seldom case where - the mantissa will be empty after the shift. */ - { - int i; - - round_limb = retval[RETURN_LIMB_SIZE - 1]; - round_bit = (MANT_DIG - 1) % BITS_PER_MP_LIMB; - for (i = 0; i < RETURN_LIMB_SIZE; ++i) - more_bits |= retval[i] != 0; - MPN_ZERO (retval, RETURN_LIMB_SIZE); - } - else if (shift >= BITS_PER_MP_LIMB) - { - int i; - - round_limb = retval[(shift - 1) / BITS_PER_MP_LIMB]; - round_bit = (shift - 1) % BITS_PER_MP_LIMB; - for (i = 0; i < (shift - 1) / BITS_PER_MP_LIMB; ++i) - more_bits |= retval[i] != 0; - more_bits |= ((round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) - != 0); - - (void) __mpn_rshift (retval, &retval[shift / BITS_PER_MP_LIMB], - RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB), - shift % BITS_PER_MP_LIMB); - MPN_ZERO (&retval[RETURN_LIMB_SIZE - (shift / BITS_PER_MP_LIMB)], - shift / BITS_PER_MP_LIMB); - } - else if (shift > 0) - { - round_limb = retval[0]; - round_bit = shift - 1; - (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, shift); - } - /* This is a hook for the m68k long double format, where the - exponent bias is the same for normalized and denormalized - numbers. */ -#ifndef DENORM_EXP -# define DENORM_EXP (MIN_EXP - 2) -#endif - exponent = DENORM_EXP; - } - - if ((round_limb & (((mp_limb_t) 1) << round_bit)) != 0 - && (more_bits || (retval[0] & 1) != 0 - || (round_limb & ((((mp_limb_t) 1) << round_bit) - 1)) != 0)) - { - mp_limb_t cy = __mpn_add_1 (retval, retval, RETURN_LIMB_SIZE, 1); - - if (((MANT_DIG % BITS_PER_MP_LIMB) == 0 && cy) || - ((MANT_DIG % BITS_PER_MP_LIMB) != 0 && - (retval[RETURN_LIMB_SIZE - 1] - & (((mp_limb_t) 1) << (MANT_DIG % BITS_PER_MP_LIMB))) != 0)) - { - ++exponent; - (void) __mpn_rshift (retval, retval, RETURN_LIMB_SIZE, 1); - retval[RETURN_LIMB_SIZE - 1] - |= ((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB); - } - else if (exponent == DENORM_EXP - && (retval[RETURN_LIMB_SIZE - 1] - & (((mp_limb_t) 1) << ((MANT_DIG - 1) % BITS_PER_MP_LIMB))) - != 0) - /* The number was denormalized but now normalized. */ - exponent = MIN_EXP - 1; - } - - if (exponent > MAX_EXP) - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - - return MPN2FLOAT (retval, exponent, negative); -} - - -/* Read a multi-precision integer starting at STR with exactly DIGCNT digits - into N. Return the size of the number limbs in NSIZE at the first - character od the string that is not part of the integer as the function - value. If the EXPONENT is small enough to be taken as an additional - factor for the resulting number (see code) multiply by it. */ -static const STRING_TYPE * -str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize, - int *exponent -#ifndef USE_WIDE_CHAR - , const char *decimal, size_t decimal_len, const char *thousands -#endif - - ) -{ - /* Number of digits for actual limb. */ - int cnt = 0; - mp_limb_t low = 0; - mp_limb_t start; - - *nsize = 0; - assert (digcnt > 0); - do - { - if (cnt == MAX_DIG_PER_LIMB) - { - if (*nsize == 0) - { - n[0] = low; - *nsize = 1; - } - else - { - mp_limb_t cy; - cy = __mpn_mul_1 (n, n, *nsize, MAX_FAC_PER_LIMB); - cy += __mpn_add_1 (n, n, *nsize, low); - if (cy != 0) - { - n[*nsize] = cy; - ++(*nsize); - } - } - cnt = 0; - low = 0; - } - - /* There might be thousands separators or radix characters in - the string. But these all can be ignored because we know the - format of the number is correct and we have an exact number - of characters to read. */ -#ifdef USE_WIDE_CHAR - if (*str < L'0' || *str > L'9') - ++str; -#else - if (*str < '0' || *str > '9') - { - int inner = 0; - if (thousands != NULL && *str == *thousands - && ({ for (inner = 1; thousands[inner] != '\0'; ++inner) - if (thousands[inner] != str[inner]) - break; - thousands[inner] == '\0'; })) - str += inner; - else - str += decimal_len; - } -#endif - low = low * 10 + *str++ - L_('0'); - ++cnt; - } - while (--digcnt > 0); - - if (*exponent > 0 && cnt + *exponent <= MAX_DIG_PER_LIMB) - { - low *= _tens_in_limb[*exponent]; - start = _tens_in_limb[cnt + *exponent]; - *exponent = 0; - } - else - start = _tens_in_limb[cnt]; - - if (*nsize == 0) - { - n[0] = low; - *nsize = 1; - } - else - { - mp_limb_t cy; - cy = __mpn_mul_1 (n, n, *nsize, start); - cy += __mpn_add_1 (n, n, *nsize, low); - if (cy != 0) - n[(*nsize)++] = cy; - } - - return str; -} - - -/* Shift {PTR, SIZE} COUNT bits to the left, and fill the vacated bits - with the COUNT most significant bits of LIMB. - - Tege doesn't like this function so I have to write it here myself. :) - --drepper */ -static inline void -__attribute ((always_inline)) -__mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count, - mp_limb_t limb) -{ - if (__builtin_constant_p (count) && count == BITS_PER_MP_LIMB) - { - /* Optimize the case of shifting by exactly a word: - just copy words, with no actual bit-shifting. */ - mp_size_t i; - for (i = size - 1; i > 0; --i) - ptr[i] = ptr[i - 1]; - ptr[0] = limb; - } - else - { - (void) __mpn_lshift (ptr, ptr, size, count); - ptr[0] |= limb >> (BITS_PER_MP_LIMB - count); - } -} - - #define INTERNAL(x) INTERNAL1(x) #define INTERNAL1(x) __##x##_internal -/* This file defines a function to check for correct grouping. */ -#include "grouping.h" - -/* Return a floating point number with the value of the given string NPTR. - Set *ENDPTR to the character after the last used one. If the number is - smaller than the smallest representable number, set `errno' to ERANGE and - return 0.0. If the number is too big to be represented, set `errno' to - ERANGE and return HUGE_VAL with the appropriate sign. */ FLOAT -INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM) +INTERNAL (STRTOF) (nptr, endptr, group) const STRING_TYPE *nptr; STRING_TYPE **endptr; int group; - LOCALE_PARAM_DECL { - int negative; /* The sign of the number. */ - MPN_VAR (num); /* MP representation of the number. */ - int exponent; /* Exponent of the number. */ - - /* Numbers starting `0X' or `0x' have to be processed with base 16. */ - int base = 10; - - /* When we have to compute fractional digits we form a fraction with a - second multi-precision number (and we sometimes need a second for - temporary results). */ - MPN_VAR (den); - - /* Representation for the return value. */ - mp_limb_t retval[RETURN_LIMB_SIZE]; - /* Number of bits currently in result value. */ - int bits; - - /* Running pointer after the last character processed in the string. */ - const STRING_TYPE *cp, *tp; - /* Start of significant part of the number. */ - const STRING_TYPE *startp, *start_of_digits; - /* Points at the character following the integer and fractional digits. */ - const STRING_TYPE *expp; - /* Total number of digit and number of digits in integer part. */ - int dig_no, int_no, lead_zero; - /* Contains the last character read. */ - CHAR_TYPE c; - -/* We should get wint_t from <stddef.h>, but not all GCC versions define it - there. So define it ourselves if it remains undefined. */ -#ifndef _WINT_T - typedef unsigned int wint_t; -#endif - /* The radix character of the current locale. */ -#ifdef USE_WIDE_CHAR - wchar_t decimal; -#else - const char *decimal; - size_t decimal_len; -#endif - /* The thousands character of the current locale. */ -#ifdef USE_WIDE_CHAR - wchar_t thousands = L'\0'; -#else - const char *thousands = NULL; -#endif - /* The numeric grouping specification of the current locale, - in the format described in <locale.h>. */ - const char *grouping; - /* Used in several places. */ - int cnt; - -#ifdef USE_IN_EXTENDED_LOCALE_MODEL - struct locale_data *current = loc->__locales[LC_NUMERIC]; -#endif - - if (group) - { - grouping = _NL_CURRENT (LC_NUMERIC, GROUPING); - if (*grouping <= 0 || *grouping == CHAR_MAX) - grouping = NULL; - else - { - /* Figure out the thousands separator character. */ -#ifdef USE_WIDE_CHAR - thousands = _NL_CURRENT_WORD (LC_NUMERIC, - _NL_NUMERIC_THOUSANDS_SEP_WC); - if (thousands == L'\0') - grouping = NULL; -#else - thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP); - if (*thousands == '\0') - { - thousands = NULL; - grouping = NULL; - } -#endif - } - } - else - grouping = NULL; - - /* Find the locale's decimal point character. */ -#ifdef USE_WIDE_CHAR - decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC); - assert (decimal != L'\0'); -# define decimal_len 1 -#else - decimal = _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT); - decimal_len = strlen (decimal); - assert (decimal_len > 0); -#endif - - /* Prepare number representation. */ - exponent = 0; - negative = 0; - bits = 0; - - /* Parse string to get maximal legal prefix. We need the number of - characters of the integer part, the fractional part and the exponent. */ - cp = nptr - 1; - /* Ignore leading white space. */ - do - c = *++cp; - while (ISSPACE (c)); - - /* Get sign of the result. */ - if (c == L_('-')) - { - negative = 1; - c = *++cp; - } - else if (c == L_('+')) - c = *++cp; - - /* Return 0.0 if no legal string is found. - No character is used even if a sign was found. */ -#ifdef USE_WIDE_CHAR - if (c == (wint_t) decimal - && (wint_t) cp[1] >= L'0' && (wint_t) cp[1] <= L'9') - { - /* We accept it. This funny construct is here only to indent - the code directly. */ - } -#else - for (cnt = 0; decimal[cnt] != '\0'; ++cnt) - if (cp[cnt] != decimal[cnt]) - break; - if (decimal[cnt] == '\0' && cp[cnt] >= '0' && cp[cnt] <= '9') - { - /* We accept it. This funny construct is here only to indent - the code directly. */ - } -#endif - else if (c < L_('0') || c > L_('9')) - { - /* Check for `INF' or `INFINITY'. */ - if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0) - { - /* Return +/- infinity. */ - if (endptr != NULL) - *endptr = (STRING_TYPE *) - (cp + (STRNCASECMP (cp + 3, L_("inity"), 5) == 0 - ? 8 : 3)); - - return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL; - } - - if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0) - { - /* Return NaN. */ - FLOAT retval = NAN; - - cp += 3; - - /* Match `(n-char-sequence-digit)'. */ - if (*cp == L_('(')) - { - const STRING_TYPE *startp = cp; - do - ++cp; - while ((*cp >= L_('0') && *cp <= L_('9')) - || (TOLOWER (*cp) >= L_('a') && TOLOWER (*cp) <= L_('z')) - || *cp == L_('_')); - - if (*cp != L_(')')) - /* The closing brace is missing. Only match the NAN - part. */ - cp = startp; - else - { - /* This is a system-dependent way to specify the - bitmask used for the NaN. We expect it to be - a number which is put in the mantissa of the - number. */ - STRING_TYPE *endp; - unsigned long long int mant; - - mant = STRTOULL (startp + 1, &endp, 0); - if (endp == cp) - SET_MANTISSA (retval, mant); - } - } - - if (endptr != NULL) - *endptr = (STRING_TYPE *) cp; - - return retval; - } - - /* It is really a text we do not recognize. */ - RETURN (0.0, nptr); - } - - /* First look whether we are faced with a hexadecimal number. */ - if (c == L_('0') && TOLOWER (cp[1]) == L_('x')) - { - /* Okay, it is a hexa-decimal number. Remember this and skip - the characters. BTW: hexadecimal numbers must not be - grouped. */ - base = 16; - cp += 2; - c = *cp; - grouping = NULL; - } - - /* Record the start of the digits, in case we will check their grouping. */ - start_of_digits = startp = cp; - - /* Ignore leading zeroes. This helps us to avoid useless computations. */ -#ifdef USE_WIDE_CHAR - while (c == L'0' || ((wint_t) thousands != L'\0' && c == (wint_t) thousands)) - c = *++cp; - |
