strtoul.c revision 1573
11573Srgrimes/*
21573Srgrimes * Copyright (c) 1990, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 3. All advertising materials mentioning features or use of this software
141573Srgrimes *    must display the following acknowledgement:
151573Srgrimes *	This product includes software developed by the University of
161573Srgrimes *	California, Berkeley and its contributors.
171573Srgrimes * 4. Neither the name of the University nor the names of its contributors
181573Srgrimes *    may be used to endorse or promote products derived from this software
191573Srgrimes *    without specific prior written permission.
201573Srgrimes *
211573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311573Srgrimes * SUCH DAMAGE.
321573Srgrimes */
331573Srgrimes
341573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
351573Srgrimesstatic char sccsid[] = "@(#)strtoul.c	8.1 (Berkeley) 6/4/93";
361573Srgrimes#endif /* LIBC_SCCS and not lint */
371573Srgrimes
381573Srgrimes#include <limits.h>
391573Srgrimes#include <ctype.h>
401573Srgrimes#include <errno.h>
411573Srgrimes#include <stdlib.h>
421573Srgrimes
431573Srgrimes/*
441573Srgrimes * Convert a string to an unsigned long integer.
451573Srgrimes *
461573Srgrimes * Ignores `locale' stuff.  Assumes that the upper and lower case
471573Srgrimes * alphabets and digits are each contiguous.
481573Srgrimes */
491573Srgrimesunsigned long
501573Srgrimesstrtoul(nptr, endptr, base)
511573Srgrimes	const char *nptr;
521573Srgrimes	char **endptr;
531573Srgrimes	register int base;
541573Srgrimes{
551573Srgrimes	register const char *s = nptr;
561573Srgrimes	register unsigned long acc;
571573Srgrimes	register int c;
581573Srgrimes	register unsigned long cutoff;
591573Srgrimes	register int neg = 0, any, cutlim;
601573Srgrimes
611573Srgrimes	/*
621573Srgrimes	 * See strtol for comments as to the logic used.
631573Srgrimes	 */
641573Srgrimes	do {
651573Srgrimes		c = *s++;
661573Srgrimes	} while (isspace(c));
671573Srgrimes	if (c == '-') {
681573Srgrimes		neg = 1;
691573Srgrimes		c = *s++;
701573Srgrimes	} else if (c == '+')
711573Srgrimes		c = *s++;
721573Srgrimes	if ((base == 0 || base == 16) &&
731573Srgrimes	    c == '0' && (*s == 'x' || *s == 'X')) {
741573Srgrimes		c = s[1];
751573Srgrimes		s += 2;
761573Srgrimes		base = 16;
771573Srgrimes	}
781573Srgrimes	if (base == 0)
791573Srgrimes		base = c == '0' ? 8 : 10;
801573Srgrimes	cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
811573Srgrimes	cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
821573Srgrimes	for (acc = 0, any = 0;; c = *s++) {
831573Srgrimes		if (isdigit(c))
841573Srgrimes			c -= '0';
851573Srgrimes		else if (isalpha(c))
861573Srgrimes			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
871573Srgrimes		else
881573Srgrimes			break;
891573Srgrimes		if (c >= base)
901573Srgrimes			break;
911573Srgrimes		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
921573Srgrimes			any = -1;
931573Srgrimes		else {
941573Srgrimes			any = 1;
951573Srgrimes			acc *= base;
961573Srgrimes			acc += c;
971573Srgrimes		}
981573Srgrimes	}
991573Srgrimes	if (any < 0) {
1001573Srgrimes		acc = ULONG_MAX;
1011573Srgrimes		errno = ERANGE;
1021573Srgrimes	} else if (neg)
1031573Srgrimes		acc = -acc;
1041573Srgrimes	if (endptr != 0)
1051573Srgrimes		*endptr = (char *)(any ? s - 1 : nptr);
1061573Srgrimes	return (acc);
1071573Srgrimes}
108