"Fossies" - the Fresh Open Source Software Archive 
Member "xombrero-1.6.4/netbsd/netbsd.c" (17 Feb 2015, 8446 Bytes) of package /linux/www/old/xombrero-1.6.4.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "netbsd.c" see the
Fossies "Dox" file reference documentation.
1 /* $OpenBSD: fmt_scaled.c,v 1.10 2009/06/20 15:00:04 martynas Exp $ */
2
3 /*
4 * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * fmt_scaled: Format numbers scaled for human comprehension
31 * scan_scaled: Scan numbers in this format.
32 *
33 * "Human-readable" output uses 4 digits max, and puts a unit suffix at
34 * the end. Makes output compact and easy-to-read esp. on huge disks.
35 * Formatting code was originally in OpenBSD "df", converted to library routine.
36 * Scanning code written for OpenBSD libutil.
37 */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <errno.h>
42 #include <string.h>
43 #include <ctype.h>
44 #include <limits.h>
45
46 #include "util.h"
47
48 typedef enum {
49 NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6
50 } unit_type;
51
52 /* These three arrays MUST be in sync! XXX make a struct */
53 static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA };
54 static char scale_chars[] = "BKMGTPE";
55 static long long scale_factors[] = {
56 1LL,
57 1024LL,
58 1024LL*1024,
59 1024LL*1024*1024,
60 1024LL*1024*1024*1024,
61 1024LL*1024*1024*1024*1024,
62 1024LL*1024*1024*1024*1024*1024,
63 };
64 #define SCALE_LENGTH (sizeof(units)/sizeof(units[0]))
65
66 #define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */
67
68 /* Convert the given input string "scaled" into numeric in "result".
69 * Return 0 on success, -1 and errno set on error.
70 */
71 int
72 scan_scaled(char *scaled, long long *result)
73 {
74 char *p = scaled;
75 int sign = 0;
76 unsigned int i, ndigits = 0, fract_digits = 0;
77 long long scale_fact = 1, whole = 0, fpart = 0;
78
79 /* Skip leading whitespace */
80 while (isascii((unsigned char)*p) &&
81 isspace((unsigned char)*p))
82 ++p;
83
84 /* Then at most one leading + or - */
85 while (*p == '-' || *p == '+') {
86 if (*p == '-') {
87 if (sign) {
88 errno = EINVAL;
89 return -1;
90 }
91 sign = -1;
92 ++p;
93 } else if (*p == '+') {
94 if (sign) {
95 errno = EINVAL;
96 return -1;
97 }
98 sign = +1;
99 ++p;
100 }
101 }
102
103 /* Main loop: Scan digits, find decimal point, if present.
104 * We don't allow exponentials, so no scientific notation
105 * (but note that E for Exa might look like e to some!).
106 * Advance 'p' to end, to get scale factor.
107 */
108 for (; isascii((unsigned char)*p) &&
109 (isdigit((unsigned char)*p) || *p=='.'); ++p) {
110 if (*p == '.') {
111 if (fract_digits > 0) { /* oops, more than one '.' */
112 errno = EINVAL;
113 return -1;
114 }
115 fract_digits = 1;
116 continue;
117 }
118
119 i = (*p) - '0'; /* whew! finally a digit we can use */
120 if (fract_digits > 0) {
121 if (fract_digits >= MAX_DIGITS-1)
122 /* ignore extra fractional digits */
123 continue;
124 fract_digits++; /* for later scaling */
125 fpart *= 10;
126 fpart += i;
127 } else { /* normal digit */
128 if (++ndigits >= MAX_DIGITS) {
129 errno = ERANGE;
130 return -1;
131 }
132 whole *= 10;
133 whole += i;
134 }
135 }
136
137 if (sign) {
138 whole *= sign;
139 fpart *= sign;
140 }
141
142 /* If no scale factor given, we're done. fraction is discarded. */
143 if (!*p) {
144 *result = whole;
145 return 0;
146 }
147
148 /* Validate scale factor, and scale whole and fraction by it. */
149 for (i = 0; i < SCALE_LENGTH; i++) {
150
151 /* Are we there yet? */
152 if (*p == scale_chars[i] ||
153 *p == tolower((unsigned char)scale_chars[i])) {
154
155 /* If it ends with alphanumerics after the scale char, bad. */
156 if (isalnum((unsigned char)*(p+1))) {
157 errno = EINVAL;
158 return -1;
159 }
160 scale_fact = scale_factors[i];
161
162 /* scale whole part */
163 whole *= scale_fact;
164
165 /* truncate fpart so it does't overflow.
166 * then scale fractional part.
167 */
168 while (fpart >= LLONG_MAX / scale_fact) {
169 fpart /= 10;
170 fract_digits--;
171 }
172 fpart *= scale_fact;
173 if (fract_digits > 0) {
174 for (i = 0; i < fract_digits -1; i++)
175 fpart /= 10;
176 }
177 whole += fpart;
178 *result = whole;
179 return 0;
180 }
181 }
182 errno = ERANGE;
183 return -1;
184 }
185
186 /* Format the given "number" into human-readable form in "result".
187 * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE.
188 * Return 0 on success, -1 and errno set if error.
189 */
190 int
191 fmt_scaled(long long number, char *result)
192 {
193 long long abval, fract = 0;
194 unsigned int i;
195 unit_type unit = NONE;
196
197 abval = llabs(number);
198
199 /* Not every negative long long has a positive representation.
200 * Also check for numbers that are just too darned big to format
201 */
202 if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) {
203 errno = ERANGE;
204 return -1;
205 }
206
207 /* scale whole part; get unscaled fraction */
208 for (i = 0; i < SCALE_LENGTH; i++) {
209 if (abval/1024 < scale_factors[i]) {
210 unit = units[i];
211 fract = (i == 0) ? 0 : abval % scale_factors[i];
212 number /= scale_factors[i];
213 if (i > 0)
214 fract /= scale_factors[i - 1];
215 break;
216 }
217 }
218
219 fract = (10 * fract + 512) / 1024;
220 /* if the result would be >= 10, round main number */
221 if (fract == 10) {
222 if (number >= 0)
223 number++;
224 else
225 number--;
226 fract = 0;
227 }
228
229 if (number == 0)
230 strlcpy(result, "0B", FMT_SCALED_STRSIZE);
231 else if (unit == NONE || number >= 100 || number <= -100) {
232 if (fract >= 5) {
233 if (number >= 0)
234 number++;
235 else
236 number--;
237 }
238 (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c",
239 number, scale_chars[unit]);
240 } else
241 (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c",
242 number, fract, scale_chars[unit]);
243
244 return 0;
245 }
246
247 /* $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $ */
248
249 /*
250 * Copyright (c) 2004 Ted Unangst and Todd Miller
251 * All rights reserved.
252 *
253 * Permission to use, copy, modify, and distribute this software for any
254 * purpose with or without fee is hereby granted, provided that the above
255 * copyright notice and this permission notice appear in all copies.
256 *
257 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
258 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
259 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
260 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
261 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
262 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
263 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
264 */
265
266 #include <errno.h>
267 #include <limits.h>
268 #include <stdlib.h>
269
270 #define INVALID 1
271 #define TOOSMALL 2
272 #define TOOLARGE 3
273
274 long long
275 strtonum(const char *numstr, long long minval, long long maxval,
276 const char **errstrp)
277 {
278 long long ll = 0;
279 char *ep;
280 int error = 0;
281 struct errval {
282 const char *errstr;
283 int err;
284 } ev[4] = {
285 { NULL, 0 },
286 { "invalid", EINVAL },
287 { "too small", ERANGE },
288 { "too large", ERANGE },
289 };
290
291 ev[0].err = errno;
292 errno = 0;
293 if (minval > maxval)
294 error = INVALID;
295 else {
296 ll = strtoll(numstr, &ep, 10);
297 if (numstr == ep || *ep != '\0')
298 error = INVALID;
299 else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
300 error = TOOSMALL;
301 else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
302 error = TOOLARGE;
303 }
304 if (errstrp != NULL)
305 *errstrp = ev[error].errstr;
306 errno = ev[error].err;
307 if (error)
308 ll = 0;
309
310 return (ll);
311 }