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