Annotation of gforth/strtol.c, revision 1.1

1.1     ! anton       1: /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
        !             2: This file is part of the GNU C Library.
        !             3: 
        !             4: The GNU C Library is free software; you can redistribute it and/or
        !             5: modify it under the terms of the GNU Library General Public License as
        !             6: published by the Free Software Foundation; either version 2 of the
        !             7: License, or (at your option) any later version.
        !             8: 
        !             9: The GNU C Library is distributed in the hope that it will be useful,
        !            10: but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12: Library General Public License for more details.
        !            13: 
        !            14: You should have received a copy of the GNU Library General Public
        !            15: License along with the GNU C Library; see the file COPYING.LIB.  If
        !            16: not, write to the Free Software Foundation, Inc., 675 Mass Ave,
        !            17: Cambridge, MA 02139, USA.  */
        !            18: 
        !            19: #include <ansidecl.h>
        !            20: #include <ctype.h>
        !            21: #include <limits.h>
        !            22: #include <stddef.h>
        !            23: #include <stdlib.h>
        !            24: 
        !            25: 
        !            26: #ifndef        UNSIGNED
        !            27: #define        UNSIGNED        0
        !            28: #endif
        !            29: 
        !            30: /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
        !            31:    If BASE is 0 the base is determined by the presence of a leading
        !            32:    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
        !            33:    If BASE is < 2 or > 36, it is reset to 10.
        !            34:    If ENDPTR is not NULL, a pointer to the character after the last
        !            35:    one converted is stored in *ENDPTR.  */
        !            36: #if    UNSIGNED
        !            37: unsigned long int
        !            38: #define        strtol  strtoul
        !            39: #else
        !            40: long int
        !            41: #endif
        !            42: DEFUN(strtol, (nptr, endptr, base),
        !            43:       CONST char *nptr AND char **endptr AND int base)
        !            44: {
        !            45:   int negative;
        !            46:   register unsigned long int cutoff;
        !            47:   register unsigned int cutlim;
        !            48:   register unsigned long int i;
        !            49:   register CONST char *s;
        !            50:   register unsigned char c;
        !            51:   CONST char *save;
        !            52:   int overflow;
        !            53: 
        !            54:   if (base < 0 || base == 1 || base > 36)
        !            55:     base = 10;
        !            56: 
        !            57:   s = nptr;
        !            58: 
        !            59:   /* Skip white space.  */
        !            60:   while (isspace(*s))
        !            61:     ++s;
        !            62:   if (*s == '\0')
        !            63:     goto noconv;
        !            64: 
        !            65:   /* Check for a sign.  */
        !            66:   if (*s == '-')
        !            67:     {
        !            68:       negative = 1;
        !            69:       ++s;
        !            70:     }
        !            71:   else if (*s == '+')
        !            72:     {
        !            73:       negative = 0;
        !            74:       ++s;
        !            75:     }
        !            76:   else
        !            77:     negative = 0;
        !            78: 
        !            79:   if (base == 16 && s[0] == '0' && toupper(s[1]) == 'X')
        !            80:     s += 2;
        !            81: 
        !            82:   /* If BASE is zero, figure it out ourselves.  */
        !            83:   if (base == 0)
        !            84:     if (*s == '0')
        !            85:       {
        !            86:        if (toupper(s[1]) == 'X')
        !            87:          {
        !            88:            s += 2;
        !            89:            base = 16;
        !            90:          }
        !            91:        else
        !            92:          base = 8;
        !            93:       }
        !            94:     else
        !            95:       base = 10;
        !            96: 
        !            97:   /* Save the pointer so we can check later if anything happened.  */
        !            98:   save = s;
        !            99: 
        !           100:   cutoff = ULONG_MAX / (unsigned long int) base;
        !           101:   cutlim = ULONG_MAX % (unsigned long int) base;
        !           102: 
        !           103:   overflow = 0;
        !           104:   i = 0;
        !           105:   for (c = *s; c != '\0'; c = *++s)
        !           106:     {
        !           107:       if (isdigit(c))
        !           108:        c -= '0';
        !           109:       else if (isalpha(c))
        !           110:        c = toupper(c) - 'A' + 10;
        !           111:       else
        !           112:        break;
        !           113:       if (c >= base)
        !           114:        break;
        !           115:       /* Check for overflow.  */
        !           116:       if (i > cutoff || (i == cutoff && c > cutlim))
        !           117:        overflow = 1;
        !           118:       else
        !           119:        {
        !           120:          i *= (unsigned long int) base;
        !           121:          i += c;
        !           122:        }
        !           123:     }
        !           124: 
        !           125:   /* Check if anything actually happened.  */
        !           126:   if (s == save)
        !           127:     goto noconv;
        !           128: 
        !           129:   /* Store in ENDPTR the address of one character
        !           130:      past the last character we converted.  */
        !           131:   if (endptr != NULL)
        !           132:     *endptr = (char *) s;
        !           133: 
        !           134: #if    !UNSIGNED
        !           135:   /* Check for a value that is within the range of
        !           136:      `unsigned long int', but outside the range of `long int'.  */
        !           137:   if (i > (negative ?
        !           138:           - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
        !           139:     overflow = 1;
        !           140: #endif
        !           141: 
        !           142:   if (overflow)
        !           143:     {
        !           144:       errno = ERANGE;
        !           145: #if    UNSIGNED
        !           146:       return ULONG_MAX;
        !           147: #else
        !           148:       return negative ? LONG_MIN : LONG_MAX;
        !           149: #endif
        !           150:     }
        !           151: 
        !           152:   /* Return the result of the appropriate sign.  */
        !           153:   return (negative ? - i : i);
        !           154: 
        !           155:  noconv:
        !           156:   /* There was no number to convert.  */
        !           157:   if (endptr != NULL)
        !           158:     *endptr = (char *) nptr;
        !           159:   return 0L;
        !           160: }

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