test: fix 4-argument case
Upstream dash commit:
Date: Sun, 13 Jul 2008 19:20:10 +0800
Fixed 3,4-argument cases for test per POSIX
----- Forwarded message from Gerrit Pape <pape@smarden.org> -----
Subject: Bug#455828: dash: 4-argument test "test \( ! -e \)" yields an error
Date: Fri, 28 Dec 2007 08:53:29 +0000
From: Gerrit Pape <pape@smarden.org>
To: Vincent Lefevre <vincent@vinc17.org>, 455828@bugs.debian.org
On Thu, Dec 27, 2007 at 06:23:20PM +0100, Vincent Lefevre wrote:
> On 2007-12-27 16:00:06 +0000, Gerrit Pape wrote:
> > On Wed, Dec 12, 2007 at 02:18:47AM +0100, Vincent Lefevre wrote:
> > > According to POSIX[*], "test \( ! -e \)" is a 4-argument test and is
> > > here equivalent to "test ! -e". But dash (like ksh93 and bash) yields
> > > an error:
> > >
> > > $ test \( ! -e \) || echo $?
> > > test: 1: closing paren expected
> > > 2
> > > $ test ! -e || echo $?
> > > 1
> >
> > Hi Vincent,
> >
> > the -e switch to test takes an argument, a pathname.
>
> According to POSIX, in both above examples, "-e" is *not* a switch,
> just a string.
>
> test \( ! -e \)
>
> means: return true if the string "-e" is empty, otherwhise return false.
> The error in dash is that it incorrectly thinks that "-e" is a switch in
> this context.
I see, you're right. Thanks, Gerrit.
----- End forwarded message -----
This patch hard-codes the 3,4-argument cases in the way required by
POSIX.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
function old new delta
test_main 370 421 +51
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
@@ -879,18 +879,48 @@ int test_main(int argc, char **argv)
|
||||
res = (argv[0][0] == '\0');
|
||||
goto ret_special;
|
||||
}
|
||||
if (argv[2] && !argv[3]) {
|
||||
check_operator(argv[1]);
|
||||
if (last_operator->op_type == BINOP) {
|
||||
/* "test [!] arg1 <binary_op> arg2" */
|
||||
args = argv;
|
||||
res = (binop() == 0);
|
||||
if (argv[2]) {
|
||||
if (!argv[3]) {
|
||||
/*
|
||||
* http://pubs.opengroup.org/onlinepubs/009695399/utilities/test.html
|
||||
* """ 3 arguments:
|
||||
* If $2 is a binary primary, perform the binary test of $1 and $3.
|
||||
* """
|
||||
*/
|
||||
check_operator(argv[1]);
|
||||
if (last_operator->op_type == BINOP) {
|
||||
/* "test [!] arg1 <binary_op> arg2" */
|
||||
args = argv;
|
||||
res = (binop() == 0);
|
||||
ret_special:
|
||||
/* If there was leading "!" op... */
|
||||
res ^= negate;
|
||||
goto ret;
|
||||
/* If there was leading "!" op... */
|
||||
res ^= negate;
|
||||
goto ret;
|
||||
}
|
||||
/* """If $1 is '(' and $3 is ')', perform the unary test of $2."""
|
||||
* Looks like this works without additional coding.
|
||||
*/
|
||||
goto check_negate;
|
||||
}
|
||||
/* argv[3] exists (at least 4 args), is it exactly 4 args? */
|
||||
if (!argv[4]) {
|
||||
/*
|
||||
* """ 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.
|
||||
* """
|
||||
* Example why code below is necessary: test '(' ! -e ')'
|
||||
*/
|
||||
if (LONE_CHAR(argv[0], '(')
|
||||
&& LONE_CHAR(argv[3], ')')
|
||||
) {
|
||||
/* "test [!] ( x y )" */
|
||||
argv[3] = NULL;
|
||||
argv++;
|
||||
}
|
||||
}
|
||||
}
|
||||
check_negate:
|
||||
if (LONE_CHAR(argv[0], '!')) {
|
||||
argv++;
|
||||
negate ^= 1;
|
||||
|
||||
Reference in New Issue
Block a user