/*
=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.
}
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 && GvNAMELEN(gv) == 3
+ && strnEQ(GvNAME(gv), "ISA", 3))
+ 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;
#endif
}
if ((PERLDB_LINE || PERLDB_SAVESRC) && !GvAV(gv))
- hv_magic(GvHVn(gv_AVadd(gv)), NULL, PERL_MAGIC_dbfile);
+ hv_magic(GvHVn(gv), GvAVn(gv), PERL_MAGIC_dbfile);
if (tmpbuf != smallbuf)
Safefree(tmpbuf);
return gv;
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));
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 */
- filegv = CopFILEGV(PL_curcop);
- if (filegv) {
- file = GvNAME(filegv)+2;
- len = GvNAMELEN(filegv)-2;
- } 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
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))
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));
+
default: NOOP;
}
SvRV_set(gv, NULL);
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 (has_constant && SvTYPE(has_constant) == SVt_PVCV) {
+ /* Not actually a constant. Just a regular sub. */
+ CV * const cv = (CV *)has_constant;
+ GvCV_set(gv,cv);
+ if (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 :
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. */
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
GV *
Perl_gv_fetchmeth_pvn(pTHX_ HV *stash, const char *name, STRLEN len, I32 level, U32 flags)
{
- dVAR;
GV** gvp;
AV* linear_av;
SV** linear_svp;
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;
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 $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
*/
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;
GV* gv;
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);
* 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;
STATIC HV*
S_require_tie_mod(pTHX_ GV *gv, const char *varpv, SV* namesv, const char *methpv,const U32 flags)
{
- dVAR;
HV* stash = gv_stashsv(namesv, 0);
PERL_ARGS_ASSERT_REQUIRE_TIE_MOD;
so save it. For the moment it's always
a single char. */
const char type = varname == '[' ? '$' : '%';
+#ifdef DEBUGGING
dSP;
+#endif
ENTER;
SAVEFREESV(namesv);
if ( flags & 1 )
save_scalar(gv);
- PUSHSTACKi(PERLSI_MAGIC);
Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, module, NULL);
- POPSTACK;
+ assert(sp == PL_stack_sp);
stash = gv_stashsv(namesv, 0);
if (!stash)
Perl_croak(aTHX_ "panic: Can't use %c%c because %"SVf" is not available",
The most important of which are probably GV_ADD and SVf_UTF8.
+Note, use of C<gv_stashsv> instead of C<gv_stashpvn> where possible is strongly
+recommended for performance reasons.
+
=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;
}
/*
+gv_stashsvpvn_cached
+
+Returns a pointer to the stash for a specified package, possibly
+cached. Implements both C<gv_stashpvn> and C<gc_stashsv>.
+
+Requires one of either namesv or namepv to be non-null.
+
+See C<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) return INT2PTR(HV*,SvIVX(HeVAL(he)));
+ 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>.
+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;
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;
-
- 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;
+ PERL_ARGS_ASSERT_PARSE_GV_STASH_NAME;
+
+ if (full_len > 2 && **name == '*' && isIDFIRST_lazy_if(*name + 1, is_utf8)) {
+ /* accidental stringify on a GV? */
+ (*name)++;
}
- if (full_len > 2 && *name == '*' && isIDFIRST_lazy_if(name + 1, 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;
-
- 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);
- }
- }
- else if (!HvNAME_get(stash))
- hv_name_set(stash, nambeg, name_cursor - nambeg, is_utf8);
- }
+ 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 FALSE;
+
+ *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 {
+ 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 ? -((I32)*len) : (I32)*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 FALSE;
+
+ 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);
+ }
+ }
+ 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));
- }
+ if (*name_cursor == ':')
+ name_cursor++;
+ *name = name_cursor+1;
+ if (*name == name_end) {
+ if (!*gv)
+ *gv = MUTABLE_GV(*hv_fetchs(PL_defstash, "main::", TRUE));
+ return TRUE;
+ }
+ }
}
- len = name_cursor - name;
-
- /* 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;
- }
+ *len = name_cursor - *name;
+ return TRUE;
+}
- 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(name, 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 beforehand.
+ *
+ * The return value has a specific meaning for gv_fetchpvn_flags:
+ * If it returns true, and the gv is empty, it indicates that its
+ * refcount should be decreased.
+ */
+PERL_STATIC_INLINE bool
+S_gv_magicalize(pTHX_ GV *gv, HV *stash, const char *name, STRLEN len,
+ bool addmg, 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) {
+ if (len) {
const char * const name2 = name + 1;
switch (*name) {
case 'E':
if (strEQ(name2, "ERSION"))
GvMULTI_on(gv);
break;
+ case 'a':
+ case 'b':
+ if (len == 1 && sv_type == SVt_PV)
+ GvMULTI_on(gv);
+ /* FALLTHROUGH */
default:
goto try_core;
}
- goto add_magical_gv;
+ return addmg;
}
try_core:
if (len > 1 /* shortest is uc */ && HvNAMELEN_get(stash) == 4) {
/* 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
{
goto ro_magicalize;
break;
case '\015': /* $^MATCH */
- if (strEQ(name2, "ATCH"))
- goto magicalize;
+ if (strEQ(name2, "ATCH")) {
+ paren = RX_BUFF_IDX_CARET_FULLMATCH;
+ goto storeparen;
+ }
+ break;
case '\017': /* $^OPEN */
if (strEQ(name2, "PEN"))
goto magicalize;
break;
case '\020': /* $^PREMATCH $^POSTMATCH */
- if (strEQ(name2, "REMATCH") || strEQ(name2, "OSTMATCH"))
- goto magicalize;
+ if (strEQ(name2, "REMATCH")) {
+ paren = RX_BUFF_IDX_CARET_PREMATCH;
+ goto storeparen;
+ }
+ if (strEQ(name2, "OSTMATCH")) {
+ paren = RX_BUFF_IDX_CARET_POSTMATCH;
+ goto storeparen;
+ }
break;
case '\024': /* ${^TAINT} */
if (strEQ(name2, "AINT"))
/* This snippet is taken from is_gv_magical */
const char *end = name + len;
while (--end > name) {
- if (!isDIGIT(*end)) goto add_magical_gv;
+ if (!isDIGIT(*end))
+ return addmg;
}
- goto magicalize;
+ paren = grok_atou(name, NULL);
+ 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);
/* magicalization must be done before require_tie_mod 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);
+ addmg = FALSE;
}
break;
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);
+ addmg = FALSE;
}
break;
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;
+ addmg = FALSE;
}
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 '=': /* $= */
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;
+
+ return addmg;
+}
+
+/* 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(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
+ }
+ }
+}
+
+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 (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;
+ }
+ /* 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 ( isIDFIRST_lazy_if(name, is_utf8) && !ckWARN(WARN_ONCE) )
+ GvMULTI_on(gv) ;
+
+ /* First, store the gv in the symtab if we're adding magic,
+ * but only for non-empty GVs
+ */
+#define GvEMPTY(gv) !(GvAV(gv) || GvHV(gv) || GvIO(gv) \
+ || GvCV(gv) || (GvSV(gv) && SvOK(GvSV(gv))))
+
+ if ( addmg && !GvEMPTY(gv) ) {
+ (void)hv_store(stash,name,len,(SV *)gv,0);
+ }
+
+ /* set up magic where warranted */
+ if ( gv_magicalize(gv, stash, name, len, addmg, sv_type) ) {
+ /* See 23496c6 */
+ if (GvEMPTY(gv)) {
+ if ( GvSV(gv) && SvMAGICAL(GvSV(gv)) ) {
+ /* The GV was and still is "empty", except that now
+ * it has the magic flags turned on, so we want it
+ * stored in the symtab.
+ */
+ (void)hv_store(stash,name,len,(SV *)gv,0);
+ }
+ else {
+ /* Most likely 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;
}
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_ HV *stash)
{
- dVAR;
I32 i;
PERL_ARGS_ASSERT_GV_CHECK;
if (!HvARRAY(stash))
return;
+
+ assert(SvOOK(stash));
+
for (i = 0; i <= (I32) HvMAX(stash); i++) {
const HE *entry;
- /* SvIsCOW is unused on HVs, so we can use it to mark stashes we
- are currently searching through recursively. */
- SvIsCOW_on(stash);
+ /* 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] == ':' &&
(gv = MUTABLE_GV(HeVAL(entry))) && isGV(gv) && (hv = GvHV(gv)))
{
- if (hv != PL_defstash && hv != stash && !SvIsCOW(hv))
+ 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) != '_'
HEKfARG(GvNAME_HEK(gv)));
}
}
- SvIsCOW_off(stash);
+ 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));
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));
+ DEBUG_o(Perl_deb(aTHX_ "gp_free clearing PL_stashcache for '%"HEKf"'\n", HEKfARG(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);
+ (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 =
+ CvNAMED(cv) ? CvNAME_HEK(cv) : GvNAME_HEK(CvGV(cv));
+ const HEK * const stashek =
+ HvNAME_HEK(CvNAMED(cv) ? CvSTASH(cv) : GvSTASH(CvGV(cv)));
+ if (HEK_LEN(gvhek) == 3 && strEQ(HEK_KEY(gvhek), "nil")
+ && stashek && HEK_LEN(stashek) == 8
+ && strEQ(HEK_KEY(stashek), "overload")) {
/* This is a hack to support autoloading..., while
knowing *which* methods were declared as overloaded. */
/* GvSV contains the name of the method. */
}
}
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;
bool
Perl_try_amagic_un(pTHX_ int method, int flags) {
- dVAR;
dSP;
SV* tmpsv;
SV* const arg = TOPs;
bool
Perl_try_amagic_bin(pTHX_ int method, int flags) {
- dVAR;
dSP;
SV* const left = TOPm1s;
SV* const right = TOPs;
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 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;
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);
!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);
}
}
+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