about summary refs log tree commit diff
path: root/sysdeps/generic
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/generic')
-rw-r--r--sysdeps/generic/strtol.c533
-rw-r--r--sysdeps/generic/strtol_l.c493
-rw-r--r--sysdeps/generic/strtold_l.c (renamed from sysdeps/generic/strtold.c)18
-rw-r--r--sysdeps/generic/strtoll_l.c8
-rw-r--r--sysdeps/generic/strtoul_l.c8
-rw-r--r--sysdeps/generic/strtoull_l.c9
-rw-r--r--sysdeps/generic/wcstol_l.c8
-rw-r--r--sysdeps/generic/wcstoll_l.c8
-rw-r--r--sysdeps/generic/wcstoul_l.c8
-rw-r--r--sysdeps/generic/wcstoull_l.c8
10 files changed, 558 insertions, 543 deletions
diff --git a/sysdeps/generic/strtol.c b/sysdeps/generic/strtol.c
index 953c6c4a90..02ec19aabe 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,2000,2001,2002,2003
+   Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003,2004
    	Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -18,46 +18,10 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef _LIBC
-# define USE_NUMBER_GROUPING
-# define STDC_HEADERS
-# define HAVE_LIMITS_H
-#endif
-
-#include <ctype.h>
-#include <errno.h>
-#ifndef errno
-extern int errno;
-#endif
-#ifndef __set_errno
-# define __set_errno(Val) errno = (Val)
-#endif
-
-#ifdef HAVE_LIMITS_H
-# include <limits.h>
-#endif
-
-#ifdef STDC_HEADERS
-# include <stddef.h>
-# include <stdlib.h>
-# include <string.h>
-# include <locale.h>
-#else
-# ifndef NULL
-#  define NULL 0
-# endif
-#endif
-
-#ifdef USE_NUMBER_GROUPING
-# include "../locale/localeinfo.h"
-#endif
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale/localeinfo.h>
 
-/* Nonzero if we are defining `strtoul' or `strtoull', operating on
-   unsigned integers.  */
 #ifndef UNSIGNED
 # define UNSIGNED 0
 # define INT LONG int
@@ -65,508 +29,83 @@ extern int errno;
 # define INT unsigned LONG int
 #endif
 
-/* Determine the name.  */
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# if UNSIGNED
-#  ifdef USE_WIDE_CHAR
-#   ifdef QUAD
-#    define strtol __wcstoull_l
-#   else
-#    define strtol __wcstoul_l
-#   endif
+#if UNSIGNED
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol wcstoull
+#   define __strtol_l __wcstoull_l
 #  else
-#   ifdef QUAD
-#    define strtol __strtoull_l
-#   else
-#    define strtol __strtoul_l
-#   endif
+#   define strtol wcstoul
+#   define __strtol_l __wcstoul_l
 #  endif
 # else
-#  ifdef USE_WIDE_CHAR
-#   ifdef QUAD
-#    define strtol __wcstoll_l
-#   else
-#    define strtol __wcstol_l
-#   endif
+#  ifdef QUAD
+#   define strtol strtoull
+#   define __strtol_l __strtoull_l
 #  else
-#   ifdef QUAD
-#    define strtol __strtoll_l
-#   else
-#    define strtol __strtol_l
-#   endif
+#   define strtol strtoul
+#   define __strtol_l __strtoul_l
 #  endif
 # endif
 #else
-# if UNSIGNED
-#  ifdef USE_WIDE_CHAR
-#   ifdef QUAD
-#    define strtol wcstoull
-#   else
-#    define strtol wcstoul
-#   endif
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol wcstoll
+#   define __strtol_l __wcstoll_l
 #  else
-#   ifdef QUAD
-#    define strtol strtoull
-#   else
-#    define strtol strtoul
-#   endif
+#   define strtol wcstol
+#   define __strtol_l __wcstol_l
 #  endif
 # else
-#  ifdef USE_WIDE_CHAR
-#   ifdef QUAD
-#    define strtol wcstoll
-#   else
-#    define strtol wcstol
-#   endif
-#  else
-#   ifdef QUAD
-#    define strtol strtoll
-#   endif
+#  ifdef QUAD
+#   define strtol strtoll
+#   define __strtol_l __strtoll_l
 #  endif
 # endif
 #endif
 
+
 /* If QUAD is defined, we are defining `strtoll' or `strtoull',
    operating on `long long int's.  */
 #ifdef QUAD
 # define LONG long long
