+#ifndef mPUSHi
+# define mPUSHi(I) PUSHs(sv_2mortal(newSViv(I)))
+#endif
+
+#ifndef PERL_MAGIC_ext
+# define PERL_MAGIC_ext '~'
+#endif
+
+#ifndef MGf_COPY
+# define MGf_COPY 0
+#endif
+
+#ifndef MGf_DUP
+# define MGf_DUP 0
+#endif
+
+#ifndef MGf_LOCAL
+# define MGf_LOCAL 0
+#endif
+
+/* uvar magic and Hash::Util::FieldHash were commited with p28419 */
+#if VMG_HAS_PERL_AND(28419, 5, 9, 4)
+# define VMG_UVAR 1
+#else
+# define VMG_UVAR 0
+#endif
+
+#if !defined(VMG_COMPAT_ARRAY_PUSH_NOLEN) && VMG_HAS_PERL_OR(25854, 5, 9, 3)
+# define VMG_COMPAT_ARRAY_PUSH_NOLEN 1
+#else
+# define VMG_COMPAT_ARRAY_PUSH_NOLEN 0
+#endif
+
+/* since 5.9.5 - see #43357 */
+#if VMG_HAS_PERL_OR(31473, 5, 9, 5)
+# define VMG_COMPAT_ARRAY_UNDEF_CLEAR 1
+#else
+# define VMG_COMPAT_ARRAY_UNDEF_CLEAR 0
+#endif
+
+#if VMG_HAS_PERL_OR(32969, 5, 11, 0)
+# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 1
+#else
+# define VMG_COMPAT_SCALAR_LENGTH_NOLEN 0
+#endif
+
+#if VMG_UVAR
+
+/* Bug-free mg_magical - see http://www.xray.mpe.mpg.de/mailing-lists/perl5-porters/2008-01/msg00036.html - but specialized to our needs. */
+STATIC void vmg_sv_magicuvar(pTHX_ SV *sv, const char *uf, I32 len) {
+#define vmg_sv_magicuvar(S, U, L) vmg_sv_magicuvar(aTHX_ (S), (U), (L))
+ const MAGIC* mg;
+ sv_magic(sv, NULL, PERL_MAGIC_uvar, uf, len);
+ /* uvar magic has set and get magic, hence this has set SVs_GMG and SVs_SMG. */
+ PERL_UNUSED_CONTEXT;
+ if ((mg = SvMAGIC(sv))) {
+ SvRMAGICAL_off(sv);
+ do {
+ const MGVTBL* const vtbl = mg->mg_virtual;
+ if (vtbl) {
+ if (vtbl->svt_clear) {
+ SvRMAGICAL_on(sv);
+ break;
+ }
+ }
+ } while ((mg = mg->mg_moremagic));
+ }
+}