1 #include <stdlib.h> 2 #include <errno.h> 3 #include <limits.h> 4 5 unsigned long 6 strtoul(const char *nptr, char **endptr, int base) 7 { 8 const char *p; 9 unsigned long n, nn; 10 int c, ovfl, neg, v, ndig; 11 12 p = (char*)nptr; 13 neg = 0; 14 n = 0; 15 ndig = 0; 16 ovfl = 0; 17 18 /* 19 * White space 20 */ 21 for(;;p++){ 22 switch(*p){ 23 case ' ': 24 case '\t': 25 case '\n': 26 case '\f': 27 case '\r': 28 case '\v': 29 continue; 30 } 31 break; 32 } 33 34 /* 35 * Sign 36 */ 37 if(*p=='-' || *p=='+') 38 if(*p++ == '-') 39 neg = 1; 40 41 /* 42 * Base 43 */ 44 if(base==0){ 45 if(*p != '0') 46 base = 10; 47 else{ 48 base = 8; 49 if(p[1]=='x' || p[1]=='X'){ 50 p += 2; 51 base = 16; 52 } 53 } 54 }else if(base==16 && *p=='0'){ 55 if(p[1]=='x' || p[1]=='X') 56 p += 2; 57 }else if(base<0 || 36<base) 58 goto Return; 59 60 /* 61 * Non-empty sequence of digits 62 */ 63 for(;; p++,ndig++){ 64 c = *p; 65 v = base; 66 if('0'<=c && c<='9') 67 v = c - '0'; 68 else if('a'<=c && c<='z') 69 v = c - 'a' + 10; 70 else if('A'<=c && c<='Z') 71 v = c - 'A' + 10; 72 if(v >= base) 73 break; 74 nn = n*base + v; 75 if(nn < n) 76 ovfl = 1; 77 n = nn; 78 } 79 80 Return: 81 if(ndig == 0) 82 p = nptr; 83 if(endptr) 84 *endptr = (char *)p; 85 if(ovfl){ 86 errno = ERANGE; 87 return ULONG_MAX; 88 } 89 if(neg) 90 return -n; 91 return n; 92 } 93