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