-# define STRTOL_LONG_MIN LONG_LONG_MIN
-# define STRTOL_LONG_MAX LONG_LONG_MAX
-# define STRTOL_ULONG_MAX ULONG_LONG_MAX
-# if __GNUC__ == 2 && __GNUC_MINOR__ < 7
-   /* Work around gcc bug with using this constant.  */
-   static const unsigned long long int maxquad = ULONG_LONG_MAX;
-#  undef STRTOL_ULONG_MAX
-#  define STRTOL_ULONG_MAX maxquad
-# endif
 #else
 # define LONG long
-
-# ifndef ULONG_MAX
-#  define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
-# endif
-# ifndef LONG_MAX
-#  define LONG_MAX ((long int) (ULONG_MAX >> 1))
-# endif
-# define STRTOL_LONG_MIN LONG_MIN
-# define STRTOL_LONG_MAX LONG_MAX
-# define STRTOL_ULONG_MAX ULONG_MAX
-#endif
-
-
-/* We use this code also for the extended locale handling where the
-   function gets as an additional argument the locale which has to be
-   used.  To access the values we have to redefine the _NL_CURRENT
-   macro.  */
-#ifdef USE_IN_EXTENDED_LOCALE_MODEL
-# undef _NL_CURRENT
-# define _NL_CURRENT(category, item) \
-  (current->values[_NL_ITEM_INDEX (item)].string)
-# define LOCALE_PARAM , loc
-# define LOCALE_PARAM_DECL __locale_t loc;
-#else
-# define LOCALE_PARAM
-# define LOCALE_PARAM_DECL
 #endif
 
-#if defined _LIBC || defined HAVE_WCHAR_H
-# include <wchar.h>
-#endif
 
 #ifdef USE_WIDE_CHAR
-# include <wctype.h>
-# define L_(Ch) L##Ch
-# define UCHAR_TYPE wint_t
 # define STRING_TYPE wchar_t
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
-#  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
-#  define TOUPPER(Ch) __towupper_l ((Ch), loc)
-# else
-#  define ISSPACE(Ch) iswspace (Ch)
-#  define ISALPHA(Ch) iswalpha (Ch)
-#  define TOUPPER(Ch) towupper (Ch)
-# endif
-# else
-#  if defined _LIBC \
-   || defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
-#   define IN_CTYPE_DOMAIN(c) 1
-#  else
-#   define IN_CTYPE_DOMAIN(c) isascii(c)
-#  endif
-#  define L_(Ch) Ch
-#  define UCHAR_TYPE unsigned char
-#  define STRING_TYPE char
-# ifdef USE_IN_EXTENDED_LOCALE_MODEL
-#  define ISSPACE(Ch) __isspace_l ((Ch), loc)
-#  define ISALPHA(Ch) __isalpha_l ((Ch), loc)
-#  define TOUPPER(Ch) __toupper_l ((Ch), loc)
-# else
-#  define ISSPACE(Ch) (IN_CTYPE_DOMAIN (Ch) && isspace (Ch))
-#  define ISALPHA(Ch) (IN_CTYPE_DOMAIN (Ch) && isalpha (Ch))
-#  define TOUPPER(Ch) (IN_CTYPE_DOMAIN (Ch) ? toupper (Ch) : (Ch))
-# endif
-#endif
-
-#ifdef __STDC__
-# define INTERNAL(X) INTERNAL1(X)
-# define INTERNAL1(X) __##X##_internal
-# define WEAKNAME(X) WEAKNAME1(X)
 #else
-# define INTERNAL(X) __/**/X/**/_internal
+# define STRING_TYPE char
 #endif
 
-#ifdef USE_NUMBER_GROUPING
-/* This file defines a function to check for correct grouping.  */
-# include "grouping.h"
-#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
 
 
+extern INT INTERNAL (__strtol_l) (const STRING_TYPE *, STRING_TYPE **, int,
+				  int, __locale_t);
 
-/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
-   If BASE is 0 the base is determined by the presence of a leading
-   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
-   If BASE is < 2 or > 36, it is reset to 10.
-   If ENDPTR is not NULL, a pointer to the character after the last
-   one converted is stored in *ENDPTR.  */
 
 INT
-INTERNAL (strtol) (nptr, endptr, base, group LOCALE_PARAM)
+INTERNAL (strtol) (nptr, endptr, base, group)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
      int base;
      int group;
