On Tue, 5 Apr 2016 09:09:40 -0600 Eric Blake <[email protected]> wrote:
> tag 23222 confirmed > thanks > > On 04/05/2016 05:57 AM, Mattias Andrée wrote: > > Failing test-case #1: > > > > ./test -n -a -n > > > > fails and outputs > > > > ./test: extra argument ‘-n’ > > > > Expected behaviour is silent success, as seen in > > Bash's implementation. > > Thanks for the report. POSIX indeed says that -a is a > binary primary, and also says that > "3 arguments: > If $2 is a binary primary, perform the binary > test of $1 and > $3." (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) > > So by that reading, coreutils MUST parse your expression > as: > > test \( -n \) -a \( -n \) > > whereas it appears that coreutils has instead > accidentally parsed it as: > > test \( -n -a \) -n > > Not everyday someone finds a real bug in 'test'! > > That said, POSIX _also_ says that portable scripts MUST > NOT use -a or -o; it is inherently ambiguous. > > You are better off fixing your script to use: > > test -n && test -n > > whether or not someone is able to quickly patch > coreutils' bug. I'm not actually using -a, -o, (, ), and !. I just noticed the bug by running some test-cases. > > > > > > Explanation: -a has higher precedence than -n. > > Not quite true. The POSIX rules state that -a is > optional (non-XSI systems don't even have to have it), > and that precedence has no bearing (rather, it is whether > you have exactly three arguments that determines whether > -a must be used in its role as a binary operator). > > > > > > Failing test-case #2: > > > > ./test ! '' -a '' > > > > shall fail (exit value 1), but in this > > implementation it succeeds. > > Sorry, but here, you're wrong. POSIX states: > > "4 arguments: > If $1 is '!', negate the three-argument test of > $2, $3, and $4." > > which means this parses as: > > test ! \( '' -a '' \) > > or as: > > test ! \( \( '' \) -a \( '' \) \) > > The negation of 'false and false' is true, so the exit > status is correctly 0. > > > > > > Explanation: ! has higher precedence than -a, > > Wrong. As mentioned above, the rules are based not on > precedence, but on how many operands are present. > XSI-conformant systems shall use the following precedence rules (highest to lowest), as documented (not quite as clearly) in the POSIX specifications: * parentheses (1) * string binary primaries * unary non-string primaries * algebraic binary primaries (2) * unary string primary with * (3) * ! * -a * -o * (4) in that order but not necessarily directly followed by each other somewhere between (1) and (2), and with other binary primitives somewhere between (3) and (5). The POSIX specification does indeed that that the number of arguments shall determine the precedence for 1 to 4 arguments. And the given rules do conflict with XSI. But if we run test \( \( ... \) \) instead of test it seems only reasonable to use the XSI rules. Is it too much to ask that test ... gives the same result? Your implementation appear to be unaffected if it is given extra parentheses in this way. But it does evaluate test ! \( '' \) -a \( '' \) as expected. It is very weird that test ! \( '' \) -a \( '' \) and test ! '' -a '' do not give the same result. I believe that POSIX rule for 4 arguments shall be disregarded. It is clearly only intended for other binary operators than logical operators.
pgp1tSZGm9sQA.pgp
Description: OpenPGP digital signature
