/* gv.c
*
* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- * 2000, 2001, 2002, 2003, 2004, by Larry Wall and others
+ * 2000, 2001, 2002, 2003, 2004, 2005, 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.
#define PERL_IN_GV_C
#include "perl.h"
+static const char S_autoload[] = "AUTOLOAD";
+static const STRLEN S_autolen = sizeof(S_autoload)-1;
+
GV *
Perl_gv_AVadd(pTHX_ register GV *gv)
{
void
Perl_gv_init(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, int multi)
{
+ dVAR;
register GP *gp;
- bool doproto = SvTYPE(gv) > SVt_NULL;
- char *proto = (doproto && SvPOK(gv)) ? SvPVX(gv) : NULL;
+ const bool doproto = SvTYPE(gv) > SVt_NULL;
+ const char * const proto = (doproto && SvPOK(gv)) ? SvPVX_const(gv) : NULL;
sv_upgrade((SV*)gv, SVt_PVGV);
if (SvLEN(gv)) {
if (proto) {
- SvPVX(gv) = NULL;
- SvLEN(gv) = 0;
+ SvPV_set(gv, NULL);
+ SvLEN_set(gv, 0);
SvPOK_off(gv);
} else
- Safefree(SvPVX(gv));
+ Safefree(SvPVX_const(gv));
}
Newz(602, gp, 1, GP);
GvGP(gv) = gp_ref(gp);
GvSV(gv) = NEWSV(72,0);
GvLINE(gv) = CopLINE(PL_curcop);
- GvFILE(gv) = CopFILE(PL_curcop) ? CopFILE(PL_curcop) : "";
+ /* XXX Ideally this cast would be replaced with a change to const char*
+ in the struct. */
+ GvFILE(gv) = CopFILE(PL_curcop) ? CopFILE(PL_curcop) : (char *) "";
GvCVGEN(gv) = 0;
GvEGV(gv) = gv;
sv_magic((SV*)gv, (SV*)gv, PERL_MAGIC_glob, Nullch, 0);
GV* gv;
GV** gvp;
CV* cv;
+ const char *hvname;
/* UNIVERSAL methods should be callable without a stash */
if (!stash) {
return 0;
}
- if (!HvNAME(stash))
+ hvname = HvNAME_get(stash);
+ if (!hvname)
Perl_croak(aTHX_
"Can't use anonymous symbol table for method lookup");
if ((level > 100) || (level < -100))
Perl_croak(aTHX_ "Recursive inheritance detected while looking for method '%s' in package '%s'",
- name, HvNAME(stash));
+ name, hvname);
- DEBUG_o( Perl_deb(aTHX_ "Looking for method %s in package %s\n",name,HvNAME(stash)) );
+ DEBUG_o( Perl_deb(aTHX_ "Looking for method %s in package %s\n",name,hvname) );
gvp = (GV**)hv_fetch(stash, name, len, (level >= 0));
if (!gvp)
/* create and re-create @.*::SUPER::ISA on demand */
if (!av || !SvMAGIC(av)) {
- char* packname = HvNAME(stash);
- STRLEN packlen = strlen(packname);
+ /* FIXME - get this from the symtab magic. */
+ STRLEN packlen = strlen(hvname);
- if (packlen >= 7 && strEQ(packname + packlen - 7, "::SUPER")) {
+ if (packlen >= 7 && strEQ(hvname + packlen - 7, "::SUPER")) {
HV* basestash;
packlen -= 7;
- basestash = gv_stashpvn(packname, packlen, TRUE);
+ basestash = gv_stashpvn(hvname, packlen, TRUE);
gvp = (GV**)hv_fetch(basestash, "ISA", 3, FALSE);
if (gvp && (gv = *gvp) != (GV*)&PL_sv_undef && (av = GvAV(gv))) {
gvp = (GV**)hv_fetch(stash, "ISA", 3, TRUE);
if (!gvp || !(gv = *gvp))
- Perl_croak(aTHX_ "Cannot create %s::ISA", HvNAME(stash));
+ Perl_croak(aTHX_ "Cannot create %s::ISA", hvname);
if (SvTYPE(gv) != SVt_PVGV)
gv_init(gv, stash, "ISA", 3, TRUE);
SvREFCNT_dec(GvAV(gv));
if (!basestash) {
if (ckWARN(WARN_MISC))
Perl_warner(aTHX_ packWARN(WARN_MISC), "Can't locate package %"SVf" for @%s::ISA",
- sv, HvNAME(stash));
+ sv, hvname);
continue;
}
gv = gv_fetchmeth(basestash, name, len,
GV *gv = gv_fetchmeth(stash, name, len, level);
if (!gv) {
- char autoload[] = "AUTOLOAD";
- STRLEN autolen = sizeof(autoload)-1;
CV *cv;
GV **gvp;
if (!stash)
return Nullgv; /* UNIVERSAL::AUTOLOAD could cause trouble */
- if (len == autolen && strnEQ(name, autoload, autolen))
+ if (len == S_autolen && strnEQ(name, S_autoload, S_autolen))
return Nullgv;
- if (!(gv = gv_fetchmeth(stash, autoload, autolen, FALSE)))
+ if (!(gv = gv_fetchmeth(stash, S_autoload, S_autolen, FALSE)))
return Nullgv;
cv = GvCV(gv);
if (!(CvROOT(cv) || CvXSUB(cv)))
SV *tmpstr = sv_2mortal(Perl_newSVpvf(aTHX_ "%s::SUPER",
CopSTASHPV(PL_curcop)));
/* __PACKAGE__::SUPER stash should be autovivified */
- stash = gv_stashpvn(SvPVX(tmpstr), SvCUR(tmpstr), TRUE);
+ stash = gv_stashpvn(SvPVX_const(tmpstr), SvCUR(tmpstr), TRUE);
DEBUG_o( Perl_deb(aTHX_ "Treating %s as %s::%s\n",
- origname, HvNAME(stash), name) );
+ origname, HvNAME_get(stash), name) );
}
else {
/* don't autovifify if ->NoSuchStash::method */
GV*
Perl_gv_autoload4(pTHX_ HV *stash, const char *name, STRLEN len, I32 method)
{
- char autoload[] = "AUTOLOAD";
- STRLEN autolen = sizeof(autoload)-1;
+ dVAR;
GV* gv;
CV* cv;
HV* varstash;
GV* vargv;
SV* varsv;
- char *packname = "";
+ const char *packname = "";
- if (len == autolen && strnEQ(name, autoload, autolen))
+ if (len == S_autolen && strnEQ(name, S_autoload, S_autolen))
return Nullgv;
if (stash) {
if (SvTYPE(stash) < SVt_PVHV) {
stash = Nullhv;
}
else {
- packname = HvNAME(stash);
+ packname = HvNAME_get(stash);
}
}
- if (!(gv = gv_fetchmeth(stash, autoload, autolen, FALSE)))
+ if (!(gv = gv_fetchmeth(stash, S_autoload, S_autolen, FALSE)))
return Nullgv;
cv = GvCV(gv);
* pass along the same data via some unused fields in the CV
*/
CvSTASH(cv) = stash;
- SvPVX(cv) = (char *)name; /* cast to lose constness warning */
- SvCUR(cv) = len;
+ SvPV_set(cv, (char *)name); /* cast to lose constness warning */
+ SvCUR_set(cv, len);
return gv;
}
* original package to look up $AUTOLOAD.
*/
varstash = GvSTASH(CvGV(cv));
- vargv = *(GV**)hv_fetch(varstash, autoload, autolen, TRUE);
+ vargv = *(GV**)hv_fetch(varstash, S_autoload, S_autolen, TRUE);
ENTER;
if (!isGV(vargv))
- gv_init(vargv, varstash, autoload, autolen, FALSE);
+ gv_init(vargv, varstash, S_autoload, S_autolen, FALSE);
LEAVE;
varsv = GvSV(vargv);
sv_setpv(varsv, packname);
STATIC void
S_require_errno(pTHX_ GV *gv)
{
+ dVAR;
HV* stash = gv_stashpvn("Errno",5,FALSE);
if (!stash || !(gv_fetchmethod(stash, "TIEHASH"))) {
if (!GvHV(tmpgv))
GvHV(tmpgv) = newHV();
stash = GvHV(tmpgv);
- if (!HvNAME(stash))
- HvNAME(stash) = savepv(name);
+ if (!HvNAME_get(stash))
+ Perl_hv_name_set(aTHX_ stash, name, namelen, 0);
return stash;
}
HV*
Perl_gv_stashsv(pTHX_ SV *sv, I32 create)
{
- register char *ptr;
STRLEN len;
- ptr = SvPV(sv,len);
+ const char *ptr = SvPV(sv,len);
return gv_stashpvn(ptr, len, create);
}
GV *
-Perl_gv_fetchpv(pTHX_ const char *nambeg, I32 add, I32 sv_type)
+Perl_gv_fetchpv(pTHX_ const char *nambeg, I32 add, I32 sv_type) {
+ return gv_fetchpvn_flags(nambeg, strlen(nambeg), add, sv_type);
+}
+
+GV *
+Perl_gv_fetchsv(pTHX_ SV *name, I32 flags, I32 sv_type) {
+ STRLEN len;
+ const char *nambeg = SvPV(name, len);
+ return gv_fetchpvn_flags(nambeg, len, flags | SvUTF8(name), sv_type);
+}
+
+GV *
+Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
+ I32 sv_type)
{
register const char *name = nambeg;
register GV *gv = 0;
I32 len;
register const char *namend;
HV *stash = 0;
+ const I32 add = flags & ~SVf_UTF8;
+ (void)full_len;
if (*name == '*' && isALPHA(name[1])) /* accidental stringify on a GV? */
name++;
if (!(stash = GvHV(gv)))
stash = GvHV(gv) = newHV();
- if (!HvNAME(stash))
- HvNAME(stash) = savepvn(nambeg, namend - nambeg);
+ if (!HvNAME_get(stash))
+ Perl_hv_name_set(aTHX_ stash, nambeg, namend - nambeg, 0);
}
if (*namend == ':')
/* set up magic where warranted */
if (len > 1) {
+#ifndef EBCDIC
if (*name > 'V' ) {
/* Nothing else to do.
The compiler will probably turn the switch statement into a
branch table. Make sure we avoid even that small overhead for
the common case of lower case variable names. */
- } else {
+ } else
+#endif
+ {
const char *name2 = name + 1;
switch (*name) {
case 'A':
if ((add & GV_ADDMULTI) && strEQ(nambeg,"AnyDBM_File::ISA")
&& AvFILLp(av) == -1)
{
- char *pname;
+ const char *pname;
av_push(av, newSVpvn(pname = "NDBM_File",9));
gv_stashpvn(pname, 9, TRUE);
av_push(av, newSVpvn(pname = "DB_File",7));
if (strEQ(name2, "ERSION"))
GvMULTI_on(gv);
break;
+ case '\003': /* $^CHILD_ERROR_NATIVE */
+ if (strEQ(name2, "HILD_ERROR_NATIVE"))
+ goto magicalize;
+ break;
case '\005': /* $^ENCODING */
if (strEQ(name2, "NCODING"))
goto magicalize;
if (strEQ(name2, "AINT"))
goto ro_magicalize;
break;
- case '\025': /* $^UNICODE */
+ case '\025': /* ${^UNICODE}, ${^UTF8LOCALE} */
if (strEQ(name2, "NICODE"))
goto ro_magicalize;
+ if (strEQ(name2, "TF8LOCALE"))
+ goto ro_magicalize;
break;
case '\027': /* $^WARNING_BITS */
if (strEQ(name2, "ARNING_BITS"))
}
}
}
- } else if (len == 1) {
- /* Names of length 1. */
+ } else {
+ /* Names of length 1. (Or 0. But name is NUL terminated, so that will
+ be case '\0' in this switch statement (ie a default case) */
switch (*name) {
case '&':
case '`':
break;
case '\026': /* $^V */
{
- SV *sv = GvSV(gv);
+ SV * const sv = GvSV(gv);
GvSV(gv) = new_version(PL_patchlevel);
SvREADONLY_on(GvSV(gv));
SvREFCNT_dec(sv);
}
void
-Perl_gv_fullname4(pTHX_ SV *sv, GV *gv, const char *prefix, bool keepmain)
+Perl_gv_fullname4(pTHX_ SV *sv, const GV *gv, const char *prefix, bool keepmain)
{
- char *name;
- HV *hv = GvSTASH(gv);
+ const char *name;
+ const HV * const hv = GvSTASH(gv);
if (!hv) {
SvOK_off(sv);
return;
}
sv_setpv(sv, prefix ? prefix : "");
- name = HvNAME(hv);
+ name = HvNAME_get(hv);
if (!name)
name = "__ANON__";
}
void
-Perl_gv_fullname3(pTHX_ SV *sv, GV *gv, const char *prefix)
+Perl_gv_fullname3(pTHX_ SV *sv, const GV *gv, const char *prefix)
{
gv_fullname4(sv, gv, prefix, TRUE);
}
void
-Perl_gv_efullname4(pTHX_ SV *sv, GV *gv, const char *prefix, bool keepmain)
+Perl_gv_efullname4(pTHX_ SV *sv, const GV *gv, const char *prefix, bool keepmain)
{
- GV *egv = GvEGV(gv);
+ const GV *egv = GvEGV(gv);
if (!egv)
egv = gv;
gv_fullname4(sv, egv, prefix, keepmain);
}
void
-Perl_gv_efullname3(pTHX_ SV *sv, GV *gv, const char *prefix)
+Perl_gv_efullname3(pTHX_ SV *sv, const GV *gv, const char *prefix)
{
gv_efullname4(sv, gv, prefix, TRUE);
}
-/* XXX compatibility with versions <= 5.003. */
+/* compatibility with versions <= 5.003. */
void
-Perl_gv_fullname(pTHX_ SV *sv, GV *gv)
+Perl_gv_fullname(pTHX_ SV *sv, const GV *gv)
{
- gv_fullname3(sv, gv, sv == (SV*)gv ? "*" : "");
+ gv_fullname3(sv, gv, sv == (const SV*)gv ? "*" : "");
}
-/* XXX compatibility with versions <= 5.003. */
+/* compatibility with versions <= 5.003. */
void
-Perl_gv_efullname(pTHX_ SV *sv, GV *gv)
+Perl_gv_efullname(pTHX_ SV *sv, const GV *gv)
{
- gv_efullname3(sv, gv, sv == (SV*)gv ? "*" : "");
+ gv_efullname3(sv, gv, sv == (const SV*)gv ? "*" : "");
}
IO *
Perl_newIO(pTHX)
{
- IO *io;
GV *iogv;
+ IO * const io = (IO*)NEWSV(0,0);
- io = (IO*)NEWSV(0,0);
sv_upgrade((SV *)io,SVt_PVIO);
SvREFCNT(io) = 1;
SvOBJECT_on(io);
/* unless exists($main::{FileHandle}) and defined(%main::FileHandle::) */
if (!(iogv && GvHV(iogv) && HvARRAY(GvHV(iogv))))
iogv = gv_fetchpv("IO::Handle::", TRUE, SVt_PVHV);
- SvSTASH(io) = (HV*)SvREFCNT_inc(GvHV(iogv));
+ SvSTASH_set(io, (HV*)SvREFCNT_inc(GvHV(iogv)));
return io;
}
void
Perl_gv_check(pTHX_ HV *stash)
{
- register HE *entry;
register I32 i;
- register GV *gv;
- HV *hv;
if (!HvARRAY(stash))
return;
for (i = 0; i <= (I32) HvMAX(stash); i++) {
+ const HE *entry;
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
+ register GV *gv;
+ HV *hv;
if (HeKEY(entry)[HeKLEN(entry)-1] == ':' &&
(gv = (GV*)HeVAL(entry)) && isGV(gv) && (hv = GvHV(gv)))
{
gv_check(hv); /* nested package */
}
else if (isALPHA(*HeKEY(entry))) {
- char *file;
+ const char *file;
gv = (GV*)HeVAL(entry);
if (SvTYPE(gv) != SVt_PVGV || GvMULTI(gv))
continue;
}
CopLINE_set(PL_curcop, GvLINE(gv));
#ifdef USE_ITHREADS
- CopFILE(PL_curcop) = file; /* set for warning */
+ CopFILE(PL_curcop) = (char *)file; /* set for warning */
#else
CopFILEGV(PL_curcop) = gv_fetchfile(file);
#endif
Perl_warner(aTHX_ packWARN(WARN_ONCE),
"Name \"%s::%s\" used only once: possible typo",
- HvNAME(stash), GvNAME(gv));
+ HvNAME_get(stash), GvNAME(gv));
}
}
}
}
GV *
-Perl_newGVgen(pTHX_ char *pack)
+Perl_newGVgen(pTHX_ const char *pack)
{
return gv_fetchpv(Perl_form(aTHX_ "%s::_GEN_%ld", pack, (long)PL_gensym++),
TRUE, SVt_PVGV);
if (gp->gp_sv) SvREFCNT_dec(gp->gp_sv);
if (gp->gp_av) SvREFCNT_dec(gp->gp_av);
- if (gp->gp_hv) {
- if (PL_stashcache && HvNAME(gp->gp_hv))
- hv_delete(PL_stashcache,
- HvNAME(gp->gp_hv), strlen(HvNAME(gp->gp_hv)),
- G_DISCARD);
- SvREFCNT_dec(gp->gp_hv);
+ /* FIXME - another reference loop GV -> symtab -> GV ?
+ Somehow gp->gp_hv can end up pointing at freed garbage. */
+ if (gp->gp_hv && SvTYPE(gp->gp_hv) == SVt_PVHV) {
+ /* FIXME strlen HvNAME */
+ const char *hvname = HvNAME_get(gp->gp_hv);
+ if (PL_stashcache && hvname)
+ hv_delete(PL_stashcache, hvname, strlen(hvname), G_DISCARD);
+ SvREFCNT_dec(gp->gp_hv);
}
if (gp->gp_io) SvREFCNT_dec(gp->gp_io);
if (gp->gp_cv) SvREFCNT_dec(gp->gp_cv);
Perl_magic_freeovrld(pTHX_ SV *sv, MAGIC *mg)
{
AMT *amtp = (AMT*)mg->mg_ptr;
+ (void)sv;
+
if (amtp && AMT_AMAGIC(amtp)) {
int i;
for (i = 1; i < NofAMmeth; i++) {
return (bool)AMT_OVERLOADED(amtp);
sv_unmagic((SV*)stash, PERL_MAGIC_overload_table);
- DEBUG_o( Perl_deb(aTHX_ "Recalcing overload magic in package %s\n",HvNAME(stash)) );
+ DEBUG_o( Perl_deb(aTHX_ "Recalcing overload magic in package %s\n",HvNAME_get(stash)) );
Zero(&amt,1,AMT);
amt.was_ok_am = PL_amagic_generation;
for (i = 1; i < lim; i++)
amt.table[i] = Nullcv;
for (; i < NofAMmeth; i++) {
- char *cooky = (char*)PL_AMG_names[i];
+ const char *cooky = PL_AMG_names[i];
/* Human-readable form, for debugging: */
- char *cp = (i >= DESTROY_amg ? cooky : AMG_id2name(i));
- STRLEN l = strlen(cooky);
+ const char *cp = (i >= DESTROY_amg ? cooky : AMG_id2name(i));
+ const STRLEN l = strlen(cooky);
DEBUG_o( Perl_deb(aTHX_ "Checking overloading of `%s' in package `%.256s'\n",
- cp, HvNAME(stash)) );
+ cp, HvNAME_get(stash)) );
/* don't fill the cache while looking up!
Creation of inheritance stubs in intermediate packages may
conflict with the logic of runtime method substitution.
gv = Perl_gv_fetchmeth(aTHX_ stash, cooky, l, -1);
cv = 0;
if (gv && (cv = GvCV(gv))) {
+ const char *hvname;
if (GvNAMELEN(CvGV(cv)) == 3 && strEQ(GvNAME(CvGV(cv)), "nil")
- && strEQ(HvNAME(GvSTASH(CvGV(cv))), "overload")) {
+ && strEQ(hvname = HvNAME_get(GvSTASH(CvGV(cv))), "overload")) {
/* This is a hack to support autoloading..., while
knowing *which* methods were declared as overloaded. */
/* GvSV contains the name of the method. */
DEBUG_o( Perl_deb(aTHX_ "Resolving method `%"SVf256\
"' for overloaded `%s' in package `%.256s'\n",
- GvSV(gv), cp, HvNAME(stash)) );
+ GvSV(gv), cp, hvname) );
if (!SvPOK(GvSV(gv))
- || !(ngv = gv_fetchmethod_autoload(stash, SvPVX(GvSV(gv)),
+ || !(ngv = gv_fetchmethod_autoload(stash, SvPVX_const(GvSV(gv)),
FALSE)))
{
/* Can be an import stub (created by `can'). */
SV *gvsv = GvSV(gv);
- const char *name = SvPOK(gvsv) ? SvPVX(gvsv) : "???";
+ const char *name = 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(stash));
+ name, cp, hvname);
}
cv = GvCV(gv = ngv);
}
DEBUG_o( Perl_deb(aTHX_ "Overloading `%s' in package `%.256s' via `%.256s::%.256s' \n",
- cp, HvNAME(stash), HvNAME(GvSTASH(CvGV(cv))),
+ cp, HvNAME_get(stash), HvNAME_get(GvSTASH(CvGV(cv))),
GvNAME(CvGV(cv))) );
filled = 1;
if (i < DESTROY_amg)
{
MAGIC *mg;
AMT *amtp;
- CV *ret;
- if (!stash || !HvNAME(stash))
+ if (!stash || !HvNAME_get(stash))
return Nullcv;
mg = mg_find((SV*)stash, PERL_MAGIC_overload_table);
if (!mg) {
|| amtp->was_ok_sub != PL_sub_generation )
goto do_update;
if (AMT_AMAGIC(amtp)) {
- ret = amtp->table[id];
+ CV * const ret = amtp->table[id];
if (ret && isGV(ret)) { /* Autoloading stab */
/* Passing it through may have resulted in a warning
"Inherited AUTOLOAD for a non-method deprecated", since
our caller is going through a function call, not a method call.
So return the CV for AUTOLOAD, setting $AUTOLOAD. */
- GV *gv = gv_fetchmethod(stash, (char*)PL_AMG_names[id]);
+ GV *gv = gv_fetchmethod(stash, PL_AMG_names[id]);
if (gv && GvCV(gv))
return GvCV(gv);
SV*
Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
{
+ dVAR;
MAGIC *mg;
CV *cv=NULL;
CV **cvp=NULL, **ocvp=NULL;
case string_amg:
(void)((cv = cvp[off=numer_amg]) || (cv = cvp[off=bool__amg]));
break;
- case not_amg:
- (void)((cv = cvp[off=bool__amg])
- || (cv = cvp[off=numer_amg])
- || (cv = cvp[off=string_amg]));
- postpr = 1;
- break;
+ case not_amg:
+ (void)((cv = cvp[off=bool__amg])
+ || (cv = cvp[off=numer_amg])
+ || (cv = cvp[off=string_amg]));
+ postpr = 1;
+ break;
case copy_amg:
{
/*
*/
SV* newref = newSVsv(tmpRef);
SvOBJECT_on(newref);
- SvSTASH(newref) = (HV*)SvREFCNT_inc(SvSTASH(tmpRef));
+ SvSTASH_set(newref, (HV*)SvREFCNT_inc(SvSTASH(tmpRef)));
return newref;
}
}
"in overloaded package ":
"has no overloaded magic",
SvAMAGIC(left)?
- HvNAME(SvSTASH(SvRV(left))):
+ HvNAME_get(SvSTASH(SvRV(left))):
"",
SvAMAGIC(right)?
",\n\tright argument in overloaded package ":
? ""
: ",\n\tright argument has no overloaded magic"),
SvAMAGIC(right)?
- HvNAME(SvSTASH(SvRV(right))):
+ HvNAME_get(SvSTASH(SvRV(right))):
""));
if (amtp && amtp->fallback >= AMGfallYES) {
- DEBUG_o( Perl_deb(aTHX_ "%s", SvPVX(msg)) );
+ DEBUG_o( Perl_deb(aTHX_ "%s", SvPVX_const(msg)) );
} else {
Perl_croak(aTHX_ "%"SVf, msg);
}
flags & AMGf_unary? "" :
lr==1 ? " for right argument": " for left argument",
flags & AMGf_unary? " for argument" : "",
- stash ? HvNAME(stash) : "null",
+ stash ? HvNAME_get(stash) : "null",
fl? ",\n\tassignment variant used": "") );
}
#endif
dSP;
BINOP myop;
SV* res;
- bool oldcatch = CATCH_GET;
+ const bool oldcatch = CATCH_GET;
CATCH_SET(TRUE);
Zero(&myop, 1, BINOP);
CATCH_SET(oldcatch);
if (postpr) {
- int ans=0;
+ int ans;
switch (method) {
case le_amg:
case sle_amg:
SvSetSV(left,res); return left;
case not_amg:
ans=!SvTRUE(res); break;
+ default:
+ ans=0; break;
}
return boolSV(ans);
} else if (method==copy_amg) {
}
/*
+=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 *temp = SvPV(name, len);
+ return is_gv_magical(temp, len, flags);
+}
+
+/*
=for apidoc is_gv_magical
Returns C<TRUE> if given the name of a magical GV.
C<flags> is not used at present but available for future extension to
allow selecting particular classes of magical variable.
+Currently assumes that C<name> is NUL terminated (as well as len being valid).
+This assumption is met by all callers within the perl core, which all pass
+pointers returned by SvPV.
+
=cut
*/
bool
-Perl_is_gv_magical(pTHX_ char *name, STRLEN len, U32 flags)
+Perl_is_gv_magical(pTHX_ const char *name, STRLEN len, U32 flags)
{
- if (!len)
- return FALSE;
-
- switch (*name) {
- case 'I':
- if (len == 3 && strEQ(name, "ISA"))
- goto yes;
- break;
- case 'O':
- if (len == 8 && strEQ(name, "OVERLOAD"))
- goto yes;
- break;
- case 'S':
- if (len == 3 && strEQ(name, "SIG"))
- goto yes;
- break;
- case '\017': /* $^O & $^OPEN */
- if (len == 1
- || (len == 4 && strEQ(name, "\017PEN")))
- {
- goto yes;
- }
- break;
- case '\025':
- if (len > 1 && strEQ(name, "\025NICODE"))
- goto yes;
- case '\027': /* $^W & $^WARNING_BITS */
- if (len == 1
- || (len == 12 && strEQ(name, "\027ARNING_BITS"))
- )
+ (void)flags;
+ if (len > 1) {
+ const char *name1 = name + 1;
+ switch (*name) {
+ case 'I':
+ if (len == 3 && name1[1] == 'S' && name[2] == 'A')
+ goto yes;
+ break;
+ case 'O':
+ if (len == 8 && strEQ(name1, "VERLOAD"))
+ goto yes;
+ break;
+ case 'S':
+ if (len == 3 && name[1] == 'I' && name[2] == 'G')
+ goto yes;
+ break;
+ /* Using ${^...} variables is likely to be sufficiently rare that
+ it seems sensible to avoid the space hit of also checking the
+ length. */
+ case '\017': /* ${^OPEN} */
+ if (strEQ(name1, "PEN"))
+ goto yes;
+ break;
+ case '\024': /* ${^TAINT} */
+ if (strEQ(name1, "AINT"))
+ goto yes;
+ break;
+ case '\025': /* ${^UNICODE} */
+ if (strEQ(name1, "NICODE"))
+ goto yes;
+ if (strEQ(name1, "TF8LOCALE"))
+ goto yes;
+ break;
+ case '\027': /* ${^WARNING_BITS} */
+ if (strEQ(name1, "ARNING_BITS"))
+ goto yes;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
{
- goto yes;
- }
- break;
-
- case '&':
- case '`':
- case '\'':
- case ':':
- case '?':
- case '!':
- case '-':
- case '#':
- case '[':
- case '^':
- case '~':
- case '=':
- case '%':
- case '.':
- case '(':
- case ')':
- case '<':
- case '>':
- case ',':
- case '\\':
- case '/':
- case '|':
- case '+':
- case ';':
- case ']':
- case '\001': /* $^A */
- case '\003': /* $^C */
- case '\004': /* $^D */
- case '\005': /* $^E */
- case '\006': /* $^F */
- case '\010': /* $^H */
- case '\011': /* $^I, NOT \t in EBCDIC */
- case '\014': /* $^L */
- case '\016': /* $^N */
- case '\020': /* $^P */
- case '\023': /* $^S */
- case '\026': /* $^V */
- if (len == 1)
- goto yes;
- break;
- case '\024': /* $^T, ${^TAINT} */
- if (len == 1 || strEQ(name, "\024AINT"))
- goto yes;
- break;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- if (len > 1) {
- char *end = name + len;
+ const char *end = name + len;
while (--end > name) {
if (!isDIGIT(*end))
return FALSE;
}
+ goto yes;
+ }
+ }
+ } else {
+ /* Because we're already assuming that name is NUL terminated
+ below, we can treat an empty name as "\0" */
+ switch (*name) {
+ case '&':
+ case '`':
+ case '\'':
+ case ':':
+ case '?':
+ case '!':
+ case '-':
+ case '#':
+ case '[':
+ case '^':
+ case '~':
+ case '=':
+ case '%':
+ case '.':
+ case '(':
+ case ')':
+ case '<':
+ case '>':
+ case ',':
+ case '\\':
+ case '/':
+ case '|':
+ case '+':
+ case ';':
+ case ']':
+ case '\001': /* $^A */
+ case '\003': /* $^C */
+ case '\004': /* $^D */
+ case '\005': /* $^E */
+ case '\006': /* $^F */
+ case '\010': /* $^H */
+ case '\011': /* $^I, NOT \t in EBCDIC */
+ case '\014': /* $^L */
+ case '\016': /* $^N */
+ case '\017': /* $^O */
+ case '\020': /* $^P */
+ case '\023': /* $^S */
+ case '\024': /* $^T */
+ case '\026': /* $^V */
+ case '\027': /* $^W */
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ yes:
+ return TRUE;
+ default:
+ break;
}
- yes:
- return TRUE;
- default:
- break;
}
return FALSE;
}
+
+/*
+ * Local variables:
+ * c-indentation-style: bsd
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ *
+ * ex: set ts=8 sts=4 sw=4 noet:
+ */