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