Annotation of gforth/engine/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
1.2     ! anton      16: not, write to the Free Software Foundation, Inc., 
        !            17: 59 Temple Place, Suite 330, Boston, MA 02111, USA.  */
1.1       anton      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>