aboutsummaryrefslogtreecommitdiff
path: root/stdlib
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/grouping.h20
-rw-r--r--stdlib/stdlib.h36
-rw-r--r--stdlib/strtod.c126
-rw-r--r--stdlib/strtol.c109
4 files changed, 182 insertions, 109 deletions
diff --git a/stdlib/grouping.h b/stdlib/grouping.h
index 566f6a6109..f53368991f 100644
--- a/stdlib/grouping.h
+++ b/stdlib/grouping.h
@@ -1,6 +1,6 @@
/* Internal header for proving correct grouping in strings of numbers.
-Copyright (C) 1995 Free Software Foundation, Inc.
-Contributed by Ulrich Drepper.
+Copyright (C) 1995, 1996 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
modify it under the terms of the GNU Library General Public License as
@@ -28,16 +28,16 @@ Cambridge, MA 02139, USA. */
satisfies the grouping rules. It is assumed that at least one digit
follows BEGIN directly. */
-static inline const char *
-correctly_grouped_prefix (const char *begin, const char *end,
+static inline const STRING_TYPE *
+correctly_grouped_prefix (const STRING_TYPE *begin, const STRING_TYPE *end,
wchar_t thousands, const char *grouping)
{
- if (! grouping)
+ if (grouping == NULL)
return end;
while (end > begin)
{
- const char *cp = end - 1;
+ const STRING_TYPE *cp = end - 1;
const char *gp = grouping;
/* Check first group. */
@@ -48,7 +48,7 @@ correctly_grouped_prefix (const char *begin, const char *end,
{
/* This group matches the specification. */
- const char *new_end;
+ const STRING_TYPE *new_end;
if (cp < begin)
/* There is just one complete group. We are done. */
@@ -66,7 +66,7 @@ correctly_grouped_prefix (const char *begin, const char *end,
/* Get the next grouping rule. */
++gp;
if (*gp == 0)
- /* If end is reached use last rule. */
+ /* If end is reached use last rule. */
--gp;
/* Skip the thousands separator. */
@@ -85,7 +85,7 @@ correctly_grouped_prefix (const char *begin, const char *end,
else
{
/* Check the next group. */
- const char *group_end = cp;
+ const STRING_TYPE *group_end = cp;
while (cp >= begin && (wchar_t) *cp != thousands)
--cp;
@@ -120,4 +120,4 @@ correctly_grouped_prefix (const char *begin, const char *end,
}
return MAX (begin, end);
-}
+}
diff --git a/stdlib/stdlib.h b/stdlib/stdlib.h
index 40b81c688c..2fde1c806f 100644
--- a/stdlib/stdlib.h
+++ b/stdlib/stdlib.h
@@ -102,22 +102,26 @@ extern unsigned long long int strtouq __P ((__const char *__nptr,
/* The internal entry points for `strtoX' take an extra flag argument
saying whether or not to parse locale-dependent number grouping. */
-extern double __strtod_internal (__const char *__nptr,
- char **__endptr, int __group);
-extern float __strtof_internal (__const char *__nptr, char **__endptr,
- int __group);
-extern __long_double_t __strtold_internal (__const char *__nptr,
- char **__endptr, int __group);
-extern long int __strtol_internal (__const char *__nptr, char **__endptr,
- int __base, int __group);
-extern unsigned long int __strtoul_internal (__const char *__nptr,
- char **__endptr, int __base,
- int __group);
-extern long long int __strtoq_internal (__const char *__nptr, char **__endptr,
- int __base, int __group);
-extern unsigned long long int __strtouq_internal (__const char *__nptr,
+extern double __strtod_internal __P ((__const char *__nptr,
+ char **__endptr, int __group));
+extern float __strtof_internal __P ((__const char *__nptr, char **__endptr,
+ int __group));
+extern __long_double_t __strtold_internal __P ((__const char *__nptr,
+ char **__endptr, int __group));
+extern long int __strtol_internal __P ((__const char *__nptr, char **__endptr,
+ int __base, int __group));
+extern unsigned long int __strtoul_internal __P ((__const char *__nptr,
char **__endptr, int __base,
- int __group);
+ int __group));
+#ifdef __GNUC__
+extern long long int __strtoq_internal __P ((__const char *__nptr,
+ char **__endptr, int __base,
+ int __group));
+extern unsigned long long int __strtouq_internal __P ((__const char *__nptr,
+ char **__endptr,
+ int __base,
+ int __group));
+#endif /* GCC */
#if defined (__OPTIMIZE__) && __GNUC__ >= 2
/* Define inline functions which call the internal entry points. */
@@ -143,7 +147,7 @@ extern __inline long long int strtoq (__const char *__nptr, char **__endptr,
int __base)
{ return __strtoq_internal (__nptr, __endptr, __base, 0); }
extern __inline unsigned long long int strtouq (__const char *__nptr,
- char **__endptr, int __base)
+ char **__endptr, int __base)
{ return __strtouq_internal (__nptr, __endptr, __base, 0); }
#endif
diff --git a/stdlib/strtod.c b/stdlib/strtod.c
index 51dc520c01..e262f3de83 100644
--- a/stdlib/strtod.c
+++ b/stdlib/strtod.c
@@ -1,6 +1,6 @@
/* Read decimal floating point numbers.
Copyright (C) 1995, 1996 Free Software Foundation, Inc.
-Contributed by Ulrich Drepper.
+Contributed by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
This file is part of the GNU C Library.
@@ -15,18 +15,39 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
-/* Configuration part. These macros are defined by `strtold.c' and `strtof.c'
- to produce the `long double' and `float' versions of the reader. */
+/* 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. */
#ifndef FLOAT
-#define FLOAT double
-#define FLT DBL
-#define STRTOF strtod
-#define MPN2FLOAT __mpn_construct_double
-#define FLOAT_HUGE_VAL HUGE_VAL
+# define FLOAT double
+# define FLT DBL
+# ifdef USE_WIDE_CHAR
+# define STRTOF wcstod
+# else
+# define STRTOF strtod
+# endif
+# define MPN2FLOAT __mpn_construct_double
+# define FLOAT_HUGE_VAL HUGE_VAL
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# include <wchar.h>
+# define STRING_TYPE wchar_t
+# define CHAR_TYPE wint_t
+# define L_(Ch) L##Ch
+# define ISSPACE(Ch) iswspace (Ch)
+# define TOLOWER(Ch) towlower (Ch)
+#else
+# define STRING_TYPE char
+# define CHAR_TYPE char
+# define L_(Ch) Ch
+# define ISSPACE(Ch) isspace (Ch)
+# define TOLOWER(Ch) tolower (Ch)
#endif
/* End of configuration part. */
@@ -103,8 +124,9 @@ static const mp_limb _tens_in_limb[MAX_DIG_PER_LIMB + 1] =
#define NDIG (MAX_10_EXP - MIN_10_EXP + 2 * MANT_DIG)
#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)
+#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) \
@@ -206,8 +228,8 @@ round_and_return (mp_limb *retval, int exponent, int negative,
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 inline const char *
-str_to_mpn (const char *str, int digcnt, mp_limb *n, mp_size_t *nsize,
+static inline const STRING_TYPE *
+str_to_mpn (const STRING_TYPE *str, int digcnt, mp_limb *n, mp_size_t *nsize,
int *exponent)
{
/* Number of digits for actual limb. */
@@ -239,9 +261,9 @@ str_to_mpn (const char *str, int digcnt, mp_limb *n, mp_size_t *nsize,
/* 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. */
- while (!isdigit (*str))
+ while (*str < L_('0') || *str > L_('9'))
++str;
- low = low * 10 + *str++ - '0';
+ low = low * 10 + *str++ - L_('0');
++cnt;
}
while (--digcnt > 0);
@@ -311,8 +333,8 @@ __mpn_lshift_1 (mp_limb *ptr, mp_size_t size, unsigned int count, mp_limb limb)
ERANGE and return HUGE_VAL with the approriate sign. */
FLOAT
INTERNAL (STRTOF) (nptr, endptr, group)
- const char *nptr;
- char **endptr;
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
int group;
{
int negative; /* The sign of the number. */
@@ -330,15 +352,15 @@ INTERNAL (STRTOF) (nptr, endptr, group)
int bits;
/* Running pointer after the last character processed in the string. */
- const char *cp, *tp;
+ const STRING_TYPE *cp, *tp;
/* Start of significant part of the number. */
- const char *startp, *start_of_digits;
+ const STRING_TYPE *startp, *start_of_digits;
/* Points at the character following the integer and fractional digits. */
- const char *expp;
+ 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 c;
+ CHAR_TYPE c;
/* The radix character of the current locale. */
wchar_t decimal;
@@ -386,32 +408,33 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* Ignore leading white space. */
do
c = *++cp;
- while (isspace (c));
+ while (ISSPACE (c));
/* Get sign of the result. */
- if (c == '-')
+ if (c == L_('-'))
{
negative = 1;
c = *++cp;
}
- else if (c == '+')
+ 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. */
- if (!isdigit (c) && (c != decimal || !isdigit (cp[1])))
+ if ((c < L_('0') || c > L_('9'))
+ && (c != decimal || cp[1] < L_('0') || cp[1] > L_('9')))
RETURN (0.0, nptr);
/* 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. */
- while (c == '0' || (thousands != L'\0' && c == thousands))
+ while (c == L_('0') || (thousands != L'\0' && c == thousands))
c = *++cp;
/* If no other digit but a '0' is found the result is 0.0.
Return current read pointer. */
- if (!isdigit (c) && c != decimal)
+ if ((c < L_('0') || c > L_('9')) && c != decimal)
{
tp = correctly_grouped_prefix (start_of_digits, cp, thousands, grouping);
/* If TP is at the start of the digits, there was no correctly
@@ -428,7 +451,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
so we can check all the grouping separators. */
grouping)
{
- if (isdigit (c))
+ if (c >= L_('0') && c <= L_('9'))
++dig_no;
else if (thousands == L'\0' || c != thousands)
/* Not a digit or separator: end of the integer part. */
@@ -458,7 +481,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
cp = tp;
dig_no = 0;
for (tp = startp; tp < cp; ++tp)
- if (isdigit (*tp))
+ if (*tp >= L_('0') && *tp <= L_('9'))
++dig_no;
int_no = dig_no;
@@ -481,31 +504,35 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* Read the fractional digits. A special case are the 'american style'
numbers like `16.' i.e. with decimal but without trailing digits. */
if (c == decimal)
- while (isdigit (c = *++cp))
- {
- if (c != '0' && lead_zero == -1)
- lead_zero = dig_no - int_no;
- ++dig_no;
- }
+ {
+ c = *++cp;
+ while (c >= L_('0') && c <= L_('9'))
+ {
+ if (c != L_('0') && lead_zero == -1)
+ lead_zero = dig_no - int_no;
+ ++dig_no;
+ c = *++cp;
+ }
+ }
/* Remember start of exponent (if any). */
expp = cp;
/* Read exponent. */
- if (tolower (c) == 'e')
+ if (TOLOWER (c) == L_('e'))
{
int exp_negative = 0;
c = *++cp;
- if (c == '-')
+ if (c == L_('-'))
{
exp_negative = 1;
c = *++cp;
}
- else if (c == '+')
+ else if (c == L_('+'))
c = *++cp;
- if (isdigit (c))
+ if (c >= L_('0') && c <= L_('9'))
{
int exp_limit;
@@ -532,16 +559,16 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* Accept all following digits as part of the exponent. */
do
++cp;
- while (isdigit (*cp));
+ while (*cp >= L_('0') && *cp <= L_('9'));
RETURN (retval, cp);
/* NOTREACHED */
}
- exponent += c - '0';
+ exponent += c - L_('0');
c = *++cp;
}
- while (isdigit (c));
+ while (c >= L_('0') && c <= L_('9'));
if (exp_negative)
exponent = -exponent;
@@ -553,7 +580,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* We don't want to have to work with trailing zeroes after the radix. */
if (dig_no > int_no)
{
- while (expp[-1] == '0')
+ while (expp[-1] == L_('0'))
{
--expp;
--dig_no;
@@ -565,7 +592,7 @@ INTERNAL (STRTOF) (nptr, endptr, group)
/* The whole string is parsed. Store the address of the next character. */
if (endptr)
- *endptr = (char *) cp;
+ *endptr = (STRING_TYPE *) cp;
if (dig_no == 0)
return 0.0;
@@ -573,7 +600,8 @@ INTERNAL (STRTOF) (nptr, endptr, group)
if (lead_zero)
{
/* Find the decimal point */
- while (*startp != decimal) startp++;
+ while (*startp != decimal)
+ ++startp;
startp += lead_zero + 1;
exponent -= lead_zero;
dig_no -= lead_zero;
@@ -1131,8 +1159,8 @@ INTERNAL (STRTOF) (nptr, endptr, group)
FLOAT
STRTOF (nptr, endptr)
- const char *nptr;
- char **endptr;
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
{
return INTERNAL (STRTOF) (nptr, endptr, 0);
}
diff --git a/stdlib/strtol.c b/stdlib/strtol.c
index 289aa04383..2a2a8ea5e7 100644
--- a/stdlib/strtol.c
+++ b/stdlib/strtol.c
@@ -1,5 +1,4 @@
-/* Copyright (C) 1991, 1992, 1994, 1995, 1996 Free Software Foundation, Inc.
-
+/* Copyright (C) 1991, 92, 94, 95, 96 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
@@ -56,18 +55,41 @@ extern int errno;
# define UNSIGNED 0
# define INT LONG int
#else
-# define strtol strtoul
# define INT unsigned LONG int
#endif
+/* Determine the name. */
+#if UNSIGNED
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstouq
+# else
+# define strtol wcstoul
+# endif
+# else
+# ifdef QUAD
+# define strtol strtouq
+# else
+# define strtol strtoul
+# endif
+# endif
+#else
+# ifdef USE_WIDE_CHAR
+# ifdef QUAD
+# define strtol wcstoq
+# else
+# define strtol wcstol
+# endif
+# else
+# ifdef QUAD
+# define strtol strtoq
+# endif
+# endif
+#endif
+
/* If QUAD is defined, we are defining `strtoq' or `strtouq',
operating on `long long int's. */
#ifdef QUAD
-# if UNSIGNED
-# define strtoul strtouq
-# else
-# define strtol strtoq
-# endif
# define LONG long long
# undef LONG_MIN
# define LONG_MIN LONG_LONG_MIN
@@ -85,6 +107,24 @@ extern int errno;
# define LONG long
#endif
+#ifdef USE_WIDE_CHAR
+# include <wchar.h>
+# include <wctype.h>
+# define L_(ch) L##ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# define ISSPACE(ch) iswspace (ch)
+# define ISALPHA(ch) iswalpha (ch)
+# define TOUPPER(ch) towupper (ch)
+#else
+# define L_(ch) ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# define ISSPACE(ch) isspace (ch)
+# define ISALPHA(ch) isalpha (ch)
+# define TOUPPER(ch) toupper (ch)
+#endif
+
#ifdef __STDC__
# define INTERNAL(x) INTERNAL1(x)
# define INTERNAL1(x) __##x##_internal
@@ -107,8 +147,8 @@ extern int errno;
INT
INTERNAL (strtol) (nptr, endptr, base, group)
- const char *nptr;
- char **endptr;
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
int base;
int group;
{
@@ -116,9 +156,9 @@ INTERNAL (strtol) (nptr, endptr, base, group)
register unsigned LONG int cutoff;
register unsigned int cutlim;
register unsigned LONG int i;
- register const char *s;
- register unsigned char c;
- const char *save, *end;
+ register const STRING_TYPE *s;
+ register UCHAR_TYPE c;
+ const STRING_TYPE *save, *end;
int overflow;
#ifdef USE_NUMBER_GROUPING
@@ -153,18 +193,18 @@ INTERNAL (strtol) (nptr, endptr, base, group)
save = s = nptr;
/* Skip white space. */
- while (isspace (*s))
+ while (ISSPACE (*s))
++s;
- if (*s == '\0')
+ if (*s == L_('\0'))
goto noconv;
/* Check for a sign. */
- if (*s == '-')
+ if (*s == L_('-'))
{
negative = 1;
++s;
}
- else if (*s == '+')
+ else if (*s == L_('+'))
{
negative = 0;
++s;
@@ -172,14 +212,14 @@ INTERNAL (strtol) (nptr, endptr, base, group)
else
negative = 0;
- if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
+ if (base == 16 && s[0] == L_('0') && TOUPPER (s[1]) == L_('X'))
s += 2;
/* If BASE is zero, figure it out ourselves. */
if (base == 0)
- if (*s == '0')
+ if (*s == L_('0'))
{
- if (toupper (s[1]) == 'X')
+ if (TOUPPER (s[1]) == L_('X'))
{
s += 2;
base = 16;
@@ -198,9 +238,9 @@ INTERNAL (strtol) (nptr, endptr, base, group)
{
/* Find the end of the digit string and check its grouping. */
end = s;
- for (c = *end; c != '\0'; c = *++end)
- if (c != thousands && !isdigit (c) &&
- (!isalpha (c) || toupper (c) - 'A' + 10 >= base))
+ for (c = *end; c != L_('\0'); c = *++end)
+ if (c != thousands && (c < L_('0') || c > L_('9'))
+ && (!ISALPHA (c) || TOUPPER (c) - L_('A') + 10 >= base))
break;
if (*s == thousands)
end = s;
@@ -216,14 +256,14 @@ INTERNAL (strtol) (nptr, endptr, base, group)
overflow = 0;
i = 0;
- for (c = *s; c != '\0'; c = *++s)
+ for (c = *s; c != L_('\0'); c = *++s)
{
if (s == end)
break;
- if (isdigit (c))
- c -= '0';
- else if (isalpha (c))
- c = toupper (c) - 'A' + 10;
+ if (c >= L_('0') && c <= L_('9'))
+ c -= L_('0');
+ else if (ISALPHA (c))
+ c = TOUPPER (c) - L_('A') + 10;
else
break;
if (c >= base)
@@ -245,7 +285,7 @@ INTERNAL (strtol) (nptr, endptr, base, group)
/* Store in ENDPTR the address of one character
past the last character we converted. */
if (endptr != NULL)
- *endptr = (char *) s;
+ *endptr = (STRING_TYPE *) s;
#if !UNSIGNED
/* Check for a value that is within the range of
@@ -274,11 +314,12 @@ noconv:
hexadecimal digits. This is no error case. We return 0 and
ENDPTR points to the `x`. */
if (endptr != NULL)
- if (save - nptr >= 2 && tolower (save[-1]) == 'x' && save[-2] == '0')
- *endptr = (char *) &save[-1];
+ if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
+ && save[-2] == L_('0'))
+ *endptr = (STRING_TYPE *) &save[-1];
else
/* There was no number to convert. */
- *endptr = (char *) nptr;
+ *endptr = (STRING_TYPE *) nptr;
return 0L;
}
@@ -287,8 +328,8 @@ noconv:
INT
strtol (nptr, endptr, base)
- const char *nptr;
- char **endptr;
+ const STRING_TYPE *nptr;
+ STRING_TYPE **endptr;
int base;
{
return INTERNAL (strtol) (nptr, endptr, base, 0);