This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Re: [PATCH] add pTHX_ parameter to new_warnings_bitfield()
[perl5.git] / pp_ctl.c
index 45ca9ea..5288c66 100644 (file)
--- 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, 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.
 
 #define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o))
 
-static I32 run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen);
-
 PP(pp_wantarray)
 {
+    dVAR;
     dSP;
     I32 cxix;
     EXTEND(SP, 1);
@@ -62,6 +61,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;
@@ -71,10 +71,11 @@ PP(pp_regcreset)
 
 PP(pp_regcomp)
 {
+    dVAR;
     dSP;
     register PMOP *pm = (PMOP*)cLOGOP->op_other;
     SV *tmpstr;
-    MAGIC *mg = Null(MAGIC*);
+    MAGIC *mg = NULL;
 
     /* prevent recompiling under /o and ithreads. */
 #if defined(USE_ITHREADS)
@@ -132,7 +133,7 @@ PP(pp_regcomp)
        {
            if (PM_GETRE(pm)) {
                ReREFCNT_dec(PM_GETRE(pm));
-               PM_SETRE(pm, Null(REGEXP*));    /* crucial if regcomp aborts */
+               PM_SETRE(pm, NULL);     /* crucial if regcomp aborts */
            }
            if (PL_op->op_flags & OPf_SPECIAL)
                PL_reginterp_cnt = I32_MAX; /* Mark as safe.  */
@@ -182,6 +183,7 @@ PP(pp_regcomp)
 
 PP(pp_substcont)
 {
+    dVAR;
     dSP;
     register PERL_CONTEXT *cx = &cxstack[cxstack_ix];
     register PMOP * const pm = (PMOP*) cLOGOP->op_other;
@@ -190,7 +192,7 @@ 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)
@@ -209,6 +211,7 @@ PP(pp_substcont)
        if (!(cx->sb_rxtainted & 2) && SvTAINTED(TOPs))
            cx->sb_rxtainted |= 2;
        sv_catsv(dstr, POPs);
+       FREETMPS; /* Prevent excess tmp stack */
 
        /* Are we done */
        if (cx->sb_once || !CALLREGEXEC(aTHX_ rx, s, cx->sb_strend, orig,
@@ -241,7 +244,7 @@ PP(pp_substcont)
            SvLEN_set(targ, SvLEN(dstr));
            if (DO_UTF8(dstr))
                SvUTF8_on(targ);
-           SvPV_set(dstr, (char*)0);
+           SvPV_set(dstr, NULL);
            sv_free(dstr);
 
            TAINT_IF(cx->sb_rxtainted & 1);
@@ -281,8 +284,12 @@ PP(pp_substcont)
        if (SvTYPE(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(lsv))
+               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))
@@ -301,6 +308,7 @@ Perl_rxres_save(pTHX_ void **rsp, REGEXP *rx)
 {
     UV *p = (UV*)*rsp;
     U32 i;
+    PERL_UNUSED_CONTEXT;
 
     if (!p || p[1] < rx->nparens) {
 #ifdef PERL_OLD_COPY_ON_WRITE
@@ -315,12 +323,12 @@ 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 : NULL);
     RX_MATCH_COPIED_off(rx);
 
 #ifdef PERL_OLD_COPY_ON_WRITE
     *p++ = PTR2UV(rx->saved_copy);
-    rx->saved_copy = Nullsv;
+    rx->saved_copy = NULL;
 #endif
 
     *p++ = rx->nparens;
@@ -338,6 +346,7 @@ Perl_rxres_restore(pTHX_ void **rsp, REGEXP *rx)
 {
     UV *p = (UV*)*rsp;
     U32 i;
+    PERL_UNUSED_CONTEXT;
 
     RX_MATCH_COPY_FREE(rx);
     RX_MATCH_COPIED_set(rx, *p);
@@ -364,13 +373,14 @@ void
 Perl_rxres_free(pTHX_ void **rsp)
 {
     UV * const p = (UV*)*rsp;
+    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
@@ -380,26 +390,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;
@@ -407,8 +417,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;
 
@@ -1048,6 +1058,7 @@ PP(pp_mapwhile)
 
 PP(pp_range)
 {
+    dVAR;
     if (GIMME == G_ARRAY)
        return NORMAL;
     if (SvTRUEx(PAD_SV(PL_op->op_targ)))
@@ -1058,6 +1069,7 @@ PP(pp_range)
 
 PP(pp_flip)
 {
+    dVAR;
     dSP;
 
     if (GIMME == G_ARRAY) {
@@ -1073,7 +1085,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));
            }
@@ -1112,7 +1124,7 @@ PP(pp_flip)
 
 PP(pp_flop)
 {
-    dSP;
+    dVAR; dSP;
 
     if (GIMME == G_ARRAY) {
        dPOPPOPssrl;
@@ -1167,7 +1179,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));
            }
        }
@@ -1177,7 +1189,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);
     }
@@ -1194,12 +1206,15 @@ static const char * const context_name[] = {
     "loop",
     "substitution",
     "block",
-    "format"
+    "format",
+    "given",
+    "when"
 };
 
 STATIC I32
 S_dopoptolabel(pTHX_ const char *label)
 {
+    dVAR;
     register I32 i;
 
     for (i = cxstack_ix; i >= 0; i--) {
@@ -1210,6 +1225,8 @@ 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));
@@ -1229,9 +1246,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;
 }
@@ -1239,6 +1259,7 @@ Perl_dowantarray(pTHX)
 I32
 Perl_block_gimme(pTHX)
 {
+    dVAR;
     const I32 cxix = dopoptosub(cxstack_ix);
     if (cxix < 0)
        return G_VOID;
@@ -1260,6 +1281,7 @@ 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 */
 
@@ -1272,12 +1294,14 @@ Perl_is_lvalue_sub(pTHX)
 STATIC I32
 S_dopoptosub(pTHX_ I32 startingblock)
 {
+    dVAR;
     return dopoptosub_at(cxstack, startingblock);
 }
 
 STATIC I32
 S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock)
 {
+    dVAR;
     I32 i;
     for (i = startingblock; i >= 0; i--) {
        register const PERL_CONTEXT * const cx = &cxstk[i];
@@ -1297,6 +1321,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];
@@ -1314,6 +1339,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];
@@ -1337,9 +1363,51 @@ 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:
+           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) {
@@ -1376,6 +1444,7 @@ Perl_dounwind(pTHX_ I32 cxix)
 void
 Perl_qerror(pTHX_ SV *err)
 {
+    dVAR;
     if (PL_in_eval)
        sv_catsv(ERRSV, err);
     else if (PL_errors)
@@ -1398,7 +1467,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) {
@@ -1406,7 +1475,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);
@@ -1483,7 +1552,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
@@ -1492,6 +1561,7 @@ PP(pp_xor)
 
 PP(pp_caller)
 {
+    dVAR;
     dSP;
     register I32 cxix = dopoptosub(cxstack_ix);
     register const PERL_CONTEXT *cx;
@@ -1550,7 +1620,7 @@ PP(pp_caller)
        RETURN;
     }
 
-    EXTEND(SP, 10);
+    EXTEND(SP, 11);
 
     if (!stashname)
        PUSHs(&PL_sv_undef);
@@ -1561,21 +1631,21 @@ PP(pp_caller)
     if (!MAXARG)
        RETURN;
     if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
-       GV *cvgv = CvGV(ccstack[cxix].blk_sub.cv);
+       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);
+           SV * const sv = newSV(0);
+           gv_efullname3(sv, cvgv, NULL);
            PUSHs(sv_2mortal(sv));
            PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
        }
        else {
-           PUSHs(sv_2mortal(newSVpvn("(unknown)",9)));
+           PUSHs(sv_2mortal(newSVpvs("(unknown)")));
            PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
        }
     }
     else {
-       PUSHs(sv_2mortal(newSVpvn("(eval)",6)));
+       PUSHs(sv_2mortal(newSVpvs("(eval)")));
        PUSHs(sv_2mortal(newSViv(0)));
     }
     gimme = (I32)cx->blk_gimme;
