home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / cvs-1.8.7-src.tgz / tar.out / fsf / cvs / lib / strtoul.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  2KB  |  101 lines

  1. /*
  2.  * strtol : convert a string to long.
  3.  *
  4.  * Andy Wilson, 2-Oct-89.
  5.  */
  6.  
  7. #include <errno.h>
  8. #include <ctype.h>
  9. #include <stdio.h>
  10.  
  11. #ifdef HAVE_CONFIG_H
  12. #include "config.h"
  13. #endif
  14.  
  15. #ifndef ULONG_MAX
  16. #define    ULONG_MAX    ((unsigned long)(~0L))        /* 0xFFFFFFFF */
  17. #endif
  18.  
  19. extern int errno;
  20.  
  21. unsigned long
  22. strtoul(s, ptr, base)
  23.      const char *s; char **ptr; int base;
  24. {
  25.   unsigned long total = 0;
  26.   unsigned digit;
  27.   const char *start=s;
  28.   int did_conversion=0;
  29.   int overflow = 0;
  30.   int negate = 0;
  31.   unsigned long maxdiv, maxrem;
  32.  
  33.   if (s==NULL)
  34.     {
  35.       errno = ERANGE;
  36.       if (!ptr)
  37.     *ptr = (char *)start;
  38.       return 0L;
  39.     }
  40.  
  41.   while (isspace(*s))
  42.     s++;
  43.   if (*s == '+')
  44.     s++;
  45.   else if (*s == '-')
  46.     s++, negate = 1;
  47.   if (base==0 || base==16) /*  the 'base==16' is for handling 0x */
  48.     {
  49.       int tmp;
  50.  
  51.       /*
  52.        * try to infer base from the string
  53.        */
  54.       if (*s != '0')
  55.         tmp = 10;    /* doesn't start with 0 - assume decimal */
  56.       else if (s[1] == 'X' || s[1] == 'x')
  57.     tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
  58.       else
  59.     tmp = 8;    /* starts with 0 - hence octal */
  60.       if (base==0)
  61.     base = (int)tmp;
  62.     }
  63.  
  64.   maxdiv = ULONG_MAX / base;
  65.   maxrem = ULONG_MAX % base;
  66.  
  67.   while ((digit = *s) != '\0')
  68.     {
  69.       if (digit >= '0' && digit < ('0'+base))
  70.     digit -= '0';
  71.       else
  72.     if (base > 10)
  73.       {
  74.         if (digit >= 'a' && digit < ('a'+(base-10)))
  75.           digit = digit - 'a' + 10;
  76.         else if (digit >= 'A' && digit < ('A'+(base-10)))
  77.           digit = digit - 'A' + 10;
  78.         else
  79.           break;
  80.       }
  81.     else
  82.       break;
  83.       did_conversion = 1;
  84.       if (total > maxdiv
  85.       || (total == maxdiv && digit > maxrem))
  86.     overflow = 1;
  87.       total = (total * base) + digit;
  88.       s++;
  89.     }
  90.   if (overflow)
  91.     {
  92.       errno = ERANGE;
  93.       if (ptr != NULL)
  94.     *ptr = (char *)s;
  95.       return (ULONG_MAX);
  96.     }
  97.   if (ptr != NULL)
  98.     *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
  99.   return negate ? -total : total;
  100. }
  101.