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