@@ -1611,9 +1681,8 @@ PP(pp_caller)
        const int off = AvARRAY(ary) - AvALLOC(ary);
 
        if (!PL_dbargs) {
-           GV* tmpgv;
-           PL_dbargs = GvAV(gv_AVadd(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) */
        }
@@ -1626,11 +1695,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)));
+    PUSHs(sv_2mortal(newSViv(CopHINTS_get(cx->blk_oldcop))));
     {
        SV * mask ;
-       SV * 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))
@@ -1640,8 +1708,8 @@ PP(pp_caller)
            /* Get the bit mask for $warnings::Bits{all}, because
             * it could have been extended by warnings::register */
            SV **bits_all;
-           HV *bits = get_hv("warnings::Bits", FALSE);
-           if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) {
+           HV * const bits = get_hv("warnings::Bits", FALSE);
+           if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) {
                mask = newSVsv(*bits_all);
            }
            else {
@@ -1649,21 +1717,23 @@ PP(pp_caller)
            }
        }
         else
-            mask = newSVsv(old_warnings);
+            mask = newSVpvn((char *) (old_warnings + 1), old_warnings[0]);
         PUSHs(sv_2mortal(mask));
     }
+
+    PUSHs(cx->blk_oldcop->cop_hints ?
+         sv_2mortal(newRV_noinc(
+               (SV*)Perl_refcounted_he_chain_2hv(aTHX_
+                                                 cx->blk_oldcop->cop_hints)))
+         : &PL_sv_undef);
     RETURN;
 }
 
 PP(pp_reset)
 {
+    dVAR;
     dSP;
-    const char *tmps;
-
-    if (MAXARG < 1)
-       tmps = "";
-    else
-       tmps = POPpconstx;
+    const char * const tmps = (MAXARG < 1) ? "" : POPpconstx;
     sv_reset(tmps, CopSTASH(PL_curcop));
     PUSHs(&PL_sv_yes);
     RETURN;
@@ -1683,14 +1753,12 @@ PP(pp_dbstate)
            || SvIV(PL_DBsingle) || SvIV(PL_DBsignal) || SvIV(PL_DBtrace))
     {
        dSP;
-       register CV *cv;
        register PERL_CONTEXT *cx;
        const I32 gimme = G_ARRAY;
        U8 hasargs;
-       GV *gv;
+       GV * const gv = PL_DBgv;
+       register CV * const cv = GvCV(gv);
 
-       gv = PL_DBgv;
-       cv = GvCV(gv);
        if (!cv)
            DIE(aTHX_ "No DB::DB routine defined");
 
@@ -1707,7 +1775,7 @@ PP(pp_dbstate)
        hasargs = 0;
        SPAGAIN;
 
-       if (CvXSUB(cv)) {
+       if (CvISXSUB(cv)) {
            CvDEPTH(cv)++;
            PUSHMARK(SP);
            (void)(*CvXSUB(cv))(aTHX_ cv);
@@ -1736,7 +1804,7 @@ PP(pp_enteriter)
     register PERL_CONTEXT *cx;
     const I32 gimme = GIMME_V;
     SV **svp;
-    U32 cxtype = CXt_LOOP;
+    U32 cxtype = CXt_LOOP | CXp_FOREACH;
 #ifdef USE_ITHREADS
     void *iterdata;
 #endif
@@ -1760,15 +1828,18 @@ PP(pp_enteriter)
 #endif
     }
     else {
-       GV *gv = (GV*)POPs;
+       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;
 #endif
     }
 
+    if (PL_op->op_private & OPpITER_DEF)
+       cxtype |= CXp_FOR_DEF;
+
     ENTER;
 
     PUSHBLOCK(cx, cxtype, SP);
@@ -1781,7 +1852,7 @@ PP(pp_enteriter)
        cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs);
        if (SvTYPE(cx->blk_loop.iterary) != SVt_PVAV) {
            dPOPss;
-           SV *right = (SV*)cx->blk_loop.iterary;
+           SV * const right = (SV*)cx->blk_loop.iterary;
            SvGETMAGIC(sv);
            SvGETMAGIC(right);
            if (RANGE_IS_NUMERIC(sv,right)) {
@@ -1854,7 +1925,7 @@ PP(pp_leaveloop)
 
     TAINT_NOT;
     if (gimme == G_VOID)
-       ; /* do nothing */
+       /*EMPTY*/; /* do nothing */
     else if (gimme == G_SCALAR) {
        if (mark < SP)
            *++newsp = sv_mortalcopy(*SP);
@@ -1882,7 +1953,6 @@ PP(pp_leaveloop)
 PP(pp_return)
 {
     dVAR; dSP; dMARK;
-    I32 cxix;
     register PERL_CONTEXT *cx;
     bool popsub2 = FALSE;
     bool clear_errsv = FALSE;
@@ -1893,7 +1963,8 @@ PP(pp_return)
     SV *sv;
     OP *retop;
 
-    cxix = dopoptosub(cxstack_ix);
+    const I32 cxix = dopoptosub(cxstack_ix);
+
     if (cxix < 0) {
        if (CxMULTICALL(cxstack)) { /* In this case we must be in a
                                     * sort block, which is a CXt_NULL
@@ -1994,7 +2065,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);
@@ -2015,7 +2086,7 @@ PP(pp_last)
     SV **newsp;
     PMOP *newpm;
     SV **mark;
-    SV *sv = Nullsv;
+    SV *sv = NULL;
 
 
     if (PL_op->op_flags & OPf_SPECIAL) {
@@ -2164,6 +2235,7 @@ 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";
 
@@ -2211,12 +2283,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";
 
@@ -2247,14 +2319,14 @@ PP(pp_goto)
                    if (autogv && (cv = GvCV(autogv)))
                        goto retry;
                    tmpstr = sv_newmortal();
-                   gv_efullname3(tmpstr, gv, Nullch);
+                   gv_efullname3(tmpstr, gv, NULL);
                    DIE(aTHX_ "Goto undefined subroutine &%"SVf"",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)
@@ -2292,7 +2364,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. */
@@ -2309,47 +2381,27 @@ 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<items; index++)
                        sv_2mortal(SP[-index]);
                }
-#ifdef PERL_XSUB_OLDSTYLE
-               if (CvOLDSTYLE(cv)) {
-                   I32 (*fp3)(int,int,int);
-                   while (SP > 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_eval_root = cx->blk_eval.old_eval_root;
@@ -2357,11 +2409,11 @@ PP(pp_goto)
                    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_void_NN(cv);
                else {
                    if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
                        sub_crush_depth(cv);
@@ -2371,16 +2423,15 @@ PP(pp_goto)
                PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv));
                if (cx->blk_sub.hasargs)
                {
-                   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);
@@ -2413,8 +2464,6 @@ PP(pp_goto)
                     * 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);
@@ -2423,13 +2472,15 @@ PP(pp_goto)
                        (void)SvIOK_on(sv);
                        SvIV_set(sv, PTR2IV(cv)); /* Do it the quickest way */
                    } else {
-                       gv_efullname3(sv, CvGV(cv), Nullch);
+                       gv_efullname3(sv, CvGV(cv), NULL);
                    }
-                   if (  PERLDB_GOTO
-                         && (gotocv = get_cv("DB::goto", FALSE)) ) {
-                       PUSHMARK( PL_stack_sp );
-                       call_sv((SV*)gotocv, G_SCALAR | G_NODEBUG);
-                       PL_stack_sp--;
+                   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));
@@ -2449,14 +2500,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];
@@ -2536,7 +2587,7 @@ PP(pp_goto)
        /* push wanted frames */
 
        if (*enterops && enterops[1]) {
-           OP *oldop = PL_op;
+           OP * const oldop = PL_op;
            ix = enterops[1]->op_type == OP_ENTER && in_block ? 2 : 1;
            for (; enterops[ix]; ix++) {
                PL_op = enterops[ix];
@@ -2568,6 +2619,7 @@ PP(pp_goto)
 
 PP(pp_exit)
 {
+    dVAR;
     dSP;
     I32 anum;
 
@@ -2582,51 +2634,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
@@ -2638,7 +2656,7 @@ S_save_lines(pTHX_ AV *array, SV *sv)
 
     while (s && s < send) {
        const char *t;
-       SV * const tmpstr = NEWSV(85,0);
+       SV * const tmpstr = newSV(0);
 
        sv_upgrade(tmpstr, SVt_PVMG);
        t = strchr(s, '\n');
@@ -2656,6 +2674,7 @@ S_save_lines(pTHX_ AV *array, SV *sv)
 STATIC void
 S_docatch_body(pTHX)
 {
+    dVAR;
     CALLRUNOPS(aTHX);
     return;
 }
@@ -2663,6 +2682,7 @@ S_docatch_body(pTHX)
 STATIC OP *
 S_docatch(pTHX_ OP *o)
 {
+    dVAR;
     int ret;
     OP * const oldop = PL_op;
     dJMPENV;
@@ -2707,7 +2727,7 @@ S_docatch(pTHX_ OP *o)
     }
     JMPENV_POP;
     PL_op = oldop;
-    return Nullop;
+    return NULL;
 }
 
 OP *
@@ -2728,7 +2748,7 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, const char *code, PAD** padp)
     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;
 
     ENTER;
@@ -2778,7 +2798,7 @@ 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, NULL);
 
     if (runtime)
        rop = doeval(G_SCALAR, startop, runcv, PL_curcop->cop_seq);
@@ -2791,10 +2811,10 @@ 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
@@ -2820,6 +2840,7 @@ than in the scope of the debugger itself).
 CV*
 Perl_find_runcv(pTHX_ U32 *db_seqp)
 {
+    dVAR;
     PERL_SI     *si;
 
     if (db_seqp)
@@ -2865,21 +2886,22 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     PUSHMARK(SP);
 
     SAVESPTR(PL_compcv);
-    PL_compcv = (CV*)NEWSV(1104,0);
+    PL_compcv = (CV*)newSV(0);
     sv_upgrade((SV *)PL_compcv, 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);
 
 
-    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 */
 
@@ -2892,13 +2914,18 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
     SAVEFREESV(PL_beginav);
     SAVEI32(PL_error_count);
 
+#ifdef PERL_MAD
+    SAVEI32(PL_madskills);
+    PL_madskills = 0;
+#endif
+
     /* try to compile it */
 
-    PL_eval_root = Nullop;
+    PL_eval_root = NULL;
     PL_error_count = 0;
     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);
@@ -2911,7 +2938,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) {
@@ -2989,6 +3016,18 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
 }
 
 STATIC PerlIO *
+S_check_type_and_open(pTHX_ const char *name, const char *mode)
+{
+    Stat_t st;
+    const int st_rc = PerlLIO_stat(name, &st);
+    if (st_rc < 0 || S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
+       return NULL;
+    }
+
+    return PerlIO_open(name, mode);
+}
+
+STATIC PerlIO *
 S_doopen_pm(pTHX_ const char *name, const char *mode)
 {
 #ifndef PERL_DISABLE_PMC
@@ -3000,27 +3039,19 @@ S_doopen_pm(pTHX_ const char *name, const char *mode)
        const char * const pmc = SvPV_nolen_const(pmcsv);
        Stat_t pmcstat;
        if (PerlLIO_stat(pmc, &pmcstat) < 0) {
-           fp = PerlIO_open(name, mode);
+           fp = check_type_and_open(name, mode);
        }
        else {
-           Stat_t pmstat;
-           if (PerlLIO_stat(name, &pmstat) < 0 ||
-               pmstat.st_mtime < pmcstat.st_mtime)
-           {
-               fp = PerlIO_open(pmc, mode);
-           }
-           else {
-               fp = PerlIO_open(name, mode);
-           }
+           fp = check_type_and_open(pmc, mode);
        }
        SvREFCNT_dec(pmcsv);
     }
     else {
-       fp = PerlIO_open(name, mode);
+       fp = check_type_and_open(name, mode);
     }
     return fp;
 #else
-    return PerlIO_open(name, mode);
+    return check_type_and_open(name, mode);
 #endif /* !PERL_DISABLE_PMC */
 }
 
