Annotation of gforth/engine/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: /* errno.h is needed on SunOS 4.1.2 */
        !            25: #include <errno.h>
        !            26: 
        !            27: #ifndef        UNSIGNED
        !            28: #define        UNSIGNED        0
        !            29: #endif
        !            30: 
        !            31: /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
        !            32:    If BASE is 0 the base is determined by the presence of a leading
        !            33:    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
        !            34:    If BASE is < 2 or > 36, it is reset to 10.
        !            35:    If ENDPTR is not NULL, a pointer to the character after the last
        !            36:    one converted is stored in *ENDPTR.  */
        !            37: #if    UNSIGNED
        !            38: unsigned long int
        !            39: #define        strtol  strtoul
        !            40: #else
        !            41: long int
        !            42: #endif
        !            43: DEFUN(strtol, (nptr, endptr, base),
        !            44:       CONST char *nptr AND char **endptr AND int base)
        !            45: {
        !            46:   int negative;
        !            47:   register unsigned long int cutoff;
        !            48:   register unsigned int cutlim;
        !            49:   register unsigned long int i;
        !            50:   register CONST char *s;
        !            51:   register unsigned char c;
        !            52:   CONST char *save;
        !            53:   int overflow;
        !            54: 
        !            55:   if (base < 0 || base == 1 || base > 36)
        !            56:     base = 10;
        !            57: 
        !            58:   s = nptr;
        !            59: 
        !            60:   /* Skip white space.  */
        !            61:   while (isspace(*s))
        !            62:     ++s;
        !            63:   if (*s == '\0')
        !            64:     goto noconv;
        !            65: 
        !            66:   /* Check for a sign.  */
        !            67:   if (*s == '-')
        !            68:     {
        !            69:       negative = 1;
        !            70:       ++s;
        !            71:     }
        !            72:   else if (*s == '+')
        !            73:     {
        !            74:       negative = 0;
        !            75:       ++s;
        !            76:     }
        !            77:   else
        !            78:     negative = 0;
        !            79: 
        !            80:   if (base == 16 && s[0] == '0' && toupper(s[1]) == 'X')
        !            81:     s += 2;
        !            82: 
        !            83:   /* If BASE is zero, figure it out ourselves.  */
        !            84:   if (base == 0)
        !            85:     if (*s == '0')
        !            86:       {
        !            87:        if (toupper(s[1]) == 'X')
        !            88:          {
        !            89:            s += 2;
        !            90:            base = 16;
        !            91:          }
        !            92:        else
        !            93:          base = 8;
        !            94:       }
        !            95:     else
        !            96:       base = 10;
        !            97: 
        !            98:   /* Save the pointer so we can check later if anything happened.  */
        !            99:   save = s;
        !           100: 
        !           101:   cutoff = ULONG_MAX / (unsigned long int) base;
        !           102:   cutlim = ULONG_MAX % (unsigned long int) base;
        !           103: 
        !           104:   overflow = 0;
        !           105:   i = 0;
        !           106:   for (c = *s; c != '\0'; c = *++s)
        !           107:     {
        !           108:       if (isdigit(c))
        !           109:        c -= '0';
        !           110:       else if (isalpha(c))
        !           111:        c = toupper(c) - 'A' + 10;
        !           112:       else
        !           113:        break;
        !           114:       if (c >= base)
        !           115:        break;
        !           116:       /* Check for overflow.  */
        !           117:       if (i > cutoff || (i == cutoff && c > cutlim))
        !           118:        overflow = 1;
        !           119:       else
        !           120:        {
        !           121:          i *= (unsigned long int) base;
        !           122:          i += c;
        !           123:        }
        !           124:     }
        !           125: 
        !           126:   /* Check if anything actually happened.  */
        !           127:   if (s == save)
        !           128:     goto noconv;
        !           129: 
        !           130:   /* Store in ENDPTR the address of one character
        !           131:      past the last character we converted.  */
        !           132:   if (endptr != NULL)
        !           133:     *endptr = (char *) s;
        !           134: 
        !           135: #if    !UNSIGNED
        !           136:   /* Check for a value that is within the range of
        !           137:      `unsigned long int', but outside the range of `long int'.  */
        !           138:   if (i > (negative ?
        !           139:           - (unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
        !           140:     overflow = 1;
        !           141: #endif
        !           142: 
        !           143:   if (overflow)
        !           144:     {
        !           145:       errno = ERANGE;
        !           146: #if    UNSIGNED
        !           147:       return ULONG_MAX;
        !           148: #else
        !           149:       return negative ? LONG_MIN : LONG_MAX;
        !           150: #endif
        !           151:     }
        !           152: 
        !           153:   /* Return the result of the appropriate sign.  */
        !           154:   return (negative ? - i : i);
        !           155: 
        !           156:  noconv:
        !           157:   /* There was no number to convert.  */
        !           158:   if (endptr != NULL)
        !           159:     *endptr = (char *) nptr;
        !           160:   return 0L;
        !           161: }

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