+/* --- Actions ------------------------------------------------------------- */
+
+typedef struct {
+ I32 depth;
+ I32 *origin;
+ void (*handler)(pTHX_ void *);
+} su_ud_common;
+
+#define SU_UD_DEPTH(U) (((su_ud_common *) (U))->depth)
+#define SU_UD_ORIGIN(U) (((su_ud_common *) (U))->origin)
+#define SU_UD_HANDLER(U) (((su_ud_common *) (U))->handler)
+
+#define SU_UD_FREE(U) do { \
+ if (SU_UD_ORIGIN(U)) Safefree(SU_UD_ORIGIN(U)); \
+ Safefree(U); \
+} while (0)
+
+/* ... Reap ................................................................ */
+
+typedef struct {
+ su_ud_common ci;
+ SV *cb;
+} su_ud_reap;
+
+STATIC void su_call(pTHX_ void *ud_) {
+ su_ud_reap *ud = (su_ud_reap *) ud_;
+#if SU_HAS_PERL(5, 10, 0)
+ I32 dieing = PL_op->op_type == OP_DIE;
+#endif
+
+ dSP;
+
+ SU_D(PerlIO_printf(Perl_debug_log, "%p: @@@ call at %d (save is %d)\n",
+ ud, PL_scopestack_ix, PL_savestack_ix));
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ PUTBACK;
+
+ /* If cxstack_ix isn't incremented there, the eval context will be overwritten
+ * when the new sub scope will be created in call_sv. */
+
+#if SU_HAS_PERL(5, 10, 0)
+ if (dieing)
+ if (cxstack_ix < cxstack_max)
+ ++cxstack_ix;
+ else
+ cxstack_ix = Perl_cxinc(aTHX);
+#endif
+
+ call_sv(ud->cb, G_VOID);
+
+#if SU_HAS_PERL(5, 10, 0)
+ if (dieing && cxstack_ix > 0)
+ --cxstack_ix;
+#endif
+
+ SPAGAIN;
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ SvREFCNT_dec(ud->cb);
+ SU_UD_FREE(ud);
+}
+
+STATIC void su_reap(pTHX_ void *ud) {
+#define su_reap(U) su_reap(aTHX_ (U))
+ SU_D(PerlIO_printf(Perl_debug_log, "%p: === reap at %d (save is %d)\n",
+ ud, PL_scopestack_ix, PL_savestack_ix));
+ SAVEDESTRUCTOR_X(su_call, ud);
+ SU_D(PerlIO_printf(Perl_debug_log, "%p: savestack is now at %d, base at %d\n",
+ ud, PL_savestack_ix,
+ PL_scopestack[PL_scopestack_ix]));
+}
+
+/* ... Localize & localize array/hash element .............................. */
+
+typedef struct {
+ su_ud_common ci;
+ SV *sv;
+ SV *val;
+ SV *elem;
+} su_ud_localize;
+