@@ -3031,15 +3062,15 @@ PP(pp_require)
     SV *sv;
     const char *name;
     STRLEN len;
-    const char *tryname = Nullch;
-    SV *namesv = Nullsv;
+    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;
+    GV *filter_child_proc = NULL;
+    SV *filter_state = NULL;
+    SV *filter_sub = NULL;
+    SV *hook_sv = NULL;
     SV *encoding;
     OP *op;
 
@@ -3051,7 +3082,7 @@ PP(pp_require)
 
        sv = new_version(sv);
        if (!sv_derived_from(PL_patchlevel, "version"))
-           (void *)upg_version(PL_patchlevel);
+           upg_version(PL_patchlevel);
        if (cUNOP->op_first->op_type == OP_CONST && cUNOP->op_first->op_private & OPpCONST_NOVER) {
            if ( vcmp(sv,PL_patchlevel) < 0 )
                DIE(aTHX_ "Perls since %"SVf" too modern--this is %"SVf", stopped",
@@ -3070,7 +3101,7 @@ PP(pp_require)
        DIE(aTHX_ "Null filename used");
     TAINT_PROPER("require");
     if (PL_op->op_type == OP_REQUIRE) {
-       SV ** const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
+       SV * const * const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
        if ( svp ) {
            if (*svp != &PL_sv_undef)
                RETPUSHYES;
@@ -3101,10 +3132,10 @@ PP(pp_require)
        I32 i;
 #ifdef VMS
        char *unixname;
-       if ((unixname = tounixspec(name, Nullch)) != Nullch)
+       if ((unixname = tounixspec(name, NULL)) != NULL)
 #endif
        {
-           namesv = NEWSV(806, 0);
+           namesv = newSV(0);
            for (i = 0; i <= AvFILL(ar); i++) {
                SV *dirsv = *av_fetch(ar, i, TRUE);
 
@@ -3121,7 +3152,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;
@@ -3163,14 +3194,14 @@ PP(pp_require)
                                       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);
+                                   SvREFCNT_inc_simple_void(filter_child_proc);
                                }
                                else {
                                    if (IoOFP(io) && IoOFP(io) != IoIFP(io)) {
                                        PerlIO_close(IoOFP(io));
                                    }
-                                   IoIFP(io) = Nullfp;
-                                   IoOFP(io) = Nullfp;
+                                   IoIFP(io) = NULL;
+                                   IoOFP(io) = NULL;
                                }
                            }
 
@@ -3181,16 +3212,15 @@ PP(pp_require)
 
                        if (SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVCV) {
                            filter_sub = arg;
-                           (void)SvREFCNT_inc(filter_sub);
+                           SvREFCNT_inc_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) {
+                               tryrsfp = PerlIO_open("/dev/null", PERL_SCRIPT_MODE);
                            }
                        }
                        SP--;
@@ -3208,15 +3238,15 @@ PP(pp_require)
                    filter_has_file = 0;
                    if (filter_child_proc) {
                        SvREFCNT_dec(filter_child_proc);
-                       filter_child_proc = 0;
+                       filter_child_proc = 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 {
@@ -3238,7 +3268,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);
@@ -3280,29 +3310,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);
                }    
            }
