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