39292: Distinguish "=" and "==" tests in output.

This is both in xtrace output and shell code rebuilt from
internal structures.
This commit is contained in:
Peter Stephenson 2016-09-13 09:42:24 +01:00
parent 23c1c774b9
commit 1993a3cd2a
9 changed files with 60 additions and 29 deletions

View File

@ -1,5 +1,11 @@
2016-09-13 Peter Stephenson <p.stephenson@samsung.com>
* 39292: Config/version.mk, Src/cond.c, Src/parse.c, Src/text.c,
Src/zsh.h, Test/C02cond.ztst, Test/D01prompt.ztst,
Test/E02xtrace.ztst: Distinguish "=" and "==" tests in output to
avoid confusion. Update version number to 5.2-dev-2 (unposted:
update date, too).
* 39305: Src/exec.c: error handling on substitution for here
document was illogical.

View File

@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
VERSION=5.2-dev-1
VERSION_DATE='January 20, 2015'
VERSION=5.2-dev-2
VERSION_DATE='August 13, 2016'

View File

@ -34,7 +34,7 @@
int tracingcond; /* updated by execcond() in exec.c */
static char *condstr[COND_MOD] = {
"!", "&&", "||", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"!", "&&", "||", "=", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"-ne", "-lt", "-gt", "-le", "-ge", "=~"
};
@ -196,7 +196,8 @@ evalcond(Estate state, char *fromtest)
cond_subst(&left, !fromtest);
untokenize(left);
}
if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRNEQ) {
if (ctype <= COND_GE && ctype != COND_STREQ && ctype != COND_STRDEQ &&
ctype != COND_STRNEQ) {
right = ecgetstr(state, EC_DUPTOK, &htok);
if (htok) {
cond_subst(&right, !fromtest);
@ -208,7 +209,8 @@ evalcond(Estate state, char *fromtest)
fputc(' ',xtrerr);
quotedzputs(left, xtrerr);
fprintf(xtrerr, " %s ", condstr[ctype]);
if (ctype == COND_STREQ || ctype == COND_STRNEQ) {
if (ctype == COND_STREQ || ctype == COND_STRDEQ ||
ctype == COND_STRNEQ) {
char *rt = dupstring(ecrawstr(state->prog, state->pc, NULL));
cond_subst(&rt, !fromtest);
quote_tokenized_output(rt, xtrerr);
@ -287,6 +289,7 @@ evalcond(Estate state, char *fromtest)
switch (ctype) {
case COND_STREQ:
case COND_STRDEQ:
case COND_STRNEQ:
{
int test, npat = state->pc[1];
@ -313,7 +316,7 @@ evalcond(Estate state, char *fromtest)
state->pc += 2;
test = (pprog && pattry(pprog, left));
return !(ctype == COND_STREQ ? test : !test);
return !(ctype == COND_STRNEQ ? !test : test);
}
case COND_STRLT:
return !(strcmp(left, right) < 0);

View File

@ -2498,12 +2498,17 @@ par_cond_triple(char *a, char *b, char *c)
{
int t0;
if ((b[0] == Equals || b[0] == '=') &&
(!b[1] || ((b[1] == Equals || b[1] == '=') && !b[2]))) {
if ((b[0] == Equals || b[0] == '=') && !b[1]) {
ecadd(WCB_COND(COND_STREQ, 0));
ecstr(a);
ecstr(c);
ecadd(ecnpats++);
} else if ((b[0] == Equals || b[0] == '=') &&
(b[1] == Equals || b[1] == '=') && !b[2]) {
ecadd(WCB_COND(COND_STRDEQ, 0));
ecstr(a);
ecstr(c);
ecadd(ecnpats++);
} else if (b[0] == '!' && (b[1] == Equals || b[1] == '=') && !b[2]) {
ecadd(WCB_COND(COND_STRNEQ, 0));
ecstr(a);

View File

@ -46,7 +46,7 @@ int text_expand_tabs;
* et seq. in zsh.h.
*/
static const char *cond_binary_ops[] = {
"=", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"=", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq",
"-ne", "-lt", "-gt", "-le", "-ge", "=~", NULL
};
@ -934,6 +934,7 @@ gettext2(Estate state)
taddstr(" ");
taddstr(ecgetstr(state, EC_NODUP, NULL));
if (ctype == COND_STREQ ||
ctype == COND_STRDEQ ||
ctype == COND_STRNEQ)
state->pc++;
} else {

View File

@ -622,27 +622,34 @@ struct timedfn {
/* (1<<4) is used for Z_END, see the wordcode definitions */
/* (1<<5) is used for Z_SIMPLE, see the wordcode definitions */
/* Condition types. */
/*
* Condition types.
*
* Careful when changing these: both cond_binary_ops in text.c and
* condstr in cond.c depend on these. (The zsh motto is "two instances
* are better than one". Or something.)
*/
#define COND_NOT 0
#define COND_AND 1
#define COND_OR 2
#define COND_STREQ 3
#define COND_STRNEQ 4
#define COND_STRLT 5
#define COND_STRGTR 6
#define COND_NT 7
#define COND_OT 8
#define COND_EF 9
#define COND_EQ 10
#define COND_NE 11
#define COND_LT 12
#define COND_GT 13
#define COND_LE 14
#define COND_GE 15
#define COND_REGEX 16
#define COND_MOD 17
#define COND_MODI 18
#define COND_STRDEQ 4
#define COND_STRNEQ 5
#define COND_STRLT 6
#define COND_STRGTR 7
#define COND_NT 8
#define COND_OT 9
#define COND_EF 10
#define COND_EQ 11
#define COND_NE 12
#define COND_LT 13
#define COND_GT 14
#define COND_LE 15
#define COND_GE 16
#define COND_REGEX 17
#define COND_MOD 18
#define COND_MODI 19
typedef int (*CondHandler) _((char **, int));

View File

@ -414,6 +414,13 @@ F:Failures in these cases do not indicate a problem in the shell.
>OK 4
>OK 5
fn() { [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]] }
which -x2 fn
0: = and == appear as input
>fn () {
> [[ 'a' == 'b' || 'b' = 'c' || 'c' != 'd' ]]
>}
%clean
# This works around a bug in rm -f in some versions of Cygwin
chmod 644 unmodish

View File

@ -196,8 +196,8 @@
?+zsh_directory_name:1> emulate -L zsh
?+zsh_directory_name:2> setopt extendedglob
?+zsh_directory_name:3> local -a match mbegin mend
?+zsh_directory_name:4> [[ d == n ]]
?+zsh_directory_name:12> [[ <parent>/very_long_directory_name == (#b)(*)/very_long_directory_name ]]
?+zsh_directory_name:4> [[ d = n ]]
?+zsh_directory_name:12> [[ <parent>/very_long_directory_name = (#b)(*)/very_long_directory_name ]]
?+zsh_directory_name:14> return 0
?+fn:7> local d='~[<parent>:l]'
?+fn:8> print '~[<parent>:l]'

View File

@ -120,13 +120,15 @@
?+./fnfile:3> print This is fn.
set -x
[[ 'f o' == 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
[[ 'f o' = 'f x'* || 'b r' != 'z o' && 'squashy sound' < 'squishy sound' ]]
[[ -e nonexistentfile || ( -z '' && -t 3 ) ]]
set +x
0:Trace for conditions
?+(eval):2> [[ 'f o' == f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
?+(eval):3> [[ -e nonexistentfile || -z '' && -t 3 ]]
?+(eval):4> set +x
?+(eval):3> [[ 'f o' = f\ x* || 'b r' != z\ o && 'squashy sound' < 'squishy sound' ]]
?+(eval):4> [[ -e nonexistentfile || -z '' && -t 3 ]]
?+(eval):5> set +x
# Part 1: Recurses into nested anonymous functions
fn() {