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