+/*
+ * How to build the first jmpenv.
+ *
+ * top_env needs to be non-zero. It points to an area
+ * in which longjmp() stuff is stored, as C callstack
+ * info there at least is thread specific this has to
+ * be per-thread. Otherwise a 'die' in a thread gives
+ * that thread the C stack of last thread to do an eval {}!
+ */
+
+#define JMPENV_BOOTSTRAP \
+ STMT_START { \
+ Zero(&PL_start_env, 1, JMPENV); \
+ PL_start_env.je_ret = -1; \
+ PL_start_env.je_mustcatch = TRUE; \
+ PL_top_env = &PL_start_env; \
+ } STMT_END
+
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
+
+/*
+ * These exception-handling macros are split up to
+ * ease integration with C++ exceptions.
+ *
+ * To use C++ try+catch to catch Perl exceptions, an extension author
+ * needs to first write an extern "C" function to throw an appropriate
+ * exception object; typically it will be or contain an integer,
+ * because Perl's internals use integers to track exception types:
+ * extern "C" { static void thrower(int i) { throw i; } }
+ *
+ * Then (as shown below) the author needs to use, not the simple
+ * JMPENV_PUSH, but several of its constitutent macros, to arrange for
+ * the Perl internals to call thrower() rather than longjmp() to
+ * report exceptions:
+ *
+ * dJMPENV;
+ * JMPENV_PUSH_INIT(thrower);
+ * try {
+ * ... stuff that may throw exceptions ...
+ * }
+ * catch (int why) { // or whatever matches thrower()
+ * JMPENV_POST_CATCH;
+ * EXCEPT_SET(why);
+ * switch (why) {
+ * ... // handle various Perl exception codes
+ * }
+ * }
+ * JMPENV_POP; // don't forget this!
+ */
+
+/*
+ * Function that catches/throws, and its callback for the
+ * body of protected processing.
+ */
+typedef void *(CPERLscope(*protect_body_t)) (pTHX_ va_list);
+typedef void *(CPERLscope(*protect_proc_t)) (pTHX_ volatile JMPENV *pcur_env,
+ int *, protect_body_t, ...);
+
+#define dJMPENV JMPENV cur_env; \
+ volatile JMPENV *pcur_env = ((cur_env.je_noset = 0),&cur_env)
+
+#define JMPENV_PUSH_INIT_ENV(ce,THROWFUNC) \