From bced1beb8cc530ea28aa994808707043dd156fb8 Mon Sep 17 00:00:00 2001 From: Daniel Shahaf Date: Wed, 20 Jan 2016 07:47:53 +0000 Subject: 37700: Teach ${(z)} the 'repeat WORD SUBLIST' syntax. --- Src/parse.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Src/parse.c') diff --git a/Src/parse.c b/Src/parse.c index 4829e3a6d..628a9aa2d 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -63,6 +63,12 @@ int isnewlin; /**/ int infor; +/* != 0 if we are after a repeat keyword; if it's nonzero it's a 1-based index + * of the current token from the last-seen command position */ + +/**/ +int inrepeat_; /* trailing underscore because of name clash with Zle/zle_vi.c */ + /* != 0 if parsing arguments of typeset etc. */ /**/ @@ -271,6 +277,7 @@ parse_context_save(struct parse_stack *ps, int toplevel) ps->incasepat = incasepat; ps->isnewlin = isnewlin; ps->infor = infor; + ps->inrepeat_ = inrepeat_; ps->intypeset = intypeset; ps->hdocs = hdocs; @@ -305,6 +312,7 @@ parse_context_restore(const struct parse_stack *ps, int toplevel) incasepat = ps->incasepat; isnewlin = ps->isnewlin; infor = ps->infor; + inrepeat_ = ps->inrepeat_; intypeset = ps->intypeset; hdocs = ps->hdocs; @@ -447,6 +455,7 @@ init_parse_status(void) * using the lexical analyser for strings as well as here. */ incasepat = incond = inredir = infor = intypeset = 0; + inrepeat_ = 0; incmdpos = 1; } @@ -1482,6 +1491,7 @@ par_while(int *cmplx) static void par_repeat(int *cmplx) { + /* ### what to do about inrepeat_ here? */ int oecused = ecused, p; p = ecadd(0); -- cgit v1.2.3 From bc958ab27591f3bb717efeb95fa541ee14a2405b Mon Sep 17 00:00:00 2001 From: "Barton E. Schaefer" Date: Sun, 6 Mar 2016 15:10:27 -0800 Subject: 38106: if...then if...else should be a parse error. --- ChangeLog | 2 ++ Src/parse.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 734d685fa..b9d34e430 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,7 @@ 2016-03-06 Barton E. Schaefer + * 38106: Src/parse.c: if...then if...else should be a parse error. + * Greg Klanderman: 38086: Doc/Zsh/params.yo, Src/init.c, Src/params.c: shuffle init code to localize a global, add $ZSH_ARGZERO, refine $ZSH_SCRIPT diff --git a/Src/parse.c b/Src/parse.c index 628a9aa2d..349d1e427 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1413,7 +1413,7 @@ par_if(int *cmplx) } } cmdpop(); - if (xtok == ELSE) { + if (xtok == ELSE || tok == ELSE) { pp = ecadd(0); cmdpush(CS_ELSE); while (tok == SEPER) -- cgit v1.2.3 From 28c46c1bfb03fd7d1f563147435a4071b446f780 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 7 Mar 2016 10:49:35 +0000 Subject: 38111: Remove redundant return values in parsing. Return values from par_list() and par_list1() are no longer used. --- ChangeLog | 3 +++ Src/parse.c | 15 ++++----------- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 4db9df49b..420eb261d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2016-03-07 Peter Stephenson + * 38111: Src/parse.c: remove redundant return values from + par_list() and par_list1(). + * users/21352: Src/subst.c, Test/A03quoting.ztst: use nulstring to ensure $'' isn't elided. diff --git a/Src/parse.c b/Src/parse.c index 349d1e427..94ac04922 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -718,7 +718,7 @@ set_sublist_code(int p, int type, int flags, int skip, int cmplx) */ /**/ -static int +static void par_list(int *cmplx) { int p, lp = -1, c; @@ -747,19 +747,15 @@ par_list(int *cmplx) goto rec; } else set_list_code(p, (Z_SYNC | Z_END), c); - return 1; } else { ecused--; - if (lp >= 0) { + if (lp >= 0) ecbuf[lp] |= wc_bdata(Z_END); - return 1; - } - return 0; } } /**/ -static int +static void par_list1(int *cmplx) { int p = ecadd(0), c = 0; @@ -767,11 +763,8 @@ par_list1(int *cmplx) if (par_sublist(&c)) { set_list_code(p, (Z_SYNC | Z_END), c); *cmplx |= c; - return 1; - } else { + } else ecused--; - return 0; - } } /* -- 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/parse.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 00708285e94ce42a31fd59bbcd06d010a6d0d6ee Mon Sep 17 00:00:00 2001 From: Oliver Kiddle Date: Thu, 15 Sep 2016 23:56:06 +0200 Subject: unposted: remove duplicated assignment --- ChangeLog | 4 ++++ Src/parse.c | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 5ef7678a8..1c749ae64 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2016-09-15 Oliver Kiddle + + * unposted: Src/parse.c: remove duplicated assignment + 2016-09-14 Peter Stephenson * unposted: Doc/Zsh/expn.yo: small documentation tweaks. diff --git a/Src/parse.c b/Src/parse.c index 6e7d40e29..d3c418184 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -309,7 +309,6 @@ parse_context_restore(const struct parse_stack *ps, int toplevel) incond = ps->incond; inredir = ps->inredir; incasepat = ps->incasepat; - incasepat = ps->incasepat; isnewlin = ps->isnewlin; infor = ps->infor; inrepeat_ = ps->inrepeat_; -- 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/parse.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 From 88c42a2ba0f0baa9fd20bb7abddc2ad89b66a508 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 30 Oct 2016 17:12:04 +0000 Subject: 39777: $() is a valid empty command substitution --- ChangeLog | 5 +++++ Src/parse.c | 2 +- Test/D08cmdsubst.ztst | 14 ++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index c453aee84..e08cafd30 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2016-10-30 Peter Stephenson + + * 39777: Src/parse.c, Test/D08cmdsubst.ztst: $() is a valid + empty command substitution. + 2016-10-29 Barton E. Schaefer * 39758: Src/builtin.c, Src/params.c: revise 39704 to output diff --git a/Src/parse.c b/Src/parse.c index 24b8cd97f..50a0d5f9f 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -594,7 +594,7 @@ par_event(int endtok) if (tok == ENDINPUT) return 0; if (tok == endtok) - return 0; + return 1; p = ecadd(0); diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst index 89e725966..362537349 100644 --- a/Test/D08cmdsubst.ztst +++ b/Test/D08cmdsubst.ztst @@ -153,3 +153,17 @@ eval 'foo echo this just works, OK\?)' 0:backtracking within command string parsing with alias still pending >this just works, OK? + + ( + set errexit + show_nargs() { print $#; } + print a $() b + print c "$()" d + ) +0:Empty $() is a valid empty substitution. +>a b +>c d + + empty=$() && print "'$empty'" +0:Empty $() is a valid assignment +>'' -- cgit v1.2.3