1 #include "lib9.h"
2
3 #define UVLONG_MAX ((uvlong)1<<63)
4
5 uvlong
strtoull(const char * nptr,char ** endptr,int base)6 strtoull(const char *nptr, char **endptr, int base)
7 {
8 const char *p;
9 uvlong n, nn, m;
10 int c, ovfl, v, neg, ndig;
11
12 p = 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 base = 10;
46 if(*p == '0') {
47 base = 8;
48 if(p[1] == 'x' || p[1] == 'X'){
49 p += 2;
50 base = 16;
51 }
52 }
53 } else
54 if(base == 16 && *p == '0') {
55 if(p[1] == 'x' || p[1] == 'X')
56 p += 2;
57 } else
58 if(base < 0 || 36 < base)
59 goto Return;
60
61 /*
62 * Non-empty sequence of digits
63 */
64 m = UVLONG_MAX/base;
65 for(;; p++,ndig++) {
66 c = *p;
67 v = base;
68 if('0' <= c && c <= '9')
69 v = c - '0';
70 else
71 if('a' <= c && c <= 'z')
72 v = c - 'a' + 10;
73 else
74 if('A' <= c && c <= 'Z')
75 v = c - 'A' + 10;
76 if(v >= base)
77 break;
78 if(n > m)
79 ovfl = 1;
80 nn = n*base + v;
81 if(nn < n)
82 ovfl = 1;
83 n = nn;
84 }
85
86 Return:
87 if(ndig == 0)
88 p = nptr;
89 if(endptr)
90 *endptr = (char*)p;
91 if(ovfl)
92 return UVLONG_MAX;
93 if(neg)
94 return -n;
95 return n;
96 }
97