svn commit: r350179 - head/lib/libutil

Bruce Evans brde at optusnet.com.au
Sat Jul 20 19:58:12 UTC 2019


On Sat, 20 Jul 2019, John Baldwin wrote:

> Log:
>  expand_number(3) parses suffixes, not prefixes.

This is not quite correct, although conflating prefixes and suffixes is
one of the bugs that I pointed out in mails about [de]humanize_number and
expand_number() long ago.

Bugs in expand_number() start with its name.  It doesn't expand numbers.
It parses strings and produces integers with a wrong limited type/range
(uint64_t instead of uintmax_t plus sign info).  I don't know what it
means to expand a number, but this is close to the opposite.

expand_number() is not nearly as badly designed as humanize_number().
humanize_number() doesn't humanize numbers.  It converts integers with
a different wrong limited type/range (int64_t instead of uint64_t plus
sign info) to a hideous/dehumanized string format.  The humanized format
would be decimal decimal.  humanize_number() produces a scientific format.

humanize_number() still documents SI prefixes, and has a suffix arg which
gives the units.  Its SI prefixes are prefixes to the suffix.  E.g., a
prefix of "K" and a suffix of "B" gives units of non-disk-marketers
kilobytes.  It is only when the suffix is null that the prefix becomes
a suffix.  Most quantities have units, but it is common to omit the units
in the string representation to save space.  expand_number() doesn't even
support units, except it treats the suffix "B" or "b" as a null unit
provided it doesn't have a prefix (e.g., "1B" gives 1, byut "1KB" is a 
syntax error).

strtonum() uses the long long abomination instead of the correct type
(uintmax_t with sign info).  Its name is better, but uses the precious
str* namespace for a badly designed API.

I would prefer a strtonum() that is more like expand_number() (not too
much error handling) but handles any number of suffixes and multipliers
like the number-parsing function in dd.  This should be almost as easy
to use as atoi(), but have some error handling.  E.g.,

 	uintmax_t strtonum(const char *nptr, const char *errspec, ...);

where simple uses use errspec = NULL to get default error handling
similar to expand_number().  errspec would need 3 specifiers to specify
the last 3 args in the current strtonum().

> Modified: head/lib/libutil/expand_number.3
> ==============================================================================
> --- head/lib/libutil/expand_number.3	Sat Jul 20 15:59:49 2019	(r350178)
> +++ head/lib/libutil/expand_number.3	Sat Jul 20 16:03:54 2019	(r350179)
> @@ -42,11 +42,10 @@
> .Sh DESCRIPTION
> The
> .Fn expand_number
> -function unformats the
> +function parses the

Better.

The supported formats are still undocumented.  Not even that they are
integers.  They may have leading whitespace and signs, or hex and octal
prefixes (anything parseable by strtoumax(), with special treatment of
a single optional suffix character).

> .Fa buf
> -string and stores a unsigned 64-bit quantity at address pointed out by the
> -.Fa num
> -argument.
> +string and stores a unsigned 64-bit quantity at
> +.Fa *num .

"unsigned 64-bit quantity" is a bad way of spelling of "uint64_t".
uint64_t's aren't quantities.

> .Pp
> The
> .Fn expand_number
> @@ -54,9 +53,9 @@ function
> is case-insensitive and
> follows the SI power of two convention.

There is no SI power of 2 convention according to Wikipedia.

humanize_number() and its bugs must be understood to see what this means.

Google gives approximately zero hits for "SI suffix".  It automatically
translates "SI suffix" to "SI prefix" and of course finds zillions of hits
for that.  humanize_number(3) says that it "follows the traditional
computer science conventions by default, rather than the IEE/IEC (and now
also SI) power of two convention...", but according to Wikipedia, IEC
60027-2 Amendment 2 confirms that SI only supports power of 10 prefixes.

According to Wikipedia, the power of 2 convention is IEC for kibi
through yobi, and JEDEC has the better traditional prefixes and names for
K/kilo though G/Giga.

k is documented to mean 1000 and K 1024 for humanize_number(), but
expand_number() treats both as 1024.  The other prefixes can't be
disambiguated like this.

> .Pp
> -The prefixes are:
> -.Bl -column "Prefix" "Description" "1000000000000000000" -offset indent
> -.It Sy "Prefix" Ta Sy "Description" Ta Sy "Multiplier"
> +The suffixes are:
> +.Bl -column "Suffix" "Description" "1000000000000000000" -offset indent
> +.It Sy "Suffix" Ta Sy "Description" Ta Sy "Multiplier"
> .It Li K Ta No kilo Ta 1024
> .It Li M Ta No mega Ta 1048576
> .It Li G Ta No giga Ta 1073741824
> @@ -74,7 +73,7 @@ function will fail if:
> .It Bq Er EINVAL
> The given string contains no digits.
> .It Bq Er EINVAL
> -An unrecognized prefix was given.
> +An unrecognized suffix was given.
> .It Bq Er ERANGE
> Result doesn't fit into 64 bits.
> .El

Bruce


More information about the svn-src-all mailing list