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