@@ -3322,32 +3351,34 @@ PP(pp_require)
     } else {
        SV** const svp = hv_fetch(GvHVn(PL_incgv), name, len, 0);
        if (!svp)
-           (void)hv_store(GvHVn(PL_incgv), name, len, SvREFCNT_inc(hook_sv), 0 );
+           (void)hv_store(GvHVn(PL_incgv), name, len, SvREFCNT_inc_simple(hook_sv), 0 );
     }
 
     ENTER;
     SAVETMPS;
-    lex_start(sv_2mortal(newSVpvn("",0)));
+    lex_start(sv_2mortal(newSVpvs("")));
     SAVEGENERICSV(PL_rsfp_filters);
-    PL_rsfp_filters = Nullav;
+    PL_rsfp_filters = NULL;
 
     PL_rsfp = tryrsfp;
     SAVEHINTS();
     PL_hints = 0;
-    SAVESPTR(PL_compiling.cop_warnings);
+    SAVECOPWARNINGS(&PL_compiling);
     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 if (PL_taint_warn) {
+        PL_compiling.cop_warnings
+           = Perl_new_warnings_bitfield(aTHX_ NULL, WARN_TAINTstring, WARNsize);
+    }
     else
         PL_compiling.cop_warnings = pWARN_STD ;
     SAVESPTR(PL_compiling.cop_io);
