1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-29 11:41:21 +03:00
This commit is contained in:
Jakub Jelinek
2007-07-12 18:26:36 +00:00
parent 7d58530341
commit 0ecb606cb6
6215 changed files with 494638 additions and 305010 deletions

View File

@ -1,5 +1,6 @@
/* Convert string representing a number to float value, using given locale.
Copyright (C) 1997,98,2002, 2004 Free Software Foundation, Inc.
Copyright (C) 1997,1998,2002,2004,2005,2006,2007
Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@ -28,6 +29,7 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
`strtof.c', `wcstod.c', `wcstold.c', and `wcstof.c' to produce the
`long double' and `float' versions of the reader. */
#ifndef FLOAT
# include <math_ldbl_opt.h>
# define FLOAT double
# define FLT DBL
# ifdef USE_WIDE_CHAR
@ -68,8 +70,8 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
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 "gmp-impl.h"
#include "longlong.h"
#include "fpioconst.h"
#define NDEBUG 1
@ -100,7 +102,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
# 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 TOLOWER_C(Ch) __towlower_l ((Ch), _nl_C_locobj_ptr)
# define STRNCASECMP(S1, S2, N) \
__wcsncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
# define STRTOULL(S, E, B) ____wcstoull_l_internal ((S), (E), (B), 0, loc)
#else
# define STRING_TYPE char
@ -110,7 +114,9 @@ extern unsigned long long int ____strtoull_l_internal (const char *, char **,
# 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 TOLOWER_C(Ch) __tolower_l ((Ch), _nl_C_locobj_ptr)
# define STRNCASECMP(S1, S2, N) \
__strncasecmp_l ((S1), (S2), (N), _nl_C_locobj_ptr)
# define STRTOULL(S, E, B) ____strtoull_l_internal ((S), (E), (B), 0, loc)
#endif
@ -402,6 +408,9 @@ __mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
#define INTERNAL(x) INTERNAL1(x)
#define INTERNAL1(x) __##x##_internal
#ifndef ____STRTOF_INTERNAL
# define ____STRTOF_INTERNAL INTERNAL (__STRTOF)
#endif
/* This file defines a function to check for correct grouping. */
#include "grouping.h"
@ -413,7 +422,7 @@ __mpn_lshift_1 (mp_limb_t *ptr, mp_size_t size, unsigned int count,
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, loc)
____STRTOF_INTERNAL (nptr, endptr, group, loc)
const STRING_TYPE *nptr;
STRING_TYPE **endptr;
int group;
@ -554,7 +563,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
else if (c < L_('0') || c > L_('9'))
{
/* Check for `INF' or `INFINITY'. */
if (TOLOWER (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
if (TOLOWER_C (c) == L_('i') && STRNCASECMP (cp, L_("inf"), 3) == 0)
{
/* Return +/- infinity. */
if (endptr != NULL)
@ -565,7 +574,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
}
if (TOLOWER (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
if (TOLOWER_C (c) == L_('n') && STRNCASECMP (cp, L_("nan"), 3) == 0)
{
/* Return NaN. */
FLOAT retval = NAN;
@ -642,10 +651,11 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
if (c != '0')
{
for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
if (c != thousands[cnt])
if (thousands[cnt] != cp[cnt])
break;
if (thousands[cnt] != '\0')
break;
cp += cnt - 1;
}
c = *++cp;
}
@ -654,20 +664,29 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
/* If no other digit but a '0' is found the result is 0.0.
Return current read pointer. */
if ((c < L_('0') || c > L_('9'))
&& (base == 16 && (c < (CHAR_TYPE) TOLOWER (L_('a'))
|| c > (CHAR_TYPE) TOLOWER (L_('f'))))
if (!((c >= L_('0') && c <= L_('9'))
|| (base == 16 && ((CHAR_TYPE) TOLOWER (c) >= L_('a')
&& (CHAR_TYPE) TOLOWER (c) <= L_('f')))
|| (
#ifdef USE_WIDE_CHAR
&& c != (wint_t) decimal
c == (wint_t) decimal
#else
&& ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
if (decimal[cnt] != cp[cnt])
break;
decimal[cnt] != '\0'; })
({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
if (decimal[cnt] != cp[cnt])
break;
decimal[cnt] == '\0'; })
#endif
&& (base == 16 && (cp == start_of_digits
|| (CHAR_TYPE) TOLOWER (c) != L_('p')))
&& (base != 16 && (CHAR_TYPE) TOLOWER (c) != L_('e')))
/* '0x.' alone is not a valid hexadecimal number.
'.' alone is not valid either, but that has been checked
already earlier. */
&& (base != 16
|| cp != start_of_digits
|| (cp[decimal_len] >= L_('0') && cp[decimal_len] <= L_('9'))
|| ((CHAR_TYPE) TOLOWER (cp[decimal_len]) >= L_('a')
&& (CHAR_TYPE) TOLOWER (cp[decimal_len]) <= L_('f'))))
|| (base == 16 && (cp != start_of_digits
&& (CHAR_TYPE) TOLOWER (c) == L_('p')))
|| (base != 16 && (CHAR_TYPE) TOLOWER (c) == L_('e'))))
{
#ifdef USE_WIDE_CHAR
tp = __correctly_grouped_prefixwc (start_of_digits, cp, thousands,
@ -707,13 +726,14 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
break;
if (thousands[cnt] != '\0')
break;
cp += cnt - 1;
}
#endif
}
c = *++cp;
}
if (grouping && dig_no > 0)
if (grouping && cp > start_of_digits)
{
/* Check the grouping of the digits. */
#ifdef USE_WIDE_CHAR
@ -751,13 +771,15 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
}
}
/* We have the number digits in the integer part. Whether these are all or
any is really a fractional digit will be decided later. */
/* We have the number of digits in the integer part. Whether these
are all or any is really a fractional digit will be decided
later. */
int_no = dig_no;
lead_zero = int_no == 0 ? -1 : 0;
/* Read the fractional digits. A special case are the 'american style'
numbers like `16.' i.e. with decimal but without trailing digits. */
/* Read the fractional digits. A special case are the 'american
style' numbers like `16.' i.e. with decimal point but without
trailing digits. */
if (
#ifdef USE_WIDE_CHAR
c == (wint_t) decimal
@ -807,15 +829,16 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
if (base == 16)
exp_limit = (exp_negative ?
-MIN_EXP + MANT_DIG + 4 * int_no :
MAX_EXP - 4 * int_no + lead_zero);
MAX_EXP - 4 * int_no + 4 * lead_zero + 3);
else
exp_limit = (exp_negative ?
-MIN_10_EXP + MANT_DIG + int_no :
MAX_10_EXP - int_no + lead_zero);
MAX_10_EXP - int_no + lead_zero + 1);
do
{
exponent *= 10;
exponent += c - L_('0');
if (exponent > exp_limit)
/* The exponent is too large/small to represent a valid
@ -845,7 +868,6 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
/* NOTREACHED */
}
exponent += c - L_('0');
c = *++cp;
}
while (c >= L_('0') && c <= L_('9'));
@ -880,7 +902,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
--expp;
--dig_no;
--int_no;
++exponent;
exponent += base == 16 ? 4 : 1;
}
while (dig_no > 0 && exponent < 0);
@ -1553,7 +1575,7 @@ INTERNAL (__STRTOF) (nptr, endptr, group, loc)
/* NOTREACHED */
}
#if defined _LIBC && !defined USE_WIDE_CHAR
libc_hidden_def (INTERNAL (__STRTOF))
libc_hidden_def (____STRTOF_INTERNAL)
#endif
/* External user entry point. */
@ -1567,6 +1589,23 @@ __STRTOF (nptr, endptr, loc)
STRING_TYPE **endptr;
__locale_t loc;
{
return INTERNAL (__STRTOF) (nptr, endptr, 0, loc);
return ____STRTOF_INTERNAL (nptr, endptr, 0, loc);
}
weak_alias (__STRTOF, STRTOF)
#ifdef LONG_DOUBLE_COMPAT
# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_1)
# ifdef USE_WIDE_CHAR
compat_symbol (libc, __wcstod_l, __wcstold_l, GLIBC_2_1);
# else
compat_symbol (libc, __strtod_l, __strtold_l, GLIBC_2_1);
# endif
# endif
# if LONG_DOUBLE_COMPAT(libc, GLIBC_2_3)
# ifdef USE_WIDE_CHAR
compat_symbol (libc, wcstod_l, wcstold_l, GLIBC_2_3);
# else
compat_symbol (libc, strtod_l, strtold_l, GLIBC_2_3);
# endif
# endif
#endif