Annotation of gforth/strtol.c, revision 1.2

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: 
1.2     ! anton      19: #include "ansidecl.h"
1.1       anton      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>