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

Re: 4.3.4-dev-4 and 4.2.6-dev-2 available

On 2007-12-12 13:07:03 +0000, Peter Stephenson wrote:
> which is that in the traditional "test" command (not [[, which is parsed
> properly),
>   ( ! -e )
> should be treated as
>   ( ! -n -e )
> which is horrible, but it's a horror we're already trying to work around so
> presumably we ought to go the extra mile.

No, this is not what POSIX says. See


In particular:

  The algorithm for determining the precedence of the operators and
  the return value that shall be generated is based on the number of
  arguments presented to test.

Here, there are 4 arguments. Thus the parentheses have the precedence:

  4 arguments:
    * If $1 is '!', negate the three-argument test of $2, $3, and $4.
    * If $1 is '(' and $4 is ')', perform the two-argument test of $2
      and $3.

As a consequence, this is equivalent to 'test ! -e' (2-argument test),
which corresponds to:

  2 arguments:
    * If $1 is '!', exit true if $2 is null, false if $2 is not null.

> Furthermore, this change makes
>   ( ! -e ) )
> an error:

Hmm... I don't think so. POSIX is a bit unclear, but its rationale
is more detailed. If you use a greedy left-to-right algorithm and
the POSIX precedence rules, this is not an error. Otherwise I don't
see how you can determine which closing parenthesis you should take
(taking the first one doesn't seem to be more intuitive than taking
the last one). Now, I can see that GNU test regards this as an
error, but it may be wrong here.

However, I don't know how this should be parsed:

  -n OK -a ! ( = )

i.e. if this should be regarded as

  -n OK -a ! ( <expression> )

or as

  -n OK -a ! <string> = <string>

Or things like this: -n OK -a ! = = =

> Unfortunately,
>   ( -e ) )
> is parsed by GNU test as -e ")" in parentheses. This is rather
> inconsistent of it.

Well, this is what POSIX (with XSI) requires: the rules are different
whether you have up to 4 arguments or more than 4 arguments. Portable
script should follow POSIX anyway. Otherwise, users should rather use
[[ ... ]]. As you said, the 'test' builtin is for compatibility.

But try the following:

  /usr/bin/test -n OK -a \( -e \) \)

Here it returns the error:

  /usr/bin/test: extra argument `)'

This is consistent with its parsing of "\( \! -e \) \)". I still think
that both are wrong, though.

I think the rationale behind the specific rules for up to 4 arguments
is for compatibility with historical systems, to be able to support
the implicit "-n".

> What I don't have is a set of tests:  our test suite doesn't include many
> tests for test or [.  This is a real nuisance, since it's quite likely this
> changes something.  So I'll need to write something first (I presume no one
> else is going to).

Perhaps GNU test has a more complete test suite, at least for the
cases up to 4 arguments?

Vincent Lefèvre <vincent@xxxxxxxxxx> - Web: <http://www.vinc17.org/>
100% accessible validated (X)HTML - Blog: <http://www.vinc17.org/blog/>
Work: CR INRIA - computer arithmetic / Arenaire project (LIP, ENS-Lyon)

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