strtoul.c revision 1.1
11.1Schristos/* $NetBSD: strtoul.c,v 1.1 2005/12/20 19:28:52 christos Exp $ */ 21.1Schristos 31.1Schristos/* 41.1Schristos * Copyright (c) 1990, 1993 51.1Schristos * The Regents of the University of California. All rights reserved. 61.1Schristos * 71.1Schristos * Redistribution and use in source and binary forms, with or without 81.1Schristos * modification, are permitted provided that the following conditions 91.1Schristos * are met: 101.1Schristos * 1. Redistributions of source code must retain the above copyright 111.1Schristos * notice, this list of conditions and the following disclaimer. 121.1Schristos * 2. Redistributions in binary form must reproduce the above copyright 131.1Schristos * notice, this list of conditions and the following disclaimer in the 141.1Schristos * documentation and/or other materials provided with the distribution. 151.1Schristos * 3. Neither the name of the University nor the names of its contributors 161.1Schristos * may be used to endorse or promote products derived from this software 171.1Schristos * without specific prior written permission. 181.1Schristos * 191.1Schristos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 201.1Schristos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 211.1Schristos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 221.1Schristos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 231.1Schristos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 241.1Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 251.1Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 261.1Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 271.1Schristos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 281.1Schristos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 291.1Schristos * SUCH DAMAGE. 301.1Schristos */ 311.1Schristos 321.1Schristos#if !defined(_KERNEL) && !defined(_STANDALONE) 331.1Schristos#include <sys/cdefs.h> 341.1Schristos#if defined(LIBC_SCCS) && !defined(lint) 351.1Schristos#if 0 361.1Schristosstatic char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93"; 371.1Schristos#else 381.1Schristos__RCSID("$NetBSD: strtoul.c,v 1.1 2005/12/20 19:28:52 christos Exp $"); 391.1Schristos#endif 401.1Schristos#endif /* LIBC_SCCS and not lint */ 411.1Schristos 421.1Schristos#include <assert.h> 431.1Schristos#include <ctype.h> 441.1Schristos#include <errno.h> 451.1Schristos#include <limits.h> 461.1Schristos#include <stdlib.h> 471.1Schristos#else 481.1Schristos#include <sys/param.h> 491.1Schristos#include <lib/libkern/libkern.h> 501.1Schristos#define isspace(x) ((x) == ' ' || (x) == '\t' || (x) == '\n' || (x) == '\r') 511.1Schristos#define isdigit(x) ((x) >= '0' && (x) <= '9') 521.1Schristos#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) 531.1Schristos#define toupper(x) ((x) & ~0x20) 541.1Schristos#endif 551.1Schristos 561.1Schristos/* 571.1Schristos * Convert a string to an unsigned long integer. 581.1Schristos * 591.1Schristos * Ignores `locale' stuff. Assumes that the upper and lower case 601.1Schristos * alphabets and digits are each contiguous. 611.1Schristos */ 621.1Schristosunsigned long 631.1Schristosstrtoul(nptr, endptr, base) 641.1Schristos const char *nptr; 651.1Schristos char **endptr; 661.1Schristos int base; 671.1Schristos{ 681.1Schristos const char *s; 691.1Schristos unsigned long acc, cutoff; 701.1Schristos int c; 711.1Schristos int neg, any, cutlim; 721.1Schristos 731.1Schristos _DIAGASSERT(nptr != NULL); 741.1Schristos /* endptr may be NULL */ 751.1Schristos 761.1Schristos /* 771.1Schristos * See strtol for comments as to the logic used. 781.1Schristos */ 791.1Schristos s = nptr; 801.1Schristos do { 811.1Schristos c = (unsigned char) *s++; 821.1Schristos } while (isspace(c)); 831.1Schristos if (c == '-') { 841.1Schristos neg = 1; 851.1Schristos c = *s++; 861.1Schristos } else { 871.1Schristos neg = 0; 881.1Schristos if (c == '+') 891.1Schristos c = *s++; 901.1Schristos } 911.1Schristos if ((base == 0 || base == 16) && 921.1Schristos c == '0' && (*s == 'x' || *s == 'X')) { 931.1Schristos c = s[1]; 941.1Schristos s += 2; 951.1Schristos base = 16; 961.1Schristos } 971.1Schristos if (base == 0) 981.1Schristos base = c == '0' ? 8 : 10; 991.1Schristos 1001.1Schristos cutoff = ULONG_MAX / (unsigned long)base; 1011.1Schristos cutlim = (int)(ULONG_MAX % (unsigned long)base); 1021.1Schristos for (acc = 0, any = 0;; c = (unsigned char) *s++) { 1031.1Schristos if (isdigit(c)) 1041.1Schristos c -= '0'; 1051.1Schristos else if (isalpha(c)) { 1061.1Schristos#if defined(_KERNEL) || defined(_STANDALONE) 1071.1Schristos c = toupper(c) - 'A' + 10; 1081.1Schristos#else 1091.1Schristos c -= isupper(c) ? 'A' - 10 : 'a' - 10; 1101.1Schristos#endif 1111.1Schristos } else 1121.1Schristos break; 1131.1Schristos if (c >= base) 1141.1Schristos break; 1151.1Schristos if (any < 0) 1161.1Schristos continue; 1171.1Schristos if (acc > cutoff || (acc == cutoff && c > cutlim)) { 1181.1Schristos#if defined(_KERNEL) || defined(_STANDALONE) 1191.1Schristos if (endptr) 1201.1Schristos *endptr = __UNCONST(nptr); 1211.1Schristos return ULONG_MAX; 1221.1Schristos#else 1231.1Schristos any = -1; 1241.1Schristos acc = ULONG_MAX; 1251.1Schristos errno = ERANGE; 1261.1Schristos#endif 1271.1Schristos } else { 1281.1Schristos any = 1; 1291.1Schristos acc *= (unsigned long)base; 1301.1Schristos acc += c; 1311.1Schristos } 1321.1Schristos } 1331.1Schristos if (neg && any > 0) 1341.1Schristos acc = -acc; 1351.1Schristos if (endptr != NULL) 1361.1Schristos *endptr = __UNCONST(any ? s - 1 : nptr); 1371.1Schristos return (acc); 1381.1Schristos} 139