Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 1994 DJ Delorie, see COPYING.DJ for details */
  2. #include <limits.h>
  3. #include <ctype.h>
  4. #include <errno.h>
  5. #include <stdlib.h>
  6. #include <libc/unconst.h>
  7.  
  8. /*
  9.  * Convert a string to an unsigned long integer.
  10.  *
  11.  * Ignores `locale' stuff.  Assumes that the upper and lower case
  12.  * alphabets and digits are each contiguous.
  13.  */
  14. unsigned long
  15. strtoul(const char *nptr, char **endptr, int base)
  16. {
  17.   const char *s = nptr;
  18.   unsigned long acc;
  19.   int c;
  20.   unsigned long cutoff;
  21.   int neg = 0, any, cutlim;
  22.  
  23.   /*
  24.    * See strtol for comments as to the logic used.
  25.    */
  26.   do {
  27.     c = *s++;
  28.   } while (isspace(c));
  29.   if (c == '-')
  30.   {
  31.     neg = 1;
  32.     c = *s++;
  33.   }
  34.   else if (c == '+')
  35.     c = *s++;
  36.   if ((base == 0 || base == 16) &&
  37.       c == '0' && (*s == 'x' || *s == 'X'))
  38.   {
  39.     c = s[1];
  40.     s += 2;
  41.     base = 16;
  42.   }
  43.   if (base == 0)
  44.     base = c == '0' ? 8 : 10;
  45.   cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
  46.   cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
  47.   for (acc = 0, any = 0;; c = *s++)
  48.   {
  49.     if (isdigit(c))
  50.       c -= '0';
  51.     else if (isalpha(c))
  52.       c -= isupper(c) ? 'A' - 10 : 'a' - 10;
  53.     else
  54.       break;
  55.     if (c >= base)
  56.       break;
  57.     if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
  58.       any = -1;
  59.     else {
  60.       any = 1;
  61.       acc *= base;
  62.       acc += c;
  63.     }
  64.   }
  65.   if (any < 0)
  66.   {
  67.     acc = ULONG_MAX;
  68.     errno = ERANGE;
  69.   }
  70.   else if (neg)
  71.     acc = -acc;
  72.   if (endptr != 0)
  73.     *endptr = any ? unconst(s, char *) - 1 : unconst(nptr, char *);
  74.   return acc;
  75. }
  76.