171671b9obrien/*
271671b9obrien * Copyright (c) 1990 Regents of the University of California.
371671b9obrien * All rights reserved.
471671b9obrien *
571671b9obrien * Redistribution and use in source and binary forms, with or without
671671b9obrien * modification, are permitted provided that the following conditions
771671b9obrien * are met:
871671b9obrien * 1. Redistributions of source code must retain the above copyright
971671b9obrien *    notice, this list of conditions and the following disclaimer.
1071671b9obrien * 2. Redistributions in binary form must reproduce the above copyright
1171671b9obrien *    notice, this list of conditions and the following disclaimer in the
1271671b9obrien *    documentation and/or other materials provided with the distribution.
1371671b9obrien * 3. [rescinded 22 July 1999]
1471671b9obrien * 4. Neither the name of the University nor the names of its contributors
1571671b9obrien *    may be used to endorse or promote products derived from this software
1671671b9obrien *    without specific prior written permission.
1771671b9obrien *
1871671b9obrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1971671b9obrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2071671b9obrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2171671b9obrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2271671b9obrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2371671b9obrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2471671b9obrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2571671b9obrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2671671b9obrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2771671b9obrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2871671b9obrien * SUCH DAMAGE.
2971671b9obrien */
3071671b9obrien
3171671b9obrien#ifdef HAVE_CONFIG_H
3271671b9obrien#include "config.h"
3371671b9obrien#endif
3471671b9obrien#ifdef HAVE_LIMITS_H
3571671b9obrien#include <limits.h>
3671671b9obrien#endif
3771671b9obrien#ifdef HAVE_SYS_PARAM_H
3871671b9obrien#include <sys/param.h>
3971671b9obrien#endif
4071671b9obrien#include <errno.h>
4171671b9obrien#ifdef NEED_DECLARATION_ERRNO
4271671b9obrienextern int errno;
4371671b9obrien#endif
4471671b9obrien#if 0
4571671b9obrien#include <stdlib.h>
4671671b9obrien#endif
4771671b9obrien#include "ansidecl.h"
4871671b9obrien#include "safe-ctype.h"
4971671b9obrien
5071671b9obrien#ifndef ULONG_MAX
5171671b9obrien#define	ULONG_MAX	((unsigned long)(~0L))		/* 0xFFFFFFFF */
5271671b9obrien#endif
5371671b9obrien
5471671b9obrien/*
5571671b9obrien * Convert a string to an unsigned long integer.
5671671b9obrien *
5771671b9obrien * Ignores `locale' stuff.  Assumes that the upper and lower case
5871671b9obrien * alphabets and digits are each contiguous.
5971671b9obrien */
6071671b9obrienunsigned long
610acbbeedimstrtoul(const char *nptr, char **endptr, register int base)
6271671b9obrien{
6371671b9obrien	register const char *s = nptr;
6471671b9obrien	register unsigned long acc;
6571671b9obrien	register int c;
6671671b9obrien	register unsigned long cutoff;
6771671b9obrien	register int neg = 0, any, cutlim;
6871671b9obrien
6971671b9obrien	/*
7071671b9obrien	 * See strtol for comments as to the logic used.
7171671b9obrien	 */
7271671b9obrien	do {
7371671b9obrien		c = *s++;
7471671b9obrien	} while (ISSPACE(c));
7571671b9obrien	if (c == '-') {
7671671b9obrien		neg = 1;
7771671b9obrien		c = *s++;
7871671b9obrien	} else if (c == '+')
7971671b9obrien		c = *s++;
8071671b9obrien	if ((base == 0 || base == 16) &&
8171671b9obrien	    c == '0' && (*s == 'x' || *s == 'X')) {
8271671b9obrien		c = s[1];
8371671b9obrien		s += 2;
8471671b9obrien		base = 16;
8571671b9obrien	}
8671671b9obrien	if (base == 0)
8771671b9obrien		base = c == '0' ? 8 : 10;
8871671b9obrien	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
8971671b9obrien	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
9071671b9obrien	for (acc = 0, any = 0;; c = *s++) {
9171671b9obrien		if (ISDIGIT(c))
9271671b9obrien			c -= '0';
9371671b9obrien		else if (ISALPHA(c))
9471671b9obrien			c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10;
9571671b9obrien		else
9671671b9obrien			break;
9771671b9obrien		if (c >= base)
9871671b9obrien			break;
9971671b9obrien		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
10071671b9obrien			any = -1;
10171671b9obrien		else {
10271671b9obrien			any = 1;
10371671b9obrien			acc *= base;
10471671b9obrien			acc += c;
10571671b9obrien		}
10671671b9obrien	}
10771671b9obrien	if (any < 0) {
10871671b9obrien		acc = ULONG_MAX;
10971671b9obrien		errno = ERANGE;
11071671b9obrien	} else if (neg)
11171671b9obrien		acc = -acc;
11271671b9obrien	if (endptr != 0)
11371671b9obrien		*endptr = (char *) (any ? s - 1 : nptr);
11471671b9obrien	return (acc);
11571671b9obrien}
116