Annotation of embedaddon/lrzsz/lib/strtol.c, revision 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>