X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=pp_hot.c;h=13e7c25b5a9c7f3be4fc3120b53d1288891dd5a3;hb=f70b6ff5dbae63778d9b1ac9a297c2d960e64cbf;hp=7bfec4a57c999a2494099464950584b7d357a434;hpb=748a93069b3d16374a9859d1456065dd3ae11394;p=p5sagit%2Fp5-mst-13.2.git diff --git a/pp_hot.c b/pp_hot.c index 7bfec4a..13e7c25 100644 --- a/pp_hot.c +++ b/pp_hot.c @@ -144,12 +144,16 @@ PP(pp_concat) dPOPTOPssrl; STRLEN len; char *s; + if (SvGMAGICAL(left)) + mg_get(left); if (TARG != left) { s = SvPV(left,len); sv_setpvn(TARG,s,len); } - else if (!SvOK(TARG)) + else if (!SvOK(TARG)) { + s = SvPV_force(TARG, len); sv_setpv(TARG, ""); /* Suppress warning. */ + } s = SvPV(right,len); sv_catpvn(TARG,s,len); SETTARG; @@ -161,8 +165,24 @@ PP(pp_padsv) { dSP; dTARGET; XPUSHs(TARG); - if (op->op_private & OPpLVAL_INTRO) - SAVECLEARSV(curpad[op->op_targ]); + if (op->op_flags & OPf_MOD) { + if (op->op_private & OPpLVAL_INTRO) + SAVECLEARSV(curpad[op->op_targ]); + else if (op->op_private & (OPpDEREF_HV|OPpDEREF_AV)) { + SV* sv = curpad[op->op_targ]; + if (SvGMAGICAL(sv)) + mg_get(sv); + if (!SvOK(sv)) { + if (SvREADONLY(sv)) + croak(no_modify); + (void)SvUPGRADE(sv, SVt_RV); + SvRV(sv) = (op->op_private & OPpDEREF_HV ? + (SV*)newHV() : (SV*)newAV()); + SvROK_on(sv); + SvSETMAGIC(sv); + } + } + } RETURN; } @@ -360,6 +380,8 @@ PP(pp_rv2av) if (op->op_flags & OPf_REF || op->op_private & HINT_STRICT_REFS) DIE(no_usym, "an ARRAY"); + if (GIMME == G_ARRAY) + RETURN; RETPUSHUNDEF; } sym = SvPV(sv,na); @@ -431,6 +453,10 @@ PP(pp_rv2hv) if (op->op_flags & OPf_REF || op->op_private & HINT_STRICT_REFS) DIE(no_usym, "a HASH"); + if (GIMME == G_ARRAY) { + SP--; + RETURN; + } RETSETUNDEF; } sym = SvPV(sv,na); @@ -502,6 +528,7 @@ PP(pp_aassign) ary = Null(AV*); hash = Null(HV*); while (lelem <= lastlelem) { + tainted = 0; /* Each item stands on its own, taintwise. */ sv = *lelem++; switch (SvTYPE(sv)) { case SVt_PVAV: @@ -518,6 +545,7 @@ PP(pp_aassign) (void)av_store(ary,i++,sv); if (magic) mg_set(sv); + tainted = 0; } break; case SVt_PVHV: { @@ -542,6 +570,7 @@ PP(pp_aassign) (void)hv_store(hash,tmps,len,tmpstr,0); if (magic) mg_set(tmpstr); + tainted = 0; } } break; @@ -571,66 +600,62 @@ PP(pp_aassign) if (delaymagic & DM_UID) { #ifdef HAS_SETRESUID (void)setresuid(uid,euid,(Uid_t)-1); -#else /* not HAS_SETRESUID */ -#ifdef HAS_SETREUID +#else +# ifdef HAS_SETREUID (void)setreuid(uid,euid); -#else /* not HAS_SETREUID */ -#ifdef HAS_SETRUID +# else +# ifdef HAS_SETRUID if ((delaymagic & DM_UID) == DM_RUID) { (void)setruid(uid); delaymagic &= ~DM_RUID; } -#endif /* HAS_SETRUID */ -#endif /* HAS_SETRESUID */ -#ifdef HAS_SETEUID +# endif /* HAS_SETRUID */ +# ifdef HAS_SETEUID if ((delaymagic & DM_UID) == DM_EUID) { (void)seteuid(uid); delaymagic &= ~DM_EUID; } -#endif /* HAS_SETEUID */ +# endif /* HAS_SETEUID */ if (delaymagic & DM_UID) { if (uid != euid) DIE("No setreuid available"); (void)setuid(uid); } -#endif /* not HAS_SETREUID */ +# endif /* HAS_SETREUID */ +#endif /* HAS_SETRESUID */ uid = (int)getuid(); euid = (int)geteuid(); } if (delaymagic & DM_GID) { #ifdef HAS_SETRESGID (void)setresgid(gid,egid,(Gid_t)-1); -#else /* not HAS_SETREGID */ -#ifdef HAS_SETREGID +#else +# ifdef HAS_SETREGID (void)setregid(gid,egid); -#else /* not HAS_SETREGID */ -#endif /* not HAS_SETRESGID */ -#ifdef HAS_SETRGID +# else +# ifdef HAS_SETRGID if ((delaymagic & DM_GID) == DM_RGID) { (void)setrgid(gid); delaymagic &= ~DM_RGID; } -#endif /* HAS_SETRGID */ -#ifdef HAS_SETRESGID - (void)setresgid(gid,egid,(Gid_t)-1); -#else /* not HAS_SETREGID */ -#ifdef HAS_SETEGID +# endif /* HAS_SETRGID */ +# ifdef HAS_SETEGID if ((delaymagic & DM_GID) == DM_EGID) { (void)setegid(gid); delaymagic &= ~DM_EGID; } -#endif /* HAS_SETEGID */ +# endif /* HAS_SETEGID */ if (delaymagic & DM_GID) { if (gid != egid) DIE("No setregid available"); (void)setgid(gid); } -#endif /* not HAS_SETRESGID */ -#endif /* not HAS_SETREGID */ +# endif /* HAS_SETREGID */ +#endif /* HAS_SETRESGID */ gid = (int)getgid(); egid = (int)getegid(); } - tainting |= (euid != uid || egid != gid); + tainting |= (uid && (euid != uid || egid != gid)); } delaymagic = 0; if (GIMME == G_ARRAY) { @@ -641,16 +666,11 @@ PP(pp_aassign) RETURN; } else { + dTARGET; SP = firstrelem; - for (relem = firstrelem; relem <= lastrelem; ++relem) { - if (SvOK(*relem)) { - dTARGET; - SETi(lastrelem - firstrelem + 1); - RETURN; - } - } - RETSETUNDEF; + SETi(lastrelem - firstrelem + 1); + RETURN; } } @@ -668,6 +688,7 @@ PP(pp_match) I32 gimme = GIMME; STRLEN len; I32 minmatch = 0; + I32 oldsave = savestack_ix; if (op->op_flags & OPf_STACKED) TARG = POPs; @@ -756,7 +777,7 @@ play_it_again: pm->op_pmshort = Nullsv; /* opt is being useless */ } } - if (regexec(rx, s, strend, truebase, minmatch, + if (pregexec(rx, s, strend, truebase, minmatch, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { curpm = pm; @@ -792,6 +813,7 @@ play_it_again: ++rx->endp[0]; goto play_it_again; } + LEAVE_SCOPE(oldsave); RETURN; } else { @@ -813,6 +835,7 @@ play_it_again: else mg->mg_len = -1; } + LEAVE_SCOPE(oldsave); RETPUSHYES; } @@ -839,6 +862,7 @@ yup: tmps = rx->startp[0] = tmps + (s - t); rx->endp[0] = tmps + SvCUR(pm->op_pmshort); } + LEAVE_SCOPE(oldsave); RETPUSHYES; nope: @@ -853,6 +877,7 @@ ret_no: mg->mg_len = -1; } } + LEAVE_SCOPE(oldsave); if (gimme == G_ARRAY) RETURN; RETPUSHNO; @@ -978,7 +1003,7 @@ do_readline() sv_setpvn(tmpcmd, cshname, cshlen); sv_catpv(tmpcmd, " -cf 'set nonomatch; glob "); sv_catsv(tmpcmd, tmpglob); - sv_catpv(tmpcmd, "'|"); + sv_catpv(tmpcmd, "' 2>/dev/null |"); #else sv_setpv(tmpcmd, "echo "); sv_catsv(tmpcmd, tmpglob); @@ -999,7 +1024,7 @@ do_readline() SP--; } if (!fp) { - if (dowarn && !(IoFLAGS(io) & IOf_START)) + if (dowarn && io && !(IoFLAGS(io) & IOf_START)) warn("Read on closed filehandle <%s>", GvENAME(last_in_gv)); if (GIMME == G_SCALAR) { (void)SvOK_off(TARG); @@ -1204,16 +1229,20 @@ PP(pp_iter) dSP; register CONTEXT *cx; SV *sv; + AV* av; EXTEND(sp, 1); cx = &cxstack[cxstack_ix]; if (cx->cx_type != CXt_LOOP) DIE("panic: pp_iter"); + av = cx->blk_loop.iterary; + if (av == stack && cx->blk_loop.iterix >= cx->blk_oldsp) + RETPUSHNO; - if (cx->blk_loop.iterix >= cx->blk_oldsp) + if (cx->blk_loop.iterix >= AvFILL(av)) RETPUSHNO; - if (sv = AvARRAY(cx->blk_loop.iterary)[++cx->blk_loop.iterix]) { + if (sv = AvARRAY(av)[++cx->blk_loop.iterix]) { SvTEMP_off(sv); *cx->blk_loop.itervar = sv; } @@ -1244,6 +1273,7 @@ PP(pp_subst) register REGEXP *rx = pm->op_pmregexp; STRLEN len; int force_on_match = 0; + I32 oldsave = savestack_ix; if (pm->op_pmflags & PMf_CONST) /* known replacement string? */ dstr = POPs; @@ -1254,7 +1284,7 @@ PP(pp_subst) EXTEND(SP,1); } s = SvPV(TARG, len); - if (!SvPOKp(TARG) || SvREADONLY(TARG)) + if (!SvPOKp(TARG) || SvREADONLY(TARG) || (SvTYPE(TARG) == SVt_PVGV)) force_on_match = 1; force_it: @@ -1315,7 +1345,7 @@ PP(pp_subst) c = SvPV(dstr, clen); if (clen <= rx->minlen) { /* can do inplace substitution */ - if (regexec(rx, s, strend, orig, 0, + if (pregexec(rx, s, strend, orig, 0, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { if (force_on_match) { force_on_match = 0; @@ -1346,6 +1376,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } /*SUPPRESS 560*/ @@ -1361,6 +1392,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } else if (clen) { @@ -1370,6 +1402,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } else { @@ -1377,6 +1410,7 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(&sv_yes); + LEAVE_SCOPE(oldsave); RETURN; } /* NOTREACHED */ @@ -1396,7 +1430,7 @@ PP(pp_subst) d += clen; } s = rx->endp[0]; - } while (regexec(rx, s, strend, orig, s == m, + } while (pregexec(rx, s, strend, orig, s == m, Nullsv, TRUE)); /* (don't match same null twice) */ if (s != d) { i = strend - s; @@ -1406,15 +1440,17 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(sv_2mortal(newSViv((I32)iters))); + LEAVE_SCOPE(oldsave); RETURN; } PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; } } else c = Nullch; - if (regexec(rx, s, strend, orig, 0, + if (pregexec(rx, s, strend, orig, 0, SvSCREAM(TARG) ? TARG : Nullsv, safebase)) { long_way: if (force_on_match) { @@ -1447,10 +1483,12 @@ PP(pp_subst) sv_catpvn(dstr, c, clen); if (once) break; - } while (regexec(rx, s, strend, orig, s == m, Nullsv, + } while (pregexec(rx, s, strend, orig, s == m, Nullsv, safebase)); sv_catpvn(dstr, s, strend - s); + (void)SvOOK_off(TARG); + Safefree(SvPVX(TARG)); SvPVX(TARG) = SvPVX(dstr); SvCUR_set(TARG, SvCUR(dstr)); SvLEN_set(TARG, SvLEN(dstr)); @@ -1460,14 +1498,17 @@ PP(pp_subst) (void)SvPOK_only(TARG); SvSETMAGIC(TARG); PUSHs(sv_2mortal(newSViv((I32)iters))); + LEAVE_SCOPE(oldsave); RETURN; } PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; nope: ++BmUSEFUL(pm->op_pmshort); PUSHs(&sv_no); + LEAVE_SCOPE(oldsave); RETURN; } @@ -1563,6 +1604,7 @@ PP(pp_entersub) HV *stash; register CV *cv; register CONTEXT *cx; + I32 gimme; if (!sv) DIE("Not a CODE reference"); @@ -1606,8 +1648,17 @@ PP(pp_entersub) if (!CvROOT(cv) && !CvXSUB(cv)) { if (gv = CvGV(cv)) { - SV *tmpstr = sv_newmortal(); + SV *tmpstr; GV *ngv; + if (SvFAKE(cv) && GvCV(gv) != cv) { /* autoloaded stub? */ + cv = GvCV(gv); + if (SvTYPE(sv) == SVt_PVGV) { + SvREFCNT_dec(GvCV((GV*)sv)); + GvCV((GV*)sv) = (CV*)SvREFCNT_inc((SV*)cv); + } + goto retry; + } + tmpstr = sv_newmortal(); gv_efullname(tmpstr, gv); ngv = gv_fetchmethod(GvESTASH(gv), "AUTOLOAD"); if (ngv && ngv != gv && (cv = GvCV(ngv))) { /* One more chance... */ @@ -1621,10 +1672,11 @@ PP(pp_entersub) DIE("Undefined subroutine called"); } + gimme = GIMME; if ((op->op_private & OPpDEREF_DB) && !CvXSUB(cv)) { sv = GvSV(DBsub); save_item(sv); - if (SvFLAGS(cv) & SVpcv_ANON) /* Is GV potentially non-unique? */ + if (SvFLAGS(cv) & (SVpcv_ANON | SVpcv_CLONED)) /* Is GV potentially non-unique? */ sv_setsv(sv, newRV((SV*)cv)); else { gv = CvGV(cv); @@ -1658,7 +1710,7 @@ PP(pp_entersub) (void)(*CvXSUB(cv))(cv); /* Enforce some sanity in scalar context. */ - if (GIMME == G_SCALAR && ++markix != stack_sp - stack_base ) { + if (gimme == G_SCALAR && ++markix != stack_sp - stack_base ) { if (markix > stack_sp - stack_base) *(stack_base + markix) = &sv_undef; else @@ -1673,7 +1725,6 @@ PP(pp_entersub) dMARK; register I32 items = SP - MARK; I32 hasargs = (op->op_flags & OPf_STACKED) != 0; - I32 gimme = GIMME; AV* padlist = CvPADLIST(cv); SV** svp = AvARRAY(padlist); push_return(op->op_next); @@ -1688,7 +1739,7 @@ PP(pp_entersub) if (CvDEPTH(cv) > AvFILL(padlist)) { AV *av; AV *newpad = newAV(); - AV *oldpad = (AV*)AvARRAY(svp[CvDEPTH(cv)-1]); + SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]); I32 ix = AvFILL((AV*)svp[1]); svp = AvARRAY(svp[0]); for ( ;ix > 0; ix--) { @@ -1696,7 +1747,7 @@ PP(pp_entersub) char *name = SvPVX(svp[ix]); if (SvFLAGS(svp[ix]) & SVf_FAKE) { /* outer lexical? */ av_store(newpad, ix, - SvREFCNT_inc(AvARRAY(oldpad)[ix]) ); + SvREFCNT_inc(oldpad[ix]) ); } else { /* our own lexical */ if (*name == '@') @@ -1810,8 +1861,10 @@ PP(pp_method) sv = *(stack_base + TOPMARK + 1); gv = 0; + if (SvGMAGICAL(sv)) + mg_get(sv); if (SvROK(sv)) - ob = SvRV(sv); + ob = (SV*)SvRV(sv); else { GV* iogv; char* packname = 0;