13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier #define LONG_MAX 2147483647L
53e12c5d1SDavid du Colombier #define LONG_MIN -2147483648L
63e12c5d1SDavid du Colombier
73e12c5d1SDavid du Colombier long
strtol(char * nptr,char ** endptr,int base)83e12c5d1SDavid du Colombier strtol(char *nptr, char **endptr, int base)
93e12c5d1SDavid du Colombier {
103e12c5d1SDavid du Colombier char *p;
11*7dd7cddfSDavid du Colombier long n, nn, m;
123e12c5d1SDavid du Colombier int c, ovfl, v, neg, ndig;
133e12c5d1SDavid du Colombier
143e12c5d1SDavid du Colombier p = nptr;
153e12c5d1SDavid du Colombier neg = 0;
163e12c5d1SDavid du Colombier n = 0;
173e12c5d1SDavid du Colombier ndig = 0;
183e12c5d1SDavid du Colombier ovfl = 0;
193e12c5d1SDavid du Colombier
203e12c5d1SDavid du Colombier /*
213e12c5d1SDavid du Colombier * White space
223e12c5d1SDavid du Colombier */
233e12c5d1SDavid du Colombier for(;; p++) {
243e12c5d1SDavid du Colombier switch(*p) {
253e12c5d1SDavid du Colombier case ' ':
263e12c5d1SDavid du Colombier case '\t':
273e12c5d1SDavid du Colombier case '\n':
283e12c5d1SDavid du Colombier case '\f':
293e12c5d1SDavid du Colombier case '\r':
303e12c5d1SDavid du Colombier case '\v':
313e12c5d1SDavid du Colombier continue;
323e12c5d1SDavid du Colombier }
333e12c5d1SDavid du Colombier break;
343e12c5d1SDavid du Colombier }
353e12c5d1SDavid du Colombier
363e12c5d1SDavid du Colombier /*
373e12c5d1SDavid du Colombier * Sign
383e12c5d1SDavid du Colombier */
393e12c5d1SDavid du Colombier if(*p=='-' || *p=='+')
403e12c5d1SDavid du Colombier if(*p++ == '-')
413e12c5d1SDavid du Colombier neg = 1;
423e12c5d1SDavid du Colombier
433e12c5d1SDavid du Colombier /*
443e12c5d1SDavid du Colombier * Base
453e12c5d1SDavid du Colombier */
463e12c5d1SDavid du Colombier if(base==0) {
473e12c5d1SDavid du Colombier base = 10;
48*7dd7cddfSDavid du Colombier if(*p == '0') {
493e12c5d1SDavid du Colombier base = 8;
503e12c5d1SDavid du Colombier if(p[1]=='x' || p[1]=='X') {
513e12c5d1SDavid du Colombier p += 2;
523e12c5d1SDavid du Colombier base = 16;
533e12c5d1SDavid du Colombier }
543e12c5d1SDavid du Colombier }
55*7dd7cddfSDavid du Colombier } else
56*7dd7cddfSDavid du Colombier if(base==16 && *p=='0'){
573e12c5d1SDavid du Colombier if(p[1]=='x' || p[1]=='X')
583e12c5d1SDavid du Colombier p += 2;
59*7dd7cddfSDavid du Colombier } else
60*7dd7cddfSDavid du Colombier if(base<0 || 36<base)
613e12c5d1SDavid du Colombier goto Return;
623e12c5d1SDavid du Colombier
633e12c5d1SDavid du Colombier /*
643e12c5d1SDavid du Colombier * Non-empty sequence of digits
653e12c5d1SDavid du Colombier */
66*7dd7cddfSDavid du Colombier m = LONG_MAX/base;
673e12c5d1SDavid du Colombier for(;; p++,ndig++){
683e12c5d1SDavid du Colombier c = *p;
693e12c5d1SDavid du Colombier v = base;
703e12c5d1SDavid du Colombier if('0'<=c && c<='9')
713e12c5d1SDavid du Colombier v = c - '0';
72*7dd7cddfSDavid du Colombier else
73*7dd7cddfSDavid du Colombier if('a'<=c && c<='z')
743e12c5d1SDavid du Colombier v = c - 'a' + 10;
75*7dd7cddfSDavid du Colombier else
76*7dd7cddfSDavid du Colombier if('A'<=c && c<='Z')
773e12c5d1SDavid du Colombier v = c - 'A' + 10;
783e12c5d1SDavid du Colombier if(v >= base)
793e12c5d1SDavid du Colombier break;
80*7dd7cddfSDavid du Colombier if(n > m)
81*7dd7cddfSDavid du Colombier ovfl = 1;
823e12c5d1SDavid du Colombier nn = n*base + v;
833e12c5d1SDavid du Colombier if(nn < n)
843e12c5d1SDavid du Colombier ovfl = 1;
853e12c5d1SDavid du Colombier n = nn;
863e12c5d1SDavid du Colombier }
873e12c5d1SDavid du Colombier
883e12c5d1SDavid du Colombier Return:
893e12c5d1SDavid du Colombier if(ndig == 0)
903e12c5d1SDavid du Colombier p = nptr;
913e12c5d1SDavid du Colombier if(endptr)
923e12c5d1SDavid du Colombier *endptr = p;
933e12c5d1SDavid du Colombier if(ovfl){
943e12c5d1SDavid du Colombier if(neg)
953e12c5d1SDavid du Colombier return LONG_MIN;
963e12c5d1SDavid du Colombier return LONG_MAX;
973e12c5d1SDavid du Colombier }
983e12c5d1SDavid du Colombier if(neg)
993e12c5d1SDavid du Colombier return -n;
1003e12c5d1SDavid du Colombier return n;
1013e12c5d1SDavid du Colombier }
102