/*
=head1 GV Functions
-
A GV is a structure which corresponds to to a Perl typeglob, ie *foo.
It is a structure that holds a pointer to a scalar, an array, a hash etc,
corresponding to $foo, @foo, %foo.
#include "EXTERN.h"
#define PERL_IN_GV_C
#include "perl.h"
-#include "overload.c"
+#include "overload.inc"
#include "keywords.h"
#include "feature.h"
static const char S_autoload[] = "AUTOLOAD";
-static const STRLEN S_autolen = sizeof(S_autoload)-1;
+#define S_autolen (sizeof("AUTOLOAD")-1)
GV *
Perl_gv_add_by_type(pTHX_ GV *gv, svtype type)
}
if (!*where)
+ {
*where = newSV_type(type);
- if (type == SVt_PVAV && GvNAMELEN(gv) == 3
- && strnEQ(GvNAME(gv), "ISA", 3))
- sv_magic(*where, (SV *)gv, PERL_MAGIC_isa, NULL, 0);
+ if (type == SVt_PVAV
+ && memEQs(GvNAME(gv), GvNAMELEN(gv), "ISA"))
+ sv_magic(*where, (SV *)gv, PERL_MAGIC_isa, NULL, 0);
+ }
return gv;
}
Perl_gv_fetchfile_flags(pTHX_ const char *const name, const STRLEN namelen,
const U32 flags)
{
- dVAR;
char smallbuf[128];
char *tmpbuf;
const STRLEN tmplen = namelen + 2;
sv_setpvn(GvSV(gv), name, namelen);
#endif
}
- if ((PERLDB_LINE || PERLDB_SAVESRC) && !GvAV(gv))
- hv_magic(GvHVn(gv_AVadd(gv)), NULL, PERL_MAGIC_dbfile);
+ if (PERLDB_LINE_OR_SAVESRC && !GvAV(gv))
+ hv_magic(GvHVn(gv), GvAVn(gv), PERL_MAGIC_dbfile);
if (tmpbuf != smallbuf)
Safefree(tmpbuf);
return gv;
If C<gv> is a typeglob whose subroutine entry is a constant sub eligible for
inlining, or C<gv> is a placeholder reference that would be promoted to such
a typeglob, then returns the value returned by the sub. Otherwise, returns
-NULL.
+C<NULL>.
=cut
*/
Perl_gv_const_sv(pTHX_ GV *gv)
{
PERL_ARGS_ASSERT_GV_CONST_SV;
+ PERL_UNUSED_CONTEXT;
if (SvTYPE(gv) == SVt_PVGV)
return cv_const_sv(GvCVu(gv));
- return SvROK(gv) && SvTYPE(SvRV(gv)) != SVt_PVAV ? SvRV(gv) : NULL;
+ return SvROK(gv) && SvTYPE(SvRV(gv)) != SVt_PVAV && SvTYPE(SvRV(gv)) != SVt_PVCV ? SvRV(gv) : NULL;
}
GP *
const char *file;
STRLEN len;
#ifndef USE_ITHREADS
- SV * temp_sv;
+ GV *filegv;
#endif
dVAR;
gp->gp_sv = newSV(0);
#endif
-#ifdef USE_ITHREADS
+ /* PL_curcop may be null here. E.g.,
+ INIT { bless {} and exit }
+ frees INIT before looking up DESTROY (and creating *DESTROY)
+ */
if (PL_curcop) {
gp->gp_line = CopLINE(PL_curcop); /* 0 otherwise Newxz */
+#ifdef USE_ITHREADS
if (CopFILE(PL_curcop)) {
file = CopFILE(PL_curcop);
len = strlen(file);
}
+#else
+ filegv = CopFILEGV(PL_curcop);
+ if (filegv) {
+ file = GvNAME(filegv)+2;
+ len = GvNAMELEN(filegv)-2;
+ }
+#endif
else goto no_file;
}
else {
file = "";
len = 0;
}
-#else
- if(PL_curcop)
- gp->gp_line = CopLINE(PL_curcop); /* 0 otherwise Newxz */
- temp_sv = CopFILESV(PL_curcop);
- if (temp_sv) {
- file = SvPVX(temp_sv);
- len = SvCUR(temp_sv);
- } else {
- file = "";
- len = 0;
- }
-#endif
PERL_HASH(hash, file, len);
gp->gp_file_hek = share_hek(file, len, hash);
void
Perl_cvgv_set(pTHX_ CV* cv, GV* gv)
{
- GV * const oldgv = CvGV(cv);
+ GV * const oldgv = CvNAMED(cv) ? NULL : SvANY(cv)->xcv_gv_u.xcv_gv;
HEK *hek;
PERL_ARGS_ASSERT_CVGV_SET;
sv_del_backref(MUTABLE_SV(oldgv), MUTABLE_SV(cv));
}
}
- else if ((hek = CvNAME_HEK(cv))) unshare_hek(hek);
+ else if ((hek = CvNAME_HEK(cv))) {
+ unshare_hek(hek);
+ CvLEXICAL_off(cv);
+ }
+ CvNAMED_off(cv);
SvANY(cv)->xcv_gv_u.xcv_gv = gv;
assert(!CvCVGV_RC(cv));
}
}
+/* Convert CvSTASH + CvNAME_HEK into a GV. Conceptually, all subs have a
+ GV, but for efficiency that GV may not in fact exist. This function,
+ called by CvGV, reifies it. */
+
+GV *
+Perl_cvgv_from_hek(pTHX_ CV *cv)
+{
+ GV *gv;
+ SV **svp;
+ PERL_ARGS_ASSERT_CVGV_FROM_HEK;
+ assert(SvTYPE(cv) == SVt_PVCV);
+ if (!CvSTASH(cv)) return NULL;
+ ASSUME(CvNAME_HEK(cv));
+ svp = hv_fetchhek(CvSTASH(cv), CvNAME_HEK(cv), 0);
+ gv = MUTABLE_GV(svp && *svp ? *svp : newSV(0));
+ if (!isGV(gv))
+ gv_init_pvn(gv, CvSTASH(cv), HEK_KEY(CvNAME_HEK(cv)),
+ HEK_LEN(CvNAME_HEK(cv)),
+ SVf_UTF8 * !!HEK_UTF8(CvNAME_HEK(cv)));
+ if (!CvNAMED(cv)) { /* gv_init took care of it */
+ assert (SvANY(cv)->xcv_gv_u.xcv_gv == gv);
+ return gv;
+ }
+ unshare_hek(CvNAME_HEK(cv));
+ CvNAMED_off(cv);
+ SvANY(cv)->xcv_gv_u.xcv_gv = gv;
+ if (svp && *svp) SvREFCNT_inc_simple_void_NN(gv);
+ CvCVGV_RC_on(cv);
+ return gv;
+}
+
/* Assign CvSTASH(cv) = st, handling weak references. */
void
Converts a scalar into a typeglob. This is an incoercible typeglob;
assigning a reference to it will assign to one of its slots, instead of
-overwriting it as happens with typeglobs created by SvSetSV. Converting
-any scalar that is SvOK() may produce unpredictable results and is reserved
+overwriting it as happens with typeglobs created by C<SvSetSV>. Converting
+any scalar that is C<SvOK()> may produce unpredictable results and is reserved
for perl's internal use.
C<gv> is the scalar to be converted.
passed to this function matches the name of the element. If it does not
match, perl's internal bookkeeping will get out of sync.
-C<flags> can be set to SVf_UTF8 if C<name> is a UTF8 string, or
+C<flags> can be set to C<SVf_UTF8> if C<name> is a UTF-8 string, or
the return value of SvUTF8(sv). It can also take the
-GV_ADDMULTI flag, which means to pretend that the GV has been
+C<GV_ADDMULTI> flag, which means to pretend that the GV has been
seen before (i.e., suppress "Used once" warnings).
=for apidoc gv_init
-The old form of gv_init_pvn(). It does not work with UTF8 strings, as it
+The old form of C<gv_init_pvn()>. It does not work with UTF-8 strings, as it
has no flags parameter. If the C<multi> parameter is set, the
-GV_ADDMULTI flag will be passed to gv_init_pvn().
+C<GV_ADDMULTI> flag will be passed to C<gv_init_pvn()>.
=for apidoc gv_init_pv
-Same as gv_init_pvn(), but takes a nul-terminated string for the name
+Same as C<gv_init_pvn()>, but takes a nul-terminated string for the name
instead of separate char * and length parameters.
=for apidoc gv_init_sv
-Same as gv_init_pvn(), but takes an SV * for the name instead of separate
+Same as C<gv_init_pvn()>, but takes an SV * for the name instead of separate
char * and length parameters. C<flags> is currently unused.
=cut
void
Perl_gv_init_pvn(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len, U32 flags)
{
- dVAR;
const U32 old_type = SvTYPE(gv);
const bool doproto = old_type > SVt_NULL;
char * const proto = (doproto && SvPOK(gv))
const U32 proto_utf8 = proto ? SvUTF8(gv) : 0;
SV *const has_constant = doproto && SvROK(gv) ? SvRV(gv) : NULL;
const U32 exported_constant = has_constant ? SvPCS_IMPORTED(gv) : 0;
+ const bool really_sub =
+ has_constant && SvTYPE(has_constant) == SVt_PVCV;
+ COP * const old = PL_curcop;
PERL_ARGS_ASSERT_GV_INIT_PVN;
assert (!(proto && has_constant));
if (has_constant) {
- /* The constant has to be a simple scalar type. */
+ /* The constant has to be a scalar, array or subroutine. */
switch (SvTYPE(has_constant)) {
case SVt_PVHV:
- case SVt_PVCV:
case SVt_PVFM:
case SVt_PVIO:
Perl_croak(aTHX_ "Cannot convert a reference to %s to typeglob",
sv_reftype(has_constant, 0));
+ NOT_REACHED; /* NOTREACHED */
+ break;
+
default: NOOP;
}
SvRV_set(gv, NULL);
SvIOK_off(gv);
isGV_with_GP_on(gv);
+ if (really_sub && !CvISXSUB(has_constant) && CvSTART(has_constant)
+ && ( CvSTART(has_constant)->op_type == OP_NEXTSTATE
+ || CvSTART(has_constant)->op_type == OP_DBSTATE))
+ PL_curcop = (COP *)CvSTART(has_constant);
GvGP_set(gv, Perl_newGP(aTHX_ gv));
+ PL_curcop = old;
GvSTASH(gv) = stash;
if (stash)
Perl_sv_add_backref(aTHX_ MUTABLE_SV(stash), MUTABLE_SV(gv));
gv_name_set(gv, name, len, GV_ADD | ( flags & SVf_UTF8 ? SVf_UTF8 : 0 ));
if (flags & GV_ADDMULTI || doproto) /* doproto means it */
GvMULTI_on(gv); /* _was_ mentioned */
- if (doproto) {
+ if (really_sub) {
+ /* Not actually a constant. Just a regular sub. */
+ CV * const cv = (CV *)has_constant;
+ GvCV_set(gv,cv);
+ if (CvNAMED(cv) && CvSTASH(cv) == stash && (
+ CvNAME_HEK(cv) == GvNAME_HEK(gv)
+ || ( HEK_LEN(CvNAME_HEK(cv)) == HEK_LEN(GvNAME_HEK(gv))
+ && HEK_FLAGS(CvNAME_HEK(cv)) != HEK_FLAGS(GvNAME_HEK(gv))
+ && HEK_UTF8(CvNAME_HEK(cv)) == HEK_UTF8(GvNAME_HEK(gv))
+ && memEQ(HEK_KEY(CvNAME_HEK(cv)), GvNAME(gv), GvNAMELEN(gv))
+ )
+ ))
+ CvGV_set(cv,gv);
+ }
+ else if (doproto) {
CV *cv;
if (has_constant) {
/* newCONSTSUB takes ownership of the reference from us. */
/* no support for \&CORE::infix;
no support for funcs that do not parse like funcs */
case KEY___DATA__: case KEY___END__: case KEY_and: case KEY_AUTOLOAD:
- case KEY_BEGIN : case KEY_CHECK : case KEY_cmp: case KEY_CORE :
+ case KEY_BEGIN : case KEY_CHECK : case KEY_cmp:
case KEY_default : case KEY_DESTROY:
case KEY_do : case KEY_dump : case KEY_else : case KEY_elsif :
case KEY_END : case KEY_eq : case KEY_eval :
return NULL;
case KEY_chdir:
case KEY_chomp: case KEY_chop: case KEY_defined: case KEY_delete:
- case KEY_each : case KEY_eof : case KEY_exec : case KEY_exists:
- case KEY_keys:
+ case KEY_eof : case KEY_exec: case KEY_exists :
case KEY_lstat:
- case KEY_pop:
- case KEY_push:
- case KEY_shift:
- case KEY_splice: case KEY_split:
+ case KEY_split:
case KEY_stat:
case KEY_system:
case KEY_truncate: case KEY_unlink:
- case KEY_unshift:
- case KEY_values:
ampable = FALSE;
}
if (!gv) {
cv = MUTABLE_CV(newSV_type(SVt_PVCV));
GvCV_set(gv,cv);
GvCVGEN(gv) = 0;
- mro_method_changed_in(GvSTASH(gv));
CvISXSUB_on(cv);
CvXSUB(cv) = core_xsub;
+ PoisonPADLIST(cv);
}
CvGV_set(cv, gv); /* This stops new ATTRSUB from setting CvFILE
from PL_curcop. */
- (void)gv_fetchfile(file);
+ /* XSUBs can't be perl lang/perl5db.pl debugged
+ if (PERLDB_LINE_OR_SAVESRC)
+ (void)gv_fetchfile(file); */
CvFILE(cv) = (char *)file;
/* XXX This is inefficient, as doing things this order causes
a prototype check in newATTRSUB. But we have to do
CvLVALUE_on(cv);
/* newATTRSUB will free the CV and return NULL if we're still
compiling after a syntax error */
- if ((cv = newATTRSUB_flags(
+ if ((cv = newATTRSUB_x(
oldsavestack_ix, (OP *)gv,
NULL,NULL,
coresub_op(
: newSVpvn(name,len),
code, opnum
),
- 1
+ TRUE
)) != NULL) {
assert(GvCV(gv) == orig_cv);
if (opnum != OP_VEC && opnum != OP_SUBSTR && opnum != OP_POS
- && opnum != OP_UNDEF)
+ && opnum != OP_UNDEF && opnum != OP_KEYS)
CvLVALUE_off(cv); /* Now *that* was a neat trick. */
}
LEAVE;
PL_compcv = oldcompcv;
}
if (cv) {
- SV *opnumsv = opnum ? newSVuv((UV)opnum) : (SV *)NULL;
- cv_set_call_checker(
- cv, Perl_ck_entersub_args_core, opnumsv ? opnumsv : (SV *)cv
- );
- SvREFCNT_dec(opnumsv);
+ SV *opnumsv = newSViv(
+ (opnum == OP_ENTEREVAL && len == 9 && memEQ(name, "evalbytes", 9)) ?
+ (OP_ENTEREVAL | (1<<16))
+ : opnum ? opnum : (((I32)name[2]) << 16));
+ cv_set_call_checker_flags(cv, Perl_ck_entersub_args_core, opnumsv, 0);
+ SvREFCNT_dec_NN(opnumsv);
}
return gv;
GV *
Perl_gv_fetchmeth_sv(pTHX_ HV *stash, SV *namesv, I32 level, U32 flags)
{
- char *namepv;
- STRLEN namelen;
- PERL_ARGS_ASSERT_GV_FETCHMETH_SV;
- namepv = SvPV(namesv, namelen);
- if (SvUTF8(namesv))
- flags |= SVf_UTF8;
- return gv_fetchmeth_pvn(stash, namepv, namelen, level, flags);
+ char *namepv;
+ STRLEN namelen;
+ PERL_ARGS_ASSERT_GV_FETCHMETH_SV;
+ if (LIKELY(SvPOK_nog(namesv))) /* common case */
+ return gv_fetchmeth_internal(stash, namesv, NULL, 0, level,
+ flags | SvUTF8(namesv));
+ namepv = SvPV(namesv, namelen);
+ if (SvUTF8(namesv)) flags |= SVf_UTF8;
+ return gv_fetchmeth_pvn(stash, namepv, namelen, level, flags);
}
/*
Perl_gv_fetchmeth_pv(pTHX_ HV *stash, const char *name, I32 level, U32 flags)
{
PERL_ARGS_ASSERT_GV_FETCHMETH_PV;
- return gv_fetchmeth_pvn(stash, name, strlen(name), level, flags);
+ return gv_fetchmeth_internal(stash, NULL, name, strlen(name), level, flags);
}
/*
Returns the glob with the given C<name> and a defined subroutine or
C<NULL>. The glob lives in the given C<stash>, or in the stashes
-accessible via @ISA and UNIVERSAL::.
+accessible via C<@ISA> and C<UNIVERSAL::>.
The argument C<level> should be either 0 or -1. If C<level==0>, as a
side-effect creates a glob with the given C<name> in the given C<stash>
which in the case of success contains an alias for the subroutine, and sets
up caching info for this glob.
-The only significant values for C<flags> are GV_SUPER and SVf_UTF8.
+The only significant values for C<flags> are C<GV_SUPER> and C<SVf_UTF8>.
-GV_SUPER indicates that we want to look up the method in the superclasses
+C<GV_SUPER> indicates that we want to look up the method in the superclasses
of the C<stash>.
The
the GV directly; instead, you should use the method's CV, which can be
obtained from the GV with the C<GvCV> macro.
+=for apidoc Amnh||GV_SUPER
+
=cut
*/
/* NOTE: No support for tied ISA */
-GV *
-Perl_gv_fetchmeth_pvn(pTHX_ HV *stash, const char *name, STRLEN len, I32 level, U32 flags)
+PERL_STATIC_INLINE GV*
+S_gv_fetchmeth_internal(pTHX_ HV* stash, SV* meth, const char* name, STRLEN len, I32 level, U32 flags)
{
- dVAR;
GV** gvp;
+ HE* he;
AV* linear_av;
SV** linear_svp;
SV* linear_sv;
CV* cand_cv = NULL;
GV* topgv = NULL;
const char *hvname;
- I32 create = (level >= 0) ? 1 : 0;
+ I32 create = (level >= 0) ? HV_FETCH_LVALUE : 0;
I32 items;
U32 topgen_cmp;
U32 is_utf8 = flags & SVf_UTF8;
- PERL_ARGS_ASSERT_GV_FETCHMETH_PVN;
-
/* UNIVERSAL methods should be callable without a stash */
if (!stash) {
create = 0; /* probably appropriate */
Perl_croak(aTHX_ "Can't use anonymous symbol table for method lookup");
assert(hvname);
- assert(name);
+ assert(name || meth);
DEBUG_o( Perl_deb(aTHX_ "Looking for %smethod %s in package %s\n",
- flags & GV_SUPER ? "SUPER " : "",name,hvname) );
+ flags & GV_SUPER ? "SUPER " : "",
+ name ? name : SvPV_nolen(meth), hvname) );
topgen_cmp = HvMROMETA(stash)->cache_gen + PL_sub_generation;
if (flags & GV_SUPER) {
- if (!HvAUX(stash)->xhv_super) HvAUX(stash)->xhv_super = newHV();
- cachestash = HvAUX(stash)->xhv_super;
+ if (!HvAUX(stash)->xhv_mro_meta->super)
+ HvAUX(stash)->xhv_mro_meta->super = newHV();
+ cachestash = HvAUX(stash)->xhv_mro_meta->super;
}
else cachestash = stash;
/* check locally for a real method or a cache entry */
- gvp = (GV**)hv_fetch(cachestash, name, is_utf8 ? -(I32)len : (I32)len,
- create);
+ he = (HE*)hv_common(
+ cachestash, meth, name, len, is_utf8 ? HVhek_UTF8 : 0, create, NULL, 0
+ );
+ if (he) gvp = (GV**)&HeVAL(he);
+ else gvp = NULL;
+
if(gvp) {
topgv = *gvp;
have_gv:
assert(topgv);
if (SvTYPE(topgv) != SVt_PVGV)
+ {
+ if (!name)
+ name = SvPV_nomg(meth, len);
gv_init_pvn(topgv, stash, name, len, GV_ADDMULTI|is_utf8);
+ }
if ((cand_cv = GvCV(topgv))) {
/* If genuine method or valid cache entry, use it */
if (!GvCVGEN(topgv) || GvCVGEN(topgv) == topgen_cmp) {
return 0;
}
else if (stash == cachestash
- && len > 1 /* shortest is uc */ && HvNAMELEN_get(stash) == 4
- && strnEQ(hvname, "CORE", 4)
+ && len > 1 /* shortest is uc */
+ && memEQs(hvname, HvNAMELEN_get(stash), "CORE")
&& S_maybe_add_coresub(aTHX_ NULL,topgv,name,len))
goto have_gv;
}
if (!cstash) {
Perl_ck_warner(aTHX_ packWARN(WARN_SYNTAX),
- "Can't locate package %"SVf" for @%"HEKf"::ISA",
+ "Can't locate package %" SVf " for @%" HEKf "::ISA",
SVfARG(linear_sv),
HEKfARG(HvNAME_HEK(stash)));
continue;
assert(cstash);
- gvp = (GV**)hv_fetch(cstash, name, is_utf8 ? -(I32)len : (I32)len, 0);
+ gvp = (GV**)hv_common(
+ cstash, meth, name, len, is_utf8 ? HVhek_UTF8 : 0, HV_FETCH_JUST_SV, NULL, 0
+ );
if (!gvp) {
if (len > 1 && HvNAMELEN_get(cstash) == 4) {
const char *hvname = HvNAME(cstash); assert(hvname);
- if (strnEQ(hvname, "CORE", 4)
+ if (strBEGINs(hvname, "CORE")
&& (candidate =
S_maybe_add_coresub(aTHX_ cstash,NULL,name,len)
))
/* Check UNIVERSAL without caching */
if(level == 0 || level == -1) {
- candidate = gv_fetchmeth_pvn(NULL, name, len, 1, flags &~GV_SUPER);
+ candidate = gv_fetchmeth_internal(NULL, meth, name, len, 1,
+ flags &~GV_SUPER);
if(candidate) {
cand_cv = GvCV(candidate);
if (topgv && (GvREFCNT(topgv) == 1) && (CvROOT(cand_cv) || CvXSUB(cand_cv))) {
return 0;
}
+GV *
+Perl_gv_fetchmeth_pvn(pTHX_ HV *stash, const char *name, STRLEN len, I32 level, U32 flags)
+{
+ PERL_ARGS_ASSERT_GV_FETCHMETH_PVN;
+ return gv_fetchmeth_internal(stash, NULL, name, len, level, flags);
+}
+
/*
=for apidoc gv_fetchmeth_autoload
/*
=for apidoc gv_fetchmeth_pvn_autoload
-Same as gv_fetchmeth_pvn(), but looks for autoloaded subroutines too.
+Same as C<gv_fetchmeth_pvn()>, but looks for autoloaded subroutines too.
Returns a glob for the subroutine.
For an autoloaded subroutine without a GV, will create a GV even
-if C<level < 0>. For an autoloaded subroutine without a stub, GvCV()
+if C<level < 0>. For an autoloaded subroutine without a stub, C<GvCV()>
of the result may be zero.
-Currently, the only significant value for C<flags> is SVf_UTF8.
+Currently, the only significant value for C<flags> is C<SVf_UTF8>.
=cut
*/
Returns the glob which contains the subroutine to call to invoke the method
on the C<stash>. In fact in the presence of autoloading this may be the
-glob for "AUTOLOAD". In this case the corresponding variable $AUTOLOAD is
+glob for "AUTOLOAD". In this case the corresponding variable C<$AUTOLOAD> is
already setup.
The third parameter of C<gv_fetchmethod_autoload> determines whether
Calling C<gv_fetchmethod> is equivalent to calling C<gv_fetchmethod_autoload>
with a non-zero C<autoload> parameter.
-These functions grant C<"SUPER"> token as a prefix of the method name. Note
+These functions grant C<"SUPER"> token
+as a prefix of the method name. Note
that if you want to keep the returned glob for a long time, you need to
check for it being "AUTOLOAD", since at the later time the call may load a
-different subroutine due to $AUTOLOAD changing its value. Use the glob
-created via a side effect to do this.
+different subroutine due to C<$AUTOLOAD> changing its value. Use the glob
+created as a side effect to do this.
-These functions have the same side-effects and as C<gv_fetchmeth> with
-C<level==0>. C<name> should be writable if contains C<':'> or C<'
-''>. The warning against passing the GV returned by C<gv_fetchmeth> to
-C<call_sv> apply equally to these functions.
+These functions have the same side-effects as C<gv_fetchmeth> with
+C<level==0>. The warning against passing the GV returned by
+C<gv_fetchmeth> to C<call_sv> applies equally to these functions.
=cut
*/
return gv_fetchmethod_pvn_flags(stash, name, strlen(name), flags);
}
-/* Don't merge this yet, as it's likely to get a len parameter, and possibly
- even a U32 hash */
GV *
Perl_gv_fetchmethod_pvn_flags(pTHX_ HV *stash, const char *name, const STRLEN len, U32 flags)
{
- dVAR;
- const char *nend;
- const char *nsplit = NULL;
+ const char * const origname = name;
+ const char * const name_end = name + len;
+ const char *last_separator = 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;
if (SvTYPE(stash) < SVt_PVHV)
stash = NULL;
else {
- /* The only way stash can become NULL later on is if nsplit is set,
+ /* The only way stash can become NULL later on is if last_separator 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 != (origname + len); nend++) {
- if (*nend == '\'') {
- nsplit = nend;
- name = nend + 1;
- }
- else if (*nend == ':' && *(nend + 1) == ':') {
- nsplit = nend++;
- name = nend + 1;
- }
+ {
+ /* check if the method name is fully qualified or
+ * not, and separate the package name from the actual
+ * method name.
+ *
+ * leaves last_separator pointing to the beginning of the
+ * last package separator (either ' or ::) or 0
+ * if none was found.
+ *
+ * leaves name pointing at the beginning of the
+ * method name.
+ */
+ const char *name_cursor = name;
+ const char * const name_em1 = name_end - 1; /* name_end minus 1 */
+ for (name_cursor = name; name_cursor < name_end ; name_cursor++) {
+ if (*name_cursor == '\'') {
+ last_separator = name_cursor;
+ name = name_cursor + 1;
+ }
+ else if (name_cursor < name_em1 && *name_cursor == ':' && name_cursor[1] == ':') {
+ last_separator = name_cursor++;
+ name = name_cursor + 1;
+ }
+ }
}
- if (nsplit) {
- if ((nsplit - origname) == 5 && memEQ(origname, "SUPER", 5)) {
+
+ /* did we find a separator? */
+ if (last_separator) {
+ STRLEN sep_len= last_separator - origname;
+ if ( memEQs(origname, sep_len, "SUPER")) {
/* ->SUPER::method should really be looked up in original stash */
stash = CopSTASH(PL_curcop);
flags |= GV_SUPER;
DEBUG_o( Perl_deb(aTHX_ "Treating %s as %s::%s\n",
origname, HvENAME_get(stash), name) );
}
- else if ((nsplit - origname) >= 7 &&
- strnEQ(nsplit - 7, "::SUPER", 7)) {
+ else if ( sep_len >= 7 &&
+ strBEGINs(last_separator - 7, "::SUPER")) {
/* don't autovifify if ->NoSuchStash::SUPER::method */
- stash = gv_stashpvn(origname, nsplit - origname - 7, is_utf8);
+ stash = gv_stashpvn(origname, sep_len - 7, is_utf8);
if (stash) flags |= GV_SUPER;
}
else {
/* don't autovifify if ->NoSuchStash::method */
- stash = gv_stashpvn(origname, nsplit - origname, is_utf8);
+ stash = gv_stashpvn(origname, sep_len, is_utf8);
}
ostash = stash;
}
- gv = gv_fetchmeth_pvn(stash, name, nend - name, 0, flags);
+ gv = gv_fetchmeth_pvn(stash, name, name_end - name, 0, flags);
if (!gv) {
- if (strEQ(name,"import") || strEQ(name,"unimport"))
- gv = MUTABLE_GV(&PL_sv_yes);
- else if (autoload)
+ /* This is the special case that exempts Foo->import and
+ Foo->unimport from being an error even if there's no
+ import/unimport subroutine */
+ if (strEQ(name,"import") || strEQ(name,"unimport")) {
+ gv = (GV*)sv_2mortal((SV*)newCONSTSUB_flags(NULL,
+ NULL, 0, 0, NULL));
+ } else if (autoload)
gv = gv_autoload_pvn(
- ostash, name, nend - name, GV_AUTOLOAD_ISMETHOD|flags
+ ostash, name, name_end - name, GV_AUTOLOAD_ISMETHOD|flags
);
if (!gv && do_croak) {
/* Right now this is exclusively for the benefit of S_method_common
HV_FETCH_ISEXISTS, NULL, 0)
) {
require_pv("IO/File.pm");
- gv = gv_fetchmeth_pvn(stash, name, nend - name, 0, flags);
+ gv = gv_fetchmeth_pvn(stash, name, name_end - name, 0, flags);
if (gv)
return gv;
}
Perl_croak(aTHX_
- "Can't locate object method \"%"UTF8f
- "\" via package \"%"HEKf"\"",
- UTF8fARG(is_utf8, nend - name, name),
+ "Can't locate object method \"%" UTF8f
+ "\" via package \"%" HEKf "\"",
+ UTF8fARG(is_utf8, name_end - name, name),
HEKfARG(HvNAME_HEK(stash)));
}
else {
SV* packnamesv;
- if (nsplit) {
- packnamesv = newSVpvn_flags(origname, nsplit - origname,
+ if (last_separator) {
+ packnamesv = newSVpvn_flags(origname, last_separator - origname,
SVs_TEMP | is_utf8);
} else {
packnamesv = error_report;
}
Perl_croak(aTHX_
- "Can't locate object method \"%"UTF8f
- "\" via package \"%"SVf"\""
- " (perhaps you forgot to load \"%"SVf"\"?)",
- UTF8fARG(is_utf8, nend - name, name),
+ "Can't locate object method \"%" UTF8f
+ "\" via package \"%" SVf "\""
+ " (perhaps you forgot to load \"%" SVf "\"?)",
+ UTF8fARG(is_utf8, name_end - name, name),
SVfARG(packnamesv), SVfARG(packnamesv));
}
}
GV* stubgv;
GV* autogv;
- if (CvANON(cv))
+ if (CvANON(cv) || CvLEXICAL(cv))
stubgv = gv;
else {
stubgv = CvGV(cv);
GV*
Perl_gv_autoload_pvn(pTHX_ HV *stash, const char *name, STRLEN len, U32 flags)
{
- dVAR;
GV* gv;
CV* cv;
HV* varstash;
packname = sv_2mortal(newSVhek(HvNAME_HEK(stash)));
if (flags & GV_SUPER) sv_catpvs(packname, "::SUPER");
}
- if (!(gv = gv_fetchmeth_pvn(stash, S_autoload, S_autolen, FALSE, is_utf8)))
+ if (!(gv = gv_fetchmeth_pvn(stash, S_autoload, S_autolen, FALSE,
+ is_utf8 | (flags & GV_SUPER))))
return NULL;
cv = GvCV(gv);
return NULL;
/*
- * Inheriting AUTOLOAD for non-methods works ... for now.
+ * Inheriting AUTOLOAD for non-methods no longer works
*/
if (
!(flags & GV_AUTOLOAD_ISMETHOD)
&& (GvCVGEN(gv) || GvSTASH(gv) != stash)
)
- Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED),
- "Use of inherited AUTOLOAD for non-method %"SVf
- "::%"UTF8f"() is deprecated",
+ Perl_croak(aTHX_ "Use of inherited AUTOLOAD for non-method %" SVf
+ "::%" UTF8f "() is no longer allowed",
SVfARG(packname),
UTF8fARG(is_utf8, len, name));
if (SvUTF8(cv))
sv_utf8_upgrade_flags_grow(tmpsv, 0, CvPROTOLEN(cv) + 2);
ulen = SvCUR(tmpsv);
- SvCUR(tmpsv)++; /* include null in string */
+ SvCUR_set(tmpsv, SvCUR(tmpsv) + 1); /* include null in string */
sv_catpvn_flags(
tmpsv, proto, CvPROTOLEN(cv), SV_CATBYTES*!SvUTF8(cv)
);
sv_setsv_nomg((SV *)cv, tmpsv);
SvTEMP_off(tmpsv);
SvREFCNT_dec_NN(tmpsv);
- SvLEN(cv) = SvCUR(cv) + 1;
- SvCUR(cv) = ulen;
+ SvLEN_set(cv, SvCUR(cv) + 1);
+ SvCUR_set(cv, ulen);
}
else {
sv_setpvn((SV *)cv, name, len);
* use that, but for lack of anything better we will use the sub's
* original package to look up $AUTOLOAD.
*/
- varstash = GvSTASH(CvGV(cv));
+ varstash = CvNAMED(cv) ? CvSTASH(cv) : GvSTASH(CvGV(cv));
vargv = *(GV**)hv_fetch(varstash, S_autoload, S_autolen, TRUE);
ENTER;
/* require_tie_mod() internal routine for requiring a module
* that implements the logic of automatic ties like %! and %-
+ * It loads the module and then calls the _tie_it subroutine
+ * with the passed gv as an argument.
*
* The "gv" parameter should be the glob.
- * "varpv" holds the name of the var, used for error messages.
+ * "varname" holds the 1-char name of the var, used for error messages.
* "namesv" holds the module name. Its refcount will be decremented.
- * "methpv" holds the method name to test for to check that things
- * are working reasonably close to as expected.
* "flags": if flag & 1 then save the scalar before loading.
* For the protection of $! to work (it is set by this routine)
* the sv slot must already be magicalized.
*/
-STATIC HV*
-S_require_tie_mod(pTHX_ GV *gv, const char *varpv, SV* namesv, const char *methpv,const U32 flags)
+STATIC void
+S_require_tie_mod(pTHX_ GV *gv, const char varname, const char * name,
+ STRLEN len, const U32 flags)
{
- dVAR;
- HV* stash = gv_stashsv(namesv, 0);
+ const SV * const target = varname == '[' ? GvSV(gv) : (SV *)GvHV(gv);
PERL_ARGS_ASSERT_REQUIRE_TIE_MOD;
- if (!stash || !(gv_fetchmethod_autoload(stash, methpv, FALSE))) {
- SV *module = newSVsv(namesv);
- char varname = *varpv; /* varpv might be clobbered by load_module,
- so save it. For the moment it's always
- a single char. */
+ /* If it is not tied */
+ if (!target || !SvRMAGICAL(target)
+ || !mg_find(target,
+ varname == '[' ? PERL_MAGIC_tiedscalar : PERL_MAGIC_tied))
+ {
+ HV *stash;
+ GV **gvp;
+ dSP;
+
+ PUSHSTACKi(PERLSI_MAGIC);
+ ENTER;
+
+#define GET_HV_FETCH_TIE_FUNC \
+ ( (gvp = (GV **)hv_fetchs(stash, "_tie_it", 0)) \
+ && *gvp \
+ && ( (isGV(*gvp) && GvCV(*gvp)) \
+ || (SvROK(*gvp) && SvTYPE(SvRV(*gvp)) == SVt_PVCV) ) \
+ )
+
+ /* Load the module if it is not loaded. */
+ if (!(stash = gv_stashpvn(name, len, 0))
+ || ! GET_HV_FETCH_TIE_FUNC)
+ {
+ SV * const module = newSVpvn(name, len);
const char type = varname == '[' ? '$' : '%';
- dSP;
- ENTER;
- SAVEFREESV(namesv);
if ( flags & 1 )
save_scalar(gv);
- PUSHSTACKi(PERLSI_MAGIC);
Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, module, NULL);
- POPSTACK;
- stash = gv_stashsv(namesv, 0);
+ assert(sp == PL_stack_sp);
+ stash = gv_stashpvn(name, len, 0);
if (!stash)
- Perl_croak(aTHX_ "panic: Can't use %c%c because %"SVf" is not available",
- type, varname, SVfARG(namesv));
- else if (!gv_fetchmethod(stash, methpv))
- Perl_croak(aTHX_ "panic: Can't use %c%c because %"SVf" does not support method %s",
- type, varname, SVfARG(namesv), methpv);
- LEAVE;
+ Perl_croak(aTHX_ "panic: Can't use %c%c because %s is not available",
+ type, varname, name);
+ else if (! GET_HV_FETCH_TIE_FUNC)
+ Perl_croak(aTHX_ "panic: Can't use %c%c because %s does not define _tie_it",
+ type, varname, name);
+ }
+ /* Now call the tie function. It should be in *gvp. */
+ assert(gvp); assert(*gvp);
+ PUSHMARK(SP);
+ XPUSHs((SV *)gv);
+ PUTBACK;
+ call_sv((SV *)*gvp, G_VOID|G_DISCARD);
+ LEAVE;
+ POPSTACK;
}
- else SvREFCNT_dec_NN(namesv);
- return stash;
}
+/* add a require_tie_mod_s - the _s suffix is similar to pvs type suffixes,
+ * IOW it means we do STR_WITH_LEN() ourselves and the user should pass in
+ * a true string WITHOUT a len.
+ */
+#define require_tie_mod_s(gv, varname, name, flags) \
+ S_require_tie_mod(aTHX_ gv, varname, STR_WITH_LEN(name), flags)
+
/*
=for apidoc gv_stashpv
parameter indicates the length of the C<name>, in bytes. C<flags> is passed
to C<gv_fetchpvn_flags()>, so if set to C<GV_ADD> then the package will be
created if it does not already exist. If the package does not exist and
-C<flags> is 0 (or any other setting that does not create packages) then NULL
+C<flags> is 0 (or any other setting that does not create packages) then C<NULL>
is returned.
Flags may be one of:
GV_NOEXPAND
GV_ADDMG
-The most important of which are probably GV_ADD and SVf_UTF8.
+The most important of which are probably C<GV_ADD> and C<SVf_UTF8>.
+
+Note, use of C<gv_stashsv> instead of C<gv_stashpvn> where possible is strongly
+recommended for performance reasons.
+
+=for apidoc Amnh||GV_ADD
=cut
*/
-HV*
-Perl_gv_stashpvn(pTHX_ const char *name, U32 namelen, I32 flags)
+/*
+gv_stashpvn_internal
+
+Perform the internal bits of gv_stashsvpvn_cached. You could think of this
+as being one half of the logic. Not to be called except from gv_stashsvpvn_cached().
+
+*/
+
+PERL_STATIC_INLINE HV*
+S_gv_stashpvn_internal(pTHX_ const char *name, U32 namelen, I32 flags)
{
char smallbuf[128];
char *tmpbuf;
GV *tmpgv;
U32 tmplen = namelen + 2;
- PERL_ARGS_ASSERT_GV_STASHPVN;
+ PERL_ARGS_ASSERT_GV_STASHPVN_INTERNAL;
if (tmplen <= sizeof smallbuf)
tmpbuf = smallbuf;
tmpgv = gv_fetchpvn_flags(tmpbuf, tmplen, flags, SVt_PVHV);
if (tmpbuf != smallbuf)
Safefree(tmpbuf);
- if (!tmpgv)
+ if (!tmpgv || !isGV_with_GP(tmpgv))
return NULL;
stash = GvHV(tmpgv);
if (!(flags & ~GV_NOADD_MASK) && !stash) return NULL;
}
/*
+gv_stashsvpvn_cached
+
+Returns a pointer to the stash for a specified package, possibly
+cached. Implements both C<gv_stashpvn> and C<gv_stashsv>.
+
+Requires one of either namesv or namepv to be non-null.
+
+See C<L</gv_stashpvn>> for details on "flags".
+
+Note the sv interface is strongly preferred for performance reasons.
+
+*/
+
+#define PERL_ARGS_ASSERT_GV_STASHSVPVN_CACHED \
+ assert(namesv || name)
+
+PERL_STATIC_INLINE HV*
+S_gv_stashsvpvn_cached(pTHX_ SV *namesv, const char *name, U32 namelen, I32 flags)
+{
+ HV* stash;
+ HE* he;
+
+ PERL_ARGS_ASSERT_GV_STASHSVPVN_CACHED;
+
+ he = (HE *)hv_common(
+ PL_stashcache, namesv, name, namelen,
+ (flags & SVf_UTF8) ? HVhek_UTF8 : 0, 0, NULL, 0
+ );
+
+ if (he) {
+ SV *sv = HeVAL(he);
+ HV *hv;
+ assert(SvIOK(sv));
+ hv = INT2PTR(HV*, SvIVX(sv));
+ assert(SvTYPE(hv) == SVt_PVHV);
+ return hv;
+ }
+ else if (flags & GV_CACHE_ONLY) return NULL;
+
+ if (namesv) {
+ if (SvOK(namesv)) { /* prevent double uninit warning */
+ STRLEN len;
+ name = SvPV_const(namesv, len);
+ namelen = len;
+ flags |= SvUTF8(namesv);
+ } else {
+ name = ""; namelen = 0;
+ }
+ }
+ stash = gv_stashpvn_internal(name, namelen, flags);
+
+ if (stash && namelen) {
+ SV* const ref = newSViv(PTR2IV(stash));
+ (void)hv_store(PL_stashcache, name,
+ (flags & SVf_UTF8) ? -(I32)namelen : (I32)namelen, ref, 0);
+ }
+
+ return stash;
+}
+
+HV*
+Perl_gv_stashpvn(pTHX_ const char *name, U32 namelen, I32 flags)
+{
+ PERL_ARGS_ASSERT_GV_STASHPVN;
+ return gv_stashsvpvn_cached(NULL, name, namelen, flags);
+}
+
+/*
=for apidoc gv_stashsv
-Returns a pointer to the stash for a specified package. See C<gv_stashpvn>.
+Returns a pointer to the stash for a specified package. See
+C<L</gv_stashpvn>>.
+
+Note this interface is strongly preferred over C<gv_stashpvn> for performance
+reasons.
=cut
*/
HV*
Perl_gv_stashsv(pTHX_ SV *sv, I32 flags)
{
- STRLEN len;
- const char * const ptr = SvPV_const(sv,len);
-
PERL_ARGS_ASSERT_GV_STASHSV;
-
- return gv_stashpvn(ptr, len, flags | SvUTF8(sv));
+ return gv_stashsvpvn_cached(sv, NULL, 0, flags);
}
return gv_fetchpvn_flags(nambeg, len, flags | SvUTF8(name), sv_type);
}
-STATIC void
+PERL_STATIC_INLINE void
S_gv_magicalize_isa(pTHX_ GV *gv)
{
AV* av;
NULL, 0);
}
-GV *
-Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
- const svtype sv_type)
+/* This function grabs name and tries to split a stash and glob
+ * from its contents. TODO better description, comments
+ *
+ * If the function returns TRUE and 'name == name_end', then
+ * 'gv' can be directly returned to the caller of gv_fetchpvn_flags
+ */
+PERL_STATIC_INLINE bool
+S_parse_gv_stash_name(pTHX_ HV **stash, GV **gv, const char **name,
+ STRLEN *len, const char *nambeg, STRLEN full_len,
+ const U32 is_utf8, const I32 add)
{
- dVAR;
- const char *name = nambeg;
- GV *gv = NULL;
- GV**gvp;
- STRLEN len;
+ char *tmpfullbuf = NULL; /* only malloc one big chunk of memory when the smallbuff is not large enough */
const char *name_cursor;
- HV *stash = NULL;
- const I32 no_init = flags & (GV_NOADD_NOINIT | GV_NOINIT);
- const I32 no_expand = flags & GV_NOEXPAND;
- const I32 add = flags & ~GV_NOADD_MASK;
- const U32 is_utf8 = flags & SVf_UTF8;
- bool addmg = !!(flags & GV_ADDMG);
const char *const name_end = nambeg + full_len;
const char *const name_em1 = name_end - 1;
- U32 faking_it;
+ char smallbuf[64]; /* small buffer to avoid a malloc when possible */
- PERL_ARGS_ASSERT_GV_FETCHPVN_FLAGS;
-
- if (flags & GV_NOTQUAL) {
- /* Caller promised that there is no stash, so we can skip the check. */
- len = full_len;
- goto no_stash;
- }
-
- if (full_len > 2 && *name == '*' && isIDFIRST_lazy_if(name + 1, is_utf8)) {
- /* accidental stringify on a GV? */
- name++;
+ PERL_ARGS_ASSERT_PARSE_GV_STASH_NAME;
+
+ if ( full_len > 2
+ && **name == '*'
+ && isIDFIRST_lazy_if_safe(*name + 1, name_end, is_utf8))
+ {
+ /* accidental stringify on a GV? */
+ (*name)++;
}
- for (name_cursor = name; name_cursor < name_end; name_cursor++) {
- if (name_cursor < name_em1 &&
- ((*name_cursor == ':'
- && name_cursor[1] == ':')
- || *name_cursor == '\''))
- {
- if (!stash)
- stash = PL_defstash;
- if (!stash || !SvREFCNT(stash)) /* symbol table under destruction */
- return NULL;
-
- len = name_cursor - name;
- if (name_cursor > nambeg) { /* Skip for initial :: or ' */
- const char *key;
- if (*name_cursor == ':') {
- key = name;
- len += 2;
- } else {
- char *tmpbuf;
- Newx(tmpbuf, len+2, char);
- Copy(name, tmpbuf, len, char);
- tmpbuf[len++] = ':';
- tmpbuf[len++] = ':';
- key = tmpbuf;
- }
- gvp = (GV**)hv_fetch(stash, key, is_utf8 ? -len : len, add);
- gv = gvp ? *gvp : NULL;
- if (gv && gv != (const GV *)&PL_sv_undef) {
- if (SvTYPE(gv) != SVt_PVGV)
- gv_init_pvn(gv, stash, key, len, (add & GV_ADDMULTI)|is_utf8);
- else
- GvMULTI_on(gv);
- }
- if (key != name)
- Safefree(key);
- if (!gv || gv == (const GV *)&PL_sv_undef)
- return NULL;
+ for (name_cursor = *name; name_cursor < name_end; name_cursor++) {
+ if (name_cursor < name_em1 &&
+ ((*name_cursor == ':' && name_cursor[1] == ':')
+ || *name_cursor == '\''))
+ {
+ if (!*stash)
+ *stash = PL_defstash;
+ if (!*stash || !SvREFCNT(*stash)) /* symbol table under destruction */
+ goto notok;
+
+ *len = name_cursor - *name;
+ if (name_cursor > nambeg) { /* Skip for initial :: or ' */
+ const char *key;
+ GV**gvp;
+ if (*name_cursor == ':') {
+ key = *name;
+ *len += 2;
+ }
+ else { /* using ' for package separator */
+ /* use our pre-allocated buffer when possible to save a malloc */
+ char *tmpbuf;
+ if ( *len+2 <= sizeof smallbuf)
+ tmpbuf = smallbuf;
+ else {
+ /* only malloc once if needed */
+ if (tmpfullbuf == NULL) /* only malloc&free once, a little more than needed */
+ Newx(tmpfullbuf, full_len+2, char);
+ tmpbuf = tmpfullbuf;
+ }
+ Copy(*name, tmpbuf, *len, char);
+ tmpbuf[(*len)++] = ':';
+ tmpbuf[(*len)++] = ':';
+ key = tmpbuf;
+ }
+ gvp = (GV**)hv_fetch(*stash, key, is_utf8 ? -((I32)*len) : (I32)*len, add);
+ *gv = gvp ? *gvp : NULL;
+ if (!*gv || *gv == (const GV *)&PL_sv_undef) {
+ goto notok;
+ }
+ /* here we know that *gv && *gv != &PL_sv_undef */
+ if (SvTYPE(*gv) != SVt_PVGV)
+ gv_init_pvn(*gv, *stash, key, *len, (add & GV_ADDMULTI)|is_utf8);
+ else
+ GvMULTI_on(*gv);
+
+ if (!(*stash = GvHV(*gv))) {
+ *stash = GvHV(*gv) = newHV();
+ if (!HvNAME_get(*stash)) {
+ if (GvSTASH(*gv) == PL_defstash && *len == 6
+ && strBEGINs(*name, "CORE"))
+ hv_name_sets(*stash, "CORE", 0);
+ else
+ hv_name_set(
+ *stash, nambeg, name_cursor-nambeg, is_utf8
+ );
+ /* If the containing stash has multiple effective
+ names, see that this one gets them, too. */
+ if (HvAUX(GvSTASH(*gv))->xhv_name_count)
+ mro_package_moved(*stash, NULL, *gv, 1);
+ }
+ }
+ else if (!HvNAME_get(*stash))
+ hv_name_set(*stash, nambeg, name_cursor - nambeg, is_utf8);
+ }
- if (!(stash = GvHV(gv)))
- {
- stash = GvHV(gv) = newHV();
- if (!HvNAME_get(stash)) {
- if (GvSTASH(gv) == PL_defstash && len == 6
- && strnEQ(name, "CORE", 4))
- hv_name_set(stash, "CORE", 4, 0);
- else
- hv_name_set(
- stash, nambeg, name_cursor-nambeg, is_utf8
- );
- /* If the containing stash has multiple effective
- names, see that this one gets them, too. */
- if (HvAUX(GvSTASH(gv))->xhv_name_count)
- mro_package_moved(stash, NULL, gv, 1);
+ if (*name_cursor == ':')
+ name_cursor++;
+ *name = name_cursor+1;
+ if (*name == name_end) {
+ if (!*gv) {
+ *gv = MUTABLE_GV(*hv_fetchs(PL_defstash, "main::", TRUE));
+ if (SvTYPE(*gv) != SVt_PVGV) {
+ gv_init_pvn(*gv, PL_defstash, "main::", 6,
+ GV_ADDMULTI);
+ GvHV(*gv) =
+ MUTABLE_HV(SvREFCNT_inc_simple(PL_defstash));
}
}
- else if (!HvNAME_get(stash))
- hv_name_set(stash, nambeg, name_cursor - nambeg, is_utf8);
- }
-
- if (*name_cursor == ':')
- name_cursor++;
- name = name_cursor+1;
- if (name == name_end)
- return gv
- ? gv : MUTABLE_GV(*hv_fetchs(PL_defstash, "main::", TRUE));
- }
+ goto ok;
+ }
+ }
}
- len = name_cursor - name;
+ *len = name_cursor - *name;
+ ok:
+ Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */
+ return TRUE;
+ notok:
+ Safefree(tmpfullbuf); /* free our tmpfullbuf if it was used */
+ return FALSE;
+}
- /* No stash in name, so see how we can default */
- if (!stash) {
- no_stash:
- if (len && isIDFIRST_lazy_if(name, is_utf8)) {
- bool global = FALSE;
-
- switch (len) {
- case 1:
- if (*name == '_')
- global = TRUE;
- break;
- case 3:
- if ((name[0] == 'I' && name[1] == 'N' && name[2] == 'C')
- || (name[0] == 'E' && name[1] == 'N' && name[2] == 'V')
- || (name[0] == 'S' && name[1] == 'I' && name[2] == 'G'))
- global = TRUE;
- break;
- case 4:
- if (name[0] == 'A' && name[1] == 'R' && name[2] == 'G'
- && name[3] == 'V')
- global = TRUE;
- break;
- case 5:
- if (name[0] == 'S' && name[1] == 'T' && name[2] == 'D'
- && name[3] == 'I' && name[4] == 'N')
- global = TRUE;
- break;
- case 6:
- if ((name[0] == 'S' && name[1] == 'T' && name[2] == 'D')
- &&((name[3] == 'O' && name[4] == 'U' && name[5] == 'T')
- ||(name[3] == 'E' && name[4] == 'R' && name[5] == 'R')))
- global = TRUE;
- break;
- case 7:
- if (name[0] == 'A' && name[1] == 'R' && name[2] == 'G'
- && name[3] == 'V' && name[4] == 'O' && name[5] == 'U'
- && name[6] == 'T')
- global = TRUE;
- break;
- }
-
- if (global)
- stash = PL_defstash;
- else if (IN_PERL_COMPILETIME) {
- stash = PL_curstash;
- if (add && (PL_hints & HINT_STRICT_VARS) &&
- sv_type != SVt_PVCV &&
- sv_type != SVt_PVGV &&
- sv_type != SVt_PVFM &&
- sv_type != SVt_PVIO &&
- !(len == 1 && sv_type == SVt_PV &&
- (*name == 'a' || *name == 'b')) )
- {
- gvp = (GV**)hv_fetch(stash,name,is_utf8 ? -len : len,0);
- if (!gvp ||
- *gvp == (const GV *)&PL_sv_undef ||
- SvTYPE(*gvp) != SVt_PVGV)
- {
- stash = NULL;
- }
- else if ((sv_type == SVt_PV && !GvIMPORTED_SV(*gvp)) ||
- (sv_type == SVt_PVAV && !GvIMPORTED_AV(*gvp)) ||
- (sv_type == SVt_PVHV && !GvIMPORTED_HV(*gvp)) )
- {
- /* diag_listed_as: Variable "%s" is not imported%s */
- Perl_ck_warner_d(
- aTHX_ packWARN(WARN_MISC),
- "Variable \"%c%"UTF8f"\" is not imported",
- sv_type == SVt_PVAV ? '@' :
- sv_type == SVt_PVHV ? '%' : '$',
- UTF8fARG(is_utf8, len, name));
- if (GvCVu(*gvp))
- Perl_ck_warner_d(
- aTHX_ packWARN(WARN_MISC),
- "\t(Did you mean &%"UTF8f" instead?)\n",
- UTF8fARG(is_utf8, len, name)
- );
- stash = NULL;
- }
- }
- }
- else
- stash = CopSTASH(PL_curcop);
- }
- else
- stash = PL_defstash;
+/* Checks if an unqualified name is in the main stash */
+PERL_STATIC_INLINE bool
+S_gv_is_in_main(pTHX_ const char *name, STRLEN len, const U32 is_utf8)
+{
+ PERL_ARGS_ASSERT_GV_IS_IN_MAIN;
+
+ /* If it's an alphanumeric variable */
+ if ( len && isIDFIRST_lazy_if_safe(name, name + len, is_utf8) ) {
+ /* Some "normal" variables are always in main::,
+ * like INC or STDOUT.
+ */
+ switch (len) {
+ case 1:
+ if (*name == '_')
+ return TRUE;
+ break;
+ case 3:
+ if ((name[0] == 'I' && name[1] == 'N' && name[2] == 'C')
+ || (name[0] == 'E' && name[1] == 'N' && name[2] == 'V')
+ || (name[0] == 'S' && name[1] == 'I' && name[2] == 'G'))
+ return TRUE;
+ break;
+ case 4:
+ if (name[0] == 'A' && name[1] == 'R' && name[2] == 'G'
+ && name[3] == 'V')
+ return TRUE;
+ break;
+ case 5:
+ if (name[0] == 'S' && name[1] == 'T' && name[2] == 'D'
+ && name[3] == 'I' && name[4] == 'N')
+ return TRUE;
+ break;
+ case 6:
+ if ((name[0] == 'S' && name[1] == 'T' && name[2] == 'D')
+ &&((name[3] == 'O' && name[4] == 'U' && name[5] == 'T')
+ ||(name[3] == 'E' && name[4] == 'R' && name[5] == 'R')))
+ return TRUE;
+ break;
+ case 7:
+ if (name[0] == 'A' && name[1] == 'R' && name[2] == 'G'
+ && name[3] == 'V' && name[4] == 'O' && name[5] == 'U'
+ && name[6] == 'T')
+ return TRUE;
+ break;
+ }
}
+ /* *{""}, or a special variable like $@ */
+ else
+ return TRUE;
+
+ return FALSE;
+}
- /* By this point we should have a stash and a name */
-
- if (!stash) {
- if (add && !PL_in_clean_all) {
- SV * const err = Perl_mess(aTHX_
- "Global symbol \"%s%"UTF8f
- "\" requires explicit package name",
- (sv_type == SVt_PV ? "$"
- : sv_type == SVt_PVAV ? "@"
- : sv_type == SVt_PVHV ? "%"
- : ""), UTF8fARG(is_utf8, len, name));
- GV *gv;
- if (is_utf8)
- SvUTF8_on(err);
- qerror(err);
- gv = gv_fetchpvs("<none>::", GV_ADDMULTI, SVt_PVHV);
- if(!gv) {
- /* symbol table under destruction */
- return NULL;
- }
- stash = GvHV(gv);
- }
- else
- return NULL;
- }
- if (!SvREFCNT(stash)) /* symbol table under destruction */
- return NULL;
+/* This function is called if parse_gv_stash_name() failed to
+ * find a stash, or if GV_NOTQUAL or an empty name was passed
+ * to gv_fetchpvn_flags.
+ *
+ * It returns FALSE if the default stash can't be found nor created,
+ * which might happen during global destruction.
+ */
+PERL_STATIC_INLINE bool
+S_find_default_stash(pTHX_ HV **stash, const char *name, STRLEN len,
+ const U32 is_utf8, const I32 add,
+ const svtype sv_type)
+{
+ PERL_ARGS_ASSERT_FIND_DEFAULT_STASH;
+
+ /* No stash in name, so see how we can default */
- gvp = (GV**)hv_fetch(stash,name,is_utf8 ? -len : len,add);
- if (!gvp || *gvp == (const GV *)&PL_sv_undef) {
- if (addmg) gv = (GV *)newSV(0);
- else return NULL;
+ if ( gv_is_in_main(name, len, is_utf8) ) {
+ *stash = PL_defstash;
}
- else gv = *gvp, addmg = 0;
- /* From this point on, addmg means gv has not been inserted in the
- symtab yet. */
-
- if (SvTYPE(gv) == SVt_PVGV) {
- if (add) {
- GvMULTI_on(gv);
- gv_init_svtype(gv, sv_type);
- /* You reach this path once the typeglob has already been created,
- either by the same or a different sigil. If this path didn't
- exist, then (say) referencing $! first, and %! second would
- mean that %! was not handled correctly. */
- if (len == 1 && stash == PL_defstash) {
- if (sv_type == SVt_PVHV || sv_type == SVt_PVGV) {
- if (*name == '!')
- require_tie_mod(gv, "!", newSVpvs("Errno"), "TIEHASH", 1);
- else if (*name == '-' || *name == '+')
- require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "TIEHASH", 0);
- } else if (sv_type == SVt_PV) {
- if (*name == '*' || *name == '#') {
- /* diag_listed_as: $* is no longer supported */
- Perl_ck_warner_d(aTHX_ packWARN2(WARN_DEPRECATED,
- WARN_SYNTAX),
- "$%c is no longer supported", *name);
- }
- }
- if (sv_type==SVt_PV || sv_type==SVt_PVGV) {
- switch (*name) {
- case '[':
- require_tie_mod(gv,name,newSVpvs("arybase"),"FETCH",0);
- break;
-#ifdef PERL_SAWAMPERSAND
- case '`':
- PL_sawampersand |= SAWAMPERSAND_LEFT;
- (void)GvSVn(gv);
- break;
- case '&':
- PL_sawampersand |= SAWAMPERSAND_MIDDLE;
- (void)GvSVn(gv);
- break;
- case '\'':
- PL_sawampersand |= SAWAMPERSAND_RIGHT;
- (void)GvSVn(gv);
- break;
-#endif
+ else {
+ if (IN_PERL_COMPILETIME) {
+ *stash = PL_curstash;
+ if (add && (PL_hints & HINT_STRICT_VARS) &&
+ sv_type != SVt_PVCV &&
+ sv_type != SVt_PVGV &&
+ sv_type != SVt_PVFM &&
+ sv_type != SVt_PVIO &&
+ !(len == 1 && sv_type == SVt_PV &&
+ (*name == 'a' || *name == 'b')) )
+ {
+ GV**gvp = (GV**)hv_fetch(*stash,name,is_utf8 ? -(I32)len : (I32)len,0);
+ if (!gvp || *gvp == (const GV *)&PL_sv_undef ||
+ SvTYPE(*gvp) != SVt_PVGV)
+ {
+ *stash = NULL;
}
- }
- }
- else if (len == 3 && sv_type == SVt_PVAV
- && strnEQ(name, "ISA", 3)
- && (!GvAV(gv) || !SvSMAGICAL(GvAV(gv))))
- gv_magicalize_isa(gv);
- }
- return gv;
- } else if (no_init) {
- assert(!addmg);
- return gv;
- } else if (no_expand && SvROK(gv)) {
- assert(!addmg);
- return gv;
+ else if ((sv_type == SVt_PV && !GvIMPORTED_SV(*gvp)) ||
+ (sv_type == SVt_PVAV && !GvIMPORTED_AV(*gvp)) ||
+ (sv_type == SVt_PVHV && !GvIMPORTED_HV(*gvp)) )
+ {
+ /* diag_listed_as: Variable "%s" is not imported%s */
+ Perl_ck_warner_d(
+ aTHX_ packWARN(WARN_MISC),
+ "Variable \"%c%" UTF8f "\" is not imported",
+ sv_type == SVt_PVAV ? '@' :
+ sv_type == SVt_PVHV ? '%' : '$',
+ UTF8fARG(is_utf8, len, name));
+ if (GvCVu(*gvp))
+ Perl_ck_warner_d(
+ aTHX_ packWARN(WARN_MISC),
+ "\t(Did you mean &%" UTF8f " instead?)\n",
+ UTF8fARG(is_utf8, len, name)
+ );
+ *stash = NULL;
+ }
+ }
+ }
+ else {
+ /* Use the current op's stash */
+ *stash = CopSTASH(PL_curcop);
+ }
}
- /* Adding a new symbol.
- Unless of course there was already something non-GV here, in which case
- we want to behave as if there was always a GV here, containing some sort
- of subroutine.
- Otherwise we run the risk of creating things like GvIO, which can cause
- subtle bugs. eg the one that tripped up SQL::Translator */
+ if (!*stash) {
+ if (add && !PL_in_clean_all) {
+ GV *gv;
+ qerror(Perl_mess(aTHX_
+ "Global symbol \"%s%" UTF8f
+ "\" requires explicit package name (did you forget to "
+ "declare \"my %s%" UTF8f "\"?)",
+ (sv_type == SVt_PV ? "$"
+ : sv_type == SVt_PVAV ? "@"
+ : sv_type == SVt_PVHV ? "%"
+ : ""), UTF8fARG(is_utf8, len, name),
+ (sv_type == SVt_PV ? "$"
+ : sv_type == SVt_PVAV ? "@"
+ : sv_type == SVt_PVHV ? "%"
+ : ""), UTF8fARG(is_utf8, len, name)));
+ /* To maintain the output of errors after the strict exception
+ * above, and to keep compat with older releases, rather than
+ * placing the variables in the pad, we place
+ * them in the <none>:: stash.
+ */
+ gv = gv_fetchpvs("<none>::", GV_ADDMULTI, SVt_PVHV);
+ if (!gv) {
+ /* symbol table under destruction */
+ return FALSE;
+ }
+ *stash = GvHV(gv);
+ }
+ else
+ return FALSE;
+ }
- faking_it = SvOK(gv);
+ if (!SvREFCNT(*stash)) /* symbol table under destruction */
+ return FALSE;
- if (add & GV_ADDWARN)
- Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL),
- "Had to create %"UTF8f" unexpectedly",
- UTF8fARG(is_utf8, name_end-nambeg, nambeg));
- gv_init_pvn(gv, stash, name, len, (add & GV_ADDMULTI)|is_utf8);
+ return TRUE;
+}
- if ( isIDFIRST_lazy_if(name, is_utf8)
- && ! (isLEXWARN_on ? ckWARN(WARN_ONCE) : (PL_dowarn & G_WARN_ON ) ) )
- GvMULTI_on(gv) ;
+/* gv_magicalize only turns on the SVf_READONLY flag, not SVf_PROTECT. So
+ redefine SvREADONLY_on for that purpose. We don’t use it later on in
+ this file. */
+#undef SvREADONLY_on
+#define SvREADONLY_on(sv) (SvFLAGS(sv) |= SVf_READONLY)
+
+/* gv_magicalize() is called by gv_fetchpvn_flags when creating
+ * a new GV.
+ * Note that it does not insert the GV into the stash prior to
+ * magicalization, which some variables require need in order
+ * to work (like %+, %-, %!), so callers must take care of
+ * that.
+ *
+ * It returns true if the gv did turn out to be magical one; i.e.,
+ * if gv_magicalize actually did something.
+ */
+PERL_STATIC_INLINE bool
+S_gv_magicalize(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len,
+ const svtype sv_type)
+{
+ SSize_t paren;
- /* set up magic where warranted */
+ PERL_ARGS_ASSERT_GV_MAGICALIZE;
+
if (stash != PL_defstash) { /* not the main stash */
- /* We only have to check for three names here: EXPORT, ISA
+ /* We only have to check for a few names here: a, b, EXPORT, ISA
and VERSION. All the others apply only to the main stash or to
CORE (which is checked right after this). */
- if (len > 2) {
- const char * const name2 = name + 1;
+ if (len) {
switch (*name) {
case 'E':
- if (strnEQ(name2, "XPORT", 5))
+ if (
+ len >= 6 && name[1] == 'X' &&
+ (memEQs(name, len, "EXPORT")
+ ||memEQs(name, len, "EXPORT_OK")
+ ||memEQs(name, len, "EXPORT_FAIL")
+ ||memEQs(name, len, "EXPORT_TAGS"))
+ )
GvMULTI_on(gv);
break;
case 'I':
- if (strEQ(name2, "SA"))
+ if (memEQs(name, len, "ISA"))
gv_magicalize_isa(gv);
break;
case 'V':
- if (strEQ(name2, "ERSION"))
+ if (memEQs(name, len, "VERSION"))
GvMULTI_on(gv);
break;
+ case 'a':
+ if (stash == PL_debstash && memEQs(name, len, "args")) {
+ GvMULTI_on(gv_AVadd(gv));
+ break;
+ }
+ /* FALLTHROUGH */
+ case 'b':
+ if (len == 1 && sv_type == SVt_PV)
+ GvMULTI_on(gv);
+ /* FALLTHROUGH */
default:
goto try_core;
}
- goto add_magical_gv;
+ goto ret;
}
try_core:
if (len > 1 /* shortest is uc */ && HvNAMELEN_get(stash) == 4) {
/* Avoid null warning: */
const char * const stashname = HvNAME(stash); assert(stashname);
- if (strnEQ(stashname, "CORE", 4))
+ if (strBEGINs(stashname, "CORE"))
S_maybe_add_coresub(aTHX_ 0, gv, name, len);
}
}
/* 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. */
+ the common case of lower case variable names. (On EBCDIC
+ platforms, we can't just do:
+ if (NATIVE_TO_ASCII(*name) > NATIVE_TO_ASCII('V') ) {
+ because cases like '\027' in the switch statement below are
+ C1 (non-ASCII) controls on those platforms, so the remapping
+ would make them larger than 'V')
+ */
} else
#endif
{
- const char * const name2 = name + 1;
switch (*name) {
case 'A':
- if (strEQ(name2, "RGV")) {
+ if (memEQs(name, len, "ARGV")) {
IoFLAGS(GvIOn(gv)) |= IOf_ARGV|IOf_START;
}
- else if (strEQ(name2, "RGVOUT")) {
+ else if (memEQs(name, len, "ARGVOUT")) {
GvMULTI_on(gv);
}
break;
case 'E':
- if (strnEQ(name2, "XPORT", 5))
+ if (
+ len >= 6 && name[1] == 'X' &&
+ (memEQs(name, len, "EXPORT")
+ ||memEQs(name, len, "EXPORT_OK")
+ ||memEQs(name, len, "EXPORT_FAIL")
+ ||memEQs(name, len, "EXPORT_TAGS"))
+ )
GvMULTI_on(gv);
break;
case 'I':
- if (strEQ(name2, "SA")) {
+ if (memEQs(name, len, "ISA")) {
gv_magicalize_isa(gv);
}
break;
case 'S':
- if (strEQ(name2, "IG")) {
+ if (memEQs(name, len, "SIG")) {
HV *hv;
I32 i;
if (!PL_psig_name) {
}
break;
case 'V':
- if (strEQ(name2, "ERSION"))
+ if (memEQs(name, len, "VERSION"))
GvMULTI_on(gv);
break;
case '\003': /* $^CHILD_ERROR_NATIVE */
- if (strEQ(name2, "HILD_ERROR_NATIVE"))
+ if (memEQs(name, len, "\003HILD_ERROR_NATIVE"))
goto magicalize;
+ /* @{^CAPTURE} %{^CAPTURE} */
+ if (memEQs(name, len, "\003APTURE")) {
+ AV* const av = GvAVn(gv);
+ const Size_t n = *name;
+
+ sv_magic(MUTABLE_SV(av), (SV*)n, PERL_MAGIC_regdata, NULL, 0);
+ SvREADONLY_on(av);
+
+ require_tie_mod_s(gv, '+', "Tie::Hash::NamedCapture",0);
+
+ } else /* %{^CAPTURE_ALL} */
+ if (memEQs(name, len, "\003APTURE_ALL")) {
+ require_tie_mod_s(gv, '-', "Tie::Hash::NamedCapture",0);
+ }
break;
case '\005': /* $^ENCODING */
- if (strEQ(name2, "NCODING"))
+ if (memEQs(name, len, "\005NCODING"))
goto magicalize;
break;
+ case '\006':
+ if (memEQs(name, len, "\006EATURE_BITS"))
+ goto magicalize;
+ break;
case '\007': /* $^GLOBAL_PHASE */
- if (strEQ(name2, "LOBAL_PHASE"))
+ if (memEQs(name, len, "\007LOBAL_PHASE"))
goto ro_magicalize;
break;
case '\014': /* $^LAST_FH */
- if (strEQ(name2, "AST_FH"))
+ if (memEQs(name, len, "\014AST_FH"))
goto ro_magicalize;
break;
case '\015': /* $^MATCH */
- if (strEQ(name2, "ATCH"))
- goto magicalize;
+ if (memEQs(name, len, "\015ATCH")) {
+ paren = RX_BUFF_IDX_CARET_FULLMATCH;
+ goto storeparen;
+ }
+ break;
case '\017': /* $^OPEN */
- if (strEQ(name2, "PEN"))
+ if (memEQs(name, len, "\017PEN"))
goto magicalize;
break;
case '\020': /* $^PREMATCH $^POSTMATCH */
- if (strEQ(name2, "REMATCH") || strEQ(name2, "OSTMATCH"))
- goto magicalize;
+ if (memEQs(name, len, "\020REMATCH")) {
+ paren = RX_BUFF_IDX_CARET_PREMATCH;
+ goto storeparen;
+ }
+ if (memEQs(name, len, "\020OSTMATCH")) {
+ paren = RX_BUFF_IDX_CARET_POSTMATCH;
+ goto storeparen;
+ }
+ break;
+ case '\023':
+ if (memEQs(name, len, "\023AFE_LOCALES"))
+ goto ro_magicalize;
break;
case '\024': /* ${^TAINT} */
- if (strEQ(name2, "AINT"))
+ if (memEQs(name, len, "\024AINT"))
goto ro_magicalize;
break;
case '\025': /* ${^UNICODE}, ${^UTF8LOCALE} */
- if (strEQ(name2, "NICODE"))
+ if (memEQs(name, len, "\025NICODE"))
goto ro_magicalize;
- if (strEQ(name2, "TF8LOCALE"))
+ if (memEQs(name, len, "\025TF8LOCALE"))
goto ro_magicalize;
- if (strEQ(name2, "TF8CACHE"))
+ if (memEQs(name, len, "\025TF8CACHE"))
goto magicalize;
break;
case '\027': /* $^WARNING_BITS */
- if (strEQ(name2, "ARNING_BITS"))
+ if (memEQs(name, len, "\027ARNING_BITS"))
goto magicalize;
+#ifdef WIN32
+ else if (memEQs(name, len, "\027IN32_SLOPPY_STAT"))
+ goto magicalize;
+#endif
break;
case '1':
case '2':
{
/* Ensures that we have an all-digit variable, ${"1foo"} fails
this test */
- /* This snippet is taken from is_gv_magical */
- const char *end = name + len;
- while (--end > name) {
- if (!isDIGIT(*end)) goto add_magical_gv;
- }
- goto magicalize;
+ UV uv;
+ if (!grok_atoUV(name, &uv, NULL) || uv > I32_MAX)
+ goto ret;
+ /* XXX why are we using a SSize_t? */
+ paren = (SSize_t)(I32)uv;
+ goto storeparen;
}
}
}
be case '\0' in this switch statement (ie a default case) */
switch (*name) {
case '&': /* $& */
+ paren = RX_BUFF_IDX_FULLMATCH;
+ goto sawampersand;
case '`': /* $` */
+ paren = RX_BUFF_IDX_PREMATCH;
+ goto sawampersand;
case '\'': /* $' */
+ paren = RX_BUFF_IDX_POSTMATCH;
+ sawampersand:
#ifdef PERL_SAWAMPERSAND
if (!(
sv_type == SVt_PVAV ||
: SAWAMPERSAND_RIGHT;
}
#endif
- goto magicalize;
+ goto storeparen;
+ case '1': /* $1 */
+ case '2': /* $2 */
+ case '3': /* $3 */
+ case '4': /* $4 */
+ case '5': /* $5 */
+ case '6': /* $6 */
+ case '7': /* $7 */
+ case '8': /* $8 */
+ case '9': /* $9 */
+ paren = *name - '0';
+
+ storeparen:
+ /* Flag the capture variables with a NULL mg_ptr
+ Use mg_len for the array index to lookup. */
+ sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, NULL, paren);
+ break;
case ':': /* $: */
sv_setpv(GvSVn(gv),PL_chopset);
sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, name, len);
- /* magicalization must be done before require_tie_mod is called */
+ /* magicalization must be done before require_tie_mod_s is called */
if (sv_type == SVt_PVHV || sv_type == SVt_PVGV)
- {
- if (addmg) (void)hv_store(stash,name,len,(SV *)gv,0);
- addmg = 0;
- require_tie_mod(gv, "!", newSVpvs("Errno"), "TIEHASH", 1);
- }
+ require_tie_mod_s(gv, '!', "Errno", 1);
break;
- case '-': /* $- */
- case '+': /* $+ */
- GvMULTI_on(gv); /* no used once warnings here */
- {
- AV* const av = GvAVn(gv);
- SV* const avc = (*name == '+') ? MUTABLE_SV(av) : NULL;
-
- 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);
-
- if (sv_type == SVt_PVHV || sv_type == SVt_PVGV)
- {
- if (addmg) (void)hv_store(stash,name,len,(SV *)gv,0);
- addmg = 0;
- require_tie_mod(gv, name, newSVpvs("Tie::Hash::NamedCapture"), "TIEHASH", 0);
- }
+ case '-': /* $-, %-, @- */
+ case '+': /* $+, %+, @+ */
+ GvMULTI_on(gv); /* no used once warnings here */
+ { /* $- $+ */
+ sv_magic(GvSVn(gv), MUTABLE_SV(gv), PERL_MAGIC_sv, name, len);
+ if (*name == '+')
+ SvREADONLY_on(GvSVn(gv));
+ }
+ { /* %- %+ */
+ if (sv_type == SVt_PVHV || sv_type == SVt_PVGV)
+ require_tie_mod_s(gv, *name, "Tie::Hash::NamedCapture",0);
+ }
+ { /* @- @+ */
+ AV* const av = GvAVn(gv);
+ const Size_t n = *name;
+ sv_magic(MUTABLE_SV(av), (SV*)n, PERL_MAGIC_regdata, NULL, 0);
+ SvREADONLY_on(av);
+ }
break;
- }
case '*': /* $* */
case '#': /* $# */
- if (sv_type == SVt_PV)
- /* diag_listed_as: $* is no longer supported */
- Perl_ck_warner_d(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX),
- "$%c is no longer supported", *name);
- break;
+ if (sv_type == SVt_PV)
+ /* diag_listed_as: $* is no longer supported as of Perl 5.30 */
+ Perl_croak(aTHX_ "$%c is no longer supported as of Perl 5.30", *name);
+ break;
case '\010': /* $^H */
{
HV *const hv = GvHVn(gv);
hv_magic(hv, NULL, PERL_MAGIC_hints);
}
goto magicalize;
- case '[': /* $[ */
- if ((sv_type == SVt_PV || sv_type == SVt_PVGV)
- && FEATURE_ARYBASE_IS_ENABLED) {
- if (addmg) (void)hv_store(stash,name,len,(SV *)gv,0);
- require_tie_mod(gv,name,newSVpvs("arybase"),"FETCH",0);
- addmg = 0;
- }
- else goto magicalize;
- break;
case '\023': /* $^S */
ro_magicalize:
SvREADONLY_on(GvSVn(gv));
- /* FALL THROUGH */
+ /* FALLTHROUGH */
case '0': /* $0 */
- case '1': /* $1 */
- case '2': /* $2 */
- case '3': /* $3 */
- case '4': /* $4 */
- case '5': /* $5 */
- case '6': /* $6 */
- case '7': /* $7 */
- case '8': /* $8 */
- case '9': /* $9 */
case '^': /* $^ */
case '~': /* $~ */
case '=': /* $= */
case '/': /* $/ */
case '|': /* $| */
case '$': /* $$ */
+ case '[': /* $[ */
case '\001': /* $^A */
case '\003': /* $^C */
case '\004': /* $^D */
SvREFCNT_dec(sv);
}
break;
+ case 'a':
+ case 'b':
+ if (sv_type == SVt_PV)
+ GvMULTI_on(gv);
}
}
- add_magical_gv:
- if (addmg) {
- if (GvAV(gv) || GvHV(gv) || GvIO(gv) || GvCV(gv) || (
- GvSV(gv) && (SvOK(GvSV(gv)) || SvMAGICAL(GvSV(gv)))
- ))
- (void)hv_store(stash,name,len,(SV *)gv,0);
- else SvREFCNT_dec_NN(gv), gv = NULL;
+
+ ret:
+ /* Return true if we actually did something. */
+ return GvAV(gv) || GvHV(gv) || GvIO(gv) || GvCV(gv)
+ || ( GvSV(gv) && (
+ SvOK(GvSV(gv)) || SvMAGICAL(GvSV(gv))
+ )
+ );
+}
+
+/* If we do ever start using this later on in the file, we need to make
+ sure we don’t accidentally use the wrong definition. */
+#undef SvREADONLY_on
+
+/* This function is called when the stash already holds the GV of the magic
+ * variable we're looking for, but we need to check that it has the correct
+ * kind of magic. For example, if someone first uses $! and then %!, the
+ * latter would end up here, and we add the Errno tie to the HASH slot of
+ * the *! glob.
+ */
+PERL_STATIC_INLINE void
+S_maybe_multimagic_gv(pTHX_ GV *gv, const char *name, const svtype sv_type)
+{
+ PERL_ARGS_ASSERT_MAYBE_MULTIMAGIC_GV;
+
+ if (sv_type == SVt_PVHV || sv_type == SVt_PVGV) {
+ if (*name == '!')
+ require_tie_mod_s(gv, '!', "Errno", 1);
+ else if (*name == '-' || *name == '+')
+ require_tie_mod_s(gv, *name, "Tie::Hash::NamedCapture", 0);
+ } else if (sv_type == SVt_PV) {
+ if (*name == '*' || *name == '#') {
+ /* diag_listed_as: $* is no longer supported as of Perl 5.30 */
+ Perl_croak(aTHX_ "$%c is no longer supported as of Perl 5.30", *name);
+ }
}
+ if (sv_type==SVt_PV || sv_type==SVt_PVGV) {
+ switch (*name) {
+#ifdef PERL_SAWAMPERSAND
+ case '`':
+ PL_sawampersand |= SAWAMPERSAND_LEFT;
+ (void)GvSVn(gv);
+ break;
+ case '&':
+ PL_sawampersand |= SAWAMPERSAND_MIDDLE;
+ (void)GvSVn(gv);
+ break;
+ case '\'':
+ PL_sawampersand |= SAWAMPERSAND_RIGHT;
+ (void)GvSVn(gv);
+ break;
+#endif
+ }
+ }
+}
+
+GV *
+Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags,
+ const svtype sv_type)
+{
+ const char *name = nambeg;
+ GV *gv = NULL;
+ GV**gvp;
+ STRLEN len;
+ HV *stash = NULL;
+ const I32 no_init = flags & (GV_NOADD_NOINIT | GV_NOINIT);
+ const I32 no_expand = flags & GV_NOEXPAND;
+ const I32 add = flags & ~GV_NOADD_MASK;
+ const U32 is_utf8 = flags & SVf_UTF8;
+ bool addmg = cBOOL(flags & GV_ADDMG);
+ const char *const name_end = nambeg + full_len;
+ U32 faking_it;
+
+ PERL_ARGS_ASSERT_GV_FETCHPVN_FLAGS;
+
+ /* If we have GV_NOTQUAL, the caller promised that
+ * there is no stash, so we can skip the check.
+ * Similarly if full_len is 0, since then we're
+ * dealing with something like *{""} or ""->foo()
+ */
+ if ((flags & GV_NOTQUAL) || !full_len) {
+ len = full_len;
+ }
+ else if (parse_gv_stash_name(&stash, &gv, &name, &len, nambeg, full_len, is_utf8, add)) {
+ if (name == name_end) return gv;
+ }
+ else {
+ return NULL;
+ }
+
+ if (!stash && !find_default_stash(&stash, name, len, is_utf8, add, sv_type)) {
+ return NULL;
+ }
+
+ /* By this point we should have a stash and a name */
+ gvp = (GV**)hv_fetch(stash,name,is_utf8 ? -(I32)len : (I32)len,add);
+ if (!gvp || *gvp == (const GV *)&PL_sv_undef) {
+ if (addmg) gv = (GV *)newSV(0);
+ else return NULL;
+ }
+ else gv = *gvp, addmg = 0;
+ /* From this point on, addmg means gv has not been inserted in the
+ symtab yet. */
+
+ if (SvTYPE(gv) == SVt_PVGV) {
+ /* The GV already exists, so return it, but check if we need to do
+ * anything else with it before that.
+ */
+ if (add) {
+ /* This is the heuristic that handles if a variable triggers the
+ * 'used only once' warning. If there's already a GV in the stash
+ * with this name, then we assume that the variable has been used
+ * before and turn its MULTI flag on.
+ * It's a heuristic because it can easily be "tricked", like with
+ * BEGIN { $a = 1; $::{foo} = *a }; () = $foo
+ * not warning about $main::foo being used just once
+ */
+ GvMULTI_on(gv);
+ gv_init_svtype(gv, sv_type);
+ /* You reach this path once the typeglob has already been created,
+ either by the same or a different sigil. If this path didn't
+ exist, then (say) referencing $! first, and %! second would
+ mean that %! was not handled correctly. */
+ if (len == 1 && stash == PL_defstash) {
+ maybe_multimagic_gv(gv, name, sv_type);
+ }
+ else if (sv_type == SVt_PVAV
+ && memEQs(name, len, "ISA")
+ && (!GvAV(gv) || !SvSMAGICAL(GvAV(gv))))
+ gv_magicalize_isa(gv);
+ }
+ return gv;
+ } else if (no_init) {
+ assert(!addmg);
+ return gv;
+ }
+ /* If GV_NOEXPAND is true and what we got off the stash is a ref,
+ * don't expand it to a glob. This is an optimization so that things
+ * copying constants over, like Exporter, don't have to be rewritten
+ * to take into account that you can store more than just globs in
+ * stashes.
+ */
+ else if (no_expand && SvROK(gv)) {
+ assert(!addmg);
+ return gv;
+ }
+
+ /* Adding a new symbol.
+ Unless of course there was already something non-GV here, in which case
+ we want to behave as if there was always a GV here, containing some sort
+ of subroutine.
+ Otherwise we run the risk of creating things like GvIO, which can cause
+ subtle bugs. eg the one that tripped up SQL::Translator */
+
+ faking_it = SvOK(gv);
+
+ if (add & GV_ADDWARN)
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_INTERNAL),
+ "Had to create %" UTF8f " unexpectedly",
+ UTF8fARG(is_utf8, name_end-nambeg, nambeg));
+ gv_init_pvn(gv, stash, name, len, (add & GV_ADDMULTI)|is_utf8);
+
+ if ( full_len != 0
+ && isIDFIRST_lazy_if_safe(name, name + full_len, is_utf8)
+ && !ckWARN(WARN_ONCE) )
+ {
+ GvMULTI_on(gv) ;
+ }
+
+ /* set up magic where warranted */
+ if ( gv_magicalize(gv, stash, name, len, sv_type) ) {
+ /* See 23496c6 */
+ if (addmg) {
+ /* gv_magicalize magicalised this gv, so we want it
+ * stored in the symtab.
+ * Effectively the caller is asking, ‘Does this gv exist?’
+ * And we respond, ‘Er, *now* it does!’
+ */
+ (void)hv_store(stash,name,len,(SV *)gv,0);
+ }
+ }
+ else if (addmg) {
+ /* The temporary GV created above */
+ SvREFCNT_dec_NN(gv);
+ gv = NULL;
+ }
+
if (gv) gv_init_svtype(gv, faking_it ? SVt_PVCV : sv_type);
return gv;
}
if (hv && (name = HvNAME(hv))) {
const STRLEN len = HvNAMELEN(hv);
- if (keepmain || strnNE(name, "main", len)) {
+ if (keepmain || ! memBEGINs(name, len, "main")) {
sv_catpvn_flags(sv,name,len,HvNAMEUTF8(hv)?SV_CATUTF8:SV_CATBYTES);
sv_catpvs(sv,"::");
}
gv_fullname4(sv, egv ? egv : gv, prefix, keepmain);
}
+
+/* recursively scan a stash and any nested stashes looking for entries
+ * that need the "only used once" warning raised
+ */
+
void
-Perl_gv_check(pTHX_ const HV *stash)
+Perl_gv_check(pTHX_ HV *stash)
{
- dVAR;
I32 i;
PERL_ARGS_ASSERT_GV_CHECK;
- if (!HvARRAY(stash))
+ if (!SvOOK(stash))
return;
+
+ assert(HvARRAY(stash));
+
for (i = 0; i <= (I32) HvMAX(stash); i++) {
const HE *entry;
+ /* mark stash is being scanned, to avoid recursing */
+ HvAUX(stash)->xhv_aux_flags |= HvAUXf_SCAN_STASH;
for (entry = HvARRAY(stash)[i]; entry; entry = HeNEXT(entry)) {
GV *gv;
HV *hv;
- if (HeKEY(entry)[HeKLEN(entry)-1] == ':' &&
+ STRLEN keylen = HeKLEN(entry);
+ const char * const key = HeKEY(entry);
+
+ if (keylen >= 2 && key[keylen-2] == ':' && key[keylen-1] == ':' &&
(gv = MUTABLE_GV(HeVAL(entry))) && isGV(gv) && (hv = GvHV(gv)))
{
- if (hv != PL_defstash && hv != stash)
+ if (hv != PL_defstash && hv != stash
+ && !(SvOOK(hv)
+ && (HvAUX(hv)->xhv_aux_flags & HvAUXf_SCAN_STASH))
+ )
gv_check(hv); /* nested package */
}
- else if ( *HeKEY(entry) != '_'
- && isIDFIRST_lazy_if(HeKEY(entry), HeUTF8(entry)) ) {
+ else if ( HeKLEN(entry) != 0
+ && *HeKEY(entry) != '_'
+ && isIDFIRST_lazy_if_safe(HeKEY(entry),
+ HeKEY(entry) + HeKLEN(entry),
+ HeUTF8(entry)) )
+ {
const char *file;
gv = MUTABLE_GV(HeVAL(entry));
if (SvTYPE(gv) != SVt_PVGV || GvMULTI(gv))
= gv_fetchfile_flags(file, HEK_LEN(GvFILE_HEK(gv)), 0);
#endif
Perl_warner(aTHX_ packWARN(WARN_ONCE),
- "Name \"%"HEKf"::%"HEKf
+ "Name \"%" HEKf "::%" HEKf
"\" used only once: possible typo",
HEKfARG(HvNAME_HEK(stash)),
HEKfARG(GvNAME_HEK(gv)));
}
}
+ HvAUX(stash)->xhv_aux_flags &= ~HvAUXf_SCAN_STASH;
}
}
GV *
Perl_newGVgen_flags(pTHX_ const char *pack, U32 flags)
{
- dVAR;
PERL_ARGS_ASSERT_NEWGVGEN_FLAGS;
assert(!(flags & ~SVf_UTF8));
- return gv_fetchpv(Perl_form(aTHX_ "%"UTF8f"::_GEN_%ld",
+ return gv_fetchpv(Perl_form(aTHX_ "%" UTF8f "::_GEN_%ld",
UTF8fARG(flags, strlen(pack), pack),
(long)PL_gensym++),
GV_ADD, SVt_PVGV);
GP*
Perl_gp_ref(pTHX_ GP *gp)
{
- dVAR;
if (!gp)
return NULL;
gp->gp_refcnt++;
void
Perl_gp_free(pTHX_ GV *gv)
{
- dVAR;
GP* gp;
int attempts = 100;
pTHX__FORMAT pTHX__VALUE);
return;
}
- if (--gp->gp_refcnt > 0) {
+ if (gp->gp_refcnt > 1) {
+ borrowed:
if (gp->gp_egv == gv)
gp->gp_egv = 0;
+ gp->gp_refcnt--;
GvGP_set(gv, NULL);
return;
}
Somehow gp->gp_hv can end up pointing at freed garbage. */
if (hv && SvTYPE(hv) == SVt_PVHV) {
const HEK *hvname_hek = HvNAME_HEK(hv);
- DEBUG_o(Perl_deb(aTHX_ "gp_free clearing PL_stashcache for '%"HEKf"'\n", hvname_hek));
- if (PL_stashcache && hvname_hek)
- (void)hv_delete(PL_stashcache, HEK_KEY(hvname_hek),
- (HEK_UTF8(hvname_hek) ? -HEK_LEN(hvname_hek) : HEK_LEN(hvname_hek)),
- G_DISCARD);
+ if (PL_stashcache && hvname_hek) {
+ DEBUG_o(Perl_deb(aTHX_
+ "gp_free clearing PL_stashcache for '%" HEKf "'\n",
+ HEKfARG(hvname_hek)));
+ (void)hv_deletehek(PL_stashcache, hvname_hek, G_DISCARD);
+ }
SvREFCNT_dec(hv);
}
+ if (io && SvREFCNT(io) == 1 && IoIFP(io)
+ && (IoTYPE(io) == IoTYPE_WRONLY ||
+ IoTYPE(io) == IoTYPE_RDWR ||
+ IoTYPE(io) == IoTYPE_APPEND)
+ && ckWARN_d(WARN_IO)
+ && IoIFP(io) != PerlIO_stdin()
+ && IoIFP(io) != PerlIO_stdout()
+ && IoIFP(io) != PerlIO_stderr()
+ && !(IoFLAGS(io) & IOf_FAKE_DIRP))
+ io_close(io, gv, FALSE, TRUE);
SvREFCNT_dec(io);
SvREFCNT_dec(cv);
SvREFCNT_dec(form);
+ /* Possibly reallocated by a destructor */
+ gp = GvGP(gv);
+
if (!gp->gp_file_hek
&& !gp->gp_sv
&& !gp->gp_av
}
}
+ /* Possibly incremented by a destructor doing glob assignment */
+ if (gp->gp_refcnt > 1) goto borrowed;
Safefree(gp);
GvGP_set(gv, NULL);
}
int
Perl_Gv_AMupdate(pTHX_ HV *stash, bool destructing)
{
- dVAR;
MAGIC* const mg = mg_find((const SV *)stash, PERL_MAGIC_overload_table);
AMT amt;
const struct mro_meta* stash_meta = HvMROMETA(stash);
{
int filled = 0;
int i;
+ bool deref_seen = 0;
+
/* Work with "fallback" key, which we assume to be first in PL_AMG_names */
filled = 1;
}
+ assert(SvOOK(stash));
+ /* initially assume the worst */
+ HvAUX(stash)->xhv_aux_flags &= ~HvAUXf_NO_DEREF;
+
for (i = 1; i < NofAMmeth; i++) {
const char * const cooky = PL_AMG_names[i];
/* Human-readable form, for debugging: */
numifying instead of C's "+0". */
gv = Perl_gv_fetchmeth_pvn(aTHX_ stash, cooky, l, -1, 0);
cv = 0;
- if (gv && (cv = GvCV(gv))) {
- if(GvNAMELEN(CvGV(cv)) == 3 && strEQ(GvNAME(CvGV(cv)), "nil")){
- const char * const hvname = HvNAME_get(GvSTASH(CvGV(cv)));
- if (hvname && HEK_LEN(HvNAME_HEK(GvSTASH(CvGV(cv)))) == 8
- && strEQ(hvname, "overload")) {
+ if (gv && (cv = GvCV(gv)) && CvHASGV(cv)) {
+ const HEK * const gvhek = CvGvNAME_HEK(cv);
+ const HEK * const stashek =
+ HvNAME_HEK(CvNAMED(cv) ? CvSTASH(cv) : GvSTASH(CvGV(cv)));
+ if (memEQs(HEK_KEY(gvhek), HEK_LEN(gvhek), "nil")
+ && stashek
+ && memEQs(HEK_KEY(stashek), HEK_LEN(stashek), "overload")) {
/* This is a hack to support autoloading..., while
knowing *which* methods were declared as overloaded. */
/* GvSV contains the name of the method. */
GV *ngv = NULL;
SV *gvsv = GvSV(gv);
- DEBUG_o( Perl_deb(aTHX_ "Resolving method \"%"SVf256\
+ DEBUG_o( Perl_deb(aTHX_ "Resolving method \"%" SVf256\
"\" for overloaded \"%s\" in package \"%.256s\"\n",
(void*)GvSV(gv), cp, HvNAME(stash)) );
if (!gvsv || !SvPOK(gvsv)
? gvsv
: newSVpvs_flags("???", SVs_TEMP);
/* diag_listed_as: Can't resolve method "%s" overloading "%s" in package "%s" */
- Perl_croak(aTHX_ "%s method \"%"SVf256
+ Perl_croak(aTHX_ "%s method \"%" SVf256
"\" overloading \"%s\" "\
- "in package \"%"HEKf256"\"",
+ "in package \"%" HEKf256 "\"",
(GvCVGEN(gv) ? "Stub found while resolving"
: "Can't resolve"),
SVfARG(name), cp,
}
}
cv = GvCV(gv = ngv);
- }
}
DEBUG_o( Perl_deb(aTHX_ "Overloading \"%s\" in package \"%.256s\" via \"%.256s::%.256s\"\n",
cp, HvNAME_get(stash), HvNAME_get(GvSTASH(CvGV(cv))),
filled = 1;
}
amt.table[i]=MUTABLE_CV(SvREFCNT_inc_simple(cv));
+
+ if (gv) {
+ switch (i) {
+ case to_sv_amg:
+ case to_av_amg:
+ case to_hv_amg:
+ case to_gv_amg:
+ case to_cv_amg:
+ case nomethod_amg:
+ deref_seen = 1;
+ break;
+ }
+ }
}
+ if (!deref_seen)
+ /* none of @{} etc overloaded; we can do $obj->[N] quicker.
+ * NB - aux var invalid here, HvARRAY() could have been
+ * reallocated since it was assigned to */
+ HvAUX(stash)->xhv_aux_flags |= HvAUXf_NO_DEREF;
+
if (filled) {
AMT_AMAGIC_on(&amt);
sv_magic(MUTABLE_SV(stash), 0, PERL_MAGIC_overload_table,
CV*
Perl_gv_handler(pTHX_ HV *stash, I32 id)
{
- dVAR;
MAGIC *mg;
AMT *amtp;
U32 newgen;
/* Implement tryAMAGICun_MG macro.
Do get magic, then see if the stack arg is overloaded and if so call it.
Flags:
- AMGf_set return the arg using SETs rather than assigning to
- the targ
AMGf_numeric apply sv_2num to the stack arg.
*/
bool
Perl_try_amagic_un(pTHX_ int method, int flags) {
- dVAR;
dSP;
SV* tmpsv;
SV* const arg = TOPs;
SvGETMAGIC(arg);
if (SvAMAGIC(arg) && (tmpsv = amagic_call(arg, &PL_sv_undef, method,
- AMGf_noright | AMGf_unary))) {
- if (flags & AMGf_set) {
- SETs(tmpsv);
- }
- else {
- dTARGET;
- if (SvPADMY(TARG)) {
- sv_setsv(TARG, tmpsv);
- SETTARG;
- }
- else
- SETs(tmpsv);
- }
+ AMGf_noright | AMGf_unary
+ | (flags & AMGf_numarg))))
+ {
+ /* where the op is of the form:
+ * $lex = $x op $y (where the assign is optimised away)
+ * then assign the returned value to targ and return that;
+ * otherwise return the value directly
+ */
+ if ( (PL_opargs[PL_op->op_type] & OA_TARGLEX)
+ && (PL_op->op_private & OPpTARGET_MY))
+ {
+ dTARGET;
+ sv_setsv(TARG, tmpsv);
+ SETTARG;
+ }
+ else
+ SETs(tmpsv);
+
PUTBACK;
return TRUE;
}
Do get magic, then see if the two stack args are overloaded and if so
call it.
Flags:
- AMGf_set return the arg using SETs rather than assigning to
- the targ
AMGf_assign op may be called as mutator (eg +=)
AMGf_numeric apply sv_2num to the stack arg.
*/
bool
Perl_try_amagic_bin(pTHX_ int method, int flags) {
- dVAR;
dSP;
SV* const left = TOPm1s;
SV* const right = TOPs;
SvGETMAGIC(right);
if (SvAMAGIC(left) || SvAMAGIC(right)) {
- SV * const tmpsv = amagic_call(left, right, method,
- ((flags & AMGf_assign) && opASSIGN ? AMGf_assign: 0));
+ SV * tmpsv;
+ /* STACKED implies mutator variant, e.g. $x += 1 */
+ bool mutator = (flags & AMGf_assign) && (PL_op->op_flags & OPf_STACKED);
+
+ tmpsv = amagic_call(left, right, method,
+ (mutator ? AMGf_assign: 0)
+ | (flags & AMGf_numarg));
if (tmpsv) {
- if (flags & AMGf_set) {
- (void)POPs;
- SETs(tmpsv);
- }
- else {
- dATARGET;
- (void)POPs;
- if (opASSIGN || SvPADMY(TARG)) {
- sv_setsv(TARG, tmpsv);
- SETTARG;
- }
- else
- SETs(tmpsv);
- }
+ (void)POPs;
+ /* where the op is one of the two forms:
+ * $x op= $y
+ * $lex = $x op $y (where the assign is optimised away)
+ * then assign the returned value to targ and return that;
+ * otherwise return the value directly
+ */
+ if ( mutator
+ || ( (PL_opargs[PL_op->op_type] & OA_TARGLEX)
+ && (PL_op->op_private & OPpTARGET_MY)))
+ {
+ dTARG;
+ TARG = mutator ? *SP : PAD_SV(PL_op->op_targ);
+ sv_setsv(TARG, tmpsv);
+ SETTARG;
+ }
+ else
+ SETs(tmpsv);
+
PUTBACK;
return TRUE;
}
}
+
if(left==right && SvGMAGICAL(left)) {
SV * const left = sv_newmortal();
*(sp-1) = left;
SV *
Perl_amagic_deref_call(pTHX_ SV *ref, int method) {
SV *tmpsv = NULL;
+ HV *stash;
PERL_ARGS_ASSERT_AMAGIC_DEREF_CALL;
- while (SvAMAGIC(ref) &&
- (tmpsv = amagic_call(ref, &PL_sv_undef, method,
+ if (!SvAMAGIC(ref))
+ return ref;
+ /* return quickly if none of the deref ops are overloaded */
+ stash = SvSTASH(SvRV(ref));
+ assert(SvOOK(stash));
+ if (HvAUX(stash)->xhv_aux_flags & HvAUXf_NO_DEREF)
+ return ref;
+
+ while ((tmpsv = amagic_call(ref, &PL_sv_undef, method,
AMGf_noright | AMGf_unary))) {
if (!SvROK(tmpsv))
Perl_croak(aTHX_ "Overloaded dereference did not return a reference");
return tmpsv;
}
ref = tmpsv;
+ if (!SvAMAGIC(ref))
+ break;
}
return tmpsv ? tmpsv : ref;
}
case abs_amg:
if ((cvp[off1=lt_amg] || cvp[off1=ncmp_amg])
&& ((cv = cvp[off=neg_amg]) || (cv = cvp[off=subtr_amg]))) {
- SV* const nullsv=sv_2mortal(newSViv(0));
+ SV* const nullsv=&PL_sv_zero;
if (off1==lt_amg) {
SV* const lessp = amagic_call(left,nullsv,
lt_amg,AMGf_noright);
- logic = SvTRUE(lessp);
+ logic = SvTRUE_NN(lessp);
} else {
SV* const lessp = amagic_call(left,nullsv,
ncmp_amg,AMGf_noright);
case neg_amg:
if ((cv = cvp[off=subtr_amg])) {
right = left;
- left = sv_2mortal(newSViv(0));
+ left = &PL_sv_zero;
lr = 1;
}
break;
case regexp_amg:
/* FAIL safe */
return NULL; /* Delegate operation to standard mechanisms. */
- break;
+
case to_sv_amg:
case to_av_amg:
case to_hv_amg:
case to_cv_amg:
/* FAIL safe */
return left; /* Delegate operation to standard mechanisms. */
- break;
+
default:
goto not_found;
}
case to_cv_amg:
/* FAIL safe */
return left; /* Delegate operation to standard mechanisms. */
- break;
}
if (ocvp && (cv=ocvp[nomethod_amg])) { /* Call report method */
notfound = 1; lr = -1;
SV *msg;
if (off==-1) off=method;
msg = sv_2mortal(Perl_newSVpvf(aTHX_
- "Operation \"%s\": no method found,%sargument %s%"SVf"%s%"SVf,
+ "Operation \"%s\": no method found,%sargument %s%" SVf "%s%" SVf,
AMG_id2name(method + assignshift),
(flags & AMGf_unary ? " " : "\n\tleft "),
SvAMAGIC(left)?
SVfARG(sv_2mortal(newSVhek(HvNAME_HEK(SvSTASH(SvRV(right)))))):
SVfARG(&PL_sv_no)));
if (use_default_op) {
- DEBUG_o( Perl_deb(aTHX_ "%"SVf, SVfARG(msg)) );
+ DEBUG_o( Perl_deb(aTHX_ "%" SVf, SVfARG(msg)) );
} else {
- Perl_croak(aTHX_ "%"SVf, SVfARG(msg));
+ Perl_croak(aTHX_ "%" SVf, SVfARG(msg));
}
return NULL;
}
case band_amg:
case bor_amg:
case bxor_amg:
+ case sband_amg:
+ case sbor_amg:
+ case sbxor_amg:
if (assign)
force_scalar = 1;
break;
#ifdef DEBUGGING
if (!notfound) {
DEBUG_o(Perl_deb(aTHX_
- "Overloaded operator \"%s\"%s%s%s:\n\tmethod%s found%s in package %"SVf"%s\n",
+ "Overloaded operator \"%s\"%s%s%s:\n\tmethod%s found%s in package %" SVf "%s\n",
AMG_id2name(off),
method+assignshift==off? "" :
" (initially \"",
SV* res;
const bool oldcatch = CATCH_GET;
I32 oldmark, nret;
- int gimme = force_scalar ? G_SCALAR : GIMME_V;
+ /* for multiconcat, we may call overload several times,
+ * with the context of individual concats being scalar,
+ * regardless of the overall context of the multiconcat op
+ */
+ U8 gimme = (force_scalar || PL_op->op_type == OP_MULTICONCAT)
+ ? G_SCALAR : GIMME_V;
CATCH_SET(TRUE);
Zero(&myop, 1, BINOP);
PL_op = (OP *) &myop;
if (PERLDB_SUB && PL_curstash != PL_debstash)
PL_op->op_private |= OPpENTERSUB_DB;
- PUTBACK;
Perl_pp_pushmark(aTHX);
EXTEND(SP, notfound + 5);
PUSHs(newSVpvn_flags(AMG_id2name(method + assignshift),
AMG_id2namelen(method + assignshift), SVs_TEMP));
}
+ else if (flags & AMGf_numarg)
+ PUSHs(&PL_sv_undef);
+ if (flags & AMGf_numarg)
+ PUSHs(&PL_sv_yes);
PUSHs(MUTABLE_SV(cv));
PUTBACK;
oldmark = TOPMARK;
res = &PL_sv_undef;
SP = PL_stack_base + oldmark;
break;
- case G_ARRAY: {
+ case G_ARRAY:
if (flags & AMGf_want_list) {
res = sv_2mortal((SV *)newAV());
av_extend((AV *)res, nret);
break;
}
/* FALLTHROUGH */
- }
default:
res = POPs;
break;
case dec_amg:
SvSetSV(left,res); return left;
case not_amg:
- ans=!SvTRUE(res); break;
+ ans=!SvTRUE_NN(res); break;
default:
ans=0; break;
}
PERL_ARGS_ASSERT_GV_NAME_SET;
if (len > I32_MAX)
- Perl_croak(aTHX_ "panic: gv name too long (%"UVuf")", (UV) len);
+ Perl_croak(aTHX_ "panic: gv name too long (%" UVuf ")", (UV) len);
if (!(flags & GV_ADD) && GvNAME_HEK(gv)) {
unshare_hek(GvNAME_HEK(gv));
!GvSV(gv) && !GvAV(gv) && !GvHV(gv) && !GvIOp(gv) && !GvFORM(gv) &&
GvEGVx(gv) == gv && (stash = GvSTASH(gv))))
return;
+ if (gv == PL_statgv || gv == PL_last_in_gv || gv == PL_stderrgv)
+ return;
if (SvMAGICAL(gv)) {
MAGIC *mg;
/* only backref magic is allowed */
cv = GvCV(gv);
if (!cv) {
HEK *gvnhek = GvNAME_HEK(gv);
- (void)hv_delete(stash, HEK_KEY(gvnhek),
- HEK_UTF8(gvnhek) ? -HEK_LEN(gvnhek) : HEK_LEN(gvnhek), G_DISCARD);
- } else if (GvMULTI(gv) && cv &&
+ (void)hv_deletehek(stash, gvnhek, G_DISCARD);
+ } else if (GvMULTI(gv) && cv && SvREFCNT(cv) == 1 &&
!SvOBJECT(cv) && !SvMAGICAL(cv) && !SvREADONLY(cv) &&
- CvSTASH(cv) == stash && CvGV(cv) == gv &&
+ CvSTASH(cv) == stash && !CvNAMED(cv) && CvGV(cv) == gv &&
CvCONST(cv) && !CvMETHOD(cv) && !CvLVALUE(cv) && !CvUNIQUE(cv) &&
!CvNODEBUG(cv) && !CvCLONE(cv) && !CvCLONED(cv) && !CvANON(cv) &&
(namehek = GvNAME_HEK(gv)) &&
- (gvp = hv_fetch(stash, HEK_KEY(namehek),
- HEK_LEN(namehek)*(HEK_UTF8(namehek) ? -1 : 1), 0)) &&
+ (gvp = hv_fetchhek(stash, namehek, 0)) &&
*gvp == (SV*)gv) {
SV *value = SvREFCNT_inc(CvXSUBANY(cv).any_ptr);
const bool imported = !!GvIMPORTED_CV(gv);
sv_clear((SV*)gv);
SvREFCNT(gv) = 1;
SvFLAGS(gv) = SVt_IV|SVf_ROK|SVprv_PCS_IMPORTED * imported;
+
+ /* See also: 'SET_SVANY_FOR_BODYLESS_IV' in sv.c */
SvANY(gv) = (XPVGV*)((char*)&(gv->sv_u.svu_iv) -
STRUCT_OFFSET(XPVIV, xiv_iv));
SvRV_set(gv, value);
}
}
+GV *
+Perl_gv_override(pTHX_ const char * const name, const STRLEN len)
+{
+ GV *gv = gv_fetchpvn(name, len, GV_NOTQUAL, SVt_PVCV);
+ GV * const *gvp;
+ PERL_ARGS_ASSERT_GV_OVERRIDE;
+ if (gv && GvCVu(gv) && GvIMPORTED_CV(gv)) return gv;
+ gvp = (GV**)hv_fetch(PL_globalstash, name, len, FALSE);
+ gv = gvp ? *gvp : NULL;
+ if (gv && !isGV(gv)) {
+ if (!SvPCS_IMPORTED(gv)) return NULL;
+ gv_init(gv, PL_globalstash, name, len, 0);
+ return gv;
+ }
+ return gv && GvCVu(gv) && GvIMPORTED_CV(gv) ? gv : NULL;
+}
+
#include "XSUB.h"
static void
}
/*
- * Local variables:
- * c-indentation-style: bsd
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- *
* ex: set ts=8 sts=4 sw=4 et:
*/