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