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