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