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