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