Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: sh emulation POSIX non-conformances ("inf"/"Inf" in arithmetic expressions)



2021-04-12 13:41:58 -0700, Bart Schaefer:
> On Sun, Apr 11, 2021 at 12:32 PM Stephane Chazelas
> <stephane@xxxxxxxxxxxx> wrote:
> >
> > $ zsh --emulate sh -c 'inf=42; echo $((inf))'
> > Inf
> >
> > (POSIX requires 42 there).
> 
> Is that because "Inf" is case-sensitive, or because POSIX requires
> evaluating the variable?  E.g. what does

That was because "inf" in an arithmetic expression, where inf is
the name of a variable whose contents is an integer constant
(decimal, octal or hex) is meant to represent the corresponding
integer number (and an empty or unset variable is meant to yield
0)..

https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/basedefs/V1_chap08.html#tag_08
warns about some of the special variables used by some shells
(such as RANDOM and SECONDS), but in those cases, $((RANDOM))
still expands to the value of the variable.

Here, a user must make sure they don't use "inf" (or
INF/InF/Inf, nan/NAN...) as the name of a variable if they want
to use it in an arithmetic expression. Same family of issues as
those linked to zsh special parameters or keywords/builtins. 

Since the POSIX shell language doesn't support floating point
arithmetics, zsh could disable it in POSIX mode, but it may not
be worth the bother. Since floating point arithmetics is
supported by a few shells (ksh93, yash, zsh), maybe a better
approach would be for text to be added to the POSIX standard to
warn against using those as variable names.

I think it would be worth documenting that nan and inf are
recognised in arithmetic expressions (and warn against using
variables with the same name). Maybe something like:

diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index bc3e35ad5..44c35edab 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -120,6 +120,11 @@ taken for a parameter name.  All numeric parts (before and after the
 decimal point and in the exponent) may contain underscores after the
 leading digit for visual guidance; these are ignored in computation.
 
+tt(Inf)) and tt(NaN) and all their variation of case (tt(inf), tt(NAN), etc.)
+are also recognised as meaning "infinity" and "not-a-number" floating point
+constants respectively. One should avoid using variables with such names when
+they are to be used in arithmetic expressions.
+
 cindex(arithmetic operators)
 cindex(operators, arithmetic)
 An arithmetic expression uses nearly the same syntax and

> 
> sh -c 'Inf=42; echo $((Inf))'
> 
> yield in POSIX?  What about

42

> sh -c 'unset Inf; echo $((Inf))'

0

> sh -c 'unset inf; echo $((inf))'

0

> ??  I don't have a POSIX shell to test with, it seems.  Ksh "Version A
> 2020.0.0" responds the same as zsh, and bash "5.0.17(1)-release"
> doesn't seem to have Inf at all (and gives a syntax error on
> floating-point arithmetic?).

There's not really such a thing as a POSIX shell. There's a
standard specification of the POSIX sh *language*, and a number
of shell implementations that try to provide a compliant
interpreter for that language.

That language specification was initially based on a subset of
ksh88's, but with some deviations.

The only Unix shells that I know that have been /certified/ as
compliant are some ksh88 derivatives (like on Solaris, AIX,
HPUX) and some versions of bash (in posix mode and with xpg_echo
enabled, like on macos, Inspur K/UX).

They both have non-conformances, especially ksh88-based ones
(which have much more serious ones than the one I've listed in
this thread). I'd say zsh's sh emulation is probably more
compliant than those ksh88-based ones.

The Opengroup does have a certification test suite, but I don't
think it's publicly available.

Note that ksh2020 development has been abandoned. It was based
on a beta version of ksh93 released when AT&T Research was shut
down, but eventually deemed too buggy to fix. There is still
some community effort to maintain a ksh93u+ based shell.

Having said that, ksh93/ksh2020 is one of the few Bourne-like
shells that support floating point arithmetic expressions (and
the first one that did). $((inf)) expands to "inf" for me with
those (which would also make it non-compliant).

yash (the other shell with floating point arithmetic expressions
and which was written to the POSIX specification) doesn't support
nan/inf in arithmetic expressions unless you do

  inf=inf nan=nan (and Inf=inf, NaN=nan... if you want to use
  those)

and disables floating point arithmetics when in posix mode (yash
-o posix). All three handle the locale decimal radix character
differently, which makes me think there's little hope floating
point arithmetics ever makes it to the POSIX spec.

-- 
Stephane




Messages sorted by: Reverse Date, Date, Thread, Author