/* gv.c
*
- * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others
+ * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ * 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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.
/*
* 'Mercy!' cried Gandalf. 'If the giving of information is to be the cure
- * of your inquisitiveness, I shall spend all the rest of my days answering
+ * of your inquisitiveness, I shall spend all the rest of my days in answering
* you. What more do you want to know?'
* 'The names of all the stars, and of all living things, and the whole
* history of Middle-earth and Over-heaven and of the Sundering Seas,'
* laughed Pippin.
+ *
+ * [p.599 of _The Lord of the Rings_, III/xi: "The PalantÃr"]
*/
/*
static const char S_autoload[] = "AUTOLOAD";
static const STRLEN S_autolen = sizeof(S_autoload)-1;
-
-#ifdef PERL_DONT_CREATE_GVSV
-GV *
-Perl_gv_SVadd(pTHX_ GV *gv)
-{
- PERL_ARGS_ASSERT_GV_SVADD;
-
- if (!gv || SvTYPE((SV*)gv) != SVt_PVGV)
- Perl_croak(aTHX_ "Bad symbol for scalar");
- if (!GvSV(gv))
- GvSV(gv) = newSV(0);
- return gv;
-}
-#endif
-
-GV *
-Perl_gv_AVadd(pTHX_ register GV *gv)
-{
- PERL_ARGS_ASSERT_GV_AVADD;
-
- if (!gv || SvTYPE((SV*)gv) != SVt_PVGV)
- Perl_croak(aTHX_ "Bad symbol for array");
- if (!GvAV(gv))
- GvAV(gv) = newAV();
- return gv;
-}
-
-GV *
-Perl_gv_HVadd(pTHX_ register GV *gv)
-{
- PERL_ARGS_ASSERT_GV_HVADD;
-
- if (!gv || SvTYPE((SV*)gv) != SVt_PVGV)
- Perl_croak(aTHX_ "Bad symbol for hash");
- if (!GvHV(gv))
- GvHV(gv) = newHV();
- return gv;
-}
-
GV *
-Perl_gv_IOadd(pTHX_ register GV *gv)
+Perl_gv_add_by_type(pTHX_ GV *gv, svtype type)
{
- dVAR;
-
- PERL_ARGS_ASSERT_GV_IOADD;
-
- if (!gv || SvTYPE((SV*)gv) != SVt_PVGV) {
-
- /*
- * if it walks like a dirhandle, then let's assume that
- * this is a dirhandle.
- */
- const char * const fh =
- PL_op->op_type == OP_READDIR ||
- PL_op->op_type == OP_TELLDIR ||
- PL_op->op_type == OP_SEEKDIR ||
- PL_op->op_type == OP_REWINDDIR ||
- PL_op->op_type == OP_CLOSEDIR ?
- "dirhandle" : "filehandle";
- Perl_croak(aTHX_ "Bad symbol for %s", fh);
+ SV **where;
+
+ if (!gv || SvTYPE((const SV *)gv) != SVt_PVGV) {
+ const char *what;
+ if (type == SVt_PVIO) {
+ /*
+ * if it walks like a dirhandle, then let's assume that
+ * this is a dirhandle.
+ */
+ what = PL_op->op_type == OP_READDIR ||
+ PL_op->op_type == OP_TELLDIR ||
+ PL_op->op_type == OP_SEEKDIR ||
+ PL_op->op_type == OP_REWINDDIR ||
+ PL_op->op_type == OP_CLOSEDIR ?
+ "dirhandle" : "filehandle";
+ /* diag_listed_as: Bad symbol for filehandle */
+ } else if (type == SVt_PVHV) {
+ what = "hash";
+ } else {
+ what = type == SVt_PVAV ? "array" : "scalar";
+ }
+ Perl_croak(aTHX_ "Bad symbol for %s", what);
}
- if (!GvIOp(gv)) {
-#ifdef GV_UNIQUE_CHECK
- if (GvUNIQUE(gv)) {
- Perl_croak(aTHX_ "Bad symbol for filehandle (GV is unique)");
- }
-#endif
- GvIOp(gv) = newIO();
+ if (type == SVt_PVHV) {
+ where = (SV **)&GvHV(gv);
+ } else if (type == SVt_PVAV) {
+ where = (SV **)&GvAV(gv);
+ } else if (type == SVt_PVIO) {
+ where = (SV **)&GvIOp(gv);
+ } else {
+ where = &GvSV(gv);
}
+
+ if (!*where)
+ *where = newSV_type(type);
return gv;
}
#else
sv_setpvn(GvSV(gv), name, namelen);
#endif
- if (PERLDB_LINE)
+ if (PERLDB_LINE || PERLDB_SAVESRC)
hv_magic(GvHVn(gv_AVadd(gv)), NULL, PERL_MAGIC_dbfile);
}
if (tmpbuf != smallbuf)
if (old_type < SVt_PVGV) {
if (old_type >= SVt_PV)
SvCUR_set(gv, 0);
- sv_upgrade((SV*)gv, SVt_PVGV);
+ sv_upgrade(MUTABLE_SV(gv), SVt_PVGV);
}
if (SvLEN(gv)) {
if (proto) {
GvGP(gv) = Perl_newGP(aTHX_ gv);
GvSTASH(gv) = stash;
if (stash)
- Perl_sv_add_backref(aTHX_ (SV*)stash, (SV*)gv);
+ Perl_sv_add_backref(aTHX_ MUTABLE_SV(stash), MUTABLE_SV(gv));
gv_name_set(gv, name, len, GV_ADD);
if (multi || doproto) /* doproto means it _was_ mentioned */
GvMULTI_on(gv);
CvFILE_set_from_cop(GvCV(gv), PL_curcop);
CvSTASH(GvCV(gv)) = PL_curstash;
if (proto) {
- sv_usepvn_flags((SV*)GvCV(gv), proto, protolen,
+ sv_usepvn_flags(MUTABLE_SV(GvCV(gv)), proto, protolen,
SV_HAS_TRAILING_NUL);
}
}
if (!stash)
return NULL; /* UNIVERSAL::AUTOLOAD could cause trouble */
- if (len == S_autolen && strnEQ(name, S_autoload, S_autolen))
+ if (len == S_autolen && memEQ(name, S_autoload, S_autolen))
return NULL;
if (!(gv = gv_fetchmeth(stash, S_autoload, S_autolen, FALSE)))
return NULL;
gv_init(gv, stash, "ISA", 3, TRUE);
superisa = GvAVn(gv);
GvMULTI_on(gv);
- sv_magic((SV*)superisa, (SV*)gv, PERL_MAGIC_isa, NULL, 0);
+ sv_magic(MUTABLE_SV(superisa), MUTABLE_SV(gv), PERL_MAGIC_isa, NULL, 0);
#ifdef USE_ITHREADS
av_push(superisa, newSVpv(CopSTASHPV(PL_curcop), 0));
#else
return stash;
}
-/* FIXME. If changing this function note the comment in pp_hot's
- S_method_common:
-
- This code tries to figure out just what went wrong with
- gv_fetchmethod. It therefore needs to duplicate a lot of
- the internals of that function. ...
+GV *
+Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
+{
+ PERL_ARGS_ASSERT_GV_FETCHMETHOD_AUTOLOAD;
- I'd guess that with one more flag bit that could all be moved inside
- here.
-*/
+ return gv_fetchmethod_flags(stash, name, autoload ? GV_AUTOLOAD : 0);
+}
+/* Don't merge this yet, as it's likely to get a len parameter, and possibly
+ even a U32 hash */
GV *
-Perl_gv_fetchmethod_autoload(pTHX_ HV *stash, const char *name, I32 autoload)
+Perl_gv_fetchmethod_flags(pTHX_ HV *stash, const char *name, U32 flags)
{
dVAR;
register const char *nend;
const char *nsplit = NULL;
GV* gv;
HV* ostash = stash;
+ const char * const origname = name;
+ SV *const error_report = MUTABLE_SV(stash);
+ const U32 autoload = flags & GV_AUTOLOAD;
+ const U32 do_croak = flags & GV_CROAK;
- PERL_ARGS_ASSERT_GV_FETCHMETHOD_AUTOLOAD;
+ PERL_ARGS_ASSERT_GV_FETCHMETHOD_FLAGS;
- if (stash && SvTYPE(stash) < SVt_PVHV)
+ if (SvTYPE(stash) < SVt_PVHV)
stash = NULL;
+ else {
+ /* The only way stash can become NULL later on is if nsplit is set,
+ which in turn means that there is no need for a SVt_PVHV case
+ the error reporting code. */
+ }
for (nend = name; *nend; nend++) {
- if (*nend == '\'')
+ if (*nend == '\'') {
nsplit = nend;
- else if (*nend == ':' && *(nend + 1) == ':')
- nsplit = ++nend;
+ name = nend + 1;
+ }
+ else if (*nend == ':' && *(nend + 1) == ':') {
+ nsplit = nend++;
+ name = nend + 1;
+ }
}
if (nsplit) {
- const char * const origname = name;
- name = nsplit + 1;
- if (*nsplit == ':')
- --nsplit;
- if ((nsplit - origname) == 5 && strnEQ(origname, "SUPER", 5)) {
+ if ((nsplit - origname) == 5 && memEQ(origname, "SUPER", 5)) {
/* ->SUPER::method should really be looked up in original stash */
SV * const tmpstr = sv_2mortal(Perl_newSVpvf(aTHX_ "%s::SUPER",
CopSTASHPV(PL_curcop)));
gv = gv_fetchmeth(stash, name, nend - name, 0);
if (!gv) {
if (strEQ(name,"import") || strEQ(name,"unimport"))
- gv = (GV*)&PL_sv_yes;
+ gv = MUTABLE_GV(&PL_sv_yes);
else if (autoload)
gv = gv_autoload4(ostash, name, nend - name, TRUE);
+ if (!gv && do_croak) {
+ /* Right now this is exclusively for the benefit of S_method_common
+ in pp_hot.c */
+ if (stash) {
+ Perl_croak(aTHX_
+ "Can't locate object method \"%s\" via package \"%.*s\"",
+ name, (int)HvNAMELEN_get(stash), HvNAME_get(stash));
+ }
+ else {
+ STRLEN packlen;
+ const char *packname;
+
+ if (nsplit) {
+ packlen = nsplit - origname;
+ packname = origname;
+ } else {
+ packname = SvPV_const(error_report, packlen);
+ }
+
+ Perl_croak(aTHX_
+ "Can't locate object method \"%s\" via package \"%.*s\""
+ " (perhaps you forgot to load \"%.*s\"?)",
+ name, (int)packlen, packname, (int)packlen, packname);
+ }
+ }
}
else if (autoload) {
CV* const cv = GvCV(gv);
PERL_ARGS_ASSERT_GV_AUTOLOAD4;
- if (len == S_autolen && strnEQ(name, S_autoload, S_autolen))
+ if (len == S_autolen && memEQ(name, S_autoload, S_autolen))
return NULL;
if (stash) {
if (SvTYPE(stash) < SVt_PVHV) {
- packname = SvPV_const((SV*)stash, packname_len);
+ packname = SvPV_const(MUTABLE_SV(stash), packname_len);
stash = NULL;
}
else {
tmpbuf[len++] = ':';
gvp = (GV**)hv_fetch(stash,tmpbuf,len,add);
gv = gvp ? *gvp : NULL;
- if (gv && gv != (GV*)&PL_sv_undef) {
+ if (gv && gv != (const GV *)&PL_sv_undef) {
if (SvTYPE(gv) != SVt_PVGV)
gv_init(gv, stash, tmpbuf, len, (add & GV_ADDMULTI));
else
}
if (tmpbuf != smallbuf)
Safefree(tmpbuf);
- if (!gv || gv == (GV*)&PL_sv_undef)
+ if (!gv || gv == (const GV *)&PL_sv_undef)
return NULL;
if (!(stash = GvHV(gv)))
name_cursor++;
name = name_cursor;
if (name == name_end)
- return gv ? gv : (GV*)*hv_fetchs(PL_defstash, "main::", TRUE);
+ return gv
+ ? gv : MUTABLE_GV(*hv_fetchs(PL_defstash, "main::", TRUE));
}
}
len = name_cursor - name;
{
gvp = (GV**)hv_fetch(stash,name,len,0);
if (!gvp ||
- *gvp == (GV*)&PL_sv_undef ||
+ *gvp == (const GV *)&PL_sv_undef ||
SvTYPE(*gvp) != SVt_PVGV)
{
stash = NULL;
(sv_type == SVt_PVAV && !GvIMPORTED_AV(*gvp)) ||
(sv_type == SVt_PVHV && !GvIMPORTED_HV(*gvp)) )
{
+ /* diag_listed_as: Variable "%s" is not imported%s */
Perl_warn(aTHX_ "Variable \"%c%s\" is not imported",
sv_type == SVt_PVAV ? '@' :
sv_type == SVt_PVHV ? '%' : '$',
if (USE_UTF8_IN_NAMES)
SvUTF8_on(err);
qerror(err);
- gv = gv_fetchpvn_flags("<none>::", 8, GV_ADDMULTI, SVt_PVHV);
+ gv = gv_fetchpvs("<none>::", GV_ADDMULTI, SVt_PVHV);
if(!gv) {
/* symbol table under destruction */
return NULL;
return NULL;
gvp = (GV**)hv_fetch(stash,name,len,add);
- if (!gvp || *gvp == (GV*)&PL_sv_undef)
+ if (!gvp || *gvp == (const GV *)&PL_sv_undef)
return NULL;
gv = *gvp;
if (SvTYPE(gv) == SVt_PVGV) {
if (strEQ(name2, "SA")) {
AV* const av = GvAVn(gv);
GvMULTI_on(gv);
- sv_magic((SV*)av, (SV*)gv, PERL_MAGIC_isa, NULL, 0);
+ sv_magic(MUTABLE_SV(av), MUTABLE_SV(gv), PERL_MAGIC_isa,
+ NULL, 0);
/* NOTE: No support for tied ISA */
if ((add & GV_ADDMULTI) && strEQ(nambeg,"AnyDBM_File::ISA")
&& AvFILLp(av) == -1)
{
- const char *pname;
- av_push(av, newSVpvn(pname = "NDBM_File",9));
- gv_stashpvn(pname, 9, GV_ADD);
- av_push(av, newSVpvn(pname = "DB_File",7));
- gv_stashpvn(pname, 7, GV_ADD);
- av_push(av, newSVpvn(pname = "GDBM_File",9));
- gv_stashpvn(pname, 9, GV_ADD);
- av_push(av, newSVpvn(pname = "SDBM_File",9));
- gv_stashpvn(pname, 9, GV_ADD);
- av_push(av, newSVpvn(pname = "ODBM_File",9));
- gv_stashpvn(pname, 9, GV_ADD);
+ av_push(av, newSVpvs("NDBM_File"));
+ gv_stashpvs("NDBM_File", GV_ADD);
+ av_push(av, newSVpvs("DB_File"));
+ gv_stashpvs("DB_File", GV_ADD);
+ av_push(av, newSVpvs("GDBM_File"));
+ gv_stashpvs("GDBM_File", GV_ADD);
+ av_push(av, newSVpvs("SDBM_File"));
+ gv_stashpvs("SDBM_File", GV_ADD);
+ av_push(av, newSVpvs("ODBM_File"));
+ gv_stashpvs("ODBM_File", GV_ADD);
}
}
break;
if (strEQ(name2, "IG")) {
HV *hv;
I32 i;
- if (!PL_psig_ptr) {
- Newxz(PL_psig_ptr, SIG_SIZE, SV*);
- Newxz(PL_psig_name, SIG_SIZE, SV*);
+ if (!PL_psig_name) {
+ Newxz(PL_psig_name, 2 * SIG_SIZE, SV*);
Newxz(PL_psig_pend, SIG_SIZE, int);
+ PL_psig_ptr = PL_psig_name + SIG_SIZE;
+ } else {
+ /* I think that the only way to get here is to re-use an
+ embedded perl interpreter, where the previous
+ use didn't clean up fully because
+ PL_perl_destruct_level was 0. I'm not sure that we
+ "support" that, in that I suspect in that scenario
+ there are sufficient other garbage values left in the
+ interpreter structure that something else will crash
+ before we get here. I suspect that this is one of
+ those "doctor, it hurts when I do this" bugs. */
+ Zero(PL_psig_name, 2 * SIG_SIZE, SV*);
+ Zero(PL_psig_pend, SIG_SIZE, int);
}
GvMULTI_on(gv);
hv = GvHVn(gv);
SV * const * const init = hv_fetch(hv, PL_sig_name[i], strlen(PL_sig_name[i]), 1);
if (init)
sv_setsv(*init, &PL_sv_undef);
- PL_psig_ptr[i] = 0;
- PL_psig_name[i] = 0;
- PL_psig_pend[i] = 0;
}
}
break;
GvMULTI_on(gv);
/* If %! has been used, automatically load Errno.pm. */
- sv_magic(GvSVn(gv), (SV*)gv, PERL_MAGIC_sv, name, len);
+ sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, name, len);
/* magicalization must be done before require_tie_mod is called */
if (sv_type == SVt_PVHV || sv_type == SVt_PVGV)
GvMULTI_on(gv); /* no used once warnings here */
{
AV* const av = GvAVn(gv);
- SV* const avc = (*name == '+') ? (SV*)av : NULL;
+ SV* const avc = (*name == '+') ? MUTABLE_SV(av) : NULL;
- sv_magic((SV*)av, avc, PERL_MAGIC_regdata, NULL, 0);
- sv_magic(GvSVn(gv), (SV*)gv, PERL_MAGIC_sv, name, len);
+ sv_magic(MUTABLE_SV(av), avc, PERL_MAGIC_regdata, NULL, 0);
+ sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, name, len);
if (avc)
SvREADONLY_on(GvSVn(gv));
SvREADONLY_on(av);
ro_magicalize:
SvREADONLY_on(GvSVn(gv));
/* FALL THROUGH */
+ case '0':
case '1':
case '2':
case '3':
case ')':
case '<':
case '>':
- case ',':
case '\\':
case '/':
case '\001': /* $^A */
case '\024': /* $^T */
case '\027': /* $^W */
magicalize:
- sv_magic(GvSVn(gv), (SV*)gv, PERL_MAGIC_sv, name, len);
+ sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, name, len);
break;
case '\014': /* $^L */
- sv_setpvn(GvSVn(gv),"\f",1);
+ sv_setpvs(GvSVn(gv),"\f");
PL_formfeed = GvSVn(gv);
break;
case ';':
- sv_setpvn(GvSVn(gv),"\034",1);
+ sv_setpvs(GvSVn(gv),"\034");
break;
case ']':
{
gv_fullname4(sv, egv ? egv : gv, prefix, keepmain);
}
-IO *
-Perl_newIO(pTHX)
-{
- dVAR;
- GV *iogv;
- IO * const io = (IO*)newSV_type(SVt_PVIO);
- /* This used to read SvREFCNT(io) = 1;
- It's not clear why the reference count needed an explicit reset. NWC
- */
- assert (SvREFCNT(io) == 1);
- SvOBJECT_on(io);
- /* Clear the stashcache because a new IO could overrule a package name */
- hv_clear(PL_stashcache);
- iogv = gv_fetchpvs("FileHandle::", 0, SVt_PVHV);
- /* unless exists($main::{FileHandle}) and defined(%main::FileHandle::) */
- if (!(iogv && GvHV(iogv) && HvARRAY(GvHV(iogv))))
- iogv = gv_fetchpvs("IO::Handle::", GV_ADD, SVt_PVHV);
- SvSTASH_set(io, (HV*)SvREFCNT_inc(GvHV(iogv)));
- return io;
-}
-
void
Perl_gv_check(pTHX_ const HV *stash)
{
register GV *gv;
HV *hv;
if (HeKEY(entry)[HeKLEN(entry)-1] == ':' &&
- (gv = (GV*)HeVAL(entry)) && isGV(gv) && (hv = GvHV(gv)))
+ (gv = MUTABLE_GV(HeVAL(entry))) && isGV(gv) && (hv = GvHV(gv)))
{
if (hv != PL_defstash && hv != stash)
gv_check(hv); /* nested package */
}
else if (isALPHA(*HeKEY(entry))) {
const char *file;
- gv = (GV*)HeVAL(entry);
+ gv = MUTABLE_GV(HeVAL(entry));
if (SvTYPE(gv) != SVt_PVGV || GvMULTI(gv))
continue;
file = GvFILE(gv);
for (i = 1; i < NofAMmeth; i++) {
CV * const cv = amtp->table[i];
if (cv) {
- SvREFCNT_dec((SV *) cv);
+ SvREFCNT_dec(MUTABLE_SV(cv));
amtp->table[i] = NULL;
}
}
}
/* Updates and caches the CV's */
+/* Returns:
+ * 1 on success and there is some overload
+ * 0 if there is no overload
+ * -1 if some error occurred and it couldn't croak
+ */
-bool
-Perl_Gv_AMupdate(pTHX_ HV *stash)
+int
+Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
{
dVAR;
- MAGIC* const mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
+ MAGIC* const mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table);
AMT amt;
const struct mro_meta* stash_meta = HvMROMETA(stash);
U32 newgen;
const AMT * const amtp = (AMT*)mg->mg_ptr;
if (amtp->was_ok_am == PL_amagic_generation
&& amtp->was_ok_sub == newgen) {
- return (bool)AMT_OVERLOADED(amtp);
+ return AMT_OVERLOADED(amtp) ? 1 : 0;
}
- sv_unmagic((SV*)stash, PERL_MAGIC_overload_table);
+ sv_unmagic(MUTABLE_SV(stash), PERL_MAGIC_overload_table);
}
DEBUG_o( Perl_deb(aTHX_ "Recalcing overload magic in package %s\n",HvNAME_get(stash)) );
FALSE)))
{
/* Can be an import stub (created by "can"). */
- const char * const name = (gvsv && SvPOK(gvsv)) ? SvPVX_const(gvsv) : "???";
- Perl_croak(aTHX_ "%s method \"%.256s\" overloading \"%s\" "\
- "in package \"%.256s\"",
- (GvCVGEN(gv) ? "Stub found while resolving"
- : "Can't resolve"),
- name, cp, hvname);
+ if (destructing) {
+ return -1;
+ }
+ else {
+ const char * const name = (gvsv && SvPOK(gvsv)) ? SvPVX_const(gvsv) : "???";
+ Perl_croak(aTHX_ "%s method \"%.256s\" overloading \"%s\" "\
+ "in package \"%.256s\"",
+ (GvCVGEN(gv) ? "Stub found while resolving"
+ : "Can't resolve"),
+ name, cp, hvname);
+ }
}
cv = GvCV(gv = ngv);
}
if (i < DESTROY_amg)
have_ovl = 1;
} else if (gv) { /* Autoloaded... */
- cv = (CV*)gv;
+ cv = MUTABLE_CV(gv);
filled = 1;
}
- amt.table[i]=(CV*)SvREFCNT_inc_simple(cv);
+ amt.table[i]=MUTABLE_CV(SvREFCNT_inc_simple(cv));
}
if (filled) {
AMT_AMAGIC_on(&amt);
if (have_ovl)
AMT_OVERLOADED_on(&amt);
- sv_magic((SV*)stash, 0, PERL_MAGIC_overload_table,
+ sv_magic(MUTABLE_SV(stash), 0, PERL_MAGIC_overload_table,
(char*)&amt, sizeof(AMT));
return have_ovl;
}
/* Here we have no table: */
/* no_table: */
AMT_AMAGIC_off(&amt);
- sv_magic((SV*)stash, 0, PERL_MAGIC_overload_table,
+ sv_magic(MUTABLE_SV(stash), 0, PERL_MAGIC_overload_table,
(char*)&amt, sizeof(AMTS));
- return FALSE;
+ return 0;
}
stash_meta = HvMROMETA(stash);
newgen = PL_sub_generation + stash_meta->pkg_gen + stash_meta->cache_gen;
- mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
+ mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table);
if (!mg) {
do_update:
- Gv_AMupdate(stash);
- mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
+ /* If we're looking up a destructor to invoke, we must avoid
+ * that Gv_AMupdate croaks, because we might be dying already */
+ if (Gv_AMupdate(stash, id == DESTROY_amg) == -1) {
+ /* and if it didn't found a destructor, we fall back
+ * to a simpler method that will only look for the
+ * destructor instead of the whole magic */
+ if (id == DESTROY_amg) {
+ GV * const gv = gv_fetchmethod(stash, "DESTROY");
+ if (gv)
+ return GvCV(gv);
+ }
+ return NULL;
+ }
+ mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table);
}
assert(mg);
amtp = (AMT*)mg->mg_ptr;
PERL_ARGS_ASSERT_AMAGIC_CALL;
+ if ( PL_curcop->cop_hints & HINT_NO_AMAGIC ) {
+ SV *lex_mask = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash,
+ 0, "overloading", 11, 0, 0);
+
+ if ( !lex_mask || !SvOK(lex_mask) )
+ /* overloading lexically disabled */
+ return NULL;
+ else if ( lex_mask && SvPOK(lex_mask) ) {
+ /* we have an entry in the hints hash, check if method has been
+ * masked by overloading.pm */
+ STRLEN len;
+ const int offset = method / 8;
+ const int bit = method % 8;
+ char *pv = SvPV(lex_mask, len);
+
+ /* Bit set, so this overloading operator is disabled */
+ if ( (STRLEN)offset < len && pv[offset] & ( 1 << bit ) )
+ return NULL;
+ }
+ }
+
if (!(AMGf_noleft & flags) && SvAMAGIC(left)
&& (stash = SvSTASH(SvRV(left)))
- && (mg = mg_find((SV*)stash, PERL_MAGIC_overload_table))
+ && (mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table))
&& (ocvp = cvp = (AMT_AMAGIC((AMT*)mg->mg_ptr)
? (oamtp = amtp = (AMT*)mg->mg_ptr)->table
: NULL))
Hence we can't use SvAMAGIC_on()
*/
SvFLAGS(newref) |= SVf_AMAGIC;
- SvSTASH_set(newref, (HV*)SvREFCNT_inc(SvSTASH(tmpRef)));
+ SvSTASH_set(newref, MUTABLE_HV(SvREFCNT_inc(SvSTASH(tmpRef))));
return newref;
}
}
break;
case int_amg:
case iter_amg: /* XXXX Eventually should do to_gv. */
+ case ftest_amg: /* XXXX Eventually should do to_gv. */
/* FAIL safe */
return NULL; /* Delegate operation to standard mechanisms. */
break;
if (!cv) goto not_found;
} else if (!(AMGf_noright & flags) && SvAMAGIC(right)
&& (stash = SvSTASH(SvRV(right)))
- && (mg = mg_find((SV*)stash, PERL_MAGIC_overload_table))
+ && (mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table))
&& (cvp = (AMT_AMAGIC((AMT*)mg->mg_ptr)
? (amtp = (AMT*)mg->mg_ptr)->table
: NULL))
PUSHs(newSVpvn_flags(AMG_id2name(method + assignshift),
AMG_id2namelen(method + assignshift), SVs_TEMP));
}
- PUSHs((SV*)cv);
+ PUSHs(MUTABLE_SV(cv));
PUTBACK;
- if ((PL_op = Perl_pp_entersub(aTHX)))
+ if ((PL_op = PL_ppaddr[OP_ENTERSUB](aTHX)))
CALLRUNOPS(aTHX);
LEAVE;
SPAGAIN;
/*
=for apidoc is_gv_magical_sv
-Returns C<TRUE> if given the name of a magical GV. Calls is_gv_magical.
-
-=cut
-*/
-
-bool
-Perl_is_gv_magical_sv(pTHX_ SV *name, U32 flags)
-{
- STRLEN len;
- const char * const temp = SvPV_const(name, len);
-
- PERL_ARGS_ASSERT_IS_GV_MAGICAL_SV;
-
- return is_gv_magical(temp, len, flags);
-}
-
-/*
-=for apidoc is_gv_magical
-
Returns C<TRUE> if given the name of a magical GV.
Currently only useful internally when determining if a GV should be
=cut
*/
+
bool
-Perl_is_gv_magical(pTHX_ const char *name, STRLEN len, U32 flags)
+Perl_is_gv_magical_sv(pTHX_ SV *const name_sv, U32 flags)
{
- PERL_UNUSED_CONTEXT;
- PERL_UNUSED_ARG(flags);
+ STRLEN len;
+ const char *const name = SvPV_const(name_sv, len);
- PERL_ARGS_ASSERT_IS_GV_MAGICAL;
+ PERL_UNUSED_ARG(flags);
+ PERL_ARGS_ASSERT_IS_GV_MAGICAL_SV;
if (len > 1) {
const char * const name1 = name + 1;
switch (*name) {
case 'I':
- if (len == 3 && name1[1] == 'S' && name[2] == 'A')
+ if (len == 3 && name[1] == 'S' && name[2] == 'A')
goto yes;
break;
case 'O':
case ')':
case '<':
case '>':
- case ',':
case '\\':
case '/':
case '|':