(root)/
tar-1.35/
gnu/
strtol.c
       1  /* Convert string representation of a number into an integer value.
       2  
       3     Copyright (C) 1991-1992, 1994-1999, 2003, 2005-2007, 2009-2023 Free Software
       4     Foundation, Inc.
       5  
       6     NOTE: The canonical source of this file is maintained with the GNU C
       7     Library.  Bugs can be reported to bug-glibc@gnu.org.
       8  
       9     This file is free software: you can redistribute it and/or modify
      10     it under the terms of the GNU Lesser General Public License as
      11     published by the Free Software Foundation, either version 3 of the
      12     License, or (at your option) any later version.
      13  
      14     This file is distributed in the hope that it will be useful,
      15     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17     GNU Lesser General Public License for more details.
      18  
      19     You should have received a copy of the GNU Lesser General Public License
      20     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      21  
      22  #ifdef _LIBC
      23  # define USE_NUMBER_GROUPING
      24  #else
      25  # include <config.h>
      26  #endif
      27  
      28  #include <ctype.h>
      29  #include <errno.h>
      30  #ifndef __set_errno
      31  # define __set_errno(Val) errno = (Val)
      32  #endif
      33  
      34  #include <limits.h>
      35  #include <stddef.h>
      36  #include <stdlib.h>
      37  #include <string.h>
      38  
      39  #ifdef USE_NUMBER_GROUPING
      40  # include "../locale/localeinfo.h"
      41  #endif
      42  
      43  /* Nonzero if we are defining 'strtoul' or 'strtoull', operating on
      44     unsigned integers.  */
      45  #ifndef UNSIGNED
      46  # define UNSIGNED 0
      47  # define INT LONG int
      48  #else
      49  # define INT unsigned LONG int
      50  #endif
      51  
      52  /* Determine the name.  */
      53  #ifdef USE_IN_EXTENDED_LOCALE_MODEL
      54  # undef strtol
      55  # if UNSIGNED
      56  #  ifdef USE_WIDE_CHAR
      57  #   ifdef QUAD
      58  #    define strtol __wcstoull_l
      59  #   else
      60  #    define strtol __wcstoul_l
      61  #   endif
      62  #  else
      63  #   ifdef QUAD
      64  #    define strtol __strtoull_l
      65  #   else
      66  #    define strtol __strtoul_l
      67  #   endif
      68  #  endif
      69  # else
      70  #  ifdef USE_WIDE_CHAR
      71  #   ifdef QUAD
      72  #    define strtol __wcstoll_l
      73  #   else
      74  #    define strtol __wcstol_l
      75  #   endif
      76  #  else
      77  #   ifdef QUAD
      78  #    define strtol __strtoll_l
      79  #   else
      80  #    define strtol __strtol_l
      81  #   endif
      82  #  endif
      83  # endif
      84  #else
      85  # if UNSIGNED
      86  #  undef strtol
      87  #  ifdef USE_WIDE_CHAR
      88  #   ifdef QUAD
      89  #    define strtol wcstoull
      90  #   else
      91  #    define strtol wcstoul
      92  #   endif
      93  #  else
      94  #   ifdef QUAD
      95  #    define strtol strtoull
      96  #   else
      97  #    define strtol strtoul
      98  #   endif
      99  #  endif
     100  # else
     101  #  ifdef USE_WIDE_CHAR
     102  #   undef strtol
     103  #   ifdef QUAD
     104  #    define strtol wcstoll
     105  #   else
     106  #    define strtol wcstol
     107  #   endif
     108  #  else
     109  #   ifdef QUAD
     110  #    undef strtol
     111  #    define strtol strtoll
     112  #   endif
     113  #  endif
     114  # endif
     115  #endif
     116  
     117  /* If QUAD is defined, we are defining 'strtoll' or 'strtoull',
     118     operating on 'long long int's.  */
     119  #ifdef QUAD
     120  # define LONG long long
     121  # define STRTOL_LONG_MIN LLONG_MIN
     122  # define STRTOL_LONG_MAX LLONG_MAX
     123  # define STRTOL_ULONG_MAX ULLONG_MAX
     124  # if __GNUC__ == 2 && __GNUC_MINOR__ < 7
     125     /* Work around gcc bug with using this constant.  */
     126     static const unsigned long long int maxquad = ULLONG_MAX;
     127  #  undef STRTOL_ULONG_MAX
     128  #  define STRTOL_ULONG_MAX maxquad
     129  # endif
     130  #else
     131  # define LONG long
     132  # define STRTOL_LONG_MIN LONG_MIN
     133  # define STRTOL_LONG_MAX LONG_MAX
     134  # define STRTOL_ULONG_MAX ULONG_MAX
     135  #endif
     136  
     137  
     138  #ifdef USE_NUMBER_GROUPING
     139  # define GROUP_PARAM_PROTO , int group
     140  #else
     141  # define GROUP_PARAM_PROTO
     142  #endif
     143  
     144  /* We use this code also for the extended locale handling where the
     145     function gets as an additional argument the locale which has to be
     146     used.  To access the values we have to redefine the _NL_CURRENT
     147     macro.  */
     148  #ifdef USE_IN_EXTENDED_LOCALE_MODEL
     149  # undef _NL_CURRENT
     150  # define _NL_CURRENT(category, item) \
     151    (current->values[_NL_ITEM_INDEX (item)].string)
     152  # define LOCALE_PARAM , loc
     153  # define LOCALE_PARAM_PROTO , __locale_t loc
     154  #else
     155  # define LOCALE_PARAM
     156  # define LOCALE_PARAM_PROTO
     157  #endif
     158  
     159  #ifdef USE_WIDE_CHAR
     160  # include <wchar.h>
     161  # include <wctype.h>
     162  # define L_(Ch) L##Ch
     163  # define UCHAR_TYPE wint_t
     164  # define STRING_TYPE wchar_t
     165  # ifdef USE_IN_EXTENDED_LOCALE_MODEL
     166  #  define ISSPACE(Ch) __iswspace_l ((Ch), loc)
     167  #  define ISALPHA(Ch) __iswalpha_l ((Ch), loc)
     168  #  define TOUPPER(Ch) __towupper_l ((Ch), loc)
     169  # else
     170  #  define ISSPACE(Ch) iswspace (Ch)
     171  #  define ISALPHA(Ch) iswalpha (Ch)
     172  #  define TOUPPER(Ch) towupper (Ch)
     173  # endif
     174  #else
     175  # define L_(Ch) Ch
     176  # define UCHAR_TYPE unsigned char
     177  # define STRING_TYPE char
     178  # ifdef USE_IN_EXTENDED_LOCALE_MODEL
     179  #  define ISSPACE(Ch) __isspace_l ((unsigned char) (Ch), loc)
     180  #  define ISALPHA(Ch) __isalpha_l ((unsigned char) (Ch), loc)
     181  #  define TOUPPER(Ch) __toupper_l ((unsigned char) (Ch), loc)
     182  # else
     183  #  define ISSPACE(Ch) isspace ((unsigned char) (Ch))
     184  #  define ISALPHA(Ch) isalpha ((unsigned char) (Ch))
     185  #  define TOUPPER(Ch) toupper ((unsigned char) (Ch))
     186  # endif
     187  #endif
     188  
     189  #ifdef USE_NUMBER_GROUPING
     190  # define INTERNAL(X) INTERNAL1(X)
     191  # define INTERNAL1(X) __##X##_internal
     192  # define WEAKNAME(X) WEAKNAME1(X)
     193  #else
     194  # define INTERNAL(X) X
     195  #endif
     196  
     197  #ifdef USE_NUMBER_GROUPING
     198  /* This file defines a function to check for correct grouping.  */
     199  # include "grouping.h"
     200  #endif
     201  
     202  
     203  
     204  /* Convert NPTR to an 'unsigned long int' or 'long int' in base BASE.
     205     If BASE is 0 the base is determined by the presence of a leading
     206     zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
     207     If BASE is < 2 or > 36, it is reset to 10.
     208     If ENDPTR is not NULL, a pointer to the character after the last
     209     one converted is stored in *ENDPTR.  */
     210  
     211  INT
     212  INTERNAL (strtol) (const STRING_TYPE *nptr, STRING_TYPE **endptr,
     213                     int base GROUP_PARAM_PROTO LOCALE_PARAM_PROTO)
     214  {
     215    int negative;
     216    register unsigned LONG int cutoff;
     217    register unsigned int cutlim;
     218    register unsigned LONG int i;
     219    register const STRING_TYPE *s;
     220    register UCHAR_TYPE c;
     221    const STRING_TYPE *save, *end;
     222    int overflow;
     223  
     224  #ifdef USE_NUMBER_GROUPING
     225  # ifdef USE_IN_EXTENDED_LOCALE_MODEL
     226    struct locale_data *current = loc->__locales[LC_NUMERIC];
     227  # endif
     228    /* The thousands character of the current locale.  */
     229    wchar_t thousands = L'\0';
     230    /* The numeric grouping specification of the current locale,
     231       in the format described in <locale.h>.  */
     232    const char *grouping;
     233  
     234    if (group)
     235      {
     236        grouping = _NL_CURRENT (LC_NUMERIC, GROUPING);
     237        if (*grouping <= 0 || *grouping == CHAR_MAX)
     238          grouping = NULL;
     239        else
     240          {
     241            /* Figure out the thousands separator character.  */
     242  # if defined _LIBC || defined _HAVE_BTOWC
     243            thousands = __btowc (*_NL_CURRENT (LC_NUMERIC, THOUSANDS_SEP));
     244            if (thousands == WEOF)
     245              thousands = L'\0';
     246  # endif
     247            if (thousands == L'\0')
     248              grouping = NULL;
     249          }
     250      }
     251    else
     252      grouping = NULL;
     253  #endif
     254  
     255    if (base < 0 || base == 1 || base > 36)
     256      {
     257        __set_errno (EINVAL);
     258        return 0;
     259      }
     260  
     261    save = s = nptr;
     262  
     263    /* Skip white space.  */
     264    while (ISSPACE (*s))
     265      ++s;
     266    if (*s == L_('\0'))
     267      goto noconv;
     268  
     269    /* Check for a sign.  */
     270    if (*s == L_('-'))
     271      {
     272        negative = 1;
     273        ++s;
     274      }
     275    else if (*s == L_('+'))
     276      {
     277        negative = 0;
     278        ++s;
     279      }
     280    else
     281      negative = 0;
     282  
     283    /* Recognize number prefix and if BASE is zero, figure it out ourselves.  */
     284    if (*s == L_('0'))
     285      {
     286        if ((base == 0 || base == 16) && TOUPPER (s[1]) == L_('X'))
     287          {
     288            s += 2;
     289            base = 16;
     290          }
     291        else if ((base == 0 || base == 2) && TOUPPER (s[1]) == L_('B'))
     292          {
     293            s += 2;
     294            base = 2;
     295          }
     296        else if (base == 0)
     297          base = 8;
     298      }
     299    else if (base == 0)
     300      base = 10;
     301  
     302    /* Save the pointer so we can check later if anything happened.  */
     303    save = s;
     304  
     305  #ifdef USE_NUMBER_GROUPING
     306    if (group)
     307      {
     308        /* Find the end of the digit string and check its grouping.  */
     309        end = s;
     310        for (c = *end; c != L_('\0'); c = *++end)
     311          if ((wchar_t) c != thousands
     312              && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
     313              && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
     314            break;
     315        if (*s == thousands)
     316          end = s;
     317        else
     318          end = correctly_grouped_prefix (s, end, thousands, grouping);
     319      }
     320    else
     321  #endif
     322      end = NULL;
     323  
     324    cutoff = STRTOL_ULONG_MAX / (unsigned LONG int) base;
     325    cutlim = STRTOL_ULONG_MAX % (unsigned LONG int) base;
     326  
     327    overflow = 0;
     328    i = 0;
     329    for (c = *s; c != L_('\0'); c = *++s)
     330      {
     331        if (s == end)
     332          break;
     333        if (c >= L_('0') && c <= L_('9'))
     334          c -= L_('0');
     335        else if (ISALPHA (c))
     336          c = TOUPPER (c) - L_('A') + 10;
     337        else
     338          break;
     339        if ((int) c >= base)
     340          break;
     341        /* Check for overflow.  */
     342        if (i > cutoff || (i == cutoff && c > cutlim))
     343          overflow = 1;
     344        else
     345          {
     346            i *= (unsigned LONG int) base;
     347            i += c;
     348          }
     349      }
     350  
     351    /* Check if anything actually happened.  */
     352    if (s == save)
     353      goto noconv;
     354  
     355    /* Store in ENDPTR the address of one character
     356       past the last character we converted.  */
     357    if (endptr != NULL)
     358      *endptr = (STRING_TYPE *) s;
     359  
     360  #if !UNSIGNED
     361    /* Check for a value that is within the range of
     362       'unsigned LONG int', but outside the range of 'LONG int'.  */
     363    if (overflow == 0
     364        && i > (negative
     365                ? -((unsigned LONG int) (STRTOL_LONG_MIN + 1)) + 1
     366                : (unsigned LONG int) STRTOL_LONG_MAX))
     367      overflow = 1;
     368  #endif
     369  
     370    if (overflow)
     371      {
     372        __set_errno (ERANGE);
     373  #if UNSIGNED
     374        return STRTOL_ULONG_MAX;
     375  #else
     376        return negative ? STRTOL_LONG_MIN : STRTOL_LONG_MAX;
     377  #endif
     378      }
     379  
     380    /* Return the result of the appropriate sign.  */
     381    return negative ? -i : i;
     382  
     383  noconv:
     384    /* We must handle a special case here: the base is 0 or 16 and the
     385       first two characters are '0' and 'x', but the rest are no
     386       hexadecimal digits.  Likewise when the base is 0 or 2 and the
     387       first two characters are '0' and 'b', but the rest are no binary
     388       digits.  This is no error case.  We return 0 and ENDPTR points to
     389       the 'x' or 'b'.  */
     390    if (endptr != NULL)
     391      {
     392        if (save - nptr >= 2
     393            && (TOUPPER (save[-1]) == L_('X') || TOUPPER (save[-1]) == L_('B'))
     394            && save[-2] == L_('0'))
     395          *endptr = (STRING_TYPE *) &save[-1];
     396        else
     397          /*  There was no number to convert.  */
     398          *endptr = (STRING_TYPE *) nptr;
     399      }
     400  
     401    return 0L;
     402  }
     403  
     404  #ifdef USE_NUMBER_GROUPING
     405  /* External user entry point.  */
     406  
     407  INT
     408  # ifdef weak_function
     409  weak_function
     410  # endif
     411  strtol (const STRING_TYPE *nptr, STRING_TYPE **endptr,
     412          int base LOCALE_PARAM_PROTO)
     413  {
     414    return INTERNAL (strtol) (nptr, endptr, base, 0 LOCALE_PARAM);
     415  }
     416  #endif