xref: /plan9/sys/src/ape/lib/ap/gen/strtoull.c (revision d9306527b4a7229dcf0cf3c58aed36bb9da82854)
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