-    PL_compiling.cop_io = Nullsv;
+    PL_compiling.cop_io = NULL;
 
     if (filter_sub || filter_child_proc) {
-       SV * const datasv = filter_add(run_user_filter, Nullsv);
+       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;
@@ -3356,7 +3387,7 @@ PP(pp_require)
 
     /* switch to eval mode */
     PUSHBLOCK(cx, CXt_EVAL, SP);
-    PUSHEVAL(cx, name, Nullgv);
+    PUSHEVAL(cx, name, NULL);
     cx->blk_eval.retop = PL_op->op_next;
 
     SAVECOPLINE(&PL_compiling);
@@ -3366,9 +3397,9 @@ 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));
+    op = DOCATCH(doeval(gimme, NULL, NULL, PL_curcop->cop_seq));
 
     /* Restore encoding. */
     PL_encoding = encoding;
@@ -3380,7 +3411,7 @@ 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];
@@ -3390,6 +3421,12 @@ PP(pp_entereval)
     OP *ret;
     CV* runcv;
     U32 seq;
+    HV *saved_hh = NULL;
+    
+    if (PL_op->op_private & OPpEVAL_HAS_HH) {
+       saved_hh = (HV*) SvREFCNT_inc(POPs);
+    }
+    sv = POPs;
 
     if (!SvPV_nolen_const(sv))
        RETPUSHUNDEF;
