mirror of
git://git.code.sf.net/p/zsh/code
synced 2025-09-10 12:40:58 +02:00
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.
This commit is contained in:
parent
20f694d101
commit
151b95cfd2
3 changed files with 27 additions and 12 deletions
|
@ -754,6 +754,17 @@ It may be reset, clearing the error condition. See
|
||||||
ifzman(em(Complex Commands) in zmanref(zshmisc))\
|
ifzman(em(Complex Commands) in zmanref(zshmisc))\
|
||||||
ifnzman(noderef(Complex Commands))
|
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)
|
vindex(TTY)
|
||||||
item(tt(TTY))(
|
item(tt(TTY))(
|
||||||
The name of the tty associated with the shell, if any.
|
The name of the tty associated with the shell, if any.
|
||||||
|
|
27
Src/loop.c
27
Src/loop.c
|
@ -633,6 +633,14 @@ execcase(Estate state, int do_exec)
|
||||||
zlong
|
zlong
|
||||||
try_errflag = -1;
|
try_errflag = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Corrresponding interrupt error status form `try' block.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**/
|
||||||
|
zlong
|
||||||
|
try_interrupt = -1;
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
zlong
|
zlong
|
||||||
try_tryflag = 0;
|
try_tryflag = 0;
|
||||||
|
@ -643,8 +651,8 @@ exectry(Estate state, int do_exec)
|
||||||
{
|
{
|
||||||
Wordcode end, always;
|
Wordcode end, always;
|
||||||
int endval;
|
int endval;
|
||||||
int save_retflag, save_breaks, save_contflag, try_interrupt;
|
int save_retflag, save_breaks, save_contflag;
|
||||||
zlong save_try_errflag, save_try_tryflag;
|
zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
|
||||||
|
|
||||||
end = state->pc + WC_TRY_SKIP(state->pc[-1]);
|
end = state->pc + WC_TRY_SKIP(state->pc[-1]);
|
||||||
always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
|
always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
|
||||||
|
@ -671,8 +679,9 @@ exectry(Estate state, int do_exec)
|
||||||
|
|
||||||
/* The always clause. */
|
/* The always clause. */
|
||||||
save_try_errflag = try_errflag;
|
save_try_errflag = try_errflag;
|
||||||
|
save_try_interrupt = try_interrupt;
|
||||||
try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
|
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 */
|
/* We need to reset all errors to allow the block to execute */
|
||||||
errflag = 0;
|
errflag = 0;
|
||||||
save_retflag = retflag;
|
save_retflag = retflag;
|
||||||
|
@ -689,18 +698,12 @@ exectry(Estate state, int do_exec)
|
||||||
errflag |= ERRFLAG_ERROR;
|
errflag |= ERRFLAG_ERROR;
|
||||||
else
|
else
|
||||||
errflag &= ~ERRFLAG_ERROR;
|
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)
|
if (try_interrupt)
|
||||||
errflag |= ERRFLAG_INT;
|
errflag |= ERRFLAG_INT;
|
||||||
|
else
|
||||||
|
errflag &= ~ERRFLAG_INT;
|
||||||
try_errflag = save_try_errflag;
|
try_errflag = save_try_errflag;
|
||||||
|
try_interrupt = save_try_interrupt;
|
||||||
if (!retflag)
|
if (!retflag)
|
||||||
retflag = save_retflag;
|
retflag = save_retflag;
|
||||||
if (!breaks)
|
if (!breaks)
|
||||||
|
|
|
@ -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}
|
#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("OPTIND", &zoptind, varinteger_gsu),
|
||||||
IPDEF6("TRY_BLOCK_ERROR", &try_errflag, 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 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}
|
#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
|
||||||
|
|
Loading…
Reference in a new issue