1133936Sobrien/* $NetBSD: strsuftoll.c,v 1.5 2004/01/17 23:02:51 dbj Exp $ */ 2108760Sobrien/*- 3133936Sobrien * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc. 4108760Sobrien * All rights reserved. 5108760Sobrien * 6108760Sobrien * This code is derived from software contributed to The NetBSD Foundation 7108760Sobrien * by Luke Mewburn. 8108760Sobrien * 9108760Sobrien * Redistribution and use in source and binary forms, with or without 10108760Sobrien * modification, are permitted provided that the following conditions 11108760Sobrien * are met: 12108760Sobrien * 1. Redistributions of source code must retain the above copyright 13108760Sobrien * notice, this list of conditions and the following disclaimer. 14108760Sobrien * 2. Redistributions in binary form must reproduce the above copyright 15108760Sobrien * notice, this list of conditions and the following disclaimer in the 16108760Sobrien * documentation and/or other materials provided with the distribution. 17108760Sobrien * 3. All advertising materials mentioning features or use of this software 18108760Sobrien * must display the following acknowledgement: 19108760Sobrien * This product includes software developed by the NetBSD 20108760Sobrien * Foundation, Inc. and its contributors. 21108760Sobrien * 4. Neither the name of The NetBSD Foundation nor the names of its 22108760Sobrien * contributors may be used to endorse or promote products derived 23108760Sobrien * from this software without specific prior written permission. 24108760Sobrien * 25108760Sobrien * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26108760Sobrien * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27108760Sobrien * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28108760Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29108760Sobrien * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30108760Sobrien * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31108760Sobrien * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32108760Sobrien * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33108760Sobrien * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34108760Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35108760Sobrien * POSSIBILITY OF SUCH DAMAGE. 36108760Sobrien */ 37108760Sobrien/*- 38108760Sobrien * Copyright (c) 1991, 1993, 1994 39108760Sobrien * The Regents of the University of California. All rights reserved. 40108760Sobrien * 41108760Sobrien * This code is derived from software contributed to Berkeley by 42108760Sobrien * Keith Muller of the University of California, San Diego and Lance 43108760Sobrien * Visser of Convex Computer Corporation. 44108760Sobrien * 45108760Sobrien * Redistribution and use in source and binary forms, with or without 46108760Sobrien * modification, are permitted provided that the following conditions 47108760Sobrien * are met: 48108760Sobrien * 1. Redistributions of source code must retain the above copyright 49108760Sobrien * notice, this list of conditions and the following disclaimer. 50108760Sobrien * 2. Redistributions in binary form must reproduce the above copyright 51108760Sobrien * notice, this list of conditions and the following disclaimer in the 52108760Sobrien * documentation and/or other materials provided with the distribution. 53133936Sobrien * 3. Neither the name of the University nor the names of its contributors 54108760Sobrien * may be used to endorse or promote products derived from this software 55108760Sobrien * without specific prior written permission. 56108760Sobrien * 57108760Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58108760Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59108760Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60108760Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61108760Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62108760Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63108760Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64108760Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65108760Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66108760Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67108760Sobrien * SUCH DAMAGE. 68108760Sobrien */ 69108760Sobrien 70133936Sobrien#if HAVE_NBTOOL_CONFIG_H 71133936Sobrien#include "nbtool_config.h" 72133936Sobrien#endif 73133936Sobrien 74108760Sobrien#include <sys/cdefs.h> 75108760Sobrien 76108760Sobrien#if defined(LIBC_SCCS) && !defined(lint) 77133936Sobrien__RCSID("$NetBSD: strsuftoll.c,v 1.5 2004/01/17 23:02:51 dbj Exp $"); 78108760Sobrien#endif /* LIBC_SCCS and not lint */ 79108760Sobrien 80108760Sobrien#ifdef _LIBC 81108760Sobrien#include "namespace.h" 82108760Sobrien#endif 83108760Sobrien 84108760Sobrien#if !HAVE_STRSUFTOLL 85108760Sobrien 86108760Sobrien#include <sys/types.h> 87108760Sobrien#include <sys/time.h> 88108760Sobrien 89108760Sobrien#include <assert.h> 90108760Sobrien#include <ctype.h> 91108760Sobrien#include <err.h> 92108760Sobrien#include <errno.h> 93108760Sobrien#include <limits.h> 94108760Sobrien#include <stdio.h> 95108760Sobrien#include <stdlib.h> 96108760Sobrien#include <string.h> 97108760Sobrien 98108760Sobrien#ifdef _LIBC 99108760Sobrien# ifdef __weak_alias 100108760Sobrien__weak_alias(strsuftoll, _strsuftoll) 101108760Sobrien__weak_alias(strsuftollx, _strsuftollx) 102108760Sobrien# endif 103133936Sobrien#endif /* LIBC */ 104108760Sobrien 105108760Sobrien/* 106108760Sobrien * Convert an expression of the following forms to a (u)int64_t. 107108760Sobrien * 1) A positive decimal number. 108108760Sobrien * 2) A positive decimal number followed by a b (mult by 512). 109108760Sobrien * 3) A positive decimal number followed by a k (mult by 1024). 110108760Sobrien * 4) A positive decimal number followed by a m (mult by 1048576). 111133936Sobrien * 5) A positive decimal number followed by a g (mult by 1073741824). 112133936Sobrien * 6) A positive decimal number followed by a t (mult by 1099511627776). 113133936Sobrien * 7) A positive decimal number followed by a w (mult by sizeof int) 114133936Sobrien * 8) Two or more positive decimal numbers (with/without k,b or w). 115108760Sobrien * separated by x (also * for backwards compatibility), specifying 116108760Sobrien * the product of the indicated values. 117108760Sobrien * Returns the result upon successful conversion, or exits with an 118108760Sobrien * appropriate error. 119108760Sobrien * 120108760Sobrien */ 121108760Sobrien/* LONGLONG */ 122108760Sobrienlong long 123133936Sobrienstrsuftoll(const char *desc, const char *val, 124108760Sobrien long long min, long long max) 125108760Sobrien{ 126108760Sobrien long long result; 127108760Sobrien char errbuf[100]; 128108760Sobrien 129108760Sobrien result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf)); 130108760Sobrien if (*errbuf != '\0') 131108760Sobrien errx(1, "%s", errbuf); 132108760Sobrien return (result); 133108760Sobrien} 134108760Sobrien 135108760Sobrien/* 136108760Sobrien * As strsuftoll(), but returns the error message into the provided buffer 137108760Sobrien * rather than exiting with it. 138108760Sobrien */ 139108760Sobrien/* LONGLONG */ 140108760Sobrienlong long 141133936Sobrienstrsuftollx(const char *desc, const char *val, 142108760Sobrien long long min, long long max, char *ebuf, size_t ebuflen) 143108760Sobrien{ 144108760Sobrien long long num, t; 145108760Sobrien char *expr; 146108760Sobrien 147108760Sobrien _DIAGASSERT(desc != NULL); 148108760Sobrien _DIAGASSERT(val != NULL); 149108760Sobrien _DIAGASSERT(ebuf != NULL); 150108760Sobrien 151108760Sobrien errno = 0; 152108760Sobrien ebuf[0] = '\0'; 153108760Sobrien 154108760Sobrien while (isspace((unsigned char)*val)) /* Skip leading space */ 155108760Sobrien val++; 156108760Sobrien 157133936Sobrien num = strtoll(val, &expr, 10); 158108760Sobrien if (errno == ERANGE) 159108760Sobrien goto erange; /* Overflow */ 160108760Sobrien 161108760Sobrien if (expr == val) /* No digits */ 162108760Sobrien goto badnum; 163108760Sobrien 164108760Sobrien switch (*expr) { 165108760Sobrien case 'b': 166108760Sobrien t = num; 167108760Sobrien num *= 512; /* 1 block */ 168108760Sobrien if (t > num) 169108760Sobrien goto erange; 170108760Sobrien ++expr; 171108760Sobrien break; 172108760Sobrien case 'k': 173108760Sobrien t = num; 174108760Sobrien num *= 1024; /* 1 kilobyte */ 175108760Sobrien if (t > num) 176108760Sobrien goto erange; 177108760Sobrien ++expr; 178108760Sobrien break; 179108760Sobrien case 'm': 180108760Sobrien t = num; 181108760Sobrien num *= 1048576; /* 1 megabyte */ 182108760Sobrien if (t > num) 183108760Sobrien goto erange; 184108760Sobrien ++expr; 185108760Sobrien break; 186108760Sobrien case 'g': 187108760Sobrien t = num; 188108760Sobrien num *= 1073741824; /* 1 gigabyte */ 189108760Sobrien if (t > num) 190108760Sobrien goto erange; 191108760Sobrien ++expr; 192108760Sobrien break; 193108760Sobrien case 't': 194108760Sobrien t = num; 195108760Sobrien num *= 1099511627776LL; /* 1 terabyte */ 196108760Sobrien if (t > num) 197108760Sobrien goto erange; 198108760Sobrien ++expr; 199108760Sobrien break; 200108760Sobrien case 'w': 201108760Sobrien t = num; 202108760Sobrien num *= sizeof(int); /* 1 word */ 203108760Sobrien if (t > num) 204108760Sobrien goto erange; 205108760Sobrien ++expr; 206108760Sobrien break; 207108760Sobrien } 208108760Sobrien 209108760Sobrien switch (*expr) { 210108760Sobrien case '\0': 211108760Sobrien break; 212108760Sobrien case '*': /* Backward compatible */ 213108760Sobrien case 'x': 214108760Sobrien t = num; 215108760Sobrien num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen); 216108760Sobrien if (*ebuf != '\0') 217108760Sobrien return (0); 218108760Sobrien if (t > num) { 219108760Sobrien erange: 220108760Sobrien snprintf(ebuf, ebuflen, 221108760Sobrien "%s: %s", desc, strerror(ERANGE)); 222108760Sobrien return (0); 223108760Sobrien } 224108760Sobrien break; 225108760Sobrien default: 226108760Sobrien badnum: snprintf(ebuf, ebuflen, 227108760Sobrien "%s `%s': illegal number", desc, val); 228108760Sobrien return (0); 229108760Sobrien } 230108760Sobrien if (num < min) { 231108760Sobrien /* LONGLONG */ 232108760Sobrien snprintf(ebuf, ebuflen, "%s %lld is less than %lld.", 233108760Sobrien desc, (long long)num, (long long)min); 234108760Sobrien return (0); 235108760Sobrien } 236108760Sobrien if (num > max) { 237108760Sobrien /* LONGLONG */ 238108760Sobrien snprintf(ebuf, ebuflen, 239108760Sobrien "%s %lld is greater than %lld.", 240133936Sobrien desc, (long long)num, (long long)max); 241108760Sobrien return (0); 242108760Sobrien } 243108760Sobrien *ebuf = '\0'; 244108760Sobrien return (num); 245108760Sobrien} 246108760Sobrien 247108760Sobrien#endif /* !HAVE_STRSUFTOLL */ 248