1*a19008b1Slukem /* $NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $ */ 26ca5b5bbSlukem /*- 3*a19008b1Slukem * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc. 46ca5b5bbSlukem * All rights reserved. 56ca5b5bbSlukem * 66ca5b5bbSlukem * This code is derived from software contributed to The NetBSD Foundation 76ca5b5bbSlukem * by Luke Mewburn. 86ca5b5bbSlukem * 96ca5b5bbSlukem * Redistribution and use in source and binary forms, with or without 106ca5b5bbSlukem * modification, are permitted provided that the following conditions 116ca5b5bbSlukem * are met: 126ca5b5bbSlukem * 1. Redistributions of source code must retain the above copyright 136ca5b5bbSlukem * notice, this list of conditions and the following disclaimer. 146ca5b5bbSlukem * 2. Redistributions in binary form must reproduce the above copyright 156ca5b5bbSlukem * notice, this list of conditions and the following disclaimer in the 166ca5b5bbSlukem * documentation and/or other materials provided with the distribution. 176ca5b5bbSlukem * 3. All advertising materials mentioning features or use of this software 186ca5b5bbSlukem * must display the following acknowledgement: 196ca5b5bbSlukem * This product includes software developed by the NetBSD 206ca5b5bbSlukem * Foundation, Inc. and its contributors. 216ca5b5bbSlukem * 4. Neither the name of The NetBSD Foundation nor the names of its 226ca5b5bbSlukem * contributors may be used to endorse or promote products derived 236ca5b5bbSlukem * from this software without specific prior written permission. 246ca5b5bbSlukem * 256ca5b5bbSlukem * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 266ca5b5bbSlukem * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 276ca5b5bbSlukem * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 286ca5b5bbSlukem * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 296ca5b5bbSlukem * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 306ca5b5bbSlukem * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 316ca5b5bbSlukem * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 326ca5b5bbSlukem * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 336ca5b5bbSlukem * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 346ca5b5bbSlukem * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 356ca5b5bbSlukem * POSSIBILITY OF SUCH DAMAGE. 366ca5b5bbSlukem */ 376ca5b5bbSlukem /*- 386ca5b5bbSlukem * Copyright (c) 1991, 1993, 1994 396ca5b5bbSlukem * The Regents of the University of California. All rights reserved. 406ca5b5bbSlukem * 416ca5b5bbSlukem * This code is derived from software contributed to Berkeley by 426ca5b5bbSlukem * Keith Muller of the University of California, San Diego and Lance 436ca5b5bbSlukem * Visser of Convex Computer Corporation. 446ca5b5bbSlukem * 456ca5b5bbSlukem * Redistribution and use in source and binary forms, with or without 466ca5b5bbSlukem * modification, are permitted provided that the following conditions 476ca5b5bbSlukem * are met: 486ca5b5bbSlukem * 1. Redistributions of source code must retain the above copyright 496ca5b5bbSlukem * notice, this list of conditions and the following disclaimer. 506ca5b5bbSlukem * 2. Redistributions in binary form must reproduce the above copyright 516ca5b5bbSlukem * notice, this list of conditions and the following disclaimer in the 526ca5b5bbSlukem * documentation and/or other materials provided with the distribution. 53eb7c1594Sagc * 3. Neither the name of the University nor the names of its contributors 546ca5b5bbSlukem * may be used to endorse or promote products derived from this software 556ca5b5bbSlukem * without specific prior written permission. 566ca5b5bbSlukem * 576ca5b5bbSlukem * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 586ca5b5bbSlukem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 596ca5b5bbSlukem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 606ca5b5bbSlukem * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 616ca5b5bbSlukem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 626ca5b5bbSlukem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 636ca5b5bbSlukem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 646ca5b5bbSlukem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 656ca5b5bbSlukem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 666ca5b5bbSlukem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 676ca5b5bbSlukem * SUCH DAMAGE. 686ca5b5bbSlukem */ 696ca5b5bbSlukem 70171d6532Slukem #if HAVE_NBTOOL_CONFIG_H 71171d6532Slukem #include "nbtool_config.h" 72171d6532Slukem #endif 73171d6532Slukem 746ca5b5bbSlukem #include <sys/cdefs.h> 756ca5b5bbSlukem 766ca5b5bbSlukem #if defined(LIBC_SCCS) && !defined(lint) 77*a19008b1Slukem __RCSID("$NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $"); 786ca5b5bbSlukem #endif /* LIBC_SCCS and not lint */ 796ca5b5bbSlukem 806ca5b5bbSlukem #ifdef _LIBC 816ca5b5bbSlukem #include "namespace.h" 826ca5b5bbSlukem #endif 836ca5b5bbSlukem 846ca5b5bbSlukem #if !HAVE_STRSUFTOLL 856ca5b5bbSlukem 866ca5b5bbSlukem #include <sys/types.h> 876ca5b5bbSlukem #include <sys/time.h> 886ca5b5bbSlukem 896ca5b5bbSlukem #include <assert.h> 906ca5b5bbSlukem #include <ctype.h> 916ca5b5bbSlukem #include <err.h> 926ca5b5bbSlukem #include <errno.h> 936ca5b5bbSlukem #include <limits.h> 946ca5b5bbSlukem #include <stdio.h> 956ca5b5bbSlukem #include <stdlib.h> 966ca5b5bbSlukem #include <string.h> 976ca5b5bbSlukem 986ca5b5bbSlukem #ifdef _LIBC 996ca5b5bbSlukem # ifdef __weak_alias 1006ca5b5bbSlukem __weak_alias(strsuftoll, _strsuftoll) 1016ca5b5bbSlukem __weak_alias(strsuftollx, _strsuftollx) 1026ca5b5bbSlukem # endif 103ca348cd6Sitohy #endif /* LIBC */ 1046ca5b5bbSlukem 1056ca5b5bbSlukem /* 1066ca5b5bbSlukem * Convert an expression of the following forms to a (u)int64_t. 1076ca5b5bbSlukem * 1) A positive decimal number. 1086ca5b5bbSlukem * 2) A positive decimal number followed by a b (mult by 512). 1096ca5b5bbSlukem * 3) A positive decimal number followed by a k (mult by 1024). 1106ca5b5bbSlukem * 4) A positive decimal number followed by a m (mult by 1048576). 111*a19008b1Slukem * 5) A positive decimal number followed by a g (mult by 1073741824). 112*a19008b1Slukem * 6) A positive decimal number followed by a t (mult by 1099511627776). 113*a19008b1Slukem * 7) A positive decimal number followed by a w (mult by sizeof int) 114*a19008b1Slukem * 8) Two or more positive decimal numbers (with/without k,b or w). 1156ca5b5bbSlukem * separated by x (also * for backwards compatibility), specifying 1166ca5b5bbSlukem * the product of the indicated values. 1176ca5b5bbSlukem * Returns the result upon successful conversion, or exits with an 1186ca5b5bbSlukem * appropriate error. 1196ca5b5bbSlukem * 1206ca5b5bbSlukem */ 1216ca5b5bbSlukem /* LONGLONG */ 1226ca5b5bbSlukem long long 123ca348cd6Sitohy strsuftoll(const char *desc, const char *val, 1246ca5b5bbSlukem long long min, long long max) 1256ca5b5bbSlukem { 1266ca5b5bbSlukem long long result; 1276ca5b5bbSlukem char errbuf[100]; 1286ca5b5bbSlukem 1296ca5b5bbSlukem result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 1306ca5b5bbSlukem if (*errbuf != '\0') 1316ca5b5bbSlukem errx(1, "%s", errbuf); 1326ca5b5bbSlukem return (result); 1336ca5b5bbSlukem } 1346ca5b5bbSlukem 1356ca5b5bbSlukem /* 1366ca5b5bbSlukem * As strsuftoll(), but returns the error message into the provided buffer 1376ca5b5bbSlukem * rather than exiting with it. 1386ca5b5bbSlukem */ 1396ca5b5bbSlukem /* LONGLONG */ 1406ca5b5bbSlukem long long 141ca348cd6Sitohy strsuftollx(const char *desc, const char *val, 1426ca5b5bbSlukem long long min, long long max, char *ebuf, size_t ebuflen) 1436ca5b5bbSlukem { 1446ca5b5bbSlukem long long num, t; 1456ca5b5bbSlukem char *expr; 1466ca5b5bbSlukem 1476ca5b5bbSlukem _DIAGASSERT(desc != NULL); 1486ca5b5bbSlukem _DIAGASSERT(val != NULL); 1496ca5b5bbSlukem _DIAGASSERT(ebuf != NULL); 1506ca5b5bbSlukem 1516ca5b5bbSlukem errno = 0; 1526ca5b5bbSlukem ebuf[0] = '\0'; 1536ca5b5bbSlukem 1546ca5b5bbSlukem while (isspace((unsigned char)*val)) /* Skip leading space */ 1556ca5b5bbSlukem val++; 1566ca5b5bbSlukem 157*a19008b1Slukem num = strtoll(val, &expr, 10); 1586ca5b5bbSlukem if (errno == ERANGE) 1596ca5b5bbSlukem goto erange; /* Overflow */ 1606ca5b5bbSlukem 1616ca5b5bbSlukem if (expr == val) /* No digits */ 1626ca5b5bbSlukem goto badnum; 1636ca5b5bbSlukem 1646ca5b5bbSlukem switch (*expr) { 1656ca5b5bbSlukem case 'b': 1666ca5b5bbSlukem t = num; 1676ca5b5bbSlukem num *= 512; /* 1 block */ 1686ca5b5bbSlukem if (t > num) 1696ca5b5bbSlukem goto erange; 1706ca5b5bbSlukem ++expr; 1716ca5b5bbSlukem break; 1726ca5b5bbSlukem case 'k': 1736ca5b5bbSlukem t = num; 1746ca5b5bbSlukem num *= 1024; /* 1 kilobyte */ 1756ca5b5bbSlukem if (t > num) 1766ca5b5bbSlukem goto erange; 1776ca5b5bbSlukem ++expr; 1786ca5b5bbSlukem break; 1796ca5b5bbSlukem case 'm': 1806ca5b5bbSlukem t = num; 1816ca5b5bbSlukem num *= 1048576; /* 1 megabyte */ 1826ca5b5bbSlukem if (t > num) 1836ca5b5bbSlukem goto erange; 1846ca5b5bbSlukem ++expr; 1856ca5b5bbSlukem break; 1866ca5b5bbSlukem case 'g': 1876ca5b5bbSlukem t = num; 1886ca5b5bbSlukem num *= 1073741824; /* 1 gigabyte */ 1896ca5b5bbSlukem if (t > num) 1906ca5b5bbSlukem goto erange; 1916ca5b5bbSlukem ++expr; 1926ca5b5bbSlukem break; 1936ca5b5bbSlukem case 't': 1946ca5b5bbSlukem t = num; 1956ca5b5bbSlukem num *= 1099511627776LL; /* 1 terabyte */ 1966ca5b5bbSlukem if (t > num) 1976ca5b5bbSlukem goto erange; 1986ca5b5bbSlukem ++expr; 1996ca5b5bbSlukem break; 2006ca5b5bbSlukem case 'w': 2016ca5b5bbSlukem t = num; 2026ca5b5bbSlukem num *= sizeof(int); /* 1 word */ 2036ca5b5bbSlukem if (t > num) 2046ca5b5bbSlukem goto erange; 2056ca5b5bbSlukem ++expr; 2066ca5b5bbSlukem break; 2076ca5b5bbSlukem } 2086ca5b5bbSlukem 2096ca5b5bbSlukem switch (*expr) { 2106ca5b5bbSlukem case '\0': 2116ca5b5bbSlukem break; 2126ca5b5bbSlukem case '*': /* Backward compatible */ 2136ca5b5bbSlukem case 'x': 2146ca5b5bbSlukem t = num; 2156ca5b5bbSlukem num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 2166ca5b5bbSlukem if (*ebuf != '\0') 2176ca5b5bbSlukem return (0); 2186ca5b5bbSlukem if (t > num) { 2196ca5b5bbSlukem erange: 2206ca5b5bbSlukem snprintf(ebuf, ebuflen, 2216ca5b5bbSlukem "%s: %s", desc, strerror(ERANGE)); 2226ca5b5bbSlukem return (0); 2236ca5b5bbSlukem } 2246ca5b5bbSlukem break; 2256ca5b5bbSlukem default: 2266ca5b5bbSlukem badnum: snprintf(ebuf, ebuflen, 2276ca5b5bbSlukem "%s `%s': illegal number", desc, val); 2286ca5b5bbSlukem return (0); 2296ca5b5bbSlukem } 2306ca5b5bbSlukem if (num < min) { 2316ca5b5bbSlukem /* LONGLONG */ 2326ca5b5bbSlukem snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 2336ca5b5bbSlukem desc, (long long)num, (long long)min); 2346ca5b5bbSlukem return (0); 2356ca5b5bbSlukem } 2366ca5b5bbSlukem if (num > max) { 2376ca5b5bbSlukem /* LONGLONG */ 2386ca5b5bbSlukem snprintf(ebuf, ebuflen, 2396ca5b5bbSlukem "%s %lld is greater than %lld.", 2401d817633Sdbj desc, (long long)num, (long long)max); 2416ca5b5bbSlukem return (0); 2426ca5b5bbSlukem } 2436ca5b5bbSlukem *ebuf = '\0'; 2446ca5b5bbSlukem return (num); 2456ca5b5bbSlukem } 2466ca5b5bbSlukem 2476ca5b5bbSlukem #endif /* !HAVE_STRSUFTOLL */ 248