X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/7d49f6898e172f330a81e972c5944fc5726fcbf3..50edf520be9fa4c0e7982006bec3a6939b2f61a7:/pp_ctl.c diff --git a/pp_ctl.c b/pp_ctl.c index a3f76cf..1dcca0b 100644 --- a/pp_ctl.c +++ b/pp_ctl.c @@ -1,7 +1,7 @@ /* pp_ctl.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, 2007 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. @@ -38,8 +38,11 @@ #define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o)) +#define dopoptosub(plop) dopoptosub_at(cxstack, (plop)) + PP(pp_wantarray) { + dVAR; dSP; I32 cxix; EXTEND(SP, 1); @@ -60,6 +63,7 @@ PP(pp_wantarray) PP(pp_regcreset) { + dVAR; /* XXXX Should store the old value to allow for tie/overload - and restore in regcomp, where marked with XXXX. */ PL_reginterp_cnt = 0; @@ -69,10 +73,11 @@ PP(pp_regcreset) PP(pp_regcomp) { + dVAR; dSP; register PMOP *pm = (PMOP*)cLOGOP->op_other; SV *tmpstr; - MAGIC *mg = Null(MAGIC*); + REGEXP *re = NULL; /* prevent recompiling under /o and ithreads. */ #if defined(USE_ITHREADS) @@ -110,76 +115,95 @@ PP(pp_regcomp) tmpstr = POPs; if (SvROK(tmpstr)) { - SV *sv = SvRV(tmpstr); - if(SvMAGICAL(sv)) - mg = mg_find(sv, PERL_MAGIC_qr); + SV * const sv = SvRV(tmpstr); + if (SvTYPE(sv) == SVt_REGEXP) + re = (REGEXP*) sv; } - if (mg) { - regexp * const re = (regexp *)mg->mg_obj; + if (re) { + re = reg_temp_copy(re); ReREFCNT_dec(PM_GETRE(pm)); - PM_SETRE(pm, ReREFCNT_inc(re)); + PM_SETRE(pm, re); } else { STRLEN len; - const char *t = SvPV_const(tmpstr, len); + const char *t = SvOK(tmpstr) ? SvPV_const(tmpstr, len) : ""; + re = PM_GETRE(pm); + assert (re != (REGEXP*) &PL_sv_undef); /* Check against the last compiled regexp. */ - if (!PM_GETRE(pm) || !PM_GETRE(pm)->precomp || - PM_GETRE(pm)->prelen != (I32)len || - memNE(PM_GETRE(pm)->precomp, t, len)) + if (!re || !RX_PRECOMP(re) || RX_PRELEN(re) != len || + memNE(RX_PRECOMP(re), t, len)) { - if (PM_GETRE(pm)) { - ReREFCNT_dec(PM_GETRE(pm)); - PM_SETRE(pm, Null(REGEXP*)); /* crucial if regcomp aborts */ + const regexp_engine *eng = re ? RX_ENGINE(re) : NULL; + U32 pm_flags = pm->op_pmflags & PMf_COMPILETIME; + if (re) { + ReREFCNT_dec(re); +#ifdef USE_ITHREADS + PM_SETRE(pm, (REGEXP*) &PL_sv_undef); +#else + PM_SETRE(pm, NULL); /* crucial if regcomp aborts */ +#endif + } else if (PL_curcop->cop_hints_hash) { + SV *ptr = Perl_refcounted_he_fetch(aTHX_ PL_curcop->cop_hints_hash, 0, + "regcomp", 7, 0, 0); + if (ptr && SvIOK(ptr) && SvIV(ptr)) + eng = INT2PTR(regexp_engine*,SvIV(ptr)); } + if (PL_op->op_flags & OPf_SPECIAL) PL_reginterp_cnt = I32_MAX; /* Mark as safe. */ - pm->op_pmflags = pm->op_pmpermflags; /* reset case sensitivity */ - if (DO_UTF8(tmpstr)) - pm->op_pmdynflags |= PMdf_DYN_UTF8; - else { - pm->op_pmdynflags &= ~PMdf_DYN_UTF8; - if (pm->op_pmdynflags & PMdf_UTF8) - t = (char*)bytes_to_utf8((U8*)t, &len); + if (DO_UTF8(tmpstr)) { + assert (SvUTF8(tmpstr)); + } else if (SvUTF8(tmpstr)) { + /* Not doing UTF-8, despite what the SV says. Is this only if + we're trapped in use 'bytes'? */ + /* Make a copy of the octet sequence, but without the flag on, + as the compiler now honours the SvUTF8 flag on tmpstr. */ + STRLEN len; + const char *const p = SvPV(tmpstr, len); + tmpstr = newSVpvn_flags(p, len, SVs_TEMP); } - PM_SETRE(pm, CALLREGCOMP(aTHX_ (char *)t, (char *)t + len, pm)); - if (!DO_UTF8(tmpstr) && (pm->op_pmdynflags & PMdf_UTF8)) - Safefree(t); + + if (eng) + PM_SETRE(pm, CALLREGCOMP_ENG(eng, tmpstr, pm_flags)); + else + PM_SETRE(pm, CALLREGCOMP(tmpstr, pm_flags)); + PL_reginterp_cnt = 0; /* XXXX Be extra paranoid - needed inside tie/overload accessors. */ } } + + re = PM_GETRE(pm); #ifndef INCOMPLETE_TAINTS if (PL_tainting) { if (PL_tainted) - pm->op_pmdynflags |= PMdf_TAINTED; + RX_EXTFLAGS(re) |= RXf_TAINTED; else - pm->op_pmdynflags &= ~PMdf_TAINTED; + RX_EXTFLAGS(re) &= ~RXf_TAINTED; } #endif - if (!PM_GETRE(pm)->prelen && PL_curpm) + if (!RX_PRELEN(PM_GETRE(pm)) && PL_curpm) pm = PL_curpm; - else if (strEQ("\\s+", PM_GETRE(pm)->precomp)) - pm->op_pmflags |= PMf_WHITE; - else - pm->op_pmflags &= ~PMf_WHITE; - /* XXX runtime compiled output needs to move to the pad */ + +#if !defined(USE_ITHREADS) + /* can't change the optree at runtime either */ + /* PMf_KEEP is handled differently under threads to avoid these problems */ if (pm->op_pmflags & PMf_KEEP) { pm->op_private &= ~OPpRUNTIME; /* no point compiling again */ -#if !defined(USE_ITHREADS) - /* XXX can't change the optree at runtime either */ cLOGOP->op_first->op_next = PL_op->op_next; -#endif } +#endif RETURN; } PP(pp_substcont) { + dVAR; dSP; register PERL_CONTEXT *cx = &cxstack[cxstack_ix]; register PMOP * const pm = (PMOP*) cLOGOP->op_other; @@ -188,12 +212,12 @@ PP(pp_substcont) register char *m = cx->sb_m; char *orig = cx->sb_orig; register REGEXP * const rx = cx->sb_rx; - SV *nsv = Nullsv; + SV *nsv = NULL; REGEXP *old = PM_GETRE(pm); if(old != rx) { if(old) ReREFCNT_dec(old); - PM_SETRE(pm,rx); + PM_SETRE(pm,ReREFCNT_inc(rx)); } rxres_restore(&cx->sb_rxres, rx); @@ -210,7 +234,7 @@ PP(pp_substcont) FREETMPS; /* Prevent excess tmp stack */ /* Are we done */ - if (cx->sb_once || !CALLREGEXEC(aTHX_ rx, s, cx->sb_strend, orig, + if (CxONCE(cx) || !CALLREGEXEC(rx, s, cx->sb_strend, orig, s == m, cx->sb_targ, NULL, ((cx->sb_rflags & REXEC_COPY_STR) ? (REXEC_IGNOREPOS|REXEC_NOT_FIRST) @@ -240,11 +264,10 @@ PP(pp_substcont) SvLEN_set(targ, SvLEN(dstr)); if (DO_UTF8(dstr)) SvUTF8_on(targ); - SvPV_set(dstr, (char*)0); - sv_free(dstr); + SvPV_set(dstr, NULL); TAINT_IF(cx->sb_rxtainted & 1); - PUSHs(sv_2mortal(newSViv(saviters - 1))); + mPUSHi(saviters - 1); (void)SvPOK_only_UTF8(targ); TAINT_IF(cx->sb_rxtainted); @@ -252,36 +275,38 @@ PP(pp_substcont) SvTAINT(targ); LEAVE_SCOPE(cx->sb_oldsave); - ReREFCNT_dec(rx); POPSUBST(cx); RETURNOP(pm->op_next); } cx->sb_iters = saviters; } - if (RX_MATCH_COPIED(rx) && rx->subbeg != orig) { + if (RX_MATCH_COPIED(rx) && RX_SUBBEG(rx) != orig) { m = s; s = orig; - cx->sb_orig = orig = rx->subbeg; + cx->sb_orig = orig = RX_SUBBEG(rx); s = orig + (m - s); cx->sb_strend = s + (cx->sb_strend - m); } - cx->sb_m = m = rx->startp[0] + orig; + cx->sb_m = m = RX_OFFS(rx)[0].start + orig; if (m > s) { if (DO_UTF8(dstr) && !SvUTF8(cx->sb_targ)) sv_catpvn_utf8_upgrade(dstr, s, m - s, nsv); else sv_catpvn(dstr, s, m-s); } - cx->sb_s = rx->endp[0] + orig; + cx->sb_s = RX_OFFS(rx)[0].end + orig; { /* Update the pos() information. */ SV * const sv = cx->sb_targ; MAGIC *mg; I32 i; - if (SvTYPE(sv) < SVt_PVMG) - SvUPGRADE(sv, SVt_PVMG); + SvUPGRADE(sv, SVt_PVMG); if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) { - sv_magic(sv, Nullsv, PERL_MAGIC_regex_global, Nullch, 0); - mg = mg_find(sv, PERL_MAGIC_regex_global); +#ifdef PERL_OLD_COPY_ON_WRITE + if (SvIsCOW(sv)) + sv_force_normal_flags(sv, 0); +#endif + mg = sv_magicext(sv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, + NULL, 0); } i = m - orig; if (DO_UTF8(sv)) @@ -292,7 +317,7 @@ PP(pp_substcont) (void)ReREFCNT_inc(rx); cx->sb_rxtainted |= RX_MATCH_TAINTED(rx); rxres_save(&cx->sb_rxres, rx); - RETURNOP(pm->op_pmreplstart); + RETURNOP(pm->op_pmstashstartu.op_pmreplstart); } void @@ -301,11 +326,14 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) UV *p = (UV*)*rsp; U32 i; - if (!p || p[1] < rx->nparens) { + PERL_ARGS_ASSERT_RXRES_SAVE; + PERL_UNUSED_CONTEXT; + + if (!p || p[1] < RX_NPARENS(rx)) { #ifdef PERL_OLD_COPY_ON_WRITE - i = 7 + rx->nparens * 2; + i = 7 + RX_NPARENS(rx) * 2; #else - i = 6 + rx->nparens * 2; + i = 6 + RX_NPARENS(rx) * 2; #endif if (!p) Newx(p, i, UV); @@ -314,21 +342,21 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx) *rsp = (void*)p; } - *p++ = PTR2UV(RX_MATCH_COPIED(rx) ? rx->subbeg : Nullch); + *p++ = PTR2UV(RX_MATCH_COPIED(rx) ? RX_SUBBEG(rx) : NULL); RX_MATCH_COPIED_off(rx); #ifdef PERL_OLD_COPY_ON_WRITE - *p++ = PTR2UV(rx->saved_copy); - rx->saved_copy = Nullsv; + *p++ = PTR2UV(RX_SAVED_COPY(rx)); + RX_SAVED_COPY(rx) = NULL; #endif - *p++ = rx->nparens; + *p++ = RX_NPARENS(rx); - *p++ = PTR2UV(rx->subbeg); - *p++ = (UV)rx->sublen; - for (i = 0; i <= rx->nparens; ++i) { - *p++ = (UV)rx->startp[i]; - *p++ = (UV)rx->endp[i]; + *p++ = PTR2UV(RX_SUBBEG(rx)); + *p++ = (UV)RX_SUBLEN(rx); + for (i = 0; i <= RX_NPARENS(rx); ++i) { + *p++ = (UV)RX_OFFS(rx)[i].start; + *p++ = (UV)RX_OFFS(rx)[i].end; } } @@ -338,24 +366,27 @@ Perl_rxres_restore(pTHX_ void **rsp, REGEXP *rx) UV *p = (UV*)*rsp; U32 i; + PERL_ARGS_ASSERT_RXRES_RESTORE; + PERL_UNUSED_CONTEXT; + RX_MATCH_COPY_FREE(rx); RX_MATCH_COPIED_set(rx, *p); *p++ = 0; #ifdef PERL_OLD_COPY_ON_WRITE - if (rx->saved_copy) - SvREFCNT_dec (rx->saved_copy); - rx->saved_copy = INT2PTR(SV*,*p); + if (RX_SAVED_COPY(rx)) + SvREFCNT_dec (RX_SAVED_COPY(rx)); + RX_SAVED_COPY(rx) = INT2PTR(SV*,*p); *p++ = 0; #endif - rx->nparens = *p++; + RX_NPARENS(rx) = *p++; - rx->subbeg = INT2PTR(char*,*p++); - rx->sublen = (I32)(*p++); - for (i = 0; i <= rx->nparens; ++i) { - rx->startp[i] = (I32)(*p++); - rx->endp[i] = (I32)(*p++); + RX_SUBBEG(rx) = INT2PTR(char*,*p++); + RX_SUBLEN(rx) = (I32)(*p++); + for (i = 0; i <= RX_NPARENS(rx); ++i) { + RX_OFFS(rx)[i].start = (I32)(*p++); + RX_OFFS(rx)[i].end = (I32)(*p++); } } @@ -364,12 +395,15 @@ Perl_rxres_free(pTHX_ void **rsp) { UV * const p = (UV*)*rsp; + PERL_ARGS_ASSERT_RXRES_FREE; + PERL_UNUSED_CONTEXT; + if (p) { #ifdef PERL_POISON void *tmp = INT2PTR(char*,*p); Safefree(tmp); if (*p) - Poison(*p, 1, sizeof(*p)); + PoisonFree(*p, 1, sizeof(*p)); #else Safefree(INT2PTR(char*,*p)); #endif @@ -379,26 +413,26 @@ Perl_rxres_free(pTHX_ void **rsp) } #endif Safefree(p); - *rsp = Null(void*); + *rsp = NULL; } } PP(pp_formline) { - dSP; dMARK; dORIGMARK; + dVAR; dSP; dMARK; dORIGMARK; register SV * const tmpForm = *++MARK; register U32 *fpc; register char *t; const char *f; register I32 arg; - register SV *sv = Nullsv; - const char *item = Nullch; + register SV *sv = NULL; + const char *item = NULL; I32 itemsize = 0; I32 fieldsize = 0; I32 lines = 0; - bool chopspace = (strchr(PL_chopset, ' ') != Nullch); - const char *chophere = Nullch; - char *linemark = Nullch; + bool chopspace = (strchr(PL_chopset, ' ') != NULL); + const char *chophere = NULL; + char *linemark = NULL; NV value; bool gotsome = FALSE; STRLEN len; @@ -406,8 +440,8 @@ PP(pp_formline) ? (SvCUR(tmpForm) * (IN_BYTES ? 1 : 3) + 1) : 0; bool item_is_utf8 = FALSE; bool targ_is_utf8 = FALSE; - SV * nsv = Nullsv; - OP * parseres = 0; + SV * nsv = NULL; + OP * parseres = NULL; const char *fmt; bool oneline; @@ -787,17 +821,23 @@ PP(pp_formline) case FF_0DECIMAL: arg = *fpc++; #if defined(USE_LONG_DOUBLE) - fmt = (arg & 256) ? "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl; + fmt = (const char *) + ((arg & 256) ? + "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl); #else - fmt = (arg & 256) ? "%#0*.*f" : "%0*.*f"; + fmt = (const char *) + ((arg & 256) ? + "%#0*.*f" : "%0*.*f"); #endif goto ff_dec; case FF_DECIMAL: arg = *fpc++; #if defined(USE_LONG_DOUBLE) - fmt = (arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl; + fmt = (const char *) + ((arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl); #else - fmt = (arg & 256) ? "%#*.*f" : "%*.*f"; + fmt = (const char *) + ((arg & 256) ? "%#*.*f" : "%*.*f"); #endif ff_dec: /* If the field is marked with ^ and the value is undefined, @@ -820,7 +860,7 @@ PP(pp_formline) /* Formats aren't yet marked for locales, so assume "yes". */ { STORE_NUMERIC_STANDARD_SET_LOCAL(); - sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value); + my_snprintf(t, SvLEN(PL_formtarget) - (t - SvPVX(PL_formtarget)), fmt, (int) fieldsize, (int) arg & 255, value); RESTORE_NUMERIC_STANDARD(); } t += fieldsize; @@ -905,7 +945,7 @@ PP(pp_grepstart) if (PL_stack_base + *PL_markstack_ptr == SP) { (void)POPMARK; if (GIMME_V == G_SCALAR) - XPUSHs(sv_2mortal(newSViv(0))); + mXPUSHi(0); RETURNOP(PL_op->op_next->op_next); } PL_stack_sp = PL_stack_base + *PL_markstack_ptr + 1; @@ -1047,6 +1087,7 @@ PP(pp_mapwhile) PP(pp_range) { + dVAR; if (GIMME == G_ARRAY) return NORMAL; if (SvTRUEx(PAD_SV(PL_op->op_targ))) @@ -1057,6 +1098,7 @@ PP(pp_range) PP(pp_flip) { + dVAR; dSP; if (GIMME == G_ARRAY) { @@ -1072,7 +1114,7 @@ PP(pp_flip) flip = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv)); } else { - GV * const gv = gv_fetchpv(".", TRUE, SVt_PV); + GV * const gv = gv_fetchpvs(".", GV_ADD|GV_NOTQUAL, SVt_PV); if (gv && GvSV(gv)) flip = SvIV(sv) == SvIV(GvSV(gv)); } @@ -1111,7 +1153,7 @@ PP(pp_flip) PP(pp_flop) { - dSP; + dVAR; dSP; if (GIMME == G_ARRAY) { dPOPPOPssrl; @@ -1166,7 +1208,7 @@ PP(pp_flop) flop = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv)); } else { - GV * const gv = gv_fetchpv(".", TRUE, SVt_PV); + GV * const gv = gv_fetchpvs(".", GV_ADD|GV_NOTQUAL, SVt_PV); if (gv && GvSV(gv)) flop = SvIV(sv) == SvIV(GvSV(gv)); } } @@ -1176,7 +1218,7 @@ PP(pp_flop) if (flop) { sv_setiv(PAD_SV(((UNOP*)cUNOP->op_first)->op_first->op_targ), 0); - sv_catpvn(targ, "E0", 2); + sv_catpvs(targ, "E0"); } SETs(targ); } @@ -1188,19 +1230,27 @@ PP(pp_flop) static const char * const context_name[] = { "pseudo-block", + "when", + NULL, /* CXt_BLOCK never actually needs "block" */ + "given", + NULL, /* CXt_LOOP_FOR never actually needs "loop" */ + NULL, /* CXt_LOOP_PLAIN never actually needs "loop" */ + NULL, /* CXt_LOOP_LAZYSV never actually needs "loop" */ + NULL, /* CXt_LOOP_LAZYIV never actually needs "loop" */ "subroutine", + "format", "eval", - "loop", "substitution", - "block", - "format" }; STATIC I32 S_dopoptolabel(pTHX_ const char *label) { + dVAR; register I32 i; + PERL_ARGS_ASSERT_DOPOPTOLABEL; + for (i = cxstack_ix; i >= 0; i--) { register const PERL_CONTEXT * const cx = &cxstack[i]; switch (CxTYPE(cx)) { @@ -1209,16 +1259,21 @@ S_dopoptolabel(pTHX_ const char *label) case CXt_FORMAT: case CXt_EVAL: case CXt_NULL: + case CXt_GIVEN: + case CXt_WHEN: if (ckWARN(WARN_EXITING)) Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting %s via %s", context_name[CxTYPE(cx)], OP_NAME(PL_op)); if (CxTYPE(cx) == CXt_NULL) return -1; break; - case CXt_LOOP: - if ( !cx->blk_loop.label || strNE(label, cx->blk_loop.label) ) { + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: + if ( !CxLABEL(cx) || strNE(label, CxLABEL(cx)) ) { DEBUG_l(Perl_deb(aTHX_ "(Skipping label #%ld %s)\n", - (long)i, cx->blk_loop.label)); + (long)i, CxLABEL(cx))); continue; } DEBUG_l( Perl_deb(aTHX_ "(Found label #%ld %s)\n", (long)i, label)); @@ -1228,9 +1283,12 @@ S_dopoptolabel(pTHX_ const char *label) return i; } + + I32 Perl_dowantarray(pTHX) { + dVAR; const I32 gimme = block_gimme(); return (gimme == G_VOID) ? G_SCALAR : gimme; } @@ -1238,6 +1296,7 @@ Perl_dowantarray(pTHX) I32 Perl_block_gimme(pTHX) { + dVAR; const I32 cxix = dopoptosub(cxstack_ix); if (cxix < 0) return G_VOID; @@ -1259,25 +1318,24 @@ Perl_block_gimme(pTHX) I32 Perl_is_lvalue_sub(pTHX) { + dVAR; const I32 cxix = dopoptosub(cxstack_ix); assert(cxix >= 0); /* We should only be called from inside subs */ - if (cxstack[cxix].blk_sub.lval && CvLVALUE(cxstack[cxix].blk_sub.cv)) - return cxstack[cxix].blk_sub.lval; + if (CxLVAL(cxstack + cxix) && CvLVALUE(cxstack[cxix].blk_sub.cv)) + return CxLVAL(cxstack + cxix); else return 0; } STATIC I32 -S_dopoptosub(pTHX_ I32 startingblock) -{ - return dopoptosub_at(cxstack, startingblock); -} - -STATIC I32 S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) { + dVAR; I32 i; + + PERL_ARGS_ASSERT_DOPOPTOSUB_AT; + for (i = startingblock; i >= 0; i--) { register const PERL_CONTEXT * const cx = &cxstk[i]; switch (CxTYPE(cx)) { @@ -1296,6 +1354,7 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) STATIC I32 S_dopoptoeval(pTHX_ I32 startingblock) { + dVAR; I32 i; for (i = startingblock; i >= 0; i--) { register const PERL_CONTEXT *cx = &cxstack[i]; @@ -1313,6 +1372,7 @@ S_dopoptoeval(pTHX_ I32 startingblock) STATIC I32 S_dopoptoloop(pTHX_ I32 startingblock) { + dVAR; I32 i; for (i = startingblock; i >= 0; i--) { register const PERL_CONTEXT * const cx = &cxstack[i]; @@ -1328,7 +1388,10 @@ S_dopoptoloop(pTHX_ I32 startingblock) if ((CxTYPE(cx)) == CXt_NULL) return -1; break; - case CXt_LOOP: + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: DEBUG_l( Perl_deb(aTHX_ "(Found loop #%ld)\n", (long)i)); return i; } @@ -1336,9 +1399,56 @@ S_dopoptoloop(pTHX_ I32 startingblock) return i; } +STATIC I32 +S_dopoptogiven(pTHX_ I32 startingblock) +{ + dVAR; + I32 i; + for (i = startingblock; i >= 0; i--) { + register const PERL_CONTEXT *cx = &cxstack[i]; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_GIVEN: + DEBUG_l( Perl_deb(aTHX_ "(Found given #%ld)\n", (long)i)); + return i; + case CXt_LOOP_PLAIN: + assert(!CxFOREACHDEF(cx)); + break; + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + if (CxFOREACHDEF(cx)) { + DEBUG_l( Perl_deb(aTHX_ "(Found foreach #%ld)\n", (long)i)); + return i; + } + } + } + return i; +} + +STATIC I32 +S_dopoptowhen(pTHX_ I32 startingblock) +{ + dVAR; + I32 i; + for (i = startingblock; i >= 0; i--) { + register const PERL_CONTEXT *cx = &cxstack[i]; + switch (CxTYPE(cx)) { + default: + continue; + case CXt_WHEN: + DEBUG_l( Perl_deb(aTHX_ "(Found when #%ld)\n", (long)i)); + return i; + } + } + return i; +} + void Perl_dounwind(pTHX_ I32 cxix) { + dVAR; I32 optype; while (cxstack_ix > cxix) { @@ -1358,7 +1468,10 @@ Perl_dounwind(pTHX_ I32 cxix) case CXt_EVAL: POPEVAL(cx); break; - case CXt_LOOP: + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: POPLOOP(cx); break; case CXt_NULL: @@ -1375,13 +1488,18 @@ Perl_dounwind(pTHX_ I32 cxix) void Perl_qerror(pTHX_ SV *err) { + dVAR; + + PERL_ARGS_ASSERT_QERROR; + if (PL_in_eval) sv_catsv(ERRSV, err); else if (PL_errors) sv_catsv(PL_errors, err); else - Perl_warn(aTHX_ "%"SVf, err); - ++PL_error_count; + Perl_warn(aTHX_ "%"SVf, SVfARG(err)); + if (PL_parser) + ++PL_parser->error_count; } OP * @@ -1397,7 +1515,7 @@ Perl_die_where(pTHX_ const char *message, STRLEN msglen) if (PL_in_eval & EVAL_KEEPERR) { static const char prefix[] = "\t(in cleanup) "; SV * const err = ERRSV; - const char *e = Nullch; + const char *e = NULL; if (!SvPOK(err)) sv_setpvn(err,"",0); else if (SvCUR(err) >= sizeof(prefix)+msglen-1) { @@ -1405,7 +1523,7 @@ Perl_die_where(pTHX_ const char *message, STRLEN msglen) e = SvPV_const(err, len); e += len - msglen; if (*e != *message || strNE(e,message)) - e = Nullch; + e = NULL; } if (!e) { SvGROW(err, SvCUR(err)+sizeof(prefix)+msglen); @@ -1441,7 +1559,7 @@ Perl_die_where(pTHX_ const char *message, STRLEN msglen) if (CxTYPE(cx) != CXt_EVAL) { if (!message) message = SvPVx_const(ERRSV, msglen); - PerlIO_write(Perl_error_log, "panic: die ", 11); + PerlIO_write(Perl_error_log, (const char *)"panic: die ", 11); PerlIO_write(Perl_error_log, message, msglen); my_exit(1); } @@ -1482,7 +1600,7 @@ Perl_die_where(pTHX_ const char *message, STRLEN msglen) PP(pp_xor) { - dSP; dPOPTOPssrl; + dVAR; dSP; dPOPTOPssrl; if (SvTRUE(left) != SvTRUE(right)) RETSETYES; else @@ -1491,6 +1609,7 @@ PP(pp_xor) PP(pp_caller) { + dVAR; dSP; register I32 cxix = dopoptosub(cxstack_ix); register const PERL_CONTEXT *cx; @@ -1549,48 +1668,48 @@ PP(pp_caller) RETURN; } - EXTEND(SP, 10); + EXTEND(SP, 11); if (!stashname) PUSHs(&PL_sv_undef); else - PUSHs(sv_2mortal(newSVpv(stashname, 0))); - PUSHs(sv_2mortal(newSVpv(OutCopFILE(cx->blk_oldcop), 0))); - PUSHs(sv_2mortal(newSViv((I32)CopLINE(cx->blk_oldcop)))); + mPUSHs(newSVpv(stashname, 0)); + mPUSHs(newSVpv(OutCopFILE(cx->blk_oldcop), 0)); + mPUSHi((I32)CopLINE(cx->blk_oldcop)); if (!MAXARG) RETURN; if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { GV * const cvgv = CvGV(ccstack[cxix].blk_sub.cv); /* So is ccstack[dbcxix]. */ if (isGV(cvgv)) { - SV * const sv = NEWSV(49, 0); - gv_efullname3(sv, cvgv, Nullch); - PUSHs(sv_2mortal(sv)); - PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs))); + SV * const sv = newSV(0); + gv_efullname3(sv, cvgv, NULL); + mPUSHs(sv); + PUSHs(boolSV(CxHASARGS(cx))); } else { - PUSHs(sv_2mortal(newSVpvn("(unknown)",9))); - PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs))); + PUSHs(newSVpvs_flags("(unknown)", SVs_TEMP)); + PUSHs(boolSV(CxHASARGS(cx))); } } else { - PUSHs(sv_2mortal(newSVpvn("(eval)",6))); - PUSHs(sv_2mortal(newSViv(0))); + PUSHs(newSVpvs_flags("(eval)", SVs_TEMP)); + mPUSHi(0); } gimme = (I32)cx->blk_gimme; if (gimme == G_VOID) PUSHs(&PL_sv_undef); else - PUSHs(sv_2mortal(newSViv(gimme & G_ARRAY))); + PUSHs(boolSV((gimme & G_WANT) == G_ARRAY)); if (CxTYPE(cx) == CXt_EVAL) { /* eval STRING */ - if (cx->blk_eval.old_op_type == OP_ENTEREVAL) { + if (CxOLD_OP_TYPE(cx) == OP_ENTEREVAL) { PUSHs(cx->blk_eval.cur_text); PUSHs(&PL_sv_no); } /* require */ else if (cx->blk_eval.old_namesv) { - PUSHs(sv_2mortal(newSVsv(cx->blk_eval.old_namesv))); + mPUSHs(newSVsv(cx->blk_eval.old_namesv)); PUSHs(&PL_sv_yes); } /* eval BLOCK (try blocks have old_namesv == 0) */ @@ -1603,14 +1722,14 @@ PP(pp_caller) PUSHs(&PL_sv_undef); PUSHs(&PL_sv_undef); } - if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.hasargs + if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx) && CopSTASH_eq(PL_curcop, PL_debstash)) { AV * const ary = cx->blk_sub.argarray; const int off = AvARRAY(ary) - AvALLOC(ary); if (!PL_dbargs) { - GV* const tmpgv = gv_fetchpv("DB::args", TRUE, SVt_PVAV); + GV* const tmpgv = gv_fetchpvs("DB::args", GV_ADD, SVt_PVAV); PL_dbargs = GvAV(gv_AVadd(tmpgv)); GvMULTI_on(tmpgv); AvREAL_off(PL_dbargs); /* XXX should be REIFY (see av.h) */ @@ -1624,11 +1743,10 @@ PP(pp_caller) /* XXX only hints propagated via op_private are currently * visible (others are not easily accessible, since they * use the global PL_hints) */ - PUSHs(sv_2mortal(newSViv((I32)cx->blk_oldcop->op_private & - HINT_PRIVATE_MASK))); + mPUSHi(CopHINTS_get(cx->blk_oldcop)); { SV * mask ; - SV * const old_warnings = cx->blk_oldcop->cop_warnings ; + STRLEN * const old_warnings = cx->blk_oldcop->cop_warnings ; if (old_warnings == pWARN_NONE || (old_warnings == pWARN_STD && (PL_dowarn & G_WARN_ON) == 0)) @@ -1639,7 +1757,7 @@ PP(pp_caller) * it could have been extended by warnings::register */ SV **bits_all; HV * const bits = get_hv("warnings::Bits", FALSE); - if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) { + if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) { mask = newSVsv(*bits_all); } else { @@ -1647,16 +1765,23 @@ PP(pp_caller) } } else - mask = newSVsv(old_warnings); - PUSHs(sv_2mortal(mask)); + mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]); + mPUSHs(mask); } + + PUSHs(cx->blk_oldcop->cop_hints_hash ? + sv_2mortal(newRV_noinc( + (SV*)Perl_refcounted_he_chain_2hv(aTHX_ + cx->blk_oldcop->cop_hints_hash))) + : &PL_sv_undef); RETURN; } PP(pp_reset) { + dVAR; dSP; - const char * const tmps = (MAXARG < 1) ? "" : POPpconstx; + const char * const tmps = (MAXARG < 1) ? (const char *)"" : POPpconstx; sv_reset(tmps, CopSTASH(PL_curcop)); PUSHs(&PL_sv_yes); RETURN; @@ -1698,7 +1823,7 @@ PP(pp_dbstate) hasargs = 0; SPAGAIN; - if (CvXSUB(cv)) { + if (CvISXSUB(cv)) { CvDEPTH(cv)++; PUSHMARK(SP); (void)(*CvXSUB(cv))(aTHX_ cv); @@ -1727,9 +1852,9 @@ PP(pp_enteriter) register PERL_CONTEXT *cx; const I32 gimme = GIMME_V; SV **svp; - U32 cxtype = CXt_LOOP; + U8 cxtype = CXt_LOOP_FOR; #ifdef USE_ITHREADS - void *iterdata; + PAD *iterdata; #endif ENTER; @@ -1741,72 +1866,111 @@ PP(pp_enteriter) SAVESETSVFLAGS(PAD_SVl(PL_op->op_targ), SVs_PADSTALE, SVs_PADSTALE); } + SAVEPADSVANDMORTALIZE(PL_op->op_targ); #ifndef USE_ITHREADS svp = &PAD_SVl(PL_op->op_targ); /* "my" variable */ - SAVESPTR(*svp); #else - SAVEPADSV(PL_op->op_targ); - iterdata = INT2PTR(void*, PL_op->op_targ); - cxtype |= CXp_PADVAR; + iterdata = NULL; #endif } else { GV * const gv = (GV*)POPs; svp = &GvSV(gv); /* symbol table variable */ SAVEGENERICSV(*svp); - *svp = NEWSV(0,0); + *svp = newSV(0); #ifdef USE_ITHREADS - iterdata = (void*)gv; + iterdata = (PAD*)gv; #endif } + if (PL_op->op_private & OPpITER_DEF) + cxtype |= CXp_FOR_DEF; + ENTER; PUSHBLOCK(cx, cxtype, SP); #ifdef USE_ITHREADS - PUSHLOOP(cx, iterdata, MARK); + PUSHLOOP_FOR(cx, iterdata, MARK, PL_op->op_targ); #else - PUSHLOOP(cx, svp, MARK); + PUSHLOOP_FOR(cx, svp, MARK, 0); #endif if (PL_op->op_flags & OPf_STACKED) { - cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs); - if (SvTYPE(cx->blk_loop.iterary) != SVt_PVAV) { + SV *maybe_ary = POPs; + if (SvTYPE(maybe_ary) != SVt_PVAV) { dPOPss; - SV * const right = (SV*)cx->blk_loop.iterary; + SV * const right = maybe_ary; SvGETMAGIC(sv); SvGETMAGIC(right); if (RANGE_IS_NUMERIC(sv,right)) { - if ((SvOK(sv) && SvNV(sv) < IV_MIN) || - (SvOK(right) && SvNV(right) >= IV_MAX)) + cx->cx_type &= ~CXTYPEMASK; + cx->cx_type |= CXt_LOOP_LAZYIV; + /* Make sure that no-one re-orders cop.h and breaks our + assumptions */ + assert(CxTYPE(cx) == CXt_LOOP_LAZYIV); +#ifdef NV_PRESERVES_UV + if ((SvOK(sv) && ((SvNV(sv) < (NV)IV_MIN) || + (SvNV(sv) > (NV)IV_MAX))) + || + (SvOK(right) && ((SvNV(right) > (NV)IV_MAX) || + (SvNV(right) < (NV)IV_MIN)))) +#else + if ((SvOK(sv) && ((SvNV(sv) <= (NV)IV_MIN) + || + ((SvNV(sv) > 0) && + ((SvUV(sv) > (UV)IV_MAX) || + (SvNV(sv) > (NV)UV_MAX))))) + || + (SvOK(right) && ((SvNV(right) <= (NV)IV_MIN) + || + ((SvNV(right) > 0) && + ((SvUV(right) > (UV)IV_MAX) || + (SvNV(right) > (NV)UV_MAX)))))) +#endif DIE(aTHX_ "Range iterator outside integer range"); - cx->blk_loop.iterix = SvIV(sv); - cx->blk_loop.itermax = SvIV(right); + cx->blk_loop.state_u.lazyiv.cur = SvIV(sv); + cx->blk_loop.state_u.lazyiv.end = SvIV(right); #ifdef DEBUGGING /* for correct -Dstv display */ cx->blk_oldsp = sp - PL_stack_base; #endif } else { - cx->blk_loop.iterlval = newSVsv(sv); - (void) SvPV_force_nolen(cx->blk_loop.iterlval); + cx->cx_type &= ~CXTYPEMASK; + cx->cx_type |= CXt_LOOP_LAZYSV; + /* Make sure that no-one re-orders cop.h and breaks our + assumptions */ + assert(CxTYPE(cx) == CXt_LOOP_LAZYSV); + cx->blk_loop.state_u.lazysv.cur = newSVsv(sv); + cx->blk_loop.state_u.lazysv.end = right; + SvREFCNT_inc(right); + (void) SvPV_force_nolen(cx->blk_loop.state_u.lazysv.cur); + /* This will do the upgrade to SVt_PV, and warn if the value + is uninitialised. */ (void) SvPV_nolen_const(right); + /* Doing this avoids a check every time in pp_iter in pp_hot.c + to replace !SvOK() with a pointer to "". */ + if (!SvOK(right)) { + SvREFCNT_dec(right); + cx->blk_loop.state_u.lazysv.end = &PL_sv_no; + } } } - else if (PL_op->op_private & OPpITER_REVERSED) { - cx->blk_loop.itermax = 0; - cx->blk_loop.iterix = AvFILL(cx->blk_loop.iterary) + 1; - + else /* SvTYPE(maybe_ary) == SVt_PVAV */ { + cx->blk_loop.state_u.ary.ary = (AV*)maybe_ary; + SvREFCNT_inc(maybe_ary); + cx->blk_loop.state_u.ary.ix = + (PL_op->op_private & OPpITER_REVERSED) ? + AvFILL(cx->blk_loop.state_u.ary.ary) + 1 : + -1; } } - else { - cx->blk_loop.iterary = PL_curstack; - AvFILLp(PL_curstack) = SP - PL_stack_base; + else { /* iterating over items on the stack */ + cx->blk_loop.state_u.ary.ary = NULL; /* means to use the stack */ if (PL_op->op_private & OPpITER_REVERSED) { - cx->blk_loop.itermax = MARK - PL_stack_base + 1; - cx->blk_loop.iterix = cx->blk_oldsp + 1; + cx->blk_loop.state_u.ary.ix = cx->blk_oldsp + 1; } else { - cx->blk_loop.iterix = MARK - PL_stack_base; + cx->blk_loop.state_u.ary.ix = MARK - PL_stack_base; } } @@ -1823,8 +1987,8 @@ PP(pp_enterloop) SAVETMPS; ENTER; - PUSHBLOCK(cx, CXt_LOOP, SP); - PUSHLOOP(cx, 0, SP); + PUSHBLOCK(cx, CXt_LOOP_PLAIN, SP); + PUSHLOOP_PLAIN(cx, SP); RETURN; } @@ -1839,13 +2003,13 @@ PP(pp_leaveloop) SV **mark; POPBLOCK(cx,newpm); - assert(CxTYPE(cx) == CXt_LOOP); + assert(CxTYPE_is_LOOP(cx)); mark = newsp; newsp = PL_stack_base + cx->blk_loop.resetsp; TAINT_NOT; if (gimme == G_VOID) - ; /* do nothing */ + NOOP; else if (gimme == G_SCALAR) { if (mark < SP) *++newsp = sv_mortalcopy(*SP); @@ -1932,7 +2096,7 @@ PP(pp_return) /* Unassume the success we assumed earlier. */ SV * const nsv = cx->blk_eval.old_namesv; (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD); - DIE(aTHX_ "%"SVf" did not return a true value", nsv); + DIE(aTHX_ "%"SVf" did not return a true value", SVfARG(nsv)); } break; case CXt_FORMAT: @@ -1985,7 +2149,7 @@ PP(pp_return) POPSUB(cx,sv); /* release CV and @_ ... */ } else - sv = Nullsv; + sv = NULL; PL_curpm = newpm; /* ... and pop $1 et al */ LEAVESUB(sv); @@ -2006,7 +2170,7 @@ PP(pp_last) SV **newsp; PMOP *newpm; SV **mark; - SV *sv = Nullsv; + SV *sv = NULL; if (PL_op->op_flags & OPf_SPECIAL) { @@ -2026,10 +2190,13 @@ PP(pp_last) cxstack_ix++; /* temporarily protect top context */ mark = newsp; switch (CxTYPE(cx)) { - case CXt_LOOP: - pop2 = CXt_LOOP; + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: + pop2 = CxTYPE(cx); newsp = PL_stack_base + cx->blk_loop.resetsp; - nextop = cx->blk_loop.last_op->op_next; + nextop = cx->blk_loop.my_op->op_lastop->op_next; break; case CXt_SUB: pop2 = CXt_SUB; @@ -2069,7 +2236,10 @@ PP(pp_last) cxstack_ix--; /* Stack values are safe: */ switch (pop2) { - case CXt_LOOP: + case CXt_LOOP_LAZYIV: + case CXt_LOOP_PLAIN: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: POPLOOP(cx); /* release loop vars ... */ LEAVE; break; @@ -2112,7 +2282,7 @@ PP(pp_next) if (PL_scopestack_ix < inner) leave_scope(PL_scopestack[PL_scopestack_ix]); PL_curcop = cx->blk_oldcop; - return cx->blk_loop.next_op; + return CX_LOOP_NEXTOP_GET(cx); } PP(pp_redo) @@ -2136,7 +2306,7 @@ PP(pp_redo) if (cxix < cxstack_ix) dounwind(cxix); - redo_op = cxstack[cxix].blk_loop.redo_op; + redo_op = cxstack[cxix].blk_loop.my_op->op_redoop; if (redo_op->op_type == OP_ENTER) { /* pop one less context to avoid $x being freed in while (my $x..) */ cxstack_ix++; @@ -2155,9 +2325,12 @@ PP(pp_redo) STATIC OP * S_dofindlabel(pTHX_ OP *o, const char *label, OP **opstack, OP **oplimit) { + dVAR; OP **ops = opstack; static const char too_deep[] = "Target of goto is too deeply nested"; + PERL_ARGS_ASSERT_DOFINDLABEL; + if (ops >= oplimit) Perl_croak(aTHX_ too_deep); if (o->op_type == OP_LEAVE || @@ -2202,12 +2375,12 @@ S_dofindlabel(pTHX_ OP *o, const char *label, OP **opstack, OP **oplimit) PP(pp_goto) { dVAR; dSP; - OP *retop = 0; + OP *retop = NULL; I32 ix; register PERL_CONTEXT *cx; #define GOTO_DEPTH 64 OP *enterops[GOTO_DEPTH]; - const char *label = 0; + const char *label = NULL; const bool do_dump = (PL_op->op_type == OP_DUMP); static const char must_have_label[] = "goto must have label"; @@ -2238,14 +2411,14 @@ PP(pp_goto) if (autogv && (cv = GvCV(autogv))) goto retry; tmpstr = sv_newmortal(); - gv_efullname3(tmpstr, gv, Nullch); - DIE(aTHX_ "Goto undefined subroutine &%"SVf"",tmpstr); + gv_efullname3(tmpstr, gv, NULL); + DIE(aTHX_ "Goto undefined subroutine &%"SVf"", SVfARG(tmpstr)); } DIE(aTHX_ "Goto undefined subroutine"); } /* First do some returnish stuff. */ - (void)SvREFCNT_inc(cv); /* avoid premature free during unwind */ + SvREFCNT_inc_simple_void(cv); /* avoid premature free during unwind */ FREETMPS; cxix = dopoptosub(cxstack_ix); if (cxix < 0) @@ -2263,7 +2436,7 @@ PP(pp_goto) } else if (CxMULTICALL(cx)) DIE(aTHX_ "Can't goto subroutine from a sort sub (or similar callback)"); - if (CxTYPE(cx) == CXt_SUB && cx->blk_sub.hasargs) { + if (CxTYPE(cx) == CXt_SUB && CxHASARGS(cx)) { /* put @_ back onto stack */ AV* av = cx->blk_sub.argarray; @@ -2283,7 +2456,7 @@ PP(pp_goto) PAD_SVl(0) = (SV*)(cx->blk_sub.argarray = av); } } - else if (CvXSUB(cv)) { /* put GvAV(defgv) back onto stack */ + else if (CvISXSUB(cv)) { /* put GvAV(defgv) back onto stack */ AV* const av = GvAV(PL_defgv); items = AvFILLp(av) + 1; EXTEND(SP, items+1); /* @_ could have been extended. */ @@ -2300,87 +2473,65 @@ PP(pp_goto) /* Now do some callish stuff. */ SAVETMPS; SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */ - if (CvXSUB(cv)) { - OP* retop = cx->blk_sub.retop; + if (CvISXSUB(cv)) { + OP* const retop = cx->blk_sub.retop; + SV **newsp; + I32 gimme; if (reified) { I32 index; for (index=0; index mark) { - SP[1] = SP[0]; - SP--; - } - fp3 = (I32(*)(int,int,int))CvXSUB(cv); - items = (*fp3)(CvXSUBANY(cv).any_i32, - mark - PL_stack_base + 1, - items); - SP = PL_stack_base + items; - } - else -#endif /* PERL_XSUB_OLDSTYLE */ - { - SV **newsp; - I32 gimme; - /* XS subs don't have a CxSUB, so pop it */ - POPBLOCK(cx, PL_curpm); - /* Push a mark for the start of arglist */ - PUSHMARK(mark); - PUTBACK; - (void)(*CvXSUB(cv))(aTHX_ cv); - /* Put these at the bottom since the vars are set but not used */ - PERL_UNUSED_VAR(newsp); - PERL_UNUSED_VAR(gimme); - } + /* XS subs don't have a CxSUB, so pop it */ + POPBLOCK(cx, PL_curpm); + /* Push a mark for the start of arglist */ + PUSHMARK(mark); + PUTBACK; + (void)(*CvXSUB(cv))(aTHX_ cv); LEAVE; return retop; } else { - AV* padlist = CvPADLIST(cv); + AV* const padlist = CvPADLIST(cv); if (CxTYPE(cx) == CXt_EVAL) { - PL_in_eval = cx->blk_eval.old_in_eval; + PL_in_eval = CxOLD_IN_EVAL(cx); PL_eval_root = cx->blk_eval.old_eval_root; cx->cx_type = CXt_SUB; - cx->blk_sub.hasargs = 0; } cx->blk_sub.cv = cv; - cx->blk_sub.olddepth = (U16)CvDEPTH(cv); + cx->blk_sub.olddepth = CvDEPTH(cv); CvDEPTH(cv)++; if (CvDEPTH(cv) < 2) - (void)SvREFCNT_inc(cv); + SvREFCNT_inc_simple_void_NN(cv); else { - if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION)) + if (CvDEPTH(cv) == PERL_SUB_DEPTH_WARN && ckWARN(WARN_RECURSION)) sub_crush_depth(cv); pad_push(padlist, CvDEPTH(cv)); } SAVECOMPPAD(); PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); - if (cx->blk_sub.hasargs) + if (CxHASARGS(cx)) { - AV* av = (AV*)PAD_SVl(0); - SV** ary; + AV* const av = (AV*)PAD_SVl(0); cx->blk_sub.savearray = GvAV(PL_defgv); - GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av); + GvAV(PL_defgv) = (AV*)SvREFCNT_inc_simple(av); CX_CURPAD_SAVE(cx->blk_sub); cx->blk_sub.argarray = av; if (items >= AvMAX(av) + 1) { - ary = AvALLOC(av); + SV **ary = AvALLOC(av); if (AvARRAY(av) != ary) { AvMAX(av) += AvARRAY(av) - AvALLOC(av); - SvPV_set(av, (char*)ary); + AvARRAY(av) = ary; } if (items >= AvMAX(av) + 1) { AvMAX(av) = items - 1; Renew(ary,items+1,SV*); AvALLOC(av) = ary; - SvPV_set(av, (char*)ary); + AvARRAY(av) = ary; } } ++mark; @@ -2399,28 +2550,14 @@ PP(pp_goto) } } if (PERLDB_SUB) { /* Checking curstash breaks DProf. */ - /* - * We do not care about using sv to call CV; - * it's for informational purposes only. - */ - SV * const sv = GvSV(PL_DBsub); - CV *gotocv; - - save_item(sv); - if (PERLDB_SUB_NN) { - const int type = SvTYPE(sv); - if (type < SVt_PVIV && type != SVt_IV) - sv_upgrade(sv, SVt_PVIV); - (void)SvIOK_on(sv); - SvIV_set(sv, PTR2IV(cv)); /* Do it the quickest way */ - } else { - gv_efullname3(sv, CvGV(cv), Nullch); - } - if ( PERLDB_GOTO - && (gotocv = get_cv("DB::goto", FALSE)) ) { - PUSHMARK( PL_stack_sp ); - call_sv((SV*)gotocv, G_SCALAR | G_NODEBUG); - PL_stack_sp--; + Perl_get_db_sub(aTHX_ NULL, cv); + if (PERLDB_GOTO) { + CV * const gotocv = get_cv("DB::goto", FALSE); + if (gotocv) { + PUSHMARK( PL_stack_sp ); + call_sv((SV*)gotocv, G_SCALAR | G_NODEBUG); + PL_stack_sp--; + } } } RETURNOP(CvSTART(cv)); @@ -2440,14 +2577,14 @@ PP(pp_goto) label = cPVOP->op_pv; if (label && *label) { - OP *gotoprobe = 0; + OP *gotoprobe = NULL; bool leaving_eval = FALSE; bool in_block = FALSE; - PERL_CONTEXT *last_eval_cx = 0; + PERL_CONTEXT *last_eval_cx = NULL; /* find label */ - PL_lastgotoprobe = 0; + PL_lastgotoprobe = NULL; *enterops = 0; for (ix = cxstack_ix; ix >= 0; ix--) { cx = &cxstack[ix]; @@ -2462,7 +2599,10 @@ PP(pp_goto) break; } /* else fall through */ - case CXt_LOOP: + case CXt_LOOP_LAZYIV: + case CXt_LOOP_LAZYSV: + case CXt_LOOP_FOR: + case CXt_LOOP_PLAIN: gotoprobe = cx->blk_oldcop->op_sibling; break; case CXt_SUBST: @@ -2559,6 +2699,7 @@ PP(pp_goto) PP(pp_exit) { + dVAR; dSP; I32 anum; @@ -2573,51 +2714,17 @@ PP(pp_exit) #endif } PL_exit_flags |= PERL_EXIT_EXPECTED; +#ifdef PERL_MAD + /* KLUDGE: disable exit 0 in BEGIN blocks when we're just compiling */ + if (anum || !(PL_minus_c && PL_madskills)) + my_exit(anum); +#else my_exit(anum); +#endif PUSHs(&PL_sv_undef); RETURN; } -#ifdef NOTYET -PP(pp_nswitch) -{ - dSP; - const NV value = SvNVx(GvSV(cCOP->cop_gv)); - register I32 match = I_32(value); - - if (value < 0.0) { - if (((NV)match) > value) - --match; /* was fractional--truncate other way */ - } - match -= cCOP->uop.scop.scop_offset; - if (match < 0) - match = 0; - else if (match > cCOP->uop.scop.scop_max) - match = cCOP->uop.scop.scop_max; - PL_op = cCOP->uop.scop.scop_next[match]; - RETURNOP(PL_op); -} - -PP(pp_cswitch) -{ - dSP; - register I32 match; - - if (PL_multiline) - PL_op = PL_op->op_next; /* can't assume anything */ - else { - match = *(SvPVx_nolen_const(GvSV(cCOP->cop_gv))) & 255; - match -= cCOP->uop.scop.scop_offset; - if (match < 0) - match = 0; - else if (match > cCOP->uop.scop.scop_max) - match = cCOP->uop.scop.scop_max; - PL_op = cCOP->uop.scop.scop_next[match]; - } - RETURNOP(PL_op); -} -#endif - /* Eval. */ STATIC void @@ -2627,11 +2734,12 @@ S_save_lines(pTHX_ AV *array, SV *sv) const char * const send = SvPVX_const(sv) + SvCUR(sv); I32 line = 1; + PERL_ARGS_ASSERT_SAVE_LINES; + while (s && s < send) { const char *t; - SV * const tmpstr = NEWSV(85,0); + SV * const tmpstr = newSV_type(SVt_PVMG); - sv_upgrade(tmpstr, SVt_PVMG); t = strchr(s, '\n'); if (t) t++; @@ -2644,16 +2752,10 @@ S_save_lines(pTHX_ AV *array, SV *sv) } } -STATIC void -S_docatch_body(pTHX) -{ - CALLRUNOPS(aTHX); - return; -} - STATIC OP * S_docatch(pTHX_ OP *o) { + dVAR; int ret; OP * const oldop = PL_op; dJMPENV; @@ -2670,7 +2772,7 @@ S_docatch(pTHX_ OP *o) assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL); cxstack[cxstack_ix].blk_eval.cur_top_env = PL_top_env; redo_body: - docatch_body(); + CALLRUNOPS(aTHX); break; case 3: /* die caught by an inner eval - continue inner loop */ @@ -2698,7 +2800,7 @@ S_docatch(pTHX_ OP *o) } JMPENV_POP; PL_op = oldop; - return Nullop; + return NULL; } OP * @@ -2714,16 +2816,17 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) I32 gimme = G_VOID; I32 optype; OP dummy; - OP *rop; char tbuf[TYPE_DIGITS(long) + 12 + 10]; char *tmpbuf = tbuf; char *safestr; int runtime; - CV* runcv = Nullcv; /* initialise to avoid compiler warnings */ + CV* runcv = NULL; /* initialise to avoid compiler warnings */ STRLEN len; + PERL_ARGS_ASSERT_SV_COMPILE_2OP; + ENTER; - lex_start(sv); + lex_start(sv, NULL, FALSE); SAVETMPS; /* switch to eval mode */ @@ -2740,8 +2843,8 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) len = SvCUR(sv); } else - len = my_sprintf(tmpbuf, "_<(%.10s_eval %lu)", code, - (unsigned long)++PL_evalseq); + len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(%.10s_eval %lu)", code, + (unsigned long)++PL_evalseq); SAVECOPFILE_FREE(&PL_compiling); CopFILE_set(&PL_compiling, tmpbuf+2); SAVECOPLINE(&PL_compiling); @@ -2769,12 +2872,12 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) PL_op->op_type = OP_ENTEREVAL; PL_op->op_flags = 0; /* Avoid uninit warning. */ PUSHBLOCK(cx, CXt_EVAL|(IN_PERL_COMPILETIME ? 0 : CXp_REAL), SP); - PUSHEVAL(cx, 0, Nullgv); + PUSHEVAL(cx, 0); if (runtime) - rop = doeval(G_SCALAR, startop, runcv, PL_curcop->cop_seq); + (void) doeval(G_SCALAR, startop, runcv, PL_curcop->cop_seq); else - rop = doeval(G_SCALAR, startop, PL_compcv, PL_cop_seqmax); + (void) doeval(G_SCALAR, startop, PL_compcv, PL_cop_seqmax); POPBLOCK(cx,PL_curpm); POPEVAL(cx); @@ -2782,17 +2885,17 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp) (*startop)->op_ppaddr = PL_ppaddr[OP_NULL]; lex_end(); /* XXX DAPM do this properly one year */ - *padp = (AV*)SvREFCNT_inc(PL_comppad); + *padp = (AV*)SvREFCNT_inc_simple(PL_comppad); LEAVE; if (IN_PERL_COMPILETIME) - PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK); + CopHINTS_set(&PL_compiling, PL_hints); #ifdef OP_IN_REGISTER op = PL_opsave; #endif PERL_UNUSED_VAR(newsp); PERL_UNUSED_VAR(optype); - return rop; + return PL_eval_start; } @@ -2811,6 +2914,7 @@ than in the scope of the debugger itself). CV* Perl_find_runcv(pTHX_ U32 *db_seqp) { + dVAR; PERL_SI *si; if (db_seqp) @@ -2840,10 +2944,12 @@ Perl_find_runcv(pTHX_ U32 *db_seqp) * In the last case, startop is non-null, and contains the address of * a pointer that should be set to the just-compiled code. * outside is the lexically enclosing CV (if any) that invoked us. + * Returns a bool indicating whether the compile was successful; if so, + * PL_eval_start contains the first op of the compiled ocde; otherwise, + * pushes undef (also croaks if startop != NULL). */ -/* With USE_5005THREADS, eval_owner must be held on entry to doeval */ -STATIC OP * +STATIC bool S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) { dVAR; dSP; @@ -2856,21 +2962,22 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) PUSHMARK(SP); SAVESPTR(PL_compcv); - PL_compcv = (CV*)NEWSV(1104,0); - sv_upgrade((SV *)PL_compcv, SVt_PVCV); + PL_compcv = (CV*)newSV_type(SVt_PVCV); CvEVAL_on(PL_compcv); assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL); cxstack[cxstack_ix].blk_eval.cv = PL_compcv; CvOUTSIDE_SEQ(PL_compcv) = seq; - CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc(outside); + CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc_simple(outside); /* set up a scratch pad */ CvPADLIST(PL_compcv) = pad_new(padnew_SAVE); + PL_op = NULL; /* avoid PL_op and PL_curpad referring to different CVs */ - SAVEMORTALIZESV(PL_compcv); /* must remain until end of current statement */ + if (!PL_madskills) + SAVEMORTALIZESV(PL_compcv); /* must remain until end of current statement */ /* make sure we compile in the right package */ @@ -2878,22 +2985,29 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) SAVESPTR(PL_curstash); PL_curstash = CopSTASH(PL_curcop); } + /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */ SAVESPTR(PL_beginav); PL_beginav = newAV(); SAVEFREESV(PL_beginav); - SAVEI32(PL_error_count); + SAVESPTR(PL_unitcheckav); + PL_unitcheckav = newAV(); + SAVEFREESV(PL_unitcheckav); + +#ifdef PERL_MAD + SAVEBOOL(PL_madskills); + PL_madskills = 0; +#endif /* try to compile it */ - PL_eval_root = Nullop; - PL_error_count = 0; + PL_eval_root = NULL; PL_curcop = &PL_compiling; - PL_curcop->cop_arybase = 0; - if (saveop && saveop->op_flags & OPf_SPECIAL) + CopARYBASE_set(PL_curcop, 0); + if (saveop && (saveop->op_type != OP_REQUIRE) && (saveop->op_flags & OPf_SPECIAL)) PL_in_eval |= EVAL_KEEPERR; else sv_setpvn(ERRSV,"",0); - if (yyparse() || PL_error_count || !PL_eval_root) { + if (yyparse() || PL_parser->error_count || !PL_eval_root) { SV **newsp; /* Used by POPBLOCK. */ PERL_CONTEXT *cx = &cxstack[cxstack_ix]; I32 optype = 0; /* Might be reset by POPEVAL. */ @@ -2902,7 +3016,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) PL_op = saveop; if (PL_eval_root) { op_free(PL_eval_root); - PL_eval_root = Nullop; + PL_eval_root = NULL; } SP = PL_stack_base + POPMARK; /* pop original mark */ if (!startop) { @@ -2917,8 +3031,8 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) const SV * const nsv = cx->blk_eval.old_namesv; (void)hv_store(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), &PL_sv_undef, 0); - DIE(aTHX_ "%sCompilation failed in require", - *msg ? msg : "Unknown error\n"); + Perl_croak(aTHX_ "%sCompilation failed in require", + *msg ? msg : "Unknown error\n"); } else if (startop) { POPBLOCK(cx,PL_curpm); @@ -2928,11 +3042,13 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) } else { if (!*msg) { - sv_setpv(ERRSV, "Compilation error"); + sv_setpvs(ERRSV, "Compilation error"); } } PERL_UNUSED_VAR(newsp); - RETPUSHUNDEF; + PUSHs(&PL_sv_undef); + PUTBACK; + return FALSE; } CopLINE_set(&PL_compiling, 0); if (startop) { @@ -2948,9 +3064,9 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) && cLISTOPx(cUNOPx(PL_eval_root)->op_first)->op_last->op_type == OP_REQUIRE) scalar(PL_eval_root); - else if (gimme & G_VOID) + else if ((gimme & G_WANT) == G_VOID) scalarvoid(PL_eval_root); - else if (gimme & G_ARRAY) + else if ((gimme & G_WANT) == G_ARRAY) list(PL_eval_root); else scalar(PL_eval_root); @@ -2958,7 +3074,7 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) DEBUG_x(dump_eval()); /* Register with debugger: */ - if (PERLDB_INTER && saveop->op_type == OP_REQUIRE) { + if (PERLDB_INTER && saveop && saveop->op_type == OP_REQUIRE) { CV * const cv = get_cv("DB::postponed", FALSE); if (cv) { dSP; @@ -2969,68 +3085,68 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq) } } + if (PL_unitcheckav) + call_list(PL_scopestack_ix, PL_unitcheckav); + /* compiled okay, so do it */ CvDEPTH(PL_compcv) = 1; SP = PL_stack_base + POPMARK; /* pop original mark */ PL_op = saveop; /* The caller may need it. */ - PL_lex_state = LEX_NOTPARSING; /* $^S needs this. */ + PL_parser->lex_state = LEX_NOTPARSING; /* $^S needs this. */ - RETURNOP(PL_eval_start); + PUTBACK; + return TRUE; } STATIC PerlIO * -S_check_type_and_open(pTHX_ const char *name, const char *mode) +S_check_type_and_open(pTHX_ const char *name) { Stat_t st; - int st_rc; - st_rc = PerlLIO_stat(name, &st); - if (st_rc < 0) { - return Nullfp; - } + const int st_rc = PerlLIO_stat(name, &st); + + PERL_ARGS_ASSERT_CHECK_TYPE_AND_OPEN; - if(S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) { - Perl_die(aTHX_ "%s %s not allowed in require", - S_ISDIR(st.st_mode) ? "Directory" : "Block device", name); + if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) { + return NULL; } - return PerlIO_open(name, mode); + + return PerlIO_open(name, PERL_SCRIPT_MODE); } +#ifndef PERL_DISABLE_PMC STATIC PerlIO * -S_doopen_pm(pTHX_ const char *name, const char *mode) +S_doopen_pm(pTHX_ const char *name, const STRLEN namelen) { -#ifndef PERL_DISABLE_PMC - const STRLEN namelen = strlen(name); PerlIO *fp; - if (namelen > 3 && strEQ(name + namelen - 3, ".pm")) { - SV * const pmcsv = Perl_newSVpvf(aTHX_ "%s%c", name, 'c'); - const char * const pmc = SvPV_nolen_const(pmcsv); + PERL_ARGS_ASSERT_DOOPEN_PM; + + if (namelen > 3 && memEQs(name + namelen - 3, 3, ".pm")) { + SV *const pmcsv = newSV(namelen + 2); + char *const pmc = SvPVX(pmcsv); Stat_t pmcstat; + + memcpy(pmc, name, namelen); + pmc[namelen] = 'c'; + pmc[namelen + 1] = '\0'; + if (PerlLIO_stat(pmc, &pmcstat) < 0) { - fp = check_type_and_open(name, mode); + fp = check_type_and_open(name); } else { - Stat_t pmstat; - if (PerlLIO_stat(name, &pmstat) < 0 || - pmstat.st_mtime < pmcstat.st_mtime) - { - fp = check_type_and_open(pmc, mode); - } - else { - fp = check_type_and_open(name, mode); - } + fp = check_type_and_open(pmc); } SvREFCNT_dec(pmcsv); } else { - fp = check_type_and_open(name, mode); + fp = check_type_and_open(name); } return fp; +} #else - return check_type_and_open(name, mode); +# define doopen_pm(name, namelen) check_type_and_open(name) #endif /* !PERL_DISABLE_PMC */ -} PP(pp_require) { @@ -3039,51 +3155,123 @@ PP(pp_require) SV *sv; const char *name; STRLEN len; - const char *tryname = Nullch; - SV *namesv = Nullsv; + char * unixname; + STRLEN unixlen; +#ifdef VMS + int vms_unixname = 0; +#endif + const char *tryname = NULL; + SV *namesv = NULL; const I32 gimme = GIMME_V; - PerlIO *tryrsfp = 0; int filter_has_file = 0; - GV *filter_child_proc = 0; - SV *filter_state = 0; - SV *filter_sub = 0; - SV *hook_sv = 0; + PerlIO *tryrsfp = NULL; + SV *filter_cache = NULL; + SV *filter_state = NULL; + SV *filter_sub = NULL; + SV *hook_sv = NULL; SV *encoding; OP *op; sv = POPs; if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) { - if ( SvVOK(sv) && ckWARN(WARN_PORTABLE) ) /* require v5.6.1 */ - Perl_warner(aTHX_ packWARN(WARN_PORTABLE), - "v-string in use/require non-portable"); - sv = new_version(sv); if (!sv_derived_from(PL_patchlevel, "version")) - (void *)upg_version(PL_patchlevel); + upg_version(PL_patchlevel, TRUE); if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) { - if ( vcmp(sv,PL_patchlevel) < 0 ) + if ( vcmp(sv,PL_patchlevel) <= 0 ) DIE(aTHX_ "Perls since %"SVf" too modern--this is %"SVf", stopped", - vnormal(sv), vnormal(PL_patchlevel)); + SVfARG(vnormal(sv)), SVfARG(vnormal(PL_patchlevel))); } else { - if ( vcmp(sv,PL_patchlevel) > 0 ) - DIE(aTHX_ "Perl %"SVf" required--this is only %"SVf", stopped", - vnormal(sv), vnormal(PL_patchlevel)); + if ( vcmp(sv,PL_patchlevel) > 0 ) { + I32 first = 0; + AV *lav; + SV * const req = SvRV(sv); + SV * const pv = *hv_fetchs((HV*)req, "original", FALSE); + + /* get the left hand term */ + lav = (AV *)SvRV(*hv_fetchs((HV*)req, "version", FALSE)); + + first = SvIV(*av_fetch(lav,0,0)); + if ( first > (int)PERL_REVISION /* probably 'use 6.0' */ + || hv_exists((HV*)req, "qv", 2 ) /* qv style */ + || av_len(lav) > 1 /* FP with > 3 digits */ + || strstr(SvPVX(pv),".0") /* FP with leading 0 */ + ) { + DIE(aTHX_ "Perl %"SVf" required--this is only " + "%"SVf", stopped", SVfARG(vnormal(req)), + SVfARG(vnormal(PL_patchlevel))); + } + else { /* probably 'use 5.10' or 'use 5.8' */ + SV * hintsv = newSV(0); + I32 second = 0; + + if (av_len(lav)>=1) + second = SvIV(*av_fetch(lav,1,0)); + + second /= second >= 600 ? 100 : 10; + hintsv = Perl_newSVpvf(aTHX_ "v%d.%d.%d", + (int)first, (int)second,0); + upg_version(hintsv, TRUE); + + DIE(aTHX_ "Perl %"SVf" required (did you mean %"SVf"?)" + "--this is only %"SVf", stopped", + SVfARG(vnormal(req)), + SVfARG(vnormal(hintsv)), + SVfARG(vnormal(PL_patchlevel))); + } + } } - RETPUSHYES; + /* We do this only with use, not require. */ + if (PL_compcv && + /* If we request a version >= 5.9.5, load feature.pm with the + * feature bundle that corresponds to the required version. */ + vcmp(sv, sv_2mortal(upg_version(newSVnv(5.009005), FALSE))) >= 0) { + SV *const importsv = vnormal(sv); + *SvPVX_mutable(importsv) = ':'; + ENTER; + Perl_load_module(aTHX_ 0, newSVpvs("feature"), NULL, importsv, NULL); + LEAVE; + } + + RETPUSHYES; } name = SvPV_const(sv, len); if (!(name && len > 0 && *name)) DIE(aTHX_ "Null filename used"); TAINT_PROPER("require"); + + +#ifdef VMS + /* The key in the %ENV hash is in the syntax of file passed as the argument + * usually this is in UNIX format, but sometimes in VMS format, which + * can result in a module being pulled in more than once. + * To prevent this, the key must be stored in UNIX format if the VMS + * name can be translated to UNIX. + */ + if ((unixname = tounixspec(name, NULL)) != NULL) { + unixlen = strlen(unixname); + vms_unixname = 1; + } + else +#endif + { + /* if not VMS or VMS name can not be translated to UNIX, pass it + * through. + */ + unixname = (char *) name; + unixlen = len; + } if (PL_op->op_type == OP_REQUIRE) { - SV * const * const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0); + SV * const * const svp = hv_fetch(GvHVn(PL_incgv), + unixname, unixlen, 0); if ( svp ) { if (*svp != &PL_sv_undef) RETPUSHYES; else - DIE(aTHX_ "Compilation failed in require"); + DIE(aTHX_ "Attempt to reload %s aborted.\n" + "Compilation failed in require", unixname); } } @@ -3091,7 +3279,7 @@ PP(pp_require) if (path_is_absolute(name)) { tryname = name; - tryrsfp = doopen_pm(name,PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(name, len); } #ifdef MACOS_TRADITIONAL if (!tryrsfp) { @@ -3100,7 +3288,7 @@ PP(pp_require) MacPerl_CanonDir(name, newname, 1); if (path_is_absolute(newname)) { tryname = newname; - tryrsfp = doopen_pm(newname,PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(newname, strlen(newname)); } } #endif @@ -3108,16 +3296,18 @@ PP(pp_require) AV * const ar = GvAVn(PL_incgv); I32 i; #ifdef VMS - char *unixname; - if ((unixname = tounixspec(name, Nullch)) != Nullch) + if (vms_unixname) #endif { - namesv = NEWSV(806, 0); + namesv = newSV_type(SVt_PV); for (i = 0; i <= AvFILL(ar); i++) { - SV *dirsv = *av_fetch(ar, i, TRUE); + SV * const dirsv = *av_fetch(ar, i, TRUE); + if (SvTIED_mg((SV*)ar, PERL_MAGIC_tied)) + mg_get(dirsv); if (SvROK(dirsv)) { int count; + SV **svp; SV *loader = dirsv; if (SvTYPE(SvRV(loader)) == SVt_PVAV @@ -3129,7 +3319,7 @@ PP(pp_require) Perl_sv_setpvf(aTHX_ namesv, "/loader/0x%"UVxf"/%s", PTR2UV(SvRV(dirsv)), name); tryname = SvPVX_const(namesv); - tryrsfp = 0; + tryrsfp = NULL; ENTER; SAVETMPS; @@ -3145,6 +3335,11 @@ PP(pp_require) count = call_sv(loader, G_ARRAY); SPAGAIN; + /* Adjust file name if the hook has set an %INC entry */ + svp = hv_fetch(GvHVn(PL_incgv), name, len, 0); + if (svp) + tryname = SvPVX_const(*svp); + if (count > 0) { int i = 0; SV *arg; @@ -3152,34 +3347,32 @@ PP(pp_require) SP -= count - 1; arg = SP[i++]; + if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV) + && !isGV_with_GP(SvRV(arg))) { + filter_cache = SvRV(arg); + SvREFCNT_inc_simple_void_NN(filter_cache); + + if (i < count) { + arg = SP[i++]; + } + } + if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVGV) { arg = SvRV(arg); } if (SvTYPE(arg) == SVt_PVGV) { - IO *io = GvIO((GV *)arg); + IO * const io = GvIO((GV *)arg); ++filter_has_file; if (io) { tryrsfp = IoIFP(io); - if (IoTYPE(io) == IoTYPE_PIPE) { - /* reading from a child process doesn't - nest -- when returning from reading - the inner module, the outer one is - unreadable (closed?) I've tried to - save the gv to manage the lifespan of - the pipe, but this didn't help. XXX */ - filter_child_proc = (GV *)arg; - (void)SvREFCNT_inc(filter_child_proc); - } - else { - if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { - PerlIO_close(IoOFP(io)); - } - IoIFP(io) = Nullfp; - IoOFP(io) = Nullfp; + if (IoOFP(io) && IoOFP(io) != IoIFP(io)) { + PerlIO_close(IoOFP(io)); } + IoIFP(io) = NULL; + IoOFP(io) = NULL; } if (i < count) { @@ -3189,17 +3382,17 @@ PP(pp_require) if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVCV) { filter_sub = arg; - (void)SvREFCNT_inc(filter_sub); + SvREFCNT_inc_simple_void_NN(filter_sub); if (i < count) { filter_state = SP[i]; - (void)SvREFCNT_inc(filter_state); + SvREFCNT_inc_simple_void(filter_state); } + } - if (tryrsfp == 0) { - tryrsfp = PerlIO_open("/dev/null", - PERL_SCRIPT_MODE); - } + if (!tryrsfp && (filter_cache || filter_sub)) { + tryrsfp = PerlIO_open(BIT_BUCKET, + PERL_SCRIPT_MODE); } SP--; } @@ -3214,17 +3407,17 @@ PP(pp_require) } filter_has_file = 0; - if (filter_child_proc) { - SvREFCNT_dec(filter_child_proc); - filter_child_proc = 0; + if (filter_cache) { + SvREFCNT_dec(filter_cache); + filter_cache = NULL; } if (filter_state) { SvREFCNT_dec(filter_state); - filter_state = 0; + filter_state = NULL; } if (filter_sub) { SvREFCNT_dec(filter_sub); - filter_sub = 0; + filter_sub = NULL; } } else { @@ -3236,7 +3429,16 @@ PP(pp_require) || (*name == ':' && name[1] != ':' && strchr(name+2, ':')) #endif ) { - const char *dir = SvPVx_nolen_const(dirsv); + const char *dir; + STRLEN dirlen; + + if (SvOK(dirsv)) { + dir = SvPV_const(dirsv, dirlen); + } else { + dir = ""; + dirlen = 0; + } + #ifdef MACOS_TRADITIONAL char buf1[256]; char buf2[256]; @@ -3246,7 +3448,7 @@ PP(pp_require) #else # ifdef VMS char *unixdir; - if ((unixdir = tounixpath(dir, Nullch)) == Nullch) + if ((unixdir = tounixpath(dir, NULL)) == NULL) continue; sv_setpv(namesv, unixdir); sv_catpv(namesv, unixname); @@ -3264,18 +3466,40 @@ PP(pp_require) "%s\\%s", dir, name); # else - Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name); + /* The equivalent of + Perl_sv_setpvf(aTHX_ namesv, "%s/%s", dir, name); + but without the need to parse the format string, or + call strlen on either pointer, and with the correct + allocation up front. */ + { + char *tmp = SvGROW(namesv, dirlen + len + 2); + + memcpy(tmp, dir, dirlen); + tmp +=dirlen; + *tmp++ = '/'; + /* name came from an SV, so it will have a '\0' at the + end that we can copy as part of this memcpy(). */ + memcpy(tmp, name, len + 1); + + SvCUR_set(namesv, dirlen + len + 1); + + /* Don't even actually have to turn SvPOK_on() as we + access it directly with SvPVX() below. */ + } # endif # endif #endif TAINT_PROPER("require"); tryname = SvPVX_const(namesv); - tryrsfp = doopen_pm(tryname, PERL_SCRIPT_MODE); + tryrsfp = doopen_pm(tryname, SvCUR(namesv)); if (tryrsfp) { if (tryname[0] == '.' && tryname[1] == '/') tryname += 2; break; } + else if (errno == EMFILE) + /* no point in trying other paths if out of handles */ + break; } } } @@ -3288,29 +3512,28 @@ PP(pp_require) if (PL_op->op_type == OP_REQUIRE) { const char *msgstr = name; if(errno == EMFILE) { - SV * const msg = sv_2mortal(newSVpv(msgstr,0)); - sv_catpv(msg, ": "); - sv_catpv(msg, Strerror(errno)); + SV * const msg + = sv_2mortal(Perl_newSVpvf(aTHX_ "%s: %s", msgstr, + Strerror(errno))); msgstr = SvPV_nolen_const(msg); } else { if (namesv) { /* did we lookup @INC? */ - SV * const msg = sv_2mortal(newSVpv(msgstr,0)); - SV * const dirmsgsv = NEWSV(0, 0); AV * const ar = GvAVn(PL_incgv); I32 i; - sv_catpvn(msg, " in @INC", 8); - if (instr(SvPVX_const(msg), ".h ")) - sv_catpv(msg, " (change .h to .ph maybe?)"); - if (instr(SvPVX_const(msg), ".ph ")) - sv_catpv(msg, " (did you run h2ph?)"); - sv_catpv(msg, " (@INC contains:"); + SV * const msg = sv_2mortal(Perl_newSVpvf(aTHX_ + "%s in @INC%s%s (@INC contains:", + msgstr, + (instr(msgstr, ".h ") + ? " (change .h to .ph maybe?)" : ""), + (instr(msgstr, ".ph ") + ? " (did you run h2ph?)" : "") + )); + for (i = 0; i <= AvFILL(ar); i++) { - const char *dir = SvPVx_nolen_const(*av_fetch(ar, i, TRUE)); - Perl_sv_setpvf(aTHX_ dirmsgsv, " %s", dir); - sv_catsv(msg, dirmsgsv); + sv_catpvs(msg, " "); + sv_catsv(msg, *av_fetch(ar, i, TRUE)); } - sv_catpvn(msg, ")", 1); - SvREFCNT_dec(dirmsgsv); + sv_catpvs(msg, ")"); msgstr = SvPV_nolen_const(msg); } } @@ -3326,45 +3549,45 @@ PP(pp_require) /* name is never assigned to again, so len is still strlen(name) */ /* Check whether a hook in @INC has already filled %INC */ if (!hook_sv) { - (void)hv_store(GvHVn(PL_incgv), name, len, newSVpv(CopFILE(&PL_compiling),0),0); + (void)hv_store(GvHVn(PL_incgv), + unixname, unixlen, newSVpv(CopFILE(&PL_compiling),0),0); } else { - SV** const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0); + SV** const svp = hv_fetch(GvHVn(PL_incgv), unixname, unixlen, 0); if (!svp) - (void)hv_store(GvHVn(PL_incgv), name, len, SvREFCNT_inc(hook_sv), 0 ); + (void)hv_store(GvHVn(PL_incgv), + unixname, unixlen, SvREFCNT_inc_simple(hook_sv), 0 ); } ENTER; SAVETMPS; - lex_start(sv_2mortal(newSVpvn("",0))); - SAVEGENERICSV(PL_rsfp_filters); - PL_rsfp_filters = NULL; + lex_start(NULL, tryrsfp, TRUE); - PL_rsfp = tryrsfp; SAVEHINTS(); PL_hints = 0; - SAVESPTR(PL_compiling.cop_warnings); + if (PL_compiling.cop_hints_hash) { + Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash); + PL_compiling.cop_hints_hash = NULL; + } + + SAVECOMPILEWARNINGS(); if (PL_dowarn & G_WARN_ALL_ON) PL_compiling.cop_warnings = pWARN_ALL ; else if (PL_dowarn & G_WARN_ALL_OFF) PL_compiling.cop_warnings = pWARN_NONE ; - else if (PL_taint_warn) - PL_compiling.cop_warnings = newSVpvn(WARN_TAINTstring, WARNsize); else PL_compiling.cop_warnings = pWARN_STD ; - SAVESPTR(PL_compiling.cop_io); - PL_compiling.cop_io = Nullsv; - if (filter_sub || filter_child_proc) { - SV * const datasv = filter_add(S_run_user_filter, Nullsv); + if (filter_sub || filter_cache) { + SV * const datasv = filter_add(S_run_user_filter, NULL); IoLINES(datasv) = filter_has_file; - IoFMT_GV(datasv) = (GV *)filter_child_proc; IoTOP_GV(datasv) = (GV *)filter_state; IoBOTTOM_GV(datasv) = (GV *)filter_sub; + IoFMT_GV(datasv) = (GV *)filter_cache; } /* switch to eval mode */ PUSHBLOCK(cx, CXt_EVAL, SP); - PUSHEVAL(cx, name, Nullgv); + PUSHEVAL(cx, name); cx->blk_eval.retop = PL_op->op_next; SAVECOPLINE(&PL_compiling); @@ -3374,9 +3597,12 @@ PP(pp_require) /* Store and reset encoding. */ encoding = PL_encoding; - PL_encoding = Nullsv; + PL_encoding = NULL; - op = DOCATCH(doeval(gimme, NULL, Nullcv, PL_curcop->cop_seq)); + if (doeval(gimme, NULL, NULL, PL_curcop->cop_seq)) + op = DOCATCH(PL_eval_start); + else + op = PL_op->op_next; /* Restore encoding. */ PL_encoding = encoding; @@ -3388,37 +3614,44 @@ PP(pp_entereval) { dVAR; dSP; register PERL_CONTEXT *cx; - dPOPss; + SV *sv; const I32 gimme = GIMME_V; const I32 was = PL_sub_generation; char tbuf[TYPE_DIGITS(long) + 12]; char *tmpbuf = tbuf; char *safestr; STRLEN len; - OP *ret; + bool ok; CV* runcv; U32 seq; + HV *saved_hh = NULL; + const char * const fakestr = "_<(eval )"; + const int fakelen = 9 + 1; + + if (PL_op->op_private & OPpEVAL_HAS_HH) { + saved_hh = (HV*) SvREFCNT_inc(POPs); + } + sv = POPs; - if (!SvPV_nolen_const(sv)) - RETPUSHUNDEF; + TAINT_IF(SvTAINTED(sv)); TAINT_PROPER("eval"); ENTER; - lex_start(sv); + lex_start(sv, NULL, FALSE); SAVETMPS; /* switch to eval mode */ if (PERLDB_NAMEEVAL && CopLINE(PL_curcop)) { - SV * const sv = sv_newmortal(); - Perl_sv_setpvf(aTHX_ sv, "_<(eval %lu)[%s:%"IVdf"]", + SV * const temp_sv = sv_newmortal(); + Perl_sv_setpvf(aTHX_ temp_sv, "_<(eval %lu)[%s:%"IVdf"]", (unsigned long)++PL_evalseq, CopFILE(PL_curcop), (IV)CopLINE(PL_curcop)); - tmpbuf = SvPVX(sv); - len = SvCUR(sv); + tmpbuf = SvPVX(temp_sv); + len = SvCUR(temp_sv); } else - len = my_sprintf(tmpbuf, "_<(eval %lu)", (unsigned long)++PL_evalseq); + len = my_snprintf(tmpbuf, sizeof(tbuf), "_<(eval %lu)", (unsigned long)++PL_evalseq); SAVECOPFILE_FREE(&PL_compiling); CopFILE_set(&PL_compiling, tmpbuf+2); SAVECOPLINE(&PL_compiling); @@ -3432,19 +3665,18 @@ PP(pp_entereval) SAVEDELETE(PL_defstash, safestr, len); SAVEHINTS(); PL_hints = PL_op->op_targ; - SAVESPTR(PL_compiling.cop_warnings); - if (specialWARN(PL_curcop->cop_warnings)) - PL_compiling.cop_warnings = PL_curcop->cop_warnings; - else { - PL_compiling.cop_warnings = newSVsv(PL_curcop->cop_warnings); - SAVEFREESV(PL_compiling.cop_warnings); + if (saved_hh) + GvHV(PL_hintgv) = saved_hh; + SAVECOMPILEWARNINGS(); + PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings); + if (PL_compiling.cop_hints_hash) { + Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash); } - SAVESPTR(PL_compiling.cop_io); - if (specialCopIO(PL_curcop->cop_io)) - PL_compiling.cop_io = PL_curcop->cop_io; - else { - PL_compiling.cop_io = newSVsv(PL_curcop->cop_io); - SAVEFREESV(PL_compiling.cop_io); + PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash; + if (PL_compiling.cop_hints_hash) { + HINTS_REFCNT_LOCK; + PL_compiling.cop_hints_hash->refcounted_he_refcnt++; + HINTS_REFCNT_UNLOCK; } /* special case: an eval '' executed within the DB package gets lexically * placed in the first non-DB CV rather than the current CV - this @@ -3454,20 +3686,21 @@ PP(pp_entereval) runcv = find_runcv(&seq); PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP); - PUSHEVAL(cx, 0, Nullgv); + PUSHEVAL(cx, 0); cx->blk_eval.retop = PL_op->op_next; /* prepare to compile string */ if (PERLDB_LINE && PL_curstash != PL_debstash) - save_lines(CopFILEAV(&PL_compiling), PL_linestr); + save_lines(CopFILEAV(&PL_compiling), PL_parser->linestr); PUTBACK; - ret = doeval(gimme, NULL, runcv, seq); + ok = doeval(gimme, NULL, runcv, seq); if (PERLDB_INTER && was != (I32)PL_sub_generation /* Some subs defined here. */ - && ret != PL_op->op_next) { /* Successive compilation. */ - strcpy(safestr, "_<(eval )"); /* Anything fake and short. */ + && ok) { + /* Copy in anything fake and short. */ + my_strlcpy(safestr, fakestr, fakelen); } - return DOCATCH(ret); + return ok ? DOCATCH(PL_eval_start) : PL_op->op_next; } PP(pp_leaveeval) @@ -3526,7 +3759,7 @@ PP(pp_leaveeval) /* Unassume the success we assumed earlier. */ SV * const nsv = cx->blk_eval.old_namesv; (void)hv_delete(GvHVn(PL_incgv), SvPVX_const(nsv), SvCUR(nsv), G_DISCARD); - retop = Perl_die(aTHX_ "%"SVf" did not return a true value", nsv); + retop = Perl_die(aTHX_ "%"SVf" did not return a true value", SVfARG(nsv)); /* die_where() did LEAVE, or we won't be here */ } else { @@ -3538,29 +3771,62 @@ PP(pp_leaveeval) RETURNOP(retop); } -PP(pp_entertry) +/* Common code for Perl_call_sv and Perl_fold_constants, put here to keep it + close to the related Perl_create_eval_scope. */ +void +Perl_delete_eval_scope(pTHX) { - dVAR; dSP; + SV **newsp; + PMOP *newpm; + I32 gimme; register PERL_CONTEXT *cx; - const I32 gimme = GIMME_V; + I32 optype; + + POPBLOCK(cx,newpm); + POPEVAL(cx); + PL_curpm = newpm; + LEAVE; + PERL_UNUSED_VAR(newsp); + PERL_UNUSED_VAR(gimme); + PERL_UNUSED_VAR(optype); +} +/* Common-ish code salvaged from Perl_call_sv and pp_entertry, because it was + also needed by Perl_fold_constants. */ +PERL_CONTEXT * +Perl_create_eval_scope(pTHX_ U32 flags) +{ + PERL_CONTEXT *cx; + const I32 gimme = GIMME_V; + ENTER; SAVETMPS; - PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), SP); - PUSHEVAL(cx, 0, 0); - cx->blk_eval.retop = cLOGOP->op_other->op_next; + PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp); + PUSHEVAL(cx, 0); PL_in_eval = EVAL_INEVAL; - sv_setpvn(ERRSV,"",0); - PUTBACK; + if (flags & G_KEEPERR) + PL_in_eval |= EVAL_KEEPERR; + else + sv_setpvn(ERRSV,"",0); + if (flags & G_FAKINGEVAL) { + PL_eval_root = PL_op; /* Only needed so that goto works right. */ + } + return cx; +} + +PP(pp_entertry) +{ + dVAR; + PERL_CONTEXT * const cx = create_eval_scope(0); + cx->blk_eval.retop = cLOGOP->op_other->op_next; return DOCATCH(PL_op->op_next); } PP(pp_leavetry) { dVAR; dSP; - register SV **mark; SV **newsp; PMOP *newpm; I32 gimme; @@ -3575,6 +3841,7 @@ PP(pp_leavetry) if (gimme == G_VOID) SP = newsp; else if (gimme == G_SCALAR) { + register SV **mark; MARK = newsp + 1; if (MARK <= SP) { if (SvFLAGS(TOPs) & (SVs_PADTMP|SVs_TEMP)) @@ -3590,6 +3857,7 @@ PP(pp_leavetry) } else { /* in case LEAVE wipes old return values */ + register SV **mark; for (mark = newsp + 1; mark <= SP; mark++) { if (!(SvFLAGS(*mark) & (SVs_PADTMP|SVs_TEMP))) { *mark = sv_mortalcopy(*mark); @@ -3604,25 +3872,597 @@ PP(pp_leavetry) RETURN; } +PP(pp_entergiven) +{ + dVAR; dSP; + register PERL_CONTEXT *cx; + const I32 gimme = GIMME_V; + + ENTER; + SAVETMPS; + + if (PL_op->op_targ == 0) { + SV ** const defsv_p = &GvSV(PL_defgv); + *defsv_p = newSVsv(POPs); + SAVECLEARSV(*defsv_p); + } + else + sv_setsv(PAD_SV(PL_op->op_targ), POPs); + + PUSHBLOCK(cx, CXt_GIVEN, SP); + PUSHGIVEN(cx); + + RETURN; +} + +PP(pp_leavegiven) +{ + dVAR; dSP; + register PERL_CONTEXT *cx; + I32 gimme; + SV **newsp; + PMOP *newpm; + PERL_UNUSED_CONTEXT; + + POPBLOCK(cx,newpm); + assert(CxTYPE(cx) == CXt_GIVEN); + + SP = newsp; + PUTBACK; + + PL_curpm = newpm; /* pop $1 et al */ + + LEAVE; + + return NORMAL; +} + +/* Helper routines used by pp_smartmatch */ +STATIC PMOP * +S_make_matcher(pTHX_ REGEXP *re) +{ + dVAR; + PMOP *matcher = (PMOP *) newPMOP(OP_MATCH, OPf_WANT_SCALAR | OPf_STACKED); + + PERL_ARGS_ASSERT_MAKE_MATCHER; + + PM_SETRE(matcher, ReREFCNT_inc(re)); + + SAVEFREEOP((OP *) matcher); + ENTER; SAVETMPS; + SAVEOP(); + return matcher; +} + +STATIC bool +S_matcher_matches_sv(pTHX_ PMOP *matcher, SV *sv) +{ + dVAR; + dSP; + + PERL_ARGS_ASSERT_MATCHER_MATCHES_SV; + + PL_op = (OP *) matcher; + XPUSHs(sv); + PUTBACK; + (void) pp_match(); + SPAGAIN; + return (SvTRUEx(POPs)); +} + +STATIC void +S_destroy_matcher(pTHX_ PMOP *matcher) +{ + dVAR; + + PERL_ARGS_ASSERT_DESTROY_MATCHER; + PERL_UNUSED_ARG(matcher); + + FREETMPS; + LEAVE; +} + +/* Do a smart match */ +PP(pp_smartmatch) +{ + return do_smartmatch(NULL, NULL); +} + +/* This version of do_smartmatch() implements the + * table of smart matches that is found in perlsyn. + */ +STATIC OP * +S_do_smartmatch(pTHX_ HV *seen_this, HV *seen_other) +{ + dVAR; + dSP; + + SV *e = TOPs; /* e is for 'expression' */ + SV *d = TOPm1s; /* d is for 'default', as in PL_defgv */ + SV *This, *Other; /* 'This' (and Other to match) to play with C++ */ + REGEXP *this_regex, *other_regex; + +# define NOT_EMPTY_PROTO(cv) (!SvPOK(cv) || SvCUR(cv) == 0) + +# define SM_REF(type) ( \ + (SvROK(d) && (SvTYPE(This = SvRV(d)) == SVt_##type) && (Other = e)) \ + || (SvROK(e) && (SvTYPE(This = SvRV(e)) == SVt_##type) && (Other = d))) + +# define SM_CV_NEP /* Find a code ref without an empty prototype */ \ + ((SvROK(d) && (SvTYPE(This = SvRV(d)) == SVt_PVCV) \ + && NOT_EMPTY_PROTO(This) && (Other = e)) \ + || (SvROK(e) && (SvTYPE(This = SvRV(e)) == SVt_PVCV) \ + && NOT_EMPTY_PROTO(This) && (Other = d))) + +# define SM_REGEX ( \ + (SvROK(d) && (SvTYPE(This = SvRV(d)) == SVt_REGEXP) \ + && (this_regex = (REGEXP*) This) \ + && (Other = e)) \ + || \ + (SvROK(e) && (SvTYPE(This = SvRV(e)) == SVt_REGEXP) \ + && (this_regex = (REGEXP*) This) \ + && (Other = d)) ) + + +# define SM_OTHER_REF(type) \ + (SvROK(Other) && SvTYPE(SvRV(Other)) == SVt_##type) + +# define SM_OTHER_REGEX (SvROK(Other) \ + && (SvTYPE(SvRV(Other)) == SVt_REGEXP) \ + && (other_regex = (REGEXP*) SvRV(Other))) + + +# define SM_SEEN_THIS(sv) hv_exists_ent(seen_this, \ + sv_2mortal(newSViv(PTR2IV(sv))), 0) + +# define SM_SEEN_OTHER(sv) hv_exists_ent(seen_other, \ + sv_2mortal(newSViv(PTR2IV(sv))), 0) + + tryAMAGICbinSET(smart, 0); + + SP -= 2; /* Pop the values */ + + /* Take care only to invoke mg_get() once for each argument. + * Currently we do this by copying the SV if it's magical. */ + if (d) { + if (SvGMAGICAL(d)) + d = sv_mortalcopy(d); + } + else + d = &PL_sv_undef; + + assert(e); + if (SvGMAGICAL(e)) + e = sv_mortalcopy(e); + + if (SM_CV_NEP) { + I32 c; + + if ( SM_OTHER_REF(PVCV) && NOT_EMPTY_PROTO(SvRV(Other)) ) + { + if (This == SvRV(Other)) + RETPUSHYES; + else + RETPUSHNO; + } + + ENTER; + SAVETMPS; + PUSHMARK(SP); + PUSHs(Other); + PUTBACK; + c = call_sv(This, G_SCALAR); + SPAGAIN; + if (c == 0) + PUSHs(&PL_sv_no); + else if (SvTEMP(TOPs)) + SvREFCNT_inc_void(TOPs); + FREETMPS; + LEAVE; + RETURN; + } + else if (SM_REF(PVHV)) { + if (SM_OTHER_REF(PVHV)) { + /* Check that the key-sets are identical */ + HE *he; + HV *other_hv = (HV *) SvRV(Other); + bool tied = FALSE; + bool other_tied = FALSE; + U32 this_key_count = 0, + other_key_count = 0; + + /* Tied hashes don't know how many keys they have. */ + if (SvTIED_mg(This, PERL_MAGIC_tied)) { + tied = TRUE; + } + else if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied)) { + HV * const temp = other_hv; + other_hv = (HV *) This; + This = (SV *) temp; + tied = TRUE; + } + if (SvTIED_mg((SV *) other_hv, PERL_MAGIC_tied)) + other_tied = TRUE; + + if (!tied && HvUSEDKEYS((HV *) This) != HvUSEDKEYS(other_hv)) + RETPUSHNO; + + /* The hashes have the same number of keys, so it suffices + to check that one is a subset of the other. */ + (void) hv_iterinit((HV *) This); + while ( (he = hv_iternext((HV *) This)) ) { + I32 key_len; + char * const key = hv_iterkey(he, &key_len); + + ++ this_key_count; + + if(!hv_exists(other_hv, key, key_len)) { + (void) hv_iterinit((HV *) This); /* reset iterator */ + RETPUSHNO; + } + } + + if (other_tied) { + (void) hv_iterinit(other_hv); + while ( hv_iternext(other_hv) ) + ++other_key_count; + } + else + other_key_count = HvUSEDKEYS(other_hv); + + if (this_key_count != other_key_count) + RETPUSHNO; + else + RETPUSHYES; + } + else if (SM_OTHER_REF(PVAV)) { + AV * const other_av = (AV *) SvRV(Other); + const I32 other_len = av_len(other_av) + 1; + I32 i; + + for (i = 0; i < other_len; ++i) { + SV ** const svp = av_fetch(other_av, i, FALSE); + char *key; + STRLEN key_len; + + if (svp) { /* ??? When can this not happen? */ + key = SvPV(*svp, key_len); + if (hv_exists((HV *) This, key, key_len)) + RETPUSHYES; + } + } + RETPUSHNO; + } + else if (SM_OTHER_REGEX) { + PMOP * const matcher = make_matcher(other_regex); + HE *he; + + (void) hv_iterinit((HV *) This); + while ( (he = hv_iternext((HV *) This)) ) { + if (matcher_matches_sv(matcher, hv_iterkeysv(he))) { + (void) hv_iterinit((HV *) This); + destroy_matcher(matcher); + RETPUSHYES; + } + } + destroy_matcher(matcher); + RETPUSHNO; + } + else { + if (hv_exists_ent((HV *) This, Other, 0)) + RETPUSHYES; + else + RETPUSHNO; + } + } + else if (SM_REF(PVAV)) { + if (SM_OTHER_REF(PVAV)) { + AV *other_av = (AV *) SvRV(Other); + if (av_len((AV *) This) != av_len(other_av)) + RETPUSHNO; + else { + I32 i; + const I32 other_len = av_len(other_av); + + if (NULL == seen_this) { + seen_this = newHV(); + (void) sv_2mortal((SV *) seen_this); + } + if (NULL == seen_other) { + seen_this = newHV(); + (void) sv_2mortal((SV *) seen_other); + } + for(i = 0; i <= other_len; ++i) { + SV * const * const this_elem = av_fetch((AV *)This, i, FALSE); + SV * const * const other_elem = av_fetch(other_av, i, FALSE); + + if (!this_elem || !other_elem) { + if (this_elem || other_elem) + RETPUSHNO; + } + else if (SM_SEEN_THIS(*this_elem) + || SM_SEEN_OTHER(*other_elem)) + { + if (*this_elem != *other_elem) + RETPUSHNO; + } + else { + (void)hv_store_ent(seen_this, + sv_2mortal(newSViv(PTR2IV(*this_elem))), + &PL_sv_undef, 0); + (void)hv_store_ent(seen_other, + sv_2mortal(newSViv(PTR2IV(*other_elem))), + &PL_sv_undef, 0); + PUSHs(*this_elem); + PUSHs(*other_elem); + + PUTBACK; + (void) do_smartmatch(seen_this, seen_other); + SPAGAIN; + + if (!SvTRUEx(POPs)) + RETPUSHNO; + } + } + RETPUSHYES; + } + } + else if (SM_OTHER_REGEX) { + PMOP * const matcher = make_matcher(other_regex); + const I32 this_len = av_len((AV *) This); + I32 i; + + for(i = 0; i <= this_len; ++i) { + SV * const * const svp = av_fetch((AV *)This, i, FALSE); + if (svp && matcher_matches_sv(matcher, *svp)) { + destroy_matcher(matcher); + RETPUSHYES; + } + } + destroy_matcher(matcher); + RETPUSHNO; + } + else if (SvIOK(Other) || SvNOK(Other)) { + I32 i; + + for(i = 0; i <= AvFILL((AV *) This); ++i) { + SV * const * const svp = av_fetch((AV *)This, i, FALSE); + if (!svp) + continue; + + PUSHs(Other); + PUSHs(*svp); + PUTBACK; + if (CopHINTS_get(PL_curcop) & HINT_INTEGER) + (void) pp_i_eq(); + else + (void) pp_eq(); + SPAGAIN; + if (SvTRUEx(POPs)) + RETPUSHYES; + } + RETPUSHNO; + } + else if (SvPOK(Other)) { + const I32 this_len = av_len((AV *) This); + I32 i; + + for(i = 0; i <= this_len; ++i) { + SV * const * const svp = av_fetch((AV *)This, i, FALSE); + if (!svp) + continue; + + PUSHs(Other); + PUSHs(*svp); + PUTBACK; + (void) pp_seq(); + SPAGAIN; + if (SvTRUEx(POPs)) + RETPUSHYES; + } + RETPUSHNO; + } + } + else if (!SvOK(d) || !SvOK(e)) { + if (!SvOK(d) && !SvOK(e)) + RETPUSHYES; + else + RETPUSHNO; + } + else if (SM_REGEX) { + PMOP * const matcher = make_matcher(this_regex); + + PUTBACK; + PUSHs(matcher_matches_sv(matcher, Other) + ? &PL_sv_yes + : &PL_sv_no); + destroy_matcher(matcher); + RETURN; + } + else if (SM_REF(PVCV)) { + I32 c; + /* This must be a null-prototyped sub, because we + already checked for the other kind. */ + + ENTER; + SAVETMPS; + PUSHMARK(SP); + PUTBACK; + c = call_sv(This, G_SCALAR); + SPAGAIN; + if (c == 0) + PUSHs(&PL_sv_undef); + else if (SvTEMP(TOPs)) + SvREFCNT_inc_void(TOPs); + + if (SM_OTHER_REF(PVCV)) { + /* This one has to be null-proto'd too. + Call both of 'em, and compare the results */ + PUSHMARK(SP); + c = call_sv(SvRV(Other), G_SCALAR); + SPAGAIN; + if (c == 0) + PUSHs(&PL_sv_undef); + else if (SvTEMP(TOPs)) + SvREFCNT_inc_void(TOPs); + FREETMPS; + LEAVE; + PUTBACK; + return pp_eq(); + } + + FREETMPS; + LEAVE; + RETURN; + } + else if ( ((SvIOK(d) || SvNOK(d)) && (This = d) && (Other = e)) + || ((SvIOK(e) || SvNOK(e)) && (This = e) && (Other = d)) ) + { + if (SvPOK(Other) && !looks_like_number(Other)) { + /* String comparison */ + PUSHs(d); PUSHs(e); + PUTBACK; + return pp_seq(); + } + /* Otherwise, numeric comparison */ + PUSHs(d); PUSHs(e); + PUTBACK; + if (CopHINTS_get(PL_curcop) & HINT_INTEGER) + (void) pp_i_eq(); + else + (void) pp_eq(); + SPAGAIN; + if (SvTRUEx(POPs)) + RETPUSHYES; + else + RETPUSHNO; + } + + /* As a last resort, use string comparison */ + PUSHs(d); PUSHs(e); + PUTBACK; + return pp_seq(); +} + +PP(pp_enterwhen) +{ + dVAR; dSP; + register PERL_CONTEXT *cx; + const I32 gimme = GIMME_V; + + /* This is essentially an optimization: if the match + fails, we don't want to push a context and then + pop it again right away, so we skip straight + to the op that follows the leavewhen. + */ + if ((0 == (PL_op->op_flags & OPf_SPECIAL)) && !SvTRUEx(POPs)) + return cLOGOP->op_other->op_next; + + ENTER; + SAVETMPS; + + PUSHBLOCK(cx, CXt_WHEN, SP); + PUSHWHEN(cx); + + RETURN; +} + +PP(pp_leavewhen) +{ + dVAR; dSP; + register PERL_CONTEXT *cx; + I32 gimme; + SV **newsp; + PMOP *newpm; + + POPBLOCK(cx,newpm); + assert(CxTYPE(cx) == CXt_WHEN); + + SP = newsp; + PUTBACK; + + PL_curpm = newpm; /* pop $1 et al */ + + LEAVE; + return NORMAL; +} + +PP(pp_continue) +{ + dVAR; + I32 cxix; + register PERL_CONTEXT *cx; + I32 inner; + + cxix = dopoptowhen(cxstack_ix); + if (cxix < 0) + DIE(aTHX_ "Can't \"continue\" outside a when block"); + if (cxix < cxstack_ix) + dounwind(cxix); + + /* clear off anything above the scope we're re-entering */ + inner = PL_scopestack_ix; + TOPBLOCK(cx); + if (PL_scopestack_ix < inner) + leave_scope(PL_scopestack[PL_scopestack_ix]); + PL_curcop = cx->blk_oldcop; + return cx->blk_givwhen.leave_op; +} + +PP(pp_break) +{ + dVAR; + I32 cxix; + register PERL_CONTEXT *cx; + I32 inner; + + cxix = dopoptogiven(cxstack_ix); + if (cxix < 0) { + if (PL_op->op_flags & OPf_SPECIAL) + DIE(aTHX_ "Can't use when() outside a topicalizer"); + else + DIE(aTHX_ "Can't \"break\" outside a given block"); + } + if (CxFOREACH(&cxstack[cxix]) && (0 == (PL_op->op_flags & OPf_SPECIAL))) + DIE(aTHX_ "Can't \"break\" in a loop topicalizer"); + + if (cxix < cxstack_ix) + dounwind(cxix); + + /* clear off anything above the scope we're re-entering */ + inner = PL_scopestack_ix; + TOPBLOCK(cx); + if (PL_scopestack_ix < inner) + leave_scope(PL_scopestack[PL_scopestack_ix]); + PL_curcop = cx->blk_oldcop; + + if (CxFOREACH(cx)) + return CX_LOOP_NEXTOP_GET(cx); + else + return cx->blk_givwhen.leave_op; +} + STATIC OP * S_doparseform(pTHX_ SV *sv) { STRLEN len; register char *s = SvPV_force(sv, len); - register char *send = s + len; - register char *base = Nullch; + register char * const send = s + len; + register char *base = NULL; register I32 skipspaces = 0; bool noblank = FALSE; bool repeat = FALSE; bool postspace = FALSE; U32 *fops; register U32 *fpc; - U32 *linepc = 0; + U32 *linepc = NULL; register I32 arg; bool ischop; bool unchopnum = FALSE; int maxops = 12; /* FF_LINEMARK + FF_END + 10 (\0 without preceding \n) */ + PERL_ARGS_ASSERT_DOPARSEFORM; + if (len == 0) Perl_croak(aTHX_ "Null picture in formline"); @@ -3632,7 +4472,7 @@ S_doparseform(pTHX_ SV *sv) maxops += 10; } s = base; - base = Nullch; + base = NULL; Newx(fops, maxops, U32); fpc = fops; @@ -3813,7 +4653,7 @@ S_doparseform(pTHX_ SV *sv) } Copy(fops, s, arg, U32); Safefree(fops); - sv_magic(sv, Nullsv, PERL_MAGIC_fm, Nullch, 0); + sv_magic(sv, NULL, PERL_MAGIC_fm, NULL, 0); SvCOMPILED_on(sv); if (unchopnum && repeat) @@ -3855,21 +4695,78 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) dVAR; SV * const datasv = FILTER_DATA(idx); const int filter_has_file = IoLINES(datasv); - GV * const filter_child_proc = (GV *)IoFMT_GV(datasv); SV * const filter_state = (SV *)IoTOP_GV(datasv); SV * const filter_sub = (SV *)IoBOTTOM_GV(datasv); - int len = 0; + int status = 0; + SV *upstream; + STRLEN got_len; + const char *got_p = NULL; + const char *prune_from = NULL; + bool read_from_cache = FALSE; + STRLEN umaxlen; + + PERL_ARGS_ASSERT_RUN_USER_FILTER; + + assert(maxlen >= 0); + umaxlen = maxlen; /* I was having segfault trouble under Linux 2.2.5 after a parse error occured. (Had to hack around it with a test - for PL_error_count == 0.) Solaris doesn't segfault -- + for PL_parser->error_count == 0.) Solaris doesn't segfault -- not sure where the trouble is yet. XXX */ + if (IoFMT_GV(datasv)) { + SV *const cache = (SV *)IoFMT_GV(datasv); + if (SvOK(cache)) { + STRLEN cache_len; + const char *cache_p = SvPV(cache, cache_len); + STRLEN take = 0; + + if (umaxlen) { + /* Running in block mode and we have some cached data already. + */ + if (cache_len >= umaxlen) { + /* In fact, so much data we don't even need to call + filter_read. */ + take = umaxlen; + } + } else { + const char *const first_nl = + (const char *)memchr(cache_p, '\n', cache_len); + if (first_nl) { + take = first_nl + 1 - cache_p; + } + } + if (take) { + sv_catpvn(buf_sv, cache_p, take); + sv_chop(cache, cache_p + take); + /* Definately not EOF */ + return 1; + } + + sv_catsv(buf_sv, cache); + if (umaxlen) { + umaxlen -= cache_len; + } + SvOK_off(cache); + read_from_cache = TRUE; + } + } + + /* Filter API says that the filter appends to the contents of the buffer. + Usually the buffer is "", so the details don't matter. But if it's not, + then clearly what it contains is already filtered by this filter, so we + don't want to pass it in a second time. + I'm going to use a mortal in case the upstream filter croaks. */ + upstream = ((SvOK(buf_sv) && sv_len(buf_sv)) || SvGMAGICAL(buf_sv)) + ? sv_newmortal() : buf_sv; + SvUPGRADE(upstream, SVt_PV); + if (filter_has_file) { - len = FILTER_READ(idx+1, buf_sv, maxlen); + status = FILTER_READ(idx+1, upstream, 0); } - if (filter_sub && len >= 0) { + if (filter_sub && status >= 0) { dSP; int count; @@ -3878,9 +4775,9 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) SAVETMPS; EXTEND(SP, 2); - DEFSV = buf_sv; + DEFSV = upstream; PUSHMARK(SP); - PUSHs(sv_2mortal(newSViv(maxlen))); + mPUSHi(0); if (filter_state) { PUSHs(filter_state); } @@ -3891,7 +4788,7 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) if (count > 0) { SV *out = POPs; if (SvOK(out)) { - len = SvIV(out); + status = SvIV(out); } } @@ -3900,31 +4797,84 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen) LEAVE; } - if (len <= 0) { - IoLINES(datasv) = 0; - if (filter_child_proc) { - SvREFCNT_dec(filter_child_proc); - IoFMT_GV(datasv) = Nullgv; + if(SvOK(upstream)) { + got_p = SvPV(upstream, got_len); + if (umaxlen) { + if (got_len > umaxlen) { + prune_from = got_p + umaxlen; + } + } else { + const char *const first_nl = + (const char *)memchr(got_p, '\n', got_len); + if (first_nl && first_nl + 1 < got_p + got_len) { + /* There's a second line here... */ + prune_from = first_nl + 1; + } + } + } + if (prune_from) { + /* Oh. Too long. Stuff some in our cache. */ + STRLEN cached_len = got_p + got_len - prune_from; + SV *cache = (SV *)IoFMT_GV(datasv); + + if (!cache) { + IoFMT_GV(datasv) = (GV*) (cache = newSV(got_len - umaxlen)); + } else if (SvOK(cache)) { + /* Cache should be empty. */ + assert(!SvCUR(cache)); + } + + sv_setpvn(cache, prune_from, cached_len); + /* If you ask for block mode, you may well split UTF-8 characters. + "If it breaks, you get to keep both parts" + (Your code is broken if you don't put them back together again + before something notices.) */ + if (SvUTF8(upstream)) { + SvUTF8_on(cache); } + SvCUR_set(upstream, got_len - cached_len); + /* Can't yet be EOF */ + if (status == 0) + status = 1; + } + + /* If they are at EOF but buf_sv has something in it, then they may never + have touched the SV upstream, so it may be undefined. If we naively + concatenate it then we get a warning about use of uninitialised value. + */ + if (upstream != buf_sv && (SvOK(upstream) || SvGMAGICAL(upstream))) { + sv_catsv(buf_sv, upstream); + } + + if (status <= 0) { + IoLINES(datasv) = 0; + SvREFCNT_dec(IoFMT_GV(datasv)); if (filter_state) { SvREFCNT_dec(filter_state); - IoTOP_GV(datasv) = Nullgv; + IoTOP_GV(datasv) = NULL; } if (filter_sub) { SvREFCNT_dec(filter_sub); - IoBOTTOM_GV(datasv) = Nullgv; + IoBOTTOM_GV(datasv) = NULL; } filter_del(S_run_user_filter); } - - return len; + if (status == 0 && read_from_cache) { + /* If we read some data from the cache (and by getting here it implies + that we emptied the cache) then we aren't yet at EOF, and mustn't + report that to our caller. */ + return 1; + } + return status; } /* perhaps someone can come up with a better name for this? it is not really "absolute", per se ... */ static bool -S_path_is_absolute(pTHX_ const char *name) +S_path_is_absolute(const char *name) { + PERL_ARGS_ASSERT_PATH_IS_ABSOLUTE; + if (PERL_FILE_IS_ABSOLUTE(name) #ifdef MACOS_TRADITIONAL || (*name == ':')