@@ -3402,12 +3439,12 @@ PP(pp_entereval)
     /* 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);
@@ -3424,13 +3461,10 @@ 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;
+    SAVECOPWARNINGS(&PL_compiling);
+    PL_compiling.cop_warnings = DUP_WARNINGS(PL_curcop->cop_warnings);
     SAVESPTR(PL_compiling.cop_io);
     if (specialCopIO(PL_curcop->cop_io))
         PL_compiling.cop_io = PL_curcop->cop_io;
@@ -3438,6 +3472,15 @@ PP(pp_entereval)
         PL_compiling.cop_io = newSVsv(PL_curcop->cop_io);
         SAVEFREESV(PL_compiling.cop_io);
     }
+    if (PL_compiling.cop_hints) {
+       Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints);
+    }
+    PL_compiling.cop_hints = PL_curcop->cop_hints;
+    if (PL_compiling.cop_hints) {
+       HINTS_REFCNT_LOCK;
+       PL_compiling.cop_hints->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
      * allows the debugger to execute code, find lexicals etc, in the
@@ -3446,7 +3489,7 @@ PP(pp_entereval)
     runcv = find_runcv(&seq);
 
     PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
-    PUSHEVAL(cx, 0, Nullgv);
+    PUSHEVAL(cx, 0, NULL);
     cx->blk_eval.retop = PL_op->op_next;
 
     /* prepare to compile string */
