return NORMAL;
}
+/* This is sometimes called directly by pp_coreargs. */
PP(pp_pushmark)
{
dVAR;
context. */
if (!got_coderef && !is_gv && GIMME_V == G_VOID) {
/* Is the target symbol table currently empty? */
- GV * const gv = gv_fetchsv(right, GV_NOINIT, SVt_PVGV);
+ GV * const gv = gv_fetchsv_nomg(right, GV_NOINIT, SVt_PVGV);
if (SvTYPE(gv) != SVt_PVGV && !SvOK(gv)) {
/* Good. Create a new proxy constant subroutine in the target.
The gv becomes a(nother) reference to the constant. */
/* Need to fix things up. */
if (!is_gv) {
/* Need to fix GV. */
- right = MUTABLE_SV(gv_fetchsv(right, GV_ADD, SVt_PVGV));
+ right = MUTABLE_SV(gv_fetchsv_nomg(right,GV_ADD, SVt_PVGV));
}
if (!got_coderef) {
SAVECLEARSV(PAD_SVl(PL_op->op_targ));
if (PL_op->op_private & OPpDEREF) {
PUTBACK;
- vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
+ TOPs = vivify_ref(TOPs, PL_op->op_private & OPpDEREF);
SPAGAIN;
}
}
PP(pp_readline)
{
dVAR;
- dSP; SvGETMAGIC(TOPs);
- tryAMAGICunTARGET(iter_amg, 0, 0);
- PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--);
+ dSP;
+ if (TOPs) {
+ SvGETMAGIC(TOPs);
+ tryAMAGICunTARGET(iter_amg, 0, 0);
+ PL_last_in_gv = MUTABLE_GV(*PL_stack_sp--);
+ }
+ else PL_last_in_gv = PL_argvgv, PL_stack_sp--;
if (!isGV_with_GP(PL_last_in_gv)) {
if (SvROK(PL_last_in_gv) && isGV_with_GP(SvRV(PL_last_in_gv)))
PL_last_in_gv = MUTABLE_GV(SvRV(PL_last_in_gv));
PP(pp_preinc)
{
dVAR; dSP;
- if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs))
+ const bool inc =
+ PL_op->op_type == OP_PREINC || PL_op->op_type == OP_I_PREINC;
+ if (SvTYPE(TOPs) >= SVt_PVAV || (isGV_with_GP(TOPs) && !SvFAKE(TOPs)))
Perl_croak_no_modify(aTHX);
if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
- && SvIVX(TOPs) != IV_MAX)
+ && SvIVX(TOPs) != (inc ? IV_MAX : IV_MIN))
{
- SvIV_set(TOPs, SvIVX(TOPs) + 1);
+ SvIV_set(TOPs, SvIVX(TOPs) + (inc ? 1 : -1));
SvFLAGS(TOPs) &= ~(SVp_NOK|SVp_POK);
}
else /* Do all the PERL_PRESERVE_IVUV conditionals in sv_inc */
- sv_inc(TOPs);
+ if (inc) sv_inc(TOPs);
+ else sv_dec(TOPs);
SvSETMAGIC(TOPs);
return NORMAL;
}
const bool is_pp_rv2av = PL_op->op_type == OP_RV2AV;
const svtype type = is_pp_rv2av ? SVt_PVAV : SVt_PVHV;
- if (!(PL_op->op_private & OPpDEREFed))
- SvGETMAGIC(sv);
+ SvGETMAGIC(sv);
if (SvROK(sv)) {
if (SvAMAGIC(sv)) {
sv = amagic_deref_call(sv, is_pp_rv2av ? to_av_amg : to_hv_amg);
- SPAGAIN;
}
sv = SvRV(sv);
if (SvTYPE(sv) != type)
+ /* diag_listed_as: Not an ARRAY reference */
DIE(aTHX_ "Not %s reference", is_pp_rv2av ? an_array : a_hash);
if (PL_op->op_flags & OPf_REF) {
SETs(sv);
case SVt_PVAV:
ary = MUTABLE_AV(sv);
magic = SvMAGICAL(ary) != 0;
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
av_clear(ary);
av_extend(ary, lastrelem - relem);
i = 0;
}
if (PL_delaymagic & DM_ARRAY_ISA)
SvSETMAGIC(MUTABLE_SV(ary));
+ LEAVE;
break;
case SVt_PVHV: { /* normal hash */
SV *tmpstr;
hash = MUTABLE_HV(sv);
magic = SvMAGICAL(hash) != 0;
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(sv));
hv_clear(hash);
firsthashrelem = relem;
do_oddball(hash, relem, firstrelem);
relem++;
}
+ LEAVE;
}
break;
default:
}
}
if (PL_delaymagic & ~DM_DELAY) {
+ /* Will be used to set PL_tainting below */
+ UV tmp_uid = PerlProc_getuid();
+ UV tmp_euid = PerlProc_geteuid();
+ UV tmp_gid = PerlProc_getgid();
+ UV tmp_egid = PerlProc_getegid();
+
if (PL_delaymagic & DM_UID) {
#ifdef HAS_SETRESUID
- (void)setresuid((PL_delaymagic & DM_RUID) ? PL_uid : (Uid_t)-1,
- (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1,
+ (void)setresuid((PL_delaymagic & DM_RUID) ? PL_delaymagic_uid : (Uid_t)-1,
+ (PL_delaymagic & DM_EUID) ? PL_delaymagic_euid : (Uid_t)-1,
(Uid_t)-1);
#else
# ifdef HAS_SETREUID
- (void)setreuid((PL_delaymagic & DM_RUID) ? PL_uid : (Uid_t)-1,
- (PL_delaymagic & DM_EUID) ? PL_euid : (Uid_t)-1);
+ (void)setreuid((PL_delaymagic & DM_RUID) ? PL_delaymagic_uid : (Uid_t)-1,
+ (PL_delaymagic & DM_EUID) ? PL_delaymagic_euid : (Uid_t)-1);
# else
# ifdef HAS_SETRUID
if ((PL_delaymagic & DM_UID) == DM_RUID) {
- (void)setruid(PL_uid);
+ (void)setruid(PL_delaymagic_uid);
PL_delaymagic &= ~DM_RUID;
}
# endif /* HAS_SETRUID */
# ifdef HAS_SETEUID
if ((PL_delaymagic & DM_UID) == DM_EUID) {
- (void)seteuid(PL_euid);
+ (void)seteuid(PL_delaymagic_euid);
PL_delaymagic &= ~DM_EUID;
}
# endif /* HAS_SETEUID */
if (PL_delaymagic & DM_UID) {
- if (PL_uid != PL_euid)
+ if (PL_delaymagic_uid != PL_delaymagic_euid)
DIE(aTHX_ "No setreuid available");
- (void)PerlProc_setuid(PL_uid);
+ (void)PerlProc_setuid(PL_delaymagic_uid);
}
# endif /* HAS_SETREUID */
#endif /* HAS_SETRESUID */
- PL_uid = PerlProc_getuid();
- PL_euid = PerlProc_geteuid();
+ tmp_uid = PerlProc_getuid();
+ tmp_euid = PerlProc_geteuid();
}
if (PL_delaymagic & DM_GID) {
#ifdef HAS_SETRESGID
- (void)setresgid((PL_delaymagic & DM_RGID) ? PL_gid : (Gid_t)-1,
- (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1,
+ (void)setresgid((PL_delaymagic & DM_RGID) ? PL_delaymagic_gid : (Gid_t)-1,
+ (PL_delaymagic & DM_EGID) ? PL_delaymagic_egid : (Gid_t)-1,
(Gid_t)-1);
#else
# ifdef HAS_SETREGID
- (void)setregid((PL_delaymagic & DM_RGID) ? PL_gid : (Gid_t)-1,
- (PL_delaymagic & DM_EGID) ? PL_egid : (Gid_t)-1);
+ (void)setregid((PL_delaymagic & DM_RGID) ? PL_delaymagic_gid : (Gid_t)-1,
+ (PL_delaymagic & DM_EGID) ? PL_delaymagic_egid : (Gid_t)-1);
# else
# ifdef HAS_SETRGID
if ((PL_delaymagic & DM_GID) == DM_RGID) {
- (void)setrgid(PL_gid);
+ (void)setrgid(PL_delaymagic_gid);
PL_delaymagic &= ~DM_RGID;
}
# endif /* HAS_SETRGID */
# ifdef HAS_SETEGID
if ((PL_delaymagic & DM_GID) == DM_EGID) {
- (void)setegid(PL_egid);
+ (void)setegid(PL_delaymagic_egid);
PL_delaymagic &= ~DM_EGID;
}
# endif /* HAS_SETEGID */
if (PL_delaymagic & DM_GID) {
- if (PL_gid != PL_egid)
+ if (PL_delaymagic_gid != PL_delaymagic_egid)
DIE(aTHX_ "No setregid available");
- (void)PerlProc_setgid(PL_gid);
+ (void)PerlProc_setgid(PL_delaymagic_gid);
}
# endif /* HAS_SETREGID */
#endif /* HAS_SETRESGID */
- PL_gid = PerlProc_getgid();
- PL_egid = PerlProc_getegid();
+ tmp_gid = PerlProc_getgid();
+ tmp_egid = PerlProc_getegid();
}
- PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid));
+ PL_tainting |= (tmp_uid && (tmp_euid != tmp_uid || tmp_egid != tmp_gid));
}
PL_delaymagic = 0;
|| SvTEMP(TARG) || SvAMAGIC(TARG) || PL_sawampersand
|| (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY)))
r_flags |= REXEC_COPY_STR;
- if (SvSCREAM(TARG))
- r_flags |= REXEC_SCREAM;
play_it_again:
if (global && RX_OFFS(rx)[0].start != -1) {
if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
&& !PL_sawampersand
&& !(RX_EXTFLAGS(rx) & RXf_PMf_KEEPCOPY)
- && ((RX_EXTFLAGS(rx) & RXf_NOSCAN)
- || !((RX_EXTFLAGS(rx) & RXf_INTUIT_TAIL)
- && (r_flags & REXEC_SCREAM)))
&& !SvROK(TARG)) /* Cannot trust since INTUIT cannot guess ^ */
goto yup;
}
s = RX_OFFS(rx)[i].start + truebase;
if (RX_OFFS(rx)[i].end < 0 || RX_OFFS(rx)[i].start < 0 ||
len < 0 || len > strend - s)
- DIE(aTHX_ "panic: pp_match start/end pointers");
+ DIE(aTHX_ "panic: pp_match start/end pointers, i=%ld, "
+ "start=%ld, end=%ld, s=%p, strend=%p, len=%"UVuf,
+ (long) i, (long) RX_OFFS(rx)[i].start,
+ (long)RX_OFFS(rx)[i].end, s, strend, (UV) len);
sv_setpvn(*SP, s, len);
if (DO_UTF8(TARG) && is_utf8_string((U8*)s, len))
SvUTF8_on(*SP);
&& ckWARN2(WARN_GLOB, WARN_CLOSED))
{
if (type == OP_GLOB)
- Perl_warner(aTHX_ packWARN(WARN_GLOB),
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_GLOB),
"glob failed (can't start child: %s)",
Strerror(errno));
else
mg_get(sv);
if (SvROK(sv)) {
if (type == OP_RCATLINE)
- SvPV_force_nolen(sv);
+ SvPV_force_nomg_nolen(sv);
else
sv_unref(sv);
}
else if (isGV_with_GP(sv)) {
- SvPV_force_nolen(sv);
+ SvPV_force_nomg_nolen(sv);
}
SvUPGRADE(sv, SVt_PV);
tmplen = SvLEN(sv); /* remember if already alloced */
offset = 0;
if (type == OP_RCATLINE && SvOK(sv)) {
if (!SvPOK(sv)) {
- SvPV_force_nolen(sv);
+ SvPV_force_nomg_nolen(sv);
}
offset = SvCUR(sv);
}
}
}
-PP(pp_enter)
-{
- dVAR; dSP;
- register PERL_CONTEXT *cx;
- I32 gimme = OP_GIMME(PL_op, -1);
-
- if (gimme == -1) {
- if (cxstack_ix >= 0) {
- /* If this flag is set, we're just inside a return, so we should
- * store the caller's context */
- gimme = (PL_op->op_flags & OPf_SPECIAL)
- ? block_gimme()
- : cxstack[cxstack_ix].blk_gimme;
- } else
- gimme = G_SCALAR;
- }
-
- ENTER_with_name("block");
-
- SAVETMPS;
- PUSHBLOCK(cx, CXt_BLOCK, SP);
-
- RETURN;
-}
-
PP(pp_helem)
{
dVAR; dSP;
he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
svp = he ? &HeVAL(he) : NULL;
if (lval) {
- if (!svp || *svp == &PL_sv_undef) {
+ if (!svp || !*svp || *svp == &PL_sv_undef) {
SV* lv;
SV* key2;
if (!defer) {
else
SAVEHDELETE(hv, keysv);
}
- else if (PL_op->op_private & OPpDEREF)
- vivify_ref(*svp, PL_op->op_private & OPpDEREF);
+ else if (PL_op->op_private & OPpDEREF) {
+ PUSHs(vivify_ref(*svp, PL_op->op_private & OPpDEREF));
+ RETURN;
+ }
}
- sv = (svp ? *svp : &PL_sv_undef);
+ sv = (svp && *svp ? *svp : &PL_sv_undef);
/* Originally this did a conditional C<sv = sv_mortalcopy(sv)>; this
* was to make C<local $tied{foo} = $tied{foo}> possible.
* However, it seems no longer to be needed for that purpose, and
RETURN;
}
-PP(pp_leave)
-{
- dVAR; dSP;
- register PERL_CONTEXT *cx;
- SV **newsp;
- PMOP *newpm;
- I32 gimme;
-
- if (PL_op->op_flags & OPf_SPECIAL) {
- cx = &cxstack[cxstack_ix];
- cx->blk_oldpm = PL_curpm; /* fake block should preserve $1 et al */
- }
-
- POPBLOCK(cx,newpm);
-
- gimme = OP_GIMME(PL_op, (cxstack_ix >= 0) ? gimme : G_SCALAR);
-
- TAINT_NOT;
- if (gimme == G_VOID)
- SP = newsp;
- else if (gimme == G_SCALAR) {
- register SV **mark;
- MARK = newsp + 1;
- if (MARK <= SP) {
- if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP))
- *MARK = TOPs;
- else
- *MARK = sv_mortalcopy(TOPs);
- } else {
- MEXTEND(mark,0);
- *MARK = &PL_sv_undef;
- }
- SP = MARK;
- }
- else if (gimme == G_ARRAY) {
- /* in case LEAVE wipes old return values */
- register SV **mark;
- for (mark = newsp + 1; mark <= SP; mark++) {
- if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) {
- *mark = sv_mortalcopy(*mark);
- TAINT_NOT; /* Each item is independent */
- }
- }
- }
- PL_curpm = newpm; /* Don't pop $1 et al till now */
-
- LEAVE_with_name("block");
-
- RETURN;
-}
-
PP(pp_iter)
{
dVAR; dSP;
EXTEND(SP, 1);
cx = &cxstack[cxstack_ix];
if (!CxTYPE_is_LOOP(cx))
- DIE(aTHX_ "panic: pp_iter");
+ DIE(aTHX_ "panic: pp_iter, type=%u", CxTYPE(cx));
itersvp = CxITERVAR(cx);
if (CxTYPE(cx) == CXt_LOOP_LAZYSV) {
/*
A description of how taint works in pattern matching and substitution.
-While the pattern is being assembled/concatenated and them compiled,
+While the pattern is being assembled/concatenated and then compiled,
PL_tainted will get set if any component of the pattern is tainted, e.g.
/.*$tainted/. At the end of pattern compilation, the RXf_TAINTED flag
is set on the pattern if PL_tainted is set.
force_it:
if (!pm || !s)
- DIE(aTHX_ "panic: pp_subst");
+ DIE(aTHX_ "panic: pp_subst, pm=%p, s=%p", pm, s);
strend = s + len;
slen = RX_MATCH_UTF8(rx) ? utf8_length((U8*)s, (U8*)strend) : len;
r_flags = (RX_NPARENS(rx) || SvTEMP(TARG) || PL_sawampersand
|| (RX_EXTFLAGS(rx) & (RXf_EVAL_SEEN|RXf_PMf_KEEPCOPY)) )
? REXEC_COPY_STR : 0;
- if (SvSCREAM(TARG))
- r_flags |= REXEC_SCREAM;
orig = m = s;
if (RX_EXTFLAGS(rx) & RXf_USE_INTUIT) {
/* How to do it in subst? */
/* if ( (RX_EXTFLAGS(rx) & RXf_CHECK_ALL)
&& !PL_sawampersand
- && !(RX_EXTFLAGS(rx) & RXf_KEEPCOPY)
- && ((RX_EXTFLAGS(rx) & RXf_NOSCAN)
- || !((RX_EXTFLAGS(rx) & RXf_INTUIT_TAIL)
- && (r_flags & REXEC_SCREAM))))
+ && !(RX_EXTFLAGS(rx) & RXf_KEEPCOPY))
goto yup;
*/
}
}
d = s;
PL_curpm = pm;
- SvSCREAM_off(TARG); /* disable possible screamer */
if (once) {
if (RX_MATCH_TAINTED(rx)) /* run time pattern taint, eg locale */
rxtainted |= SUBST_TAINT_PAT;
else {
if (force_on_match) {
force_on_match = 0;
+ if (rpm->op_pmflags & PMf_NONDESTRUCT) {
+ /* I feel that it should be possible to avoid this mortal copy
+ given that the code below copies into a new destination.
+ However, I suspect it isn't worth the complexity of
+ unravelling the C<goto force_it> for the small number of
+ cases where it would be viable to drop into the copy code. */
+ TARG = sv_2mortal(newSVsv(TARG));
+ }
s = SvPV_force(TARG, len);
goto force_it;
}
I32 gimme;
register PERL_CONTEXT *cx;
SV *sv;
- bool gmagic;
if (CxMULTICALL(&cxstack[cxstack_ix]))
return 0;
POPBLOCK(cx,newpm);
cxstack_ix++; /* temporarily protect top context */
- gmagic = CxLVAL(cx) & OPpENTERSUB_DEREF;
TAINT_NOT;
if (gimme == G_SCALAR) {
MARK = newsp + 1;
if (MARK <= SP) {
if (cx->blk_sub.cv && CvDEPTH(cx->blk_sub.cv) > 1) {
- if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1) {
+ if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1
+ && !SvMAGICAL(TOPs)) {
*MARK = SvREFCNT_inc(TOPs);
FREETMPS;
sv_2mortal(*MARK);
- if (gmagic) SvGETMAGIC(*MARK);
}
else {
sv = SvREFCNT_inc(TOPs); /* FREETMPS could clobber it */
SvREFCNT_dec(sv);
}
}
- else if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1) {
+ else if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1
+ && !SvMAGICAL(TOPs)) {
*MARK = TOPs;
- if (gmagic) SvGETMAGIC(TOPs);
}
else
*MARK = sv_mortalcopy(TOPs);
}
else if (gimme == G_ARRAY) {
for (MARK = newsp + 1; MARK <= SP; MARK++) {
- if (!SvTEMP(*MARK) || SvREFCNT(*MARK) != 1) {
+ if (!SvTEMP(*MARK) || SvREFCNT(*MARK) != 1
+ || SvMAGICAL(*MARK)) {
*MARK = sv_mortalcopy(*MARK);
TAINT_NOT; /* Each item is independent */
}
switch (SvTYPE(sv)) {
/* This is overwhelming the most common case: */
case SVt_PVGV:
- if (!isGV_with_GP(sv))
- DIE(aTHX_ "Not a CODE reference");
we_have_a_glob:
if (!(cv = GvCVu((const GV *)sv))) {
HV *stash;
if (!sym)
DIE(aTHX_ PL_no_usym, "a subroutine");
if (PL_op->op_private & HINT_STRICT_REFS)
- DIE(aTHX_ "Can't use string (\"%.32s\"%s) as a subroutine ref while \"strict refs\" in use", sym, len>32 ? "..." : "");
+ DIE(aTHX_ "Can't use string (\"%" SVf32 "\"%s) as a subroutine ref while \"strict refs\" in use", sv, len>32 ? "..." : "");
cv = get_cvn_flags(sym, len, GV_ADD|SvUTF8(sv));
break;
}
/* should call AUTOLOAD now? */
else {
try_autoload:
- if ((autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
- FALSE)))
+ if ((autogv = gv_autoload_pvn(GvSTASH(gv), GvNAME(gv), GvNAMELEN(gv),
+ GvNAMEUTF8(gv) ? SVf_UTF8 : 0)))
{
cv = GvCV(autogv);
}
PUSHSUB(cx);
cx->blk_sub.retop = PL_op->op_next;
CvDEPTH(cv)++;
- /* XXX This would be a natural place to set C<PL_compcv = cv> so
- * that eval'' ops within this sub know the correct lexical space.
- * Owing the speed considerations, we choose instead to search for
- * the cv using find_runcv() when calling doeval().
- */
if (CvDEPTH(cv) >= 2) {
PERL_STACK_OVERFLOW_CHECK();
pad_push(padlist, CvDEPTH(cv));
MARK++;
}
}
+ if ((cx->blk_u16 & OPpENTERSUB_LVAL_MASK) == OPpLVAL_INTRO &&
+ !CvLVALUE(cv))
+ DIE(aTHX_ "Can't modify non-lvalue subroutine call");
/* warning must come *after* we fully set up the context
* stuff so that __WARN__ handlers can safely dounwind()
* if they want to
Perl_warner(aTHX_ packWARN(WARN_MISC),
"Use of reference \"%"SVf"\" as array index",
SVfARG(elemsv));
- if (elem > 0)
- elem -= CopARYBASE_get(PL_curcop);
if (SvTYPE(av) != SVt_PVAV)
RETPUSHUNDEF;
else
SAVEADELETE(av, elem);
}
- else if (PL_op->op_private & OPpDEREF)
- vivify_ref(*svp, PL_op->op_private & OPpDEREF);
+ else if (PL_op->op_private & OPpDEREF) {
+ PUSHs(vivify_ref(*svp, PL_op->op_private & OPpDEREF));
+ RETURN;
+ }
}
sv = (svp ? *svp : &PL_sv_undef);
if (!lval && SvRMAGICAL(av) && SvGMAGICAL(sv)) /* see note in pp_helem() */
RETURN;
}
-void
+SV*
Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
{
PERL_ARGS_ASSERT_VIVIFY_REF;
}
SvROK_on(sv);
SvSETMAGIC(sv);
+ SvGETMAGIC(sv);
+ }
+ if (SvGMAGICAL(sv)) {
+ /* copy the sv without magic to prevent magic from being
+ executed twice */
+ SV* msv = sv_newmortal();
+ sv_setsv_nomg(msv, sv);
+ return msv;
}
+ return sv;
}
PP(pp_method)
SV* ob;
GV* gv;
HV* stash;
- const char* packname = NULL;
SV *packsv = NULL;
- STRLEN packlen;
- SV * const sv = *(PL_stack_base + TOPMARK + 1);
+ SV * const sv = PL_stack_base + TOPMARK == PL_stack_sp
+ ? (Perl_croak(aTHX_ "Can't call method \"%"SVf"\" without a "
+ "package or object reference", SVfARG(meth)),
+ (SV *)NULL)
+ : *(PL_stack_base + TOPMARK + 1);
PERL_ARGS_ASSERT_METHOD_COMMON;
ob = MUTABLE_SV(SvRV(sv));
else {
GV* iogv;
+ STRLEN packlen;
+ const char * packname = NULL;
+ bool packname_is_utf8 = FALSE;
/* this isn't a reference */
- if(SvOK(sv) && (packname = SvPV_const(sv, packlen))) {
- const HE* const he = hv_fetch_ent(PL_stashcache, sv, 0, 0);
+ if(SvOK(sv) && (packname = SvPV_nomg_const(sv, packlen))) {
+ const HE* const he =
+ (const HE *)hv_common_key_len(
+ PL_stashcache, packname,
+ packlen * -(packname_is_utf8 = !!SvUTF8(sv)), 0, NULL, 0
+ );
+
if (he) {
stash = INT2PTR(HV*,SvIV(HeVAL(he)));
goto fetch;
if (!SvOK(sv) ||
!(packname) ||
- !(iogv = gv_fetchsv(sv, 0, SVt_PVIO)) ||
+ !(iogv = gv_fetchpvn_flags(
+ packname, packlen, SVf_UTF8 * packname_is_utf8, SVt_PVIO
+ )) ||
!(ob=MUTABLE_SV(GvIO(iogv))))
{
/* this isn't the name of a filehandle either */
if (!packname ||
((UTF8_IS_START(*packname) && DO_UTF8(sv))
? !isIDFIRST_utf8((U8*)packname)
- : !isIDFIRST(*packname)
+ : !isIDFIRST_L1((U8)*packname)
))
{
+ /* diag_listed_as: Can't call method "%s" without a package or object reference */
Perl_croak(aTHX_ "Can't call method \"%"SVf"\" %s",
SVfARG(meth),
SvOK(sv) ? "without a package or object reference"
: "on an undefined value");
}
/* assume it's a package name */
- stash = gv_stashpvn(packname, packlen, 0);
+ stash = gv_stashpvn(packname, packlen, packname_is_utf8 ? SVf_UTF8 : 0);
if (!stash)
packsv = sv;
else {
SV* const ref = newSViv(PTR2IV(stash));
- (void)hv_store(PL_stashcache, packname, packlen, ref, 0);
+ (void)hv_store(PL_stashcache, packname,
+ packname_is_utf8 ? -(I32)packlen : (I32)packlen, ref, 0);
}
goto fetch;
}
&& (ob = MUTABLE_SV(GvIO((const GV *)ob)))
&& SvOBJECT(ob))))
{
- const char * const name = SvPV_nolen_const(meth);
- Perl_croak(aTHX_ "Can't call method \"%s\" on unblessed reference",
- (SvSCREAM(meth) && strEQ(name,"isa")) ? "DOES" :
- name);
+ Perl_croak(aTHX_ "Can't call method \"%"SVf"\" on unblessed reference",
+ SVfARG((SvSCREAM(meth) && strEQ(SvPV_nolen_const(meth),"isa"))
+ ? newSVpvs_flags("DOES", SVs_TEMP)
+ : meth));
}
stash = SvSTASH(ob);
}
}
- gv = gv_fetchmethod_flags(stash ? stash : MUTABLE_HV(packsv),
- SvPV_nolen_const(meth),
- GV_AUTOLOAD | GV_CROAK);
+ gv = gv_fetchmethod_sv_flags(stash ? stash : MUTABLE_HV(packsv),
+ meth, GV_AUTOLOAD | GV_CROAK);
assert(gv);
* Local variables:
* c-indentation-style: bsd
* c-basic-offset: 4
- * indent-tabs-mode: t
+ * indent-tabs-mode: nil
* End:
*
- * ex: set ts=8 sts=4 sw=4 noet:
+ * ex: set ts=8 sts=4 sw=4 et:
*/