From cb596a55d921cb638a3cf0ede3ee60ae13728c10 Mon Sep 17 00:00:00 2001
From: Peter Stephenson
Date: Wed, 27 May 2015 21:25:55 +0100
Subject: 35306: "test -z \(" failed due to parse confusion
---
ChangeLog | 3 +++
Src/parse.c | 25 +++++++++++++++++--------
Test/C02cond.ztst | 14 ++++++++++++++
3 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d12275f41..625fd0160 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2015-05-27 Peter Stephenson
+ * 35306: Src/parse.c, Test/C02cond.ztst: "test -z \("
+ failed owing to overeager parsing.
+
* unposted: Config/version.mk: 5.0.7-dev-4.
2015-05-27 Daniel Hahler
diff --git a/Src/parse.c b/Src/parse.c
index 06cea744e..c932851d9 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -2212,13 +2212,14 @@ par_cond_2(void)
{
char *s1, *s2, *s3;
int dble = 0;
+ int n_testargs = (condlex == testlex) ? arrlen(testargs) + 1 : 0;
- if (condlex == testlex) {
+ if (n_testargs) {
/* See the description of test in POSIX 1003.2 */
if (tok == NULLTOK)
/* no arguments: false */
return par_cond_double(dupstring("-n"), dupstring(""));
- if (!*testargs) {
+ if (n_testargs == 1) {
/* one argument: [ foo ] is equivalent to [ -n foo ] */
s1 = tokstr;
condlex();
@@ -2227,7 +2228,7 @@ par_cond_2(void)
return par_cond_double(s1, dupstring("1"));
return par_cond_double(dupstring("-n"), s1);
}
- if (testargs[1]) {
+ if (n_testargs > 2) {
/* three arguments: if the second argument is a binary operator, *
* perform that binary test on the first and the third argument */
if (!strcmp(*testargs, "=") ||
@@ -2253,7 +2254,7 @@ par_cond_2(void)
* In "test" compatibility mode, "! -a ..." and "! -o ..."
* are treated as "[string] [and] ..." and "[string] [or] ...".
*/
- if (!(condlex == testlex && *testargs &&
+ if (!(n_testargs > 1 &&
(!strcmp(*testargs, "-a") || !strcmp(*testargs, "-o"))))
{
condlex();
@@ -2277,19 +2278,27 @@ par_cond_2(void)
}
s1 = tokstr;
dble = (s1 && *s1 == '-'
- && (condlex != testlex
+ && (!n_testargs
|| strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1)
&& !s1[2]);
if (tok != STRING) {
/* Check first argument for [[ STRING ]] re-interpretation */
if (s1 /* tok != DOUTBRACK && tok != DAMPER && tok != DBAR */
- && tok != LEXERR && (!dble || condlex == testlex)) {
+ && tok != LEXERR && (!dble || n_testargs)) {
condlex();
return par_cond_double(dupstring("-n"), s1);
} else
YYERROR(ecused);
}
condlex();
+ if (n_testargs == 2 && tok != STRING && tokstr && s1[0] == '-') {
+ /*
+ * Something like "test -z" followed by a token.
+ * We'll turn the token into a string (we've also
+ * checked it does have a string representation).
+ */
+ tok = STRING;
+ }
if (tok == INANG || tok == OUTANG) {
enum lextok xtok = tok;
condlex();
@@ -2308,7 +2317,7 @@ par_cond_2(void)
* mean we have to go back and fix up the first one
*/
if (tok != LEXERR) {
- if (!dble || condlex == testlex)
+ if (!dble || n_testargs)
return par_cond_double(dupstring("-n"), s1);
else
return par_cond_multi(s1, newlinklist());
@@ -2316,7 +2325,7 @@ par_cond_2(void)
YYERROR(ecused);
}
s2 = tokstr;
- if (condlex != testlex)
+ if (!n_testargs)
dble = (s2 && *s2 == '-' && !s2[2]);
incond++; /* parentheses do globbing */
condlex();
diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst
index 6581b9d6b..02fa4d473 100644
--- a/Test/C02cond.ztst
+++ b/Test/C02cond.ztst
@@ -374,6 +374,20 @@ F:Failures in these cases do not indicate a problem in the shell.
>foo is empty
>foo is full
+ test -z \( || print Not zero 1
+ test -z \< || print Not zero 2
+ test -n \( && print Not zero 3
+ test -n \) && print Not zero 4
+ [ -n \> ] && print Not zero 5
+ [ -n \! ] && print Not zero 6
+0:test with two arguments and a token
+>Not zero 1
+>Not zero 2
+>Not zero 3
+>Not zero 4
+>Not zero 5
+>Not zero 6
+
%clean
# This works around a bug in rm -f in some versions of Cygwin
chmod 644 unmodish
--
cgit 1.4.1