-     LOCALE_PARAM_DECL
 {
-  int negative;
-  register unsigned LONG int cutoff;
-  register unsigned int cutlim;
-  register unsigned LONG int i;
-  register const STRING_TYPE *s;
-  register UCHAR_TYPE c;
-  const STRING_TYPE *save, *end;
-  int overflow;
-#ifndef USE_WIDE_CHAR
-  size_t 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;
-  size_t thousands_len = 0;
-# endif
-  /* The numeric grouping specification of the current locale,
-     in the format described in <locale.h>.  */
-  const char *grouping;
-
-  if (__builtin_expect (group, 0))
-    {
-      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-      if (*grouping <= 0 || *grouping == CHAR_MAX)
-	grouping = NULL;
-      else
-	{
-	  /* Figure out the thousands separator character.  */
-# 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
-    grouping = NULL;
-#endif
-
-  if (base < 0 || base == 1 || base > 36)
-    {
-      __set_errno (EINVAL);
-      return 0;
-    }
-
-  save = s = nptr;
-
-  /* Skip white space.  */
-  while (ISSPACE (*s))
-    ++s;
-  if (__builtin_expect (*s == L_('\0'), 0))
-    goto noconv;
-
-  /* Check for a sign.  */
-  negative = 0;
-  if (*s == L_('-'))
-    {
-      negative = 1;
-      ++s;
-    }
-  else if (*s == L_('+'))
-    ++s;
-
-  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
-  if (*s == L_('0'))
-    {
-      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
-	{
-	  s += 2;
-	  base = 16;
-	}
-      else if (base == 0)
-	base = 8;
-    }
-  else if (base == 0)
-    base = 10;
-
-  /* Save the pointer so we can check later if anything happened.  */
-  save = s;
-
-#ifdef USE_NUMBER_GROUPING
-  if (base != 10)
-    grouping = NULL;
-
-  if (__builtin_expect (grouping != NULL, 0))
-    {
-# ifndef USE_WIDE_CHAR
-      thousands_len = strlen (thousands);
-# endif
-
-      /* Find the end of the digit string and check its grouping.  */
-      end = s;
-      if (
-# ifdef USE_WIDE_CHAR
-	  *s != thousands
-# else
-	  ({ for (cnt = 0; cnt < thousands_len; ++cnt)
-	       if (thousands[cnt] != end[cnt])
-		 break;
-	     cnt < thousands_len; })
-# endif
-	  )
-	{
-	  for (c = *end; c != L_('\0'); c = *++end)
-	    if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
-# ifdef USE_WIDE_CHAR
-		&& (wchar_t) c != thousands
-# else
-		&& ({ for (cnt = 0; cnt < thousands_len; ++cnt)
-		      if (thousands[cnt] != end[cnt])
-			break;
-		      cnt < thousands_len; })
-# endif
-		&& (!ISALPHA (c)
-		    || (int) (TOUPPER (c) - L_('A') + 10) >= base))
-	      break;
-
-# ifdef USE_WIDE_CHAR
-	  end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
-# else
-	  end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
-# endif
-	}
-    }
-  else
-#endif
-    end = NULL;
-
-  cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
-  cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
-
-  overflow = 0;
-  i = 0;
-  c = *s;
-  if (sizeof (long int) != sizeof (LONG int))
-    {
-      unsigned long int j = 0;
-      unsigned long int jmax = ULONG_MAX / base;
-
-      for (;c != L_('\0'); c = *++s)
-	{
-	  if (s == end)
-	    break;
-	  if (c >= L_('0') && c <= L_('9'))
-	    c -= L_('0');
-#ifdef USE_NUMBER_GROUPING
-# ifdef USE_WIDE_CHAR
-	  else if (grouping && (wchar_t) c == thousands)
-	    continue;
-# else
-	  else if (thousands_len)
-	    {
-	      for (cnt = 0; cnt < thousands_len; ++cnt)
-		if (thousands[cnt] != s[cnt])
-		  break;
-	      if (cnt == thousands_len)
-		{
-		  s += thousands_len - 1;
-		  continue;
-		}
-	      if (ISALPHA (c))
-		c = TOUPPER (c) - L_('A') + 10;
-	      else
-		break;
-	    }
-# endif
-#endif
-	  else if (ISALPHA (c))
-	    c = TOUPPER (c) - L_('A') + 10;
-	  else
-	    break;
-	  if ((int) c >= base)
-	    break;
-	  /* Note that we never can have an overflow.  */
-	  else if (j >= jmax)
-	    {
-	      /* We have an overflow.  Now use the long representation.  */
-	      i = (unsigned LONG int) j;
-	      goto use_long;
-	    }
-	  else
-	    j = j * (unsigned long int) base + c;
-	}
-
-      i = (unsigned LONG int) j;
-    }
-  else
-    for (;c != L_('\0'); c = *++s)
-      {
-	if (s == end)
-	  break;
-	if (c >= L_('0') && c <= L_('9'))
-	  c -= L_('0');
-#ifdef USE_NUMBER_GROUPING
-# ifdef USE_WIDE_CHAR
-	else if (grouping && (wchar_t) c == thousands)
-	  continue;
-# else
-	else if (thousands_len)
-	  {
-	    for (cnt = 0; cnt < thousands_len; ++cnt)
-	      if (thousands[cnt] != s[cnt])
-		break;
-	    if (cnt == thousands_len)
-	      {
-		s += thousands_len - 1;
-		continue;
-	      }
-	    if (ISALPHA (c))
-	      c = TOUPPER (c) - L_('A') + 10;
-	    else
-	      break;
-	  }
-# endif
-#endif
-	else if (ISALPHA (c))
-	  c = TOUPPER (c) - L_('A') + 10;
-	else
-	  break;
-	if ((int) c >= base)
-	  break;
-	/* Check for overflow.  */
-	if (i > cutoff || (i == cutoff && c > cutlim))
-	  overflow = 1;
-	else
-	  {
-	  use_long:
-	    i *= (unsigned LONG int) base;
-	    i += c;
-	  }
-      }
-
-  /* Check if anything actually happened.  */
-  if (s == save)
-    goto noconv;
-
-  /* Store in ENDPTR the address of one character
-     past the last character we converted.  */
-  if (endptr != NULL)
-    *endptr = (STRING_TYPE *) s;
-
-#if !UNSIGNED
-  /* Check for a value that is within the range of
-     `unsigned LONG int', but outside the range of `LONG int'.  */
-  if (overflow == 0
-      && i > (negative
-	      ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
-	      : (unsigned LONG int) STRTOL_LONG_MAX))
-    overflow = 1;
-#endif
-
-  if (__builtin_expect (overflow, 0))
-    {
-      __set_errno (ERANGE);
-#if UNSIGNED
-      return STRTOL_ULONG_MAX;
-#else
-      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
-#endif
-    }
-
-  /* Return the result of the appropriate sign.  */
-  return negative ? -i : i;
-
-noconv:
-  /* We must handle a special case here: the base is 0 or 16 and the
-     first two characters are '0' and 'x', but the rest are no
-     hexadecimal digits.  This is no error case.  We return 0 and
-     ENDPTR points to the `x`.  */
-  if (endptr != NULL)
-    {
-      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 = (STRING_TYPE *) nptr;
-    }
-
-  return 0L;
+  return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
 }
-#if defined _LIBC \
-    && !(defined USE_IN_EXTENDED_LOCALE_MODEL && defined USE_WIDE_CHAR)
 libc_hidden_def (INTERNAL (strtol))
-#endif
-
-/* External user entry point.  */
-
-#if _LIBC - 0 == 0
-# undef PARAMS
-# if defined (__STDC__) && __STDC__
-#  define PARAMS(Args) Args
-# else
-#  define PARAMS(Args) ()
-# endif
-
-/* Prototype.  */
-INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
-#endif
 
 
 INT
-#ifdef weak_function
-weak_function
-#endif
-strtol (nptr, endptr, base LOCALE_PARAM)
+strtol (nptr, endptr, base)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
      int base;
-     LOCALE_PARAM_DECL
 {
-  return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
+  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, _NL_CURRENT_LOCALE);
 }
