X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/db4cf31d1d6c1d09bce93986aa993818ea7b17cf..931d943835db379bfdca349cb29b11fd4f0a90e7:/pp.c diff --git a/pp.c b/pp.c index dd20288..6088a11 100644 --- a/pp.c +++ b/pp.c @@ -29,6 +29,7 @@ #include "keywords.h" #include "reentr.h" +#include "regcharclass.h" /* XXX I can't imagine anyone who doesn't have this actually _needs_ it, since pid_t is an integral type. @@ -83,6 +84,7 @@ PP(pp_padav) } gimme = GIMME_V; if (gimme == G_ARRAY) { + /* XXX see also S_pushav in pp_hot.c */ const I32 maxarg = AvFILL(MUTABLE_AV(TARG)) + 1; EXTEND(SP, maxarg); if (SvMAGICAL(TARG)) { @@ -131,6 +133,11 @@ PP(pp_padhv) if (gimme == G_ARRAY) { RETURNOP(Perl_do_kv(aTHX)); } + else if ((PL_op->op_private & OPpTRUEBOOL + || ( PL_op->op_private & OPpMAYBE_TRUEBOOL + && block_gimme() == G_VOID )) + && (!SvRMAGICAL(TARG) || !mg_find(TARG, PERL_MAGIC_tied))) + SETs(HvUSEDKEYS(TARG) ? &PL_sv_yes : sv_2mortal(newSViv(0))); else if (gimme == G_SCALAR) { SV* const sv = Perl_hv_scalar(aTHX_ MUTABLE_HV(TARG)); SETs(sv); @@ -138,6 +145,48 @@ PP(pp_padhv) RETURN; } +PP(pp_padcv) +{ + dVAR; dSP; dTARGET; + assert(SvTYPE(TARG) == SVt_PVCV); + XPUSHs(TARG); + RETURN; +} + +PP(pp_introcv) +{ + dVAR; dTARGET; + SvPADSTALE_off(TARG); + return NORMAL; +} + +PP(pp_clonecv) +{ + dVAR; dTARGET; + MAGIC * const mg = + mg_find(PadlistNAMESARRAY(CvPADLIST(find_runcv(NULL)))[ARGTARG], + PERL_MAGIC_proto); + assert(SvTYPE(TARG) == SVt_PVCV); + assert(mg); + assert(mg->mg_obj); + if (CvISXSUB(mg->mg_obj)) { /* constant */ + /* XXX Should we clone it here? */ + /* If this changes to use SAVECLEARSV, we can move the SAVECLEARSV + to introcv and remove the SvPADSTALE_off. */ + SAVEPADSVANDMORTALIZE(ARGTARG); + PAD_SVl(ARGTARG) = mg->mg_obj; + } + else { + if (CvROOT(mg->mg_obj)) { + assert(CvCLONE(mg->mg_obj)); + assert(!CvCLONED(mg->mg_obj)); + } + cv_clone_into((CV *)mg->mg_obj,(CV *)TARG); + SAVECLEARSV(PAD_SVl(ARGTARG)); + } + return NORMAL; +} + /* Translations. */ static const char S_no_symref_sv[] = @@ -182,7 +231,7 @@ S_rv2gv(pTHX_ SV *sv, const bool vivify_sv, const bool strict, if (vivify_sv && sv != &PL_sv_undef) { GV *gv; if (SvREADONLY(sv)) - Perl_croak_no_modify(aTHX); + Perl_croak_no_modify(); if (cUNOP->op_targ) { SV * const namesv = PAD_SV(cUNOP->op_targ); gv = MUTABLE_GV(newSV(0)); @@ -278,8 +327,7 @@ Perl_softref2xv(pTHX_ SV *const sv, const char *const what, } if (!SvOK(sv)) { if ( - PL_op->op_flags & OPf_REF && - PL_op->op_next->op_type != OP_BOOLKEYS + PL_op->op_flags & OPf_REF ) Perl_die(aTHX_ PL_no_usym, what); if (ckWARN(WARN_UNINITIALIZED)) @@ -729,7 +777,7 @@ S_do_chomp(pTHX_ SV *retval, SV *sv, bool chomping) sv_force_normal_flags(sv, 0); } else - Perl_croak_no_modify(aTHX); + Perl_croak_no_modify(); } if (PL_encoding) { @@ -922,16 +970,20 @@ PP(pp_undef) { /* let user-undef'd sub keep its identity */ GV* const gv = CvGV((const CV *)sv); + HEK * const hek = CvNAME_HEK((CV *)sv); + if (hek) share_hek_hek(hek); cv_undef(MUTABLE_CV(sv)); - CvGV_set(MUTABLE_CV(sv), gv); + if (gv) CvGV_set(MUTABLE_CV(sv), gv); + else if (hek) { + SvANY((CV *)sv)->xcv_gv_u.xcv_hek = hek; + CvNAMED_on(sv); + } } break; case SVt_PVGV: - if (SvFAKE(sv)) { - SvSetMagicSV(sv, &PL_sv_undef); - break; - } - else if (isGV_with_GP(sv)) { + assert(isGV_with_GP(sv)); + assert(!SvFAKE(sv)); + { GP *gp; HV *stash; @@ -969,7 +1021,6 @@ PP(pp_undef) break; } - /* FALL THROUGH */ default: if (SvTYPE(sv) >= SVt_PV && SvPVX_const(sv) && SvLEN(sv)) { SvPV_free(sv); @@ -989,7 +1040,7 @@ PP(pp_postinc) const bool inc = PL_op->op_type == OP_POSTINC || PL_op->op_type == OP_I_POSTINC; if (SvTYPE(TOPs) >= SVt_PVAV || (isGV_with_GP(TOPs) && !SvFAKE(TOPs))) - Perl_croak_no_modify(aTHX); + Perl_croak_no_modify(); if (SvROK(TOPs)) TARG = sv_newmortal(); sv_setsv(TARG, TOPs); @@ -2360,7 +2411,7 @@ PP(pp_i_divide) } } -#if defined(__GLIBC__) && IVSIZE == 8 +#if defined(__GLIBC__) && IVSIZE == 8 && !defined(PERL_DEBUG_READONLY_OPS) STATIC PP(pp_i_modulo_0) #else @@ -2383,7 +2434,7 @@ PP(pp_i_modulo) } } -#if defined(__GLIBC__) && IVSIZE == 8 +#if defined(__GLIBC__) && IVSIZE == 8 && !defined(PERL_DEBUG_READONLY_OPS) STATIC PP(pp_i_modulo_1) @@ -2838,35 +2889,16 @@ PP(pp_length) dVAR; dSP; dTARGET; SV * const sv = TOPs; - if (SvGAMAGIC(sv)) { - /* For an overloaded or magic scalar, we can't know in advance if - it's going to be UTF-8 or not. Also, we can't call sv_len_utf8 as - it likes to cache the length. Maybe that should be a documented - feature of it. - */ - STRLEN len; - const char *const p - = sv_2pv_flags(sv, &len, - SV_UNDEF_RETURNS_NULL|SV_CONST_RETURN|SV_GMAGIC); - - if (!p) { - if (!SvPADTMP(TARG)) { - sv_setsv(TARG, &PL_sv_undef); - SETTARG; - } - SETs(&PL_sv_undef); - } - else if (DO_UTF8(sv)) { - SETi(utf8_length((U8*)p, (U8*)p + len)); - } + SvGETMAGIC(sv); + if (SvOK(sv)) { + if (!IN_BYTES) + SETi(sv_len_utf8_nomg(sv)); else + { + STRLEN len; + (void)SvPV_nomg_const(sv,len); SETi(len); - } else if (SvOK(sv)) { - /* Neither magic nor overloaded. */ - if (DO_UTF8(sv)) - SETi(sv_len_utf8(sv)); - else - SETi(sv_len(sv)); + } } else { if (!SvPADTMP(TARG)) { sv_setsv_nomg(TARG, &PL_sv_undef); @@ -2964,7 +2996,6 @@ PP(pp_substr) STRLEN repl_len; int num_args = PL_op->op_private & 7; bool repl_need_utf8_upgrade = FALSE; - bool repl_is_utf8 = FALSE; if (num_args > 2) { if (num_args > 3) { @@ -2985,17 +3016,7 @@ PP(pp_substr) repl_sv = POPs; } PUTBACK; - if (repl_sv) { - repl = SvPV_const(repl_sv, repl_len); - repl_is_utf8 = DO_UTF8(repl_sv) && repl_len; - if (repl_is_utf8) { - if (!DO_UTF8(sv)) - sv_utf8_upgrade(sv); - } - else if (DO_UTF8(sv)) - repl_need_utf8_upgrade = TRUE; - } - else if (lvalue) { + if (lvalue && !repl_sv) { SV * ret; ret = sv_2mortal(newSV_type(SVt_PVLV)); /* Not TARG RT#67838 */ sv_magic(ret, NULL, PERL_MAGIC_substr, NULL, 0); @@ -3014,9 +3035,26 @@ PP(pp_substr) PUSHs(ret); /* avoid SvSETMAGIC here */ RETURN; } - tmps = SvPV_const(sv, curlen); + if (repl_sv) { + repl = SvPV_const(repl_sv, repl_len); + SvGETMAGIC(sv); + if (SvROK(sv)) + Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR), + "Attempt to use reference as lvalue in substr" + ); + tmps = SvPV_force_nomg(sv, curlen); + if (DO_UTF8(repl_sv) && repl_len) { + if (!DO_UTF8(sv)) { + sv_utf8_upgrade_nomg(sv); + curlen = SvCUR(sv); + } + } + else if (DO_UTF8(sv)) + repl_need_utf8_upgrade = TRUE; + } + else tmps = SvPV_const(sv, curlen); if (DO_UTF8(sv)) { - utf8_curlen = sv_len_utf8(sv); + utf8_curlen = sv_or_pv_len_utf8(sv, tmps, curlen); if (utf8_curlen == curlen) utf8_curlen = 0; else @@ -3034,7 +3072,7 @@ PP(pp_substr) byte_len = len; byte_pos = utf8_curlen - ? sv_pos_u2b_flags(sv, pos, &byte_len, SV_CONST_RETURN) : pos; + ? sv_or_pv_pos_u2b(sv, tmps, pos, &byte_len) : pos; tmps += byte_pos; @@ -3056,17 +3094,10 @@ PP(pp_substr) repl_sv_copy = newSVsv(repl_sv); sv_utf8_upgrade(repl_sv_copy); repl = SvPV_const(repl_sv_copy, repl_len); - repl_is_utf8 = DO_UTF8(repl_sv_copy) && repl_len; } - if (SvROK(sv)) - Perl_ck_warner(aTHX_ packWARN(WARN_SUBSTR), - "Attempt to use reference as lvalue in substr" - ); if (!SvOK(sv)) sv_setpvs(sv, ""); sv_insert_flags(sv, byte_pos, byte_len, repl, repl_len, 0); - if (repl_is_utf8) - SvUTF8_on(sv); SvREFCNT_dec(repl_sv_copy); } } @@ -4037,7 +4068,7 @@ PP(pp_quotemeta) to_quote = TRUE; } } - else if (_is_utf8_quotemeta((U8 *) s)) { + else if (is_QUOTEMETA_high(s)) { to_quote = TRUE; } @@ -4774,20 +4805,30 @@ PP(pp_anonlist) PP(pp_anonhash) { dVAR; dSP; dMARK; dORIGMARK; - HV* const hv = newHV(); + HV* const hv = (HV *)sv_2mortal((SV *)newHV()); while (MARK < SP) { - SV * const key = *++MARK; - SV * const val = newSV(0); + SV * const key = + (MARK++, SvGMAGICAL(*MARK) ? sv_mortalcopy(*MARK) : *MARK); + SV *val; if (MARK < SP) - sv_setsv(val, *++MARK); + { + MARK++; + SvGETMAGIC(*MARK); + val = newSV(0); + sv_setsv(val, *MARK); + } else + { Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Odd number of elements in anonymous hash"); + val = newSV(0); + } (void)hv_store_ent(hv,key,val,0); } SP = ORIGMARK; - mXPUSHs((PL_op->op_flags & OPf_SPECIAL) - ? newRV_noinc(MUTABLE_SV(hv)) : MUTABLE_SV(hv)); + if (PL_op->op_flags & OPf_SPECIAL) + mXPUSHs(newRV_inc(MUTABLE_SV(hv))); + else XPUSHs(MUTABLE_SV(hv)); RETURN; } @@ -5040,11 +5081,14 @@ PP(pp_push) SPAGAIN; } else { + if (SvREADONLY(ary) && MARK < SP) Perl_croak_no_modify(); PL_delaymagic = DM_DELAY; for (++MARK; MARK <= SP; MARK++) { - SV * const sv = newSV(0); + SV *sv; + if (*MARK) SvGETMAGIC(*MARK); + sv = newSV(0); if (*MARK) - sv_setsv(sv, *MARK); + sv_setsv_nomg(sv, *MARK); av_store(ary, AvFILLp(ary)+1, sv); } if (PL_delaymagic & DM_ARRAY_ISA) @@ -5246,6 +5290,7 @@ PP(pp_split) STRLEN len; const char *s = SvPV_const(sv, len); const bool do_utf8 = DO_UTF8(sv); + const bool skipwhite = PL_op->op_flags & OPf_SPECIAL; const char *strend = s + len; PMOP *pm; REGEXP *rx; @@ -5276,7 +5321,7 @@ PP(pp_split) rx = PM_GETRE(pm); TAINT_IF(get_regex_charset(RX_EXTFLAGS(rx)) == REGEX_LOCALE_CHARSET && - (RX_EXTFLAGS(rx) & (RXf_WHITE | RXf_SKIPWHITE))); + (RX_EXTFLAGS(rx) & RXf_WHITE || skipwhite)); RX_MATCH_UTF8_set(rx, do_utf8); @@ -5316,7 +5361,7 @@ PP(pp_split) } base = SP - PL_stack_base; orig = s; - if (RX_EXTFLAGS(rx) & RXf_SKIPWHITE) { + if (skipwhite) { if (do_utf8) { while (*s == ' ' || is_utf8_space((U8*)s)) s += UTF8SKIP(s); @@ -5338,7 +5383,7 @@ PP(pp_split) if (!limit) limit = maxiters + 2; - if (RX_EXTFLAGS(rx) & RXf_WHITE) { + if (RX_EXTFLAGS(rx) & RXf_WHITE || skipwhite) { while (--limit) { m = s; /* this one uses 'm' and is a negative test */ @@ -5545,13 +5590,9 @@ PP(pp_split) if (rex_return == 0) break; TAINT_IF(RX_MATCH_TAINTED(rx)); - if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) { - m = s; - s = orig; - orig = RX_SUBBEG(rx); - s = orig + (m - s); - strend = s + (strend - m); - } + /* we never pass the REXEC_COPY_STR flag, so it should + * never get copied */ + assert(!RX_MATCH_COPIED(rx)); m = RX_OFFS(rx)[0].start + orig; if (gimme_scalar) { @@ -5718,26 +5759,6 @@ PP(unimplemented_op) DIE(aTHX_ "panic: unimplemented op %s (#%d) called", name, op_type); } -PP(pp_boolkeys) -{ - dVAR; - dSP; - HV * const hv = (HV*)POPs; - - if (SvTYPE(hv) != SVt_PVHV) { XPUSHs(&PL_sv_no); RETURN; } - - if (SvRMAGICAL(hv)) { - MAGIC * const mg = mg_find((SV*)hv, PERL_MAGIC_tied); - if (mg) { - XPUSHs(magic_scalarpack(hv, mg)); - RETURN; - } - } - - XPUSHs(boolSV(HvUSEDKEYS(hv) != 0)); - RETURN; -} - /* For sorting out arguments passed to a &CORE:: subroutine */ PP(pp_coreargs) {