@@ -3530,29 +3573,63 @@ 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);
+    PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), PL_stack_sp);
     PUSHEVAL(cx, 0, 0);
-    cx->blk_eval.retop = cLOGOP->op_other->op_next;
+    PL_eval_root = PL_op;      /* Only needed so that goto works right. */
 
     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 *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;
@@ -3567,6 +3644,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))
@@ -3582,6 +3660,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);
@@ -3596,20 +3675,627 @@ 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);
+    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;
+    
+    PL_op = (OP *) matcher;
+    XPUSHs(sv);
+    PUTBACK;
+    (void) pp_match();
+    SPAGAIN;
+    return (SvTRUEx(POPs));
+}
+
+STATIC
+void
+S_destroy_matcher(pTHX_ PMOP *matcher)
+{
+    dVAR;
+    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 following
+   table of smart matches:
+    
+    $a      $b        Type of Match Implied    Matching Code
+    ======  =====     =====================    =============
+    (overloading trumps everything)
+
+    Code[+] Code[+]   referential equality     match if refaddr($a) == refaddr($b)
+    Any     Code[+]   scalar sub truth         match if $b->($a)
+
+    Hash    Hash      hash keys identical      match if sort(keys(%$a)) ÃˆeqÇ sort(keys(%$b))
+    Hash    Array     hash value slice truth   match if $a->{any(@$b)}
+    Hash    Regex     hash key grep            match if any(keys(%$a)) =~ /$b/
+    Hash    Any       hash entry existence     match if exists $a->{$b}
+
+    Array   Array     arrays are identical[*]  match if $a Ãˆ~~Ç $b
+    Array   Regex     array grep               match if any(@$a) =~ /$b/
+    Array   Num       array contains number    match if any($a) == $b
+    Array   Any       array contains string    match if any($a) eq $b
+
+    Any     undef     undefined                match if !defined $a
+    Any     Regex     pattern match            match if $a =~ /$b/
+    Code()  Code()    results are equal        match if $a->() eq $b->()
+    Any     Code()    simple closure truth     match if $b->() (ignoring $a)
+    Num     numish[!] numeric equality         match if $a == $b
+    Any     Str       string equality          match if $a eq $b
+    Any     Num       numeric equality         match if $a == $b
+
+    Any     Any       string equality          match if $a eq $b
+
+
+ + - this must be a code reference whose prototype (if present) is not ""
+     (subs with a "" prototype are dealt with by the 'Code()' entry lower down)
+ * - if a circular reference is found, we fall back to referential equality
+ ! - either a real number, or a string that looks_like_number()
+
+ */
+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;
+    MAGIC *mg;
+    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) && SvMAGICAL(this = SvRV(d))                       \
+       && (mg = mg_find(this, PERL_MAGIC_qr))                          \
+       && (this_regex = (regexp *)mg->mg_obj)                          \
+       && (other = e))                                                 \
+    ||                                                                 \
+          (SvROK(e) && SvMAGICAL(this = SvRV(e))                       \
+       && (mg = mg_find(this, PERL_MAGIC_qr))                          \
+       && (this_regex = (regexp *)mg->mg_obj)                          \
+       && (other = d)) )
+       
+
+#   define SM_OTHER_REF(type) \
+       (SvROK(other) && SvTYPE(SvRV(other)) == SVt_##type)
+
+#   define SM_OTHER_REGEX (SvROK(other) && SvMAGICAL(SvRV(other))      \
+       && (mg = mg_find(SvRV(other), PERL_MAGIC_qr))                   \
+       && (other_regex = (regexp *)mg->mg_obj))
+       
+
+#   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(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;
+           
+           if (HvUSEDKEYS((HV *) this) != other_len)
+               RETPUSHNO;
+           
+           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 happen? */
+                   RETPUSHNO;
+
+               key = SvPV(*svp, key_len);
+               if(!hv_exists((HV *) this, key, key_len))
+                   RETPUSHNO;
+           }
+           RETPUSHYES;
+       }
+       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 {
+                       hv_store_ent(seen_this,
+                           sv_2mortal(newSViv(PTR2IV(*this_elem))),
+                           &PL_sv_undef, 0);
+                       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(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(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->blk_loop.next_op;
+    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;
@@ -3624,7 +4310,7 @@ S_doparseform(pTHX_ SV *sv)
            maxops += 10;
     }
     s = base;
-    base = Nullch;
+    base = NULL;
 
     Newx(fops, maxops, U32);
     fpc = fops;
@@ -3805,7 +4491,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)
@@ -3842,14 +4528,14 @@ S_num_overflow(NV value, I32 fldsize, I32 frcsize)
 }
 
 static I32
