File:  [gforth] / gforth / engine / strtol.c
Revision 1.1: download - view: text, annotated - select for diffs
Wed May 21 20:40:11 1997 UTC (26 years, 10 months ago) by anton
Branches: MAIN
CVS tags: v0-4-0, HEAD
jwilke's changes:
Moved many files to other directories
renamed many files
other changes unknown to me.

    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>