X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=scope.c;h=452ea774fe272a0ddcdccc70a743909f993bb3f6;hb=0a1bd7acb04f7cfb7bc0973e9fa8f84b971137e7;hp=75f59cf5385f78fee3fafcd85957c2b559d8ec9d;hpb=ed08b2c61bbd3fcbc9931b185a9cf6a0a56f9acf;p=p5sagit%2Fp5-mst-13.2.git diff --git a/scope.c b/scope.c index 75f59cf..452ea77 100644 --- a/scope.c +++ b/scope.c @@ -1,7 +1,7 @@ /* scope.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -199,9 +199,9 @@ S_save_scalar_at(pTHX_ SV **sptr) sv = *sptr = NEWSV(0,0); if (SvTYPE(osv) >= SVt_PVMG && SvMAGIC(osv) && SvTYPE(osv) != SVt_PVGV) { + MAGIC *mg; sv_upgrade(sv, SvTYPE(osv)); if (SvGMAGICAL(osv)) { - MAGIC* mg; bool oldtainted = PL_tainted; mg_get(osv); /* note, can croak! */ if (PL_tainting && PL_tainted && @@ -214,7 +214,17 @@ S_save_scalar_at(pTHX_ SV **sptr) PL_tainted = oldtainted; } SvMAGIC(sv) = SvMAGIC(osv); - SvFLAGS(sv) |= SvMAGICAL(osv) | SvREADONLY(osv); + /* if it's a special scalar or if it has no 'set' magic, + * propagate the SvREADONLY flag. --rgs 20030922 */ + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { + if (mg->mg_type == '\0' + || !(mg->mg_virtual && mg->mg_virtual->svt_set)) + { + SvFLAGS(sv) |= SvREADONLY(osv); + break; + } + } + SvFLAGS(sv) |= SvMAGICAL(osv); /* XXX SvMAGIC() is *shared* between osv and sv. This can * lead to coredumps when both SVs are destroyed without one * of their SvMAGIC() slots being NULLed. */ @@ -624,6 +634,9 @@ Perl_save_aelem(pTHX_ AV *av, I32 idx, SV **sptr) SSPUSHINT(idx); SSPUSHPTR(SvREFCNT_inc(*sptr)); SSPUSHINT(SAVEt_AELEM); + /* if it gets reified later, the restore will have the wrong refcnt */ + if (!AvREAL(av) && AvREIFY(av)) + SvREFCNT_inc(*sptr); save_scalar_at(sptr); sv = *sptr; /* If we're localizing a tied array element, this new sv @@ -706,7 +719,7 @@ Perl_leave_scope(pTHX_ I32 base) value = (SV*)SSPOPPTR; gv = (GV*)SSPOPPTR; ptr = &GvSV(gv); - SvREFCNT_dec(gv); + av = (AV*)gv; /* what to refcnt_dec */ goto restore_sv; case SAVEt_GENERIC_PVREF: /* generic pv */ str = (char*)SSPOPPTR; @@ -739,6 +752,7 @@ Perl_leave_scope(pTHX_ I32 base) case SAVEt_SVREF: /* scalar reference */ value = (SV*)SSPOPPTR; ptr = SSPOPPTR; + av = Nullav; /* what to refcnt_dec */ restore_sv: sv = *(SV**)ptr; DEBUG_S(PerlIO_printf(Perl_debug_log, @@ -768,12 +782,14 @@ Perl_leave_scope(pTHX_ I32 base) * mg_get() in save_scalar_at() croaked */ SvMAGIC(value) = 0; } - SvREFCNT_dec(sv); *(SV**)ptr = value; + SvREFCNT_dec(sv); PL_localizing = 2; SvSETMAGIC(value); PL_localizing = 0; SvREFCNT_dec(value); + if (av) /* actually an av, hv or gv */ + SvREFCNT_dec(av); break; case SAVEt_AV: /* array reference */ av = (AV*)SSPOPPTR; @@ -983,13 +999,14 @@ Perl_leave_scope(pTHX_ I32 base) value = (SV*)SSPOPPTR; i = SSPOPINT; av = (AV*)SSPOPPTR; + if (!AvREAL(av) && AvREIFY(av)) /* undo reify guard */ + SvREFCNT_dec(value); ptr = av_fetch(av,i,1); if (ptr) { sv = *(SV**)ptr; if (sv && sv != &PL_sv_undef) { if (SvTIED_mg((SV*)av, PERL_MAGIC_tied)) (void)SvREFCNT_inc(sv); - SvREFCNT_dec(av); goto restore_sv; } } @@ -1007,8 +1024,8 @@ Perl_leave_scope(pTHX_ I32 base) ptr = &HeVAL((HE*)ptr); if (SvTIED_mg((SV*)hv, PERL_MAGIC_tied)) (void)SvREFCNT_inc(*(SV**)ptr); - SvREFCNT_dec(hv); SvREFCNT_dec(sv); + av = (AV*)hv; /* what to refcnt_dec */ goto restore_sv; } } @@ -1025,6 +1042,11 @@ Perl_leave_scope(pTHX_ I32 base) GvHV(PL_hintgv) = NULL; } *(I32*)&PL_hints = (I32)SSPOPINT; + if (PL_hints & HINT_LOCALIZE_HH) { + SvREFCNT_dec((SV*)GvHV(PL_hintgv)); + GvHV(PL_hintgv) = (HV*)SSPOPPTR; + } + break; case SAVEt_COMPPAD: PL_comppad = (PAD*)SSPOPPTR;