diff options
Diffstat (limited to 'Src/loop.c')
-rw-r--r-- | Src/loop.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/Src/loop.c b/Src/loop.c index f52f5e74e..4c45c1f78 100644 --- a/Src/loop.c +++ b/Src/loop.c @@ -616,3 +616,68 @@ execcase(Estate state, int do_exec) return lastval; } + +/* + * Errflag from `try' block, may be reset in `always' block. + * Accessible from an integer parameter, so needs to be a zlong. + */ + +/**/ +zlong +try_errflag = -1; + +/**/ +int +exectry(Estate state, int do_exec) +{ + Wordcode end, always; + int endval; + int save_retflag, save_breaks, save_loops, save_contflag; + zlong save_try_errflag; + + end = state->pc + WC_TRY_SKIP(state->pc[-1]); + always = state->pc + 1 + WC_TRY_SKIP(*state->pc); + state->pc++; + pushheap(); + cmdpush(CS_CURSH); + + /* The :try clause */ + execlist(state, 1, do_exec); + + /* Don't record errflag here, may be reset. */ + endval = lastval; + + freeheap(); + + cmdpop(); + cmdpush(CS_ALWAYS); + + /* The always clause. */ + save_try_errflag = try_errflag; + try_errflag = (zlong)errflag; + errflag = 0; + save_retflag = retflag; + retflag = 0; + save_breaks = breaks; + breaks = 0; + save_loops = loops; + loops = 0; + save_contflag = contflag; + contflag = 0; + + state->pc = always; + execlist(state, 1, do_exec); + + errflag = try_errflag ? 1 : 0; + try_errflag = save_try_errflag; + retflag = save_retflag; + breaks = save_breaks; + loops = save_loops; + contflag = save_contflag; + + cmdpop(); + popheap(); + state->pc = end; + + return endval; +} |