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