X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=f5e24fcdea3c5688410647ef03cd19fdf2965e8a;hb=51254d33a14eeacb273f244a97f13b86d9e56aa2;hp=130daf9809be3798ffbbff97868486e19e75327c;hpb=fc15ae8fb67c31ee845fb33ce00b1c24c4c1a908;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index 130daf9..f5e24fc 100644 --- a/op.c +++ b/op.c @@ -224,13 +224,13 @@ S_no_bareword_allowed(pTHX_ const OP *o) return; /* various ok barewords are hidden in extra OP_NULL */ qerror(Perl_mess(aTHX_ "Bareword \"%"SVf"\" not allowed while \"strict subs\" in use", - cSVOPo_sv)); + (void*)cSVOPo_sv)); } /* "register" allocation */ PADOFFSET -Perl_allocmy(pTHX_ char *name) +Perl_allocmy(pTHX_ const char *const name) { dVAR; PADOFFSET off; @@ -245,25 +245,11 @@ Perl_allocmy(pTHX_ char *name) { /* 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; - p = strchr(name, '\0'); - /* The next block assumes the buffer is at least 205 chars - long. At present, it's always at least 256 chars. */ - if (p-name > 200) { - strcpy(name+200, "..."); - p = name+199; - } - else { - p[1] = '\0'; - } - /* Move everything else down one character */ - for (; p-name > 2; p--) - *p = *(p-1); - name[2] = toCTRL(name[1]); - name[1] = '^'; + yyerror(Perl_form(aTHX_ "Can't use global %c^%c%s in \"my\"", + name[0], toCTRL(name[1]), name + 2)); + } else { + yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name)); } - yyerror(Perl_form(aTHX_ "Can't use global %s in \"my\"",name)); } /* check for duplicate declaration */ @@ -272,7 +258,8 @@ Perl_allocmy(pTHX_ char *name) if (PL_in_my_stash && *name != '$') { yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"", - name, is_our ? "our" : "my")); + name, + is_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); } /* allocate a spare slot and store the name in that slot */ @@ -284,7 +271,8 @@ Perl_allocmy(pTHX_ char *name) ? (PL_curstash && !strEQ(name,"$_") ? PL_curstash : PL_defstash) : NULL ), - 0 /* not fake */ + 0, /* not fake */ + PL_in_my == KEY_state ); return off; } @@ -506,10 +494,10 @@ S_cop_free(pTHX_ COP* cop) CopFILE_free(cop); CopSTASH_free(cop); if (! specialWARN(cop->cop_warnings)) - SvREFCNT_dec(cop->cop_warnings); + PerlMemShared_free(cop->cop_warnings); if (! specialCopIO(cop->cop_io)) { #ifdef USE_ITHREADS - /*EMPTY*/ + NOOP; #else SvREFCNT_dec(cop->cop_io); #endif @@ -1032,10 +1020,10 @@ Perl_scalarseq(pTHX_ OP *o) { dVAR; if (o) { - if (o->op_type == OP_LINESEQ || - o->op_type == OP_SCOPE || - o->op_type == OP_LEAVE || - o->op_type == OP_LEAVETRY) + const OPCODE type = o->op_type; + + if (type == OP_LINESEQ || type == OP_SCOPE || + type == OP_LEAVE || type == OP_LEAVETRY) { OP *kid; for (kid = cLISTOPo->op_first; kid; kid = kid->op_sibling) { @@ -1148,15 +1136,14 @@ Perl_mod(pTHX_ OP *o, I32 type) CV *cv; OP *okid; - if (kid->op_type == OP_PUSHMARK) - goto skip_kids; - if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST) - Perl_croak(aTHX_ - "panic: unexpected lvalue entersub " - "args: type/targ %ld:%"UVuf, - (long)kid->op_type, (UV)kid->op_targ); - kid = kLISTOP->op_first; - skip_kids: + if (kid->op_type != OP_PUSHMARK) { + if (kid->op_type != OP_NULL || kid->op_targ != OP_LIST) + Perl_croak(aTHX_ + "panic: unexpected lvalue entersub " + "args: type/targ %ld:%"UVuf, + (long)kid->op_type, (UV)kid->op_targ); + kid = kLISTOP->op_first; + } while (kid->op_sibling) kid = kid->op_sibling; if (!(kid->op_type == OP_NULL && kid->op_targ == OP_RV2CV)) { @@ -1649,7 +1636,7 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my) /* Don't force the C if we don't need it. */ SV * const * const svp = hv_fetchs(GvHVn(PL_incgv), ATTRSMODULE_PM, FALSE); if (svp && *svp != &PL_sv_undef) - /*EMPTY*/; /* already in %INC */ + NOOP; /* already in %INC */ else Perl_load_module(aTHX_ PERL_LOADMOD_NOIMPORT, newSVpvs(ATTRSMODULE), NULL); @@ -1790,7 +1777,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) type == OP_RV2HV) { /* XXX does this let anything illegal in? */ if (cUNOPo->op_first->op_type != OP_GV) { /* MJD 20011224 */ yyerror(Perl_form(aTHX_ "Can't declare %s in %s", - OP_DESC(o), PL_in_my == KEY_our ? "our" : "my")); + OP_DESC(o), + PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); } else if (attrs) { GV * const gv = cGVOPx_gv(cUNOPo->op_first); PL_in_my = FALSE; @@ -1811,7 +1799,7 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) { yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"", OP_DESC(o), - PL_in_my == KEY_our ? "our" : "my")); + PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my")); return o; } else if (attrs && type != OP_PUSHMARK) { @@ -1828,6 +1816,8 @@ S_my_kid(pTHX_ OP *o, OP *attrs, OP **imopsp) } o->op_flags |= OPf_MOD; o->op_private |= OPpLVAL_INTRO; + if (PL_in_my == KEY_state) + o->op_private |= OPpPAD_STATE; return o; } @@ -1885,48 +1875,50 @@ Perl_bind_match(pTHX_ I32 type, OP *left, OP *right) { OP *o; bool ismatchop = 0; + const OPCODE ltype = left->op_type; + const OPCODE rtype = right->op_type; - if ( (left->op_type == OP_RV2AV || - left->op_type == OP_RV2HV || - left->op_type == OP_PADAV || - left->op_type == OP_PADHV) - && ckWARN(WARN_MISC)) + if ( (ltype == OP_RV2AV || ltype == OP_RV2HV || ltype == OP_PADAV + || ltype == OP_PADHV) && ckWARN(WARN_MISC)) { - const char * const desc = PL_op_desc[(right->op_type == OP_SUBST || - right->op_type == OP_TRANS) - ? right->op_type : OP_MATCH]; - const char * const sample = ((left->op_type == OP_RV2AV || - left->op_type == OP_PADAV) - ? "@array" : "%hash"); + const char * const desc + = PL_op_desc[(rtype == OP_SUBST || rtype == OP_TRANS) + ? rtype : OP_MATCH]; + const char * const sample = ((ltype == OP_RV2AV || ltype == OP_PADAV) + ? "@array" : "%hash"); Perl_warner(aTHX_ packWARN(WARN_MISC), "Applying %s to %s will act on scalar(%s)", desc, sample, sample); } - if (right->op_type == OP_CONST && + if (rtype == OP_CONST && cSVOPx(right)->op_private & OPpCONST_BARE && cSVOPx(right)->op_private & OPpCONST_STRICT) { no_bareword_allowed(right); } - ismatchop = right->op_type == OP_MATCH || - right->op_type == OP_SUBST || - right->op_type == OP_TRANS; + ismatchop = rtype == OP_MATCH || + rtype == OP_SUBST || + rtype == OP_TRANS; if (ismatchop && right->op_private & OPpTARGET_MY) { right->op_targ = 0; right->op_private &= ~OPpTARGET_MY; } if (!(right->op_flags & OPf_STACKED) && ismatchop) { + OP *newleft; + right->op_flags |= OPf_STACKED; - if (right->op_type != OP_MATCH && - ! (right->op_type == OP_TRANS && + if (rtype != OP_MATCH && + ! (rtype == OP_TRANS && right->op_private & OPpTRANS_IDENTICAL)) - left = mod(left, right->op_type); + newleft = mod(left, rtype); + else + newleft = left; if (right->op_type == OP_TRANS) - o = newBINOP(OP_NULL, OPf_STACKED, scalar(left), right); + o = newBINOP(OP_NULL, OPf_STACKED, scalar(newleft), right); else - o = prepend_elem(right->op_type, scalar(left), right); + o = prepend_elem(rtype, scalar(newleft), right); if (type == OP_NOT) return newUNOP(OP_NOT, 0, scalar(o)); return o; @@ -1974,7 +1966,7 @@ Perl_scope(pTHX_ OP *o) } return o; } - + int Perl_block_start(pTHX_ int full) { @@ -1983,11 +1975,8 @@ Perl_block_start(pTHX_ int full) pad_block_start(full); SAVEHINTS(); PL_hints &= ~HINT_BLOCK_SCOPE; - SAVESPTR(PL_compiling.cop_warnings); - if (! specialWARN(PL_compiling.cop_warnings)) { - PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ; - SAVEFREESV(PL_compiling.cop_warnings) ; - } + SAVECOMPILEWARNINGS(); + PL_compiling.cop_warnings = DUP_WARNINGS(PL_compiling.cop_warnings); SAVESPTR(PL_compiling.cop_io); if (! specialCopIO(PL_compiling.cop_io)) { PL_compiling.cop_io = newSVsv(PL_compiling.cop_io) ; @@ -2003,7 +1992,7 @@ Perl_block_end(pTHX_ I32 floor, OP *seq) const int needblockscope = PL_hints & HINT_BLOCK_SCOPE; OP* const retval = scalarseq(seq); LEAVE_SCOPE(floor); - PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(&PL_compiling, PL_hints); if (needblockscope) PL_hints |= HINT_BLOCK_SCOPE; /* propagate out */ pad_leavemy(); @@ -2014,7 +2003,7 @@ STATIC OP * S_newDEFSVOP(pTHX) { dVAR; - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { return newSVREF(newGVOP(OP_GV, 0, PL_defgv)); } @@ -2081,7 +2070,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) #if 0 list(o); #else - /*EMPTY*/; + NOOP; #endif else { if ( PL_bufptr > PL_oldbufptr && PL_bufptr[-1] == ',' @@ -2110,7 +2099,7 @@ Perl_localize(pTHX_ OP *o, I32 lex) if (sigil && (*s == ';' || *s == '=')) { Perl_warner(aTHX_ packWARN(WARN_PARENTHESIS), "Parentheses missing around \"%s\" list", - lex ? (PL_in_my == KEY_our ? "our" : "my") + lex ? (PL_in_my == KEY_our ? "our" : PL_in_my == KEY_state ? "state" : "my") : "local"); } } @@ -2142,10 +2131,12 @@ Perl_fold_constants(pTHX_ register OP *o) register OP *curop; OP *newop; I32 type = o->op_type; - SV *sv; + SV *sv = NULL; int ret = 0; I32 oldscope; OP *old_next; + SV * const oldwarnhook = PL_warnhook; + SV * const olddiehook = PL_diehook; dJMPENV; if (PL_opargs[type] & OA_RETSCALAR) @@ -2188,12 +2179,12 @@ Perl_fold_constants(pTHX_ register OP *o) goto nope; /* Don't try to run w/ errors */ for (curop = LINKLIST(o); curop != o; curop = LINKLIST(curop)) { - if ((curop->op_type != OP_CONST || - (curop->op_private & OPpCONST_BARE)) && - curop->op_type != OP_LIST && - curop->op_type != OP_SCALAR && - curop->op_type != OP_NULL && - curop->op_type != OP_PUSHMARK) + const OPCODE type = curop->op_type; + if ((type != OP_CONST || (curop->op_private & OPpCONST_BARE)) && + type != OP_LIST && + type != OP_SCALAR && + type != OP_NULL && + type != OP_PUSHMARK) { goto nope; } @@ -2207,6 +2198,8 @@ Perl_fold_constants(pTHX_ register OP *o) oldscope = PL_scopestack_ix; create_eval_scope(G_FAKINGEVAL); + PL_warnhook = PERL_WARNHOOK_FATAL; + PL_diehook = NULL; JMPENV_PUSH(ret); switch (ret) { @@ -2229,10 +2222,15 @@ Perl_fold_constants(pTHX_ register OP *o) default: JMPENV_POP; /* Don't expect 1 (setjmp failed) or 2 (something called my_exit) */ + PL_warnhook = oldwarnhook; + PL_diehook = olddiehook; + /* XXX note that this croak may fail as we've already blown away + * the stack - eg any nested evals */ Perl_croak(aTHX_ "panic: fold_constants JMPENV_PUSH returned %d", ret); } - JMPENV_POP; + PL_warnhook = oldwarnhook; + PL_diehook = olddiehook; if (PL_scopestack_ix > oldscope) delete_eval_scope(); @@ -2243,6 +2241,7 @@ Perl_fold_constants(pTHX_ register OP *o) #ifndef PERL_MAD op_free(o); #endif + assert(sv); if (type == OP_RV2GV) newop = newGVOP(OP_GV, 0, (GV*)sv); else @@ -2842,6 +2841,7 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) const I32 to_utf = o->op_private & OPpTRANS_TO_UTF; U8* tsave = NULL; U8* rsave = NULL; + const U32 flags = UTF8_ALLOW_DEFAULT; if (!from_utf) { STRLEN len = tlen; @@ -2868,11 +2868,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) i = 0; transv = newSVpvs(""); while (t < tend) { - cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, 0); + cp[2*i] = utf8n_to_uvuni(t, tend-t, &ulen, flags); t += ulen; if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { t++; - cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, 0); + cp[2*i+1] = utf8n_to_uvuni(t, tend-t, &ulen, flags); t += ulen; } else { @@ -2926,11 +2926,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) while (t < tend || tfirst <= tlast) { /* see if we need more "t" chars */ if (tfirst > tlast) { - tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0); + tfirst = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); t += ulen; if (t < tend && NATIVE_TO_UTF(*t) == 0xff) { /* illegal utf8 val indicates range */ t++; - tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, 0); + tlast = (I32)utf8n_to_uvuni(t, tend - t, &ulen, flags); t += ulen; } else @@ -2940,11 +2940,11 @@ Perl_pmtrans(pTHX_ OP *o, OP *expr, OP *repl) /* now see if we need more "r" chars */ if (rfirst > rlast) { if (r < rend) { - rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0); + rfirst = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); r += ulen; if (r < rend && NATIVE_TO_UTF(*r) == 0xff) { /* illegal utf8 val indicates range */ r++; - rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, 0); + rlast = (I32)utf8n_to_uvuni(r, rend - r, &ulen, flags); r += ulen; } else @@ -3314,7 +3314,7 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, bool isreg) repl_has_vars = 1; } else if (curop->op_type == OP_PUSHRE) - /*EMPTY*/; /* Okay here, dangerous in newASSIGNOP */ + NOOP; /* Okay here, dangerous in newASSIGNOP */ else break; } @@ -3703,13 +3703,18 @@ Perl_newSLICEOP(pTHX_ I32 flags, OP *subscript, OP *listval) STATIC I32 S_is_list_assignment(pTHX_ register const OP *o) { + unsigned type; + U8 flags; + if (!o) return TRUE; - if (o->op_type == OP_NULL && o->op_flags & OPf_KIDS) + if ((o->op_type == OP_NULL) && (o->op_flags & OPf_KIDS)) o = cUNOPo->op_first; - if (o->op_type == OP_COND_EXPR) { + flags = o->op_flags; + type = o->op_type; + if (type == OP_COND_EXPR) { const I32 t = is_list_assignment(cLOGOPo->op_first->op_sibling); const I32 f = is_list_assignment(cLOGOPo->op_first->op_sibling->op_sibling); @@ -3720,20 +3725,20 @@ S_is_list_assignment(pTHX_ register const OP *o) return FALSE; } - if (o->op_type == OP_LIST && - (o->op_flags & OPf_WANT) == OPf_WANT_SCALAR && + if (type == OP_LIST && + (flags & OPf_WANT) == OPf_WANT_SCALAR && o->op_private & OPpLVAL_INTRO) return FALSE; - if (o->op_type == OP_LIST || o->op_flags & OPf_PARENS || - o->op_type == OP_RV2AV || o->op_type == OP_RV2HV || - o->op_type == OP_ASLICE || o->op_type == OP_HSLICE) + if (type == OP_LIST || flags & OPf_PARENS || + type == OP_RV2AV || type == OP_RV2HV || + type == OP_ASLICE || type == OP_HSLICE) return TRUE; - if (o->op_type == OP_PADAV || o->op_type == OP_PADHV) + if (type == OP_PADAV || type == OP_PADHV) return TRUE; - if (o->op_type == OP_RV2SV) + if (type == OP_RV2SV) return FALSE; return FALSE; @@ -3846,10 +3851,8 @@ Perl_newASSIGNOP(pTHX_ I32 flags, OP *left, I32 optype, OP *right) o->op_private |= OPpASSIGN_COMMON; } if (right && right->op_type == OP_SPLIT) { - OP* tmpop; - if ((tmpop = ((LISTOP*)right)->op_first) && - tmpop->op_type == OP_PUSHRE) - { + OP* tmpop = ((LISTOP*)right)->op_first; + if (tmpop && (tmpop->op_type == OP_PUSHRE)) { PMOP * const pm = (PMOP*)tmpop; if (left->op_type == OP_RV2AV && !(left->op_private & OPpLVAL_INTRO) && @@ -3931,11 +3934,11 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ]; } cop->op_flags = (U8)flags; - cop->op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(cop, PL_hints); #ifdef NATIVE_HINTS cop->op_private |= NATIVE_HINTS; #endif - PL_compiling.op_private = cop->op_private; + CopHINTS_set(&PL_compiling, CopHINTS_get(cop)); cop->op_next = (OP*)cop; if (label) { @@ -3944,17 +3947,16 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) } cop->cop_seq = seq; CopARYBASE_set(cop, CopARYBASE_get(PL_curcop)); - if (specialWARN(PL_curcop->cop_warnings)) - cop->cop_warnings = PL_curcop->cop_warnings ; - else - cop->cop_warnings = newSVsv(PL_curcop->cop_warnings) ; + cop->cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings); if (specialCopIO(PL_curcop->cop_io)) cop->cop_io = PL_curcop->cop_io; else cop->cop_io = newSVsv(PL_curcop->cop_io) ; cop->cop_hints = PL_curcop->cop_hints; if (cop->cop_hints) { + HINTS_REFCNT_LOCK; cop->cop_hints->refcounted_he_refcnt++; + HINTS_REFCNT_UNLOCK; } if (PL_copline == NOLINE) @@ -4381,7 +4383,9 @@ whileline, OP *expr, OP *block, OP *cont, I32 has_my) cont = append_elem(OP_LINESEQ, cont, unstack); } + assert(block); listop = append_list(OP_LINESEQ, (LISTOP*)block, (LISTOP*)cont); + assert(listop); redo = LINKLIST(listop); if (expr) { @@ -4471,7 +4475,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP iterpflags |= OPpITER_DEF; } else { - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset == NOT_IN_PAD || PAD_COMPNAME_FLAGS_isOUR(offset)) { sv = newGVOP(OP_GV, 0, PL_defgv); } @@ -4535,7 +4539,7 @@ Perl_newFOROP(pTHX_ I32 flags, char *label, line_t forline, OP *sv, OP *expr, OP loop = tmp; } #else - Renew(loop, 1, LOOP); + loop = PerlMemShared_realloc(loop, sizeof(LOOP)); #endif loop->op_targ = padoff; wop = newWHILEOP(flags, 1, loop, forline, newOP(OP_ITER, 0), block, cont, 0); @@ -4809,9 +4813,15 @@ Perl_cv_undef(pTHX_ CV *cv) } void -Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) -{ - if (((!p != !SvPOK(cv)) || (p && strNE(p, SvPVX_const(cv)))) && ckWARN_d(WARN_PROTOTYPE)) { +Perl_cv_ckproto_len(pTHX_ const CV *cv, const GV *gv, const char *p, + const STRLEN len) +{ + /* Can't just use a strcmp on the prototype, as CONSTSUBs "cheat" by + relying on SvCUR, and doubling up the buffer to hold CvFILE(). */ + if (((!p != !SvPOK(cv)) /* One has prototype, one has not. */ + || (p && (len != SvCUR(cv) /* Not the same length. */ + || memNE(p, SvPVX_const(cv), len)))) + && ckWARN_d(WARN_PROTOTYPE)) { SV* const msg = sv_newmortal(); SV* name = NULL; @@ -4819,17 +4829,17 @@ Perl_cv_ckproto(pTHX_ const CV *cv, const GV *gv, const char *p) gv_efullname3(name = sv_newmortal(), gv, NULL); sv_setpv(msg, "Prototype mismatch:"); if (name) - Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, name); + Perl_sv_catpvf(aTHX_ msg, " sub %"SVf, (void*)name); if (SvPOK(cv)) - Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (const SV *)cv); + Perl_sv_catpvf(aTHX_ msg, " (%"SVf")", (void*)cv); else sv_catpvs(msg, ": none"); sv_catpvs(msg, " vs "); if (p) - Perl_sv_catpvf(aTHX_ msg, "(%s)", p); + Perl_sv_catpvf(aTHX_ msg, "(%.*s)", (int) len, p); else sv_catpvs(msg, "none"); - Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, msg); + Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf, (void*)msg); } } @@ -5031,7 +5041,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "Runaway prototype"); } - cv_ckproto((CV*)gv, NULL, ps); + cv_ckproto_len((CV*)gv, NULL, ps, ps_len); } if (ps) sv_setpvn((SV*)gv, ps, ps_len); @@ -5075,7 +5085,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) * skipping the prototype check */ if (exists || SvPOK(cv)) - cv_ckproto(cv, gv, ps); + cv_ckproto_len(cv, gv, ps, ps_len); /* already defined (or promised)? */ if (exists || GvASSUMECV(gv)) { if ((!block @@ -5120,7 +5130,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } } if (const_sv) { - SvREFCNT_inc_void_NN(const_sv); + SvREFCNT_inc_simple_void_NN(const_sv); if (cv) { assert(!CvROOT(cv) && !CvCONST(cv)); sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ @@ -5240,7 +5250,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else { /* force display of errors found but not reported */ sv_catpv(ERRSV, not_safe); - Perl_croak(aTHX_ "%"SVf, ERRSV); + Perl_croak(aTHX_ "%"SVf, (void*)ERRSV); } } } @@ -5256,7 +5266,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) else { /* This makes sub {}; work as expected. */ if (block->op_type == OP_STUB) { - OP* newblock = newSTATEOP(0, NULL, 0); + OP* const newblock = newSTATEOP(0, NULL, 0); #ifdef PERL_MAD op_getmad(block,newblock,'B'); #else @@ -5333,7 +5343,7 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) call_list(oldscope, PL_beginav); PL_curcop = &PL_compiling; - PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(&PL_compiling, PL_hints); LEAVE; } else if (strEQ(s, "END") && !PL_error_count) { @@ -5386,6 +5396,15 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) { dVAR; CV* cv; +#ifdef USE_ITHREADS + const char *const temp_p = CopFILE(PL_curcop); + const STRLEN len = temp_p ? strlen(temp_p) : 0; +#else + SV *const temp_sv = CopFILESV(PL_curcop); + STRLEN len; + const char *const temp_p = temp_sv ? SvPV_const(temp_sv, len) : NULL; +#endif + char *const file = savepvn(temp_p, temp_p ? len : 0); ENTER; @@ -5402,10 +5421,13 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) CopSTASH_set(PL_curcop,stash); } - cv = newXS(name, const_sv_xsub, savepv(CopFILE(PL_curcop))); + /* file becomes the CvFILE. For an XS, it's supposed to be static storage, + and so doesn't get free()d. (It's expected to be from the C pre- + processor __FILE__ directive). But we need a dynamically allocated one, + and we need it to get freed. */ + cv = newXS_flags(name, const_sv_xsub, file, "", XS_DYNAMIC_FILENAME); CvXSUBANY(cv).any_ptr = sv; CvCONST_on(cv); - sv_setpvn((SV*)cv, "", 0); /* prototype is "" */ #ifdef USE_ITHREADS if (stash) @@ -5416,10 +5438,56 @@ Perl_newCONSTSUB(pTHX_ HV *stash, const char *name, SV *sv) return cv; } +CV * +Perl_newXS_flags(pTHX_ const char *name, XSUBADDR_t subaddr, + const char *const filename, const char *const proto, + U32 flags) +{ + CV *cv = newXS(name, subaddr, filename); + + if (flags & XS_DYNAMIC_FILENAME) { + /* We need to "make arrangements" (ie cheat) to ensure that the + filename lasts as long as the PVCV we just created, but also doesn't + leak */ + STRLEN filename_len = strlen(filename); + STRLEN proto_and_file_len = filename_len; + char *proto_and_file; + STRLEN proto_len; + + if (proto) { + proto_len = strlen(proto); + proto_and_file_len += proto_len; + + Newx(proto_and_file, proto_and_file_len + 1, char); + Copy(proto, proto_and_file, proto_len, char); + Copy(filename, proto_and_file + proto_len, filename_len + 1, char); + } else { + proto_len = 0; + proto_and_file = savepvn(filename, filename_len); + } + + /* This gets free()d. :-) */ + sv_usepvn_flags((SV*)cv, proto_and_file, proto_and_file_len, + SV_HAS_TRAILING_NUL); + if (proto) { + /* This gives us the correct prototype, rather than one with the + file name appended. */ + SvCUR_set(cv, proto_len); + } else { + SvPOK_off(cv); + } + CvFILE(cv) = proto_and_file + proto_len; + } else { + sv_setpv((SV *)cv, proto); + } + return cv; +} + /* =for apidoc U||newXS -Used by C to hook up XSUBs as Perl subs. +Used by C to hook up XSUBs as Perl subs. I needs to be +static storage, as it is used directly as CvFILE(), without a copy being made. =cut */ @@ -5565,7 +5633,7 @@ Perl_newFORM(pTHX_ I32 floor, OP *o, OP *block) CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ packWARN(WARN_REDEFINE), o ? "Format %"SVf" redefined" - : "Format STDOUT redefined" ,cSVOPo->op_sv); + : "Format STDOUT redefined", (void*)cSVOPo->op_sv); CopLINE_set(PL_curcop, oldline); } SvREFCNT_dec(cv); @@ -5806,13 +5874,12 @@ Perl_ck_spair(pTHX_ OP *o) o = modkids(ck_fun(o), type); kid = cUNOPo->op_first; newop = kUNOP->op_first->op_sibling; - if (newop && - (newop->op_sibling || - !(PL_opargs[newop->op_type] & OA_RETSCALAR) || - newop->op_type == OP_PADAV || newop->op_type == OP_PADHV || - newop->op_type == OP_RV2AV || newop->op_type == OP_RV2HV)) { - - return o; + if (newop) { + const OPCODE type = newop->op_type; + if (newop->op_sibling || !(PL_opargs[type] & OA_RETSCALAR) || + type == OP_PADAV || type == OP_PADHV || + type == OP_RV2AV || type == OP_RV2HV) + return o; } #ifdef PERL_MAD op_getmad(kUNOP->op_first,newop,'K'); @@ -6072,8 +6139,8 @@ Perl_ck_rvconst(pTHX_ register OP *o) } if (badthing) Perl_croak(aTHX_ - "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use", - kidsv, badthing); + "Can't use bareword (\"%"SVf"\") as %s ref while \"strict refs\" in use", + (void*)kidsv, badthing); } /* * This is a little tricky. We only want to add the symbol if we @@ -6123,12 +6190,13 @@ Perl_ck_ftst(pTHX_ OP *o) const I32 type = o->op_type; if (o->op_flags & OPf_REF) { - /*EMPTY*/; + NOOP; } else if (o->op_flags & OPf_KIDS && cUNOPo->op_first->op_type != OP_STUB) { SVOP * const kid = (SVOP*)cUNOPo->op_first; + const OPCODE kidtype = kid->op_type; - if (kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) { + if (kidtype == OP_CONST && (kid->op_private & OPpCONST_BARE)) { OP * const newop = newGVOP(type, OPf_REF, gv_fetchsv(kid->op_sv, GV_ADD, SVt_PVIO)); #ifdef PERL_MAD @@ -6140,8 +6208,8 @@ Perl_ck_ftst(pTHX_ OP *o) } if ((PL_hints & HINT_FILETEST_ACCESS) && OP_IS_FILETEST_ACCESS(o)) o->op_private |= OPpFT_ACCESS; - if (PL_check[kid->op_type] == MEMBER_TO_FPTR(Perl_ck_ftst) - && kid->op_type != OP_STAT && kid->op_type != OP_LSTAT) + if (PL_check[kidtype] == MEMBER_TO_FPTR(Perl_ck_ftst) + && kidtype != OP_STAT && kidtype != OP_LSTAT) o->op_private |= OPpFT_STACKED; } else { @@ -6230,7 +6298,7 @@ Perl_ck_fun(pTHX_ OP *o) if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Array @%"SVf" missing the @ in argument %"IVdf" of %s()", - ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); + (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); #ifdef PERL_MAD op_getmad(kid,newop,'K'); #else @@ -6253,7 +6321,7 @@ Perl_ck_fun(pTHX_ OP *o) if (ckWARN2(WARN_DEPRECATED, WARN_SYNTAX)) Perl_warner(aTHX_ packWARN2(WARN_DEPRECATED, WARN_SYNTAX), "Hash %%%"SVf" missing the %% in argument %"IVdf" of %s()", - ((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); + (void*)((SVOP*)kid)->op_sv, (IV)numargs, PL_op_desc[type]); #ifdef PERL_MAD op_getmad(kid,newop,'K'); #else @@ -6334,6 +6402,7 @@ Perl_ck_fun(pTHX_ OP *o) else if (kid->op_type == OP_AELEM || kid->op_type == OP_HELEM) { + OP *firstop; OP *op = ((BINOP*)kid)->op_first; name = NULL; if (op) { @@ -6343,10 +6412,10 @@ Perl_ck_fun(pTHX_ OP *o) "[]" : "{}"; if (((op->op_type == OP_RV2AV) || (op->op_type == OP_RV2HV)) && - (op = ((UNOP*)op)->op_first) && - (op->op_type == OP_GV)) { + (firstop = ((UNOP*)op)->op_first) && + (firstop->op_type == OP_GV)) { /* packagevar $a[] or $h{} */ - GV * const gv = cGVOPx_gv(op); + GV * const gv = cGVOPx_gv(firstop); if (gv) tmpstr = Perl_newSVpvf(aTHX_ @@ -6500,7 +6569,7 @@ Perl_ck_grep(pTHX_ OP *o) LOGOP *gwop = NULL; OP *kid; const OPCODE type = o->op_type == OP_GREPSTART ? OP_GREPWHILE : OP_MAPWHILE; - I32 offset; + PADOFFSET offset; o->op_ppaddr = PL_ppaddr[OP_GREPSTART]; /* don't allocate gwop here, as we may leak it if PL_error_count > 0 */ @@ -6701,7 +6770,7 @@ Perl_ck_smartmatch(pTHX_ OP *o) OP * Perl_ck_sassign(pTHX_ OP *o) { - OP *kid = cLISTOPo->op_first; + OP * const kid = cLISTOPo->op_first; /* has a disposable target? */ if ((PL_opargs[kid->op_type] & OA_TARGLEX) && !(kid->op_flags & OPf_STACKED) @@ -6730,6 +6799,16 @@ Perl_ck_sassign(pTHX_ OP *o) return kid; } } + if (kid->op_sibling) { + OP *kkid = kid->op_sibling; + if (kkid->op_type == OP_PADSV + && (kkid->op_private & OPpLVAL_INTRO) + && SvPAD_STATE(*av_fetch(PL_comppad_name, kkid->op_targ, FALSE))) { + o->op_private |= OPpASSIGN_STATE; + /* hijacking PADSTALE for uninitialized state variables */ + SvPADSTALE_on(PAD_SVl(kkid->op_targ)); + } + } return o; } @@ -6738,7 +6817,7 @@ Perl_ck_match(pTHX_ OP *o) { dVAR; if (o->op_type != OP_QR && PL_compcv) { - const I32 offset = pad_findmy("$_"); + const PADOFFSET offset = pad_findmy("$_"); if (offset != NOT_IN_PAD && !(PAD_COMPNAME_FLAGS_isOUR(offset))) { o->op_targ = offset; o->op_private |= OPpTARGET_MY; @@ -6976,8 +7055,7 @@ Perl_ck_sort(pTHX_ OP *o) dVAR; OP *firstkid; - if (o->op_type == OP_SORT && (PL_hints & HINT_LOCALIZE_HH) != 0) - { + 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); @@ -7169,6 +7247,7 @@ Perl_ck_split(pTHX_ OP *o) if (!kid->op_sibling) append_elem(OP_SPLIT, o, newSVOP(OP_CONST, 0, newSViv(0))); + assert(kid->op_sibling); kid = kid->op_sibling; scalar(kid); @@ -7203,7 +7282,8 @@ Perl_ck_subr(pTHX_ OP *o) ? cUNOPo : ((UNOP*)cUNOPo->op_first))->op_first; OP *o2 = prev->op_sibling; OP *cvop; - char *proto = NULL; + const char *proto = NULL; + const char *proto_end = NULL; CV *cv = NULL; GV *namegv = NULL; int optional = 0; @@ -7226,8 +7306,10 @@ Perl_ck_subr(pTHX_ OP *o) tmpop->op_private |= OPpEARLY_CV; else { if (SvPOK(cv)) { + STRLEN len; namegv = CvANON(cv) ? gv : CvGV(cv); - proto = SvPV_nolen((SV*)cv); + proto = SvPV((SV*)cv, len); + proto_end = proto + len; } if (CvASSERTION(cv)) { if (PL_hints & HINT_ASSERTING) { @@ -7264,9 +7346,10 @@ Perl_ck_subr(pTHX_ OP *o) else o3 = o2; if (proto) { - switch (*proto) { - case '\0': + if (proto >= proto_end) return too_many_arguments(o, gv_ename(namegv)); + + switch (*proto) { case ';': optional = 1; proto++; @@ -7349,15 +7432,13 @@ 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; + const char *p = proto; + const char *const end = proto; contextclass = 0; - *p = '\0'; while (*--p != '['); - bad_type(arg, Perl_form(aTHX_ "one of %s", p), - gv_ename(namegv), o3); - *proto = s; + bad_type(arg, Perl_form(aTHX_ "one of %.*s", + (int)(end - p), p), + gv_ename(namegv), o3); } else goto oops; break; @@ -7423,7 +7504,7 @@ Perl_ck_subr(pTHX_ OP *o) default: oops: Perl_croak(aTHX_ "Malformed prototype for %s: %"SVf, - gv_ename(namegv), cv); + gv_ename(namegv), (void*)cv); } } else @@ -7432,8 +7513,8 @@ Perl_ck_subr(pTHX_ OP *o) prev = o2; o2 = o2->op_sibling; } /* while */ - if (proto && !optional && - (*proto && *proto != '@' && *proto != '%' && *proto != ';')) + if (proto && !optional && proto_end > proto && + (*proto != '@' && *proto != '%' && *proto != ';')) return too_few_arguments(o, gv_ename(namegv)); if(delete_op) { #ifdef PERL_MAD @@ -7459,7 +7540,7 @@ OP * Perl_ck_chdir(pTHX_ OP *o) { if (o->op_flags & OPf_KIDS) { - SVOP *kid = (SVOP*)cUNOPo->op_first; + SVOP * const kid = (SVOP*)cUNOPo->op_first; if (kid && kid->op_type == OP_CONST && (kid->op_private & OPpCONST_BARE)) @@ -7694,7 +7775,7 @@ Perl_peep(pTHX_ register OP *o) gv_efullname3(sv, gv, NULL); Perl_warner(aTHX_ packWARN(WARN_PROTOTYPE), "%"SVf"() called too early to check prototype", - sv); + (void*)sv); } } else if (o->op_next->op_type == OP_READLINE @@ -7757,18 +7838,17 @@ Perl_peep(pTHX_ register OP *o) if (o->op_next && o->op_next->op_type == OP_NEXTSTATE && ckWARN(WARN_SYNTAX)) { - if (o->op_next->op_sibling && - o->op_next->op_sibling->op_type != OP_EXIT && - o->op_next->op_sibling->op_type != OP_WARN && - o->op_next->op_sibling->op_type != OP_DIE) { - const line_t oldline = CopLINE(PL_curcop); - - CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "Statement unlikely to be reached"); - Perl_warner(aTHX_ packWARN(WARN_EXEC), - "\t(Maybe you meant system() when you said exec()?)\n"); - CopLINE_set(PL_curcop, oldline); + if (o->op_next->op_sibling) { + const OPCODE type = o->op_next->op_sibling->op_type; + if (type != OP_EXIT && type != OP_WARN && type != OP_DIE) { + const line_t oldline = CopLINE(PL_curcop); + CopLINE_set(PL_curcop, CopLINE((COP*)o->op_next)); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "Statement unlikely to be reached"); + Perl_warner(aTHX_ packWARN(WARN_EXEC), + "\t(Maybe you meant system() when you said exec()?)\n"); + CopLINE_set(PL_curcop, oldline); + } } } break; @@ -7791,7 +7871,7 @@ Perl_peep(pTHX_ register OP *o) if ((!SvFAKE(sv = *svp) || !SvREADONLY(sv)) && !IS_PADCONST(sv)) { key = SvPV_const(sv, keylen); lexname = newSVpvn_share(key, - SvUTF8(sv) ? -(I32)keylen : keylen, + SvUTF8(sv) ? -(I32)keylen : (I32)keylen, 0); SvREFCNT_dec(sv); *svp = lexname; @@ -7811,7 +7891,7 @@ Perl_peep(pTHX_ register OP *o) break; key = SvPV_const(*svp, keylen); if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE)) + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { Perl_croak(aTHX_ "No such class field \"%s\" " "in variable %s of type %s", @@ -7868,7 +7948,7 @@ Perl_peep(pTHX_ register OP *o) svp = cSVOPx_svp(key_op); key = SvPV_const(*svp, keylen); if (!hv_fetch(GvHV(*fields), key, - SvUTF8(*svp) ? -(I32)keylen : keylen, FALSE)) + SvUTF8(*svp) ? -(I32)keylen : (I32)keylen, FALSE)) { Perl_croak(aTHX_ "No such class field \"%s\" " "in variable %s of type %s", @@ -8197,7 +8277,7 @@ const_sv_xsub(pTHX_ CV* cv) dVAR; dXSARGS; if (items != 0) { - /*EMPTY*/; + NOOP; #if 0 Perl_croak(aTHX_ "usage: %s::%s()", HvNAME_get(GvSTASH(CvGV(cv))), GvNAME(CvGV(cv)));