X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=op.c;h=eb60ec1876fb93cce64ba1583f6cc58a442d1663;hb=c9fcc6c44229e7c36dee08e5d883d12284a44f17;hp=06b6a7066ac197b1a0755bc12a0c0f6fbf4fde81;hpb=872465582bf743a066e1240f2c3e941735674827;p=p5sagit%2Fp5-mst-13.2.git diff --git a/op.c b/op.c index 06b6a70..eb60ec1 100644 --- a/op.c +++ b/op.c @@ -1,6 +1,6 @@ /* op.c * - * Copyright (c) 1991-1999, Larry Wall + * Copyright (c) 1991-2000, Larry Wall * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -153,22 +153,39 @@ Perl_pad_allocmy(pTHX_ char *name) } if (ckWARN(WARN_UNSAFE) && AvFILLp(PL_comppad_name) >= 0) { SV **svp = AvARRAY(PL_comppad_name); - for (off = AvFILLp(PL_comppad_name); off > PL_comppad_name_floor; off--) { + HV *ourstash = (PL_curstash ? PL_curstash : PL_defstash); + PADOFFSET top = AvFILLp(PL_comppad_name); + for (off = top; off > PL_comppad_name_floor; off--) { if ((sv = svp[off]) && sv != &PL_sv_undef && (SvIVX(sv) == PAD_MAX || SvIVX(sv) == 0) + && (PL_in_my != KEY_our + || ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash)) && strEQ(name, SvPVX(sv))) { - if (PL_in_my != KEY_our - || GvSTASH(sv) == (PL_curstash ? PL_curstash : PL_defstash)) + Perl_warner(aTHX_ WARN_UNSAFE, + "\"%s\" variable %s masks earlier declaration in same %s", + (PL_in_my == KEY_our ? "our" : "my"), + name, + (SvIVX(sv) == PAD_MAX ? "scope" : "statement")); + --off; + break; + } + } + if (PL_in_my == KEY_our) { + while (off >= 0 && off <= top) { + if ((sv = svp[off]) + && sv != &PL_sv_undef + && ((SvFLAGS(sv) & SVpad_OUR) && GvSTASH(sv) == ourstash) + && strEQ(name, SvPVX(sv))) { Perl_warner(aTHX_ WARN_UNSAFE, - "\"%s\" variable %s masks earlier declaration in same %s", - (PL_in_my == KEY_our ? "our" : "my"), - name, - (SvIVX(sv) == PAD_MAX ? "scope" : "statement")); + "\"our\" variable %s redeclared", name); + Perl_warner(aTHX_ WARN_UNSAFE, + "(Did you mean \"local\" instead of \"our\"?)\n"); + break; } - break; + --off; } } } @@ -178,8 +195,8 @@ Perl_pad_allocmy(pTHX_ char *name) sv_setpv(sv, name); if (PL_in_my_stash) { if (*name != '$') - yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"my\"", - name)); + yyerror(Perl_form(aTHX_ "Can't declare class for non-scalar %s in \"%s\"", + name, PL_in_my == KEY_our ? "our" : "my")); SvOBJECT_on(sv); (void)SvUPGRADE(sv, SVt_PVMG); SvSTASH(sv) = (HV*)SvREFCNT_inc(PL_in_my_stash); @@ -1098,7 +1115,7 @@ Perl_scalarvoid(pTHX_ OP *o) case OP_GGRGID: case OP_GETLOGIN: func_ops: - if (!(o->op_private & OPpLVAL_INTRO)) + if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO))) useless = PL_op_desc[o->op_type]; break; @@ -1395,18 +1412,19 @@ Perl_mod(pTHX_ OP *o, I32 type) if (kid->op_type == OP_METHOD_NAMED || kid->op_type == OP_METHOD) { - OP *newop; + UNOP *newop; if (kid->op_sibling || kid->op_next != kid) { yyerror("panic: unexpected optree near method call"); break; } - NewOp(1101, newop, 1, OP); + NewOp(1101, newop, 1, UNOP); newop->op_type = OP_RV2CV; newop->op_ppaddr = PL_ppaddr[OP_RV2CV]; - newop->op_next = newop; - kid->op_sibling = newop; + newop->op_first = Nullop; + newop->op_next = (OP*)newop; + kid->op_sibling = (OP*)newop; newop->op_private |= OPpLVAL_INTRO; break; } @@ -1869,7 +1887,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs) type != OP_PADHV && type != OP_PUSHMARK) { - yyerror(Perl_form(aTHX_ "Can't declare %s in my", PL_op_desc[o->op_type])); + yyerror(Perl_form(aTHX_ "Can't declare %s in \"%s\"", + PL_op_desc[o->op_type], + PL_in_my == KEY_our ? "our" : "my")); return o; } else if (attrs && type != OP_PUSHMARK) { @@ -1877,6 +1897,9 @@ S_my_kid(pTHX_ OP *o, OP *attrs) SV *padsv; SV **namesvp; + PL_in_my = FALSE; + PL_in_my_stash = Nullhv; + /* check for C when deciding package */ namesvp = av_fetch(PL_comppad_name, o->op_targ, FALSE); if (namesvp && *namesvp && SvOBJECT(*namesvp) && HvNAME(SvSTASH(*namesvp))) @@ -1896,11 +1919,12 @@ Perl_my_attrs(pTHX_ OP *o, OP *attrs) { if (o->op_flags & OPf_PARENS) list(o); - PL_in_my = FALSE; - PL_in_my_stash = Nullhv; if (attrs) SAVEFREEOP(attrs); - return my_kid(o, attrs); + o = my_kid(o, attrs); + PL_in_my = FALSE; + PL_in_my_stash = Nullhv; + return o; } OP * @@ -2111,16 +2135,18 @@ Perl_localize(pTHX_ OP *o, I32 lex) char *s; for (s = PL_bufptr; *s && (isALNUM(*s) || (*s & 0x80) || strchr("@$%, ",*s)); s++) ; if (*s == ';' || *s == '=') - Perl_warner(aTHX_ WARN_PARENTHESIS, "Parentheses missing around \"%s\" list", - lex ? "my" : "local"); + Perl_warner(aTHX_ WARN_PARENTHESIS, + "Parentheses missing around \"%s\" list", + lex ? (PL_in_my == KEY_our ? "our" : "my") : "local"); } } - PL_in_my = FALSE; - PL_in_my_stash = Nullhv; if (lex) - return my(o); + o = my(o); else - return mod(o, OP_NULL); /* a bit kludgey */ + o = mod(o, OP_NULL); /* a bit kludgey */ + PL_in_my = FALSE; + PL_in_my_stash = Nullhv; + return o; } OP * @@ -2842,12 +2868,16 @@ Perl_pmruntime(pTHX_ OP *o, OP *expr, OP *repl) p = SvPV(pat, plen); pm->op_pmflags |= PMf_SKIPWHITE; } + if ((PL_hints & HINT_UTF8) || (SvUTF8(pat) && !(PL_hints & HINT_BYTE))) + pm->op_pmdynflags |= PMdf_UTF8; pm->op_pmregexp = CALLREGCOMP(aTHX_ p, p + plen, pm); if (strEQ("\\s+", pm->op_pmregexp->precomp)) pm->op_pmflags |= PMf_WHITE; op_free(expr); } else { + if (PL_hints & HINT_UTF8) + pm->op_pmdynflags |= PMdf_UTF8; if (pm->op_pmflags & PMf_KEEP || !(PL_hints & HINT_RE_EVAL)) expr = newUNOP((!(PL_hints & HINT_RE_EVAL) ? OP_REGCRESET @@ -3076,7 +3106,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg) veop = Nullop; - if(version != Nullop) { + if (version != Nullop) { SV *vesv = ((SVOP*)version)->op_sv; if (arg == Nullop && !SvNIOK(vesv)) { @@ -3084,6 +3114,7 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg) } else { OP *pack; + SV *meth; if (version->op_type != OP_CONST || !SvNIOK(vesv)) Perl_croak(aTHX_ "Version number must be constant number"); @@ -3092,29 +3123,38 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP *id, OP *arg) pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv)); /* Fake up a method call to VERSION */ + meth = newSVpvn("VERSION",7); + sv_upgrade(meth, SVt_PVIV); + SvIOK_on(meth); + PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); veop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, append_elem(OP_LIST, - prepend_elem(OP_LIST, pack, list(version)), - newSVOP(OP_METHOD_NAMED, 0, - newSVpvn("VERSION", 7)))); + prepend_elem(OP_LIST, pack, list(version)), + newSVOP(OP_METHOD_NAMED, 0, meth))); } } /* Fake up an import/unimport */ if (arg && arg->op_type == OP_STUB) imop = arg; /* no import on explicit () */ - else if(SvNIOK(((SVOP*)id)->op_sv)) { + else if (SvNIOK(((SVOP*)id)->op_sv)) { imop = Nullop; /* use 5.0; */ } else { + SV *meth; + /* Make copy of id so we don't free it twice */ pack = newSVOP(OP_CONST, 0, newSVsv(((SVOP*)id)->op_sv)); + + /* Fake up a method call to import/unimport */ + meth = aver ? newSVpvn("import",6) : newSVpvn("unimport", 8);; + sv_upgrade(meth, SVt_PVIV); + SvIOK_on(meth); + PERL_HASH(SvUVX(meth), SvPVX(meth), SvCUR(meth)); imop = convert(OP_ENTERSUB, OPf_STACKED|OPf_SPECIAL, - append_elem(OP_LIST, - prepend_elem(OP_LIST, pack, list(arg)), - newSVOP(OP_METHOD_NAMED, 0, - aver ? newSVpvn("import", 6) - : newSVpvn("unimport", 8)))); + append_elem(OP_LIST, + prepend_elem(OP_LIST, pack, list(arg)), + newSVOP(OP_METHOD_NAMED, 0, meth))); } /* Fake up a require, handle override, if any */ @@ -3374,7 +3414,7 @@ Perl_newSTATEOP(pTHX_ I32 flags, char *label, OP *o) cop->op_ppaddr = PL_ppaddr[ OP_NEXTSTATE ]; } cop->op_flags = flags; - cop->op_private = (PL_hints & HINT_UTF8); + cop->op_private = (PL_hints & HINT_BYTE); #ifdef NATIVE_HINTS cop->op_private |= NATIVE_HINTS; #endif @@ -3475,9 +3515,8 @@ S_new_logop(pTHX_ I32 type, I32 flags, OP** firstp, OP** otherp) } } if (first->op_type == OP_CONST) { - if (ckWARN(WARN_PRECEDENCE) && (first->op_private & OPpCONST_BARE)) - Perl_warner(aTHX_ WARN_PRECEDENCE, "Probable precedence problem on %s", - PL_op_desc[type]); + if (ckWARN(WARN_BAREWORD) && (first->op_private & OPpCONST_BARE)) + Perl_warner(aTHX_ WARN_BAREWORD, "Bareword found in conditional"); if ((type == OP_AND) == (SvTRUE(((SVOP*)first)->op_sv))) { op_free(first); *firstp = Nullop; @@ -4055,8 +4094,7 @@ S_cv_clone2(pTHX_ CV *proto, CV *outside) assert(!CvUNIQUE(proto)); ENTER; - SAVEVPTR(PL_curpad); - SAVESPTR(PL_comppad); + SAVECOMPPAD(); SAVESPTR(PL_comppad_name); SAVESPTR(PL_compcv); @@ -4219,10 +4257,10 @@ Perl_op_const_sv(pTHX_ OP *o, CV *cv) { SV *sv = Nullsv; - if(!o) + if (!o) return Nullsv; - if(o->op_type == OP_LINESEQ && cLISTOPo->op_first) + if (o->op_type == OP_LINESEQ && cLISTOPo->op_first) o = cLISTOPo->op_first->op_sibling; for (; o; o = o->op_next) { @@ -4277,14 +4315,26 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) { dTHR; STRLEN n_a; - char *name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch; - GV *gv = gv_fetchpv(name ? name : "__ANON__", - GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT), - SVt_PVCV); + char *name; + char *aname; + GV *gv; char *ps = proto ? SvPVx(((SVOP*)proto)->op_sv, n_a) : Nullch; register CV *cv=0; I32 ix; + name = o ? SvPVx(cSVOPo->op_sv, n_a) : Nullch; + if (!name && PERLDB_NAMEANON && CopLINE(PL_curcop)) { + SV *sv = sv_newmortal(); + Perl_sv_setpvf(aTHX_ sv, "__ANON__[%s:%"IVdf"]", + CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); + aname = SvPVX(sv); + } + else + aname = Nullch; + gv = gv_fetchpv(name ? name : (aname ? aname : "__ANON__"), + GV_ADDMULTI | ((block || attrs) ? 0 : GV_NOINIT), + SVt_PVCV); + if (o) SAVEFREEOP(o); if (proto) @@ -4330,13 +4380,14 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) Perl_croak(aTHX_ "Can't redefine active sort subroutine %s", name); if (!block) goto withattrs; - if(const_sv = cv_const_sv(cv)) + if (const_sv = cv_const_sv(cv)) const_changed = sv_cmp(const_sv, op_const_sv(block, Nullcv)); if ((const_sv && const_changed) || ckWARN(WARN_REDEFINE) && !(CvGV(cv) && GvSTASH(CvGV(cv)) && HvNAME(GvSTASH(CvGV(cv))) && strEQ(HvNAME(GvSTASH(CvGV(cv))), - "autouse"))) { + "autouse"))) + { line_t oldline = CopLINE(PL_curcop); CopLINE_set(PL_curcop, PL_copline); Perl_warner(aTHX_ WARN_REDEFINE, @@ -4491,15 +4542,17 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } } - if (name) { + if (name || aname) { char *s; + char *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); - CV *cv; + CV *pcv; HV *hv; + char *t; Perl_sv_setpvf(aTHX_ sv, "%s:%ld-%ld", CopFILE(PL_curcop), @@ -4508,21 +4561,22 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) hv_store(GvHV(PL_DBsub), SvPVX(tmpstr), SvCUR(tmpstr), sv, 0); hv = GvHVn(db_postponed); if (HvFILL(hv) > 0 && hv_exists(hv, SvPVX(tmpstr), SvCUR(tmpstr)) - && (cv = GvCV(db_postponed))) { + && (pcv = GvCV(db_postponed))) + { dSP; PUSHMARK(SP); XPUSHs(tmpstr); PUTBACK; - call_sv((SV*)cv, G_DISCARD); + call_sv((SV*)pcv, G_DISCARD); } } - if ((s = strrchr(name,':'))) + if ((s = strrchr(tname,':'))) s++; else - s = name; + s = tname; - if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I') + if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I') goto done; if (strEQ(s, "BEGIN")) { @@ -4552,12 +4606,12 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) av_store(PL_endav, 0, SvREFCNT_inc(cv)); GvCV(gv) = 0; } - else if (strEQ(s, "STOP") && !PL_error_count) { - if (!PL_stopav) - PL_stopav = newAV(); + else if (strEQ(s, "CHECK") && !PL_error_count) { + if (!PL_checkav) + PL_checkav = newAV(); DEBUG_x( dump_sub(gv) ); - av_unshift(PL_stopav, 1); - av_store(PL_stopav, 0, SvREFCNT_inc(cv)); + av_unshift(PL_checkav, 1); + av_store(PL_checkav, 0, SvREFCNT_inc(cv)); GvCV(gv) = 0; } else if (strEQ(s, "INIT") && !PL_error_count) { @@ -4576,6 +4630,15 @@ Perl_newATTRSUB(pTHX_ I32 floor, OP *o, OP *proto, OP *attrs, OP *block) } /* XXX unsafe for threads if eval_owner isn't held */ +/* +=for apidoc newCONSTSUB + +Creates a constant sub equivalent to Perl C which is +eligible for inlining at compile-time. + +=cut +*/ + void Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv) { @@ -4610,6 +4673,14 @@ Perl_newCONSTSUB(pTHX_ HV *stash, char *name, SV *sv) LEAVE; } +/* +=for apidoc U||newXS + +Used by C to hook up XSUBs as Perl subs. + +=cut +*/ + CV * Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) { @@ -4668,7 +4739,7 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) else s = name; - if (*s != 'B' && *s != 'E' && *s != 'S' && *s != 'I') + if (*s != 'B' && *s != 'E' && *s != 'C' && *s != 'I') goto done; if (strEQ(s, "BEGIN")) { @@ -4684,11 +4755,11 @@ Perl_newXS(pTHX_ char *name, XSUBADDR_t subaddr, char *filename) av_store(PL_endav, 0, SvREFCNT_inc(cv)); GvCV(gv) = 0; } - else if (strEQ(s, "STOP")) { - if (!PL_stopav) - PL_stopav = newAV(); - av_unshift(PL_stopav, 1); - av_store(PL_stopav, 0, SvREFCNT_inc(cv)); + else if (strEQ(s, "CHECK")) { + if (!PL_checkav) + PL_checkav = newAV(); + av_unshift(PL_checkav, 1); + av_store(PL_checkav, 0, SvREFCNT_inc(cv)); GvCV(gv) = 0; } else if (strEQ(s, "INIT")) { @@ -5648,7 +5719,9 @@ Perl_ck_sassign(pTHX_ OP *o) OP *kid = cLISTOPo->op_first; /* has a disposable target? */ if ((PL_opargs[kid->op_type] & OA_TARGLEX) - && !(kid->op_flags & OPf_STACKED)) + && !(kid->op_flags & OPf_STACKED) + /* Cannot steal the second time! */ + && !(kid->op_private & OPpTARGET_MY)) { OP *kkid = kid->op_sibling; @@ -5895,7 +5968,7 @@ S_simplify_sort(pTHX_ OP *o) return; if (strEQ(GvNAME(gv), "a")) reversed = 0; - else if(strEQ(GvNAME(gv), "b")) + else if (strEQ(GvNAME(gv), "b")) reversed = 1; else return; @@ -6286,7 +6359,8 @@ Perl_peep(pTHX_ register OP *o) if (o->op_next->op_type == OP_RV2SV) { if (!(o->op_next->op_private & OPpDEREF)) { null(o->op_next); - o->op_private |= o->op_next->op_private & OPpLVAL_INTRO; + o->op_private |= o->op_next->op_private & (OPpLVAL_INTRO + | OPpOUR_INTRO); o->op_next = o->op_next->op_next; o->op_type = OP_GVSV; o->op_ppaddr = PL_ppaddr[OP_GVSV]; @@ -6384,11 +6458,12 @@ Perl_peep(pTHX_ register OP *o) UNOP *rop; SV *lexname; GV **fields; - SV **svp, **indsvp; + SV **svp, **indsvp, *sv; I32 ind; char *key; STRLEN keylen; + o->op_seq = PL_op_seqmax++; if ((o->op_private & (OPpLVAL_INTRO)) || ((BINOP*)o)->op_last->op_type != OP_CONST) break; @@ -6415,8 +6490,76 @@ Perl_peep(pTHX_ register OP *o) rop->op_ppaddr = PL_ppaddr[OP_RV2AV]; o->op_type = OP_AELEM; o->op_ppaddr = PL_ppaddr[OP_AELEM]; + sv = newSViv(ind); + if (SvREADONLY(*svp)) + SvREADONLY_on(sv); + SvFLAGS(sv) |= (SvFLAGS(*svp) + & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY)); SvREFCNT_dec(*svp); - *svp = newSViv(ind); + *svp = sv; + break; + } + + case OP_HSLICE: { + UNOP *rop; + SV *lexname; + GV **fields; + SV **svp, **indsvp, *sv; + I32 ind; + char *key; + STRLEN keylen; + SVOP *first_key_op, *key_op; + + o->op_seq = PL_op_seqmax++; + if ((o->op_private & (OPpLVAL_INTRO)) + /* I bet there's always a pushmark... */ + || ((LISTOP*)o)->op_first->op_sibling->op_type != OP_LIST) + /* hmmm, no optimization if list contains only one key. */ + break; + rop = (UNOP*)((LISTOP*)o)->op_last; + if (rop->op_type != OP_RV2HV || rop->op_first->op_type != OP_PADSV) + break; + lexname = *av_fetch(PL_comppad_name, rop->op_first->op_targ, TRUE); + if (!SvOBJECT(lexname)) + break; + fields = (GV**)hv_fetch(SvSTASH(lexname), "FIELDS", 6, FALSE); + if (!fields || !GvHV(*fields)) + break; + /* Again guessing that the pushmark can be jumped over.... */ + first_key_op = (SVOP*)((LISTOP*)((LISTOP*)o)->op_first->op_sibling) + ->op_first->op_sibling; + /* Check that the key list contains only constants. */ + for (key_op = first_key_op; key_op; + key_op = (SVOP*)key_op->op_sibling) + if (key_op->op_type != OP_CONST) + break; + if (key_op) + break; + rop->op_type = OP_RV2AV; + rop->op_ppaddr = PL_ppaddr[OP_RV2AV]; + o->op_type = OP_ASLICE; + o->op_ppaddr = PL_ppaddr[OP_ASLICE]; + for (key_op = first_key_op; key_op; + key_op = (SVOP*)key_op->op_sibling) { + svp = cSVOPx_svp(key_op); + key = SvPV(*svp, keylen); + indsvp = hv_fetch(GvHV(*fields), key, keylen, FALSE); + if (!indsvp) { + Perl_croak(aTHX_ "No such pseudo-hash field \"%s\" " + "in variable %s of type %s", + key, SvPV(lexname, n_a), HvNAME(SvSTASH(lexname))); + } + ind = SvIV(*indsvp); + if (ind < 1) + Perl_croak(aTHX_ "Bad index while coercing array into hash"); + sv = newSViv(ind); + if (SvREADONLY(*svp)) + SvREADONLY_on(sv); + SvFLAGS(sv) |= (SvFLAGS(*svp) + & (SVs_PADBUSY|SVs_PADTMP|SVs_PADMY)); + SvREFCNT_dec(*svp); + *svp = sv; + } break; }