diff --git a/sysdeps/generic/strtol_l.c b/sysdeps/generic/strtol_l.c
index e4c3140a03..a3800d6f78 100644
--- a/sysdeps/generic/strtol_l.c
+++ b/sysdeps/generic/strtol_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,13 +18,496 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
 
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef _LIBC
+# define USE_NUMBER_GROUPING
+# define STDC_HEADERS
+# define HAVE_LIMITS_H
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef __set_errno
+# define __set_errno(Val) errno = (Val)
+#endif
+
+#ifdef HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
 #include <xlocale.h>
 
-extern long int ____strtol_l_internal (const char *, char **, int, int,
-				       __locale_t);
+#ifdef USE_NUMBER_GROUPING
+# include "../locale/localeinfo.h"
+#endif
+
+/* Nonzero if we are defining `strtoul' or `strtoull', operating on
+   unsigned integers.  */
+#ifndef UNSIGNED
+# define UNSIGNED 0
+# define INT LONG int
+#else
+# define INT unsigned LONG int
+#endif
+
+/* Determine the name.  */
+#if UNSIGNED
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol_l wcstoull_l
+#  else
+#   define strtol_l wcstoul_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol_l strtoull_l
+#  else
+#   define strtol_l strtoul_l
+#  endif
+# endif
+#else
+# ifdef USE_WIDE_CHAR
+#  ifdef QUAD
+#   define strtol_l wcstoll_l
+#  else
+#   define strtol_l wcstol_l
+#  endif
+# else
+#  ifdef QUAD
+#   define strtol_l strtoll_l
+#  else
+#   define strtol_l strtol_l
+#  endif
+# endif
+#endif
+
+#define __strtol_l __strtol_l2(strtol_l)
+#define __strtol_l2(name) __strtol_l3(name)
+#define __strtol_l3(name) __##name
+
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
+   operating on `long long int's.  */
+#ifdef QUAD
+# define LONG long long
+# define STRTOL_LONG_MIN LONG_LONG_MIN
+# define STRTOL_LONG_MAX LONG_LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_LONG_MAX
+#else
+# define LONG long
+
+# ifndef ULONG_MAX
+#  define ULONG_MAX ((unsigned long int) ~(unsigned long int) 0)
+# endif
+# ifndef LONG_MAX
+#  define LONG_MAX ((long int) (ULONG_MAX >> 1))
+# endif
+# define STRTOL_LONG_MIN LONG_MIN
+# define STRTOL_LONG_MAX LONG_MAX
+# define STRTOL_ULONG_MAX ULONG_MAX
+#endif
+
+
+/* We use this code for the extended locale handling where the
+   function gets as an additional argument the locale which has to be
+   used.  To access the values we have to redefine the _NL_CURRENT and
+   _NL_CURRENT_WORD macros.  */
+#undef _NL_CURRENT
+#define _NL_CURRENT(category, item) \
+  (current->values[_NL_ITEM_INDEX (item)].string)
+#undef _NL_CURRENT_WORD
+#define _NL_CURRENT_WORD(category, item) \
+  ((uint32_t) current->values[_NL_ITEM_INDEX (item)].word)
+
+#if defined _LIBC || defined HAVE_WCHAR_H
+# include <wchar.h>
+#endif
+
+#ifdef USE_WIDE_CHAR
+# include <wctype.h>
+# define L_(Ch) L##Ch
+# define UCHAR_TYPE wint_t
+# define STRING_TYPE wchar_t
+# define ISSPACE(Ch) __iswspace_l ((Ch), loc)
+# define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __towupper_l ((Ch), loc)
+#else
+# if defined _LIBC \
+   || defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+#  define IN_CTYPE_DOMAIN(c) 1
+# else
+#  define IN_CTYPE_DOMAIN(c) isascii(c)
+# endif
+# define L_(Ch) Ch
+# define UCHAR_TYPE unsigned char
+# define STRING_TYPE char
+# define ISSPACE(Ch) __isspace_l ((Ch), loc)
+# define ISALPHA(Ch) __isalpha_l ((Ch), loc)
+# define TOUPPER(Ch) __toupper_l ((Ch), loc)
+#endif
+
+#define INTERNAL(X) INTERNAL1(X)
+#define INTERNAL1(X) __##X##_internal
+#define WEAKNAME(X) WEAKNAME1(X)
+
+#ifdef USE_NUMBER_GROUPING
+/* This file defines a function to check for correct grouping.  */
+# include "grouping.h"
+#endif
+
+
+
+/* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
+   If BASE is 0 the base is determined by the presence of a leading
+   zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
+   If BASE is < 2 or > 36, it is reset to 10.
+   If ENDPTR is not NULL, a pointer to the character after the last
+   one converted is stored in *ENDPTR.  */
+
+INT
+INTERNAL (__strtol_l) (nptr, endptr, base, group, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+     int group;
+     __locale_t loc;
+{
+  int negative;
+  register unsigned LONG int cutoff;
+  register unsigned int cutlim;
+  register unsigned LONG int i;
+  register const STRING_TYPE *s;
+  register UCHAR_TYPE c;
+  const STRING_TYPE *save, *end;
+  int overflow;
+#ifndef USE_WIDE_CHAR
+  size_t cnt;
+#endif
+
+#ifdef USE_NUMBER_GROUPING
+  struct locale_data *current = loc->__locales[LC_NUMERIC];
+  /* The thousands character of the current locale.  */
+# ifdef USE_WIDE_CHAR
+  wchar_t thousands = L'\0';
+# else
+  const char *thousands = NULL;
+  size_t thousands_len = 0;
+# endif
+  /* The numeric grouping specification of the current locale,
+     in the format described in <locale.h>.  */
+  const char *grouping;
+
+  if (__builtin_expect (group, 0))
+    {
+      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
+      if (*grouping <= 0 || *grouping == CHAR_MAX)
+	grouping = NULL;
+      else
+	{
+	  /* Figure out the thousands separator character.  */
+# 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
+    grouping = NULL;
+#endif
+
+  if (base < 0 || base == 1 || base > 36)
+    {
+      __set_errno (EINVAL);
+      return 0;
+    }
+
+  save = s = nptr;
+
+  /* Skip white space.  */
+  while (ISSPACE (*s))
+    ++s;
+  if (__builtin_expect (*s == L_('\0'), 0))
+    goto noconv;
+
+  /* Check for a sign.  */
+  negative = 0;
+  if (*s == L_('-'))
+    {
+      negative = 1;
+      ++s;
+    }
+  else if (*s == L_('+'))
+    ++s;
+
+  /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
+  if (*s == L_('0'))
+    {
+      if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
+	{
+	  s += 2;
+	  base = 16;
+	}
+      else if (base == 0)
+	base = 8;
+    }
+  else if (base == 0)
+    base = 10;
+
+  /* Save the pointer so we can check later if anything happened.  */
+  save = s;
+
+#ifdef USE_NUMBER_GROUPING
+  if (base != 10)
+    grouping = NULL;
+
+  if (__builtin_expect (grouping != NULL, 0))
+    {
+# ifndef USE_WIDE_CHAR
+      thousands_len = strlen (thousands);
+# endif
+
+      /* Find the end of the digit string and check its grouping.  */
+      end = s;
+      if (
+# ifdef USE_WIDE_CHAR
+	  *s != thousands
+# else
+	  ({ for (cnt = 0; cnt < thousands_len; ++cnt)
+	       if (thousands[cnt] != end[cnt])
+		 break;
+	     cnt < thousands_len; })
+# endif
+	  )
+	{
+	  for (c = *end; c != L_('\0'); c = *++end)
+	    if (((STRING_TYPE) c < L_('0') || (STRING_TYPE) c > L_('9'))
+# ifdef USE_WIDE_CHAR
+		&& (wchar_t) c != thousands
+# else
+		&& ({ for (cnt = 0; cnt < thousands_len; ++cnt)
+		      if (thousands[cnt] != end[cnt])
+			break;
+		      cnt < thousands_len; })
+# endif
+		&& (!ISALPHA (c)
+		    || (int) (TOUPPER (c) - L_('A') + 10) >= base))
+	      break;
+
+# ifdef USE_WIDE_CHAR
+	  end = __correctly_grouped_prefixwc (s, end, thousands, grouping);
+# else
+	  end = __correctly_grouped_prefixmb (s, end, thousands, grouping);
+# endif
+	}
+    }
+  else
+#endif
+    end = NULL;
+
+  cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
+  cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
+
+  overflow = 0;
+  i = 0;
+  c = *s;
+  if (sizeof (long int) != sizeof (LONG int))
+    {
+      unsigned long int j = 0;
+      unsigned long int jmax = ULONG_MAX / base;
+
+      for (;c != L_('\0'); c = *++s)
+	{
+	  if (s == end)
+	    break;
+	  if (c >= L_('0') && c <= L_('9'))
+	    c -= L_('0');
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_WIDE_CHAR
+	  else if (grouping && (wchar_t) c == thousands)
+	    continue;
+# else
+	  else if (thousands_len)
+	    {
+	      for (cnt = 0; cnt < thousands_len; ++cnt)
+		if (thousands[cnt] != s[cnt])
+		  break;
+	      if (cnt == thousands_len)
+		{
+		  s += thousands_len - 1;
+		  continue;
+		}
+	      if (ISALPHA (c))
+		c = TOUPPER (c) - L_('A') + 10;
+	      else
+		break;
+	    }
+# endif
+#endif
+	  else if (ISALPHA (c))
+	    c = TOUPPER (c) - L_('A') + 10;
+	  else
+	    break;
+	  if ((int) c >= base)
+	    break;
+	  /* Note that we never can have an overflow.  */
+	  else if (j >= jmax)
+	    {
+	      /* We have an overflow.  Now use the long representation.  */
+	      i = (unsigned LONG int) j;
+	      goto use_long;
+	    }
+	  else
+	    j = j * (unsigned long int) base + c;
+	}
+
+      i = (unsigned LONG int) j;
+    }
+  else
+    for (;c != L_('\0'); c = *++s)
+      {
+	if (s == end)
+	  break;
+	if (c >= L_('0') && c <= L_('9'))
+	  c -= L_('0');
+#ifdef USE_NUMBER_GROUPING
+# ifdef USE_WIDE_CHAR
+	else if (grouping && (wchar_t) c == thousands)
+	  continue;
+# else
+	else if (thousands_len)
+	  {
+	    for (cnt = 0; cnt < thousands_len; ++cnt)
+	      if (thousands[cnt] != s[cnt])
+		break;
+	    if (cnt == thousands_len)
+	      {
+		s += thousands_len - 1;
+		continue;
+	      }
+	    if (ISALPHA (c))
+	      c = TOUPPER (c) - L_('A') + 10;
+	    else
+	      break;
+	  }
+# endif
+#endif
+	else if (ISALPHA (c))
+	  c = TOUPPER (c) - L_('A') + 10;
+	else
+	  break;
+	if ((int) c >= base)
+	  break;
+	/* Check for overflow.  */
+	if (i > cutoff || (i == cutoff && c > cutlim))
+	  overflow = 1;
+	else
+	  {
+	  use_long:
+	    i *= (unsigned LONG int) base;
+	    i += c;
+	  }
+      }
+
+  /* Check if anything actually happened.  */
+  if (s == save)
+    goto noconv;
+
+  /* Store in ENDPTR the address of one character
+     past the last character we converted.  */
+  if (endptr != NULL)
+    *endptr = (STRING_TYPE *) s;
+
+#if !UNSIGNED
+  /* Check for a value that is within the range of
+     `unsigned LONG int', but outside the range of `LONG int'.  */
+  if (overflow == 0
+      && i > (negative
+	      ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
+	      : (unsigned LONG int) STRTOL_LONG_MAX))
+    overflow = 1;
+#endif
+
+  if (__builtin_expect (overflow, 0))
+    {
+      __set_errno (ERANGE);
+#if UNSIGNED
+      return STRTOL_ULONG_MAX;
+#else
+      return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
+#endif
+    }
+
+  /* Return the result of the appropriate sign.  */
+  return negative ? -i : i;
+
+noconv:
+  /* We must handle a special case here: the base is 0 or 16 and the
+     first two characters are '0' and 'x', but the rest are no
+     hexadecimal digits.  This is no error case.  We return 0 and
+     ENDPTR points to the `x`.  */
+  if (endptr != NULL)
+    {
+      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 = (STRING_TYPE *) nptr;
+    }
+
+  return 0L;
+}
+#if defined _LIBC && !defined USE_WIDE_CHAR
+libc_hidden_def (INTERNAL (__strtol_l))
+#endif
+
+/* External user entry point.  */
+
+#if _LIBC - 0 == 0
+# undef PARAMS
+# if defined (__STDC__) && __STDC__
+#  define PARAMS(Args) Args
+# else
+#  define PARAMS(Args) ()
+# endif
+
+/* Prototype.  */
+extern INT __strtol_l PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr,
+			       int base));
+#endif
 
