1 #include <stdlib.h>
2 #include <errno.h>
3 #include <limits.h>
4
5 #define UVLONG_MAX (1LL<<63)
6
7 unsigned long long
strtoull(char * nptr,char ** endptr,int base)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