diff options
author | des <des@FreeBSD.org> | 2010-08-15 18:32:06 +0000 |
---|---|---|
committer | des <des@FreeBSD.org> | 2010-08-15 18:32:06 +0000 |
commit | 3338010b29aee1ea1d5b28973d9b981dc7e4a15a (patch) | |
tree | bce45c4d58bc27285feb085529fb4f9df1227d1e /lib/libutil/expand_number.c | |
parent | f407cc3b8bf18a19de0375c20d6ab712bab4f21d (diff) | |
download | FreeBSD-src-3338010b29aee1ea1d5b28973d9b981dc7e4a15a.zip FreeBSD-src-3338010b29aee1ea1d5b28973d9b981dc7e4a15a.tar.gz |
Further simplify the code, and update the manpage.
Submitted by: Christoph Mallon <christoph.mallon@gmx.de>
Diffstat (limited to 'lib/libutil/expand_number.c')
-rw-r--r-- | lib/libutil/expand_number.c | 47 |
1 files changed, 24 insertions, 23 deletions
diff --git a/lib/libutil/expand_number.c b/lib/libutil/expand_number.c index 30a292e..5d55884 100644 --- a/lib/libutil/expand_number.c +++ b/lib/libutil/expand_number.c @@ -36,7 +36,7 @@ __FBSDID("$FreeBSD$"); #include <stdint.h> /* - * Convert an expression of the following forms to a int64_t. + * Convert an expression of the following forms to a uint64_t. * 1) A positive decimal number. * 2) A positive decimal number followed by a 'b' or 'B' (mult by 1). * 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10). @@ -50,6 +50,7 @@ int expand_number(const char *buf, uint64_t *num) { uint64_t number; + unsigned shift; char *endptr; number = strtoumax(buf, &endptr, 0); @@ -60,41 +61,41 @@ expand_number(const char *buf, uint64_t *num) return (-1); } - if (*endptr == '\0') { - /* No unit. */ - *num = number; - return (0); - } - -#define SHIFT(n, b) \ - do { if (((n << b) >> b) != n) goto overflow; n <<= b; } while (0) - switch (tolower((unsigned char)*endptr)) { case 'e': - SHIFT(number, 10); + shift = 60; + break; case 'p': - SHIFT(number, 10); + shift = 50; + break; case 't': - SHIFT(number, 10); + shift = 40; + break; case 'g': - SHIFT(number, 10); + shift = 30; + break; case 'm': - SHIFT(number, 10); + shift = 20; + break; case 'k': - SHIFT(number, 10); - case 'b': + shift = 10; break; + case 'b': + case '\0': /* No unit. */ + *num = number; + return (0); default: /* Unrecognized unit. */ errno = EINVAL; return (-1); } - *num = number; - return (0); + if ((number << shift) >> shift != number) { + /* Overflow */ + errno = ERANGE; + return (-1); + } -overflow: - /* Overflow */ - errno = ERANGE; - return (-1); + *num = number << shift; + return (0); } |