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