aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2000-06-29 08:44:37 +0000
committerUlrich Drepper <drepper@redhat.com>2000-06-29 08:44:37 +0000
commita748c3c64c832a9e4a8128f26aa17ed98139ca4a (patch)
tree8df4ef7c34a4e62f11862bde4e60a78deb412710
parent23335dcd5f7016f7191b781b81e1fd2525026cb5 (diff)
downloadglibc-a748c3c64c832a9e4a8128f26aa17ed98139ca4a.tar
glibc-a748c3c64c832a9e4a8128f26aa17ed98139ca4a.tar.gz
glibc-a748c3c64c832a9e4a8128f26aa17ed98139ca4a.tar.bz2
glibc-a748c3c64c832a9e4a8128f26aa17ed98139ca4a.zip
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 *).
-rw-r--r--ChangeLog30
-rw-r--r--stdlib/grouping.h76
-rw-r--r--stdlib/strtod.c194
-rw-r--r--sysdeps/generic/strtol.c65
4 files changed, 299 insertions, 66 deletions
diff --git a/ChangeLog b/ChangeLog
index f953e8e42b..01e9fea1b5 100644
--- a/ChangeLog
+++ b/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>
- * 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 *).
- * 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 *).
+ * 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_JUMPS_FUNC): Express in terms of _IO_JUMPS, and add cast to
THIS, since _IO_JUMPS no longer does it implicitly.
(_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.
(_IO_flush_all, _IO_flush_all_linebuffered, _IO_unbuffer_write):
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/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
to (struct _IO_FILE_plus *).
diff --git a/stdlib/grouping.h b/stdlib/grouping.h
index 71b89f9133..ca760c7978 100644
--- a/stdlib/grouping.h
+++ b/stdlib/grouping.h
@@ -1,5 +1,5 @@
/* 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.
The GNU C Library is free software; you can redistribute it and/or
@@ -30,19 +30,24 @@
static inline const STRING_TYPE *
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)
return end;
- if (*grouping == '\0')
- {
- /* No grouping allowed. Accept all characters up to the first
- thousands separator. */
- while (begin < end && *begin != thousands)
- ++begin;
- return begin;
- }
+#ifndef USE_WIDE_CHAR
+ thousands_len = strlen (thousands);
+#endif
while (end > begin)
{
@@ -50,8 +55,23 @@ correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
const char *gp = grouping;
/* Check first group. */
- while (cp >= begin && (wchar_t) *cp != thousands)
- --cp;
+ while (cp >= begin)
+ {
+#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
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. */
- while (cp >= begin && (wchar_t) *cp != thousands)
- --cp;
+ while (cp >= begin)
+ {
+#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)
/* OK, only digits followed. */
@@ -105,8 +137,20 @@ correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
/* Check the next group. */
const STRING_TYPE *group_end = cp;
- while (cp >= begin && (wchar_t) *cp != thousands)
- --cp;
+ while (cp >= begin)
+ {
+#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)
/* Final group is correct. */
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index f2ff79f6df..d15237125e 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, 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.
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. */
static inline const STRING_TYPE *
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. */
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
format of the number is correct and we have an exact number
of characters to read. */
- while (*str < L_('0') || *str > L_('9'))
+#ifdef USE_WIDE_CHAR
+ if (*str < L'0' || *str > L'9')
++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');
++cnt;
}
@@ -451,12 +470,23 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
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];
@@ -470,21 +500,34 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
else
{
/* Figure out the thousands separator character. */
- thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
- if (thousands == WEOF)
- thousands = L'\0';
+#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. */
- decimal = __btowc (*_NL_CURRENT (LC_NUMERIC, DECIMAL_POINT));
- if (decimal == WEOF)
- decimal = L'.';
+#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;
@@ -510,8 +553,23 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
/* Return 0.0 if no legal string is found.
No character is used even if a sign was found. */
- if ((c < L_('0') || c > L_('9'))
- && ((wchar_t) c != decimal || cp[1] < L_('0') || cp[1] > L_('9')))
+#ifdef USE_WIDE_CHAR
+ 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;
/* Check for `INF' or `INFINITY'. */
@@ -588,16 +646,45 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
start_of_digits = startp = cp;
/* 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;
+#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.
Return current read pointer. */
- if ((c < L_('0') || c > L_('9')) &&
- (base == 16 && (c < TOLOWER (L_('a')) || c > TOLOWER (L_('f')))) &&
- (wchar_t) c != decimal &&
- (base == 16 && (cp == start_of_digits || TOLOWER (c) != L_('p'))) &&
- (base != 16 && TOLOWER (c) != L_('e')))
+ if ((c < L_('0') || c > L_('9'))
+ && (base == 16 && (c < TOLOWER (L_('a')) || c > TOLOWER (L_('f'))))
+#ifdef USE_WIDE_CHAR
+ && c != decimal
+#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);
/* 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'))
|| (base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
++dig_no;
- else if (thousands == L'\0' || (wchar_t) c != thousands)
- /* Not a digit or separator: end of the integer part. */
- break;
+ else
+ {
+#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;
}
@@ -667,9 +770,19 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
/* Read the fractional digits. A special case are the 'american style'
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')) ||
(base == 16 && TOLOWER (c) >= L_('a') && TOLOWER (c) <= L_('f')))
{
@@ -779,9 +892,24 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
if (lead_zero)
{
/* Find the decimal point */
- while ((wchar_t) *startp != decimal)
+#ifdef USE_WIDE_CHAR
+ while (*startp != decimal)
++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;
dig_no -= lead_zero;
}
@@ -828,8 +956,8 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
while (--dig_no > 0 && idx >= 0)
{
- while (!ISXDIGIT (*startp))
- ++startp;
+ if (!ISXDIGIT (*startp))
+ startp += decimal_len;
if (ISDIGIT (*startp))
val = *startp++ - L_('0');
else
@@ -885,7 +1013,11 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
if (int_no > 0)
{
/* 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)
{
@@ -1031,7 +1163,6 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
123e-6 gives 123 / 1000000. */
int expbit;
- int cnt;
int neg_exp;
int more_bits;
mp_limb_t cy;
@@ -1095,8 +1226,11 @@ INTERNAL (STRTOF) (nptr, endptr, group LOCALE_PARAM)
memcpy (den, num, densize * sizeof (mp_limb_t));
/* 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
denominator is set. In the same process we copy the numerator to
diff --git a/sysdeps/generic/strtol.c b/sysdeps/generic/strtol.c
index 42da792c44..44e2104e18 100644
--- a/sysdeps/generic/strtol.c
+++ b/sysdeps/generic/strtol.c
@@ -1,5 +1,5 @@
/* 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.
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;
const STRING_TYPE *save, *end;
int overflow;
+#ifndef USE_WIDE_CHAR
+ int cnt;
+#endif
#ifdef USE_NUMBER_GROUPING
# ifdef USE_IN_EXTENDED_LOCALE_MODEL
struct locale_data *current = loc->__locales[LC_NUMERIC];
# 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;
@@ -262,13 +269,23 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
else
{
/* Figure out the thousands separator character. */
-# if defined _LIBC || defined _HAVE_BTOWC
- thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
- if (thousands == WEOF)
- thousands = L'\0';
-# endif
+# ifdef USE_WIDE_CHAR
+# ifdef _LIBC
+ thousands = _NL_CURRENT_WORD (LC_NUMERIC,
+ _NL_NUMERIC_THOUSANDS_SEP_WC);
+# endif
if (thousands == L'\0')
grouping = NULL;
+# else
+# ifdef _LIBC
+ thousands = _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
+# endif
+ if (*thousands == '\0')
+ {
+ thousands = NULL;
+ grouping = NULL;
+ }
+# endif
}
}
else
@@ -325,15 +342,33 @@ INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
{
/* Find the end of the digit string and check its grouping. */
end = s;
- for (c = *end; c != L_('\0'); c = *++end)
- if ((wchar_t) c != thousands
- && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
- && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
- break;
- if (*s == thousands)
- end = s;
- else
- end = correctly_grouped_prefix (s, end, thousands, grouping);
+ if (
+# ifdef USE_WIDE_CHAR
+ *s != thousands
+# else
+ ({ for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+ if (thousands[cnt] != end[cnt])
+ break;
+ thousands[cnt] != '\0'; })
+# 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
#endif