13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier #define ULONG_MAX 4294967295UL
53e12c5d1SDavid du Colombier
63e12c5d1SDavid du Colombier ulong
strtoul(char * nptr,char ** endptr,int base)73e12c5d1SDavid du Colombier strtoul(char *nptr, char **endptr, int base)
83e12c5d1SDavid du Colombier {
93e12c5d1SDavid du Colombier char *p;
10*7dd7cddfSDavid du Colombier ulong n, nn, m;
113e12c5d1SDavid du Colombier int c, ovfl, neg, v, ndig;
123e12c5d1SDavid du Colombier
13*7dd7cddfSDavid du Colombier p = nptr;
143e12c5d1SDavid du Colombier neg = 0;
153e12c5d1SDavid du Colombier n = 0;
163e12c5d1SDavid du Colombier ndig = 0;
173e12c5d1SDavid du Colombier ovfl = 0;
183e12c5d1SDavid du Colombier
193e12c5d1SDavid du Colombier /*
203e12c5d1SDavid du Colombier * White space
213e12c5d1SDavid du Colombier */
223e12c5d1SDavid du Colombier for(;;p++){
233e12c5d1SDavid du Colombier switch(*p){
243e12c5d1SDavid du Colombier case ' ':
253e12c5d1SDavid du Colombier case '\t':
263e12c5d1SDavid du Colombier case '\n':
273e12c5d1SDavid du Colombier case '\f':
283e12c5d1SDavid du Colombier case '\r':
293e12c5d1SDavid du Colombier case '\v':
303e12c5d1SDavid du Colombier continue;
313e12c5d1SDavid du Colombier }
323e12c5d1SDavid du Colombier break;
333e12c5d1SDavid du Colombier }
343e12c5d1SDavid du Colombier
353e12c5d1SDavid du Colombier /*
363e12c5d1SDavid du Colombier * Sign
373e12c5d1SDavid du Colombier */
383e12c5d1SDavid du Colombier if(*p=='-' || *p=='+')
393e12c5d1SDavid du Colombier if(*p++ == '-')
403e12c5d1SDavid du Colombier neg = 1;
413e12c5d1SDavid du Colombier
423e12c5d1SDavid du Colombier /*
433e12c5d1SDavid du Colombier * Base
443e12c5d1SDavid du Colombier */
453e12c5d1SDavid du Colombier if(base==0){
463e12c5d1SDavid du Colombier if(*p != '0')
473e12c5d1SDavid du Colombier base = 10;
483e12c5d1SDavid du Colombier else{
493e12c5d1SDavid du Colombier base = 8;
50*7dd7cddfSDavid du Colombier if(p[1]=='x' || p[1]=='X')
513e12c5d1SDavid du Colombier base = 16;
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier }
54*7dd7cddfSDavid du Colombier if(base<2 || 36<base)
553e12c5d1SDavid du Colombier goto Return;
56*7dd7cddfSDavid du Colombier if(base==16 && *p=='0'){
57*7dd7cddfSDavid du Colombier if(p[1]=='x' || p[1]=='X')
58*7dd7cddfSDavid du Colombier if(('0' <= p[2] && p[2] <= '9')
59*7dd7cddfSDavid du Colombier ||('a' <= p[2] && p[2] <= 'f')
60*7dd7cddfSDavid du Colombier ||('A' <= p[2] && p[2] <= 'F'))
61*7dd7cddfSDavid du Colombier p += 2;
62*7dd7cddfSDavid du Colombier }
633e12c5d1SDavid du Colombier /*
643e12c5d1SDavid du Colombier * Non-empty sequence of digits
653e12c5d1SDavid du Colombier */
66*7dd7cddfSDavid du Colombier n = 0;
67*7dd7cddfSDavid du Colombier m = ULONG_MAX/base;
683e12c5d1SDavid du Colombier for(;; p++,ndig++){
693e12c5d1SDavid du Colombier c = *p;
703e12c5d1SDavid du Colombier v = base;
713e12c5d1SDavid du Colombier if('0'<=c && c<='9')
723e12c5d1SDavid du Colombier v = c - '0';
733e12c5d1SDavid du Colombier else if('a'<=c && c<='z')
743e12c5d1SDavid du Colombier v = c - 'a' + 10;
753e12c5d1SDavid du Colombier else if('A'<=c && c<='Z')
763e12c5d1SDavid du Colombier v = c - 'A' + 10;
773e12c5d1SDavid du Colombier if(v >= base)
783e12c5d1SDavid du Colombier break;
79*7dd7cddfSDavid du Colombier if(n > m)
80*7dd7cddfSDavid du Colombier ovfl = 1;
813e12c5d1SDavid du Colombier nn = n*base + v;
823e12c5d1SDavid du Colombier if(nn < n)
833e12c5d1SDavid du Colombier ovfl = 1;
843e12c5d1SDavid du Colombier n = nn;
853e12c5d1SDavid du Colombier }
863e12c5d1SDavid du Colombier
873e12c5d1SDavid du Colombier Return:
883e12c5d1SDavid du Colombier if(ndig == 0)
893e12c5d1SDavid du Colombier p = nptr;
903e12c5d1SDavid du Colombier if(endptr)
913e12c5d1SDavid du Colombier *endptr = p;
923e12c5d1SDavid du Colombier if(ovfl)
933e12c5d1SDavid du Colombier return ULONG_MAX;
943e12c5d1SDavid du Colombier if(neg)
953e12c5d1SDavid du Colombier return -n;
963e12c5d1SDavid du Colombier return n;
973e12c5d1SDavid du Colombier }
98