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