119304Speter/*
219304Speter * Copyright (c) 1990, 1993
319304Speter *	The Regents of the University of California.  All rights reserved.
419304Speter *
519304Speter * Redistribution and use in source and binary forms, with or without
619304Speter * modification, are permitted provided that the following conditions
719304Speter * are met:
819304Speter * 1. Redistributions of source code must retain the above copyright
919304Speter *    notice, this list of conditions and the following disclaimer.
1019304Speter * 2. Redistributions in binary form must reproduce the above copyright
1119304Speter *    notice, this list of conditions and the following disclaimer in the
1219304Speter *    documentation and/or other materials provided with the distribution.
1319304Speter * 3. All advertising materials mentioning features or use of this software
1419304Speter *    must display the following acknowledgement:
1519304Speter *	This product includes software developed by the University of
1619304Speter *	California, Berkeley and its contributors.
1719304Speter * 4. Neither the name of the University nor the names of its contributors
1819304Speter *    may be used to endorse or promote products derived from this software
1919304Speter *    without specific prior written permission.
2019304Speter *
2119304Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2219304Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2319304Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2419304Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2519304Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2619304Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2719304Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2819304Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2919304Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3019304Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3119304Speter * SUCH DAMAGE.
3219304Speter */
3319304Speter
3419304Speter#include "config.h"
3519304Speter
3619304Speter#if defined(LIBC_SCCS) && !defined(lint)
3719304Speterstatic const char sccsid[] = "@(#)strtoul.c	8.1 (Berkeley) 6/4/93";
3819304Speter#endif /* LIBC_SCCS and not lint */
3919304Speter
4019304Speter#include <limits.h>
4119304Speter#include <ctype.h>
4219304Speter#include <errno.h>
4319304Speter#include <stdlib.h>
4419304Speter
4519304Speter/*
4619304Speter * Convert a string to an unsigned long integer.
4719304Speter *
4819304Speter * Ignores `locale' stuff.  Assumes that the upper and lower case
4919304Speter * alphabets and digits are each contiguous.
5019304Speter *
5119304Speter * PUBLIC: #ifndef HAVE_STRTOUL
5219304Speter * PUBLIC: unsigned long strtoul __P((const char *, char **, int));
5319304Speter * PUBLIC: #endif
5419304Speter */
5519304Speterunsigned long
5619304Speterstrtoul(nptr, endptr, base)
5719304Speter	const char *nptr;
5819304Speter	char **endptr;
5919304Speter	register int base;
6019304Speter{
6119304Speter	register const char *s = nptr;
6219304Speter	register unsigned long acc;
6319304Speter	register int c;
6419304Speter	register unsigned long cutoff;
6519304Speter	register int neg = 0, any, cutlim;
6619304Speter
6719304Speter	/*
6819304Speter	 * See strtol for comments as to the logic used.
6919304Speter	 */
7019304Speter	do {
7119304Speter		c = *s++;
7219304Speter	} while (isspace(c));
7319304Speter	if (c == '-') {
7419304Speter		neg = 1;
7519304Speter		c = *s++;
7619304Speter	} else if (c == '+')
7719304Speter		c = *s++;
7819304Speter	if ((base == 0 || base == 16) &&
7919304Speter	    c == '0' && (*s == 'x' || *s == 'X')) {
8019304Speter		c = s[1];
8119304Speter		s += 2;
8219304Speter		base = 16;
8319304Speter	}
8419304Speter	if (base == 0)
8519304Speter		base = c == '0' ? 8 : 10;
8619304Speter	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
8719304Speter	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
8819304Speter	for (acc = 0, any = 0;; c = *s++) {
8919304Speter		if (isdigit(c))
9019304Speter			c -= '0';
9119304Speter		else if (isalpha(c))
9219304Speter			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
9319304Speter		else
9419304Speter			break;
9519304Speter		if (c >= base)
9619304Speter			break;
9719304Speter		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
9819304Speter			any = -1;
9919304Speter		else {
10019304Speter			any = 1;
10119304Speter			acc *= base;
10219304Speter			acc += c;
10319304Speter		}
10419304Speter	}
10519304Speter	if (any < 0) {
10619304Speter		acc = ULONG_MAX;
10719304Speter		errno = ERANGE;
10819304Speter	} else if (neg)
10919304Speter		acc = -acc;
11019304Speter	if (endptr != 0)
11119304Speter		*endptr = (char *)(any ? s - 1 : nptr);
11219304Speter	return (acc);
11319304Speter}
114