File:  [gforth] / gforth / Attic / strtol.c
Revision 1.2: download - view: text, annotated - select for diffs
Fri Dec 16 18:14:58 1994 UTC (29 years, 4 months ago) by anton
Branches: MAIN
CVS tags: HEAD
fixed a bug in sparc.h
brought strtoul closer to compiling on the SPARC (but it still does not)

    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>