xref: /plan9/sys/src/libc/port/strtoul.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier 
43e12c5d1SDavid du Colombier #define ULONG_MAX	4294967295UL
53e12c5d1SDavid du Colombier 
63e12c5d1SDavid du Colombier ulong
strtoul(char * nptr,char ** endptr,int base)73e12c5d1SDavid du Colombier strtoul(char *nptr, char **endptr, int base)
83e12c5d1SDavid du Colombier {
93e12c5d1SDavid du Colombier 	char *p;
10*7dd7cddfSDavid du Colombier 	ulong n, nn, m;
113e12c5d1SDavid du Colombier 	int c, ovfl, neg, v, ndig;
123e12c5d1SDavid du Colombier 
13*7dd7cddfSDavid du Colombier 	p = nptr;
143e12c5d1SDavid du Colombier 	neg = 0;
153e12c5d1SDavid du Colombier 	n = 0;
163e12c5d1SDavid du Colombier 	ndig = 0;
173e12c5d1SDavid du Colombier 	ovfl = 0;
183e12c5d1SDavid du Colombier 
193e12c5d1SDavid du Colombier 	/*
203e12c5d1SDavid du Colombier 	 * White space
213e12c5d1SDavid du Colombier 	 */
223e12c5d1SDavid du Colombier 	for(;;p++){
233e12c5d1SDavid du Colombier 		switch(*p){
243e12c5d1SDavid du Colombier 		case ' ':
253e12c5d1SDavid du Colombier 		case '\t':
263e12c5d1SDavid du Colombier 		case '\n':
273e12c5d1SDavid du Colombier 		case '\f':
283e12c5d1SDavid du Colombier 		case '\r':
293e12c5d1SDavid du Colombier 		case '\v':
303e12c5d1SDavid du Colombier 			continue;
313e12c5d1SDavid du Colombier 		}
323e12c5d1SDavid du Colombier 		break;
333e12c5d1SDavid du Colombier 	}
343e12c5d1SDavid du Colombier 
353e12c5d1SDavid du Colombier 	/*
363e12c5d1SDavid du Colombier 	 * Sign
373e12c5d1SDavid du Colombier 	 */
383e12c5d1SDavid du Colombier 	if(*p=='-' || *p=='+')
393e12c5d1SDavid du Colombier 		if(*p++ == '-')
403e12c5d1SDavid du Colombier 			neg = 1;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	/*
433e12c5d1SDavid du Colombier 	 * Base
443e12c5d1SDavid du Colombier 	 */
453e12c5d1SDavid du Colombier 	if(base==0){
463e12c5d1SDavid du Colombier 		if(*p != '0')
473e12c5d1SDavid du Colombier 			base = 10;
483e12c5d1SDavid du Colombier 		else{
493e12c5d1SDavid du Colombier 			base = 8;
50*7dd7cddfSDavid du Colombier 			if(p[1]=='x' || p[1]=='X')
513e12c5d1SDavid du Colombier 				base = 16;
523e12c5d1SDavid du Colombier 		}
533e12c5d1SDavid du Colombier 	}
54*7dd7cddfSDavid du Colombier  	if(base<2 || 36<base)
553e12c5d1SDavid du Colombier 		goto Return;
56*7dd7cddfSDavid du Colombier 	if(base==16 && *p=='0'){
57*7dd7cddfSDavid du Colombier 		if(p[1]=='x' || p[1]=='X')
58*7dd7cddfSDavid du Colombier 			if(('0' <= p[2] && p[2] <= '9')
59*7dd7cddfSDavid du Colombier 			 ||('a' <= p[2] && p[2] <= 'f')
60*7dd7cddfSDavid du Colombier 			 ||('A' <= p[2] && p[2] <= 'F'))
61*7dd7cddfSDavid du Colombier 				p += 2;
62*7dd7cddfSDavid du Colombier 	}
633e12c5d1SDavid du Colombier 	/*
643e12c5d1SDavid du Colombier 	 * Non-empty sequence of digits
653e12c5d1SDavid du Colombier 	 */
66*7dd7cddfSDavid du Colombier 	n = 0;
67*7dd7cddfSDavid du Colombier 	m = ULONG_MAX/base;
683e12c5d1SDavid du Colombier 	for(;; p++,ndig++){
693e12c5d1SDavid du Colombier 		c = *p;
703e12c5d1SDavid du Colombier 		v = base;
713e12c5d1SDavid du Colombier 		if('0'<=c && c<='9')
723e12c5d1SDavid du Colombier 			v = c - '0';
733e12c5d1SDavid du Colombier 		else if('a'<=c && c<='z')
743e12c5d1SDavid du Colombier 			v = c - 'a' + 10;
753e12c5d1SDavid du Colombier 		else if('A'<=c && c<='Z')
763e12c5d1SDavid du Colombier 			v = c - 'A' + 10;
773e12c5d1SDavid du Colombier 		if(v >= base)
783e12c5d1SDavid du Colombier 			break;
79*7dd7cddfSDavid du Colombier 		if(n > m)
80*7dd7cddfSDavid du Colombier 			ovfl = 1;
813e12c5d1SDavid du Colombier 		nn = n*base + v;
823e12c5d1SDavid du Colombier 		if(nn < n)
833e12c5d1SDavid du Colombier 			ovfl = 1;
843e12c5d1SDavid du Colombier 		n = nn;
853e12c5d1SDavid du Colombier 	}
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier     Return:
883e12c5d1SDavid du Colombier 	if(ndig == 0)
893e12c5d1SDavid du Colombier 		p = nptr;
903e12c5d1SDavid du Colombier 	if(endptr)
913e12c5d1SDavid du Colombier 		*endptr = p;
923e12c5d1SDavid du Colombier 	if(ovfl)
933e12c5d1SDavid du Colombier 		return ULONG_MAX;
943e12c5d1SDavid du Colombier 	if(neg)
953e12c5d1SDavid du Colombier 		return -n;
963e12c5d1SDavid du Colombier 	return n;
973e12c5d1SDavid du Colombier }
98