1704f219phk/*-
24736ccfpfg * SPDX-License-Identifier: BSD-3-Clause
34736ccfpfg *
4704f219phk * Copyright (c) 1990, 1993
5704f219phk *	The Regents of the University of California.  All rights reserved.
6704f219phk *
7704f219phk * This code is derived from software contributed to Berkeley by
8704f219phk * Chris Torek.
9704f219phk *
10704f219phk * Redistribution and use in source and binary forms, with or without
11704f219phk * modification, are permitted provided that the following conditions
12704f219phk * are met:
13704f219phk * 1. Redistributions of source code must retain the above copyright
14704f219phk *    notice, this list of conditions and the following disclaimer.
15704f219phk * 2. Redistributions in binary form must reproduce the above copyright
16704f219phk *    notice, this list of conditions and the following disclaimer in the
17704f219phk *    documentation and/or other materials provided with the distribution.
187e6cabdimp * 3. Neither the name of the University nor the names of its contributors
19704f219phk *    may be used to endorse or promote products derived from this software
20704f219phk *    without specific prior written permission.
21704f219phk *
22704f219phk * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23704f219phk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24704f219phk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25704f219phk * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26704f219phk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27704f219phk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28704f219phk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29704f219phk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30704f219phk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31704f219phk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32704f219phk * SUCH DAMAGE.
33704f219phk *
348b64eb1obrien * From: @(#)strtoul.c	8.1 (Berkeley) 6/4/93
35704f219phk */
36704f219phk
378b64eb1obrien#include <sys/cdefs.h>
388b64eb1obrien__FBSDID("$FreeBSD$");
398b64eb1obrien
40704f219phk#include <sys/param.h>
41704f219phk#include <sys/systm.h>
42704f219phk#include <sys/ctype.h>
439468fdakan#include <sys/limits.h>
44704f219phk
45704f219phk/*
46704f219phk * Convert a string to an unsigned long integer.
47704f219phk *
48704f219phk * Ignores `locale' stuff.  Assumes that the upper and lower case
49704f219phk * alphabets and digits are each contiguous.
50704f219phk */
51704f219phkunsigned long
52cfbcdfbemastestrtoul(const char *nptr, char **endptr, int base)
53704f219phk{
54704f219phk	const char *s = nptr;
55704f219phk	unsigned long acc;
56704f219phk	unsigned char c;
57704f219phk	unsigned long cutoff;
58704f219phk	int neg = 0, any, cutlim;
59704f219phk
60704f219phk	/*
61704f219phk	 * See strtol for comments as to the logic used.
62704f219phk	 */
63704f219phk	do {
64704f219phk		c = *s++;
65704f219phk	} while (isspace(c));
66704f219phk	if (c == '-') {
67704f219phk		neg = 1;
68704f219phk		c = *s++;
69704f219phk	} else if (c == '+')
70704f219phk		c = *s++;
71704f219phk	if ((base == 0 || base == 16) &&
72704f219phk	    c == '0' && (*s == 'x' || *s == 'X')) {
73704f219phk		c = s[1];
74704f219phk		s += 2;
75704f219phk		base = 16;
76704f219phk	}
77704f219phk	if (base == 0)
78704f219phk		base = c == '0' ? 8 : 10;
79704f219phk	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
80704f219phk	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
81704f219phk	for (acc = 0, any = 0;; c = *s++) {
82704f219phk		if (!isascii(c))
83704f219phk			break;
84704f219phk		if (isdigit(c))
85704f219phk			c -= '0';
86704f219phk		else if (isalpha(c))
87704f219phk			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
88704f219phk		else
89704f219phk			break;
90704f219phk		if (c >= base)
91704f219phk			break;
92704f219phk		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
93704f219phk			any = -1;
94704f219phk		else {
95704f219phk			any = 1;
96704f219phk			acc *= base;
97704f219phk			acc += c;
98704f219phk		}
99704f219phk	}
100704f219phk	if (any < 0) {
101704f219phk		acc = ULONG_MAX;
102704f219phk	} else if (neg)
103704f219phk		acc = -acc;
1045b34217pfg	if (endptr != NULL)
1057004e07dim		*endptr = __DECONST(char *, any ? s - 1 : nptr);
106704f219phk	return (acc);
107704f219phk}
108