-#include "strtol.c"
 
+INT
+#ifdef weak_function
+weak_function
+#endif
+__strtol_l (nptr, endptr, base, loc)
+     const STRING_TYPE *nptr;
+     STRING_TYPE **endptr;
+     int base;
+     __locale_t loc;
+{
+  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, loc);
+}
 weak_alias (__strtol_l, strtol_l)
diff --git a/sysdeps/generic/strtold.c b/sysdeps/generic/strtold_l.c
index 7303025eff..e43654700f 100644
--- a/sysdeps/generic/strtold.c
+++ b/sysdeps/generic/strtold_l.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2002 Free Software Foundation, Inc.
+/* Copyright (C) 1999, 2002, 2004 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
@@ -18,17 +18,23 @@
 
 #include <math.h>
 #include <stdlib.h>
+#include <xlocale.h>
+
+
+extern double ____strtod_l_internal (const char *, char **, int, __locale_t);
+
 
 /* There is no `long double' type, use the `double' implementations.  */
 long double
-__strtold_internal (const char *nptr, char **endptr, int group)
+____strtold_l_internal (const char *nptr, char **endptr, int group,
+			__locale_t loc)
 {
-  return __strtod_internal (nptr, endptr, group);
+  return ____strtod_l_internal (nptr, endptr, group, loc);
 }
