about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@zsh.org>2016-09-14 10:32:29 +0100
committerPeter Stephenson <pws@zsh.org>2016-09-14 10:33:18 +0100
commita4b8ee13be494c8732c0348857befe87951a058b (patch)
tree5db582aeb688e4a1520f205a268765602f5b61e4
parentbe4c072cf50ffcc2e2c34e4edbb0e2a78900206b (diff)
downloadzsh-a4b8ee13be494c8732c0348857befe87951a058b.tar.gz
zsh-a4b8ee13be494c8732c0348857befe87951a058b.tar.xz
zsh-a4b8ee13be494c8732c0348857befe87951a058b.zip
zsh-users/21903: Fix ${...?...} in interactive shell.
On failure should abort back to top level, but we reset the error
flag around commands.  Add a hard error flag that's only reset at top level.
-rw-r--r--ChangeLog6
-rw-r--r--Src/subst.c7
-rw-r--r--Src/zsh.h9
-rw-r--r--Test/D04parameter.ztst14
4 files changed, 35 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 0c0b72272..357782c2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-14  Peter Stephenson  <p.stephenson@samsung.com>
+
+	* zsh-users/21903: Src/subst.c, Src/zsh.h,
+	Test/D04parameter.ztst: ${...?...} in interactive shell should
+	abort to top level, not just current command.
+
 2016-09-14  Marko Myllynen  <myllynen@redhat.com>
 
 	* unposted: Completion/Unix/Command/_libvirt: Add another
diff --git a/Src/subst.c b/Src/subst.c
index 1c2027f32..92fde4598 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -2922,6 +2922,13 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags,
                 if (isset(EXECOPT)) {
                     *idend = '\0';
                     zerr("%s: %s", idbeg, *s ? s : "parameter not set");
+                    /*
+                     * In interactive shell we need to return to
+                     * top-level prompt --- don't clear this error
+                     * after handling a command as we do with
+                     * most errors.
+                     */
+                    errflag |= ERRFLAG_HARD;
                     if (!interact) {
                         if (mypid == getpid()) {
                             /*
diff --git a/Src/zsh.h b/Src/zsh.h
index 996bc3369..2dc5e7e2a 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -2807,7 +2807,14 @@ enum errflag_bits {
     /*
      * User interrupt.
      */
-    ERRFLAG_INT = 2
+    ERRFLAG_INT = 2,
+    /*
+     * Hard error --- return to top-level prompt in interactive
+     * shell.  In non-interactive shell we'll typically already
+     * have exited.  This is reset by "errflag = 0" in
+     * loop(toplevel = 1, ...).
+     */
+    ERRFLAG_HARD = 4
 };
 
 /***********/
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index be6e10461..762305197 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -95,6 +95,20 @@
 ?(eval):1: unset1: exiting1
 ?(eval):2: null1: exiting2
 
+  PROMPT="" $ZTST_testdir/../Src/zsh -fis <<<'
+  unsetopt PROMPT_SP
+  PS2="" PS3="" PS4="" RPS1="" RPS2=""
+  foo() {
+      print ${1:?no arguments given}
+      print not reached
+  }
+  foo
+  print reached
+  '
+0:interactive shell returns to top level on ${...?...} error
+?foo:1: 1: no arguments given
+>reached
+
   print ${set1:+word1} ${set1+word2} ${null1:+word3} ${null1+word4}
   print ${unset1:+word5} ${unset1+word6}
 0:${...:+...}, ${...+...}