Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Interrupting globs (Re: Something rotten in tar completion)



On Sun, 07 Dec 2014 18:59:04 +0000
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx> wrote:
> > In particular with respect to always-blocks, there should be some way
> > for TRY_BLOCK_ERROR to clear interrupts as well as (maybe even instead
> > of?  TRY_BLOCK_INTERRUPT?) internal errors.  A trap that returns zero
> > only clears interrupt if there isn't another trap in a deeper scope.
> 
> Yes, probably.  I realised we'd better not do that with bits in the shell
> code as the documentation suggests setting TRY_BLOCK_ERROR to 0 clears
> errors.  We'd want clearing interrupts to be a separate explicit action.

I think this is a mechanical addition of a parallel variable, in as much
as anything is mechanical here...  Not entirely sure when we'd want to
use it, but it would get us out of jail free if the new interrupt_abort
code is riding roughshod over some shell code where we need to ensure
the state gets fully restored, so is probably worth having.

I suppose, theoretically, this means we can fix up any problems in the
new C code within shell code.  (It's now a decade and a half since I
gave up theoretical physics, but I still interpret the word
"theoretically" as meaning "I get paid to do this whatever happens in
the real world".  As I don't get paid to do this, the meaning is even
stronger.)

pws


diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 5833d6b..8da0c64 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -754,6 +754,14 @@ 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 keyboard, typically
+by the user typing tt(^C).  If set to 0, any such interrupt will
+be reset; otherwise, the interrupt is propagated after the tt(always)
+block.
+)
 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 9b0a8d7..4daa605 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 bdace79..79088d1 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}



Messages sorted by: Reverse Date, Date, Thread, Author