1155408Srwatson/*	$NetBSD: strsuftoll.c,v 1.6 2004/03/05 05:58:29 lukem Exp $	*/
2155408Srwatson/*-
3188315Srwatson * Copyright (c) 2001-2002,2004 The NetBSD Foundation, Inc.
4155408Srwatson * All rights reserved.
5155408Srwatson *
6155408Srwatson * This code is derived from software contributed to The NetBSD Foundation
7155408Srwatson * by Luke Mewburn.
8155408Srwatson *
9155408Srwatson * Redistribution and use in source and binary forms, with or without
10155408Srwatson * modification, are permitted provided that the following conditions
11155408Srwatson * are met:
12155408Srwatson * 1. Redistributions of source code must retain the above copyright
13155408Srwatson *    notice, this list of conditions and the following disclaimer.
14155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright
15155408Srwatson *    notice, this list of conditions and the following disclaimer in the
16155408Srwatson *    documentation and/or other materials provided with the distribution.
17155408Srwatson *
18155408Srwatson * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19155408Srwatson * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20155408Srwatson * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21155408Srwatson * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22155408Srwatson * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23155408Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24155408Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25155408Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26155408Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27155408Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28155408Srwatson * POSSIBILITY OF SUCH DAMAGE.
29155408Srwatson */
30178186Srwatson/*-
31178186Srwatson * Copyright (c) 1991, 1993, 1994
32178186Srwatson *	The Regents of the University of California.  All rights reserved.
33155408Srwatson *
34155408Srwatson * This code is derived from software contributed to Berkeley by
35155408Srwatson * Keith Muller of the University of California, San Diego and Lance
36155408Srwatson * Visser of Convex Computer Corporation.
37155408Srwatson *
38155408Srwatson * Redistribution and use in source and binary forms, with or without
39155408Srwatson * modification, are permitted provided that the following conditions
40155408Srwatson * are met:
41155408Srwatson * 1. Redistributions of source code must retain the above copyright
42155408Srwatson *    notice, this list of conditions and the following disclaimer.
43155408Srwatson * 2. Redistributions in binary form must reproduce the above copyright
44155408Srwatson *    notice, this list of conditions and the following disclaimer in the
45184488Srwatson *    documentation and/or other materials provided with the distribution.
46155408Srwatson * 3. Neither the name of the University nor the names of its contributors
47155408Srwatson *    may be used to endorse or promote products derived from this software
48155408Srwatson *    without specific prior written permission.
49155408Srwatson *
50184508Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
51155408Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52155408Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
53155408Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
54155408Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
55156880Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
56155408Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57155408Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
58155408Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
59155408Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
60184545Srwatson * SUCH DAMAGE.
61184545Srwatson */
62184545Srwatson
63184545Srwatson#include <sys/cdefs.h>
64155408Srwatson__FBSDID("$FreeBSD$");
65155408Srwatson
66155408Srwatson#include <sys/types.h>
67155408Srwatson#include <sys/time.h>
68155408Srwatson
69155408Srwatson#include <assert.h>
70155408Srwatson#include <ctype.h>
71155408Srwatson#include <err.h>
72174894Swkoszek#include <errno.h>
73159269Srwatson#include <limits.h>
74155408Srwatson#include <stdio.h>
75155408Srwatson#include <stdlib.h>
76155408Srwatson#include <string.h>
77155408Srwatson
78156883Srwatson#ifdef _LIBC
79188315Srwatson# ifdef __weak_alias
80155408Srwatson__weak_alias(strsuftoll, _strsuftoll)
81155408Srwatson__weak_alias(strsuftollx, _strsuftollx)
82155408Srwatson# endif
83155408Srwatson#endif /* LIBC */
84155408Srwatson
85155408Srwatson/*
86155408Srwatson * Convert an expression of the following forms to a (u)int64_t.
87155408Srwatson * 	1) A positive decimal number.
88155408Srwatson *	2) A positive decimal number followed by a b (mult by 512).
89155408Srwatson *	3) A positive decimal number followed by a k (mult by 1024).
90155408Srwatson *	4) A positive decimal number followed by a m (mult by 1048576).
91155408Srwatson *	5) A positive decimal number followed by a g (mult by 1073741824).
92159269Srwatson *	6) A positive decimal number followed by a t (mult by 1099511627776).
93159269Srwatson *	7) A positive decimal number followed by a w (mult by sizeof int)
94159269Srwatson *	8) Two or more positive decimal numbers (with/without k,b or w).
95159269Srwatson *	   separated by x (also * for backwards compatibility), specifying
96159269Srwatson *	   the product of the indicated values.
97159269Srwatson * Returns the result upon successful conversion, or exits with an
98159269Srwatson * appropriate error.
99159269Srwatson *
100159269Srwatson */
101159269Srwatson
102159269Srwatson/*
103159269Srwatson * As strsuftoll(), but returns the error message into the provided buffer
104159269Srwatson * rather than exiting with it.
105159269Srwatson */
106159269Srwatson/* LONGLONG */
107159269Srwatsonlong long
108159269Srwatsonstrsuftollx(const char *desc, const char *val,
109155408Srwatson    long long min, long long max, char *ebuf, size_t ebuflen)
110155408Srwatson{
111155408Srwatson	long long num, t;
112155408Srwatson	char	*expr;
113155408Srwatson
114155408Srwatson	errno = 0;
115155408Srwatson	ebuf[0] = '\0';
116155408Srwatson
117155408Srwatson	while (isspace((unsigned char)*val))	/* Skip leading space */
118155408Srwatson		val++;
119155408Srwatson
120155408Srwatson	num = strtoll(val, &expr, 10);
121184488Srwatson	if (errno == ERANGE)
122184488Srwatson		goto erange;			/* Overflow */
123184488Srwatson
124184508Srwatson	if (expr == val)			/* No digits */
125184488Srwatson		goto badnum;
126184488Srwatson
127184508Srwatson	switch (*expr) {
128184508Srwatson	case 'b':
129184508Srwatson		t = num;
130184508Srwatson		num *= 512;			/* 1 block */
131184508Srwatson		if (t > num)
132184508Srwatson			goto erange;
133184508Srwatson		++expr;
134184508Srwatson		break;
135184488Srwatson	case 'k':
136184488Srwatson		t = num;
137184488Srwatson		num *= 1024;			/* 1 kilobyte */
138184488Srwatson		if (t > num)
139184488Srwatson			goto erange;
140184536Srwatson		++expr;
141184536Srwatson		break;
142184536Srwatson	case 'm':
143184536Srwatson		t = num;
144184536Srwatson		num *= 1048576;			/* 1 megabyte */
145184536Srwatson		if (t > num)
146184536Srwatson			goto erange;
147155408Srwatson		++expr;
148155408Srwatson		break;
149184536Srwatson	case 'g':
150184536Srwatson		t = num;
151155408Srwatson		num *= 1073741824;		/* 1 gigabyte */
152184540Srwatson		if (t > num)
153184540Srwatson			goto erange;
154184540Srwatson		++expr;
155155408Srwatson		break;
156155408Srwatson	case 't':
157155408Srwatson		t = num;
158155408Srwatson		num *= 1099511627776LL;		/* 1 terabyte */
159159269Srwatson		if (t > num)
160159269Srwatson			goto erange;
161159269Srwatson		++expr;
162159269Srwatson		break;
163159269Srwatson	case 'w':
164159269Srwatson		t = num;
165159269Srwatson		num *= sizeof(int);		/* 1 word */
166159269Srwatson		if (t > num)
167159269Srwatson			goto erange;
168159269Srwatson		++expr;
169159269Srwatson		break;
170184508Srwatson	}
171184508Srwatson
172186662Srwatson	switch (*expr) {
173186662Srwatson	case '\0':
174159269Srwatson		break;
175155408Srwatson	case '*':				/* Backward compatible */
176155408Srwatson	case 'x':
177159269Srwatson		t = num;
178159269Srwatson		num *= strsuftollx(desc, expr + 1, min, max, ebuf, ebuflen);
179159269Srwatson		if (*ebuf != '\0')
180155408Srwatson			return (0);
181155408Srwatson		if (t > num) {
182155408Srwatson erange:
183184508Srwatson			snprintf(ebuf, ebuflen,
184184508Srwatson			    "%s: %s", desc, strerror(ERANGE));
185184508Srwatson			return (0);
186184508Srwatson		}
187184508Srwatson		break;
188184508Srwatson	default:
189184508Srwatson badnum:	snprintf(ebuf, ebuflen,
190184488Srwatson		    "%s `%s': illegal number", desc, val);
191184508Srwatson		return (0);
192184508Srwatson	}
193184508Srwatson	if (num < min) {
194184508Srwatson			/* LONGLONG */
195184508Srwatson		snprintf(ebuf, ebuflen, "%s %lld is less than %lld.",
196184508Srwatson		    desc, (long long)num, (long long)min);
197155408Srwatson		return (0);
198184488Srwatson	}
199184488Srwatson	if (num > max) {
200184488Srwatson			/* LONGLONG */
201184488Srwatson		snprintf(ebuf, ebuflen,
202155408Srwatson		    "%s %lld is greater than %lld.",
203155408Srwatson		    desc, (long long)num, (long long)max);
204184488Srwatson		return (0);
205155408Srwatson	}
206184488Srwatson	*ebuf = '\0';
207184488Srwatson	return (num);
208184488Srwatson}
209184488Srwatson
210184488Srwatson/* LONGLONG */
211184488Srwatsonlong long
212184488Srwatsonstrsuftoll(const char *desc, const char *val,
213184488Srwatson    long long min, long long max)
214155408Srwatson{
215155408Srwatson	long long result;
216155408Srwatson	char	errbuf[100];
217155408Srwatson
218155408Srwatson	result = strsuftollx(desc, val, min, max, errbuf, sizeof(errbuf));
219155408Srwatson	if (*errbuf != '\0')
220155408Srwatson		errx(1, "%s", errbuf);
221155408Srwatson	return (result);
222155408Srwatson}
223155408Srwatson