133965Sjdp/* 233965Sjdp * Copyright (c) 1990 Regents of the University of California. 333965Sjdp * All rights reserved. 433965Sjdp * 533965Sjdp * Redistribution and use in source and binary forms, with or without 633965Sjdp * modification, are permitted provided that the following conditions 733965Sjdp * are met: 833965Sjdp * 1. Redistributions of source code must retain the above copyright 933965Sjdp * notice, this list of conditions and the following disclaimer. 1033965Sjdp * 2. Redistributions in binary form must reproduce the above copyright 1133965Sjdp * notice, this list of conditions and the following disclaimer in the 1233965Sjdp * documentation and/or other materials provided with the distribution. 1360484Sobrien * 3. [rescinded 22 July 1999] 1433965Sjdp * 4. Neither the name of the University nor the names of its contributors 1533965Sjdp * may be used to endorse or promote products derived from this software 1633965Sjdp * without specific prior written permission. 1733965Sjdp * 1833965Sjdp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1933965Sjdp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2033965Sjdp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2133965Sjdp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2233965Sjdp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2333965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2433965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2533965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2633965Sjdp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2733965Sjdp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2833965Sjdp * SUCH DAMAGE. 2933965Sjdp */ 3033965Sjdp 3177298Sobrien#ifdef HAVE_CONFIG_H 3277298Sobrien#include "config.h" 3377298Sobrien#endif 3477298Sobrien#ifdef HAVE_LIMITS_H 3533965Sjdp#include <limits.h> 3677298Sobrien#endif 3777298Sobrien#ifdef HAVE_SYS_PARAM_H 3877298Sobrien#include <sys/param.h> 3977298Sobrien#endif 4033965Sjdp#include <errno.h> 4177298Sobrien#ifdef NEED_DECLARATION_ERRNO 4277298Sobrienextern int errno; 4377298Sobrien#endif 4433965Sjdp#if 0 4533965Sjdp#include <stdlib.h> 4633965Sjdp#endif 4733965Sjdp#include "ansidecl.h" 4877298Sobrien#include "safe-ctype.h" 4933965Sjdp 5033965Sjdp#ifndef ULONG_MAX 5133965Sjdp#define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ 5233965Sjdp#endif 5333965Sjdp 5433965Sjdp/* 5533965Sjdp * Convert a string to an unsigned long integer. 5633965Sjdp * 5733965Sjdp * Ignores `locale' stuff. Assumes that the upper and lower case 5833965Sjdp * alphabets and digits are each contiguous. 5933965Sjdp */ 6033965Sjdpunsigned long 61218822Sdimstrtoul(const char *nptr, char **endptr, register int base) 6233965Sjdp{ 6360484Sobrien register const char *s = nptr; 6433965Sjdp register unsigned long acc; 6533965Sjdp register int c; 6633965Sjdp register unsigned long cutoff; 6733965Sjdp register int neg = 0, any, cutlim; 6833965Sjdp 6933965Sjdp /* 7033965Sjdp * See strtol for comments as to the logic used. 7133965Sjdp */ 7233965Sjdp do { 7333965Sjdp c = *s++; 7477298Sobrien } while (ISSPACE(c)); 7533965Sjdp if (c == '-') { 7633965Sjdp neg = 1; 7733965Sjdp c = *s++; 7833965Sjdp } else if (c == '+') 7933965Sjdp c = *s++; 8033965Sjdp if ((base == 0 || base == 16) && 8133965Sjdp c == '0' && (*s == 'x' || *s == 'X')) { 8233965Sjdp c = s[1]; 8333965Sjdp s += 2; 8433965Sjdp base = 16; 8533965Sjdp } 8633965Sjdp if (base == 0) 8733965Sjdp base = c == '0' ? 8 : 10; 8833965Sjdp cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 8933965Sjdp cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 9033965Sjdp for (acc = 0, any = 0;; c = *s++) { 9177298Sobrien if (ISDIGIT(c)) 9233965Sjdp c -= '0'; 9377298Sobrien else if (ISALPHA(c)) 9477298Sobrien c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; 9533965Sjdp else 9633965Sjdp break; 9733965Sjdp if (c >= base) 9833965Sjdp break; 9960484Sobrien if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 10033965Sjdp any = -1; 10133965Sjdp else { 10233965Sjdp any = 1; 10333965Sjdp acc *= base; 10433965Sjdp acc += c; 10533965Sjdp } 10633965Sjdp } 10733965Sjdp if (any < 0) { 10833965Sjdp acc = ULONG_MAX; 10933965Sjdp errno = ERANGE; 11033965Sjdp } else if (neg) 11133965Sjdp acc = -acc; 11233965Sjdp if (endptr != 0) 11333965Sjdp *endptr = (char *) (any ? s - 1 : nptr); 11433965Sjdp return (acc); 11533965Sjdp} 116