-libc_hidden_def (__strtold_internal)
+
 
 long double
-strtold (const char *nptr, char **endptr)
+strtold (const char *nptr, char **endptr, __locale_t loc)
 {
-  return __strtod_internal (nptr, endptr, 0);
+  return ____strtod_l_internal (nptr, endptr, 0, loc);
 }
diff --git a/sysdeps/generic/strtoll_l.c b/sysdeps/generic/strtoll_l.c
index 5e7ae7674c..7725035bd1 100644
--- a/sysdeps/generic/strtoll_l.c
+++ b/sysdeps/generic/strtoll_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,13 +18,11 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define QUAD	1
 
 #include <xlocale.h>
 
 extern long long int ____strtoll_l_internal (const char *, char **, int, int,
 					     __locale_t);
 
-#include <strtoll.c>
-
-weak_alias (__strtoll_l, strtoll_l)
+#include <strtol_l.c>
diff --git a/sysdeps/generic/strtoul_l.c b/sysdeps/generic/strtoul_l.c
index a049d2d006..a8b980f48d 100644
--- a/sysdeps/generic/strtoul_l.c
+++ b/sysdeps/generic/strtoul_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,13 +18,11 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define UNSIGNED	1
 
 #include <xlocale.h>
 
 extern unsigned long int ____strtoul_l_internal (const char *, char **, int,
 						 int, __locale_t);
 
