vBulletin Search Engine Optimization
| |||||||
| Register | FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
| ||||
| On Thu, Mar 06, 2008 at 03:30:42PM +0000, Paul Stoeber wrote: > fmt_scaled() rounds wrong. Example: Hi, please be a bit patient. I noted you diff, and will look at it the coming time. -Otto > > #include <util.h> > #include <stdio.h> > int main() { > long long n = 1024 * 1023 + 461; /* should round to 1023K */ > char buf[FMT_SCALED_STRSIZE]; > if (fmt_scaled(n, buf) == 0) > printf("%lld -> %s\n", n, buf); /* 1048013 -> 1024K */ > return 0; > } > > scan_scaled() doesn't have a user in src/ or xenocara/ or ports/ or > any of the distfiles of the ports having "util" in their "WANTLIB". > > The patch implements fmt_scaled() with rigour (I hope) and kills > scan_scaled(). > > Index: src/lib/libutil/shlib_version > ================================================== ================= > RCS file: /cvs/src/lib/libutil/shlib_version,v > retrieving revision 1.20 > diff -u -r1.20 shlib_version > @@ -1,2 +1,2 @@ > -major=11 > +major=12 > minor=0 > Index: src/lib/libutil/util.h > ================================================== ================= > RCS file: /cvs/src/lib/libutil/util.h,v > retrieving revision 1.27 > diff -u -r1.27 util.h > --- src/lib/libutil/util.h 14 Jun 2006 02:14:25 -0000 1.27 > +++ src/lib/libutil/util.h 5 Mar 2008 12:42:34 -0000 > @@ -112,8 +112,7 @@ > int uu_lock(const char *_ttyname); > int uu_lock_txfr(const char *_ttyname, pid_t _pid); > int uu_unlock(const char *_ttyname); > -int fmt_scaled(long long number, char *result); > -int scan_scaled(char *scaled, long long *result); > +void fmt_scaled(long long number, char *result); > __END_DECLS > > #endif /* !_UTIL_H_ */ > Index: src/lib/libutil/fmt_scaled.c > ================================================== ================= > RCS file: /cvs/src/lib/libutil/fmt_scaled.c,v > retrieving revision 1.9 > diff -u -r1.9 fmt_scaled.c > --- src/lib/libutil/fmt_scaled.c 20 Mar 2007 03:42:52 -0000 1.9 > +++ src/lib/libutil/fmt_scaled.c 5 Mar 2008 19:57:58 -0000 > @@ -1,268 +1,89 @@ > /* $OpenBSD: fmt_scaled.c,v 1.9 2007/03/20 03:42:52 tedu Exp $ */ > > /* > - * Copyright (c) 2001, 2002, 2003 Ian F. Darwin. All rights reserved. > + * Copyright (c) 2008 Paul Stoeber > * > - * Redistribution and use in source and binary forms, with or without > - * modification, are permitted provided that the following conditions > - * are met: > - * 1. Redistributions of source code must retain the above copyright > - * notice, this list of conditions and the following disclaimer. > - * 2. Redistributions in binary form must reproduce the above copyright > - * notice, this list of conditions and the following disclaimer in the > - * documentation and/or other materials provided with the distribution. > - * 3. The name of the author may not be used to endorse or promote products > - * derived from this software without specific prior written permission. > + * Permission to use, copy, modify, and distribute this software for any > + * purpose with or without fee is hereby granted, provided that the above > + * copyright notice and this permission notice appear in all copies. > * > - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR > - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES > - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. > - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, > - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT > - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF > - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > */ > > -/* > - * fmt_scaled: Format numbers scaled for human comprehension > - * scan_scaled: Scan numbers in this format. > - * > - * "Human-readable" output uses 4 digits max, and puts a unit suffix at > - * the end. Makes output compact and easy-to-read esp. on huge disks. > - * Formatting code was originally in OpenBSD "df", converted to library routine. > - * Scanning code written for OpenBSD libutil. > - */ > - > -#include <stdio.h> > -#include <stdlib.h> > -#include <errno.h> > -#include <string.h> > -#include <ctype.h> > +#include <assert.h> > #include <limits.h> > +#include <stdio.h> > > -#include "util.h" > - > -typedef enum { > - NONE = 0, KILO = 1, MEGA = 2, GIGA = 3, TERA = 4, PETA = 5, EXA = 6 > -} unit_type; > - > -/* These three arrays MUST be in sync! XXX make a struct */ > -static unit_type units[] = { NONE, KILO, MEGA, GIGA, TERA, PETA, EXA }; > -static char scale_chars[] = "BKMGTPE"; > -static long long scale_factors[] = { > - 1LL, > - 1024LL, > - 1024LL*1024, > - 1024LL*1024*1024, > - 1024LL*1024*1024*1024, > - 1024LL*1024*1024*1024*1024, > - 1024LL*1024*1024*1024*1024*1024, > -}; > -#define SCALE_LENGTH (sizeof(units)/sizeof(units[0])) > - > -#define MAX_DIGITS (SCALE_LENGTH * 3) /* XXX strlen(sprintf("%lld", -1)? */ > +const char *fmt_scaled_suffixes = "BKMGTPE"; > > -/** Convert the given input string "scaled" into numeric in "result". > - * Return 0 on success, -1 and errno set on error. > - */ > -int > -scan_scaled(char *scaled, long long *result) > +void > +fmt_scaled(long long number, char *result) > { > - char *p = scaled; > - int sign = 0; > - unsigned int i, ndigits = 0, fract_digits = 0; > - long long scale_fact = 1, whole = 0, fpart = 0; > - > - /* Skip leading whitespace */ > - while (isascii(*p) && isspace(*p)) > - ++p; > - > - /* Then at most one leading + or - */ > - while (*p == '-' || *p == '+') { > - if (*p == '-') { > - if (sign) { > - errno = EINVAL; > - return -1; > - } > - sign = -1; > - ++p; > - } else if (*p == '+') { > - if (sign) { > - errno = EINVAL; > - return -1; > - } > - sign = +1; > - ++p; > - } > - } > - > - /* Main loop: Scan digits, find decimal point, if present. > - * We don't allow exponentials, so no scientific notation > - * (but note that E for Exa might look like e to some!). > - * Advance 'p' to end, to get scale factor. > - */ > - for (; isascii(*p) && (isdigit(*p) || *p=='.'); ++p) { > - if (*p == '.') { > - if (fract_digits > 0) { /* oops, more than one '.' */ > - errno = EINVAL; > - return -1; > - } > - fract_digits = 1; > - continue; > - } > - > - i = (*p) - '0'; /* whew! finally a digit we can use */ > - if (fract_digits > 0) { > - if (fract_digits >= MAX_DIGITS-1) > - /* ignore extra fractional digits */ > - continue; > - fract_digits++; /* for later scaling */ > - fpart *= 10; > - fpart += i; > - } else { /* normal digit */ > - if (++ndigits >= MAX_DIGITS) { > - errno = ERANGE; > - return -1; > + const char *s = fmt_scaled_suffixes; > + long long a = number; /* integral part */ > + long long b = 0, c = 1; /* b/c = fractional part */ > + int d = 0, e = 1; /* d/e = rounded fractional part */ > + int r; /* digit shifted out of b/c */ > + int i, j, flag = 0; > + long long b_; > + > + if (a == LLONG_MIN) > + a++; > + if (a < 0) > + a = -a; > + assert(a >= 0); > + while (a >= 1024) { > + flag = 1; > + b += (a % 1024) * c; > + a /= 1024; > + c *= 1024; > + s++; > + assert(*s != '\0'); > + } > + i = a < 10 ? 2 : a < 100 ? 1 : 0; > + for (; > + /* do "b *= 10; r = b/c; b %= c;" without overflowing */ > + assert(c - 1 <= LLONG_MAX / 2); > + b_ = 0; > + r = 0; > + j = 10; > + while (j--) { > + b_ += b; > + while (b_ >= c) { > + b_ -= c; > + r++; > } > - whole *= 10; > - whole += i; > } > - } > - > - if (sign) { > - whole *= sign; > - fpart *= sign; > - } > - > - /* If no scale factor given, we're done. fraction is discarded. */ > - if (!*p) { > - *result = whole; > - return 0; > - } > - > - /* Validate scale factor, and scale whole and fraction by it. */ > - for (i = 0; i < SCALE_LENGTH; i++) { > - > - /** Are we there yet? */ > - if (*p == scale_chars[i] || > - *p == tolower(scale_chars[i])) { > - > - /* If it ends with alphanumerics after the scale char, bad. */ > - if (isalnum(*(p+1))) { > - errno = EINVAL; > - return -1; > - } > - scale_fact = scale_factors[i]; > - > - /* scale whole part */ > - whole *= scale_fact; > - > - /* truncate fpart so it does't overflow. > - * then scale fractional part. > - */ > - while (fpart >= LLONG_MAX / scale_fact) { > - fpart /= 10; > - fract_digits--; > - } > - fpart *= scale_fact; > - if (fract_digits > 0) { > - for (i = 0; i < fract_digits -1; i++) > - fpart /= 10; > - } > - whole += fpart; > - *result = whole; > - return 0; > - } > - } > - errno = ERANGE; > - return -1; > -} > - > -/* Format the given "number" into human-readable form in "result". > - * Result must point to an allocated buffer of length FMT_SCALED_STRSIZE. > - * Return 0 on success, -1 and errno set if error. > - */ > -int > -fmt_scaled(long long number, char *result) > -{ > - long long abval, fract = 0; > - unsigned int i; > - unit_type unit = NONE; > - > - abval = (number < 0LL) ? -number : number; /* no long long_abs yet */ > - > - /* Not every negative long long has a positive representation. > - * Also check for numbers that are just too darned big to format > - */ > - if (abval < 0 || abval / 1024 >= scale_factors[SCALE_LENGTH-1]) { > - errno = ERANGE; > - return -1; > - } > - > - /* scale whole part; get unscaled fraction */ > - for (i = 0; i < SCALE_LENGTH; i++) { > - if (abval/1024 < scale_factors[i]) { > - unit = units[i]; > - fract = (i == 0) ? 0 : abval % scale_factors[i]; > - number /= scale_factors[i]; > - if (i > 0) > - fract /= scale_factors[i - 1]; > + b = b_; > + if (i-- == 0) > break; > - } > - } > - > - fract = (10 * fract + 512) / 1024; > - /* if the result would be >= 10, round main number */ > - if (fract == 10) { > - if (number >= 0) > - number++; > - else > - number--; > - fract = 0; > - } > - > - if (number == 0) > - strlcpy(result, "0B", FMT_SCALED_STRSIZE); > - else if (unit == NONE || number >= 100 || number <= -100) { > - if (fract >= 5) { > - if (number >= 0) > - number++; > - else > - number--; > - } > - (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld%c", > - number, scale_chars[unit]); > - } else > - (void)snprintf(result, FMT_SCALED_STRSIZE, "%lld.%1lld%c", > - number, fract, scale_chars[unit]); > - > - return 0; > -} > - > -#ifdef MAIN > -/* > - * This is the original version of the program in the man page. > - * Copy-and-paste whatever you need from it. > - */ > -int > -main(int argc, char **argv) > -{ > - char *cinput = "1.5K", buf[FMT_SCALED_STRSIZE]; > - long long ninput = 10483892, result; > - > - if (scan_scaled(cinput, &result) == 0) > - printf("\"%s\" -> %lld\n", cinput, result); > + d *= 10; > + d += r; > + e *= 10; > + } > + /* round to even, like printf */ > + if (r >= 5 && !(r == 5 && b == 0 && (e == 1 ? a : d) % 2 == 0)) > + d++; > + if (d == e) { > + a++; > + d = 0; > + } > + if (number < 0) > + *result++ = '-'; > + if (a < 10 && flag) > + i = snprintf(result, 5, "%d.%02d", (int)a, d); > + else if (a < 100 && flag) > + i = snprintf(result, 5, "%d.%d", (int)a, d); > else > - perror(cinput); > - > - if (fmt_scaled(ninput, buf) == 0) > - printf("%lld -> \"%s\"\n", ninput, buf); > - else > - fprintf(stderr, "%lld invalid (%s)\n", ninput, strerror(errno)); > - > - return 0; > + i = snprintf(result, 5, "%d", (int)a); > + assert(1 <= i && i <= 4); > + result += i; > + *result++ = *s; > + *result = '\0'; > } > -#endif > Index: src/lib/libutil/fmt_scaled.3 > ================================================== ================= > RCS file: /cvs/src/lib/libutil/fmt_scaled.3,v > retrieving revision 1.4 > diff -u -r1.4 fmt_scaled.3 > --- src/lib/libutil/fmt_scaled.3 31 May 2007 19:19:38 -0000 1.4 > +++ src/lib/libutil/fmt_scaled.3 5 Mar 2008 12:42:34 -0000 > @@ -27,84 +27,42 @@ > .Dt FMT_SCALED 3 > .Os > .Sh NAME > -.Nm fmt_scaled , > -.Nm scan_scaled > -.Nd handle numbers with a human-readable scale > +.Nm fmt_scaled > +.Nd format numbers with a human-readable scale > .Sh SYNOPSIS > .Fd #include <util.h> > -.Ft int > -.Fn scan_scaled "char *number_w_scale" "long long *result" > -.Ft int > +.Ft void > .Fn fmt_scaled "long long number" "char *result" > .Sh DESCRIPTION > The > -.Fn scan_scaled > -function scans the given number and looks for a terminal scale multiplier > +.Fn fmt_scaled > +function formats a number for display using > +a terminal scale multiplier > of B, K, M, G, T, P or E > -.Pq in either upper or lower case > for Byte, Kilobyte, Megabyte, Gigabyte, Terabyte, Petabyte, Exabyte > .Po computed using powers of two, i.e., Megabyte = 1024*1024 > .Pc . > -The number can have a decimal point, as in 1.5K, which returns 1536 > -.Pq 1024+512 . > -If no scale factor is found, B is assumed. > -.Pp > -The > -.Fn fmt_scaled > -function formats a number for display using the same > -"human-readable" format, that is, a number with one of the above scale factors. > Numbers will be printed with a maximum of four digits (preceded by > a minus sign if the value is negative); values such > -as 0B, 100B, 1023B, 1K, 1.5K, 5.5M, and so on, will be generated. > +as 0B, 100B, 1023B, 1.00K, 1.50K, 5.51M, and so on, will be generated. > The > .Qq result > buffer must be allocated with at least > .Dv FMT_SCALED_STRSIZE > bytes. > The result will be left-justified in the given space, and NUL-terminated. > -.Sh RETURN VALUES > -The > -.Fn scan_scaled > -and > -.Fn fmt_scaled > -functions > -return 0 on success. > -In case of error, they return \-1, leave > -.Va *result > -as is, and set > -.Va errno > -to one of the following values: > -.Dv ERANGE > -if the input string represents a number that is too large to represent. > -.Dv EINVAL > -if an unknown character was used as scale factor, or > -if the input to > -.Fn scan_scaled > -was malformed, e.g., too many '.' characters. > .Sh EXAMPLES > .Bd -literal -offset indent > -char *cinput = "1.5K"; > -long long result; > -if (scan_scaled(cinput, &result) != 0) > - printf("%s -> %ld\en", cinput, result); > -else > - fprintf(stderr, "%s - invalid\en", cinput); > - > char buf[FMT_SCALED_STRSIZE]; > long long ninput = 10483892; > -if (fmt_scaled(ninput, buf) == 0) > - printf("%lld -> %s\en", ninput, buf); > -else > - fprintf(stderr, "fmt scaled failed (errno %d)", errno); > +fmt_scaled(ninput, buf); > +printf("%lld -> %s\en", ninput, buf); > .Ed > .Sh SEE ALSO > -.Xr printf 3 , > -.Xr scanf 3 > +.Xr printf 3 > .Sh HISTORY > -The functions > +The function > .Fn fmt_scaled > -and > -.Fn scan_scaled > first appeared in > .Ox 3.4 . > .Sh AUTHORS > @@ -114,16 +72,4 @@ > .Ox > .Xr df 1 . > Ian Darwin excerpted this and made it into a library routine > -(with significant help from Paul Janzen), and wrote > -.Fn scan_scaled . > -.Sh BUGS > -Some of the scale factors have misleading meanings in lower case > -(p for P is incorrect; p should be pico- and P for Peta-). > -However, we bend the SI rules in favor of common sense here. > -A person creating a disk partition of "100m" is unlikely to require > -100 millibytes (i.e., 0.1 byte) of storage in the partition; > -100 megabytes is the only reasonable interpretation. > -.Pp > -Cannot represent the larger scale factors on all architectures. > -.Pp > -Ignores the current locale. > +(with significant help from Paul Janzen). > Index: src/lib/libutil/Makefile > ================================================== ================= > RCS file: /cvs/src/lib/libutil/Makefile,v > retrieving revision 1.29 > diff -u -r1.29 Makefile > --- src/lib/libutil/Makefile 24 Nov 2005 20:49:23 -0000 1.29 > +++ src/lib/libutil/Makefile 5 Mar 2008 12:42:34 -0000 > @@ -33,7 +33,6 @@ > MLINKS+=uucplock.3 uu_unlock.3 > MLINKS+=uucplock.3 uu_lockerr.3 > MLINKS+=uucplock.3 uu_lock_txfr.3 > -MLINKS+=fmt_scaled.3 scan_scaled.3 > > includes: > @cd ${.CURDIR}; for i in $(HDRS); do \ > Index: src/regress/lib/libutil/fmt_scaled/fmt_test.c > ================================================== ================= > RCS file: /cvs/src/regress/lib/libutil/fmt_scaled/fmt_test.c,v > retrieving revision 1.8 > diff -u -r1.8 fmt_test.c > --- src/regress/lib/libutil/fmt_scaled/fmt_test.c 21 Oct 2005 22:23:58 -0000 1.8 > +++ src/regress/lib/libutil/fmt_scaled/fmt_test.c 5 Mar 2008 12:42:34 -0000 > @@ -1,7 +1,7 @@ > /* $OpenBSD */ > > /* > - * Combined tests for fmt_scaled and scan_scaled. > + * Tests for fmt_scaled. > * Ian Darwin, January 2001. Public domain. > */ > > @@ -9,17 +9,11 @@ > #include <stdlib.h> > #include <string.h> > #include <sys/types.h> > -#include <errno.h> > > #include <util.h> > > static int fmt_test(void); > -static int scan_test(void); > > -static void print_errno(int e); > -static int assert_int(int testnum, int checknum, int expect, int result); > -static int assert_errno(int testnum, int checknum, int expect, int result); > -static int assert_quad_t(int testnum, int checknum, quad_t expect, quad_t result); > static int assert_str(int testnum, int checknum, char * expect, char * result); > > extern char *__progname; > @@ -56,9 +50,6 @@ > if (verbose) > printf("Starting fmt_test\n"); > i = fmt_test(); > - if (verbose) > - printf("Starting scan_test\n"); > - i += scan_test(); > if (i) { > printf("*** %d errors in libutil/fmt_scaled tests ***\n", i); > } else { > @@ -68,213 +59,73 @@ > return i; > } > > -/************** tests for fmt_scaled *******************/ > - > static struct { /* the test cases */ > quad_t input; > char *expect; > - int err; > } ddata[] = { > - { 0, "0B", 0 }, > - { 1, "1B", 0 }, > - { -1, "-1B", 0 }, > - { 100, "100B", 0}, > - { -100, "-100B", 0}, > - { 999, "999B", 0 }, > - { 1000, "1000B", 0 }, > - { 1023, "1023B", 0 }, > - { -1023, "-1023B", 0 }, > - { 1024, "1.0K", 0 }, > - { 1025, "1.0K", 0 }, > - { 1234, "1.2K", 0 }, > - { -1234, "-1.2K", 0 }, > - { 1484, "1.4K", 0 }, /* rouding boundary, down */ > - { 1485, "1.5K", 0 }, /* rouding boundary, up */ > - { -1484, "-1.4K", 0 }, /* rouding boundary, down */ > - { -1485, "-1.5K", 0 }, /* rouding boundary, up */ > - { 1536, "1.5K", 0 }, > - { 1786, "1.7K", 0 }, > - { 1800, "1.8K", 0 }, > - { 2000, "2.0K", 0 }, > - { 123456, "121K", 0 }, > - { 578318, "565K", 0 }, > - { 902948, "882K", 0 }, > - { 1048576, "1.0M", 0}, > - { 1048628, "1.0M", 0}, > - { 1049447, "1.0M", 0}, > - { -102400, "-100K", 0}, > - { -103423, "-101K", 0 }, > - { 7299072, "7.0M", 0 }, > - { 409478144L, "391M", 0 }, > - { -409478144L, "-391M", 0 }, > - { 999999999L, "954M", 0 }, > - { 1499999999L, "1.4G", 0 }, > - { 12475423744LL, "11.6G", 0}, > - { 1LL<<61, "2.0E", 0 }, > - { 1LL<<62, "4.0E", 0 }, > - { 1LL<<63, "", ERANGE }, > - { 1099512676352LL, "1.0T", 0} > + { 0, "0B" }, > + { 1, "1B" }, > + { -1, "-1B" }, > + { 100, "100B" }, > + { -100, "-100B" }, > + { 999, "999B" }, > + { 1000, "1000B" }, > + { 1023, "1023B" }, > + { -1023, "-1023B" }, > + { 1024, "1.00K" }, > + { 1030, "1.01K" }, > + { 1234, "1.21K" }, > + { -1234, "-1.21K" }, > + { 1024*1023+461, "1023K" }, > + { 1024*1023+511, "1023K" }, > + { 1024*1023+512, "1024K" }, > + { 1024*11+256, "11.2K" }, /* round to even */ > + { 1024*10+768, "10.8K" }, > + { 1484, "1.45K" }, > + { 1485, "1.45K" }, > + { -1484, "-1.45K" }, > + { -1485, "-1.45K" }, > + { 1536, "1.50K" }, > + { 1786, "1.74K" }, > + { 1800, "1.76K" }, > + { 2000, "1.95K" }, > + { 123456, "121K" }, > + { 578318, "565K" }, > + { 902948, "882K" }, > + { 1048576, "1.00M" }, > + { 1064304, "1.01M" }, > + { 1064305, "1.02M" }, > + { -102400, "-100K" }, > + { -103423, "-101K" }, > + { 7299072, "6.96M" }, > + { 409478144L, "391M" }, > + { -409478144L, "-391M" }, > + { 999999999L, "954M" }, > + { 1499999999L, "1.40G" }, > + { 12475423744LL, "11.6G" }, > + { 1LL<<61, "2.00E" }, > + { 1LL<<62, "4.00E" }, > + { 9223372036854775807LL, "8.00E" }, > + { 1LL<<63, "-8.00E" }, > + { 1099512676352LL, "1.00T" } > }; > # define DDATA_LENGTH (sizeof ddata/sizeof *ddata) > > static int > fmt_test(void) > { > - unsigned int i, e, errs = 0; > - int ret; > + unsigned int i, errs = 0; > char buf[FMT_SCALED_STRSIZE]; > > for (i = 0; i < DDATA_LENGTH; i++) { > strlcpy(buf, "UNSET", FMT_SCALED_STRSIZE); > - ret = fmt_scaled(ddata[i].input, buf); > - e = errno; > + fmt_scaled(ddata[i].input, buf); > if (verbose) { > - printf("%lld --> %s (%d)", ddata[i].input, buf, ret); > - if (ret == -1) > - print_errno(e); > - printf("\n"); > + printf("%lld --> %s\n", ddata[i].input, buf); > } > - if (ret == -1) > - errs += assert_int(i, 1, ret, ddata[i].err == 0 ? 0 : -1); > - if (ddata[i].err) > - errs += assert_errno(i, 2, ddata[i].err, errno); > - else > - errs += assert_str(i, 3, ddata[i].expect, buf); > + errs += assert_str(i, 3, ddata[i].expect, buf); > } > - > return errs; > -} > - > -/************** tests for scan_scaled *******************/ > - > - > -#define IMPROBABLE (-42) > - > -extern int errno; > - > -struct { /* the test cases */ > - char *input; > - quad_t result; > - int err; > -} sdata[] = { > - { "0", 0, 0 }, > - { "123", 123, 0 }, > - { "1k", 1024, 0 }, /* lower case */ > - { "100.944", 100, 0 }, /* should --> 100 (truncates fraction) */ > - { "10099", 10099LL, 0 }, > - { "1M", 1048576LL, 0 }, > - { "1.1M", 1153433LL, 0 }, /* fractions */ > - { "1.111111111111111111M", 1165084LL, 0 }, /* fractions */ > - { "1.55M", 1625292LL, 0 }, /* fractions */ > - { "1.9M", 1992294LL, 0 }, /* fractions */ > - { "-2K", -2048LL, 0 }, /* negatives */ > - { "-2.2K", -2252LL, 0 }, /* neg with fract */ > - { "4.5k", 4608, 0 }, > - { "4.5555555555555555K", 4664, 0 }, > - { "4.5555555555555555555K", 4664, 0 }, /* handle enough digits? */ > - { "4.555555555555555555555555555555K", 4664, 0 }, /* ignores extra digits? */ > - { "1G", 1073741824LL, 0 }, > - { "G", 0, 0 }, /* should == 0G? */ > - { "1234567890", 1234567890LL, 0 }, /* should work */ > - { "1.5E", 1729382256910270464LL, 0 }, /* big */ > - { "32948093840918378473209480483092", 0, ERANGE }, /* too big */ > - { "329480938409.8378473209480483092", 0, ERANGE }, /* fraction too big */ > - { "1.5Q", 0, ERANGE }, /* invalid multiplier (XXX ERANGE??) */ > - { "1ab", 0, ERANGE }, /* ditto */ > - { "5.0e3", 0, EINVAL }, /* digits after */ > - { "5.0E3", 0, EINVAL }, /* ditto */ > - { "1..0", 0, EINVAL }, /* bad format */ > - { "", 0, 0 }, /* boundary */ > - { "--1", -1, EINVAL }, > - { "++42", -1, EINVAL }, > - /* { "9223372036854775808", -9223372036854775808LL, 0 }, */ /* XXX */ > -}; > -# define SDATA_LENGTH (sizeof sdata/sizeof *sdata) > - > -static void > -print_errno(int e) > -{ > - switch(e) { > - case EINVAL: printf("EINVAL"); break; > - case EDOM: printf("EDOM"); break; > - case ERANGE: printf("ERANGE"); break; > - default: printf("errno %d", errno); > - } > -} > - > -/** Print one result */ > -static void > -print(char *input, quad_t result, int ret) > -{ > - int e = errno; > - printf("\"%10s\" --> %lld (%d)", input, result, ret); > - if (ret == -1) { > - printf(" -- "); > - print_errno(e); > - } > - printf("\n"); > -} > - > -static int > -scan_test(void) > -{ > - unsigned int i, errs = 0, e; > - int ret; > - quad_t result; > - > - for (i = 0; i < SDATA_LENGTH; i++) { > - result = IMPROBABLE; > - /* printf("Calling scan_scaled(%s, ...)\n", sdata[i].input); */ > - ret = scan_scaled(sdata[i].input, &result); > - e = errno; /* protect across printfs &c. */ > - if (verbose) > - print(sdata[i].input, result, ret); > - errno = e; > - if (ret == -1) > - errs += assert_int(i, 1, ret, sdata[i].err == 0 ? 0 : -1); > - errno = e; > - if (sdata[i].err) > - errs += assert_errno(i, 2, sdata[i].err, errno); > - else > - errs += assert_quad_t(i, 3, sdata[i].result, result); > - } > - return errs; > -} > - > -static int > -assert_int(int testnum, int check, int expect, int result) > -{ > - if (expect == result) > - return 0; > - printf("** FAILURE: test %d check %d, expect %d, result %d **\n", > - testnum, check, expect, result); > - return 1; > -} > - > -static int > -assert_errno(int testnum, int check, int expect, int result) > -{ > - if (expect == result) > - return 0; > - printf("** FAILURE: test %d check %d, expect ", > - testnum, check); > - print_errno(expect); > - printf(", got "); > - print_errno(result); > - printf(" **\n"); > - return 1; > -} > - > -static int > -assert_quad_t(int testnum, int check, quad_t expect, quad_t result) > -{ > - if (expect == result) > - return 0; > - printf("** FAILURE: test %d check %d, expect %lld, result %lld **\n", > - testnum, check, expect, result); > - return 1; > } > > static int > Index: src/bin/df/df.c > ================================================== ================= > RCS file: /cvs/src/bin/df/df.c,v > retrieving revision 1.48 > diff -u -r1.48 df.c > --- src/bin/df/df.c 22 Dec 2007 17:37:36 -0000 1.48 > +++ src/bin/df/df.c 5 Mar 2008 12:42:34 -0000 > @@ -299,10 +299,7 @@ > { > char ret[FMT_SCALED_STRSIZE]; > > - if (fmt_scaled(bytes, ret) == -1) { > - (void)printf(" %lld", bytes); > - return; > - } > + fmt_scaled(bytes, ret); > (void)printf(" %7s", ret); > } > > Index: src/bin/ls/print.c > ================================================== ================= > RCS file: /cvs/src/bin/ls/print.c,v > retrieving revision 1.25 > diff -u -r1.25 print.c > --- src/bin/ls/print.c 7 May 2007 18:39:28 -0000 1.25 > +++ src/bin/ls/print.c 5 Mar 2008 12:42:34 -0000 > @@ -372,7 +372,8 @@ > { > char ret[FMT_SCALED_STRSIZE]; > > - if ((f_humanval) && (fmt_scaled(bytes, ret) != -1)) { > + if (f_humanval) { > + fmt_scaled(bytes, ret); > (void)printf("%*s ", (u_int)width, ret); > return; > } > Index: src/usr.bin/du/du.c > ================================================== ================= > RCS file: /cvs/src/usr.bin/du/du.c,v > retrieving revision 1.19 > diff -u -r1.19 du.c > --- src/usr.bin/du/du.c 25 Jan 2006 06:20:03 -0000 1.19 > +++ src/usr.bin/du/du.c 5 Mar 2008 12:42:34 -0000 > @@ -312,10 +312,8 @@ > else { > char buf[FMT_SCALED_STRSIZE]; > > - if (fmt_scaled(size * 512, buf) == 0) > - (void)printf("%s\t%s\n", buf, path); > - else > - (void)printf("%lld\t%s\n", (long long)size, path); > + fmt_scaled(size * 512, buf); > + (void)printf("%s\t%s\n", buf, path); > } > } > > Index: src/usr.bin/wc/wc.c > ================================================== ================= > RCS file: /cvs/src/usr.bin/wc/wc.c,v > retrieving revision 1.11 > diff -u -r1.11 wc.c > --- src/usr.bin/wc/wc.c 19 Oct 2005 21:49:02 -0000 1.11 > +++ src/usr.bin/wc/wc.c 5 Mar 2008 12:42:34 -0000 > @@ -246,7 +246,7 @@ > if (humanchar) { > char result[FMT_SCALED_STRSIZE]; > > - (void)fmt_scaled(v, result); > + fmt_scaled(v, result); > (void)printf("%7s", result); > } else { > (void)printf(" %7lld", v); > Index: src/usr.sbin/bgpctl/bgpctl.c > ================================================== ================= > RCS file: /cvs/src/usr.sbin/bgpctl/bgpctl.c,v > retrieving revision 1.132 > diff -u -r1.132 bgpctl.c > --- src/usr.sbin/bgpctl/bgpctl.c 24 Feb 2008 21:02:11 -0000 1.132 > +++ src/usr.sbin/bgpctl/bgpctl.c 5 Mar 2008 12:44:57 -0000 > @@ -1232,9 +1232,7 @@ > { > static char buf[16]; > > - if (fmt_scaled(num, buf) == -1) > - snprintf(buf, sizeof(buf), "%lldB", (long long)num); > - > + fmt_scaled(num, buf); > return (buf); > } |