xref: /csrg-svn/lib/libc/stdlib/strtoul.c (revision 61180)
142116Sbostic /*
2*61180Sbostic  * Copyright (c) 1990, 1993
3*61180Sbostic  *	The Regents of the University of California.  All rights reserved.
442116Sbostic  *
542116Sbostic  * %sccs.include.redist.c%
642116Sbostic  */
742116Sbostic 
842116Sbostic #if defined(LIBC_SCCS) && !defined(lint)
9*61180Sbostic static char sccsid[] = "@(#)strtoul.c	8.1 (Berkeley) 06/04/93";
1042116Sbostic #endif /* LIBC_SCCS and not lint */
1142116Sbostic 
1242116Sbostic #include <limits.h>
1342116Sbostic #include <ctype.h>
1442116Sbostic #include <errno.h>
1542179Sbostic #include <stdlib.h>
1642116Sbostic 
1742116Sbostic /*
1842116Sbostic  * Convert a string to an unsigned long integer.
1942116Sbostic  *
2042116Sbostic  * Ignores `locale' stuff.  Assumes that the upper and lower case
2142116Sbostic  * alphabets and digits are each contiguous.
2242116Sbostic  */
2342116Sbostic unsigned long
strtoul(nptr,endptr,base)2442116Sbostic strtoul(nptr, endptr, base)
2546599Sdonn 	const char *nptr;
2646599Sdonn 	char **endptr;
2742116Sbostic 	register int base;
2842116Sbostic {
2946599Sdonn 	register const char *s = nptr;
3042116Sbostic 	register unsigned long acc;
3142116Sbostic 	register int c;
3242116Sbostic 	register unsigned long cutoff;
3342116Sbostic 	register int neg = 0, any, cutlim;
3442116Sbostic 
3542116Sbostic 	/*
3642116Sbostic 	 * See strtol for comments as to the logic used.
3742116Sbostic 	 */
3842116Sbostic 	do {
3942116Sbostic 		c = *s++;
4042116Sbostic 	} while (isspace(c));
4142116Sbostic 	if (c == '-') {
4242116Sbostic 		neg = 1;
4342116Sbostic 		c = *s++;
4442116Sbostic 	} else if (c == '+')
4542116Sbostic 		c = *s++;
4642116Sbostic 	if ((base == 0 || base == 16) &&
4742116Sbostic 	    c == '0' && (*s == 'x' || *s == 'X')) {
4842116Sbostic 		c = s[1];
4942116Sbostic 		s += 2;
5042116Sbostic 		base = 16;
5142116Sbostic 	}
5242116Sbostic 	if (base == 0)
5342116Sbostic 		base = c == '0' ? 8 : 10;
5442116Sbostic 	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
5542116Sbostic 	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
5642116Sbostic 	for (acc = 0, any = 0;; c = *s++) {
5742116Sbostic 		if (isdigit(c))
5842116Sbostic 			c -= '0';
5942116Sbostic 		else if (isalpha(c))
6042116Sbostic 			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
6142116Sbostic 		else
6242116Sbostic 			break;
6342116Sbostic 		if (c >= base)
6442116Sbostic 			break;
6542116Sbostic 		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
6642116Sbostic 			any = -1;
6742116Sbostic 		else {
6842116Sbostic 			any = 1;
6942116Sbostic 			acc *= base;
7042116Sbostic 			acc += c;
7142116Sbostic 		}
7242116Sbostic 	}
7342116Sbostic 	if (any < 0) {
7442116Sbostic 		acc = ULONG_MAX;
7542116Sbostic 		errno = ERANGE;
7642116Sbostic 	} else if (neg)
7742116Sbostic 		acc = -acc;
7842116Sbostic 	if (endptr != 0)
7958777Storek 		*endptr = (char *)(any ? s - 1 : nptr);
8042116Sbostic 	return (acc);
8142116Sbostic }
82