strtoul.c revision 77298
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 6133965Sjdpstrtoul(nptr, endptr, base) 6260484Sobrien const char *nptr; 6333965Sjdp char **endptr; 6433965Sjdp register int base; 6533965Sjdp{ 6660484Sobrien register const char *s = nptr; 6733965Sjdp register unsigned long acc; 6833965Sjdp register int c; 6933965Sjdp register unsigned long cutoff; 7033965Sjdp register int neg = 0, any, cutlim; 7133965Sjdp 7233965Sjdp /* 7333965Sjdp * See strtol for comments as to the logic used. 7433965Sjdp */ 7533965Sjdp do { 7633965Sjdp c = *s++; 7777298Sobrien } while (ISSPACE(c)); 7833965Sjdp if (c == '-') { 7933965Sjdp neg = 1; 8033965Sjdp c = *s++; 8133965Sjdp } else if (c == '+') 8233965Sjdp c = *s++; 8333965Sjdp if ((base == 0 || base == 16) && 8433965Sjdp c == '0' && (*s == 'x' || *s == 'X')) { 8533965Sjdp c = s[1]; 8633965Sjdp s += 2; 8733965Sjdp base = 16; 8833965Sjdp } 8933965Sjdp if (base == 0) 9033965Sjdp base = c == '0' ? 8 : 10; 9133965Sjdp cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; 9233965Sjdp cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; 9333965Sjdp for (acc = 0, any = 0;; c = *s++) { 9477298Sobrien if (ISDIGIT(c)) 9533965Sjdp c -= '0'; 9677298Sobrien else if (ISALPHA(c)) 9777298Sobrien c -= ISUPPER(c) ? 'A' - 10 : 'a' - 10; 9833965Sjdp else 9933965Sjdp break; 10033965Sjdp if (c >= base) 10133965Sjdp break; 10260484Sobrien if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) 10333965Sjdp any = -1; 10433965Sjdp else { 10533965Sjdp any = 1; 10633965Sjdp acc *= base; 10733965Sjdp acc += c; 10833965Sjdp } 10933965Sjdp } 11033965Sjdp if (any < 0) { 11133965Sjdp acc = ULONG_MAX; 11233965Sjdp errno = ERANGE; 11333965Sjdp } else if (neg) 11433965Sjdp acc = -acc; 11533965Sjdp if (endptr != 0) 11633965Sjdp *endptr = (char *) (any ? s - 1 : nptr); 11733965Sjdp return (acc); 11833965Sjdp} 119