-#include "strtoul.c"
-
-weak_alias (__strtoul_l, strtoul_l)
+#include "strtol_l.c"
diff --git a/sysdeps/generic/strtoull_l.c b/sysdeps/generic/strtoull_l.c
index 55be504318..68ad0d826e 100644
--- a/sysdeps/generic/strtoull_l.c
+++ b/sysdeps/generic/strtoull_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -18,13 +18,12 @@
    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA.  */
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define QUAD		1
+#define UNSIGNED	1
 
 #include <xlocale.h>
 
 extern unsigned long long int ____strtoull_l_internal (const char *, char **,
 						       int, int, __locale_t);
 
-#include <strtoull.c>
-
-weak_alias (__strtoull_l, strtoull_l)
+#include <strtol_l.c>
diff --git a/sysdeps/generic/wcstol_l.c b/sysdeps/generic/wcstol_l.c
index 91b0d3fa7d..f1b4171f18 100644
--- a/sysdeps/generic/wcstol_l.c
+++ b/sysdeps/generic/wcstol_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -22,11 +22,9 @@
 #include <stddef.h>
 #include <locale.h>
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define	USE_WIDE_CHAR	1
 
 extern long int ____wcstol_l_internal (const wchar_t *, wchar_t **, int, int,
 				       __locale_t);
 
