From a4020e10a33f3f78681a2e18fb7add56338d4e81 Mon Sep 17 00:00:00 2001 From: Jun-ichi Takimoto Date: Wed, 3 Feb 2016 01:24:56 +0900 Subject: 37868: add 'static' to file local variables --- Src/cond.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Src/cond.c') diff --git a/Src/cond.c b/Src/cond.c index c5ab65eea..0381fe94b 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -30,7 +30,8 @@ #include "zsh.mdh" #include "cond.pro" -int tracingcond; +/**/ +int tracingcond; /* updated by execcond() in exec.c */ static char *condstr[COND_MOD] = { "!", "&&", "||", "==", "!=", "<", ">", "-nt", "-ot", "-ef", "-eq", -- cgit v1.2.3 From 1993a3cd2a7b479530da8f37f6fb3ea05a0efb71 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Tue, 13 Sep 2016 09:42:24 +0100 Subject: 39292: Distinguish "=" and "==" tests in output. This is both in xtrace output and shell code rebuilt from internal structures. --- ChangeLog | 6 ++++++ Config/version.mk | 4 ++-- Src/cond.c | 11 +++++++---- Src/parse.c | 9 +++++++-- Src/text.c | 3 ++- Src/zsh.h | 39 +++++++++++++++++++++++---------------- Test/C02cond.ztst | 7 +++++++ Test/D01prompt.ztst | 4 ++-- Test/E02xtrace.ztst | 6 ++++-- 9 files changed, 60 insertions(+), 29 deletions(-) (limited to 'Src/cond.c') diff --git a/ChangeLog b/ChangeLog index 145e9fbc2..603466e2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2016-09-13 Peter Stephenson + * 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. diff --git a/Config/version.mk b/Config/version.mk index 5577f4a0b..a62de3f59 100644 --- a/Config/version.mk +++ b/Config/version.mk @@ -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' diff --git a/Src/cond.c b/Src/cond.c index 0381fe94b..f25ebd4a3 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -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); diff --git a/Src/parse.c b/Src/parse.c index 94ac04922..6e7d40e29 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -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); diff --git a/Src/text.c b/Src/text.c index d387d361a..3658b1bc6 100644 --- a/Src/text.c +++ b/Src/text.c @@ -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 { diff --git a/Src/zsh.h b/Src/zsh.h index 87e6a9868..996bc3369 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -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)); diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst index e315f6c10..78e644a72 100644 --- a/Test/C02cond.ztst +++ b/Test/C02cond.ztst @@ -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 diff --git a/Test/D01prompt.ztst b/Test/D01prompt.ztst index 2638e2438..607ffb698 100644 --- a/Test/D01prompt.ztst +++ b/Test/D01prompt.ztst @@ -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> [[ /very_long_directory_name == (#b)(*)/very_long_directory_name ]] +?+zsh_directory_name:4> [[ d = n ]] +?+zsh_directory_name:12> [[ /very_long_directory_name = (#b)(*)/very_long_directory_name ]] ?+zsh_directory_name:14> return 0 ?+fn:7> local d='~[:l]' ?+fn:8> print '~[:l]' diff --git a/Test/E02xtrace.ztst b/Test/E02xtrace.ztst index 6e425e703..da6191cd0 100644 --- a/Test/E02xtrace.ztst +++ b/Test/E02xtrace.ztst @@ -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() { -- cgit v1.2.3 From fbafc5b509e311efee064bbd12396a2e207f3393 Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Fri, 16 Sep 2016 00:00:28 +0200 Subject: 39332: support ksh's [[ -v varname ]] condition for checking if variables are set --- ChangeLog | 4 ++++ Completion/Zsh/Context/_condition | 3 +++ Doc/Zsh/cond.yo | 3 +++ Src/cond.c | 2 ++ Src/params.c | 30 ++++++++++++++++++++++++++++++ Src/parse.c | 4 ++-- Test/C02cond.ztst | 19 +++++++++++++++++++ 7 files changed, 63 insertions(+), 2 deletions(-) (limited to 'Src/cond.c') diff --git a/ChangeLog b/ChangeLog index 1c749ae64..f54d78ca3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2016-09-15 Oliver Kiddle + * 39332: Doc/Zsh/cond.yo, Src/cond.c, Src/params.c, Src/parse.c, + Completion/Zsh/Context/_condition, Test/C02cond.ztst: support + ksh's [[ -v varname ]] condition for checking if variables are set + * unposted: Src/parse.c: remove duplicated assignment 2016-09-14 Peter Stephenson diff --git a/Completion/Zsh/Context/_condition b/Completion/Zsh/Context/_condition index 6f5e601f0..0285911ac 100644 --- a/Completion/Zsh/Context/_condition +++ b/Completion/Zsh/Context/_condition @@ -8,6 +8,8 @@ elif [[ "$prev" = -([a-hkprsuwxLOGSN]|[no]t|ef) ]]; then _tags -C "$prev" files && _files elif [[ "$prev" = -t ]]; then _file_descriptors +elif [[ "$prev" = -v ]]; then + _parameters -r "\= \t\n\[\-" else if [[ "$PREFIX" = -* ]] || ! zstyle -T ":completion:${curcontext}:options" prefix-needed; then @@ -30,6 +32,7 @@ else -s:non-empty\ file -t:terminal\ file\ descriptor -u:setuid\ bit + -v:set\ variable -w:writable\ file -x:executable\ file -z:empty\ string diff --git a/Doc/Zsh/cond.yo b/Doc/Zsh/cond.yo index 474baa1ec..e08fc0d36 100644 --- a/Doc/Zsh/cond.yo +++ b/Doc/Zsh/cond.yo @@ -63,6 +63,9 @@ is open and associated with a terminal device. item(tt(-u) var(file))( true if var(file) exists and has its setuid bit set. ) +item(tt(-v) var(varname))( +true if shell variable var(varname) is set. +) item(tt(-w) var(file))( true if var(file) exists and is writable by current process. ) diff --git a/Src/cond.c b/Src/cond.c index f25ebd4a3..42e9de30f 100644 --- a/Src/cond.c +++ b/Src/cond.c @@ -351,6 +351,8 @@ evalcond(Estate state, char *fromtest) return (!S_ISSOCK(dostat(left))); case 'u': return (!(dostat(left) & S_ISUID)); + case 'v': + return (!issetvar(left)); case 'w': return (!doaccess(left, W_OK)); case 'x': diff --git a/Src/params.c b/Src/params.c index 842b2f0d1..384c30a1a 100644 --- a/Src/params.c +++ b/Src/params.c @@ -626,6 +626,36 @@ getvaluearr(Value v) return NULL; } +/* Return whether the variable is set * + * checks that array slices are within range * + * used for [[ -v ... ]] condition test */ + +/**/ +int +issetvar(char *name) +{ + struct value vbuf; + Value v; + int slice; + char **arr; + + if (!(v = getvalue(&vbuf, &name, 1)) || *name) + return 0; /* no value or more chars after the variable name */ + if (v->isarr & ~SCANPM_ARRONLY) + return v->end > 1; /* for extracted elements, end gives us a count */ + + slice = v->start != 0 || v->end != -1; + if (PM_TYPE(v->pm->node.flags) != PM_ARRAY || !slice) + return !slice && !(v->pm->node.flags & PM_UNSET); + + if (!v->end) /* empty array slice */ + return 0; + /* get the array and check end is within range */ + if (!(arr = getvaluearr(v))) + return 0; + return arrlen_ge(arr, v->end < 0 ? - v->end : v->end); +} + /* * Split environment string into (name, value) pair. * this is used to avoid in-place editing of environment table diff --git a/Src/parse.c b/Src/parse.c index d3c418184..24b8cd97f 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -2385,7 +2385,7 @@ par_cond_2(void) s1 = tokstr; dble = (s1 && *s1 == '-' && (!n_testargs - || strspn(s1+1, "abcdefghknoprstuwxzLONGS") == 1) + || strspn(s1+1, "abcdefghknoprstuvwxzLONGS") == 1) && !s1[2]); if (tok != STRING) { /* Check first argument for [[ STRING ]] re-interpretation */ @@ -2464,7 +2464,7 @@ par_cond_double(char *a, char *b) { if (a[0] != '-' || !a[1]) COND_ERROR("parse error: condition expected: %s", a); - else if (!a[2] && strspn(a+1, "abcdefgknoprstuwxzhLONGS") == 1) { + else if (!a[2] && strspn(a+1, "abcdefgknoprstuvwxzhLONGS") == 1) { ecadd(WCB_COND(a[1], 0)); ecstr(b); } else { diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst index 78e644a72..40e4dfb0b 100644 --- a/Test/C02cond.ztst +++ b/Test/C02cond.ztst @@ -269,6 +269,25 @@ F:Failures in these cases do not indicate a problem in the shell. 0:-nt shouldn't abort on non-existent files >status = 1 + str='string' empty='' + [[ -v IFS && -v str && -v empty && ! -v str[3] && ! -v not_a_variable ]] +0:-v cond + + arr=( 1 2 3 4 ) empty=() + [[ -v arr && -v arr[1,4] && -v arr[1] && -v arr[4] && -v arr[-4] && + -v arr[(i)3] && ! -v arr[(i)x] && + ! -v arr[0] && ! -v arr[5] && ! -v arr[-5] && ! -v arr[2][1] && + ! -v arr[3]extra && -v empty && ! -v empty[1] ]] +0:-v cond with array + + typeset -A assoc=( key val num 4 ) + [[ -v assoc && -v assoc[key] && -v assoc[(i)*] && -v assoc[(I)*] && + ! -v assoc[x] && ! -v assoc[key][1] ]] +0:-v cond with association + + () { [[ -v 0 && -v 1 && -v 2 && ! -v 3 ]] } arg '' +0:-v cond with positional parameters + # core dumps on failure if zmodload zsh/regex 2>/dev/null; then echo >regex_test.sh 'if [[ $# = 1 ]]; then -- cgit v1.2.3