modules/up/src/Core/util/strtol.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. __set_errno
  2. L_
  3. ISSPACE
  4. ISALPHA
  5. TOUPPER
  6. L_
  7. ISSPACE
  8. ISALPHA
  9. TOUPPER
  10. INTERNAL
  11. INTERNAL1
  12. WEAKNAME
  13. INTERNAL
  14. INTERNAL
  15. PARAMS
  16. PARAMS
  17. strtol

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

/* [<][>][^][v][top][bottom][index][help] */