about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2016-10-02 19:16:03 +0100
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2016-10-02 19:17:19 +0100
commit6b2585147b842c69faecb136c17dbdda79b3e4b4 (patch)
treed6fff6653a7773bf525482542f6ab4b420221083
parent4f2a1810f2fa1d74008e03a09d66eaff3e5edc9e (diff)
downloadzsh-6b2585147b842c69faecb136c17dbdda79b3e4b4.tar.gz
zsh-6b2585147b842c69faecb136c17dbdda79b3e4b4.tar.xz
zsh-6b2585147b842c69faecb136c17dbdda79b3e4b4.zip
39540: "! command" should suppress ERR_EXIT and ERR_RETURN
-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