xref: /csrg-svn/lib/libc/stdlib/strtoul.c (revision 42116)
1*42116Sbostic /*
2*42116Sbostic  * Copyright (c) 1990 Regents of the University of California.
3*42116Sbostic  * All rights reserved.
4*42116Sbostic  *
5*42116Sbostic  * %sccs.include.redist.c%
6*42116Sbostic  */
7*42116Sbostic 
8*42116Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*42116Sbostic static char sccsid[] = "@(#)strtoul.c	5.1 (Berkeley) 05/16/90";
10*42116Sbostic #endif /* LIBC_SCCS and not lint */
11*42116Sbostic 
12*42116Sbostic #include <limits.h>
13*42116Sbostic #include <ctype.h>
14*42116Sbostic #include <errno.h>
15*42116Sbostic 
16*42116Sbostic /*
17*42116Sbostic  * Convert a string to an unsigned long integer.
18*42116Sbostic  *
19*42116Sbostic  * Ignores `locale' stuff.  Assumes that the upper and lower case
20*42116Sbostic  * alphabets and digits are each contiguous.
21*42116Sbostic  */
22*42116Sbostic unsigned long
23*42116Sbostic strtoul(nptr, endptr, base)
24*42116Sbostic 	char *nptr, **endptr;
25*42116Sbostic 	register int base;
26*42116Sbostic {
27*42116Sbostic 	register char *s = nptr;
28*42116Sbostic 	register unsigned long acc;
29*42116Sbostic 	register int c;
30*42116Sbostic 	register unsigned long cutoff;
31*42116Sbostic 	register int neg = 0, any, cutlim;
32*42116Sbostic 
33*42116Sbostic 	/*
34*42116Sbostic 	 * See strtol for comments as to the logic used.
35*42116Sbostic 	 */
36*42116Sbostic 	do {
37*42116Sbostic 		c = *s++;
38*42116Sbostic 	} while (isspace(c));
39*42116Sbostic 	if (c == '-') {
40*42116Sbostic 		neg = 1;
41*42116Sbostic 		c = *s++;
42*42116Sbostic 	} else if (c == '+')
43*42116Sbostic 		c = *s++;
44*42116Sbostic 	if ((base == 0 || base == 16) &&
45*42116Sbostic 	    c == '0' && (*s == 'x' || *s == 'X')) {
46*42116Sbostic 		c = s[1];
47*42116Sbostic 		s += 2;
48*42116Sbostic 		base = 16;
49*42116Sbostic 	}
50*42116Sbostic 	if (base == 0)
51*42116Sbostic 		base = c == '0' ? 8 : 10;
52*42116Sbostic 	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
53*42116Sbostic 	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
54*42116Sbostic 	for (acc = 0, any = 0;; c = *s++) {
55*42116Sbostic 		if (isdigit(c))
56*42116Sbostic 			c -= '0';
57*42116Sbostic 		else if (isalpha(c))
58*42116Sbostic 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
59*42116Sbostic 		else
60*42116Sbostic 			break;
61*42116Sbostic 		if (c >= base)
62*42116Sbostic 			break;
63*42116Sbostic 		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
64*42116Sbostic 			any = -1;
65*42116Sbostic 		else {
66*42116Sbostic 			any = 1;
67*42116Sbostic 			acc *= base;
68*42116Sbostic 			acc += c;
69*42116Sbostic 		}
70*42116Sbostic 	}
71*42116Sbostic 	if (any < 0) {
72*42116Sbostic 		acc = ULONG_MAX;
73*42116Sbostic 		errno = ERANGE;
74*42116Sbostic 	} else if (neg)
75*42116Sbostic 		acc = -acc;
76*42116Sbostic 	if (endptr != 0)
77*42116Sbostic 		*endptr = any ? s - 1 : nptr;
78*42116Sbostic 	return (acc);
79*42116Sbostic }
80