From d19d9c1eff7dfe341c8412e310015919ef7729d7 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 26 Sep 2014 14:07:43 +0100 Subject: 33242: tokens following if, for, repeat, while aren't in command position --- Src/parse.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'Src/parse.c') diff --git a/Src/parse.c b/Src/parse.c index 5f1303f1c..3633417fe 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -997,17 +997,20 @@ par_for(int *complex) par_save_list(complex); if (tok != DONE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); par_save_list(complex); if (tok != OUTBRACE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (csh || isset(CSHJUNKIELOOPS)) { par_save_list(complex); if (tok != ZEND) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (unset(SHORTLOOPS)) { YYERRORV(oecused); @@ -1186,9 +1189,12 @@ par_if(int *complex) for (;;) { xtok = tok; cmdpush(xtok == IF ? CS_IF : CS_ELIF); - zshlex(); - if (xtok == FI) + if (xtok == FI) { + incmdpos = 0; + zshlex(); break; + } + zshlex(); if (xtok == ELSE) break; while (tok == SEPER) @@ -1229,6 +1235,7 @@ par_if(int *complex) YYERRORV(oecused); } ecbuf[pp] = WCB_IF(type, ecused - 1 - pp); + /* command word (else) allowed to follow immediately */ zshlex(); incmdpos = 1; if (tok == SEPER) @@ -1266,6 +1273,7 @@ par_if(int *complex) YYERRORV(oecused); } } + incmdpos = 0; ecbuf[pp] = WCB_IF(WC_IF_ELSE, ecused - 1 - pp); zshlex(); cmdpop(); @@ -1296,12 +1304,14 @@ par_while(int *complex) par_save_list(complex); if (tok != DONE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); par_save_list(complex); if (tok != OUTBRACE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { par_save_list(complex); @@ -1340,12 +1350,14 @@ par_repeat(int *complex) par_save_list(complex); if (tok != DONE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); par_save_list(complex); if (tok != OUTBRACE) YYERRORV(oecused); + incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { par_save_list(complex); -- cgit v1.2.3 From cf6b0f5663e798c8d4303697115230ac4469baca Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Mon, 29 Sep 2014 21:02:59 +0100 Subject: 33285: apply function definition redirections at execution --- ChangeLog | 6 ++++ NEWS | 7 +++++ Src/exec.c | 77 ++++++++++++++++++++++++++++++++++++++++++--- Src/hashtable.c | 15 +++++++-- Src/parse.c | 87 +++++++++++++++++++++++++++++++++++++++++++++------ Src/signals.c | 2 +- Src/zsh.h | 1 + Test/A04redirect.ztst | 38 +++++++++++++++++++++- 8 files changed, 216 insertions(+), 17 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index e9d167310..7fa84fb86 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-09-29 Peter Stephenson + + * 33285: NEWS, Src/exec.c, Src/hashtable.c, Src/parse.c, + Src/signals.c, Src/zsh.h, Test/A04redirect.ztst: redirections in + function definitions are applied at execution not definition. + 2014-09-29 Frank Terbeck * 33277: Functions/VCS_Info/VCS_INFO_reposub: Fix diff --git a/NEWS b/NEWS index 7dc134e68..bf8969b26 100644 --- a/NEWS +++ b/NEWS @@ -107,6 +107,13 @@ Changes since 5.0.0 Also, the value of $pipestatus is now updated when a job stops, not just when it exits. +- Redirections applied to function definitions take effect when the + function is executed, not when it is defined. Other shells already + work this way. For example, + fn() { echo hello } >~/logfile + Running fn writes "hello" to logfile. In older versions of the shell + it would create an empty file at the point of definition. + Changes between 4.2 and 5.0.0 ----------------------------- diff --git a/Src/exec.c b/Src/exec.c index fb2739acc..1c2a9044c 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -198,7 +198,8 @@ static char *blank_env[] = { NULL }; /* Execution functions. */ static int (*execfuncs[WC_COUNT-WC_CURSH]) _((Estate, int)) = { - execcursh, exectime, execfuncdef, execfor, execselect, + execcursh, exectime, NULL /* execfuncdef handled specially */, + execfor, execselect, execwhile, execrepeat, execcase, execif, execcond, execarith, execautofn, exectry }; @@ -1116,8 +1117,11 @@ execsimple(Estate state) fflush(xtrerr); } lv = (errflag ? errflag : cmdoutval); - } else + } else if (code == WC_FUNCDEF) { + lv = execfuncdef(state, NULL); + } else { lv = (execfuncs[code - WC_CURSH])(state, 0); + } thisjob = otj; @@ -2790,6 +2794,42 @@ execcmd(Estate state, int input, int output, int how, int last1) return; } + if (type == WC_FUNCDEF) { + /* + * The first word of a function definition is a list of + * names. If this is empty, we're doing an anonymous function: + * in that case redirections are handled normally. + * If not, it's a function definition: then we don't do + * redirections here but pass in the list of redirections to + * be stored for recall with the function. + */ + if (*state->pc != 0) { + /* Nonymous, don't do redirections here */ + redir = NULL; + } + } else if (is_shfunc) { + Shfunc shf = (Shfunc)hn; + /* + * A function definition may have a list of additional + * redirections to apply, so retrieve it. + */ + if (shf->redir) { + struct estate s; + LinkList redir2; + + s.prog = shf->redir; + s.pc = shf->redir->prog; + s.strs = shf->redir->strs; + redir2 = ecgetredirs(&s); + if (!redir) + redir = redir2; + else { + while (nonempty(redir2)) + addlinknode(redir, ugetnode(redir2)); + } + } + } + if (type == WC_SIMPLE && !nullexec) { char *s; char trycd = (isset(AUTOCD) && isset(SHINSTDIN) && @@ -3238,7 +3278,33 @@ execcmd(Estate state, int input, int output, int how, int last1) flags |= ESUB_REVERTPGRP; entersubsh(flags); } - if (type >= WC_CURSH) { + if (type == WC_FUNCDEF) { + Eprog redir_prog; + if (!redir && wc_code(*beg) == WC_REDIR) { + /* + * We're not using a redirection from the currently + * parsed environment, which is what we'd do for an + * anonymous function, but there are redirections we + * should store with the new function. + */ + struct estate s; + + s.prog = state->prog; + s.pc = beg; + s.strs = state->prog->strs; + + /* + * The copy uses the wordcode parsing area, so save and + * restore state. + */ + lexsave(); + redir_prog = eccopyredirs(&s); + lexrestore(); + } else + redir_prog = NULL; + + lastval = execfuncdef(state, redir_prog); + } else if (type >= WC_CURSH) { if (last1 == 1) do_exec = 1; lastval = (execfuncs[type - WC_CURSH])(state, do_exec); @@ -4235,7 +4301,7 @@ exectime(Estate state, UNUSED(int do_exec)) /**/ static int -execfuncdef(Estate state, UNUSED(int do_exec)) +execfuncdef(Estate state, Eprog redir_prog) { Shfunc shf; char *s = NULL; @@ -4305,6 +4371,7 @@ execfuncdef(Estate state, UNUSED(int do_exec)) shf->node.flags = 0; shf->filename = ztrdup(scriptfilename); shf->lineno = lineno; + shf->redir = redir_prog; shfunc_set_sticky(shf); if (!names) { @@ -4335,6 +4402,8 @@ execfuncdef(Estate state, UNUSED(int do_exec)) ret = lastval; freeeprog(shf->funcdef); + if (shf->redir) /* shouldn't be */ + freeeprog(shf->redir); zsfree(shf->filename); zfree(shf, sizeof(*shf)); break; diff --git a/Src/hashtable.c b/Src/hashtable.c index ef187927b..7a430629d 100644 --- a/Src/hashtable.c +++ b/Src/hashtable.c @@ -887,6 +887,8 @@ freeshfuncnode(HashNode hn) zsfree(shf->node.nam); if (shf->funcdef) freeeprog(shf->funcdef); + if (shf->redir) + freeeprog(shf->redir); zsfree(shf->filename); if (shf->sticky) { if (shf->sticky->n_on_opts) @@ -954,10 +956,19 @@ printshfuncnode(HashNode hn, int printflags) printf(" \"$@\""); } } - printf("\n}\n"); + printf("\n}"); } else { - printf(" () { }\n"); + printf(" () { }"); } + if (f->redir) { + t = getpermtext(f->redir, NULL, 1); + if (t) { + zputs(t, stdout); + zsfree(t); + } + } + + putchar('\n'); } /**************************************/ diff --git a/Src/parse.c b/Src/parse.c index 3633417fe..6cba05082 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -375,6 +375,8 @@ init_parse(void) /* Build eprog. */ +/* careful: copy_ecstr is from arg1 to arg2, unlike memcpy */ + static void copy_ecstr(Eccstr s, char *p) { @@ -386,24 +388,25 @@ copy_ecstr(Eccstr s, char *p) } static Eprog -bld_eprog(void) +bld_eprog(int heap) { Eprog ret; int l; ecadd(WCB_END()); - ret = (Eprog) zhalloc(sizeof(*ret)); + ret = heap ? (Eprog) zhalloc(sizeof(*ret)) : (Eprog) zalloc(sizeof(*ret)); ret->len = ((ecnpats * sizeof(Patprog)) + (ecused * sizeof(wordcode)) + ecsoffs); ret->npats = ecnpats; - ret->nref = -1; /* Eprog is on the heap */ - ret->pats = (Patprog *) zhalloc(ret->len); + ret->nref = heap ? -1 : 1; + ret->pats = heap ? (Patprog *) zhalloc(ret->len) : + (Patprog *) zshcalloc(ret->len); ret->prog = (Wordcode) (ret->pats + ecnpats); ret->strs = (char *) (ret->prog + ecused); ret->shf = NULL; - ret->flags = EF_HEAP; + ret->flags = heap ? EF_HEAP : EF_REAL; ret->dump = NULL; for (l = 0; l < ecnpats; l++) ret->pats[l] = dummy_patprog1; @@ -455,7 +458,7 @@ parse_event(void) clear_hdocs(); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /**/ @@ -534,7 +537,7 @@ parse_list(void) yyerror(0); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /* @@ -553,7 +556,7 @@ parse_cond(void) clear_hdocs(); return NULL; } - return bld_eprog(); + return bld_eprog(1); } /* This adds a list wordcode. The important bit about this is that it also @@ -2554,6 +2557,73 @@ ecgetredirs(Estate s) return ret; } +/* + * Copy the consecutive set of redirections in the state at s. + * Return NULL if none, else an Eprog consisting only of the + * redirections from permanently allocated memory. + * + * s is left in the state ready for whatever follows the redirections. + */ + +/**/ +Eprog +eccopyredirs(Estate s) +{ + Wordcode pc = s->pc; + wordcode code = *pc; + int ncode, ncodes = 0, r, type; + + if (wc_code(code) != WC_REDIR) + return NULL; + + init_parse(); + + while (wc_code(code) == WC_REDIR) { + type = WC_REDIR_TYPE(code); + + DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH, + "unexpanded here document"); + + if (WC_REDIR_FROM_HEREDOC(code)) + ncode = 5; + else + ncode = 3; + if (WC_REDIR_VARID(code)) + ncode++; + pc += ncode; + ncodes += ncode; + code = *pc; + } + r = ecused; + ecispace(r, ncodes); + + code = *s->pc; + while (wc_code(code) == WC_REDIR) { + s->pc++; + + ecbuf[r++] = code; + /* fd1 */ + ecbuf[r++] = *s->pc++; + /* name or HERE string */ + /* No DUP needed as we'll copy into Eprog immediately below */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + if (WC_REDIR_FROM_HEREDOC(code)) + { + /* terminator, raw */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + /* terminator, munged */ + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + } + if (WC_REDIR_VARID(code)) + ecbuf[r++] = ecstrcode(ecgetstr(s, EC_NODUP, NULL)); + + code = *s->pc; + } + + /* bld_eprog() appends a useful WC_END marker */ + return bld_eprog(0); +} + /**/ mod_export struct eprog dummy_eprog; @@ -3546,4 +3616,3 @@ dump_autoload(char *nam, char *file, int on, Options ops, int func) } return ret; } - diff --git a/Src/signals.c b/Src/signals.c index cb2b58161..74a39e5fb 100644 --- a/Src/signals.c +++ b/Src/signals.c @@ -752,7 +752,7 @@ dosavetrap(int sig, int level) Shfunc shf, newshf = NULL; if ((shf = (Shfunc)gettrapnode(sig, 1))) { /* Copy the node for saving */ - newshf = (Shfunc) zalloc(sizeof(*newshf)); + newshf = (Shfunc) zshcalloc(sizeof(*newshf)); newshf->node.nam = ztrdup(shf->node.nam); newshf->node.flags = shf->node.flags; newshf->funcdef = dupeprog(shf->funcdef, 0); diff --git a/Src/zsh.h b/Src/zsh.h index 8f56fa265..d284c7aa7 100644 --- a/Src/zsh.h +++ b/Src/zsh.h @@ -1139,6 +1139,7 @@ struct shfunc { char *filename; /* Name of file located in */ zlong lineno; /* line number in above file */ Eprog funcdef; /* function definition */ + Eprog redir; /* redirections to apply */ Emulation_options sticky; /* sticky emulation definitions, if any */ }; diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst index 7ad02db3b..436ae59cd 100644 --- a/Test/A04redirect.ztst +++ b/Test/A04redirect.ztst @@ -54,7 +54,7 @@ 0:Here-documents stripping tabs >barbar - cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" + cat <<-$'$HERE '`$(THERE) `'$((AND)) '"\EVERYWHERE" # # tabs again. sorry about the max miller. Here's a funny thing. Here is a funny thing. I went home last night. There's a funny thing. @@ -455,3 +455,39 @@ [input1 + () { + local var + read var + print I just read $var + } output1 + print Nothing output yet + cat output1 +0:anonymous function redirections are applied immediately +>Nothing output yet +>I just read any old rubbish + + redirfn() { + local var + read var + print I want to tell you about $var + print Also, this might be an error >&2 + } output2 2>&1 + print something I heard on the radio >input2 + redirfn + print No output until after this + cat output2 +0:redirections with normal function definition +>No output until after this +>I want to tell you about something I heard on the radio +>Also, this might be an error + + which redirfn +0:text output of function with redirections +>redirfn () { +> local var +> read var +> print I want to tell you about $var +> print Also, this might be an error >&2 +>} < input2 > output2 2>&1 -- cgit v1.2.3 From 7666ceb2bcd3e38d4b2f9f7202c4a9e0021b8e8c Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Oct 2014 14:17:33 +0100 Subject: 33343: Variant anonymous function synax with arguments. Don't expand arguments as if in command position. Test. --- Src/parse.c | 31 ++++++++++++++++++++++++------- Test/C04funcdef.ztst | 6 ++++++ 2 files changed, 30 insertions(+), 7 deletions(-) (limited to 'Src/parse.c') diff --git a/Src/parse.c b/Src/parse.c index 6cba05082..860bb4b1d 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -729,7 +729,7 @@ par_pline(int *complex) p = ecadd(0); - if (!par_cmd(complex)) { + if (!par_cmd(complex, 0)) { ecused--; return 0; } @@ -780,11 +780,15 @@ par_pline(int *complex) /* * cmd : { redir } ( for | case | if | while | repeat | * subsh | funcdef | time | dinbrack | dinpar | simple ) { redir } + * + * With zsh_construct non-zero, we're doing a zsh special in which + * the following token is not considered in command position. This + * is used for arguments of anonymous functions. */ /**/ static int -par_cmd(int *complex) +par_cmd(int *complex, int zsh_construct) { int r, nr = 0; @@ -839,12 +843,12 @@ par_cmd(int *complex) case INPAR: *complex = 1; cmdpush(CS_SUBSH); - par_subsh(complex); + par_subsh(complex, zsh_construct); cmdpop(); break; case INBRACE: cmdpush(CS_CURSH); - par_subsh(complex); + par_subsh(complex, zsh_construct); cmdpop(); break; case FUNC: @@ -1378,11 +1382,13 @@ par_repeat(int *complex) /* * subsh : INPAR list OUTPAR | * INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ] + * + * zsh_construct is passed through to par_cmd(), q.v. */ /**/ static void -par_subsh(int *complex) +par_subsh(int *complex, int zsh_construct) { enum lextok otok = tok; int oecused = ecused, p, pp; @@ -1395,7 +1401,7 @@ par_subsh(int *complex) ecadd(WCB_END()); if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE)) YYERRORV(oecused); - incmdpos = 1; + incmdpos = !zsh_construct; zshlex(); /* Optional always block. No intervening SEPERs allowed. */ @@ -1760,10 +1766,21 @@ par_simple(int *complex, int nr) sl = ecadd(0); (void)ecadd(WCB_PIPE(WC_PIPE_END, 0)); - if (!par_cmd(&c)) { + if (!par_cmd(&c, argc == 0)) { cmdpop(); YYERROR(oecused); } + if (argc == 0) { + /* + * Anonymous function, possibly with arguments. + * N.B. for complex structures in particular + * ( ... ) we rely on lower level code doing this + * to get the immediately following word (the + * first token after the ")" has already been + * read). + */ + incmdpos = 0; + } set_sublist_code(sl, WC_SUBLIST_END, 0, ecused - 1 - sl, c); set_list_code(ll, (Z_SYNC | Z_END), c); diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index a2660315f..193757090 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -272,6 +272,12 @@ >ignorebraces is off >ignorebraces is still on here +# lsfoo should not be expanded as an anonymous function argument + alias lsfoo='This is not ls.' + () (echo anon func; echo "$@") lsfoo +0:Anonmous function with arguments in a form nobody sane would ever use but unfortunately we have to support anyway +>anon func +>lsfoo %clean -- cgit v1.2.3 From a778215b7c866c50830d4e1f750848239d009683 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Oct 2014 14:20:24 +0100 Subject: unposted: comments in previous commit were reversed --- ChangeLog | 7 +++++++ Src/parse.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index eae67dc16..7c658e196 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2014-10-03 Peter Stephenson + + * unposted: src/parse.c: comments were the wrong way round. + + * 33343: Src/parse.c, Test/C04funcdef.ztst: variant anonymous + function syntax with arguments. + 2014-10-02 Peter Stephenson * unposted: 5.0.6-dev-1. diff --git a/Src/parse.c b/Src/parse.c index 860bb4b1d..ad1ba8957 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -781,9 +781,7 @@ par_pline(int *complex) * cmd : { redir } ( for | case | if | while | repeat | * subsh | funcdef | time | dinbrack | dinpar | simple ) { redir } * - * With zsh_construct non-zero, we're doing a zsh special in which - * the following token is not considered in command position. This - * is used for arguments of anonymous functions. + * zsh_construct is passed through to par_subsh(), q.v. */ /**/ @@ -1383,7 +1381,9 @@ par_repeat(int *complex) * subsh : INPAR list OUTPAR | * INBRACE list OUTBRACE [ "always" INBRACE list OUTBRACE ] * - * zsh_construct is passed through to par_cmd(), q.v. + * With zsh_construct non-zero, we're doing a zsh special in which + * the following token is not considered in command position. This + * is used for arguments of anonymous functions. */ /**/ -- cgit v1.2.3 From 31750795fe13fc0343ade4f2aadb55f20548f628 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 3 Oct 2014 16:29:56 +0100 Subject: 33345: fix anonymous function complex command handling. Longstanding problem caused simple anonymous function incorrectly to reset the overall "complext" state, causing wordcode to be diverted into execsimple(), which caused a crash 'cos ist wasn't simple. --- ChangeLog | 4 ++ Src/parse.c | 167 ++++++++++++++++++++++++++------------------------- Test/C04funcdef.ztst | 4 ++ 3 files changed, 92 insertions(+), 83 deletions(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 7c658e196..3e273d1ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2014-10-03 Peter Stephenson + * 33345: Src/parse.c, Test/C04funcdef.ztst: fix longstanding + anonoymous function corruption of "complex" state that allowed + complex wordcode to be passed to execsimple(), causing crash. + * unposted: src/parse.c: comments were the wrong way round. * 33343: Src/parse.c, Test/C04funcdef.ztst: variant anonymous diff --git a/Src/parse.c b/Src/parse.c index ad1ba8957..f4ea639d6 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -202,7 +202,7 @@ struct heredocs *hdocs; * sublists is that they can be executed faster, see exec.c. In the * parser, the test if a list can be simplified is done quite simply * by passing a int* around which gets set to non-zero if the thing - * just parsed is `complex', i.e. may need to be run by forking or + * just parsed is `cmplx', i.e. may need to be run by forking or * some such. * * In each of the above, strings are encoded as one word code. For empty @@ -564,9 +564,9 @@ parse_cond(void) /**/ static void -set_list_code(int p, int type, int complex) +set_list_code(int p, int type, int cmplx) { - if (!complex && (type == Z_SYNC || type == (Z_SYNC | Z_END)) && + if (!cmplx && (type == Z_SYNC || type == (Z_SYNC | Z_END)) && WC_SUBLIST_TYPE(ecbuf[p + 1]) == WC_SUBLIST_END) { int ispipe = !(WC_SUBLIST_FLAGS(ecbuf[p + 1]) & WC_SUBLIST_SIMPLE); ecbuf[p] = WCB_LIST((type | Z_SIMPLE), ecused - 2 - p); @@ -581,9 +581,9 @@ set_list_code(int p, int type, int complex) /**/ static void -set_sublist_code(int p, int type, int flags, int skip, int complex) +set_sublist_code(int p, int type, int flags, int skip, int cmplx) { - if (complex) + if (cmplx) ecbuf[p] = WCB_SUBLIST(type, flags, skip); else { ecbuf[p] = WCB_SUBLIST(type, (flags | WC_SUBLIST_SIMPLE), skip); @@ -597,7 +597,7 @@ set_sublist_code(int p, int type, int flags, int skip, int complex) /**/ static int -par_list(int *complex) +par_list(int *cmplx) { int p, lp = -1, c; @@ -610,10 +610,10 @@ par_list(int *complex) c = 0; if (par_sublist(&c)) { - *complex |= c; + *cmplx |= c; if (tok == SEPER || tok == AMPER || tok == AMPERBANG) { if (tok != SEPER) - *complex = 1; + *cmplx = 1; set_list_code(p, ((tok == SEPER) ? Z_SYNC : (tok == AMPER) ? Z_ASYNC : (Z_ASYNC | Z_DISOWN)), c); @@ -638,13 +638,13 @@ par_list(int *complex) /**/ static int -par_list1(int *complex) +par_list1(int *cmplx) { int p = ecadd(0), c = 0; if (par_sublist(&c)) { set_list_code(p, (Z_SYNC | Z_END), c); - *complex |= c; + *cmplx |= c; return 1; } else { ecused--; @@ -658,7 +658,7 @@ par_list1(int *complex) /**/ static int -par_sublist(int *complex) +par_sublist(int *cmplx) { int f, p, c = 0; @@ -667,7 +667,7 @@ par_sublist(int *complex) if ((f = par_sublist2(&c)) != -1) { int e = ecused; - *complex |= c; + *cmplx |= c; if (tok == DBAR || tok == DAMPER) { enum lextok qtok = tok; int sl; @@ -676,7 +676,7 @@ par_sublist(int *complex) zshlex(); while (tok == SEPER) zshlex(); - sl = par_sublist(complex); + sl = par_sublist(cmplx); set_sublist_code(p, (sl ? (qtok == DBAR ? WC_SUBLIST_OR : WC_SUBLIST_AND) : WC_SUBLIST_END), @@ -697,20 +697,20 @@ par_sublist(int *complex) /**/ static int -par_sublist2(int *complex) +par_sublist2(int *cmplx) { int f = 0; if (tok == COPROC) { - *complex = 1; + *cmplx = 1; f |= WC_SUBLIST_COPROC; zshlex(); } else if (tok == BANG) { - *complex = 1; + *cmplx = 1; f |= WC_SUBLIST_NOT; zshlex(); } - if (!par_pline(complex) && !f) + if (!par_pline(cmplx) && !f) return -1; return f; @@ -722,19 +722,19 @@ par_sublist2(int *complex) /**/ static int -par_pline(int *complex) +par_pline(int *cmplx) { int p; zlong line = toklineno; p = ecadd(0); - if (!par_cmd(complex, 0)) { + if (!par_cmd(cmplx, 0)) { ecused--; return 0; } if (tok == BAR) { - *complex = 1; + *cmplx = 1; cmdpush(CS_PIPE); zshlex(); while (tok == SEPER) @@ -742,7 +742,7 @@ par_pline(int *complex) ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0)); ecispace(p + 1, 1); ecbuf[p + 1] = ecused - 1 - p; - if (!par_pline(complex)) { + if (!par_pline(cmplx)) { tok = LEXERR; } cmdpop(); @@ -758,7 +758,7 @@ par_pline(int *complex) ecbuf[r + 1] = 2; ecbuf[r + 2] = ecstrcode("1"); - *complex = 1; + *cmplx = 1; cmdpush(CS_ERRPIPE); zshlex(); while (tok == SEPER) @@ -766,7 +766,7 @@ par_pline(int *complex) ecbuf[p] = WCB_PIPE(WC_PIPE_MID, (line >= 0 ? line + 1 : 0)); ecispace(p + 1, 1); ecbuf[p + 1] = ecused - 1 - p; - if (!par_pline(complex)) { + if (!par_pline(cmplx)) { tok = LEXERR; } cmdpop(); @@ -786,14 +786,14 @@ par_pline(int *complex) /**/ static int -par_cmd(int *complex, int zsh_construct) +par_cmd(int *cmplx, int zsh_construct) { int r, nr = 0; r = ecused; if (IS_REDIROP(tok)) { - *complex = 1; + *cmplx = 1; while (IS_REDIROP(tok)) { nr += par_redir(&r, NULL); } @@ -801,57 +801,57 @@ par_cmd(int *complex, int zsh_construct) switch (tok) { case FOR: cmdpush(CS_FOR); - par_for(complex); + par_for(cmplx); cmdpop(); break; case FOREACH: cmdpush(CS_FOREACH); - par_for(complex); + par_for(cmplx); cmdpop(); break; case SELECT: - *complex = 1; + *cmplx = 1; cmdpush(CS_SELECT); - par_for(complex); + par_for(cmplx); cmdpop(); break; case CASE: cmdpush(CS_CASE); - par_case(complex); + par_case(cmplx); cmdpop(); break; case IF: - par_if(complex); + par_if(cmplx); break; case WHILE: cmdpush(CS_WHILE); - par_while(complex); + par_while(cmplx); cmdpop(); break; case UNTIL: cmdpush(CS_UNTIL); - par_while(complex); + par_while(cmplx); cmdpop(); break; case REPEAT: cmdpush(CS_REPEAT); - par_repeat(complex); + par_repeat(cmplx); cmdpop(); break; case INPAR: - *complex = 1; + *cmplx = 1; cmdpush(CS_SUBSH); - par_subsh(complex, zsh_construct); + par_subsh(cmplx, zsh_construct); cmdpop(); break; case INBRACE: cmdpush(CS_CURSH); - par_subsh(complex, zsh_construct); + par_subsh(cmplx, zsh_construct); cmdpop(); break; case FUNC: cmdpush(CS_FUNCDEF); - par_funcdef(complex); + par_funcdef(cmplx); cmdpop(); break; case DINBRACK: @@ -869,7 +869,7 @@ par_cmd(int *complex, int zsh_construct) static int inpartime = 0; if (!inpartime) { - *complex = 1; + *cmplx = 1; inpartime = 1; par_time(); inpartime = 0; @@ -882,13 +882,13 @@ par_cmd(int *complex, int zsh_construct) { int sr; - if (!(sr = par_simple(complex, nr))) { + if (!(sr = par_simple(cmplx, nr))) { if (!nr) return 0; } else { /* Take account of redirections */ if (sr > 1) { - *complex = 1; + *cmplx = 1; r += sr - 1; } } @@ -896,7 +896,7 @@ par_cmd(int *complex, int zsh_construct) break; } if (IS_REDIROP(tok)) { - *complex = 1; + *cmplx = 1; while (IS_REDIROP(tok)) (void)par_redir(&r, NULL); } @@ -914,7 +914,7 @@ par_cmd(int *complex, int zsh_construct) /**/ static void -par_for(int *complex) +par_for(int *cmplx) { int oecused = ecused, csh = (tok == FOREACH), p, sel = (tok == SELECT); int type; @@ -999,20 +999,20 @@ par_for(int *complex) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (csh || isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); incmdpos = 0; @@ -1020,7 +1020,7 @@ par_for(int *complex) } else if (unset(SHORTLOOPS)) { YYERRORV(oecused); } else - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[p] = (sel ? WCB_SELECT(type, ecused - 1 - p) : @@ -1036,7 +1036,7 @@ par_for(int *complex) /**/ static void -par_case(int *complex) +par_case(int *cmplx) { int oecused = ecused, brflag, p, pp, n = 1, type; int ona, onc; @@ -1153,7 +1153,7 @@ par_case(int *complex) pp = ecadd(0); ecstr(str); ecadd(ecnpats++); - par_save_list(complex); + par_save_list(cmplx); n++; if (tok == SEMIAMP) type = WC_CASE_AND; @@ -1183,7 +1183,7 @@ par_case(int *complex) /**/ static void -par_if(int *complex) +par_if(int *cmplx) { int oecused = ecused, p, pp, type, usebrace = 0; enum lextok xtok; @@ -1210,7 +1210,7 @@ par_if(int *complex) } pp = ecadd(0); type = (xtok == IF ? WC_IF_IF : WC_IF_ELIF); - par_save_list(complex); + par_save_list(cmplx); incmdpos = 1; if (tok == ENDINPUT) { cmdpop(); @@ -1225,7 +1225,7 @@ par_if(int *complex) cmdpop(); cmdpush(nc); zshlex(); - par_save_list(complex); + par_save_list(cmplx); ecbuf[pp] = WCB_IF(type, ecused - 1 - pp); incmdpos = 1; cmdpop(); @@ -1234,7 +1234,7 @@ par_if(int *complex) cmdpop(); cmdpush(nc); zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) { cmdpop(); YYERRORV(oecused); @@ -1252,7 +1252,7 @@ par_if(int *complex) } else { cmdpop(); cmdpush(nc); - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[pp] = WCB_IF(type, ecused - 1 - pp); incmdpos = 1; break; @@ -1266,13 +1266,13 @@ par_if(int *complex) zshlex(); if (tok == INBRACE && usebrace) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) { cmdpop(); YYERRORV(oecused); } } else { - par_save_list(complex); + par_save_list(cmplx); if (tok != FI) { cmdpop(); YYERRORV(oecused); @@ -1293,33 +1293,33 @@ par_if(int *complex) /**/ static void -par_while(int *complex) +par_while(int *cmplx) { int oecused = ecused, p; int type = (tok == UNTIL ? WC_WHILE_UNTIL : WC_WHILE_WHILE); p = ecadd(0); zshlex(); - par_save_list(complex); + par_save_list(cmplx); incmdpos = 1; while (tok == SEPER) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); zshlex(); @@ -1335,7 +1335,7 @@ par_while(int *complex) /**/ static void -par_repeat(int *complex) +par_repeat(int *cmplx) { int oecused = ecused, p; @@ -1352,27 +1352,27 @@ par_repeat(int *complex) zshlex(); if (tok == DOLOOP) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != DONE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (tok == INBRACE) { zshlex(); - par_save_list(complex); + par_save_list(cmplx); if (tok != OUTBRACE) YYERRORV(oecused); incmdpos = 0; zshlex(); } else if (isset(CSHJUNKIELOOPS)) { - par_save_list(complex); + par_save_list(cmplx); if (tok != ZEND) YYERRORV(oecused); zshlex(); } else if (unset(SHORTLOOPS)) { YYERRORV(oecused); } else - par_save_list1(complex); + par_save_list1(cmplx); ecbuf[p] = WCB_REPEAT(ecused - 1 - p); } @@ -1388,7 +1388,7 @@ par_repeat(int *complex) /**/ static void -par_subsh(int *complex, int zsh_construct) +par_subsh(int *cmplx, int zsh_construct) { enum lextok otok = tok; int oecused = ecused, p, pp; @@ -1397,7 +1397,7 @@ par_subsh(int *complex, int zsh_construct) /* Extra word only needed for always block */ pp = ecadd(0); zshlex(); - par_list(complex); + par_list(cmplx); ecadd(WCB_END()); if (tok != ((otok == INPAR) ? OUTPAR : OUTBRACE)) YYERRORV(oecused); @@ -1418,7 +1418,7 @@ par_subsh(int *complex, int zsh_construct) cmdpush(CS_ALWAYS); zshlex(); - par_save_list(complex); + par_save_list(cmplx); while (tok == SEPER) zshlex(); @@ -1441,7 +1441,7 @@ par_subsh(int *complex, int zsh_construct) /**/ static void -par_funcdef(int *complex) +par_funcdef(int *cmplx) { int oecused = ecused, num = 0, onp, p, c = 0; int so, oecssub = ecssub; @@ -1523,7 +1523,7 @@ par_funcdef(int *complex) num++; zshlex(); } - *complex = (num > 0); + *cmplx = (num > 0); ecbuf[parg] = ecused - parg; /*?*/ ecbuf[parg+1] = num; } @@ -1585,15 +1585,15 @@ par_dinbrack(void) /**/ static int -par_simple(int *complex, int nr) +par_simple(int *cmplx, int nr) { int oecused = ecused, isnull = 1, r, argc = 0, p, isfunc = 0, sr = 0; - int c = *complex, nrediradd, assignments = 0; + int c = *cmplx, nrediradd, assignments = 0; r = ecused; for (;;) { if (tok == NOCORRECT) { - *complex = c = 1; + *cmplx = c = 1; nocorrect = 1; } else if (tok == ENVSTRING) { char *p, *name, *str; @@ -1621,7 +1621,7 @@ par_simple(int *complex, int nr) */ if (p[1] == Inpar && (*p == Equals || *p == Inang || *p == OutangProc)) { - *complex = 1; + *cmplx = 1; break; } } @@ -1633,10 +1633,10 @@ par_simple(int *complex, int nr) int oldcmdpos = incmdpos, n, type2; /* - * We consider array setting complex because it can + * We consider array setting cmplx because it can * contain process substitutions, which need a valid job. */ - *complex = c = 1; + *cmplx = c = 1; p = ecadd(0); incmdpos = 0; if ((type2 = strlen(tokstr) - 1) && tokstr[type2] == '+') { @@ -1668,7 +1668,7 @@ par_simple(int *complex, int nr) if (tok == STRING) { int redir_var = 0; - *complex = 1; + *cmplx = 1; incmdpos = 0; if (!isset(IGNOREBRACES) && *tokstr == Inbrace) @@ -1687,7 +1687,7 @@ par_simple(int *complex, int nr) if (IS_REDIROP(tok) && tokfd == -1) { - *complex = c = 1; + *cmplx = c = 1; nrediradd = par_redir(&r, idstring); p += nrediradd; sr += nrediradd; @@ -1708,7 +1708,7 @@ par_simple(int *complex, int nr) zshlex(); } } else if (IS_REDIROP(tok)) { - *complex = c = 1; + *cmplx = c = 1; nrediradd = par_redir(&r, NULL); p += nrediradd; sr += nrediradd; @@ -1723,7 +1723,7 @@ par_simple(int *complex, int nr) if (assignments) YYERROR(oecused); - *complex = c; + *cmplx = c; lineno = 0; incmdpos = 1; cmdpush(CS_FUNCDEF); @@ -1773,7 +1773,7 @@ par_simple(int *complex, int nr) if (argc == 0) { /* * Anonymous function, possibly with arguments. - * N.B. for complex structures in particular + * N.B. for cmplx structures in particular * ( ... ) we rely on lower level code doing this * to get the immediately following word (the * first token after the ")" has already been @@ -1807,7 +1807,8 @@ par_simple(int *complex, int nr) argc++; zshlex(); } - *complex = (argc > 0); + if (argc > 0) + *cmplx = 1; ecbuf[parg] = ecused - parg; /*?*/ ecbuf[parg+1] = argc; } diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst index 193757090..10491a229 100644 --- a/Test/C04funcdef.ztst +++ b/Test/C04funcdef.ztst @@ -279,6 +279,10 @@ >anon func >lsfoo + print foo | () cat +0:Simple anonymous function should not simplify enclosing pipeline +>foo + %clean rm -f file.in file.out -- cgit v1.2.3 From 74e26bf1262c921c691ee0451ced99aa4eb8aefa Mon Sep 17 00:00:00 2001 From: Bart Schaefer Date: Fri, 3 Oct 2014 08:50:25 -0700 Subject: 33346: another bit of the 33345 repair --- ChangeLog | 4 ++++ Src/parse.c | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'Src/parse.c') diff --git a/ChangeLog b/ChangeLog index 3e273d1ec..5e5f3f268 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2014-10-03 Bart Schaefer + + * 33346: Src/parse.c: another bit of the 33345 repair + 2014-10-03 Peter Stephenson * 33345: Src/parse.c, Test/C04funcdef.ztst: fix longstanding diff --git a/Src/parse.c b/Src/parse.c index f4ea639d6..433efb94e 100644 --- a/Src/parse.c +++ b/Src/parse.c @@ -1523,7 +1523,8 @@ par_funcdef(int *cmplx) num++; zshlex(); } - *cmplx = (num > 0); + if (num > 0) + *cmplx = 1; ecbuf[parg] = ecused - parg; /*?*/ ecbuf[parg+1] = num; } -- cgit v1.2.3