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   /* Save the pointer so we can check later if anything happened.  */
 251   save = s;
 252 
 253 #ifdef USE_NUMBER_GROUPING
 254   if (group)
 255     {
 256       /* Find the end of the digit string and check its grouping.  */
 257       end = s;
 258       for (c = *end; c != L_('\0'); c = *++end)
 259         if ((wchar_t) c != thousands
 260             && ((wchar_t) c < L_('0') || (wchar_t) c > L_('9'))
 261             && (!ISALPHA (c) || (int) (TOUPPER (c) - L_('A') + 10) >= base))
 262           break;
 263       if (*s == thousands)
 264         end = s;
 265       else
 266         end = correctly_grouped_prefix (s, end, thousands, grouping);
 267     }
 268   else
 269 #endif
 270     end = NULL;
 271 
 272   cutoff = ULONG_MAX / (unsigned LONG int) base;
 273   cutlim = ULONG_MAX % (unsigned LONG int) base;
 274 
 275   overflow = 0;
 276   i = 0;
 277   for (c = *s; c != L_('\0'); c = *++s)
 278     {
 279       if (s == end)
 280         break;
 281       if (c >= L_('0') && c <= L_('9'))
 282         c -= L_('0');
 283       else if (ISALPHA (c))
 284         c = TOUPPER (c) - L_('A') + 10;
 285       else
 286         break;
 287       if ((int) c >= base)
 288         break;
 289       /* Check for overflow.  */
 290       if (i > cutoff || (i == cutoff && c > cutlim))
 291         overflow = 1;
 292       else
 293         {
 294           i *= (unsigned LONG int) base;
 295           i += c;
 296         }
 297     }
 298 
 299   /* Check if anything actually happened.  */
 300   if (s == save)
 301     goto noconv;
 302 
 303   /* Store in ENDPTR the address of one character
 304      past the last character we converted.  */
 305   if (endptr != NULL)
 306     *endptr = (STRING_TYPE *) s;
 307 
 308 #if !UNSIGNED
 309   /* Check for a value that is within the range of
 310      `unsigned LONG int', but outside the range of `LONG int'.  */
 311   if (overflow == 0
 312       && i > (negative
 313               ? -((unsigned LONG int) (LONG_MIN + 1)) + 1
 314               : (unsigned LONG int) LONG_MAX))
 315     overflow = 1;
 316 #endif
 317 
 318   if (overflow)
 319     {
 320       __set_errno (ERANGE);
 321 #if UNSIGNED
 322       return ULONG_MAX;
 323 #else
 324       return negative ? LONG_MIN : LONG_MAX;
 325 #endif
 326     }
 327 
 328   /* Return the result of the appropriate sign.  */
 329   return (negative ? -i : i);
 330 
 331 noconv:
 332   /* We must handle a special case here: the base is 0 or 16 and the
 333      first two characters are '0' and 'x', but the rest are no
 334      hexadecimal digits.  This is no error case.  We return 0 and
 335      ENDPTR points to the `x`.  */
 336   if (endptr != NULL)
 337     if (save - nptr >= 2 && TOUPPER (save[-1]) == L_('X')
 338         && save[-2] == L_('0'))
 339       *endptr = (STRING_TYPE *) &save[-1];
 340     else
 341       /*  There was no number to convert.  */
 342       *endptr = (STRING_TYPE *) nptr;
 343 
 344   return 0L;
 345 }
 346 
 347 /* External user entry point.  */
 348 
 349 #if _LIBC - 0 == 0
 350 # undef PARAMS
 351 # if defined (__STDC__) && __STDC__
 352 #  define PARAMS(Args) Args
     /* [<][>][^][v][top][bottom][index][help] */
 353 # else
 354 #  define PARAMS(Args) ()
     /* [<][>][^][v][top][bottom][index][help] */
 355 # endif
 356 
 357 /* Prototype.  */
 358 INT strtol PARAMS ((const STRING_TYPE *nptr, STRING_TYPE **endptr, int base));
 359 #endif
 360 
 361 
 362 INT
 363 #ifdef weak_function
 364 weak_function
 365 #endif
 366 strtol (nptr, endptr, base)
     /* [<][>][^][v][top][bottom][index][help] */
 367      const STRING_TYPE *nptr;
 368      STRING_TYPE **endptr;
 369      int base;
 370 {
 371   return INTERNAL (strtol) (nptr, endptr, base, 0);
 372 }

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