-#include "wcstol.c"
-
-weak_alias (__wcstol_l, wcstol_l)
+#include "strtol_l.c"
diff --git a/sysdeps/generic/wcstoll_l.c b/sysdeps/generic/wcstoll_l.c
index 9ed2c5aca7..f1a4ca1623 100644
--- a/sysdeps/generic/wcstoll_l.c
+++ b/sysdeps/generic/wcstoll_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -22,11 +22,9 @@
 #include <stddef.h>
 #include <locale.h>
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define QUAD	1
 
 extern long long int ____wcstoll_l_internal (const wchar_t *, wchar_t **,
 					     int, int, __locale_t);
 
-#include <wcstoll.c>
-
-weak_alias (__wcstoll_l, wcstoll_l)
+#include <wcstol_l.c>
diff --git a/sysdeps/generic/wcstoul_l.c b/sysdeps/generic/wcstoul_l.c
index 9d567bbcc5..eeee1f0baa 100644
--- a/sysdeps/generic/wcstoul_l.c
+++ b/sysdeps/generic/wcstoul_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -22,11 +22,9 @@
 #include <stddef.h>
 #include <locale.h>
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define UNSIGNED	1
 
 extern unsigned long int ____wcstoul_l_internal (const wchar_t *, wchar_t **,
 						 int, int, __locale_t);
 
-#include <wcstoul.c>
-
-weak_alias (__wcstoul_l, wcstoul_l)
+#include <wcstol_l.c>
diff --git a/sysdeps/generic/wcstoull_l.c b/sysdeps/generic/wcstoull_l.c
index f8f05ba8d8..32bc3c4bb9 100644
--- a/sysdeps/generic/wcstoull_l.c
+++ b/sysdeps/generic/wcstoull_l.c
@@ -1,5 +1,5 @@
 /* Convert string representing a number to integer value, using given locale.
-   Copyright (C) 1997, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1997, 2002, 2004 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -22,12 +22,10 @@
 #include <stddef.h>
 #include <locale.h>
 
-#define USE_IN_EXTENDED_LOCALE_MODEL	1
+#define UNSIGNED	1
 
 extern unsigned long long int ____wcstoull_l_internal (const wchar_t *,
 						       wchar_t **, int, int,
 						       __locale_t);
 
-#include <wcstoull.c>
-
-weak_alias (__wcstoull_l, wcstoull_l)
+#include <wcstoll_l.c>