about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <p.w.stephenson@ntlworld.com>2014-12-07 20:21:49 +0000
committerPeter Stephenson <p.w.stephenson@ntlworld.com>2014-12-07 21:10:07 +0000
commit151b95cfd2098de3424923f898179142062ff818 (patch)
tree267ec48308a09a36e4526c58243f3facec633cd3
parent20f694d101ae72d2ffecc28abe90144ffeeb27e4 (diff)
downloadzsh-151b95cfd2098de3424923f898179142062ff818.tar.gz
zsh-151b95cfd2098de3424923f898179142062ff818.tar.xz
zsh-151b95cfd2098de3424923f898179142062ff818.zip
33918: add TRY_BLOCK_INTERRUPT
This works the same as TRY_BLOCK_ERROR, but for a SIGINT, too.

Evena added documentation, like the professionals!  Amended along the
lines suggested by Bart in 33918.
-rw-r--r--Doc/Zsh/params.yo11
-rw-r--r--Src/loop.c27
-rw-r--r--Src/params.c1
3 files changed, 27 insertions, 12 deletions
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 5833d6be9..996f87c4f 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -754,6 +754,17 @@ It may be reset, clearing the error condition.  See
 ifzman(em(Complex Commands) in zmanref(zshmisc))\
 ifnzman(noderef(Complex Commands))
 )
+vinde(TRY_BLOCK_INTERRUPT)
+item(tt(TRY_BLOCK_INTERRUPT) <S>)(
+This variable works in a similar way to tt(TRY_BLOCK_ERROR), but
+represents the status of an interrupt from the signall SIGINT, which
+typically comes from the keyboard when the user types tt(^C).  If set to
+0, any such interrupt will be reset; otherwise, the interrupt is
+propagated after the tt(always) block.
+
+Note that it is possible that an interrupt arrives during the execution
+of the tt(always) block; this interrupt is also propagated.
+)
 vindex(TTY)
 item(tt(TTY))(
 The name of the tty associated with the shell, if any.
diff --git a/Src/loop.c b/Src/loop.c
index 9b0a8d79c..4daa60591 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -633,6 +633,14 @@ execcase(Estate state, int do_exec)
 zlong
 try_errflag = -1;
 
+/**
+ * Corrresponding interrupt error status form `try' block.
+ */
+
+/**/
+zlong
+try_interrupt = -1;
+
 /**/
 zlong
 try_tryflag = 0;
@@ -643,8 +651,8 @@ exectry(Estate state, int do_exec)
 {
     Wordcode end, always;
     int endval;
-    int save_retflag, save_breaks, save_contflag, try_interrupt;
-    zlong save_try_errflag, save_try_tryflag;
+    int save_retflag, save_breaks, save_contflag;
+    zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
 
     end = state->pc + WC_TRY_SKIP(state->pc[-1]);
     always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
@@ -671,8 +679,9 @@ exectry(Estate state, int do_exec)
 
     /* The always clause. */
     save_try_errflag = try_errflag;
+    save_try_interrupt = try_interrupt;
     try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
-    try_interrupt = errflag & ERRFLAG_INT;
+    try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0);
     /* We need to reset all errors to allow the block to execute */
     errflag = 0;
     save_retflag = retflag;
@@ -689,18 +698,12 @@ exectry(Estate state, int do_exec)
 	errflag |= ERRFLAG_ERROR;
     else
 	errflag &= ~ERRFLAG_ERROR;
-    /*
-     * TODO: currently, we always restore the interrupt
-     * error status.  We should have a way of clearing it.
-     * Doing this with try_errflag (the shell variable TRY_BLOCK_ERROR)
-     * is probably not a good idea since currently that's documented
-     * such that setting it to 0 clears errors, and we don't want
-     * to clear interrupts as a side effect.  So it probably needs
-     * a different variable.
-     */
     if (try_interrupt)
 	errflag |= ERRFLAG_INT;
+    else
+	errflag &= ~ERRFLAG_INT;
     try_errflag = save_try_errflag;
+    try_interrupt = save_try_interrupt;
     if (!retflag)
 	retflag = save_retflag;
     if (!breaks)
diff --git a/Src/params.c b/Src/params.c
index bdace7928..79088d162 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -331,6 +331,7 @@ IPDEF5("SHLVL", &shlvl, varinteger_gsu),
 #define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
 IPDEF6("OPTIND", &zoptind, varinteger_gsu),
 IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
+IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu),
 
 #define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
 #define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}