mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-30 22:43:12 +03:00
Thu Mar 16 00:04:41 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* locale/C-ctype.c: New correct data generated by drepper. * Rules: Don't use $(libc.a). Parsing of grouped numbers contributed by Ulrich Drepper. * stdlib/strtol.c (__strtol_internal): Renamed from strtol. Take new flag arg; if nonzero, parse locale-dependent thousands grouping and interpret only the prefix that is correctly grouped. (strtol): Define this to call _strtol_internal with zero for the flag. Use a weak symbol for the definition. * stdlib/strtod.c (strtod, __strtod_internal): Likewise. Check for the exponent of the number overflowing the float format. * stdlib/stdlib.h (__strtof, __strtold): Declarations removed. (__strto{f,d,ld,l,ul,q,uq}_internal): Declare these functions. [__OPTIMIZE__]: Define inline functions calling those. * stdlib/grouping.h: New file, written by drepper. * stdlib/Makefile (distribute): Add grouping.h. * stdio/vfscanf.c: Grok %' modifier to numeric conversions. Call __strtoX_internal with the grouping flag set iff the modifier is present. Wed Mar 15 00:40:54 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * sysdeps/generic/memchr.c: Fix typos: limit.h -> limits.h. * mach/Machrules: Produce static deps for all object flavors. [interface-library]: Remove all these variables and rules. ($(interface-library)-routines): Define this variable. (extra-libs): Append $(interface-library) to this. * mach/Makefile (interface-library): Omit .a suffix. * hurd/Makefile: Likewise. Tue Mar 14 23:40:31 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu> * stdio/internals.c (flushbuf): If !FLUSH_ONLY, don't skip out early if no new data in buffer after priming. * Makerules (object-suffixes, libtypes): Move all these variables to Makeconfig. * Makeconfig (object-suffixes, libtypes): Moved here from Makerules. * Makerules (build-extra-lib): New canned sequence. * sysdeps/mach/hurd/euidaccess.c: Include fcntl.h. Declare ERR; fix uses of FILE and PORT. Remove bogus weak alias for `access'. * sysdeps/mach/hurd/dirfd.c: Include hurd/fd.h and errno.h. Add missing semicolon. * sysdeps/mach/hurd/opendir.c: Include hurd/fd.h. Use a `struct hurd_fd *' temp var, since DIRP->__fd is a `void *'. * sysdeps/mach/hurd/readdir.c: Include hurd/fd.h. * stdlib/wcstombs.c: #if 0 out code for non-ASCII chars until the locale data format is implemented. * sysdeps/mach/hurd/i386/trampoline.c (_hurd_setup_sighandler): Pass &__sigreturn on the stack to the trampoline code, so it is not position-dependent. * stdio/printf_fp.c (NDEBUG): Define this to disable assert. Don't include <stdarg.h>. (__printf_fp): Last arg ARGS is now `const void **const'; dereference ARGS[0] instead of using va_arg. * locale/setlocale.c: In LC_ALL case, initialize CATEGORY before loop to install data. * locale/loadlocale.c (_nl_category_num_items): Use _NL_ITEM_INDEX to extract number from item code. (_nl_load_locale): Close the descriptor when finished. * malloc/realloc.c (_realloc_internal): Call _malloc_internal in place of malloc. * time/tzfile.c (__tzfile_default): Initialize RULE_STDOFF to zero.
This commit is contained in:
149
stdlib/strtod.c
149
stdlib/strtod.c
@ -102,10 +102,11 @@ static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
|
||||
#define RETURN_LIMB_SIZE howmany (MANT_DIG, BITS_PER_MP_LIMB)
|
||||
|
||||
#define RETURN(val,end) \
|
||||
do { if (endptr != 0) *endptr = (char *) end; return val; } while (0)
|
||||
do { if (endptr != 0) *endptr = (char *) (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)
|
||||
#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 name[MPNSIZE]; mp_size_t name##size
|
||||
/* Copy an mpn integer value. */
|
||||
@ -276,15 +277,23 @@ __mpn_lshift_1 (mp_limb *ptr, mp_size_t size, unsigned int count, mp_limb limb)
|
||||
}
|
||||
|
||||
|
||||
#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 approriate sign. */
|
||||
FLOAT
|
||||
STRTOF (nptr, endptr)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
INTERNAL (STRTOF) (nptr, endptr, group)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
int group;
|
||||
{
|
||||
int negative; /* The sign of the number. */
|
||||
MPN_VAR (num); /* MP representation of the number. */
|
||||
@ -301,9 +310,9 @@ STRTOF (nptr, endptr)
|
||||
int bits;
|
||||
|
||||
/* Running pointer after the last character processed in the string. */
|
||||
const char *cp;
|
||||
const char *cp, *tp;
|
||||
/* Start of significant part of the number. */
|
||||
const char *startp;
|
||||
const char *startp, *start_of_digits;
|
||||
/* Points at the character following the integer and fractional digits. */
|
||||
const char *expp;
|
||||
/* Total number of digit and number of digits in integer part. */
|
||||
@ -313,60 +322,29 @@ STRTOF (nptr, endptr)
|
||||
|
||||
/* The radix character of the current locale. */
|
||||
wchar_t decimal;
|
||||
#ifdef USE_GROUPING
|
||||
/* The thousands character of the current locale. */
|
||||
wchar_t thousands;
|
||||
/* The numeric grouping specification of the current locale,
|
||||
in the format described in <locale.h>. */
|
||||
const char *grouping;
|
||||
|
||||
/* Check the grouping of the integer part at [BEGIN,END).
|
||||
Return zero iff a separator is found out of place. */
|
||||
int grouping_ok (const char *begin, const char *end)
|
||||
if (group)
|
||||
{
|
||||
if (grouping)
|
||||
while (end > begin)
|
||||
{
|
||||
const char *p = end;
|
||||
do
|
||||
--p;
|
||||
while (*p != thousands && p > begin);
|
||||
if (end - 1 - p != *grouping++)
|
||||
return 0; /* Wrong number of digits in this group. */
|
||||
end = p; /* Correct group; trim it off the end. */
|
||||
|
||||
if (*grouping == 0)
|
||||
--grouping; /* Same grouping repeats in next iteration. */
|
||||
else if (*grouping == CHAR_MAX || *grouping < 0)
|
||||
{
|
||||
/* No further grouping allowed. */
|
||||
while (end > begin)
|
||||
if (*--end == thousands)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/* Return with no conversion if the grouping of [STARTP,CP) is bad. */
|
||||
#define CHECK_GROUPING if (! grouping_ok (startp, cp)) RETURN (0.0, nptr); else
|
||||
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping <= 0 || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
else
|
||||
{
|
||||
/* Figure out the thousands seperator character. */
|
||||
if (mbtowc (&thousands_sep, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
|
||||
strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
|
||||
thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
if (thousands == L'\0')
|
||||
grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
|
||||
if (*grouping <= 0 || *grouping == CHAR_MAX)
|
||||
grouping = NULL;
|
||||
else
|
||||
{
|
||||
/* Figure out the thousands separator character. */
|
||||
if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
|
||||
strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
|
||||
thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||
if (thousands == L'\0')
|
||||
grouping = NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define grouping NULL
|
||||
#define thousands L'\0'
|
||||
#define CHECK_GROUPING ((void) 0)
|
||||
#endif
|
||||
else
|
||||
grouping = NULL;
|
||||
|
||||
/* Find the locale's decimal point character. */
|
||||
if (mbtowc (&decimal, _NL_CURRENT (LC_NUMERIC, DECIMAL_POINT),
|
||||
@ -402,18 +380,21 @@ STRTOF (nptr, endptr)
|
||||
RETURN (0.0, nptr);
|
||||
|
||||
/* Record the start of the digits, in case we will check their grouping. */
|
||||
startp = cp;
|
||||
start_of_digits = startp = cp;
|
||||
|
||||
/* Ignore leading zeroes. This helps us to avoid useless computations. */
|
||||
while (c == '0' || (thousands != L'\0' && c == thousands))
|
||||
c = *++cp;
|
||||
|
||||
CHECK_GROUPING;
|
||||
|
||||
/* If no other digit but a '0' is found the result is 0.0.
|
||||
Return current read pointer. */
|
||||
if (!isdigit (c) && c != decimal)
|
||||
RETURN (0.0, cp);
|
||||
{
|
||||
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
|
||||
/* If TP is at the start of the digits, there was no correctly
|
||||
grouped prefix of the string; so no number found. */
|
||||
RETURN (0.0, tp == start_of_digits ? nptr : tp);
|
||||
}
|
||||
|
||||
/* Remember first significant digit and read following characters until the
|
||||
decimal point, exponent character or any non-FP number character. */
|
||||
@ -432,7 +413,37 @@ STRTOF (nptr, endptr)
|
||||
c = *++cp;
|
||||
}
|
||||
|
||||
CHECK_GROUPING;
|
||||
if (grouping && dig_no > 0)
|
||||
{
|
||||
/* Check the grouping of the digits. */
|
||||
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
|
||||
if (cp != tp)
|
||||
{
|
||||
/* Less than the entire string was correctly grouped. */
|
||||
|
||||
if (tp == start_of_digits)
|
||||
/* No valid group of numbers at all: no valid number. */
|
||||
RETURN (0.0, nptr);
|
||||
|
||||
if (tp < startp)
|
||||
/* The number is validly grouped, but consists
|
||||
only of zeroes. The whole value is zero. */
|
||||
RETURN (0.0, tp);
|
||||
|
||||
/* Recompute DIG_NO so we won't read more digits than
|
||||
are properly grouped. */
|
||||
cp = tp;
|
||||
dig_no = 0;
|
||||
for (tp = startp; tp < cp; ++tp)
|
||||
if (isdigit (*tp))
|
||||
++dig_no;
|
||||
|
||||
int_no = dig_no;
|
||||
lead_zero = 0;
|
||||
|
||||
goto number_parsed;
|
||||
}
|
||||
}
|
||||
|
||||
if (dig_no >= NDIG)
|
||||
/* Too many digits to be representable. Assigning this to EXPONENT
|
||||
@ -528,6 +539,8 @@ STRTOF (nptr, endptr)
|
||||
assert (dig_no >= int_no);
|
||||
}
|
||||
|
||||
number_parsed:
|
||||
|
||||
/* The whole string is parsed. Store the address of the next character. */
|
||||
if (endptr)
|
||||
*endptr = (char *) cp;
|
||||
@ -546,7 +559,7 @@ STRTOF (nptr, endptr)
|
||||
exponent -= incr;
|
||||
}
|
||||
|
||||
if (int_no + exponent > MAX_10_EXP)
|
||||
if (int_no + exponent > MAX_10_EXP + 1)
|
||||
{
|
||||
errno = ERANGE;
|
||||
return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
|
||||
@ -607,6 +620,14 @@ STRTOF (nptr, endptr)
|
||||
count_leading_zeros (bits, num[numsize - 1]);
|
||||
bits = numsize * BITS_PER_MP_LIMB - bits;
|
||||
|
||||
/* Now we know the exponent of the number in base two.
|
||||
Check it against the maximum possible exponent. */
|
||||
if (bits > MAX_EXP)
|
||||
{
|
||||
errno = ERANGE;
|
||||
return negative ? -FLOAT_HUGE_VAL : FLOAT_HUGE_VAL;
|
||||
}
|
||||
|
||||
/* We have already the first BITS bits of the result. Together with
|
||||
the information whether more non-zero bits follow this is enough
|
||||
to determine the result. */
|
||||
@ -1059,3 +1080,15 @@ STRTOF (nptr, endptr)
|
||||
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
/* External user entry point. */
|
||||
|
||||
weak_symbol (STRTOF)
|
||||
|
||||
FLOAT
|
||||
STRTOF (nptr, endptr)
|
||||
const char *nptr;
|
||||
char **endptr;
|
||||
{
|
||||
return INTERNAL (STRTOF) (nptr, endptr, 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user