-run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
+S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 {
     dVAR;
-    SV *datasv = FILTER_DATA(idx);
+    SV * const datasv = FILTER_DATA(idx);
     const int filter_has_file = IoLINES(datasv);
-    GV *filter_child_proc = (GV *)IoFMT_GV(datasv);
-    SV *filter_state = (SV *)IoTOP_GV(datasv);
-    SV *filter_sub = (SV *)IoBOTTOM_GV(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;
 
     /* I was having segfault trouble under Linux 2.2.5 after a
@@ -3896,17 +4582,17 @@ run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
        IoLINES(datasv) = 0;
        if (filter_child_proc) {
            SvREFCNT_dec(filter_child_proc);
-           IoFMT_GV(datasv) = Nullgv;
+           IoFMT_GV(datasv) = NULL;
        }
        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(run_user_filter);
+       filter_del(S_run_user_filter);
     }
 
     return len;
@@ -3915,15 +4601,16 @@ run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 /* 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)
 {
     if (PERL_FILE_IS_ABSOLUTE(name)
 #ifdef MACOS_TRADITIONAL
-       || (*name == ':'))
+       || (*name == ':')
 #else
        || (*name == '.' && (name[1] == '/' ||
-                            (name[1] == '.' && name[2] == '/'))))
+                            (name[1] == '.' && name[2] == '/')))
 #endif
+        )
     {
        return TRUE;
     }