1153816Sdougb/* 2262706Serwin * Copyright (C) 2004, 2005, 2007, 2014 Internet Systems Consortium, Inc. ("ISC") 3153816Sdougb * Copyright (C) 2003 Internet Software Consortium. 4153816Sdougb * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6153816Sdougb * purpose with or without fee is hereby granted, provided that the above 7153816Sdougb * copyright notice and this permission notice appear in all copies. 8153816Sdougb * 9153816Sdougb * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10153816Sdougb * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11153816Sdougb * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12153816Sdougb * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13153816Sdougb * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14153816Sdougb * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15153816Sdougb * PERFORMANCE OF THIS SOFTWARE. 16153816Sdougb */ 17153816Sdougb 18153816Sdougb/* 19153816Sdougb * Copyright (c) 1990, 1993 20153816Sdougb * The Regents of the University of California. All rights reserved. 21153816Sdougb * 22153816Sdougb * Redistribution and use in source and binary forms, with or without 23153816Sdougb * modification, are permitted provided that the following conditions 24153816Sdougb * are met: 25153816Sdougb * 1. Redistributions of source code must retain the above copyright 26153816Sdougb * notice, this list of conditions and the following disclaimer. 27153816Sdougb * 2. Redistributions in binary form must reproduce the above copyright 28153816Sdougb * notice, this list of conditions and the following disclaimer in the 29153816Sdougb * documentation and/or other materials provided with the distribution. 30262706Serwin * 3. Neither the name of the University nor the names of its contributors 31153816Sdougb * may be used to endorse or promote products derived from this software 32153816Sdougb * without specific prior written permission. 33153816Sdougb * 34153816Sdougb * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35153816Sdougb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36153816Sdougb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37153816Sdougb * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38153816Sdougb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39153816Sdougb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40153816Sdougb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41153816Sdougb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42153816Sdougb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43153816Sdougb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44153816Sdougb * SUCH DAMAGE. 45153816Sdougb */ 46153816Sdougb 47153816Sdougb/*! \file */ 48153816Sdougb#if defined(LIBC_SCCS) && !defined(lint) 49153816Sdougbstatic char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; 50153816Sdougb#endif /* LIBC_SCCS and not lint */ 51153816Sdougb 52254897Serwin/* $Id: strtoul.c,v 1.4 2007/06/19 23:47:22 tbox Exp $ */ 53153816Sdougb 54153816Sdougb#include <config.h> 55153816Sdougb 56153816Sdougb#include <limits.h> 57153816Sdougb#include <ctype.h> 58153816Sdougb#include <errno.h> 59153816Sdougb 60153816Sdougb#include <lwres/stdlib.h> 61153816Sdougb 62153816Sdougb#define DE_CONST(konst, var) \ 63153816Sdougb do { \ 64153816Sdougb union { const void *k; void *v; } _u; \ 65153816Sdougb _u.k = konst; \ 66153816Sdougb var = _u.v; \ 67153816Sdougb } while (0) 68153816Sdougb 69153816Sdougb/*! 70153816Sdougb * Convert a string to an unsigned long integer. 71153816Sdougb * 72153816Sdougb * Ignores `locale' stuff. Assumes that the upper and lower case 73153816Sdougb * alphabets and digits are each contiguous. 74153816Sdougb */ 75153816Sdougbunsigned long 76153816Sdougblwres_strtoul(const char *nptr, char **endptr, int base) { 77153816Sdougb const char *s = nptr; 78153816Sdougb unsigned long acc; 79153816Sdougb unsigned char c; 80153816Sdougb unsigned long cutoff; 81153816Sdougb int neg = 0, any, cutlim; 82153816Sdougb 83153816Sdougb /* 84153816Sdougb * See strtol for comments as to the logic used. 85153816Sdougb */ 86153816Sdougb do { 87153816Sdougb c = *s++; 88153816Sdougb } while (isspace(c)); 89153816Sdougb if (c == '-') { 90153816Sdougb neg = 1; 91153816Sdougb c = *s++; 92153816Sdougb } else if (c == '+') 93153816Sdougb c = *s++; 94153816Sdougb if ((base == 0 || base == 16) && 95153816Sdougb c == '0' && (*s == 'x' || *s == 'X')) { 96153816Sdougb c = s[1]; 97153816Sdougb s += 2; 98153816Sdougb base = 16; 99153816Sdougb } 100153816Sdougb if (base == 0) 101153816Sdougb base = c == '0' ? 8 : 10; 102153816Sdougb cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 103153816Sdougb cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 104153816Sdougb for (acc = 0, any = 0;; c = *s++) { 105153816Sdougb if (!isascii(c)) 106153816Sdougb break; 107153816Sdougb if (isdigit(c)) 108153816Sdougb c -= '0'; 109153816Sdougb else if (isalpha(c)) 110153816Sdougb c -= isupper(c) ? 'A' - 10 : 'a' - 10; 111153816Sdougb else 112153816Sdougb break; 113153816Sdougb if (c >= base) 114153816Sdougb break; 115153816Sdougb if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 116153816Sdougb any = -1; 117153816Sdougb else { 118153816Sdougb any = 1; 119153816Sdougb acc *= base; 120153816Sdougb acc += c; 121153816Sdougb } 122153816Sdougb } 123153816Sdougb if (any < 0) { 124153816Sdougb acc = ULONG_MAX; 125153816Sdougb errno = ERANGE; 126153816Sdougb } else if (neg) 127153816Sdougb acc = -acc; 128153816Sdougb if (endptr != 0) 129153816Sdougb DE_CONST(any ? s - 1 : nptr, *endptr); 130153816Sdougb return (acc); 131153816Sdougb} 132