home *** CD-ROM | disk | FTP | other *** search
- /*
- * strtol : convert a string to long.
- *
- * Andy Wilson, 2-Oct-89.
- */
-
- #include <errno.h>
- #include <ctype.h>
- #include <stdio.h>
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #ifndef ULONG_MAX
- #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */
- #endif
-
- extern int errno;
-
- unsigned long
- strtoul(s, ptr, base)
- const char *s; char **ptr; int base;
- {
- unsigned long total = 0;
- unsigned digit;
- const char *start=s;
- int did_conversion=0;
- int overflow = 0;
- int negate = 0;
- unsigned long maxdiv, maxrem;
-
- if (s==NULL)
- {
- errno = ERANGE;
- if (!ptr)
- *ptr = (char *)start;
- return 0L;
- }
-
- while (isspace(*s))
- s++;
- if (*s == '+')
- s++;
- else if (*s == '-')
- s++, negate = 1;
- if (base==0 || base==16) /* the 'base==16' is for handling 0x */
- {
- int tmp;
-
- /*
- * try to infer base from the string
- */
- if (*s != '0')
- tmp = 10; /* doesn't start with 0 - assume decimal */
- else if (s[1] == 'X' || s[1] == 'x')
- tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */
- else
- tmp = 8; /* starts with 0 - hence octal */
- if (base==0)
- base = (int)tmp;
- }
-
- maxdiv = ULONG_MAX / base;
- maxrem = ULONG_MAX % base;
-
- while ((digit = *s) != '\0')
- {
- if (digit >= '0' && digit < ('0'+base))
- digit -= '0';
- else
- if (base > 10)
- {
- if (digit >= 'a' && digit < ('a'+(base-10)))
- digit = digit - 'a' + 10;
- else if (digit >= 'A' && digit < ('A'+(base-10)))
- digit = digit - 'A' + 10;
- else
- break;
- }
- else
- break;
- did_conversion = 1;
- if (total > maxdiv
- || (total == maxdiv && digit > maxrem))
- overflow = 1;
- total = (total * base) + digit;
- s++;
- }
- if (overflow)
- {
- errno = ERANGE;
- if (ptr != NULL)
- *ptr = (char *)s;
- return (ULONG_MAX);
- }
- if (ptr != NULL)
- *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start);
- return negate ? -total : total;
- }
-