struct magic_state {
SV* mgs_sv;
- U32 mgs_flags;
I32 mgs_ss_ix;
+ U32 mgs_magical;
+ bool mgs_readonly;
};
/* MGS is typedef'ed to struct magic_state in perl.h */
mgs = SSPTR(mgs_ix, MGS*);
mgs->mgs_sv = sv;
- mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
+ mgs->mgs_magical = SvMAGICAL(sv);
+ mgs->mgs_readonly = SvREADONLY(sv) != 0;
mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */
SvMAGICAL_off(sv);
const MAGIC* mg;
PERL_ARGS_ASSERT_MG_MAGICAL;
PERL_UNUSED_CONTEXT;
+
+ SvMAGICAL_off(sv);
if ((mg = SvMAGIC(sv))) {
- SvRMAGICAL_off(sv);
do {
const MGVTBL* const vtbl = mg->mg_virtual;
if (vtbl) {
dVAR;
const I32 mgs_ix = SSNEW(sizeof(MGS));
const bool was_temp = (bool)SvTEMP(sv);
- int have_new = 0;
+ bool have_new = 0;
MAGIC *newmg, *head, *cur, *mg;
/* guard against sv having being freed midway by holding a private
reference. */
newmg = cur = head = mg = SvMAGIC(sv);
while (mg) {
const MGVTBL * const vtbl = mg->mg_virtual;
+ MAGIC * const nextmg = mg->mg_moremagic; /* it may delete itself */
if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) {
CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg);
/* guard against magic having been deleted - eg FETCH calling
* untie */
- if (!SvMAGIC(sv))
+ if (!SvMAGIC(sv)) {
+ (SSPTR(mgs_ix, MGS *))->mgs_magical = 0; /* recalculate flags */
break;
+ }
- /* Don't restore the flags for this entry if it was deleted. */
+ /* recalculate flags if this entry was deleted. */
if (mg->mg_flags & MGf_GSKIP)
- (SSPTR(mgs_ix, MGS *))->mgs_flags = 0;
+ (SSPTR(mgs_ix, MGS *))->mgs_magical = 0;
}
- mg = mg->mg_moremagic;
+ mg = nextmg;
if (have_new) {
/* Have we finished with the new entries we saw? Start again
have_new = 1;
cur = mg;
mg = newmg;
+ (SSPTR(mgs_ix, MGS *))->mgs_magical = 0; /* recalculate flags */
}
}
nextmg = mg->mg_moremagic; /* it may delete itself */
if (mg->mg_flags & MGf_GSKIP) {
mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
- (SSPTR(mgs_ix, MGS*))->mgs_flags = 0;
+ (SSPTR(mgs_ix, MGS*))->mgs_magical = 0;
}
if (PL_localizing == 2 && !S_is_container_magic(mg))
continue;
sv_force_normal_flags(sv, 0);
#endif
- if (mgs->mgs_flags)
- SvFLAGS(sv) |= mgs->mgs_flags;
+ if (mgs->mgs_readonly)
+ SvREADONLY_on(sv);
+ if (mgs->mgs_magical)
+ SvFLAGS(sv) |= mgs->mgs_magical;
else
mg_magical(sv);
if (SvGMAGICAL(sv)) {