Annotation of embedaddon/lrzsz/lib/strtol.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>