]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - stdlib/strtol.c
Replace FSF snail mail address with URLs.
[thirdparty/glibc.git] / stdlib / strtol.c
index 5543ab94d1ceab7c3155e48a899e18728ca34b3a..44e2af472ddc41440e9d2206e6a1a81af852f9be 100644 (file)
@@ -1,60 +1,26 @@
-/* Copyright (C) 1991, 92, 94, 95, 96 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Convert string representation of a number into an integer value.
+   Copyright (C) 1991,92,94,95,96,97,98,99,2000,2001,2002,2003,2004,2007
+       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
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser 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.  */
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#ifdef _LIBC
-# define USE_NUMBER_GROUPING
-# define STDC_HEADERS
-# define HAVE_LIMITS_H
-#endif
+#include <stdlib.h>
+#include <wchar.h>
+#include <locale/localeinfo.h>
 
-#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>
-#else
-# ifndef NULL
-#  define NULL 0
-# endif
-#endif
-
-#ifdef USE_NUMBER_GROUPING
-# include "../locale/localeinfo.h"
-#endif
-
-/* Nonzero if we are defining `strtoul' or `strtouq', operating on
-   unsigned integers.  */
 #ifndef UNSIGNED
 # define UNSIGNED 0
 # define INT LONG int
@@ -62,100 +28,65 @@ extern int errno;
 # define INT unsigned LONG int
 #endif
 
-/* Determine the name.  */
 #if UNSIGNED
 # ifdef USE_WIDE_CHAR
 #  ifdef QUAD
-#   define strtol wcstouq
+#   define strtol wcstoull
+#   define __strtol_l __wcstoull_l
 #  else
 #   define strtol wcstoul
+#   define __strtol_l __wcstoul_l
 #  endif
 # else
 #  ifdef QUAD
-#   define strtol strtouq
+#   define strtol strtoull
+#   define __strtol_l __strtoull_l
 #  else
 #   define strtol strtoul
+#   define __strtol_l __strtoul_l
 #  endif
 # endif
 #else
 # ifdef USE_WIDE_CHAR
 #  ifdef QUAD
-#   define strtol wcstoq
+#   define strtol wcstoll
+#   define __strtol_l __wcstoll_l
 #  else
 #   define strtol wcstol
+#   define __strtol_l __wcstol_l
 #  endif
 # else
 #  ifdef QUAD
-#   define strtol strtoq
+#   define strtol strtoll
+#   define __strtol_l __strtoll_l
 #  endif
 # endif
 #endif
 
-/* If QUAD is defined, we are defining `strtoq' or `strtouq',
+
+/* If QUAD is defined, we are defining `strtoll' or `strtoull',
    operating on `long long int's.  */
 #ifdef QUAD
 # define LONG long long
-# undef LONG_MIN
-# define LONG_MIN LONG_LONG_MIN
-# undef LONG_MAX
-# define LONG_MAX LONG_LONG_MAX
-# undef ULONG_MAX
-# define 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 ULONG_MAX
-#  define 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
 #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
-# define WEAKNAME(x) WEAKNAME1(x)
-#else
-# define INTERNAL(x) __/**/x/**/_internal
-#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)
@@ -164,190 +95,17 @@ INTERNAL (strtol) (nptr, endptr, base, group)
      int base;
      int group;
 {
-  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;
-
-#ifdef USE_NUMBER_GROUPING
-  /* The thousands character of the current locale.  */
-  wchar_t thousands;
-  /* The numeric grouping specification of the current locale,
-     in the format described in <locale.h>.  */
-  const char *grouping;
-
-  if (group)
-    {
-      grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
-      if (*grouping <= 0 || *grouping == CHAR_MAX)
-       grouping = NULL;
-      else
-       {
-         /* Figure out the thousands separator character.  */
-         if (mbtowc (&thousands, _NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP),
-                     strlen (_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP))) <= 0)
-           thousands = (wchar_t) *_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP);
-         if (thousands == L'\0')
-           grouping = NULL;
-       }
-    }
-  else
-    grouping = NULL;
-#endif
-
-  if (base < 0 || base == 1 || base > 36)
-    base = 10;
-
-  save = s = nptr;
-
-  /* Skip white space.  */
-  while (ISSPACE (*s))
-    ++s;
-  if (*s == L_('\0'))
-    goto noconv;
-
-  /* Check for a sign.  */
-  if (*s == L_('-'))
-    {
-      negative = 1;
-      ++s;
-    }
-  else if (*s == L_('+'))
-    {
-      negative = 0;
-      ++s;
-    }
-  else
-    negative = 0;
-
-  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 == L_('0'))
-      {
-       if (TOUPPER (s[1]) == L_('X'))
-         {
-           s += 2;
-           base = 16;
-         }
-       else
-         base = 8;
-      }
-    else
-      base = 10;
-
-  /* Save the pointer so we can check later if anything happened.  */
-  save = s;
-
-#ifdef USE_NUMBER_GROUPING
-  if (group)
-    {
-      /* 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);
-    }
-  else
-#endif
-    end = NULL;
-
-  cutoff = ULONG_MAX / (unsigned LONG int) base;
-  cutlim = ULONG_MAX % (unsigned LONG int) base;
-
-  overflow = 0;
-  i = 0;
-  for (c = *s; c != L_('\0'); c = *++s)
-    {
-      if (s == end)
-       break;
-      if (c >= L_('0') && c <= L_('9'))
-       c -= L_('0');
-      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
-       {
-         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) (LONG_MIN + 1)) + 1
-             : (unsigned LONG int) LONG_MAX))
-    overflow = 1;
-#endif
-
-  if (overflow)
-    {
-      __set_errno (ERANGE);
-#if UNSIGNED
-      return ULONG_MAX;
-#else
-      return negative ? LONG_MIN : LONG_MAX;
-#endif
-    }
-
-  /* Return the result of the appropriate sign.  */
-  return (negative ? -i : i);
+  return INTERNAL (__strtol_l) (nptr, endptr, base, group, _NL_CURRENT_LOCALE);
+}
+libc_hidden_def (INTERNAL (strtol))
 
-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;
-}
-\f
-/* External user entry point.  */
 INT
-#ifdef weak_function
-weak_function
-#endif
 strtol (nptr, endptr, base)
      const STRING_TYPE *nptr;
      STRING_TYPE **endptr;
      int base;
 {
-  return INTERNAL (strtol) (nptr, endptr, base, 0);
+  return INTERNAL (__strtol_l) (nptr, endptr, base, 0, _NL_CURRENT_LOCALE);
 }
+libc_hidden_def (strtol)