+/* --- 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) STMT_START { \
+ if (SU_UD_ORIGIN(U)) Safefree(SU_UD_ORIGIN(U)); \
+ Safefree(U); \
+} STMT_END
+
+/* ... 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, 9, 5)
+ PERL_CONTEXT saved_cx;
+ I32 cxix;
+#endif
+
+ dSP;
+
+ SU_D({
+ PerlIO_printf(Perl_debug_log,
+ "%p: @@@ call\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n",
+ ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix);
+ });
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ PUTBACK;
+
+ /* If the recently popped context isn't saved there, it will be overwritten by
+ * the sub scope from call_sv, although it's still needed in our caller. */
+
+#if SU_HAS_PERL(5, 9, 5)
+ if (cxstack_ix < cxstack_max)
+ cxix = cxstack_ix + 1;
+ else
+ cxix = Perl_cxinc(aTHX);
+ saved_cx = cxstack[cxix];
+#endif
+
+ call_sv(ud->cb, G_VOID);
+
+#if SU_HAS_PERL(5, 9, 5)
+ cxstack[cxix] = saved_cx;
+#endif
+
+ 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\n%p: depth=%2d scope_ix=%2d save_ix=%2d\n",
+ ud, ud, SU_UD_DEPTH(ud), PL_scopestack_ix, PL_savestack_ix);
+ });
+
+ SAVEDESTRUCTOR_X(su_call, ud);
+}
+
+/* ... Localize & localize array/hash element .............................. */
+
+typedef struct {
+ su_ud_common ci;
+ SV *sv;
+ SV *val;
+ SV *elem;
+ svtype type;
+} su_ud_localize;
+
+STATIC void su_ud_localize_init(pTHX_ su_ud_localize *ud, SV *sv, SV *val, SV *elem) {
+#define su_ud_localize_init(UD, S, V, E) su_ud_localize_init(aTHX_ (UD), (S), (V), (E))