From 151b95cfd2098de3424923f898179142062ff818 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Sun, 7 Dec 2014 20:21:49 +0000 Subject: 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. --- Doc/Zsh/params.yo | 11 +++++++++++ Src/loop.c | 27 +++++++++++++++------------ Src/params.c | 1 + 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) )( +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} -- cgit 1.4.1