summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--Src/exec.c8
-rw-r--r--Test/C03traps.ztst37
3 files changed, 48 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index b1b000025..1cda59e07 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-10-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 39540: Src/exec.c, Test/C03traps.ztst: "! command" should
+ suppress ERR_EXIT and ERR_RETURN.
+
2016-09-30 Daniel Shahaf <d.s@daniel.shahaf.name>
* 39495: Doc/Zsh/contrib.yo, Functions/Misc/add-zle-hook-widget:
diff --git a/Src/exec.c b/Src/exec.c
index 2714edbcb..906cf6cca 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -1226,6 +1226,7 @@ execlist(Estate state, int dont_change_job, int exiting)
}
while (wc_code(code) == WC_LIST && !breaks && !retflag && !errflag) {
int donedebug;
+ int this_noerrexit = 0;
ltype = WC_LIST_TYPE(code);
csp = cmdsp;
@@ -1309,9 +1310,12 @@ execlist(Estate state, int dont_change_job, int exiting)
goto sublist_done;
}
while (wc_code(code) == WC_SUBLIST) {
+ int isend = (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END);
next = state->pc + WC_SUBLIST_SKIP(code);
if (!oldnoerrexit)
- noerrexit = (WC_SUBLIST_TYPE(code) != WC_SUBLIST_END);
+ noerrexit = !isend;
+ if ((WC_SUBLIST_FLAGS(code) & WC_SUBLIST_NOT) && isend)
+ this_noerrexit = 1;
switch (WC_SUBLIST_TYPE(code)) {
case WC_SUBLIST_END:
/* End of sublist; just execute, ignoring status. */
@@ -1427,7 +1431,7 @@ sublist_done:
/* Check whether we are suppressing traps/errexit *
* (typically in init scripts) and if we haven't *
* already performed them for this sublist. */
- if (!noerrexit && !donetrap) {
+ if (!noerrexit && !this_noerrexit && !donetrap) {
if (sigtrapped[SIGZERR] && lastval) {
dotrap(SIGZERR);
donetrap = 1;
diff --git a/Test/C03traps.ztst b/Test/C03traps.ztst
index 83c05aa08..3a65b2876 100644
--- a/Test/C03traps.ztst
+++ b/Test/C03traps.ztst
@@ -519,6 +519,43 @@
>Yes
F:Must be tested with a top-level script rather than source or function
+ fn() {
+ emulate -L zsh
+ setopt errreturn
+ print before
+ false
+ print after
+ }
+ fn
+1:ERRRETURN, basic case
+>before
+
+ fn() {
+ emulate -L zsh
+ setopt errreturn
+ print before
+ ! true
+ ! false
+ print after
+ }
+ fn
+0:ERRETURN with "!"
+>before
+>after
+
+ fn() {
+ emulate -L zsh
+ setopt errreturn
+ print before
+ ! true
+ ! false
+ false
+ print after
+ }
+ fn
+1:ERRETURN with "!" and a following false
+>before
+
%clean
rm -f TRAPEXIT