home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / sh-utils-1.12-src.lha / sh-utils-1.12 / lib / strtol.c < prev    next >
C/C++ Source or Header  |  1994-09-26  |  4KB  |  187 lines

  1. /* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 2, or (at your option)
  6.    any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20.  
  21. #include <ctype.h>
  22. #include <errno.h>
  23.  
  24. #if HAVE_LIMITS_H
  25. #include <limits.h>
  26. #endif
  27.  
  28. #ifndef ULONG_MAX
  29. #define ULONG_MAX ((unsigned long) ~(unsigned long) 0)
  30. #endif
  31.  
  32. #ifndef LONG_MAX
  33. #define    LONG_MAX (~(1 << (sizeof (long) * 8 - 1)))
  34. #endif
  35.  
  36. #ifndef LONG_MIN
  37. #define LONG_MIN (-LONG_MAX - 1)
  38. #endif
  39.  
  40. #if STDC_HEADERS
  41. #include <stddef.h>
  42. #include <stdlib.h>
  43. #else
  44. #define NULL 0
  45. extern int errno;
  46. #endif
  47.  
  48. #ifndef    UNSIGNED
  49. #define    UNSIGNED    0
  50. #endif
  51.  
  52. /* Convert NPTR to an `unsigned long int' or `long int' in base BASE.
  53.    If BASE is 0 the base is determined by the presence of a leading
  54.    zero, indicating octal or a leading "0x" or "0X", indicating hexadecimal.
  55.    If BASE is < 2 or > 36, it is reset to 10.
  56.    If ENDPTR is not NULL, a pointer to the character after the last
  57.    one converted is stored in *ENDPTR.  */
  58. #if    UNSIGNED
  59. unsigned long int
  60. #define    strtol    strtoul
  61. #else
  62. long int
  63. #endif
  64. strtol (nptr, endptr, base)
  65.      const char *nptr;
  66.      char **endptr;
  67.      int base;
  68. {
  69.   int negative;
  70.   register unsigned long int cutoff;
  71.   register unsigned int cutlim;
  72.   register unsigned long int i;
  73.   register const char *s;
  74.   register unsigned char c;
  75.   const char *save;
  76.   int overflow;
  77.  
  78.   if (base < 0 || base == 1 || base > 36)
  79.     base = 10;
  80.  
  81.   s = nptr;
  82.  
  83.   /* Skip white space.  */
  84.   while (isspace (*s))
  85.     ++s;
  86.   if (*s == '\0')
  87.     goto noconv;
  88.  
  89.   /* Check for a sign.  */
  90.   if (*s == '-')
  91.     {
  92.       negative = 1;
  93.       ++s;
  94.     }
  95.   else if (*s == '+')
  96.     {
  97.       negative = 0;
  98.       ++s;
  99.     }
  100.   else
  101.     negative = 0;
  102.  
  103.   if (base == 16 && s[0] == '0' && toupper (s[1]) == 'X')
  104.     s += 2;
  105.  
  106.   /* If BASE is zero, figure it out ourselves.  */
  107.   if (base == 0)
  108.     {
  109.       if (*s == '0')
  110.     {
  111.       if (toupper (s[1]) == 'X')
  112.         {
  113.           s += 2;
  114.           base = 16;
  115.         }
  116.       else
  117.         base = 8;
  118.     }
  119.       else
  120.     base = 10;
  121.     }
  122.  
  123.   /* Save the pointer so we can check later if anything happened.  */
  124.   save = s;
  125.  
  126.   cutoff = ULONG_MAX / (unsigned long int) base;
  127.   cutlim = ULONG_MAX % (unsigned long int) base;
  128.  
  129.   overflow = 0;
  130.   i = 0;
  131.   for (c = *s; c != '\0'; c = *++s)
  132.     {
  133.       if (isdigit (c))
  134.     c -= '0';
  135.       else if (isalpha (c))
  136.     c = toupper (c) - 'A' + 10;
  137.       else
  138.     break;
  139.       if (c >= base)
  140.     break;
  141.       /* Check for overflow.  */
  142.       if (i > cutoff || (i == cutoff && c > cutlim))
  143.     overflow = 1;
  144.       else
  145.     {
  146.       i *= (unsigned long int) base;
  147.       i += c;
  148.     }
  149.     }
  150.  
  151.   /* Check if anything actually happened.  */
  152.   if (s == save)
  153.     goto noconv;
  154.  
  155.   /* Store in ENDPTR the address of one character
  156.      past the last character we converted.  */
  157.   if (endptr != NULL)
  158.     *endptr = (char *) s;
  159.  
  160. #if    !UNSIGNED
  161.   /* Check for a value that is within the range of
  162.      `unsigned long int', but outside the range of `long int'.  */
  163.   if (i > (negative ?
  164.        -(unsigned long int) LONG_MIN : (unsigned long int) LONG_MAX))
  165.     overflow = 1;
  166. #endif
  167.  
  168.   if (overflow)
  169.     {
  170.       errno = ERANGE;
  171. #if    UNSIGNED
  172.       return ULONG_MAX;
  173. #else
  174.       return negative ? LONG_MIN : LONG_MAX;
  175. #endif
  176.     }
  177.  
  178.   /* Return the result of the appropriate sign.  */
  179.   return (negative ? -i : i);
  180.  
  181. noconv:;
  182.   /* There was no number to convert.  */
  183.   if (endptr != NULL)
  184.     *endptr = (char *) nptr;
  185.   return 0L;
  186. }
  187.