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