X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/cc8773c013ccdaec9cb8d2c57d85a70c368e102f..112a1457c05eac6b69395fa04d5d1fdca4a73702:/op.c diff --git a/op.c b/op.c index 1bd3498..5ca1823 100644 --- a/op.c +++ b/op.c @@ -1,3 +1,4 @@ +#line 2 "op.c" /* op.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, @@ -102,8 +103,9 @@ recursive, but it's recursive on basic blocks, not on tree nodes. #include "perl.h" #include "keywords.h" -#define CALL_PEEP(o) CALL_FPTR(PL_peepp)(aTHX_ o) -#define CALL_OPFREEHOOK(o) if (PL_opfreehook) CALL_FPTR(PL_opfreehook)(aTHX_ o) +#define CALL_PEEP(o) PL_peepp(aTHX_ o) +#define CALL_RPEEP(o) PL_rpeepp(aTHX_ o) +#define CALL_OPFREEHOOK(o) if (PL_opfreehook) PL_opfreehook(aTHX_ o) #if defined(PL_OP_SLAB_ALLOC) @@ -304,7 +306,7 @@ Perl_Slab_Free(pTHX_ void *op) ? ( op_free((OP*)o), \ Perl_croak(aTHX_ "'%s' trapped by operation mask", PL_op_desc[type]), \ (OP*)0 ) \ - : CALL_FPTR(PL_check[type])(aTHX_ (OP*)o)) + : PL_check[type](aTHX_ (OP*)o)) #define RETURN_UNLIMITED_NUMBER (PERL_INT_MAX / 2) @@ -371,7 +373,7 @@ S_no_bareword_allowed(pTHX_ const OP *o) /* "register" allocation */ PADOFFSET -Perl_allocmy(pTHX_ const char *const name) +Perl_allocmy(pTHX_ const char *const name, const STRLEN len, const U32 flags) { dVAR; PADOFFSET off; @@ -379,38 +381,43 @@ Perl_allocmy(pTHX_ const char *const name) PERL_ARGS_ASSERT_ALLOCMY; + if (flags) + Perl_croak(aTHX_ "panic: allocmy illegal flag bits 0x%" UVxf, + (UV)flags); + + /* Until we're using the length for real, cross check that we're being + told the truth. */ + assert(strlen(name) == len); + /* complain about "my $" etc etc */ - if (*name && + if (len && !(is_our || isALPHA(name[1]) || (USE_UTF8_IN_NAMES && UTF8_IS_START(name[1])) || - (name[1] == '_' && (*name == '$' || name[2])))) + (name[1] == '_' && (*name == '$' || len > 2)))) { /* name[2] is true if strlen(name) > 2 */ if (!isPRINT(name[1]) || strchr("\t\n\r\f", name[1])) { - yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"%s\"", - name[0], toCTRL(name[1]), name + 2, + yyerror(Perl_form(aTHX_ "Can't use global %c^%c%.*s in \"%s\"", + name[0], toCTRL(name[1]), (int)(len - 2), name + 2, PL_parser->in_my == KEY_state ? "state" : "my")); } else { - yyerror(Perl_form(aTHX_ "Can't use global %s in \"%s\"",name, + yyerror(Perl_form(aTHX_ "Can't use global %.*s in \"%s\"", (int) len, name, PL_parser->in_my == KEY_state ? "state" : "my")); } } - /* check for duplicate declaration */ - pad_check_dup(name, is_our, (PL_curstash ? PL_curstash : PL_defstash)); - /* allocate a spare slot and store the name in that slot */ - off = pad_add_name(name, + off = pad_add_name(name, len, + is_our ? padadd_OUR : + PL_parser->in_my == KEY_state ? padadd_STATE : 0, PL_parser->in_my_stash, (is_our /* $_ is always in main::, even with our */ ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash) : NULL - ), - 0, /* not fake */ - PL_parser->in_my == KEY_state + ) ); /* anon sub prototypes contains state vars should always be cloned, * otherwise the state var would be shared between anon subs */ @@ -556,6 +563,7 @@ Perl_op_clear(pTHX_ OP *o) o->op_targ = 0; goto retry; } + case OP_ENTERTRY: case OP_ENTEREVAL: /* Was holding hints. */ o->op_targ = 0; break; @@ -569,6 +577,29 @@ Perl_op_clear(pTHX_ OP *o) case OP_AELEMFAST: if (! (o->op_type == OP_AELEMFAST && o->op_flags & OPf_SPECIAL)) { /* not an OP_PADAV replacement */ + GV *gv = (o->op_type == OP_GV || o->op_type == OP_GVSV) +#ifdef USE_ITHREADS + && PL_curpad +#endif + ? cGVOPo_gv : NULL; + /* It's possible during global destruction that the GV is freed + before the optree. Whilst the SvREFCNT_inc is happy to bump from + 0 to 1 on a freed SV, the corresponding SvREFCNT_dec from 1 to 0 + will trigger an assertion failure, because the entry to sv_clear + checks that the scalar is not already freed. A check of for + !SvIS_FREED(gv) turns out to be invalid, because during global + destruction the reference count can be forced down to zero + (with SVf_BREAK set). In which case raising to 1 and then + dropping to 0 triggers cleanup before it should happen. I + *think* that this might actually be a general, systematic, + weakness of the whole idea of SVf_BREAK, in that code *is* + allowed to raise and lower references during global destruction, + so any *valid* code that happens to do this during global + destruction might well trigger premature cleanup. */ + bool still_valid = gv && SvREFCNT(gv); + + if (still_valid) + SvREFCNT_inc_simple_void(gv); #ifdef USE_ITHREADS if (cPADOPo->op_padix > 0) { /* No GvIN_PAD_off(cGVOPo_gv) here, because other references @@ -580,6 +611,12 @@ Perl_op_clear(pTHX_ OP *o) SvREFCNT_dec(cSVOPo->op_sv); cSVOPo->op_sv = NULL; #endif + if (still_valid) { + int try_downgrade = SvREFCNT(gv) == 2; + SvREFCNT_dec(gv); + if (try_downgrade) + gv_try_downgrade(gv); + } } break; case OP_METHOD_NAMED: @@ -872,12 +909,8 @@ Perl_scalar(pTHX_ OP *o) for (kid = cUNOPo->op_first->op_sibling; kid; kid = kid->op_sibling) scalar(kid); break; - case OP_SPLIT: - if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) { - if (!kPMOP->op_pmreplrootu.op_pmreplroot) - deprecate_old("implicit split to @_"); - } /* FALL THROUGH */ + case OP_SPLIT: case OP_MATCH: case OP_QR: case OP_SUBST: @@ -892,28 +925,30 @@ Perl_scalar(pTHX_ OP *o) case OP_LEAVETRY: kid = cLISTOPo->op_first; scalar(kid); - while ((kid = kid->op_sibling)) { - if (kid->op_sibling) - scalarvoid(kid); - else + kid = kid->op_sibling; + do_kids: + while (kid) { + OP *sib = kid->op_sibling; + if (sib && kid->op_type != OP_LEAVEWHEN) { + if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) { + scalar(kid); + scalarvoid(sib); + break; + } else + scalarvoid(kid); + } else scalar(kid); + kid = sib; } PL_curcop = &PL_compiling; break; case OP_SCOPE: case OP_LINESEQ: case OP_LIST: - for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) { - if (kid->op_sibling) - scalarvoid(kid); - else - scalar(kid); - } - PL_curcop = &PL_compiling; - break; + kid = cLISTOPo->op_first; + goto do_kids; case OP_SORT: - if (ckWARN(WARN_VOID)) - Perl_warner(aTHX_ packWARN(WARN_VOID), "Useless use of sort in scalar context"); + Perl_ck_warner(aTHX_ packWARN(WARN_VOID), "Useless use of sort in scalar context"); break; } return o; @@ -955,7 +990,7 @@ Perl_scalarvoid(pTHX_ OP *o) want = o->op_flags & OPf_WANT; if ((want && want != OPf_WANT_SCALAR) || (PL_parser && PL_parser->error_count) - || o->op_type == OP_RETURN) + || o->op_type == OP_RETURN || o->op_type == OP_REQUIRE || o->op_type == OP_LEAVEWHEN) { return o; } @@ -1056,6 +1091,17 @@ Perl_scalarvoid(pTHX_ OP *o) useless = OP_DESC(o); break; + case OP_SPLIT: + kid = cLISTOPo->op_first; + if (kid && kid->op_type == OP_PUSHRE +#ifdef USE_ITHREADS + && !((PMOP*)kid)->op_pmreplrootu.op_pmtargetoff) +#else + && !((PMOP*)kid)->op_pmreplrootu.op_pmtargetgv) +#endif + useless = OP_DESC(o); + break; + case OP_NOT: kid = cUNOPo->op_first; if (kid->op_type != OP_MATCH && kid->op_type != OP_SUBST && @@ -1065,6 +1111,11 @@ Perl_scalarvoid(pTHX_ OP *o) useless = "negative pattern binding (!~)"; break; + case OP_SUBST: + if (cPMOPo->op_pmflags & PMf_NONDESTRUCT) + useless = "Non-destructive substitution (s///r)"; + break; + case OP_RV2GV: case OP_RV2SV: case OP_RV2AV: @@ -1185,21 +1236,11 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_ENTEREVAL: scalarkids(o); break; - case OP_REQUIRE: - /* all requires must return a boolean value */ - o->op_flags &= ~OPf_WANT; - /* FALL THROUGH */ case OP_SCALAR: return scalar(o); - case OP_SPLIT: - if ((kid = cLISTOPo->op_first) && kid->op_type == OP_PUSHRE) { - if (!kPMOP->op_pmreplrootu.op_pmreplroot) - deprecate_old("implicit split to @_"); - } - break; } - if (useless && ckWARN(WARN_VOID)) - Perl_warner(aTHX_ packWARN(WARN_VOID), "Useless use of %s in void context", useless); + if (useless) + Perl_ck_warner(aTHX_ packWARN(WARN_VOID), "Useless use of %s in void context", useless); return o; } @@ -1265,28 +1306,27 @@ Perl_list(pTHX_ OP *o) case OP_LEAVETRY: kid = cLISTOPo->op_first; list(kid); - while ((kid = kid->op_sibling)) { - if (kid->op_sibling) - scalarvoid(kid); - else + kid = kid->op_sibling; + do_kids: + while (kid) { + OP *sib = kid->op_sibling; + if (sib && kid->op_type != OP_LEAVEWHEN) { + if (sib->op_type == OP_BREAK && sib->op_flags & OPf_SPECIAL) { + list(kid); + scalarvoid(sib); + break; + } else + scalarvoid(kid); + } else list(kid); + kid = sib; } PL_curcop = &PL_compiling; break; case OP_SCOPE: case OP_LINESEQ: - for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) { - if (kid->op_sibling) - scalarvoid(kid); - else - list(kid); - } - PL_curcop = &PL_compiling; - break; - case OP_REQUIRE: - /* all requires must return a boolean value */ - o->op_flags &= ~OPf_WANT; - return scalar(o); + kid = cLISTOPo->op_first; + goto do_kids; } return o; } @@ -1551,12 +1591,17 @@ Perl_mod(pTHX_ OP *o, I32 type) case OP_DBSTATE: PL_modcount = RETURN_UNLIMITED_NUMBER; break; + case OP_AV2ARYLEN: + PL_hints |= HINT_BLOCK_SCOPE; + if (type == OP_LEAVESUBLV) + o->op_private |= OPpMAYBE_LVSUB; + PL_modcount++; + break; case OP_RV2SV: ref(cUNOPo->op_first, o->op_type); localize = 1; /* FALL THROUGH */ case OP_GV: - case OP_AV2ARYLEN: PL_hints |= HINT_BLOCK_SCOPE; case OP_SASSIGN: case OP_ANDASSIGN: @@ -1677,10 +1722,8 @@ Perl_mod(pTHX_ OP *o, I32 type) case 0: break; case -1: - if (ckWARN(WARN_SYNTAX)) { - Perl_warner(aTHX_ packWARN(WARN_SYNTAX), - "Useless localization of %s", OP_DESC(o)); - } + Perl_ck_warner(aTHX_ packWARN(WARN_SYNTAX), + "Useless localization of %s", OP_DESC(o)); } } else if (type != OP_GREPSTART && type != OP_ENTERSUB @@ -2188,6 +2231,11 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) no_bareword_allowed(right); } + /* !~ doesn't make sense with s///r, so error on it for now */ + if (rtype == OP_SUBST && (cPMOPx(right)->op_pmflags & PMf_NONDESTRUCT) && + type == OP_NOT) + yyerror("Using !~ with s///r doesn't make sense"); + ismatchop = rtype == OP_MATCH || rtype == OP_SUBST || rtype == OP_TRANS; @@ -2201,7 +2249,9 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) right->op_flags |= OPf_STACKED; if (rtype != OP_MATCH && ! (rtype == OP_TRANS && - right->op_private & OPpTRANS_IDENTICAL)) + right->op_private & OPpTRANS_IDENTICAL) && + ! (rtype == OP_SUBST && + (cPMOPx(right)->op_pmflags & PMf_NONDESTRUCT))) newleft = mod(left, rtype); else newleft = left; @@ -2256,17 +2306,21 @@ Perl_scope(pTHX_ OP *o) } return o; } - + int Perl_block_start(pTHX_ int full) { dVAR; const int retval = PL_savestack_ix; + pad_block_start(full); SAVEHINTS(); PL_hints &= ~HINT_BLOCK_SCOPE; SAVECOMPILEWARNINGS(); PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings); + + CALL_BLOCK_HOOKS(start, full); + return retval; } @@ -2275,20 +2329,45 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) { dVAR; const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; - OP* const retval = scalarseq(seq); + OP* retval = scalarseq(seq); + + CALL_BLOCK_HOOKS(pre_end, &retval); + LEAVE_SCOPE(floor); CopHINTS_set(&PL_compiling, PL_hints); if (needblockscope) PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */ pad_leavemy(); + + CALL_BLOCK_HOOKS(post_end, &retval); + return retval; } +/* +=head1 Compile-time scope hooks + +=for apidoc Ao||blockhook_register + +Register a set of hooks to be called when the Perl lexical scope changes +at compile time. See L. + +=cut +*/ + +void +Perl_blockhook_register(pTHX_ BHK *hk) +{ + PERL_ARGS_ASSERT_BLOCKHOOK_REGISTER; + + Perl_av_create_and_push(aTHX_ &PL_blockhooks, newSViv(PTR2IV(hk))); +} + STATIC OP * S_newDEFSVOP(pTHX) { dVAR; - const PADOFFSET offset = pad_findmy("$_"); + const PADOFFSET offset = Perl_pad_findmy(aTHX_ STR_WITH_LEN("$_"), 0); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); } @@ -2590,7 +2669,7 @@ S_gen_constant_list(pTHX_ register OP *o) o->op_ppaddr = PL_ppaddr[OP_RV2AV]; o->op_flags &= ~OPf_REF; /* treat \(1..2) like an ordinary list */ o->op_flags |= OPf_PARENS; /* and flatten \(1..2,3) */ - o->op_opt = 0; /* needs to be revisited in peep() */ + o->op_opt = 0; /* needs to be revisited in rpeep() */ curop = ((UNOP*)o)->op_first; ((UNOP*)o)->op_first = newSVOP(OP_CONST, 0, SvREFCNT_inc_NN(*PL_stack_sp--)); #ifdef PERL_MAD @@ -2770,7 +2849,7 @@ Perl_token_getmad(pTHX_ TOKEN* tk, OP* o, char slot) /* faked up qw list? */ if (slot == '(' && tm->mad_type == MAD_SV && - SvPVX((const SV *)tm->mad_val)[0] == 'q') + SvPVX((SV *)tm->mad_val)[0] == 'q') slot = 'x'; if (o) { @@ -2927,7 +3006,7 @@ Perl_newMADsv(pTHX_ char key, SV* sv) } MADPROP * -Perl_newMADPROP(pTHX_ char key, char type, const void* val, I32 vlen) +Perl_newMADPROP(pTHX_ char key, char type, void* val, I32 vlen) { MADPROP *mp; Newxz(mp, 1, MADPROP); @@ -2972,6 +3051,17 @@ Perl_mad_free(pTHX_ MADPROP* mp) #endif +/* +=head1 Optree construction + +=for apidoc Am|OP *|newNULLLIST + +Constructs, checks, and returns a new C op, which represents an +empty list expression. + +=cut +*/ + OP * Perl_newNULLLIST(pTHX) { @@ -2987,12 +3077,26 @@ S_force_list(pTHX_ OP *o) return o; } +/* +=for apidoc Am|OP *|newLISTOP|I32 type|I32 flags|OP *first|OP *last + +Constructs, checks, and returns an op of any list type. I is +the opcode. I gives the eight bits of C, except that +C will be set automatically if required. I and I +supply up to two ops to be direct children of the list op; they are +consumed by this function and become part of the constructed op tree. + +=cut +*/ + OP * Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) { dVAR; LISTOP *listop; + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_LISTOP); + NewOp(1101, listop, 1, LISTOP); listop->op_type = (OPCODE)type; @@ -3021,11 +3125,28 @@ Perl_newLISTOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) return CHECKOP(type, listop); } +/* +=for apidoc Am|OP *|newOP|I32 type|I32 flags + +Constructs, checks, and returns an op of any base type (any type that +has no extra fields). I is the opcode. I gives the +eight bits of C, and, shifted up eight bits, the eight bits +of C. + +=cut +*/ + OP * Perl_newOP(pTHX_ I32 type, I32 flags) { dVAR; OP *o; + + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_BASEOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_BASEOP_OR_UNOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_FILESTATOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_LOOPEXOP); + NewOp(1101, o, 1, OP); o->op_type = (OPCODE)type; o->op_ppaddr = PL_ppaddr[type]; @@ -3043,12 +3164,34 @@ Perl_newOP(pTHX_ I32 type, I32 flags) return CHECKOP(type, o); } +/* +=for apidoc Am|OP *|newUNOP|I32 type|I32 flags|OP *first + +Constructs, checks, and returns an op of any unary type. I is +the opcode. I gives the eight bits of C, except that +C will be set automatically if required, and, shifted up eight +bits, the eight bits of C, except that the bit with value 1 +is automatically set. I supplies an optional op to be the direct +child of the unary op; it is consumed by this function and become part +of the constructed op tree. + +=cut +*/ + OP * Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) { dVAR; UNOP *unop; + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_UNOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_BASEOP_OR_UNOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_FILESTATOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_LOOPEXOP + || type == OP_SASSIGN + || type == OP_ENTERTRY + || type == OP_NULL ); + if (!first) first = newOP(OP_STUB, 0); if (PL_opargs[type] & OA_MARK) @@ -3067,11 +3210,29 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first) return fold_constants((OP *) unop); } +/* +=for apidoc Am|OP *|newBINOP|I32 type|I32 flags|OP *first|OP *last + +Constructs, checks, and returns an op of any binary type. I +is the opcode. I gives the eight bits of C, except +that C will be set automatically, and, shifted up eight bits, +the eight bits of C, except that the bit with value 1 or +2 is automatically set as required. I and I supply up to +two ops to be the direct children of the binary op; they are consumed +by this function and become part of the constructed op tree. + +=cut +*/ + OP * Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last) { dVAR; BINOP *binop; + + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_BINOP + || type == OP_SASSIGN || type == OP_NULL ); + NewOp(1101, binop, 1, BINOP); if (!first) @@ -3442,12 +3603,10 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) } } - if(ckWARN(WARN_MISC)) { - if(del && rlen == tlen) { - Perl_warner(aTHX_ packWARN(WARN_MISC), "Useless use of /d modifier in transliteration operator"); - } else if(rlen > tlen) { - Perl_warner(aTHX_ packWARN(WARN_MISC), "Replacement list is longer than search list"); - } + if(del && rlen == tlen) { + Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Useless use of /d modifier in transliteration operator"); + } else if(rlen > tlen) { + Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Replacement list is longer than search list"); } if (grows) @@ -3463,12 +3622,24 @@ S_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) return o; } +/* +=for apidoc Am|OP *|newPMOP|I32 type|I32 flags + +Constructs, checks, and returns an op of any pattern matching type. +I is the opcode. I gives the eight bits of C +and, shifted up eight bits, the eight bits of C. + +=cut +*/ + OP * Perl_newPMOP(pTHX_ I32 type, I32 flags) { dVAR; PMOP *pmop; + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_PMOP); + NewOp(1101, pmop, 1, PMOP); pmop->op_type = (OPCODE)type; pmop->op_ppaddr = PL_ppaddr[type]; @@ -3705,6 +3876,17 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) return (OP*)pm; } +/* +=for apidoc Am|OP *|newSVOP|I32 type|I32 flags|SV *sv + +Constructs, checks, and returns an op of any type that involves an +embedded SV. I is the opcode. I gives the eight bits +of C. I gives the SV to embed in the op; this function +takes ownership of one reference to it. + +=cut +*/ + OP * Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) { @@ -3713,6 +3895,10 @@ Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) PERL_ARGS_ASSERT_NEWSVOP; + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_SVOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_PVOP_OR_SVOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_FILESTATOP); + NewOp(1101, svop, 1, SVOP); svop->op_type = (OPCODE)type; svop->op_ppaddr = PL_ppaddr[type]; @@ -3727,6 +3913,21 @@ Perl_newSVOP(pTHX_ I32 type, I32 flags, SV *sv) } #ifdef USE_ITHREADS + +/* +=for apidoc Am|OP *|newPADOP|I32 type|I32 flags|SV *sv + +Constructs, checks, and returns an op of any type that involves a +reference to a pad element. I is the opcode. I gives the +eight bits of C. A pad slot is automatically allocated, and +is populated with I; this function takes ownership of one reference +to it. + +This function only exists if Perl has been compiled to use ithreads. + +=cut +*/ + OP * Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) { @@ -3735,6 +3936,10 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) PERL_ARGS_ASSERT_NEWPADOP; + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_SVOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_PVOP_OR_SVOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_FILESTATOP); + NewOp(1101, padop, 1, PADOP); padop->op_type = (OPCODE)type; padop->op_ppaddr = PL_ppaddr[type]; @@ -3751,7 +3956,20 @@ Perl_newPADOP(pTHX_ I32 type, I32 flags, SV *sv) padop->op_targ = pad_alloc(type, SVs_PADTMP); return CHECKOP(type, padop); } -#endif + +#endif /* !USE_ITHREADS */ + +/* +=for apidoc Am|OP *|newGVOP|I32 type|I32 flags|GV *gv + +Constructs, checks, and returns an op of any type that involves an +embedded reference to a GV. I is the opcode. I gives the +eight bits of C. I identifies the GV that the op should +reference; calling this function does not transfer ownership of any +reference to it. + +=cut +*/ OP * Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) @@ -3768,11 +3986,27 @@ Perl_newGVOP(pTHX_ I32 type, I32 flags, GV *gv) #endif } +/* +=for apidoc Am|OP *|newPVOP|I32 type|I32 flags|char *pv + +Constructs, checks, and returns an op of any type that involves an +embedded C-level pointer (PV). I is the opcode. I gives +the eight bits of C. I supplies the C-level pointer, which +must have been allocated using L; the memory will +be freed when the op is destroyed. + +=cut +*/ + OP * Perl_newPVOP(pTHX_ I32 type, I32 flags, char *pv) { dVAR; PVOP *pvop; + + assert((PL_opargs[type] & OA_CLASS_MASK) == OA_PVOP_OR_SVOP + || (PL_opargs[type] & OA_CLASS_MASK) == OA_LOOPEXOP); + NewOp(1101, pvop, 1, PVOP); pvop->op_type = (OPCODE)type; pvop->op_ppaddr = PL_ppaddr[type]; @@ -3826,6 +4060,18 @@ Perl_package(pTHX_ OP *o) #endif } +void +Perl_package_version( pTHX_ OP *v ) +{ + dVAR; + U32 savehints = PL_hints; + PERL_ARGS_ASSERT_PACKAGE_VERSION; + PL_hints &= ~HINT_STRICT_VARS; + sv_setsv( GvSV(gv_fetchpvs("VERSION", GV_ADDMULTI, SVt_PV)), cSVOPx(v)->op_sv ); + PL_hints = savehints; + op_free(v); +} + #ifdef PERL_MAD OP* #else @@ -4069,6 +4315,22 @@ Perl_dofile(pTHX_ OP *term, I32 force_builtin) return doop; } +/* +=head1 Optree construction + +=for apidoc Am|OP *|newSLICEOP|I32 flags|OP *subscript|OP *listval + +Constructs, checks, and returns an C (list slice) op. I +gives the eight bits of C, except that C will +be set automatically, and, shifted up eight bits, the eight bits of +C, except that the bit with value 1 or 2 is automatically +set as required. I and I supply the parameters of +the slice; they are consumed by this function and become part of the +constructed op tree. + +=cut +*/ + OP * Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) { @@ -4121,6 +4383,29 @@ S_is_list_assignment(pTHX_ register const OP *o) return FALSE; } +/* +=for apidoc Am|OP *|newASSIGNOP|I32 flags|OP *left|I32 optype|OP *right + +Constructs, checks, and returns an assignment op. I and I +supply the parameters of the assignment; they are consumed by this +function and become part of the constructed op tree. + +If I is C, C, or C, then +a suitable conditional optree is constructed. If I is the opcode +of a binary operator, such as C, then an op is constructed that +performs the binary operation and assigns the result to the left argument. +Either way, if I is non-zero then I has no effect. + +If I is zero, then a plain scalar or list assignment is +constructed. Which type of assignment it is is automatically determined. +I gives the eight bits of C, except that C +will be set automatically, and, shifted up eight bits, the eight bits +of C, except that the bit with value 1 or 2 is automatically +set as required. + +=cut +*/ + OP * Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) { @@ -4153,6 +4438,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) if (PL_eval_start) PL_eval_start = 0; else if (left->op_type == OP_CONST) { + deprecate("assignment to $["); /* FIXME for MAD */ /* Result of assignment is always 1 (or we'd be dead already) */ return newSVOP(OP_CONST, 0, newSViv(1)); @@ -4204,7 +4490,7 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) || left->op_type == OP_PADHV || left->op_type == OP_PADANY)) { - maybe_common_vars = FALSE; + if (left->op_type == OP_PADSV) maybe_common_vars = FALSE; if (left->op_private & OPpPAD_STATE) { /* All single variable list context state assignments, hence state ($a) = ... @@ -4368,6 +4654,24 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) return o; } +/* +=for apidoc Am|OP *|newSTATEOP|I32 flags|char *label|OP *o + +Constructs a state op (COP). The state op is normally a C op, +but will be a C op if debugging is enabled for currently-compiled +code. The state op is populated from L (or L). +If I