1135446Strhodes/*
2262706Serwin * Copyright (C) 2004, 2005, 2007, 2014  Internet Systems Consortium, Inc. ("ISC")
3135446Strhodes * Copyright (C) 2003  Internet Software Consortium.
4135446Strhodes *
5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any
6135446Strhodes * purpose with or without fee is hereby granted, provided that the above
7135446Strhodes * copyright notice and this permission notice appear in all copies.
8135446Strhodes *
9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11135446Strhodes * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15135446Strhodes * PERFORMANCE OF THIS SOFTWARE.
16135446Strhodes */
17135446Strhodes
18135446Strhodes/*
19135446Strhodes * Copyright (c) 1990, 1993
20135446Strhodes *	The Regents of the University of California.  All rights reserved.
21135446Strhodes *
22135446Strhodes * Redistribution and use in source and binary forms, with or without
23135446Strhodes * modification, are permitted provided that the following conditions
24135446Strhodes * are met:
25135446Strhodes * 1. Redistributions of source code must retain the above copyright
26135446Strhodes *    notice, this list of conditions and the following disclaimer.
27135446Strhodes * 2. Redistributions in binary form must reproduce the above copyright
28135446Strhodes *    notice, this list of conditions and the following disclaimer in the
29135446Strhodes *    documentation and/or other materials provided with the distribution.
30262706Serwin * 3. Neither the name of the University nor the names of its contributors
31135446Strhodes *    may be used to endorse or promote products derived from this software
32135446Strhodes *    without specific prior written permission.
33135446Strhodes *
34135446Strhodes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35135446Strhodes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36135446Strhodes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37135446Strhodes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38135446Strhodes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39135446Strhodes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40135446Strhodes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41135446Strhodes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42135446Strhodes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43135446Strhodes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44135446Strhodes * SUCH DAMAGE.
45135446Strhodes */
46135446Strhodes
47170222Sdougb/*! \file */
48135446Strhodes#if defined(LIBC_SCCS) && !defined(lint)
49135446Strhodesstatic char sccsid[] = "@(#)strtoul.c	8.1 (Berkeley) 6/4/93";
50135446Strhodes#endif /* LIBC_SCCS and not lint */
51135446Strhodes
52234010Sdougb/* $Id: strtoul.c,v 1.7 2007/06/19 23:47:17 tbox Exp $ */
53135446Strhodes
54135446Strhodes#include <config.h>
55135446Strhodes
56135446Strhodes#include <limits.h>
57135446Strhodes#include <ctype.h>
58135446Strhodes#include <errno.h>
59135446Strhodes
60135446Strhodes#include <isc/stdlib.h>
61135446Strhodes#include <isc/util.h>
62135446Strhodes
63170222Sdougb/*!
64135446Strhodes * Convert a string to an unsigned long integer.
65135446Strhodes *
66135446Strhodes * Ignores `locale' stuff.  Assumes that the upper and lower case
67135446Strhodes * alphabets and digits are each contiguous.
68135446Strhodes */
69135446Strhodesunsigned long
70135446Strhodesisc_strtoul(const char *nptr, char **endptr, int base) {
71135446Strhodes	const char *s = nptr;
72135446Strhodes	unsigned long acc;
73135446Strhodes	unsigned char c;
74135446Strhodes	unsigned long cutoff;
75135446Strhodes	int neg = 0, any, cutlim;
76135446Strhodes
77135446Strhodes	/*
78135446Strhodes	 * See strtol for comments as to the logic used.
79135446Strhodes	 */
80135446Strhodes	do {
81135446Strhodes		c = *s++;
82135446Strhodes	} while (isspace(c));
83135446Strhodes	if (c == '-') {
84135446Strhodes		neg = 1;
85135446Strhodes		c = *s++;
86135446Strhodes	} else if (c == '+')
87135446Strhodes		c = *s++;
88135446Strhodes	if ((base == 0 || base == 16) &&
89135446Strhodes	    c == '0' && (*s == 'x' || *s == 'X')) {
90135446Strhodes		c = s[1];
91135446Strhodes		s += 2;
92135446Strhodes		base = 16;
93135446Strhodes	}
94135446Strhodes	if (base == 0)
95135446Strhodes		base = c == '0' ? 8 : 10;
96135446Strhodes	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
97135446Strhodes	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
98135446Strhodes	for (acc = 0, any = 0;; c = *s++) {
99135446Strhodes		if (!isascii(c))
100135446Strhodes			break;
101135446Strhodes		if (isdigit(c))
102135446Strhodes			c -= '0';
103135446Strhodes		else if (isalpha(c))
104135446Strhodes			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
105135446Strhodes		else
106135446Strhodes			break;
107135446Strhodes		if (c >= base)
108135446Strhodes			break;
109135446Strhodes		if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
110135446Strhodes			any = -1;
111135446Strhodes		else {
112135446Strhodes			any = 1;
113135446Strhodes			acc *= base;
114135446Strhodes			acc += c;
115135446Strhodes		}
116135446Strhodes	}
117135446Strhodes	if (any < 0) {
118135446Strhodes		acc = ULONG_MAX;
119135446Strhodes		errno = ERANGE;
120135446Strhodes	} else if (neg)
121135446Strhodes		acc = -acc;
122135446Strhodes	if (endptr != 0)
123135446Strhodes		DE_CONST(any ? s - 1 : nptr, *endptr);
124135446Strhodes	return (acc);
125135446Strhodes}
126