SvREFCNT_dec(d);
return;
}
- if (type <= SVt_PVLV) {
+ if (type <= SVt_PVLV && !isGV_with_GP(sv)) {
if (SvPVX_const(sv)) {
Perl_dump_indent(aTHX_ level, file," PV = 0x%"UVxf" ", PTR2UV(SvPVX_const(sv)));
if (SvOOK(sv))
Perl_dump_indent(aTHX_ level, file, " NAME = \"%s\"\n", GvNAME(sv));
Perl_dump_indent(aTHX_ level, file, " NAMELEN = %"IVdf"\n", (IV)GvNAMELEN(sv));
do_hv_dump (level, file, " GvSTASH", GvSTASH(sv));
+ if (!isGV_with_GP(sv))
+ break;
Perl_dump_indent(aTHX_ level, file, " GP = 0x%"UVxf"\n", PTR2UV(GvGP(sv)));
if (!GvGP(sv))
break;
FLAGS = \\(SCREAM,MULTI(?:,IN_PAD)?\\)
IV = 0
NV = 0
- PV = 0
NAME = "a"
NAMELEN = 1
GvSTASH = $ADDR\\t"main"
Safefree(SvPVX_mutable(gv));
}
Newxz(gp, 1, GP);
+ SvSCREAM_on(gv);
GvGP(gv) = gp_ref(gp);
#ifdef PERL_DONT_CREATE_GVSV
GvSV(gv) = NULL;
GvFILE(gv) = CopFILE(PL_curcop) ? CopFILE(PL_curcop) : (char *) "";
GvCVGEN(gv) = 0;
GvEGV(gv) = gv;
- SvSCREAM_on(gv);
GvSTASH(gv) = stash;
if (stash)
Perl_sv_add_backref(aTHX_ (SV*)stash, (SV*)gv);
dVAR;
GP* gp;
- if (!gv || !(gp = GvGP(gv)))
+ if (!gv || !isGV_with_GP(gv) || !(gp = GvGP(gv)))
return;
if (gp->gp_refcnt == 0) {
if (ckWARN_d(WARN_INTERNAL))
((!defined(_MSC_VER) || _MSC_VER > 1200) && !defined(__BORLANDC__))
# define GvGP(gv) (*(assert(SvTYPE(gv) == SVt_PVGV || \
SvTYPE(gv) == SVt_PVLV), \
- &(GvXPVGV(gv)->xgv_gp)))
+ assert(isGV_with_GP(gv)), \
+ &((gv)->sv_u.svu_gp)))
#else
-# define GvGP(gv) (GvXPVGV(gv)->xgv_gp)
+# define GvGP(gv) ((gv)->sv_u.svu_gp)
#endif
#define GvNAME(gv) (GvXPVGV(gv)->xgv_name)
Perl_warner(aTHX_ packWARN(WARN_SUBSTR),
"Attempt to use reference as lvalue in substr");
}
- if (SvOK(sv)) /* is it defined ? */
+ if (isGV_with_GP(sv))
+ SvPV_force_nolen(sv);
+ else if (SvOK(sv)) /* is it defined ? */
(void)SvPOK_only_UTF8(sv);
else
sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
sv = TARG;
if (SvROK(sv))
sv_unref(sv);
+ else if (isGV_with_GP(sv)) {
+ SvPV_force_nolen(sv);
+ }
SvUPGRADE(sv, SVt_PV);
tmplen = SvLEN(sv); /* remember if already alloced */
if (!tmplen && !SvREADONLY(sv))
do_clean_named_objs(pTHX_ SV *sv)
{
dVAR;
- if (SvTYPE(sv) == SVt_PVGV && GvGP(sv)) {
+ if (SvTYPE(sv) == SVt_PVGV && isGV_with_GP(sv) && GvGP(sv)) {
if ((
#ifdef PERL_DONT_CREATE_GVSV
GvSV(sv) &&
}
}
else {
- if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
- && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+ if (isGV_with_GP(sv)) {
return PTR2IV(glob_2inpuv((GV *)sv, NULL, TRUE));
}
- if (SvTYPE(sv) == SVt_PVGV)
- sv_dump(sv);
if (!(SvFLAGS(sv) & SVs_PADTMP)) {
if (!PL_localizing && ckWARN(WARN_UNINITIALIZED))
#endif /* NV_PRESERVES_UV */
}
else {
- if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
- && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+ if (isGV_with_GP(sv)) {
glob_2inpuv((GV *)sv, NULL, TRUE);
return 0.0;
}
#endif
}
else {
- if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
- && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+ if (isGV_with_GP(sv)) {
return glob_2inpuv((GV *)sv, lp, FALSE);
}
if (SvNOKp(sv))
return SvNVX(sv) != 0.0;
else {
- if ((SvFLAGS(sv) & SVp_SCREAM)
- && (SvTYPE(sv) == (SVt_PVGV) || SvTYPE(sv) == (SVt_PVLV)))
+ if (isGV_with_GP(sv))
return TRUE;
else
return FALSE;
const char * const name = GvNAME(sstr);
const STRLEN len = GvNAMELEN(sstr);
/* don't upgrade SVt_PVLV: it can hold a glob */
- if (dtype != SVt_PVLV)
+ if (dtype != SVt_PVLV) {
+ if (dtype >= SVt_PV) {
+ SvPV_free(dstr);
+ SvPV_set(dstr, 0);
+ SvLEN_set(dstr, 0);
+ SvCUR_set(dstr, 0);
+ }
sv_upgrade(dstr, SVt_PVGV);
+ }
GvSTASH(dstr) = GvSTASH(sstr);
if (GvSTASH(dstr))
Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
}
#endif
+ gp_free((GV*)dstr);
+ SvSCREAM_off(dstr);
(void)SvOK_off(dstr);
- SvSCREAM_on(dstr);
GvINTRO_off(dstr); /* one-shot flag */
- gp_free((GV*)dstr);
+ SvSCREAM_on(dstr);
GvGP(dstr) = gp_ref(GvGP(sstr));
if (SvTAINTED(sstr))
SvTAINT(dstr);
}
}
else {
- if ((stype == SVt_PVGV || stype == SVt_PVLV)
- && (sflags & SVp_SCREAM)) {
+ if (isGV_with_GP(sstr)) {
/* This stringification rule for globs is spread in 3 places.
This feels bad. FIXME. */
const U32 wasfake = sflags & SVf_FAKE;
SvFAKE_off(sv);
gv_efullname3(temp, (GV *) sv, "*");
- if (GvGP(sv))
+ if (GvGP(sv)) {
gp_free((GV*)sv);
+ }
if (GvSTASH(sv)) {
sv_del_backref((SV*)GvSTASH(sv), sv);
GvSTASH(sv) = NULL;
}
else {
/* Special case - not normally malloced for some reason */
- if ((SvREADONLY(sstr) && SvFAKE(sstr))) {
+ if (isGV_with_GP(sstr)) {
+ /* Don't need to do anything here. */
+ }
+ else if ((SvREADONLY(sstr) && SvFAKE(sstr))) {
/* A "shared" PV - clone it as "shared" PV */
SvPV_set(dstr,
HEK_KEY(hek_dup(SvSHARED_HEK_FROM_PV(SvPVX_const(sstr)),
sv_type_details->body_size + sv_type_details->offset, char);
#endif
- if (sv_type != SVt_PVAV && sv_type != SVt_PVHV)
+ if (sv_type != SVt_PVAV && sv_type != SVt_PVHV
+ && !isGV_with_GP(dstr))
Perl_rvpv_dup(aTHX_ dstr, sstr, param);
/* The Copy above means that all the source (unduplicated) pointers
break;
case SVt_PVGV:
GvNAME(dstr) = SAVEPVN(GvNAME(dstr), GvNAMELEN(dstr));
- GvSTASH(dstr) = hv_dup(GvSTASH(dstr), param);
/* Don't call sv_add_backref here as it's going to be created
as part of the magic cloning of the symbol table. */
- GvGP(dstr) = gp_dup(GvGP(dstr), param);
- (void)GpREFCNT_inc(GvGP(dstr));
+ GvSTASH(dstr) = hv_dup(GvSTASH(dstr), param);
+ if(isGV_with_GP(sstr)) {
+ /* Danger Will Robinson - GvGP(dstr) isn't initialised
+ at the point of this comment. */
+ GvGP(dstr) = gp_dup(GvGP(sstr), param);
+ (void)GpREFCNT_inc(GvGP(dstr));
+ } else
+ Perl_rvpv_dup(aTHX_ dstr, sstr, param);
break;
case SVt_PVIO:
IoIFP(dstr) = fp_dup(IoIFP(dstr), IoTYPE(dstr), param);
char* svu_pv; /* pointer to malloced string */ \
SV** svu_array; \
HE** svu_hash; \
+ GP* svu_gp; \
} sv_u
HV* xmg_stash; /* class package */
/* a full glob fits into this */
- GP* xgv_gp;
char* xgv_name;
STRLEN xgv_namelen;
HV* xgv_stash;
} xmg_u;
HV* xmg_stash; /* class package */
- GP* xgv_gp;
char* xgv_name;
STRLEN xgv_namelen;
HV* xgv_stash;
#if defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
#define assert_not_ROK(sv) ({assert(!SvROK(sv) || !SvRV(sv));}),
+#define assert_not_glob(sv) ({assert(!isGV_with_GP(sv));}),
#else
#define assert_not_ROK(sv)
+#define assert_not_glob(sv)
#endif
#define SvOK(sv) (SvFLAGS(sv) & SVf_OK)
-#define SvOK_off(sv) (assert_not_ROK(sv) \
+#define SvOK_off(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC| \
SVf_IVisUV|SVf_UTF8), \
SvOOK_off(sv))
#define SvOKp(sv) (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK))
#define SvIOKp(sv) (SvFLAGS(sv) & SVp_IOK)
-#define SvIOKp_on(sv) (SvRELEASE_IVX(sv), \
+#define SvIOKp_on(sv) (assert_not_glob(sv) SvRELEASE_IVX(sv), \
SvFLAGS(sv) |= SVp_IOK)
#define SvNOKp(sv) (SvFLAGS(sv) & SVp_NOK)
-#define SvNOKp_on(sv) (SvFLAGS(sv) |= SVp_NOK)
+#define SvNOKp_on(sv) (assert_not_glob(sv) SvFLAGS(sv) |= SVp_NOK)
#define SvPOKp(sv) (SvFLAGS(sv) & SVp_POK)
-#define SvPOKp_on(sv) (assert_not_ROK(sv) \
+#define SvPOKp_on(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) |= SVp_POK)
#define SvIOK(sv) (SvFLAGS(sv) & SVf_IOK)
-#define SvIOK_on(sv) (SvRELEASE_IVX(sv), \
+#define SvIOK_on(sv) (assert_not_glob(sv) SvRELEASE_IVX(sv), \
SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
#define SvIOK_off(sv) (SvFLAGS(sv) &= ~(SVf_IOK|SVp_IOK|SVf_IVisUV))
#define SvIOK_only(sv) (SvOK_off(sv), \
SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
-#define SvIOK_only_UV(sv) (SvOK_off_exc_UV(sv), \
+#define SvIOK_only_UV(sv) (assert_not_glob(sv) SvOK_off_exc_UV(sv), \
SvFLAGS(sv) |= (SVf_IOK|SVp_IOK))
#define SvIOK_UV(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) \
#define SvIsUV_off(sv) (SvFLAGS(sv) &= ~SVf_IVisUV)
#define SvNOK(sv) (SvFLAGS(sv) & SVf_NOK)
-#define SvNOK_on(sv) (SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
+#define SvNOK_on(sv) (assert_not_glob(sv) \
+ SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
#define SvNOK_off(sv) (SvFLAGS(sv) &= ~(SVf_NOK|SVp_NOK))
#define SvNOK_only(sv) (SvOK_off(sv), \
SvFLAGS(sv) |= (SVf_NOK|SVp_NOK))
#define SvUTF8_off(sv) (SvFLAGS(sv) &= ~(SVf_UTF8))
#define SvPOK(sv) (SvFLAGS(sv) & SVf_POK)
-#define SvPOK_on(sv) (assert_not_ROK(sv) \
+#define SvPOK_on(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) |= (SVf_POK|SVp_POK))
#define SvPOK_off(sv) (SvFLAGS(sv) &= ~(SVf_POK|SVp_POK))
-#define SvPOK_only(sv) (assert_not_ROK(sv) \
+#define SvPOK_only(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC| \
SVf_IVisUV|SVf_UTF8), \
SvFLAGS(sv) |= (SVf_POK|SVp_POK))
-#define SvPOK_only_UTF8(sv) (assert_not_ROK(sv) \
+#define SvPOK_only_UTF8(sv) (assert_not_ROK(sv) assert_not_glob(sv) \
SvFLAGS(sv) &= ~(SVf_OK|SVf_AMAGIC| \
SVf_IVisUV), \
SvFLAGS(sv) |= (SVf_POK|SVp_POK))
# define SvSTASH(sv) (0 + ((XPVMG*) SvANY(sv))->xmg_stash)
# endif
#else
-# define SvPVX(sv) ((sv)->sv_u.svu_pv)
# define SvCUR(sv) ((XPV*) SvANY(sv))->xpv_cur
# define SvLEN(sv) ((XPV*) SvANY(sv))->xpv_len
# define SvEND(sv) ((sv)->sv_u.svu_pv + ((XPV*)SvANY(sv))->xpv_cur)
# if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
/* These get expanded inside other macros that already use a variable _sv */
+# define SvPVX(sv) \
+ (*({ SV *const _svi = (SV *) sv; \
+ assert(SvTYPE(_svi) >= SVt_PV); \
+ assert(SvTYPE(_svi) != SVt_PVAV); \
+ assert(SvTYPE(_svi) != SVt_PVHV); \
+ assert(!isGV_with_GP(_svi)); \
+ &((_svi)->sv_u.svu_pv); \
+ }))
# define SvIVX(sv) \
(*({ SV *const _svi = (SV *) sv; \
assert(SvTYPE(_svi) == SVt_IV || SvTYPE(_svi) >= SVt_PVIV); \
&(((XPVMG*) SvANY(_svi))->xmg_stash); \
}))
# else
+# define SvPVX(sv) ((sv)->sv_u.svu_pv)
# define SvIVX(sv) ((XPVIV*) SvANY(sv))->xiv_iv
# define SvUVX(sv) ((XPVUV*) SvANY(sv))->xuv_uv
# define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_nv
(((XPV*) SvANY(sv))->xpv_cur = (val)); } STMT_END
#define SvLEN_set(sv, val) \
STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
+ assert(!isGV_with_GP(sv)); \
(((XPV*) SvANY(sv))->xpv_len = (val)); } STMT_END
#define SvEND_set(sv, val) \
STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
#define boolSV(b) ((b) ? &PL_sv_yes : &PL_sv_no)
#define isGV(sv) (SvTYPE(sv) == SVt_PVGV)
+/* If I give every macro argument a different name, then there won't be bugs
+ where nested macros get confused. Been there, done that. */
+#define isGV_with_GP(pwadak) \
+ (((SvFLAGS(pwadak) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM) \
+ && (SvTYPE(pwadak) == SVt_PVGV || SvTYPE(pwadak) == SVt_PVLV))
#define SvGROW(sv,len) (SvLEN(sv) < (len) ? sv_grow(sv,len) : SvPVX(sv))
#define SvGROW_mutable(sv,len) \