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