diff --git a/NEWS b/NEWS index 9c28169bb..cdafd1ff5 100644 --- a/NEWS +++ b/NEWS @@ -4,15 +4,6 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH Note also the list of incompatibilities in the README file. -Changes since 5.9 ------------------ - -Handling of ERR_EXIT is corrected when the final status of a structured -command (for, select, while, repeat, if, case, or a list in braces) is -nonzero. To be compatible with other shells, "zsh -e" now exits in -those circumstances, whereas previous versions did not. This does not -affect the handling of nonzero status within conditional statements. - Changes since 5.8.1 ------------------- diff --git a/Src/exec.c b/Src/exec.c index ce0c1f1ad..b9061e3a4 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -49,7 +49,8 @@ struct funcsave { int zoptind, lastval, optcind, numpipestats; int *pipestats; char *scriptname; - int breaks, contflag, loops, emulation, noerrexit, oflags, restore_sticky; + int breaks, contflag, loops, emulation, noerrexit, this_noerrexit, oflags; + int restore_sticky; Emulation_options sticky; struct funcstack fstack; }; @@ -451,7 +452,7 @@ execcursh(Estate state, int do_exec) cmdpop(); state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -1442,8 +1443,6 @@ execlist(Estate state, int dont_change_job, int exiting) execsimple(state); else execpline(state, code, ltype, (ltype & Z_END) && exiting); - if (!locallevel || unset(ERRRETURN)) - this_noerrexit = noerrexit; state->pc = next; goto sublist_done; break; @@ -5763,6 +5762,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) funcsave->pipestats = NULL; funcsave->numpipestats = numpipestats; funcsave->noerrexit = noerrexit; + funcsave->this_noerrexit = this_noerrexit; if (trap_state == TRAP_STATE_PRIMED) trap_return--; /* @@ -6009,6 +6009,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) trap_return++; ret = lastval; noerrexit = funcsave->noerrexit; + this_noerrexit = funcsave->this_noerrexit; if (noreturnval) { lastval = funcsave->lastval; numpipestats = funcsave->numpipestats; diff --git a/Src/loop.c b/Src/loop.c index be5261369..7c3e04b8a 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -208,7 +208,7 @@ execfor(Estate state, int do_exec) loops--; simple_pline = old_simple_pline; state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -336,7 +336,7 @@ execselect(Estate state, UNUSED(int do_exec)) loops--; simple_pline = old_simple_pline; state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -478,7 +478,7 @@ execwhile(Estate state, UNUSED(int do_exec)) popheap(); loops--; state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -532,7 +532,7 @@ execrepeat(Estate state, UNUSED(int do_exec)) loops--; simple_pline = old_simple_pline; state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -587,7 +587,7 @@ execif(Estate state, int do_exec) lastval = 0; } state->pc = end; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -701,7 +701,7 @@ execcase(Estate state, int do_exec) if (!anypatok) lastval = 0; - this_noerrexit = (WC_SUBLIST_TYPE(*end) != WC_SUBLIST_END); + this_noerrexit = 1; return lastval; } @@ -793,6 +793,7 @@ exectry(Estate state, int do_exec) cmdpop(); popheap(); state->pc = end; + this_noerrexit = 1; return endval; } diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst index 5cc45e2de..01d8fa25b 100644 --- a/Test/C03traps.ztst +++ b/Test/C03traps.ztst @@ -721,21 +721,40 @@ F:Must be tested with a top-level script rather than source or function >Good (setopt err_exit - for x in y; do + false && true + print OK + ) +0:ERR_EXIT not triggered by "false && true" +>OK + + (setopt err_exit + fn() { false && true - done + } + fn print OK ) -1:ERR_EXIT triggered by status 1 at end of for +1:ERR_EXIT not triggered by "false && true" but by return from fn (setopt err_exit - integer x=0 - while (( ! x++ )); do + for x in y; do false && true done print OK ) -1:ERR_EXIT triggered by status 1 at end of while +0:ERR_EXIT not triggered by status 1 at end of for +>OK + + (setopt err_exit + fn() { + for x in y; do + false && true + done + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of for but by return from fn (setopt err_exit repeat 1; do @@ -743,7 +762,19 @@ F:Must be tested with a top-level script rather than source or function done print OK ) -1:ERR_EXIT triggered by status 1 at end of repeat +0:ERR_EXIT not triggered by status 1 at end of repeat +>OK + + (setopt err_exit + fn() { + repeat 1; do + false && true + done + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of repeat but by return from fn (setopt err_exit if true; then @@ -751,15 +782,93 @@ F:Must be tested with a top-level script rather than source or function fi print OK ) -1:ERR_EXIT triggered by status 1 at end of if +0:ERR_EXIT not triggered by status 1 at end of if +>OK + + (setopt err_exit + fn() { + if true; then + false && true + fi + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of if but by return from fn + + (setopt err_exit + loop=true + while print COND; $loop; do + loop=false + false && true + done + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of while +>COND +>COND +>OK + + (setopt err_exit + fn() { + loop=true + while print COND; $loop; do + loop=false + false && true + done + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of while but by return from fn +>COND +>COND (setopt err_exit { false && true + } always { + print ALWAYS } print OK ) -1:ERR_EXIT triggered by status 1 at end of { } +0:ERR_EXIT not triggered by status 1 at end of always +>ALWAYS +>OK + + (setopt err_exit + fn() { + { + false && true + } always { + print ALWAYS + } + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of always but by return from fn +>ALWAYS + + (setopt err_exit + { + false && true + } + print OK + ) +0:ERR_EXIT not triggered by status 1 at end of { } +>OK + + (setopt err_exit + fn() { + { + false && true + } + } + fn + print OK + ) +1:ERR_EXIT not triggered by status 1 at end of { } but by return from fn unsetopt err_exit err_return (setopt err_exit