X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/4fdae80067c447c675a6ac92c7959d2206e207ba..d58bf5aa3d3631a46847733b1ff1985b30140228:/scope.h diff --git a/scope.h b/scope.h index d0931b1..d9fe15a 100644 --- a/scope.h +++ b/scope.h @@ -22,6 +22,7 @@ #define SAVEt_REGCONTEXT 21 #define SAVEt_STACK_POS 22 #define SAVEt_I16 23 +#define SAVEt_OP 24 #define SSCHECK(need) if (savestack_ix + need > savestack_max) savestack_grow() #define SSPUSHINT(i) (savestack[savestack_ix++].any_i32 = (I32)(i)) @@ -69,4 +70,64 @@ SSPUSHINT(stack_sp - stack_base); \ SSPUSHINT(SAVEt_STACK_POS); \ } STMT_END +#define SAVEOP() save_op() +/* A jmpenv packages the state required to perform a proper non-local jump. + * Note that there is a start_env initialized when perl starts, and top_env + * points to this initially, so top_env should always be non-null. + * + * Existence of a non-null top_env->je_prev implies it is valid to call + * longjmp() at that runlevel (we make sure start_env.je_prev is always + * null to ensure this). + * + * je_mustcatch, when set at any runlevel to TRUE, means eval ops must + * establish a local jmpenv to handle exception traps. Care must be taken + * to restore the previous value of je_mustcatch before exiting the + * stack frame iff JMPENV_PUSH was not called in that stack frame. + * GSAR 97-03-27 + */ + +struct jmpenv { + struct jmpenv * je_prev; + Sigjmp_buf je_buf; + int je_ret; /* return value of last setjmp() */ + bool je_mustcatch; /* longjmp()s must be caught locally */ +}; + +typedef struct jmpenv JMPENV; + +#ifdef OP_IN_REGISTER +#define OP_REG_TO_MEM opsave = op +#define OP_MEM_TO_REG op = opsave +#else +#define OP_REG_TO_MEM NOOP +#define OP_MEM_TO_REG NOOP +#endif + +#define dJMPENV JMPENV cur_env +#define JMPENV_PUSH(v) \ + STMT_START { \ + cur_env.je_prev = top_env; \ + OP_REG_TO_MEM; \ + cur_env.je_ret = Sigsetjmp(cur_env.je_buf, 1); \ + OP_MEM_TO_REG; \ + top_env = &cur_env; \ + cur_env.je_mustcatch = FALSE; \ + (v) = cur_env.je_ret; \ + } STMT_END +#define JMPENV_POP \ + STMT_START { top_env = cur_env.je_prev; } STMT_END +#define JMPENV_JUMP(v) \ + STMT_START { \ + OP_REG_TO_MEM; \ + if (top_env->je_prev) \ + Siglongjmp(top_env->je_buf, (v)); \ + if ((v) == 2) \ + exit(STATUS_NATIVE_EXPORT); \ + PerlIO_printf(PerlIO_stderr(), "panic: top_env\n"); \ + exit(1); \ + } STMT_END + +#define CATCH_GET (top_env->je_mustcatch) +#define CATCH_SET(v) (top_env->je_mustcatch = (v)) +