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