diff options
Diffstat (limited to 'Src/exec.c')
-rw-r--r-- | Src/exec.c | 58 |
1 files changed, 47 insertions, 11 deletions
diff --git a/Src/exec.c b/Src/exec.c index 5b360815f..6ca5b2f2b 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -65,16 +65,23 @@ int nohistsave; mod_export int errflag; /* - * Status of return from a trap. + * State of trap return value. Value is from enum trap_state. + */ + +/**/ +int trap_state; + +/* + * Value associated with return from a trap. * This is only active if we are inside a trap, else its value * is irrelevant. It is initialised to -1 for a function trap and * -2 for a non-function trap and if negative is decremented as * we go deeper into functions and incremented as we come back up. * The value is used to decide if an explicit "return" should cause * a return from the caller of the trap; it does this by setting - * trapreturn to a status (i.e. a non-negative value). + * trap_return to a status (i.e. a non-negative value). * - * In summary, trapreturn is + * In summary, trap_return is * - zero unless we are in a trap * - negative in a trap unless it has triggered. Code uses this * to detect an active trap. @@ -83,7 +90,7 @@ mod_export int errflag; */ /**/ -int trapreturn; +int trap_return; /* != 0 if this is a subshell */ @@ -1061,6 +1068,10 @@ execlist(Estate state, int dont_change_job, int exiting) } if (sigtrapped[SIGDEBUG] && isset(DEBUGBEFORECMD)) { + int oerrexit_opt = opts[ERREXIT]; + opts[ERREXIT] = 0; + noerrexit = 1; + exiting = donetrap; ret = lastval; dotrap(SIGDEBUG); @@ -1071,7 +1082,8 @@ execlist(Estate state, int dont_change_job, int exiting) * Only execute the trap once per sublist, even * if the DEBUGBEFORECMD option changes. */ - donedebug = 1; + donedebug = isset(ERREXIT) ? 2 : 1; + opts[ERREXIT] = oerrexit_opt; } else donedebug = 0; @@ -1087,6 +1099,18 @@ execlist(Estate state, int dont_change_job, int exiting) /* Loop through code followed by &&, ||, or end of sublist. */ code = *state->pc++; + if (donedebug == 2) { + /* Skip sublist. */ + while (wc_code(code) == WC_SUBLIST) { + state->pc = state->pc + WC_SUBLIST_SKIP(code); + if (WC_SUBLIST_TYPE(code) == WC_SUBLIST_END) + break; + code = *state->pc++; + } + donetrap = 1; + /* yucky but consistent... */ + goto sublist_done; + } while (wc_code(code) == WC_SUBLIST) { next = state->pc + WC_SUBLIST_SKIP(code); if (!oldnoerrexit) @@ -1177,12 +1201,20 @@ sublist_done: noerrexit = oldnoerrexit; if (sigtrapped[SIGDEBUG] && !isset(DEBUGBEFORECMD) && !donedebug) { + /* + * Save and restore ERREXIT for consistency with + * DEBUGBEFORECMD, even though it's not used. + */ + int oerrexit_opt = opts[ERREXIT]; + opts[ERREXIT] = 0; + noerrexit = 1; exiting = donetrap; ret = lastval; dotrap(SIGDEBUG); lastval = ret; donetrap = exiting; noerrexit = oldnoerrexit; + opts[ERREXIT] = oerrexit_opt; } cmdsp = csp; @@ -4145,8 +4177,8 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval) oargv0 = NULL; obreaks = breaks;; - if (trapreturn < 0) - trapreturn--; + if (trap_state == TRAP_STATE_PRIMED) + trap_return--; oldlastval = lastval; oldnumpipestats = numpipestats; if (noreturnval) { @@ -4264,8 +4296,8 @@ doshfunc(char *name, Eprog prog, LinkList doshargs, int flags, int noreturnval) endtrapscope(); - if (trapreturn < -1) - trapreturn++; + if (trap_state == TRAP_STATE_PRIMED) + trap_return++; ret = lastval; if (noreturnval) { lastval = oldlastval; @@ -4528,7 +4560,9 @@ execsave(void) es->badcshglob = badcshglob; es->cmdoutpid = cmdoutpid; es->cmdoutval = cmdoutval; - es->trapreturn = trapreturn; + es->trap_return = trap_return; + es->trap_state = trap_state; + es->trapisfunc = trapisfunc; es->noerrs = noerrs; es->subsh_close = subsh_close; es->underscore = ztrdup(underscore); @@ -4555,7 +4589,9 @@ execrestore(void) badcshglob = exstack->badcshglob; cmdoutpid = exstack->cmdoutpid; cmdoutval = exstack->cmdoutval; - trapreturn = exstack->trapreturn; + trap_return = exstack->trap_return; + trap_state = exstack->trap_state; + trapisfunc = exstack->trapisfunc; noerrs = exstack->noerrs; subsh_close = exstack->subsh_close; setunderscore(exstack->underscore); |