X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=20c08315f2296e0291e1ad7fda7b1a4c0fd4d981;hb=a146a244ce1425446618620fe96b3481b5463a4f;hp=4ec189e960de1b5fa3b793fcec93c7efe23dfe7b;hpb=7ee2227d70915603ee41631de2babf3bbc5737c4;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index 4ec189e..20c0831 100644 --- a/op.c +++ b/op.c @@ -1,7 +1,7 @@ /* op.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -208,14 +208,18 @@ S_no_bareword_allowed(pTHX_ const OP *o) PADOFFSET Perl_allocmy(pTHX_ char *name) { + dVAR; PADOFFSET off; + const bool is_our = (PL_in_my == KEY_our); /* complain about "my $" etc etc */ - if (!(PL_in_my == KEY_our || + if (*name && + !(is_our || isALPHA(name[1]) || (USE_UTF8_IN_NAMES && UTF8_IS_START(name[1])) || - (name[1] == '_' && (*name == '$' || (int)strlen(name) > 2)))) + (name[1] == '_' && (*name == '$' || name[2])))) { + /* name[2] is true if strlen(name) > 2 */ if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) { /* 1999-02-27 mjd@plover.com */ char *p; @@ -239,25 +243,22 @@ Perl_allocmy(pTHX_ char *name) } /* check for duplicate declaration */ - pad_check_dup(name, - (bool)(PL_in_my == KEY_our), - (PL_curstash ? PL_curstash : PL_defstash) - ); + pad_check_dup(name, is_our, (PL_curstash ? PL_curstash : PL_defstash)); if (PL_in_my_stash && *name != '$') { yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"", - name, PL_in_my == KEY_our ? "our" : "my")); + name, is_our ? "our" : "my")); } /* allocate a spare slot and store the name in that slot */ off = pad_add_name(name, PL_in_my_stash, - (PL_in_my == KEY_our + (is_our /* $_ is always in main::, even with our */ ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash) - : Nullhv + : NULL ), 0 /* not fake */ ); @@ -405,7 +406,7 @@ Perl_op_clear(pTHX_ OP *o) clear_pmop: { HV * const pmstash = PmopSTASH(cPMOPo); - if (pmstash && SvREFCNT(pmstash)) { + if (pmstash && !SvIS_FREED(pmstash)) { MAGIC * const mg = mg_find((SV*)pmstash, PERL_MAGIC_symtab); if (mg) { PMOP *pmop = (PMOP*) mg->mg_obj; @@ -505,19 +506,25 @@ Perl_op_refcnt_unlock(pTHX) OP * Perl_linklist(pTHX_ OP *o) { + OP *first; if (o->op_next) return o->op_next; /* establish postfix order */ - if (cUNOPo->op_first) { + first = cUNOPo->op_first; + if (first) { register OP *kid; - o->op_next = LINKLIST(cUNOPo->op_first); - for (kid = cUNOPo->op_first; kid; kid = kid->op_sibling) { - if (kid->op_sibling) + o->op_next = LINKLIST(first); + kid = first; + for (;;) { + if (kid->op_sibling) { kid->op_next = LINKLIST(kid->op_sibling); - else + kid = kid->op_sibling; + } else { kid->op_next = o; + break; + } } } else @@ -540,6 +547,7 @@ Perl_scalarkids(pTHX_ OP *o) STATIC OP * S_scalarboolean(pTHX_ OP *o) { + dVAR; if (o->op_type == OP_SASSIGN && cBINOPo->op_first->op_type == OP_CONST) { if (ckWARN(WARN_SYNTAX)) { const line_t oldline = CopLINE(PL_curcop); @@ -629,7 +637,7 @@ Perl_scalarvoid(pTHX_ OP *o) { dVAR; OP *kid; - const char* useless = 0; + const char* useless = NULL; SV* sv; U8 want; @@ -818,6 +826,8 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_AND: case OP_DOR: case OP_COND_EXPR: + case OP_ENTERGIVEN: + case OP_ENTERWHEN: for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling) scalarvoid(kid); break; @@ -839,6 +849,8 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_LEAVELOOP: case OP_LINESEQ: case OP_LIST: + case OP_LEAVEGIVEN: + case OP_LEAVEWHEN: for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) scalarvoid(kid); break; @@ -953,6 +965,7 @@ Perl_list(pTHX_ OP *o) OP * Perl_scalarseq(pTHX_ OP *o) { + dVAR; if (o) { if (o->op_type == OP_LINESEQ || o->op_type == OP_SCOPE || @@ -987,7 +1000,7 @@ S_modkids(pTHX_ OP *o, I32 type) return o; } -/* Propagate lvalue ("modifiable") context to an op and it's children. +/* Propagate lvalue ("modifiable") context to an op and its children. * 'type' represents the context type, roughly based on the type of op that * would do the modifying, although local() is represented by OP_NULL. * It's responsible for detecting things that can't be modified, flag @@ -1044,6 +1057,10 @@ Perl_mod(pTHX_ OP *o, I32 type) if ((type == OP_UNDEF || type == OP_REFGEN) && !(o->op_flags & OPf_STACKED)) { o->op_type = OP_RV2CV; /* entersub => rv2cv */ + /* The default is to set op_private to the number of children, + which for a UNOP such as RV2CV is always 1. And w're using + the bit for a flag in RV2CV, so we need it clear. */ + o->op_private &= ~1; o->op_ppaddr = PL_ppaddr[OP_RV2CV]; assert(cUNOPo->op_first->op_type == OP_NULL); op_null(((LISTOP*)cUNOPo->op_first)->op_first);/* disable pushmark */ @@ -1089,6 +1106,7 @@ Perl_mod(pTHX_ OP *o, I32 type) newop->op_next = (OP*)newop; kid->op_sibling = (OP*)newop; newop->op_private |= OPpLVAL_INTRO; + newop->op_private &= ~1; break; } @@ -1123,6 +1141,7 @@ Perl_mod(pTHX_ OP *o, I32 type) okid->op_targ = 0; okid->op_ppaddr = PL_ppaddr[OP_RV2CV]; okid->op_private |= OPpLVAL_INTRO; + okid->op_private &= ~1; break; } @@ -1136,8 +1155,9 @@ Perl_mod(pTHX_ OP *o, I32 type) /* FALL THROUGH */ default: nomod: - /* grep, foreach, subcalls, refgen */ - if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN) + /* grep, foreach, subcalls, refgen, m//g */ + if (type == OP_GREPSTART || type == OP_ENTERSUB || type == OP_REFGEN + || type == OP_MATCH) break; yyerror(Perl_form(aTHX_ "Can't modify %s in %s", (o->op_type == OP_NULL && (o->op_flags & OPf_SPECIAL) @@ -1439,6 +1459,7 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) assert(cUNOPo->op_first->op_type == OP_NULL); op_null(((LISTOP*)cUNOPo->op_first)->op_first); /* disable pushmark */ o->op_flags |= OPf_SPECIAL; + o->op_private &= ~1; } break; @@ -1518,7 +1539,8 @@ Perl_doref(pTHX_ OP *o, I32 type, bool set_op_ref) STATIC OP * S_dup_attrlist(pTHX_ OP *o) { - OP *rop = Nullop; + dVAR; + OP *rop; /* An attrlist is either a simple OP_CONST or an OP_LIST with kids, * where the first kid is OP_PUSHMARK and the remaining ones @@ -1528,6 +1550,7 @@ S_dup_attrlist(pTHX_ OP *o) rop = newSVOP(OP_CONST, o->op_flags, SvREFCNT_inc(cSVOPo->op_sv)); else { assert((o->op_type == OP_LIST) && (o->op_flags & OPf_KIDS)); + rop = Nullop; for (o = cLISTOPo->op_first; o; o=o->op_sibling) { if (o->op_type == OP_CONST) rop = append_elem(OP_LIST, rop, @@ -1554,8 +1577,7 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my) if (for_my) { /* Don't force the C if we don't need it. */ - SV * const * const svp = hv_fetch(GvHVn(PL_incgv), ATTRSMODULE_PM, - sizeof(ATTRSMODULE_PM)-1, 0); + SV * const * const svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE); if (svp && *svp != &PL_sv_undef) ; /* already in %INC */ else @@ -1580,6 +1602,7 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my) STATIC void S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) { + dVAR; OP *pack, *imop, *arg; SV *meth, *stashsv; @@ -1609,7 +1632,7 @@ S_apply_attrs_my(pTHX_ HV *stash, OP *target, OP *attrs, OP **imopsp) dup_attrlist(attrs))); /* Fake up a method call to import */ - meth = newSVpvn_share("import", 6, 0); + meth = newSVpvs_share("import"); imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL|OPf_WANT_VOID, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -1671,6 +1694,7 @@ Perl_apply_attrs_string(pTHX_ const char *stashpv, CV *cv, STATIC OP * S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { + dVAR; I32 type; if (!o || PL_error_count) @@ -1692,7 +1716,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } else if (attrs) { GV * const gv = cGVOPx_gv(cUNOPo->op_first); PL_in_my = FALSE; - PL_in_my_stash = Nullhv; + PL_in_my_stash = NULL; apply_attrs(GvSTASH(gv), (type == OP_RV2SV ? GvSV(gv) : type == OP_RV2AV ? (SV*)GvAV(gv) : @@ -1716,7 +1740,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) HV *stash; PL_in_my = FALSE; - PL_in_my_stash = Nullhv; + PL_in_my_stash = NULL; /* check for C when deciding package */ stash = PAD_COMPNAME_TYPE(o->op_targ); @@ -1732,7 +1756,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) OP * Perl_my_attrs(pTHX_ OP *o, OP *attrs) { - OP *rops = Nullop; + dVAR; + OP *rops; int maybe_scalar = 0; /* [perl #17376]: this appears to be premature, and results in code such as @@ -1747,6 +1772,7 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs) #endif if (attrs) SAVEFREEOP(attrs); + rops = Nullop; o = my_kid(o, attrs, &rops); if (rops) { if (maybe_scalar && o->op_type == OP_PADSV) { @@ -1757,7 +1783,7 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs) o = append_list(OP_LIST, (LISTOP*)o, (LISTOP*)rops); } PL_in_my = FALSE; - PL_in_my_stash = Nullhv; + PL_in_my_stash = NULL; return o; } @@ -1814,9 +1840,14 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) } if (!(right->op_flags & OPf_STACKED) && ismatchop) { right->op_flags |= OPf_STACKED; - if (right->op_type != OP_MATCH && - ! (right->op_type == OP_TRANS && - right->op_private & OPpTRANS_IDENTICAL)) + /* s/// and tr/// modify their arg. + * m//g also indirectly modifies the arg by setting pos magic on it */ + if ( (right->op_type == OP_MATCH && + (cPMOPx(right)->op_pmflags & PMf_GLOBAL)) + || (right->op_type == OP_SUBST) + || (right->op_type == OP_TRANS && + ! (right->op_private & OPpTRANS_IDENTICAL)) + ) left = mod(left, right->op_type); if (right->op_type == OP_TRANS) o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right); @@ -1871,16 +1902,10 @@ Perl_scope(pTHX_ OP *o) return o; } -/* XXX kept for BINCOMPAT only */ -void -Perl_save_hints(pTHX) -{ - Perl_croak(aTHX_ "internal error: obsolete function save_hints() called"); -} - int Perl_block_start(pTHX_ int full) { + dVAR; const int retval = PL_savestack_ix; pad_block_start(full); SAVEHINTS(); @@ -1901,6 +1926,7 @@ Perl_block_start(pTHX_ int full) OP* Perl_block_end(pTHX_ I32 floor, OP *seq) { + dVAR; const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; OP* const retval = scalarseq(seq); LEAVE_SCOPE(floor); @@ -1914,6 +1940,7 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) STATIC OP * S_newDEFSVOP(pTHX) { + dVAR; const I32 offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS(offset) & SVpad_OUR) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); @@ -1928,6 +1955,7 @@ S_newDEFSVOP(pTHX) void Perl_newPROG(pTHX_ OP *o) { + dVAR; if (PL_in_eval) { if (PL_eval_root) return; @@ -1973,6 +2001,7 @@ Perl_newPROG(pTHX_ OP *o) OP * Perl_localize(pTHX_ OP *o, I32 lex) { + dVAR; if (o->op_flags & OPf_PARENS) /* [perl #17376]: this appears to be premature, and results in code such as C< our(%x); > executing in list mode rather than void mode */ @@ -2018,7 +2047,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) else o = mod(o, OP_NULL); /* a bit kludgey */ PL_in_my = FALSE; - PL_in_my_stash = Nullhv; + PL_in_my_stash = NULL; return o; } @@ -2027,7 +2056,7 @@ Perl_jmaybe(pTHX_ OP *o) { if (o->op_type == OP_LIST) { OP *o2; - o2 = newSVREF(newGVOP(OP_GV, 0, gv_fetchpv(";", TRUE, SVt_PV))), + o2 = newSVREF(newGVOP(OP_GV, 0, gv_fetchpv(";", GV_ADD, SVt_PV))), o = convert(OP_JOIN, 0, prepend_elem(OP_LIST, o2, o)); } return o; @@ -2063,7 +2092,6 @@ Perl_fold_constants(pTHX_ register OP *o) /* XXX might want a ck_negate() for this */ cUNOPo->op_first->op_private &= ~OPpCONST_STRICT; break; - case OP_SPRINTF: case OP_UCFIRST: case OP_LCFIRST: case OP_UC: @@ -2393,6 +2421,7 @@ static int uvcompare(const void *a, const void *b) OP * Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) { + dVAR; SV * const tstr = ((SVOP*)expr)->op_sv; SV * const rstr = ((SVOP*)repl)->op_sv; STRLEN tlen; @@ -2416,8 +2445,8 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) o->op_private |= OPpTRANS_TO_UTF; if (o->op_private & (OPpTRANS_FROM_UTF|OPpTRANS_TO_UTF)) { - SV* const listsv = newSVpvn("# comment\n",10); - SV* transv = 0; + SV* const listsv = newSVpvs("# comment\n"); + SV* transv = NULL; const U8* tend = t + tlen; const U8* rend = r + rlen; STRLEN ulen; @@ -2461,7 +2490,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) UV nextmin = 0; Newx(cp, 2*tlen, UV); i = 0; - transv = newSVpvn("",0); + transv = newSVpvs(""); while (t < tend) { cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, 0); t += ulen; @@ -2778,7 +2807,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) cLISTOPx(expr)->op_first->op_sibling == cLISTOPx(expr)->op_last) { /* convert single element list to element */ - OP* oe = expr; + OP* const oe = expr; expr = cLISTOPx(oe)->op_first->op_sibling; cLISTOPx(oe)->op_first->op_sibling = Nullop; cLISTOPx(oe)->op_last = Nullop; @@ -2873,7 +2902,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) else if (repl->op_type == OP_CONST) curop = repl; else { - OP *lastop = 0; + OP *lastop = NULL; for (curop = LINKLIST(repl); curop!=repl; curop = LINKLIST(curop)) { if (PL_opargs[curop->op_type] & OA_DANGEROUS) { if (curop->op_type == OP_GV) { @@ -3013,6 +3042,7 @@ Perl_newPVOP(pTHX_ I32 type, I32 flags, char *pv) void Perl_package(pTHX_ OP *o) { + dVAR; const char *name; STRLEN len; @@ -3032,6 +3062,7 @@ Perl_package(pTHX_ OP *o) void Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) { + dVAR; OP *pack; OP *imop; OP *veop; @@ -3058,7 +3089,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)idop)->op_sv)); /* Fake up a method call to VERSION */ - meth = newSVpvn_share("VERSION", 7, 0); + meth = newSVpvs_share("VERSION"); veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(version)), @@ -3082,7 +3113,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) /* Fake up a method call to import/unimport */ meth = aver - ? newSVpvn_share("import",6, 0) : newSVpvn_share("unimport", 8, 0); + ? newSVpvs_share("import") : newSVpvs_share("unimport"); imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, prepend_elem(OP_LIST, pack, list(arg)), @@ -3091,7 +3122,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *idop, OP *arg) /* Fake up the BEGIN {}, which does its thing immediately. */ newATTRSUB(floor, - newSVOP(OP_CONST, 0, newSVpvn_share("BEGIN", 5, 0)), + newSVOP(OP_CONST, 0, newSVpvs_share("BEGIN")), Nullop, Nullop, append_elem(OP_LINESEQ, @@ -3163,6 +3194,7 @@ Perl_load_module_nocontext(U32 flags, SV *name, SV *ver, ...) void Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args) { + dVAR; OP *veop, *imop; OP * const modname = newSVOP(OP_CONST, 0, name); @@ -3203,13 +3235,14 @@ Perl_vload_module(pTHX_ U32 flags, SV *name, SV *ver, va_list *args) OP * Perl_dofile(pTHX_ OP *term, I32 force_builtin) { + dVAR; OP *doop; GV *gv = Nullgv; if (!force_builtin) { - gv = gv_fetchpv("do", FALSE, SVt_PVCV); + gv = gv_fetchpv("do", 0, SVt_PVCV); if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) { - GV * const * const gvp = (GV**)hv_fetch(PL_globalstash, "do", 2, FALSE); + GV * const * const gvp = (GV**)hv_fetchs(PL_globalstash, "do", FALSE); gv = gvp ? *gvp : Nullgv; } } @@ -3277,6 +3310,7 @@ S_is_list_assignment(pTHX_ register const OP *o) OP * Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) { + dVAR; OP *o; if (optype) { @@ -3305,15 +3339,6 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) /* Result of assignment is always 1 (or we'd be dead already) */ return newSVOP(OP_CONST, 0, newSViv(1)); } - /* optimise C to C, and likewise for hashes */ - if ((left->op_type == OP_PADAV || left->op_type == OP_PADHV) - && right->op_type == OP_STUB - && (left->op_private & OPpLVAL_INTRO)) - { - op_free(right); - left->op_flags &= ~(OPf_REF|OPf_SPECIAL); - return left; - } curop = list(force_list(left)); o = newBINOP(OP_AASSIGN, flags, list(force_list(right)), curop); o->op_private = (U8)(0 | (flags >> 8)); @@ -3500,7 +3525,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) CopSTASH_set(cop, PL_curstash); if (PERLDB_LINE && PL_curstash != PL_debstash) { - SV * const * const svp = av_fetch(CopFILEAV(PL_curcop), (I32)CopLINE(cop), FALSE); + SV * const * const svp = av_fetch(CopFILEAVx(PL_curcop), (I32)CopLINE(cop), FALSE); if (svp && *svp != &PL_sv_undef ) { (void)SvIOK_on(*svp); SvIV_set(*svp, PTR2IV(cop)); @@ -3759,6 +3784,7 @@ Perl_newRANGE(pTHX_ I32 flags, OP *left, OP *right) OP * Perl_newLOOPOP(pTHX_ I32 flags, I32 debuggable, OP *expr, OP *block) { + dVAR; OP* listop; OP* o; const bool once = block && block->op_flags & OPf_SPECIAL && @@ -3823,7 +3849,7 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my) { dVAR; OP *redo; - OP *next = 0; + OP *next = NULL; OP *listop; OP *o; U8 loopflags = 0; @@ -3931,6 +3957,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP iterpflags = sv->op_private & OPpOUR_INTRO; /* for our $x () */ sv->op_type = OP_RV2GV; sv->op_ppaddr = PL_ppaddr[OP_RV2GV]; + if (cGVOPx_gv(cUNOPx(sv)->op_first) == PL_defgv) + iterpflags |= OPpITER_DEF; } else if (sv->op_type == OP_PADSV) { /* private variable */ iterpflags = sv->op_private & OPpLVAL_INTRO; /* for my $x () */ @@ -3948,6 +3976,8 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP } else Perl_croak(aTHX_ "Can't use %s for loop variable", PL_op_desc[sv->op_type]); + if (padoff && strEQ(PAD_COMPNAME_PV(padoff), "$_")) + iterpflags |= OPpITER_DEF; } else { const I32 offset = pad_findmy("$_"); @@ -3957,6 +3987,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP else { padoff = offset; } + iterpflags |= OPpITER_DEF; } if (expr->op_type == OP_RV2AV || expr->op_type == OP_PADAV) { expr = mod(force_list(scalar(ref(expr, OP_ITER))), OP_GREPSTART); @@ -4020,6 +4051,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP OP* Perl_newLOOPEX(pTHX_ I32 type, OP *label) { + dVAR; OP *o; if (type != OP_GOTO || label->op_type == OP_CONST) { @@ -4044,6 +4076,180 @@ Perl_newLOOPEX(pTHX_ I32 type, OP *label) return o; } +/* if the condition is a literal array or hash + (or @{ ... } etc), make a reference to it. + */ +STATIC OP * +S_ref_array_or_hash(pTHX_ OP *cond) +{ + if (cond + && (cond->op_type == OP_RV2AV + || cond->op_type == OP_PADAV + || cond->op_type == OP_RV2HV + || cond->op_type == OP_PADHV)) + + return newUNOP(OP_REFGEN, + 0, mod(cond, OP_REFGEN)); + + else + return cond; +} + +/* These construct the optree fragments representing given() + and when() blocks. + + entergiven and enterwhen are LOGOPs; the op_other pointer + points up to the associated leave op. We need this so we + can put it in the context and make break/continue work. + (Also, of course, pp_enterwhen will jump straight to + op_other if the match fails.) + */ + +STATIC +OP * +S_newGIVWHENOP(pTHX_ OP *cond, OP *block, + I32 enter_opcode, I32 leave_opcode, + PADOFFSET entertarg) +{ + dVAR; + LOGOP *enterop; + OP *o; + + NewOp(1101, enterop, 1, LOGOP); + enterop->op_type = enter_opcode; + enterop->op_ppaddr = PL_ppaddr[enter_opcode]; + enterop->op_flags = (U8) OPf_KIDS; + enterop->op_targ = ((entertarg == NOT_IN_PAD) ? 0 : entertarg); + enterop->op_private = 0; + + o = newUNOP(leave_opcode, 0, (OP *) enterop); + + if (cond) { + enterop->op_first = scalar(cond); + cond->op_sibling = block; + + o->op_next = LINKLIST(cond); + cond->op_next = (OP *) enterop; + } + else { + /* This is a default {} block */ + enterop->op_first = block; + enterop->op_flags |= OPf_SPECIAL; + + o->op_next = (OP *) enterop; + } + + CHECKOP(enter_opcode, enterop); /* Currently does nothing, since + entergiven and enterwhen both + use ck_null() */ + + enterop->op_next = LINKLIST(block); + block->op_next = enterop->op_other = o; + + return o; +} + +/* Does this look like a boolean operation? For these purposes + a boolean operation is: + - a subroutine call [*] + - a logical connective + - a comparison operator + - a filetest operator, with the exception of -s -M -A -C + - defined(), exists() or eof() + - /$re/ or $foo =~ /$re/ + + [*] possibly surprising + */ +STATIC +bool +S_looks_like_bool(pTHX_ OP *o) +{ + dVAR; + switch(o->op_type) { + case OP_OR: + return looks_like_bool(cLOGOPo->op_first); + + case OP_AND: + return ( + looks_like_bool(cLOGOPo->op_first) + && looks_like_bool(cLOGOPo->op_first->op_sibling)); + + case OP_ENTERSUB: + + case OP_NOT: case OP_XOR: + /* Note that OP_DOR is not here */ + + case OP_EQ: case OP_NE: case OP_LT: + case OP_GT: case OP_LE: case OP_GE: + + case OP_I_EQ: case OP_I_NE: case OP_I_LT: + case OP_I_GT: case OP_I_LE: case OP_I_GE: + + case OP_SEQ: case OP_SNE: case OP_SLT: + case OP_SGT: case OP_SLE: case OP_SGE: + + case OP_SMARTMATCH: + + case OP_FTRREAD: case OP_FTRWRITE: case OP_FTREXEC: + case OP_FTEREAD: case OP_FTEWRITE: case OP_FTEEXEC: + case OP_FTIS: case OP_FTEOWNED: case OP_FTROWNED: + case OP_FTZERO: case OP_FTSOCK: case OP_FTCHR: + case OP_FTBLK: case OP_FTFILE: case OP_FTDIR: + case OP_FTPIPE: case OP_FTLINK: case OP_FTSUID: + case OP_FTSGID: case OP_FTSVTX: case OP_FTTTY: + case OP_FTTEXT: case OP_FTBINARY: + + case OP_DEFINED: case OP_EXISTS: + case OP_MATCH: case OP_EOF: + + return TRUE; + + case OP_CONST: + /* Detect comparisons that have been optimized away */ + if (cSVOPo->op_sv == &PL_sv_yes + || cSVOPo->op_sv == &PL_sv_no) + + return TRUE; + + /* FALL THROUGH */ + default: + return FALSE; + } +} + +OP * +Perl_newGIVENOP(pTHX_ OP *cond, OP *block, PADOFFSET defsv_off) +{ + dVAR; + assert( cond ); + return newGIVWHENOP( + ref_array_or_hash(cond), + block, + OP_ENTERGIVEN, OP_LEAVEGIVEN, + defsv_off); +} + +/* If cond is null, this is a default {} block */ +OP * +Perl_newWHENOP(pTHX_ OP *cond, OP *block) +{ + bool cond_llb = (!cond || looks_like_bool(cond)); + OP *cond_op; + + if (cond_llb) + cond_op = cond; + else { + cond_op = newBINOP(OP_SMARTMATCH, OPf_SPECIAL, + newDEFSVOP(), + scalar(ref_array_or_hash(cond))); + } + + return newGIVWHENOP( + cond_op, + append_elem(block->op_type, block, newOP(OP_BREAK, OPf_SPECIAL)), + OP_ENTERWHEN, OP_LEAVEWHEN, 0); +} + /* =for apidoc cv_undef @@ -4116,12 +4322,12 @@ Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) if (SvPOK(cv)) Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv); else - Perl_sv_catpv(aTHX_ msg, ": none"); - sv_catpv(msg, " vs "); + sv_catpvs(msg, ": none"); + sv_catpvs(msg, " vs "); if (p) Perl_sv_catpvf(aTHX_ msg, "(%s)", p); else - sv_catpv(msg, "none"); + sv_catpvs(msg, "none"); Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, msg); } } @@ -4145,9 +4351,11 @@ L. SV * Perl_cv_const_sv(pTHX_ CV *cv) { - if (!cv || !CvCONST(cv)) - return Nullsv; - return (SV*)CvXSUBANY(cv).any_ptr; + if (!cv) + return NULL; + if (!(SvTYPE(cv) == SVt_PVCV || SvTYPE(cv) == SVt_PVFM)) + return NULL; + return CvCONST(cv) ? (SV*)CvXSUBANY(cv).any_ptr : NULL; } /* op_const_sv: examine an optree to determine whether it's in-lineable. @@ -4173,6 +4381,7 @@ Perl_cv_const_sv(pTHX_ CV *cv) SV * Perl_op_const_sv(pTHX_ const OP *o, CV *cv) { + dVAR; SV *sv = Nullsv; if (!o) @@ -4256,10 +4465,16 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) GV *gv; const char *ps; STRLEN ps_len; - register CV *cv=0; + register CV *cv = NULL; SV *const_sv; - I32 gv_fetch_flags; - + /* If the subroutine has no body, no attributes, and no builtin attributes + then it's just a sub declaration, and we may be able to get away with + storing with a placeholder scalar in the symbol table, rather than a + full GV and CV. If anything is present then it will take a full CV to + store it. */ + const I32 gv_fetch_flags + = (block || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)) + ? GV_ADDMULTI : GV_ADDMULTI | GV_NOINIT; const char * const name = o ? SvPVx_nolen_const(cSVOPo->op_sv) : Nullch; if (proto) { @@ -4279,8 +4494,6 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else aname = Nullch; - gv_fetch_flags = (block || attrs || (CvFLAGS(PL_compcv) & CVf_BUILTIN_ATTRS)) - ? GV_ADDMULTI : GV_ADDMULTI | GV_NOINIT; gv = name ? gv_fetchsv(cSVOPo->op_sv, gv_fetch_flags, SVt_PVCV) : gv_fetchpv(aname ? aname : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), @@ -4352,9 +4565,6 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) SAVEFREESV(PL_compcv); goto done; } - /* ahem, death to those who redefine active sort subs */ - if (PL_curstackinfo->si_type == PERLSI_SORT && PL_sortcop == CvSTART(cv)) - Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name); if (block) { if (ckWARN(WARN_REDEFINE) || (CvCONST(cv) @@ -4511,12 +4721,12 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) if (name || aname) { const char *s; - const char *tname = (name ? name : aname); + const char * const tname = (name ? name : aname); if (PERLDB_SUBLINE && PL_curstash != PL_debstash) { - SV *sv = NEWSV(0,0); - SV *tmpstr = sv_newmortal(); - GV *db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); + SV * const sv = NEWSV(0,0); + SV * const tmpstr = sv_newmortal(); + GV * const db_postponed = gv_fetchpv("DB::postponed", GV_ADDMULTI, SVt_PVHV); HV *hv; Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld", @@ -4633,9 +4843,10 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) CvCONST_on(cv); sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ +#ifdef USE_ITHREADS if (stash) CopSTASH_free(PL_curcop); - +#endif LEAVE; return cv; @@ -4652,6 +4863,7 @@ Used by C to hook up XSUBs as Perl subs. CV * Perl_newXS(pTHX_ const char *name, XSUBADDR_t subaddr, const char *filename) { + dVAR; GV * const gv = gv_fetchpv(name ? name : (PL_curstash ? "__ANON__" : "__ANON__::__ANON__"), GV_ADDMULTI, SVt_PVCV); @@ -4761,14 +4973,13 @@ done: void Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) { + dVAR; register CV *cv; - GV *gv; - if (o) - gv = gv_fetchsv(cSVOPo->op_sv, TRUE, SVt_PVFM); - else - gv = gv_fetchpv("STDOUT", TRUE, SVt_PVFM); - + GV * const gv = o + ? gv_fetchsv(cSVOPo->op_sv, GV_ADD, SVt_PVFM) + : gv_fetchpv("STDOUT", GV_ADD, SVt_PVFM); + #ifdef GV_UNIQUE_CHECK if (GvUNIQUE(gv)) { Perl_croak(aTHX_ "Bad symbol for form (GV is unique)"); @@ -4926,15 +5137,6 @@ Perl_newHVREF(pTHX_ OP *o) } OP * -Perl_oopsCV(pTHX_ OP *o) -{ - Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__); - /* STUB */ - PERL_UNUSED_ARG(o); - NORETURN_FUNCTION_END; -} - -OP * Perl_newCVREF(pTHX_ I32 flags, OP *o) { return newUNOP(OP_RV2CV, flags, scalar(o)); @@ -4970,6 +5172,7 @@ Perl_ck_anoncode(pTHX_ OP *o) OP * Perl_ck_bitop(pTHX_ OP *o) { + dVAR; #define OP_IS_NUMCOMPARE(op) \ ((op) == OP_LT || (op) == OP_I_LT || \ (op) == OP_GT || (op) == OP_I_GT || \ @@ -5003,7 +5206,7 @@ Perl_ck_bitop(pTHX_ OP *o) OP * Perl_ck_concat(pTHX_ OP *o) { - const OP *kid = cUNOPo->op_first; + const OP * const kid = cUNOPo->op_first; if (kid->op_type == OP_CONCAT && !(kid->op_private & OPpTARGET_MY) && !(kUNOP->op_first->op_flags & OPf_MOD)) o->op_flags |= OPf_STACKED; @@ -5076,6 +5279,7 @@ Perl_ck_die(pTHX_ OP *o) OP * Perl_ck_eof(pTHX_ OP *o) { + dVAR; const I32 type = o->op_type; if (o->op_flags & OPf_KIDS) { @@ -5130,6 +5334,12 @@ Perl_ck_eval(pTHX_ OP *o) o = newUNOP(OP_ENTEREVAL, 0, newDEFSVOP()); } o->op_targ = (PADOFFSET)PL_hints; + if ((PL_hints & HINT_LOCALIZE_HH) != 0 && GvHV(PL_hintgv)) { + /* Store a copy of %^H that pp_entereval can pick up */ + OP *hhop = newSVOP(OP_CONST, 0, (SV*)newHVhv(GvHV(PL_hintgv))); + cUNOPo->op_first->op_sibling = hhop; + o->op_private |= OPpEVAL_HAS_HH; + } return o; } @@ -5139,7 +5349,7 @@ Perl_ck_exit(pTHX_ OP *o) #ifdef VMS HV * const table = GvHV(PL_hintgv); if (table) { - SV * const * const svp = hv_fetch(table, "vmsish_exit", 11, FALSE); + SV * const * const svp = hv_fetchs(table, "vmsish_exit", FALSE); if (svp && *svp && SvTRUE(*svp)) o->op_private |= OPpEXIT_VMSISH; } @@ -5166,6 +5376,7 @@ Perl_ck_exec(pTHX_ OP *o) OP * Perl_ck_exists(pTHX_ OP *o) { + dVAR; o = ck_fun(o); if (o->op_flags & OPf_KIDS) { OP * const kid = cUNOPo->op_first; @@ -5190,9 +5401,12 @@ OP * Perl_ck_rvconst(pTHX_ register OP *o) { dVAR; - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; o->op_private |= (PL_hints & HINT_STRICT_REFS); + if (o->op_type == OP_RV2CV) + o->op_private &= ~1; + if (kid->op_type == OP_CONST) { int iscv; GV *gv; @@ -5200,7 +5414,7 @@ Perl_ck_rvconst(pTHX_ register OP *o) /* Is it a constant from cv_const_sv()? */ if (SvROK(kidsv) && SvREADONLY(kidsv)) { - SV *rsv = SvRV(kidsv); + SV * const rsv = SvRV(kidsv); const int svtype = SvTYPE(rsv); const char *badtype = Nullch; @@ -5226,7 +5440,18 @@ Perl_ck_rvconst(pTHX_ register OP *o) Perl_croak(aTHX_ "Constant is not %s reference", badtype); return o; } - if ((PL_hints & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) { + else if ((o->op_type == OP_RV2HV || o->op_type == OP_RV2SV) && + (PL_hints & HINT_STRICT_REFS) && SvPOK(kidsv)) { + /* If this is an access to a stash, disable "strict refs", because + * stashes aren't auto-vivified at compile-time (unless we store + * symbols in them), and we don't want to produce a run-time + * stricture error when auto-vivifying the stash. */ + const char *s = SvPV_nolen(kidsv); + const STRLEN l = SvCUR(kidsv); + if (l > 1 && s[l-1] == ':' && s[l-2] == ':') + o->op_private &= ~HINT_STRICT_REFS; + } + if ((o->op_private & HINT_STRICT_REFS) && (kid->op_private & OPpCONST_BARE)) { const char *badthing = Nullch; switch (o->op_type) { case OP_RV2SV: @@ -5299,7 +5524,7 @@ Perl_ck_ftst(pTHX_ OP *o) if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { OP * const newop = newGVOP(type, OPf_REF, - gv_fetchsv(kid->op_sv, TRUE, SVt_PVIO)); + gv_fetchsv(kid->op_sv, GV_ADD, SVt_PVIO)); op_free(o); o = newop; return o; @@ -5326,6 +5551,7 @@ Perl_ck_ftst(pTHX_ OP *o) OP * Perl_ck_fun(pTHX_ OP *o) { + dVAR; const int type = o->op_type; register I32 oa = PL_opargs[type] >> OASHIFT; @@ -5383,7 +5609,7 @@ Perl_ck_fun(pTHX_ OP *o) (kid->op_private & OPpCONST_BARE)) { OP * const newop = newAVREF(newGVOP(OP_GV, 0, - gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVAV) )); + gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVAV) )); if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Array @%"SVf" missing the @ in argument %"IVdf" of %s()", @@ -5402,7 +5628,7 @@ Perl_ck_fun(pTHX_ OP *o) (kid->op_private & OPpCONST_BARE)) { OP * const newop = newHVREF(newGVOP(OP_GV, 0, - gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVHV) )); + gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVHV) )); if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()", @@ -5432,8 +5658,8 @@ Perl_ck_fun(pTHX_ OP *o) if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { - OP *newop = newGVOP(OP_GV, 0, - gv_fetchsv(((SVOP*)kid)->op_sv, TRUE, SVt_PVIO) ); + OP * const newop = newGVOP(OP_GV, 0, + gv_fetchsv(((SVOP*)kid)->op_sv, GV_ADD, SVt_PVIO)); if (!(o->op_private & 1) && /* if not unop */ kid == cLISTOPo->op_last) cLISTOPo->op_last = newop; @@ -5472,7 +5698,7 @@ Perl_ck_fun(pTHX_ OP *o) else if (kid->op_type == OP_RV2SV && kUNOP->op_first->op_type == OP_GV) { - GV *gv = cGVOPx_gv(kUNOP->op_first); + GV * const gv = cGVOPx_gv(kUNOP->op_first); name = GvNAME(gv); len = GvNAMELEN(gv); } @@ -5480,7 +5706,7 @@ Perl_ck_fun(pTHX_ OP *o) || kid->op_type == OP_HELEM) { OP *op = ((BINOP*)kid)->op_first; - name = 0; + name = NULL; if (op) { SV *tmpstr = Nullsv; const char * const a = @@ -5579,10 +5805,10 @@ Perl_ck_glob(pTHX_ OP *o) if ((o->op_flags & OPf_KIDS) && !cLISTOPo->op_first->op_sibling) append_elem(OP_GLOB, o, newDEFSVOP()); - if (!((gv = gv_fetchpv("glob", FALSE, SVt_PVCV)) + if (!((gv = gv_fetchpv("glob", 0, SVt_PVCV)) && GvCVu(gv) && GvIMPORTED_CV(gv))) { - gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV); + gv = gv_fetchpv("CORE::GLOBAL::glob", 0, SVt_PVCV); } #if !defined(PERL_EXTERNAL_GLOB) @@ -5591,9 +5817,9 @@ Perl_ck_glob(pTHX_ OP *o) GV *glob_gv; ENTER; Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, - newSVpvn("File::Glob", 10), Nullsv, Nullsv, Nullsv); - gv = gv_fetchpv("CORE::GLOBAL::glob", FALSE, SVt_PVCV); - glob_gv = gv_fetchpv("File::Glob::csh_glob", FALSE, SVt_PVCV); + newSVpvs("File::Glob"), Nullsv, Nullsv, Nullsv); + gv = gv_fetchpv("CORE::GLOBAL::glob", 0, SVt_PVCV); + glob_gv = gv_fetchpv("File::Glob::csh_glob", 0, SVt_PVCV); GvCV(gv) = GvCV(glob_gv); (void)SvREFCNT_inc((SV*)GvCV(gv)); GvIMPORTED_CV_on(gv); @@ -5789,6 +6015,44 @@ Perl_ck_listiob(pTHX_ OP *o) } OP * +Perl_ck_say(pTHX_ OP *o) +{ + o = ck_listiob(o); + o->op_type = OP_PRINT; + cLISTOPo->op_last = cLISTOPo->op_last->op_sibling + = newSVOP(OP_CONST, 0, newSVpvs("\n")); + return o; +} + +OP * +Perl_ck_smartmatch(pTHX_ OP *o) +{ + dVAR; + if (0 == (o->op_flags & OPf_SPECIAL)) { + OP *first = cBINOPo->op_first; + OP *second = first->op_sibling; + + /* Implicitly take a reference to an array or hash */ + first->op_sibling = Nullop; + first = cBINOPo->op_first = ref_array_or_hash(first); + second = first->op_sibling = ref_array_or_hash(second); + + /* Implicitly take a reference to a regular expression */ + if (first->op_type == OP_MATCH) { + first->op_type = OP_QR; + first->op_ppaddr = PL_ppaddr[OP_QR]; + } + if (second->op_type == OP_MATCH) { + second->op_type = OP_QR; + second->op_ppaddr = PL_ppaddr[OP_QR]; + } + } + + return o; +} + + +OP * Perl_ck_sassign(pTHX_ OP *o) { OP *kid = cLISTOPo->op_first; @@ -5815,26 +6079,14 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } - /* optimise C to C */ - if (kid->op_type == OP_UNDEF) { - OP * const kkid = kid->op_sibling; - if (kkid && kkid->op_type == OP_PADSV - && (kkid->op_private & OPpLVAL_INTRO)) - { - cLISTOPo->op_first = NULL; - kid->op_sibling = NULL; - op_free(o); - op_free(kid); - return kkid; - } - } return o; } OP * Perl_ck_match(pTHX_ OP *o) { - if (o->op_type != OP_QR) { + dVAR; + if (o->op_type != OP_QR && PL_compcv) { const I32 offset = pad_findmy("$_"); if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS(offset) & SVpad_OUR)) { o->op_targ = offset; @@ -5852,10 +6104,11 @@ Perl_ck_method(pTHX_ OP *o) OP * const kid = cUNOPo->op_first; if (kid->op_type == OP_CONST) { SV* sv = kSVOP->op_sv; - if (!(strchr(SvPVX_const(sv), ':') || strchr(SvPVX_const(sv), '\''))) { + const char * const method = SvPVX_const(sv); + if (!(strchr(method, ':') || strchr(method, '\''))) { OP *cmop; if (!SvREADONLY(sv) || !SvFAKE(sv)) { - sv = newSVpvn_share(SvPVX_const(sv), SvCUR(sv), 0); + sv = newSVpvn_share(method, SvCUR(sv), 0); } else { kSVOP->op_sv = Nullsv; @@ -5877,9 +6130,10 @@ Perl_ck_null(pTHX_ OP *o) OP * Perl_ck_open(pTHX_ OP *o) { + dVAR; HV * const table = GvHV(PL_hintgv); if (table) { - SV **svp = hv_fetch(table, "open_IN", 7, FALSE); + SV **svp = hv_fetchs(table, "open_IN", FALSE); if (svp && *svp) { const I32 mode = mode_from_discipline(*svp); if (mode & O_BINARY) @@ -5888,7 +6142,7 @@ Perl_ck_open(pTHX_ OP *o) o->op_private |= OPpOPEN_IN_CRLF; } - svp = hv_fetch(table, "open_OUT", 8, FALSE); + svp = hv_fetchs(table, "open_OUT", FALSE); if (svp && *svp) { const I32 mode = mode_from_discipline(*svp); if (mode & O_BINARY) @@ -5937,6 +6191,7 @@ Perl_ck_repeat(pTHX_ OP *o) OP * Perl_ck_require(pTHX_ OP *o) { + dVAR; GV* gv = Nullgv; if (o->op_flags & OPf_KIDS) { /* Shall we supply missing .pm? */ @@ -5959,21 +6214,22 @@ Perl_ck_require(pTHX_ OP *o) for (s = SvPVX(sv); *s; s++) { if (*s == ':' && s[1] == ':') { + const STRLEN len = strlen(s+2)+1; *s = '/'; - Move(s+2, s+1, strlen(s+2)+1, char); + Move(s+2, s+1, len, char); SvCUR_set(sv, SvCUR(sv) - 1); } } - sv_catpvn(sv, ".pm", 3); + sv_catpvs(sv, ".pm"); SvFLAGS(sv) |= was_readonly; } } if (!(o->op_flags & OPf_SPECIAL)) { /* Wasn't written as CORE::require */ /* handle override, if any */ - gv = gv_fetchpv("require", FALSE, SVt_PVCV); + gv = gv_fetchpv("require", 0, SVt_PVCV); if (!(gv && GvCVu(gv) && GvIMPORTED_CV(gv))) { - GV * const * const gvp = (GV**)hv_fetch(PL_globalstash, "require", 7, FALSE); + GV * const * const gvp = (GV**)hv_fetchs(PL_globalstash, "require", FALSE); gv = gvp ? *gvp : Nullgv; } } @@ -5995,6 +6251,7 @@ Perl_ck_require(pTHX_ OP *o) OP * Perl_ck_return(pTHX_ OP *o) { + dVAR; if (CvLVALUE(PL_compcv)) { OP *kid; for (kid = cLISTOPo->op_first->op_sibling; kid; kid = kid->op_sibling) @@ -6003,16 +6260,6 @@ Perl_ck_return(pTHX_ OP *o) return o; } -#if 0 -OP * -Perl_ck_retarget(pTHX_ OP *o) -{ - Perl_croak(aTHX_ "NOT IMPL LINE %d",__LINE__); - /* STUB */ - return o; -} -#endif - OP * Perl_ck_select(pTHX_ OP *o) { @@ -6037,6 +6284,7 @@ Perl_ck_select(pTHX_ OP *o) OP * Perl_ck_shift(pTHX_ OP *o) { + dVAR; const I32 type = o->op_type; if (!(o->op_flags & OPf_KIDS)) { @@ -6053,8 +6301,24 @@ Perl_ck_shift(pTHX_ OP *o) OP * Perl_ck_sort(pTHX_ OP *o) { + dVAR; OP *firstkid; + if (o->op_type == OP_SORT && (PL_hints & HINT_LOCALIZE_HH) != 0) + { + HV * const hinthv = GvHV(PL_hintgv); + if (hinthv) { + SV ** const svp = hv_fetchs(hinthv, "sort", FALSE); + if (svp) { + const I32 sorthints = (I32)SvIV(*svp); + if ((sorthints & HINT_SORT_QUICKSORT) != 0) + o->op_private |= OPpSORT_QSORT; + if ((sorthints & HINT_SORT_STABLE) != 0) + o->op_private |= OPpSORT_STABLE; + } + } + } + if (o->op_type == OP_SORT && o->op_flags & OPf_STACKED) simplify_sort(o); firstkid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ @@ -6116,6 +6380,7 @@ Perl_ck_sort(pTHX_ OP *o) STATIC void S_simplify_sort(pTHX_ OP *o) { + dVAR; register OP *kid = cLISTOPo->op_first->op_sibling; /* get past pushmark */ OP *k; int descending; @@ -6123,8 +6388,8 @@ S_simplify_sort(pTHX_ OP *o) const char *gvname; if (!(o->op_flags & OPf_STACKED)) return; - GvMULTI_on(gv_fetchpv("a", TRUE, SVt_PV)); - GvMULTI_on(gv_fetchpv("b", TRUE, SVt_PV)); + GvMULTI_on(gv_fetchpv("a", GV_ADD, SVt_PV)); + GvMULTI_on(gv_fetchpv("b", GV_ADD, SVt_PV)); kid = kUNOP->op_first; /* get past null */ if (kid->op_type != OP_SCOPE) return; @@ -6198,7 +6463,7 @@ Perl_ck_split(pTHX_ OP *o) op_free(cLISTOPo->op_first); cLISTOPo->op_first = kid; if (!kid) { - cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvn(" ", 1)); + cLISTOPo->op_first = kid = newSVOP(OP_CONST, 0, newSVpvs(" ")); cLISTOPo->op_last = kid; /* There was only one element previously */ } @@ -6257,17 +6522,18 @@ Perl_ck_join(pTHX_ OP *o) OP * Perl_ck_subr(pTHX_ OP *o) { + dVAR; OP *prev = ((cUNOPo->op_first->op_sibling) ? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first; OP *o2 = prev->op_sibling; OP *cvop; - char *proto = 0; - CV *cv = 0; - GV *namegv = 0; + char *proto = NULL; + CV *cv = NULL; + GV *namegv = NULL; int optional = 0; I32 arg = 0; I32 contextclass = 0; - char *e = 0; + char *e = NULL; bool delete_op = 0; o->op_private |= OPpENTERSUB_HASTARG; @@ -6365,7 +6631,7 @@ Perl_ck_subr(pTHX_ OP *o) { GV * const gv = cGVOPx_gv(gvop); OP * const sibling = o2->op_sibling; - SV * const n = newSVpvn("",0); + SV * const n = newSVpvs(""); op_free(o2); gv_fullname4(n, gv, "", FALSE); o2 = newSVOP(OP_CONST, 0, n); @@ -6397,6 +6663,7 @@ Perl_ck_subr(pTHX_ OP *o) break; case ']': if (contextclass) { + /* XXX We shouldn't be modifying proto, so we can const proto */ char *p = proto; const char s = *p; contextclass = 0; @@ -6549,7 +6816,7 @@ void Perl_peep(pTHX_ register OP *o) { dVAR; - register OP* oldop = 0; + register OP* oldop = NULL; if (!o || o->op_opt) return; @@ -6585,6 +6852,18 @@ Perl_peep(pTHX_ register OP *o) SvREADONLY_on(PAD_SVl(ix)); SvREFCNT_dec(cSVOPo->op_sv); } + else if (o->op_type == OP_CONST + && cSVOPo->op_sv == &PL_sv_undef) { + /* PL_sv_undef is hack - it's unsafe to store it in the + AV that is the pad, because av_fetch treats values of + PL_sv_undef as a "free" AV entry and will merrily + replace them with a new SV, causing pad_alloc to think + that this pad slot is free. (When, clearly, it is not) + */ + SvOK_off(PAD_SVl(ix)); + SvPADTMP_on(PAD_SVl(ix)); + SvREADONLY_on(PAD_SVl(ix)); + } else { SvREFCNT_dec(PAD_SVl(ix)); SvPADTMP_on(cSVOPo->op_sv); @@ -6653,7 +6932,7 @@ Perl_peep(pTHX_ register OP *o) case OP_PADAV: case OP_GV: if (o->op_type == OP_PADAV || o->op_next->op_type == OP_RV2AV) { - OP* pop = (o->op_type == OP_PADAV) ? + OP* const pop = (o->op_type == OP_PADAV) ? o->op_next : o->op_next->op_next; IV i; if (pop && pop->op_type == OP_CONST && @@ -6818,7 +7097,7 @@ Perl_peep(pTHX_ register OP *o) lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE); if (!(SvFLAGS(lexname) & SVpad_TYPED)) break; - fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE); + fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); if (!fields || !GvHV(*fields)) break; key = SvPV_const(*svp, keylen); @@ -6867,7 +7146,7 @@ Perl_peep(pTHX_ register OP *o) lexname = *av_fetch(PL_comppad_name, rop->op_targ, TRUE); if (!(SvFLAGS(lexname) & SVpad_TYPED)) break; - fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE); + fields = (GV**)hv_fetchs(SvSTASH(lexname), "FIELDS", FALSE); if (!fields || !GvHV(*fields)) break; /* Again guessing that the pushmark can be jumped over.... */ @@ -7098,6 +7377,58 @@ Perl_peep(pTHX_ register OP *o) break; } + + case OP_SASSIGN: { + OP *rv2gv; + UNOP *refgen, *rv2cv; + LISTOP *exlist; + + /* I do not understand this, but if o->op_opt isn't set to 1, + various tests in ext/B/t/bytecode.t fail with no readily + apparent cause. */ + + o->op_opt = 1; + + + if ((o->op_flags && OPf_WANT) != OPf_WANT_VOID) + break; + + if ((o->op_private & ~OPpASSIGN_BACKWARDS) != 2) + break; + + rv2gv = ((BINOP *)o)->op_last; + if (!rv2gv || rv2gv->op_type != OP_RV2GV) + break; + + refgen = (UNOP *)((BINOP *)o)->op_first; + + if (!refgen || refgen->op_type != OP_REFGEN) + break; + + exlist = (LISTOP *)refgen->op_first; + if (!exlist || exlist->op_type != OP_NULL + || exlist->op_targ != OP_LIST) + break; + + if (exlist->op_first->op_type != OP_PUSHMARK) + break; + + rv2cv = (UNOP*)exlist->op_last; + + if (rv2cv->op_type != OP_RV2CV) + break; + + assert ((rv2gv->op_private & OPpDONT_INIT_GV) == 0); + assert ((o->op_private & OPpASSIGN_CV_TO_GV) == 0); + assert ((rv2cv->op_private & OPpMAY_RETURN_CONSTANT) == 0); + + o->op_private |= OPpASSIGN_CV_TO_GV; + rv2gv->op_private |= OPpDONT_INIT_GV; + rv2cv->op_private |= OPpMAY_RETURN_CONSTANT; + + break; + } + default: o->op_opt = 1; @@ -7111,6 +7442,7 @@ Perl_peep(pTHX_ register OP *o) char* Perl_custom_op_name(pTHX_ const OP* o) { + dVAR; const IV index = PTR2IV(o->op_ppaddr); SV* keysv; HE* he; @@ -7130,6 +7462,7 @@ Perl_custom_op_name(pTHX_ const OP* o) char* Perl_custom_op_desc(pTHX_ const OP* o) { + dVAR; const IV index = PTR2IV(o->op_ppaddr); SV* keysv; HE* he; @@ -7152,6 +7485,7 @@ Perl_custom_op_desc(pTHX_ const OP* o) static void const_sv_xsub(pTHX_ CV* cv) { + dVAR; dXSARGS; if (items != 0) { #if 0