mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-03 00:10:10 +00:00
Update.
2000-06-29 Ulrich Drepper <drepper@redhat.com> * stdlib/grouping.h: Correctly handle multibyte thousands separator and decimal point. * stdlib/stdtod.c: Likewise. * sysdeps/generic/strtol.c: Likewise. * locale/categories.def: Add entries for wide character decimal point and thousands separator in numeric and monetary category. 2000-06-28 Ulrich Drepper <drepper@redhat.com> * stdio-common/printf_fp.c (__printf_fp): Remove unnecessary second definition and initialization of decimal. * libio/libio.h (struct _IO_cookie_file): Move struct type defintion out. * libio/libioP.h (struct _IO_cookie_file): Move struct type defintion in. (_IO_JUMPS): Don't cast THIS--expect arg to be a (struct _IO_FILE_plus *). (_IO_iter_next, _IO_iter_file): _IO_ITER is now (struct _IO_FILE_plus *). (_IO_check_libio): Set user-visible handles to (struct _IO_FILE_plus *).
This commit is contained in:
parent
23335dcd5f
commit
a748c3c64c
30
ChangeLog
30
ChangeLog
@ -1,9 +1,27 @@
|
|||||||
|
2000-06-29 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* stdlib/grouping.h: Correctly handle multibyte thousands
|
||||||
|
separator and decimal point.
|
||||||
|
* stdlib/stdtod.c: Likewise.
|
||||||
|
* sysdeps/generic/strtol.c: Likewise.
|
||||||
|
|
||||||
|
* locale/categories.def: Add entries for wide character decimal point
|
||||||
|
and thousands separator in numeric and monetary category.
|
||||||
|
|
||||||
|
2000-06-28 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* stdio-common/printf_fp.c (__printf_fp): Remove unnecessary
|
||||||
|
second definition and initialization of decimal.
|
||||||
|
|
||||||
2000-06-28 Greg McGary <greg@mcgary.org>
|
2000-06-28 Greg McGary <greg@mcgary.org>
|
||||||
|
|
||||||
* libio/libio.h (struct _IO_cookie_file): Move struct type defintion out.
|
* libio/libio.h (struct _IO_cookie_file): Move struct type defintion
|
||||||
|
out.
|
||||||
(_IO_FILE): Declare chain as (struct _IO_FILE_plus *).
|
(_IO_FILE): Declare chain as (struct _IO_FILE_plus *).
|
||||||
* libio/libioP.h (struct _IO_cookie_file): Move struct type defintion in.
|
* libio/libioP.h (struct _IO_cookie_file): Move struct type defintion
|
||||||
(_IO_JUMPS): Don't cast THIS--expect arg to be a (struct _IO_FILE_plus *).
|
in.
|
||||||
|
(_IO_JUMPS): Don't cast THIS--expect arg to be a
|
||||||
|
(struct _IO_FILE_plus *).
|
||||||
(_IO_JUMPS_FUNC): Express in terms of _IO_JUMPS, and add cast to
|
(_IO_JUMPS_FUNC): Express in terms of _IO_JUMPS, and add cast to
|
||||||
THIS, since _IO_JUMPS no longer does it implicitly.
|
THIS, since _IO_JUMPS no longer does it implicitly.
|
||||||
(_IO_file_init, _IO_old_file_init, _IO_new_file_init): Declare
|
(_IO_file_init, _IO_old_file_init, _IO_new_file_init): Declare
|
||||||
@ -18,10 +36,12 @@
|
|||||||
* libio/genops.c (_IO_link_in, _IO_un_link): Likewise.
|
* libio/genops.c (_IO_link_in, _IO_un_link): Likewise.
|
||||||
(_IO_flush_all, _IO_flush_all_linebuffered, _IO_unbuffer_write):
|
(_IO_flush_all, _IO_flush_all_linebuffered, _IO_unbuffer_write):
|
||||||
Declare iteration pointer as (struct _IO_FILE_plus *).
|
Declare iteration pointer as (struct _IO_FILE_plus *).
|
||||||
(_IO_iter_next, _IO_iter_file): _IO_ITER is now (struct _IO_FILE_plus *).
|
(_IO_iter_next, _IO_iter_file): _IO_ITER is now
|
||||||
|
(struct _IO_FILE_plus *).
|
||||||
* libio/stdfiles.c (_IO_list_all): Declare as (struct _IO_FILE_plus *).
|
* libio/stdfiles.c (_IO_list_all): Declare as (struct _IO_FILE_plus *).
|
||||||
* libio/oldstdfiles.c (_IO_list_all): Likewise.
|
* libio/oldstdfiles.c (_IO_list_all): Likewise.
|
||||||
(_IO_check_libio): Set user-visible handles to (struct _IO_FILE_plus *).
|
(_IO_check_libio): Set user-visible handles to
|
||||||
|
(struct _IO_FILE_plus *).
|
||||||
* libio/stdio.c (stdin, stdout, stderr): Set user-visible handles
|
* libio/stdio.c (stdin, stdout, stderr): Set user-visible handles
|
||||||
to (struct _IO_FILE_plus *).
|
to (struct _IO_FILE_plus *).
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Internal header for proving correct grouping in strings of numbers.
|
/* Internal header for proving correct grouping in strings of numbers.
|
||||||
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
|
||||||
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
|
Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -30,19 +30,24 @@
|
|||||||
|
|
||||||
static inline const STRING_TYPE *
|
static inline const STRING_TYPE *
|
||||||
correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
|
correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
|
||||||
wchar_t thousands, const char *grouping)
|
#ifdef USE_WIDE_CHAR
|
||||||
|
wchar_t thousands,
|
||||||
|
#else
|
||||||
|
const char *thousands,
|
||||||
|
#endif
|
||||||
|
const char *grouping)
|
||||||
{
|
{
|
||||||
|
#ifndef USE_WIDE_CHAR
|
||||||
|
size_t thousands_len;
|
||||||
|
int cnt;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (grouping == NULL)
|
if (grouping == NULL)
|
||||||
return end;
|
return end;
|
||||||
|
|
||||||
if (*grouping == '\0')
|
#ifndef USE_WIDE_CHAR
|
||||||
{
|
thousands_len = strlen (thousands);
|
||||||
/* No grouping allowed. Accept all characters up to the first
|
#endif
|
||||||
thousands separator. */
|
|
||||||
while (begin < end && *begin != thousands)
|
|
||||||
++begin;
|
|
||||||
return begin;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (end > begin)
|
while (end > begin)
|
||||||
{
|
{
|
||||||
@ -50,8 +55,23 @@ correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
|
|||||||
const char *gp = grouping;
|
const char *gp = grouping;
|
||||||
|
|
||||||
/* Check first group. */
|
/* Check first group. */
|
||||||
while (cp >= begin && (wchar_t) *cp != thousands)
|
while (cp >= begin)
|
||||||
--cp;
|
{
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
|
if (*cp == thousands)
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if (cp[thousands_len - 1] == *thousands)
|
||||||
|
{
|
||||||
|
for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != cp[thousands_len - 1 - cnt])
|
||||||
|
break;
|
||||||
|
if (thousands[cnt] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
--cp;
|
||||||
|
}
|
||||||
|
|
||||||
/* We allow the representation to contain no grouping at all even if
|
/* We allow the representation to contain no grouping at all even if
|
||||||
the locale specifies we can have grouping. */
|
the locale specifies we can have grouping. */
|
||||||
@ -93,8 +113,20 @@ correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* No more thousands separators are allowed to follow. */
|
/* No more thousands separators are allowed to follow. */
|
||||||
while (cp >= begin && (wchar_t) *cp != thousands)
|
while (cp >= begin)
|
||||||
--cp;
|
{
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
|
if (*cp == thousands)
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != cp[thousands_len - cnt - 1])
|
||||||
|
break;
|
||||||
|
if (thousands[cnt] == '\0')
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
--cp;
|
||||||
|
}
|
||||||
|
|
||||||
if (cp < begin)
|
if (cp < begin)
|
||||||
/* OK, only digits followed. */
|
/* OK, only digits followed. */
|
||||||
@ -105,8 +137,20 @@ correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
|
|||||||
/* Check the next group. */
|
/* Check the next group. */
|
||||||
const STRING_TYPE *group_end = cp;
|
const STRING_TYPE *group_end = cp;
|
||||||
|
|
||||||
while (cp >= begin && (wchar_t) *cp != thousands)
|
while (cp >= begin)
|
||||||
--cp;
|
{
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
|
if (*cp == thousands)
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != cp[thousands_len - cnt - 1])
|
||||||
|
break;
|
||||||
|
if (thousands[cnt] == '\0')
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
--cp;
|
||||||
|
}
|
||||||
|
|
||||||
if (cp < begin && group_end - cp <= (int) *gp)
|
if (cp < begin && group_end - cp <= (int) *gp)
|
||||||
/* Final group is correct. */
|
/* Final group is correct. */
|
||||||
|
194
stdlib/strtod.c
194
stdlib/strtod.c
@ -1,6 +1,6 @@
|
|||||||
/* Read decimal floating point numbers.
|
/* Read decimal floating point numbers.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
|
Copyright (C) 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc.
|
||||||
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
|
Contributed by Ulrich Drepper <drepper@gnu.org>, 1995.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -301,7 +301,12 @@ round_and_return (mp_limb_t *retval, int exponent, int negative,
|
|||||||
factor for the resulting number (see code) multiply by it. */
|
factor for the resulting number (see code) multiply by it. */
|
||||||
static inline const STRING_TYPE *
|
static inline const STRING_TYPE *
|
||||||
str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
|
str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
|
||||||
int *exponent)
|
int *exponent
|
||||||
|
#ifndef USE_WIDE_CHAR
|
||||||
|
, const char *decimal, size_t decimal_len, const char *thousands
|
||||||
|
#endif
|
||||||
|
|
||||||
|
)
|
||||||
{
|
{
|
||||||
/* Number of digits for actual limb. */
|
/* Number of digits for actual limb. */
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
@ -338,8 +343,22 @@ str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb_t *n, mp_size_t *nsize,
|
|||||||
the string. But these all can be ignored because we know the
|
the string. But these all can be ignored because we know the
|
||||||
format of the number is correct and we have an exact number
|
format of the number is correct and we have an exact number
|
||||||
of characters to read. */
|
of characters to read. */
|
||||||
while (*str < L_('0') || *str > L_('9'))
|
#ifdef USE_WIDE_CHAR
|
||||||
|
if (*str < L'0' || *str > L'9')
|
||||||
++str;
|
++str;
|
||||||
|
#else
|
||||||
|
if (*str < '0' || *str > '9')
|
||||||
|
{
|
||||||
|
if (thousands != NULL && *str == *thousands
|
||||||
|
&& ({ for (cnt == 1; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != str[cnt])
|
||||||
|
break;
|
||||||
|
thousands[cnt] == '\0'; }))
|
||||||
|
str += cnt;
|
||||||
|
else
|
||||||
|
str += decimal_len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
low = low * 10 + *str++ - L_('0');
|
low = low * 10 + *str++ - L_('0');
|
||||||
++cnt;
|
++cnt;
|
||||||
}
|
}
|
||||||
@ -451,12 +470,23 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
typedef unsigned int wint_t;
|
typedef unsigned int wint_t;
|
||||||
#endif
|
#endif
|
||||||
/* The radix character of the current locale. */
|
/* The radix character of the current locale. */
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
wchar_t decimal;
|
wchar_t decimal;
|
||||||
|
#else
|
||||||
|
const char *decimal;
|
||||||
|
size_t decimal_len;
|
||||||
|
#endif
|
||||||
/* The thousands character of the current locale. */
|
/* The thousands character of the current locale. */
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
wchar_t thousands = L'\0';
|
wchar_t thousands = L'\0';
|
||||||
|
#else
|
||||||
|
const char *thousands = NULL;
|
||||||
|
#endif
|
||||||
/* The numeric grouping specification of the current locale,
|
/* The numeric grouping specification of the current locale,
|
||||||
in the format described in <locale.h>. */
|
in the format described in <locale.h>. */
|
||||||
const char *grouping;
|
const char *grouping;
|
||||||
|
/* Used in several places. */
|
||||||
|
int cnt;
|
||||||
|
|
||||||
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
#ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||||
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
||||||
@ -470,21 +500,34 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Figure out the thousands separator character. */
|
/* Figure out the thousands separator character. */
|
||||||
thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
|
#ifdef USE_WIDE_CHAR
|
||||||
if (thousands == WEOF)
|
thousands = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||||
thousands = L'\0';
|
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||||
if (thousands == L'\0')
|
if (thousands == L'\0')
|
||||||
grouping = NULL;
|
grouping = NULL;
|
||||||
|
#else
|
||||||
|
thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||||
|
if (*thousands == '\0')
|
||||||
|
{
|
||||||
|
thousands = NULL;
|
||||||
|
grouping = NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
grouping = NULL;
|
grouping = NULL;
|
||||||
|
|
||||||
/* Find the locale's decimal point character. */
|
/* Find the locale's decimal point character. */
|
||||||
decimal = __btowc (*_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT));
|
#ifdef USE_WIDE_CHAR
|
||||||
if (decimal == WEOF)
|
decimal = _NL_CURRENT_WORD (LC_NUMERIC, _NL_NUMERIC_DECIMAL_POINT_WC);
|
||||||
decimal = L'.';
|
|
||||||
assert (decimal != L'\0');
|
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. */
|
/* Prepare number representation. */
|
||||||
exponent = 0;
|
exponent = 0;
|
||||||
@ -510,8 +553,23 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
|
|
||||||
/* Return 0.0 if no legal string is found.
|
/* Return 0.0 if no legal string is found.
|
||||||
No character is used even if a sign was found. */
|
No character is used even if a sign was found. */
|
||||||
if ((c < L_('0') || c > L_('9'))
|
#ifdef USE_WIDE_CHAR
|
||||||
&& ((wchar_t) c != decimal || cp[1] < L_('0') || cp[1] > L_('9')))
|
if (c == decimal && cp[1] >= L'0' && 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[1] >= '0' && cp[1] <= '9')
|
||||||
|
{
|
||||||
|
/* We accept it. This funny construct is here only to indent
|
||||||
|
the code directly. */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (c < L_('0') || c > L_('9'))
|
||||||
{
|
{
|
||||||
int matched = 0;
|
int matched = 0;
|
||||||
/* Check for `INF' or `INFINITY'. */
|
/* Check for `INF' or `INFINITY'. */
|
||||||
@ -588,16 +646,45 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
start_of_digits = startp = cp;
|
start_of_digits = startp = cp;
|
||||||
|
|
||||||
/* Ignore leading zeroes. This helps us to avoid useless computations. */
|
/* Ignore leading zeroes. This helps us to avoid useless computations. */
|
||||||
while (c == L_('0') || (thousands != L'\0' && (wchar_t) c == thousands))
|
#ifdef USE_WIDE_CHAR
|
||||||
|
while (c == L'0' || (thousands != L'\0' && c == thousands))
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
|
#else
|
||||||
|
if (thousands == NULL)
|
||||||
|
while (c == '0')
|
||||||
|
c = *++cp;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We also have the multibyte thousands string. */
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (c != '0')
|
||||||
|
{
|
||||||
|
for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (c != thousands[cnt])
|
||||||
|
break;
|
||||||
|
if (thousands[cnt] != '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
c = *++cp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* If no other digit but a '0' is found the result is 0.0.
|
/* If no other digit but a '0' is found the result is 0.0.
|
||||||
Return current read pointer. */
|
Return current read pointer. */
|
||||||
if ((c < L_('0') || c > L_('9')) &&
|
if ((c < L_('0') || c > L_('9'))
|
||||||
(base == 16 && (c < TOLOWER (L_('a')) || c > TOLOWER (L_('f')))) &&
|
&& (base == 16 && (c < TOLOWER (L_('a')) || c > TOLOWER (L_('f'))))
|
||||||
(wchar_t) c != decimal &&
|
#ifdef USE_WIDE_CHAR
|
||||||
(base == 16 && (cp == start_of_digits || TOLOWER (c) != L_('p'))) &&
|
&& c != decimal
|
||||||
(base != 16 && TOLOWER (c) != L_('e')))
|
#else
|
||||||
|
&& ({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
|
||||||
|
if (decimal[cnt] != cp[cnt])
|
||||||
|
break;
|
||||||
|
decimal[cnt] != '\0'; })
|
||||||
|
#endif
|
||||||
|
&& (base == 16 && (cp == start_of_digits || TOLOWER (c) != L_('p')))
|
||||||
|
&& (base != 16 && TOLOWER (c) != L_('e')))
|
||||||
{
|
{
|
||||||
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
|
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
|
||||||
/* If TP is at the start of the digits, there was no correctly
|
/* If TP is at the start of the digits, there was no correctly
|
||||||
@ -617,9 +704,25 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
if ((c >= L_('0') && c <= L_('9'))
|
if ((c >= L_('0') && c <= L_('9'))
|
||||||
|| (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
|
|| (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
|
||||||
++dig_no;
|
++dig_no;
|
||||||
else if (thousands == L'\0' || (wchar_t) c != thousands)
|
else
|
||||||
/* Not a digit or separator: end of the integer part. */
|
{
|
||||||
break;
|
#ifdef USE_WIDE_CHAR
|
||||||
|
if (thousands == L'\0' || c != thousands)
|
||||||
|
/* Not a digit or separator: end of the integer part. */
|
||||||
|
break;
|
||||||
|
#else
|
||||||
|
if (thousands == NULL)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != cp[cnt])
|
||||||
|
break;
|
||||||
|
if (thousands[cnt] != '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
c = *++cp;
|
c = *++cp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -667,9 +770,19 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
|
|
||||||
/* Read the fractional digits. A special case are the 'american style'
|
/* Read the fractional digits. A special case are the 'american style'
|
||||||
numbers like `16.' i.e. with decimal but without trailing digits. */
|
numbers like `16.' i.e. with decimal but without trailing digits. */
|
||||||
if ((wchar_t) c == decimal)
|
if (
|
||||||
|
#ifdef USE_WIDE_CHAR
|
||||||
|
c == decimal
|
||||||
|
#else
|
||||||
|
({ for (cnt = 0; decimal[cnt] != '\0'; ++cnt)
|
||||||
|
if (decimal[cnt] != cp[cnt])
|
||||||
|
break;
|
||||||
|
decimal[cnt] == '\0'; })
|
||||||
|
#endif
|
||||||
|
)
|
||||||
{
|
{
|
||||||
c = *++cp;
|
cp += decimal_len;
|
||||||
|
c = *cp;
|
||||||
while ((c >= L_('0') && c <= L_('9')) ||
|
while ((c >= L_('0') && c <= L_('9')) ||
|
||||||
(base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
|
(base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
|
||||||
{
|
{
|
||||||
@ -779,9 +892,24 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
if (lead_zero)
|
if (lead_zero)
|
||||||
{
|
{
|
||||||
/* Find the decimal point */
|
/* Find the decimal point */
|
||||||
while ((wchar_t) *startp != decimal)
|
#ifdef USE_WIDE_CHAR
|
||||||
|
while (*startp != decimal)
|
||||||
++startp;
|
++startp;
|
||||||
startp += lead_zero + 1;
|
#else
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
if (*startp == decimal[0])
|
||||||
|
{
|
||||||
|
for (cnt = 1; decimal[cnt] != '\0'; ++cnt)
|
||||||
|
if (decimal[cnt] != startp[cnt])
|
||||||
|
break;
|
||||||
|
if (decimal[cnt] == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++startp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
startp += lead_zero + decimal_len;
|
||||||
exponent -= base == 16 ? 4 * lead_zero : lead_zero;
|
exponent -= base == 16 ? 4 * lead_zero : lead_zero;
|
||||||
dig_no -= lead_zero;
|
dig_no -= lead_zero;
|
||||||
}
|
}
|
||||||
@ -828,8 +956,8 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
|
|
||||||
while (--dig_no > 0 && idx >= 0)
|
while (--dig_no > 0 && idx >= 0)
|
||||||
{
|
{
|
||||||
while (!ISXDIGIT (*startp))
|
if (!ISXDIGIT (*startp))
|
||||||
++startp;
|
startp += decimal_len;
|
||||||
if (ISDIGIT (*startp))
|
if (ISDIGIT (*startp))
|
||||||
val = *startp++ - L_('0');
|
val = *startp++ - L_('0');
|
||||||
else
|
else
|
||||||
@ -885,7 +1013,11 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
if (int_no > 0)
|
if (int_no > 0)
|
||||||
{
|
{
|
||||||
/* Read the integer part as a multi-precision number to NUM. */
|
/* Read the integer part as a multi-precision number to NUM. */
|
||||||
startp = str_to_mpn (startp, int_no, num, &numsize, &exponent);
|
startp = str_to_mpn (startp, int_no, num, &numsize, &exponent
|
||||||
|
#ifndef USE_WIDE_CHAR
|
||||||
|
, decimal, decimal_len, thousands
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
if (exponent > 0)
|
if (exponent > 0)
|
||||||
{
|
{
|
||||||
@ -1031,7 +1163,6 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
123e-6 gives 123 / 1000000. */
|
123e-6 gives 123 / 1000000. */
|
||||||
|
|
||||||
int expbit;
|
int expbit;
|
||||||
int cnt;
|
|
||||||
int neg_exp;
|
int neg_exp;
|
||||||
int more_bits;
|
int more_bits;
|
||||||
mp_limb_t cy;
|
mp_limb_t cy;
|
||||||
@ -1095,8 +1226,11 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
|
|||||||
memcpy (den, num, densize * sizeof (mp_limb_t));
|
memcpy (den, num, densize * sizeof (mp_limb_t));
|
||||||
|
|
||||||
/* Read the fractional digits from the string. */
|
/* Read the fractional digits from the string. */
|
||||||
(void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent);
|
(void) str_to_mpn (startp, dig_no - int_no, num, &numsize, &exponent
|
||||||
|
#ifndef USE_WIDE_CHAR
|
||||||
|
, decimal, decimal_len, thousands
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
/* We now have to shift both numbers so that the highest bit in the
|
/* We now have to shift both numbers so that the highest bit in the
|
||||||
denominator is set. In the same process we copy the numerator to
|
denominator is set. In the same process we copy the numerator to
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* Convert string representation of a number into an integer value.
|
/* Convert string representation of a number into an integer value.
|
||||||
Copyright (C) 1991,92,94,95,96,97,98,99 Free Software Foundation, Inc.
|
Copyright (C) 1991,92,94,95,96,97,98,99,2000 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -243,13 +243,20 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
|
|||||||
register UCHAR_TYPE c;
|
register UCHAR_TYPE c;
|
||||||
const STRING_TYPE *save, *end;
|
const STRING_TYPE *save, *end;
|
||||||
int overflow;
|
int overflow;
|
||||||
|
#ifndef USE_WIDE_CHAR
|
||||||
|
int cnt;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef USE_NUMBER_GROUPING
|
#ifdef USE_NUMBER_GROUPING
|
||||||
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
|
||||||
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
struct locale_data *current = loc->__locales[LC_NUMERIC];
|
||||||
# endif
|
# endif
|
||||||
/* The thousands character of the current locale. */
|
/* The thousands character of the current locale. */
|
||||||
|
# ifdef USE_WIDE_CHAR
|
||||||
wchar_t thousands = L'\0';
|
wchar_t thousands = L'\0';
|
||||||
|
# else
|
||||||
|
const char *thousands = NULL;
|
||||||
|
# endif
|
||||||
/* The numeric grouping specification of the current locale,
|
/* The numeric grouping specification of the current locale,
|
||||||
in the format described in <locale.h>. */
|
in the format described in <locale.h>. */
|
||||||
const char *grouping;
|
const char *grouping;
|
||||||
@ -262,13 +269,23 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Figure out the thousands separator character. */
|
/* Figure out the thousands separator character. */
|
||||||
# if defined _LIBC || defined _HAVE_BTOWC
|
# ifdef USE_WIDE_CHAR
|
||||||
thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
|
# ifdef _LIBC
|
||||||
if (thousands == WEOF)
|
thousands = _NL_CURRENT_WORD (LC_NUMERIC,
|
||||||
thousands = L'\0';
|
_NL_NUMERIC_THOUSANDS_SEP_WC);
|
||||||
# endif
|
# endif
|
||||||
if (thousands == L'\0')
|
if (thousands == L'\0')
|
||||||
grouping = NULL;
|
grouping = NULL;
|
||||||
|
# else
|
||||||
|
# ifdef _LIBC
|
||||||
|
thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
|
||||||
|
# endif
|
||||||
|
if (*thousands == '\0')
|
||||||
|
{
|
||||||
|
thousands = NULL;
|
||||||
|
grouping = NULL;
|
||||||
|
}
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -325,15 +342,33 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
|
|||||||
{
|
{
|
||||||
/* Find the end of the digit string and check its grouping. */
|
/* Find the end of the digit string and check its grouping. */
|
||||||
end = s;
|
end = s;
|
||||||
for (c = *end; c != L_('\0'); c = *++end)
|
if (
|
||||||
if ((wchar_t) c != thousands
|
# ifdef USE_WIDE_CHAR
|
||||||
&& ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
|
*s != thousands
|
||||||
&& (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
|
# else
|
||||||
break;
|
({ for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
if (*s == thousands)
|
if (thousands[cnt] != end[cnt])
|
||||||
end = s;
|
break;
|
||||||
else
|
thousands[cnt] != '\0'; })
|
||||||
end = correctly_grouped_prefix (s, end, thousands, grouping);
|
# endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (c = *end; c != L_('\0'); c = *++end)
|
||||||
|
if (((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
|
||||||
|
# ifdef USE_WIDE_CHAR
|
||||||
|
&& c != thousands
|
||||||
|
# else
|
||||||
|
&& ({ for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
|
||||||
|
if (thousands[cnt] != end[cnt])
|
||||||
|
break;
|
||||||
|
thousands[cnt] != '\0'; })
|
||||||
|
# endif
|
||||||
|
&& (!ISALPHA (c)
|
||||||
|
|| (int) (TOUPPER (c) - L_('A') + 10) >= base))
|
||||||
|
break;
|
||||||
|
|
||||||
|
end = correctly_grouped_prefix (s, end, thousands, grouping);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user