This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Proper fix for CvOUTSIDE weak refcounting
[perl5.git] / pp_ctl.c
index f64b18d..143888d 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1,6 +1,6 @@
 /*    pp_ctl.c
  *
- *    Copyright (c) 1991-2001, Larry Wall
+ *    Copyright (c) 1991-2002, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
 
 #define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o))
 
-static I32 sortcv(pTHXo_ SV *a, SV *b);
-static I32 sortcv_stacked(pTHXo_ SV *a, SV *b);
-static I32 sortcv_xsub(pTHXo_ SV *a, SV *b);
-static I32 sv_ncmp(pTHXo_ SV *a, SV *b);
-static I32 sv_i_ncmp(pTHXo_ SV *a, SV *b);
-static I32 amagic_ncmp(pTHXo_ SV *a, SV *b);
-static I32 amagic_i_ncmp(pTHXo_ SV *a, SV *b);
-static I32 amagic_cmp(pTHXo_ SV *a, SV *b);
-static I32 amagic_cmp_locale(pTHXo_ SV *a, SV *b);
-static I32 run_user_filter(pTHXo_ int idx, SV *buf_sv, int maxlen);
-
-#ifdef PERL_OBJECT
-static I32 sv_cmp_static(pTHXo_ SV *a, SV *b);
-static I32 sv_cmp_locale_static(pTHXo_ SV *a, SV *b);
-#else
-#define sv_cmp_static Perl_sv_cmp
-#define sv_cmp_locale_static Perl_sv_cmp_locale
-#endif
+static I32 run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen);
 
 PP(pp_wantarray)
 {
@@ -90,7 +73,7 @@ PP(pp_regcomp)
     tmpstr = POPs;
 
     /* prevent recompiling under /o and ithreads. */
-#if defined(USE_ITHREADS) || defined(USE_5005THREADS)
+#if defined(USE_ITHREADS)
     if (pm->op_pmflags & PMf_KEEP && PM_GETRE(pm))
         RETURN;
 #endif
@@ -110,7 +93,7 @@ PP(pp_regcomp)
 
        /* Check against the last compiled regexp. */
        if (!PM_GETRE(pm) || !PM_GETRE(pm)->precomp ||
-           PM_GETRE(pm)->prelen != len ||
+           PM_GETRE(pm)->prelen != (I32)len ||
            memNE(PM_GETRE(pm)->precomp, t, len))
        {
            if (PM_GETRE(pm)) {
@@ -155,7 +138,7 @@ PP(pp_regcomp)
     /* XXX runtime compiled output needs to move to the pad */
     if (pm->op_pmflags & PMf_KEEP) {
        pm->op_private &= ~OPpRUNTIME;  /* no point compiling again */
-#if !defined(USE_ITHREADS) && !defined(USE_5005THREADS)
+#if !defined(USE_ITHREADS)
        /* XXX can't change the optree at runtime either */
        cLOGOP->op_first->op_next = PL_op->op_next;
 #endif
@@ -175,8 +158,10 @@ PP(pp_substcont)
     register REGEXP *rx = cx->sb_rx;
 
     rxres_restore(&cx->sb_rxres, rx);
+    PL_reg_match_utf8 = SvUTF8(cx->sb_targ) ? 1 : 0;
 
     if (cx->sb_iters++) {
+       I32 saviters = cx->sb_iters;
        if (cx->sb_iters > cx->sb_maxiters)
            DIE(aTHX_ "Substitution loop");
 
@@ -218,6 +203,7 @@ PP(pp_substcont)
            POPSUBST(cx);
            RETURNOP(pm->op_next);
        }
+       cx->sb_iters = saviters;
     }
     if (RX_MATCH_COPIED(rx) && rx->subbeg != orig) {
        m = s;
@@ -410,7 +396,7 @@ PP(pp_formline)
            else {
                sv = &PL_sv_no;
                if (ckWARN(WARN_SYNTAX))
-                   Perl_warner(aTHX_ WARN_SYNTAX, "Not enough format arguments");
+                   Perl_warner(aTHX_ packWARN(WARN_SYNTAX), "Not enough format arguments");
            }
            break;
 
@@ -419,7 +405,7 @@ PP(pp_formline)
            itemsize = len;
            if (DO_UTF8(sv)) {
                itemsize = sv_len_utf8(sv);
-               if (itemsize != len) {
+               if (itemsize != (I32)len) {
                    I32 itembytes;
                    if (itemsize > fieldsize) {
                        itemsize = fieldsize;
@@ -461,7 +447,7 @@ PP(pp_formline)
            itemsize = len;
            if (DO_UTF8(sv)) {
                itemsize = sv_len_utf8(sv);
-               if (itemsize != len) {
+               if (itemsize != (I32)len) {
                    I32 itembytes;
                    if (itemsize <= fieldsize) {
                        send = chophere = s + itemsize;
@@ -850,7 +836,7 @@ PP(pp_mapwhile)
        }
        /* copy the new items down to the destination list */
        dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1;
-       while (items--)
+       while (items-- > 0)
            *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs);
     }
     LEAVE;                                     /* exit inner scope */
@@ -888,179 +874,6 @@ PP(pp_mapwhile)
     }
 }
 
-PP(pp_sort)
-{
-    dSP; dMARK; dORIGMARK;
-    register SV **up;
-    SV **myorigmark = ORIGMARK;
-    register I32 max;
-    HV *stash;
-    GV *gv;
-    CV *cv = 0;
-    I32 gimme = GIMME;
-    OP* nextop = PL_op->op_next;
-    I32 overloading = 0;
-    bool hasargs = FALSE;
-    I32 is_xsub = 0;
-
-    if (gimme != G_ARRAY) {
-       SP = MARK;
-       RETPUSHUNDEF;
-    }
-
-    ENTER;
-    SAVEVPTR(PL_sortcop);
-    if (PL_op->op_flags & OPf_STACKED) {
-       if (PL_op->op_flags & OPf_SPECIAL) {
-           OP *kid = cLISTOP->op_first->op_sibling;    /* pass pushmark */
-           kid = kUNOP->op_first;                      /* pass rv2gv */
-           kid = kUNOP->op_first;                      /* pass leave */
-           PL_sortcop = kid->op_next;
-           stash = CopSTASH(PL_curcop);
-       }
-       else {
-           cv = sv_2cv(*++MARK, &stash, &gv, 0);
-           if (cv && SvPOK(cv)) {
-               STRLEN n_a;
-               char *proto = SvPV((SV*)cv, n_a);
-               if (proto && strEQ(proto, "$$")) {
-                   hasargs = TRUE;
-               }
-           }
-           if (!(cv && CvROOT(cv))) {
-               if (cv && CvXSUB(cv)) {
-                   is_xsub = 1;
-               }
-               else if (gv) {
-                   SV *tmpstr = sv_newmortal();
-                   gv_efullname3(tmpstr, gv, Nullch);
-                   DIE(aTHX_ "Undefined sort subroutine \"%s\" called",
-                       SvPVX(tmpstr));
-               }
-               else {
-                   DIE(aTHX_ "Undefined subroutine in sort");
-               }
-           }
-
-           if (is_xsub)
-               PL_sortcop = (OP*)cv;
-           else {
-               PL_sortcop = CvSTART(cv);
-               SAVEVPTR(CvROOT(cv)->op_ppaddr);
-               CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];
-
-               SAVEVPTR(PL_curpad);
-               PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
-            }
-       }
-    }
-    else {
-       PL_sortcop = Nullop;
-       stash = CopSTASH(PL_curcop);
-    }
-
-    up = myorigmark + 1;
-    while (MARK < SP) {        /* This may or may not shift down one here. */
-       /*SUPPRESS 560*/
-       if ((*up = *++MARK)) {                  /* Weed out nulls. */
-           SvTEMP_off(*up);
-           if (!PL_sortcop && !SvPOK(*up)) {
-               STRLEN n_a;
-               if (SvAMAGIC(*up))
-                   overloading = 1;
-               else
-                   (void)sv_2pv(*up, &n_a);
-           }
-           up++;
-       }
-    }
-    max = --up - myorigmark;
-    if (PL_sortcop) {
-       if (max > 1) {
-           PERL_CONTEXT *cx;
-           SV** newsp;
-           bool oldcatch = CATCH_GET;
-
-           SAVETMPS;
-           SAVEOP();
-
-           CATCH_SET(TRUE);
-           PUSHSTACKi(PERLSI_SORT);
-           if (!hasargs && !is_xsub) {
-               if (PL_sortstash != stash || !PL_firstgv || !PL_secondgv) {
-                   SAVESPTR(PL_firstgv);
-                   SAVESPTR(PL_secondgv);
-                   PL_firstgv = gv_fetchpv("a", TRUE, SVt_PV);
-                   PL_secondgv = gv_fetchpv("b", TRUE, SVt_PV);
-                   PL_sortstash = stash;
-               }
-#ifdef USE_5005THREADS
-               sv_lock((SV *)PL_firstgv);
-               sv_lock((SV *)PL_secondgv);
-#endif
-               SAVESPTR(GvSV(PL_firstgv));
-               SAVESPTR(GvSV(PL_secondgv));
-           }
-
-           PUSHBLOCK(cx, CXt_NULL, PL_stack_base);
-           if (!(PL_op->op_flags & OPf_SPECIAL)) {
-               cx->cx_type = CXt_SUB;
-               cx->blk_gimme = G_SCALAR;
-               PUSHSUB(cx);
-               if (!CvDEPTH(cv))
-                   (void)SvREFCNT_inc(cv); /* in preparation for POPSUB */
-           }
-           PL_sortcxix = cxstack_ix;
-
-           if (hasargs && !is_xsub) {
-               /* This is mostly copied from pp_entersub */
-               AV *av = (AV*)PL_curpad[0];
-
-#ifndef USE_5005THREADS
-               cx->blk_sub.savearray = GvAV(PL_defgv);
-               GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av);
-#endif /* USE_5005THREADS */
-               cx->blk_sub.oldcurpad = PL_curpad;
-               cx->blk_sub.argarray = av;
-           }
-           qsortsv((myorigmark+1), max,
-                   is_xsub ? sortcv_xsub : hasargs ? sortcv_stacked : sortcv);
-
-           POPBLOCK(cx,PL_curpm);
-           PL_stack_sp = newsp;
-           POPSTACK;
-           CATCH_SET(oldcatch);
-       }
-    }
-    else {
-       if (max > 1) {
-           MEXTEND(SP, 20);    /* Can't afford stack realloc on signal. */
-           qsortsv(ORIGMARK+1, max,
-                   (PL_op->op_private & OPpSORT_NUMERIC)
-                       ? ( (PL_op->op_private & OPpSORT_INTEGER)
-                           ? ( overloading ? amagic_i_ncmp : sv_i_ncmp)
-                           : ( overloading ? amagic_ncmp : sv_ncmp))
-                       : ( IN_LOCALE_RUNTIME
-                           ? ( overloading
-                               ? amagic_cmp_locale
-                               : sv_cmp_locale_static)
-                           : ( overloading ? amagic_cmp : sv_cmp_static)));
-           if (PL_op->op_private & OPpSORT_REVERSE) {
-               SV **p = ORIGMARK+1;
-               SV **q = ORIGMARK+max;
-               while (p < q) {
-                   SV *tmp = *p;
-                   *p++ = *q;
-                   *q-- = tmp;
-               }
-           }
-       }
-    }
-    LEAVE;
-    PL_stack_sp = ORIGMARK + max;
-    return nextop;
-}
-
 /* Range stuff. */
 
 PP(pp_range)
@@ -1083,13 +896,16 @@ PP(pp_flip)
     else {
        dTOPss;
        SV *targ = PAD_SV(PL_op->op_targ);
-       int flip;
+       int flip = 0;
 
        if (PL_op->op_private & OPpFLIP_LINENUM) {
-           struct io *gp_io;
-           flip = PL_last_in_gv
-               && (gp_io = GvIO(PL_last_in_gv))
-               && SvIV(sv) == (IV)IoLINES(gp_io);
+           if (GvIO(PL_last_in_gv)) {
+               flip = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv));
+           }
+           else {
+               GV *gv = gv_fetchpv(".", TRUE, SVt_PV);
+               if (gv && GvSV(gv)) flip = SvIV(sv) == SvIV(GvSV(gv));
+           }
        } else {
            flip = SvTRUE(sv);
        }
@@ -1127,10 +943,14 @@ PP(pp_flop)
        if (SvGMAGICAL(right))
            mg_get(right);
 
+       /* This code tries to decide if "$left .. $right" should use the
+          magical string increment, or if the range is numeric (we make
+          an exception for .."0" [#18165]). AMS 20021031. */
+
        if (SvNIOKp(left) || !SvPOKp(left) ||
            SvNIOKp(right) || !SvPOKp(right) ||
            (looks_like_number(left) && *SvPVX(left) != '0' &&
-            looks_like_number(right) && *SvPVX(right) != '0'))
+            looks_like_number(right)))
        {
            if (SvNV(left) < IV_MIN || SvNV(right) > IV_MAX)
                DIE(aTHX_ "Range iterator outside integer range");
@@ -1167,11 +987,23 @@ PP(pp_flop)
     else {
        dTOPss;
        SV *targ = PAD_SV(cUNOP->op_first->op_targ);
+       int flop = 0;
        sv_inc(targ);
-       if ((PL_op->op_private & OPpFLIP_LINENUM)
-         ? (GvIO(PL_last_in_gv)
-            && SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv)))
-         : SvTRUE(sv) ) {
+
+       if (PL_op->op_private & OPpFLIP_LINENUM) {
+           if (GvIO(PL_last_in_gv)) {
+               flop = SvIV(sv) == (IV)IoLINES(GvIOp(PL_last_in_gv));
+           }
+           else {
+               GV *gv = gv_fetchpv(".", TRUE, SVt_PV);
+               if (gv && GvSV(gv)) flop = SvIV(sv) == SvIV(GvSV(gv));
+           }
+       }
+       else {
+           flop = SvTRUE(sv);
+       }
+
+       if (flop) {
            sv_setiv(PAD_SV(((UNOP*)cUNOP->op_first)->op_first->op_targ), 0);
            sv_catpv(targ, "E0");
        }
@@ -1194,27 +1026,27 @@ S_dopoptolabel(pTHX_ char *label)
        switch (CxTYPE(cx)) {
        case CXt_SUBST:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting substitution via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting substitution via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_SUB:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting subroutine via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting subroutine via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_FORMAT:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting format via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting format via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_EVAL:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting eval via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting eval via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_NULL:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting pseudo-block via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting pseudo-block via %s",
                        OP_NAME(PL_op));
            return -1;
        case CXt_LOOP:
@@ -1329,27 +1161,27 @@ S_dopoptoloop(pTHX_ I32 startingblock)
        switch (CxTYPE(cx)) {
        case CXt_SUBST:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting substitution via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting substitution via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_SUB:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting subroutine via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting subroutine via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_FORMAT:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting format via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting format via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_EVAL:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting eval via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting eval via %s",
                        OP_NAME(PL_op));
            break;
        case CXt_NULL:
            if (ckWARN(WARN_EXITING))
-               Perl_warner(aTHX_ WARN_EXITING, "Exiting pseudo-block via %s",
+               Perl_warner(aTHX_ packWARN(WARN_EXITING), "Exiting pseudo-block via %s",
                        OP_NAME(PL_op));
            return -1;
        case CXt_LOOP:
@@ -1412,6 +1244,9 @@ OP *
 Perl_die_where(pTHX_ char *message, STRLEN msglen)
 {
     STRLEN n_a;
+    IO *io;
+    MAGIC *mg;
+
     if (PL_in_eval) {
        I32 cxix;
        register PERL_CONTEXT *cx;
@@ -1437,7 +1272,7 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen)
                    sv_catpvn(err, message, msglen);
                    if (ckWARN(WARN_MISC)) {
                        STRLEN start = SvCUR(err)-msglen-sizeof(prefix)+1;
-                       Perl_warner(aTHX_ WARN_MISC, SvPVX(err)+start);
+                       Perl_warner(aTHX_ packWARN(WARN_MISC), SvPVX(err)+start);
                    }
                }
            }
@@ -1491,14 +1326,26 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen)
     }
     if (!message)
        message = SvPVx(ERRSV, msglen);
-    {
+
+    /* if STDERR is tied, print to it instead */
+    if (PL_stderrgv && (io = GvIOp(PL_stderrgv))
+       && (mg = SvTIED_mg((SV*)io, PERL_MAGIC_tiedscalar))) {
+       dSP; ENTER;
+       PUSHMARK(SP);
+       XPUSHs(SvTIED_obj((SV*)io, mg));
+       XPUSHs(sv_2mortal(newSVpvn(message, msglen)));
+       PUTBACK;
+       call_method("PRINT", G_SCALAR);
+       LEAVE;
+    }
+    else {
 #ifdef USE_SFIO
        /* SFIO can really mess with your errno */
        int e = errno;
 #endif
        PerlIO *serr = Perl_error_log;
 
-       PerlIO_write(serr, message, msglen);
+       PERL_WRITE_MSG_TO_CONSOLE(serr, message, msglen);
        (void)PerlIO_flush(serr);
 #ifdef USE_SFIO
        errno = e;
@@ -1535,7 +1382,40 @@ PP(pp_orassign)
     else
        RETURNOP(cLOGOP->op_other);
 }
-       
+
+PP(pp_dorassign)
+{
+    dSP;
+    register SV* sv;
+
+    sv = TOPs;
+    if (!sv || !SvANY(sv)) {
+       RETURNOP(cLOGOP->op_other);
+    }
+
+    switch (SvTYPE(sv)) {
+    case SVt_PVAV:
+       if (AvMAX(sv) >= 0 || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+           RETURN;
+       break;
+    case SVt_PVHV:
+       if (HvARRAY(sv) || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+           RETURN;
+       break;
+    case SVt_PVCV:
+       if (CvROOT(sv) || CvXSUB(sv))
+           RETURN;
+       break;
+    default:
+       if (SvGMAGICAL(sv))
+           mg_get(sv);
+       if (SvOK(sv))
+           RETURN;
+    }
+
+    RETURNOP(cLOGOP->op_other);
+}
+
 PP(pp_caller)
 {
     dSP;
@@ -1602,16 +1482,23 @@ PP(pp_caller)
        PUSHs(&PL_sv_undef);
     else
        PUSHs(sv_2mortal(newSVpv(stashname, 0)));
-    PUSHs(sv_2mortal(newSVpv(CopFILE(cx->blk_oldcop), 0)));
+    PUSHs(sv_2mortal(newSVpv(OutCopFILE(cx->blk_oldcop), 0)));
     PUSHs(sv_2mortal(newSViv((I32)CopLINE(cx->blk_oldcop))));
     if (!MAXARG)
        RETURN;
     if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
+       GV *cvgv = CvGV(ccstack[cxix].blk_sub.cv);
        /* So is ccstack[dbcxix]. */
-       sv = NEWSV(49, 0);
-       gv_efullname3(sv, CvGV(ccstack[cxix].blk_sub.cv), Nullch);
-       PUSHs(sv_2mortal(sv));
-       PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
+       if (isGV(cvgv)) {
+           sv = NEWSV(49, 0);
+           gv_efullname3(sv, cvgv, Nullch);
+           PUSHs(sv_2mortal(sv));
+           PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
+       }
+       else {
+           PUSHs(sv_2mortal(newSVpvn("(unknown)",9)));
+           PUSHs(sv_2mortal(newSViv((I32)cx->blk_sub.hasargs)));
+       }
     }
     else {
        PUSHs(sv_2mortal(newSVpvn("(eval)",6)));
@@ -1704,6 +1591,8 @@ PP(pp_lineseq)
     return NORMAL;
 }
 
+/* like pp_nextstate, but used instead when the debugger is active */
+
 PP(pp_dbstate)
 {
     PL_curcop = (COP*)PL_op;
@@ -1717,7 +1606,7 @@ PP(pp_dbstate)
        register CV *cv;
        register PERL_CONTEXT *cx;
        I32 gimme = G_ARRAY;
-       I32 hasargs;
+       U8 hasargs;
        GV *gv;
 
        gv = PL_DBgv;
@@ -1743,8 +1632,7 @@ PP(pp_dbstate)
        PUSHSUB(cx);
        CvDEPTH(cv)++;
        (void)SvREFCNT_inc(cv);
-       SAVEVPTR(PL_curpad);
-       PL_curpad = AvARRAY((AV*)*av_fetch(CvPADLIST(cv),1,FALSE));
+       PAD_SET_CUR(CvPADLIST(cv),1);
        RETURNOP(CvSTART(cv));
     }
     else
@@ -1770,21 +1658,13 @@ PP(pp_enteriter)
     ENTER;
     SAVETMPS;
 
-#ifdef USE_5005THREADS
-    if (PL_op->op_flags & OPf_SPECIAL) {
-       svp = &THREADSV(PL_op->op_targ);        /* per-thread variable */
-       SAVEGENERICSV(*svp);
-       *svp = NEWSV(0,0);
-    }
-    else
-#endif /* USE_5005THREADS */
     if (PL_op->op_targ) {
 #ifndef USE_ITHREADS
-       svp = &PL_curpad[PL_op->op_targ];               /* "my" variable */
+       svp = &PAD_SVl(PL_op->op_targ);         /* "my" variable */
        SAVESPTR(*svp);
 #else
        SAVEPADSV(PL_op->op_targ);
-       iterdata = (void*)PL_op->op_targ;
+       iterdata = INT2PTR(void*, PL_op->op_targ);
        cxtype |= CXp_PADVAR;
 #endif
     }
@@ -1810,11 +1690,11 @@ PP(pp_enteriter)
        cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs);
        if (SvTYPE(cx->blk_loop.iterary) != SVt_PVAV) {
            dPOPss;
+           /* See comment in pp_flop() */
            if (SvNIOKp(sv) || !SvPOKp(sv) ||
                SvNIOKp(cx->blk_loop.iterary) || !SvPOKp(cx->blk_loop.iterary) ||
                (looks_like_number(sv) && *SvPVX(sv) != '0' &&
-                looks_like_number((SV*)cx->blk_loop.iterary) &&
-                *SvPVX(cx->blk_loop.iterary) != '0'))
+                looks_like_number((SV*)cx->blk_loop.iterary)))
            {
                 if (SvNV(sv) < IV_MIN ||
                     SvNV((SV*)cx->blk_loop.iterary) >= IV_MAX)
@@ -2142,7 +2022,7 @@ PP(pp_redo)
 STATIC OP *
 S_dofindlabel(pTHX_ OP *o, char *label, OP **opstack, OP **oplimit)
 {
-    OP *kid;
+    OP *kid = Nullop;
     OP **ops = opstack;
     static char too_deep[] = "Target of goto is too deeply nested";
 
@@ -2252,26 +2132,20 @@ PP(pp_goto)
                EXTEND(PL_stack_sp, items); /* @_ could have been extended. */
                Copy(AvARRAY(av), PL_stack_sp, items, SV*);
                PL_stack_sp += items;
-#ifndef USE_5005THREADS
                SvREFCNT_dec(GvAV(PL_defgv));
                GvAV(PL_defgv) = cx->blk_sub.savearray;
-#endif /* USE_5005THREADS */
                /* abandon @_ if it got reified */
                if (AvREAL(av)) {
                    (void)sv_2mortal((SV*)av);  /* delay until return */
                    av = newAV();
                    av_extend(av, items-1);
                    AvFLAGS(av) = AVf_REIFY;
-                   PL_curpad[0] = (SV*)(cx->blk_sub.argarray = av);
+                   PAD_SVl(0) = (SV*)(cx->blk_sub.argarray = av);
                }
            }
            else if (CvXSUB(cv)) {      /* put GvAV(defgv) back onto stack */
                AV* av;
-#ifdef USE_5005THREADS
-               av = (AV*)PL_curpad[0];
-#else
                av = GvAV(PL_defgv);
-#endif
                items = AvFILLp(av) + 1;
                PL_stack_sp++;
                EXTEND(PL_stack_sp, items); /* @_ could have been extended. */
@@ -2309,7 +2183,7 @@ PP(pp_goto)
                    PL_stack_sp--;              /* There is no cv arg. */
                    /* Push a mark for the start of arglist */
                    PUSHMARK(mark);
-                   (void)(*CvXSUB(cv))(aTHXo_ cv);
+                   (void)(*CvXSUB(cv))(aTHX_ cv);
                    /* Pop the current context like a decent sub should */
                    POPBLOCK(cx, PL_curpm);
                    /* Do _not_ use PUTBACK, keep the XSUB's return stack! */
@@ -2319,7 +2193,6 @@ PP(pp_goto)
            }
            else {
                AV* padlist = CvPADLIST(cv);
-               SV** svp = AvARRAY(padlist);
                if (CxTYPE(cx) == CXt_EVAL) {
                    PL_in_eval = cx->blk_eval.old_in_eval;
                    PL_eval_root = cx->blk_eval.old_eval_root;
@@ -2327,86 +2200,25 @@ PP(pp_goto)
                    cx->blk_sub.hasargs = 0;
                }
                cx->blk_sub.cv = cv;
-               cx->blk_sub.olddepth = CvDEPTH(cv);
+               cx->blk_sub.olddepth = (U16)CvDEPTH(cv);
+
                CvDEPTH(cv)++;
                if (CvDEPTH(cv) < 2)
                    (void)SvREFCNT_inc(cv);
-               else {  /* save temporaries on recursion? */
+               else {
                    if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
                        sub_crush_depth(cv);
-                   if (CvDEPTH(cv) > AvFILLp(padlist)) {
-                       AV *newpad = newAV();
-                       SV **oldpad = AvARRAY(svp[CvDEPTH(cv)-1]);
-                       I32 ix = AvFILLp((AV*)svp[1]);
-                       I32 names_fill = AvFILLp((AV*)svp[0]);
-                       svp = AvARRAY(svp[0]);
-                       for ( ;ix > 0; ix--) {
-                           if (names_fill >= ix && svp[ix] != &PL_sv_undef) {
-                               char *name = SvPVX(svp[ix]);
-                               if ((SvFLAGS(svp[ix]) & SVf_FAKE)
-                                   || *name == '&')
-                               {
-                                   /* outer lexical or anon code */
-                                   av_store(newpad, ix,
-                                       SvREFCNT_inc(oldpad[ix]) );
-                               }
-                               else {          /* our own lexical */
-                                   if (*name == '@')
-                                       av_store(newpad, ix, sv = (SV*)newAV());
-                                   else if (*name == '%')
-                                       av_store(newpad, ix, sv = (SV*)newHV());
-                                   else
-                                       av_store(newpad, ix, sv = NEWSV(0,0));
-                                   SvPADMY_on(sv);
-                               }
-                           }
-                           else if (IS_PADGV(oldpad[ix]) || IS_PADCONST(oldpad[ix])) {
-                               av_store(newpad, ix, sv = SvREFCNT_inc(oldpad[ix]));
-                           }
-                           else {
-                               av_store(newpad, ix, sv = NEWSV(0,0));
-                               SvPADTMP_on(sv);
-                           }
-                       }
-                       if (cx->blk_sub.hasargs) {
-                           AV* av = newAV();
-                           av_extend(av, 0);
-                           av_store(newpad, 0, (SV*)av);
-                           AvFLAGS(av) = AVf_REIFY;
-                       }
-                       av_store(padlist, CvDEPTH(cv), (SV*)newpad);
-                       AvFILLp(padlist) = CvDEPTH(cv);
-                       svp = AvARRAY(padlist);
-                   }
+                   pad_push(padlist, CvDEPTH(cv), cx->blk_sub.hasargs);
                }
-#ifdef USE_5005THREADS
-               if (!cx->blk_sub.hasargs) {
-                   AV* av = (AV*)PL_curpad[0];
-               
-                   items = AvFILLp(av) + 1;
-                   if (items) {
-                       /* Mark is at the end of the stack. */
-                       EXTEND(SP, items);
-                       Copy(AvARRAY(av), SP + 1, items, SV*);
-                       SP += items;
-                       PUTBACK ;               
-                   }
-               }
-#endif /* USE_5005THREADS */           
-               SAVEVPTR(PL_curpad);
-               PL_curpad = AvARRAY((AV*)svp[CvDEPTH(cv)]);
-#ifndef USE_5005THREADS
+               PAD_SET_CUR(padlist, CvDEPTH(cv));
                if (cx->blk_sub.hasargs)
-#endif /* USE_5005THREADS */
                {
-                   AV* av = (AV*)PL_curpad[0];
+                   AV* av = (AV*)PAD_SVl(0);
                    SV** ary;
 
-#ifndef USE_5005THREADS
                    cx->blk_sub.savearray = GvAV(PL_defgv);
                    GvAV(PL_defgv) = (AV*)SvREFCNT_inc(av);
-#endif /* USE_5005THREADS */
-                   cx->blk_sub.oldcurpad = PL_curpad;
+                   CX_CURPAD_SAVE(cx->blk_sub);
                    cx->blk_sub.argarray = av;
                    ++mark;
 
@@ -2596,6 +2408,7 @@ PP(pp_exit)
 #ifdef VMS
         if (anum == 1 && (PL_op->op_private & OPpEXIT_VMSISH))
            anum = 0;
+        VMSISH_HUSHED  = VMSISH_HUSHED || (PL_op->op_private & OPpHUSH_VMSISH);
 #endif
     }
     PL_exit_flags |= PERL_EXIT_EXPECTED;
@@ -2691,6 +2504,7 @@ S_docatch(pTHX_ OP *o)
 {
     int ret;
     OP *oldop = PL_op;
+    OP *retop;
     volatile PERL_SI *cursi = PL_curstackinfo;
     dJMPENV;
 
@@ -2698,6 +2512,15 @@ S_docatch(pTHX_ OP *o)
     assert(CATCH_GET == TRUE);
 #endif
     PL_op = o;
+
+    /* Normally, the leavetry at the end of this block of ops will
+     * pop an op off the return stack and continue there. By setting
+     * the op to Nullop, we force an exit from the inner runops()
+     * loop. DAPM.
+     */
+    retop = pop_return();
+    push_return(Nullop);
+
 #ifdef PERL_FLEXIBLE_EXCEPTIONS
  redo_body:
     CALLPROTECT(aTHX_ pcur_env, &ret, MEMBER_TO_FPTR(S_docatch_body));
@@ -2712,11 +2535,15 @@ S_docatch(pTHX_ OP *o)
 #endif
        break;
     case 3:
+       /* die caught by an inner eval - continue inner loop */
        if (PL_restartop && cursi == PL_curstackinfo) {
            PL_op = PL_restartop;
            PL_restartop = 0;
            goto redo_body;
        }
+       /* a die in this eval - continue in outer loop */
+       if (!PL_restartop)
+           break;
        /* FALL THROUGH */
     default:
        JMPENV_POP;
@@ -2726,11 +2553,11 @@ S_docatch(pTHX_ OP *o)
     }
     JMPENV_POP;
     PL_op = oldop;
-    return Nullop;
+    return retop;
 }
 
 OP *
-Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, AV** avp)
+Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp)
 /* sv Text to convert to OP tree. */
 /* startop op_free() this to undo. */
 /* code Short string id of the caller. */
@@ -2745,6 +2572,8 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, AV** avp)
     char tbuf[TYPE_DIGITS(long) + 12 + 10];
     char *tmpbuf = tbuf;
     char *safestr;
+    int runtime;
+    CV* runcv;
 
     ENTER;
     lex_start(sv);
@@ -2783,37 +2612,79 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, AV** avp)
 #endif
     PL_hints &= HINT_UTF8;
 
+    /* we get here either during compilation, or via pp_regcomp at runtime */
+    runtime = PL_op && (PL_op->op_type == OP_REGCOMP);
+    if (runtime)
+       runcv = find_runcv();
+
     PL_op = &dummy;
     PL_op->op_type = OP_ENTEREVAL;
     PL_op->op_flags = 0;                       /* Avoid uninit warning. */
     PUSHBLOCK(cx, CXt_EVAL|(PL_curcop == &PL_compiling ? 0 : CXp_REAL), SP);
     PUSHEVAL(cx, 0, Nullgv);
-    rop = doeval(G_SCALAR, startop);
+
+    if (runtime)
+       rop = doeval(G_SCALAR, startop, runcv, PL_curcop->cop_seq);
+    else
+       rop = doeval(G_SCALAR, startop, PL_compcv, PL_cop_seqmax);
     POPBLOCK(cx,PL_curpm);
     POPEVAL(cx);
 
     (*startop)->op_type = OP_NULL;
     (*startop)->op_ppaddr = PL_ppaddr[OP_NULL];
     lex_end();
-    *avp = (AV*)SvREFCNT_inc(PL_comppad);
+    /* XXX DAPM do this properly one year */
+    *padp = (AV*)SvREFCNT_inc(PL_comppad);
     LEAVE;
     if (PL_curcop == &PL_compiling)
-       PL_compiling.op_private = PL_hints;
+       PL_compiling.op_private = (U8)(PL_hints & HINT_PRIVATE_MASK);
 #ifdef OP_IN_REGISTER
     op = PL_opsave;
 #endif
     return rop;
 }
 
+
+/*
+=for apidoc find_runcv
+
+Locate the CV corresponding to the currently executing sub or eval.
+
+=cut
+*/
+
+CV*
+Perl_find_runcv(pTHX)
+{
+    I32                 ix;
+    PERL_SI     *si;
+    PERL_CONTEXT *cx;
+
+    for (si = PL_curstackinfo; si; si = si->si_prev) {
+       for (ix = si->si_cxix; ix >= 0; ix--) {
+           cx = &(si->si_cxstack[ix]);
+           if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT)
+               return cx->blk_sub.cv;
+           else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
+               return PL_compcv;
+       }
+    }
+    return PL_main_cv;
+}
+
+
+/* Compile a require/do, an eval '', or a /(?{...})/.
+ * 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.
+ */
+
 /* With USE_5005THREADS, eval_owner must be held on entry to doeval */
 STATIC OP *
-S_doeval(pTHX_ int gimme, OP** startop)
+S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
 {
     dSP;
     OP *saveop = PL_op;
-    CV *caller;
-    AV* comppadlist;
-    I32 i;
 
     PL_in_eval = ((saveop && saveop->op_type == OP_REQUIRE)
                  ? (EVAL_INREQUIRE | (PL_in_eval & EVAL_INEVAL))
@@ -2821,27 +2692,6 @@ S_doeval(pTHX_ int gimme, OP** startop)
 
     PUSHMARK(SP);
 
-    /* set up a scratch pad */
-
-    SAVEI32(PL_padix);
-    SAVEVPTR(PL_curpad);
-    SAVESPTR(PL_comppad);
-    SAVESPTR(PL_comppad_name);
-    SAVEI32(PL_comppad_name_fill);
-    SAVEI32(PL_min_intro_pending);
-    SAVEI32(PL_max_intro_pending);
-
-    caller = PL_compcv;
-    for (i = cxstack_ix - 1; i >= 0; i--) {
-       PERL_CONTEXT *cx = &cxstack[i];
-       if (CxTYPE(cx) == CXt_EVAL)
-           break;
-       else if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) {
-           caller = cx->blk_sub.cv;
-           break;
-       }
-    }
-
     SAVESPTR(PL_compcv);
     PL_compcv = (CV*)NEWSV(1104,0);
     sv_upgrade((SV *)PL_compcv, SVt_PVCV);
@@ -2849,36 +2699,13 @@ S_doeval(pTHX_ int gimme, OP** startop)
     assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL);
     cxstack[cxstack_ix].blk_eval.cv = PL_compcv;
 
-#ifdef USE_5005THREADS
-    CvOWNER(PL_compcv) = 0;
-    New(666, CvMUTEXP(PL_compcv), 1, perl_mutex);
-    MUTEX_INIT(CvMUTEXP(PL_compcv));
-#endif /* USE_5005THREADS */
-
-    PL_comppad = newAV();
-    av_push(PL_comppad, Nullsv);
-    PL_curpad = AvARRAY(PL_comppad);
-    PL_comppad_name = newAV();
-    PL_comppad_name_fill = 0;
-    PL_min_intro_pending = 0;
-    PL_padix = 0;
-#ifdef USE_5005THREADS
-    av_store(PL_comppad_name, 0, newSVpvn("@_", 2));
-    PL_curpad[0] = (SV*)newAV();
-    SvPADMY_on(PL_curpad[0]);  /* XXX Needed? */
-#endif /* USE_5005THREADS */
-
-    comppadlist = newAV();
-    AvREAL_off(comppadlist);
-    av_store(comppadlist, 0, (SV*)PL_comppad_name);
-    av_store(comppadlist, 1, (SV*)PL_comppad);
-    CvPADLIST(PL_compcv) = comppadlist;
-
-    if (!saveop ||
-       (saveop->op_type != OP_REQUIRE && saveop->op_type != OP_DOFILE))
-    {
-       CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc(caller);
-    }
+    CvOUTSIDE_SEQ(PL_compcv) = seq;
+    CvOUTSIDE(PL_compcv) = (CV*)SvREFCNT_inc(outside);
+
+    /* set up a scratch pad */
+
+    CvPADLIST(PL_compcv) = pad_new(padnew_SAVE);
+
 
     SAVEMORTALIZESV(PL_compcv);        /* must remain until end of current statement */
 
@@ -2899,8 +2726,6 @@ S_doeval(pTHX_ int gimme, OP** startop)
     PL_error_count = 0;
     PL_curcop = &PL_compiling;
     PL_curcop->cop_arybase = 0;
-    SvREFCNT_dec(PL_rs);
-    PL_rs = newSVpvn("\n", 1);
     if (saveop && saveop->op_flags & OPf_SPECIAL)
        PL_in_eval |= EVAL_KEEPERR;
     else
@@ -2938,23 +2763,17 @@ S_doeval(pTHX_ int gimme, OP** startop)
            Perl_croak(aTHX_ "%sCompilation failed in regexp",
                       (*msg ? msg : "Unknown error\n"));
        }
-       SvREFCNT_dec(PL_rs);
-       PL_rs = SvREFCNT_inc(PL_nrs);
-#ifdef USE_5005THREADS
-       MUTEX_LOCK(&PL_eval_mutex);
-       PL_eval_owner = 0;
-       COND_SIGNAL(&PL_eval_cond);
-       MUTEX_UNLOCK(&PL_eval_mutex);
-#endif /* USE_5005THREADS */
+       else {
+           char* msg = SvPVx(ERRSV, n_a);
+           if (!*msg) {
+               sv_setpv(ERRSV, "Compilation error");
+           }
+       }
        RETPUSHUNDEF;
     }
-    SvREFCNT_dec(PL_rs);
-    PL_rs = SvREFCNT_inc(PL_nrs);
     CopLINE_set(&PL_compiling, 0);
     if (startop) {
        *startop = PL_eval_root;
-       SvREFCNT_dec(CvOUTSIDE(PL_compcv));
-       CvOUTSIDE(PL_compcv) = Nullcv;
     } else
        SAVEFREEOP(PL_eval_root);
     if (gimme & G_VOID)
@@ -2984,12 +2803,6 @@ S_doeval(pTHX_ int gimme, OP** startop)
     SP = PL_stack_base + POPMARK;              /* pop original mark */
     PL_op = saveop;                    /* The caller may need it. */
     PL_lex_state = LEX_NOTPARSING;     /* $^S needs this. */
-#ifdef USE_5005THREADS
-    MUTEX_LOCK(&PL_eval_mutex);
-    PL_eval_owner = 0;
-    COND_SIGNAL(&PL_eval_cond);
-    MUTEX_UNLOCK(&PL_eval_mutex);
-#endif /* USE_5005THREADS */
 
     RETURNOP(PL_eval_start);
 }
@@ -3043,9 +2856,12 @@ PP(pp_require)
     GV *filter_child_proc = 0;
     SV *filter_state = 0;
     SV *filter_sub = 0;
+    SV *hook_sv = 0;
+    SV *encoding;
+    OP *op;
 
     sv = POPs;
-    if (SvNIOKp(sv)) {
+    if (SvNIOKp(sv) && PL_op->op_type != OP_DOFILE) {
        if (SvPOK(sv) && SvNOK(sv) && SvNV(sv)) {               /* require v5.6.1 */
            UV rev = 0, ver = 0, sver = 0;
            STRLEN len;
@@ -3071,6 +2887,9 @@ PP(pp_require)
                    "v%d.%d.%d, stopped", rev, ver, sver, PERL_REVISION,
                    PERL_VERSION, PERL_SUBVERSION);
            }
+           if (ckWARN(WARN_PORTABLE))
+               Perl_warner(aTHX_ packWARN(WARN_PORTABLE),
+                        "v-string in use/require non-portable");
            RETPUSHYES;
        }
        else if (!SvPOKp(sv)) {                 /* require 5.005_03 */
@@ -3087,11 +2906,11 @@ PP(pp_require)
 
                /* help out with the "use 5.6" confusion */
                if (sver == 0 && (rev > 5 || (rev == 5 && ver >= 100))) {
-                   DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required--"
-                       "this is only v%d.%d.%d, stopped"
-                       " (did you mean v%"UVuf".%"UVuf".0?)",
-                       rev, ver, sver, PERL_REVISION, PERL_VERSION,
-                       PERL_SUBVERSION, rev, ver/100);
+                   DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required"
+                       " (did you mean v%"UVuf".%03"UVuf"?)--"
+                       "this is only v%d.%d.%d, stopped",
+                       rev, ver, sver, rev, ver/100,
+                       PERL_REVISION, PERL_VERSION, PERL_SUBVERSION);
                }
                else {
                    DIE(aTHX_ "Perl v%"UVuf".%"UVuf".%"UVuf" required--"
@@ -3114,30 +2933,22 @@ PP(pp_require)
 
     /* prepare to compile file */
 
-#ifdef MACOS_TRADITIONAL
-    if (PERL_FILE_IS_ABSOLUTE(name)
-       || (*name == ':' && name[1] != ':' && strchr(name+2, ':')))
-    {
+    if (path_is_absolute(name)) {
        tryname = name;
        tryrsfp = doopen_pmc(name,PERL_SCRIPT_MODE);
-       /* We consider paths of the form :a:b ambiguous and interpret them first
-          as global then as local
-       */
-       if (!tryrsfp && *name == ':' && name[1] != ':' && strchr(name+2, ':'))
-           goto trylocal;
     }
-    else
-trylocal: {
-#else
-    if (PERL_FILE_IS_ABSOLUTE(name)
-       || (*name == '.' && (name[1] == '/' ||
-                            (name[1] == '.' && name[2] == '/'))))
-    {
-       tryname = name;
-       tryrsfp = doopen_pmc(name,PERL_SCRIPT_MODE);
+#ifdef MACOS_TRADITIONAL
+    if (!tryrsfp) {
+       char newname[256];
+
+       MacPerl_CanonDir(name, newname, 1);
+       if (path_is_absolute(newname)) {
+           tryname = newname;
+           tryrsfp = doopen_pmc(newname,PERL_SCRIPT_MODE);
+       }
     }
-    else {
 #endif
+    if (!tryrsfp) {
        AV *ar = GvAVn(PL_incgv);
        I32 i;
 #ifdef VMS
@@ -3160,7 +2971,7 @@ trylocal: {
                    }
 
                    Perl_sv_setpvf(aTHX_ namesv, "/loader/0x%"UVxf"/%s",
-                                  PTR2UV(SvANY(loader)), name);
+                                  PTR2UV(SvRV(dirsv)), name);
                    tryname = SvPVX(namesv);
                    tryrsfp = 0;
 
@@ -3241,6 +3052,7 @@ trylocal: {
                    LEAVE;
 
                    if (tryrsfp) {
+                       hook_sv = dirsv;
                        break;
                    }
 
@@ -3259,10 +3071,21 @@ trylocal: {
                    }
                }
                else {
+                 if (!path_is_absolute(name)
+#ifdef MACOS_TRADITIONAL
+                       /* We consider paths of the form :a:b ambiguous and interpret them first
+                          as global then as local
+                       */
+                       || (*name == ':' && name[1] != ':' && strchr(name+2, ':'))
+#endif
+                 ) {
                    char *dir = SvPVx(dirsv, n_a);
 #ifdef MACOS_TRADITIONAL
-                   char buf[256];
-                   Perl_sv_setpvf(aTHX_ namesv, "%s%s", MacPerl_CanonDir(dir, buf), name+(name[0] == ':'));
+                   char buf1[256];
+                   char buf2[256];
+
+                   MacPerl_CanonDir(name, buf2, 1);
+                   Perl_sv_setpvf(aTHX_ namesv, "%s%s", MacPerl_CanonDir(dir, buf1, 0), buf2+(buf2[0] == ':'));
 #else
 #ifdef VMS
                    char *unixdir;
@@ -3276,20 +3099,13 @@ trylocal: {
 #endif
                    TAINT_PROPER("require");
                    tryname = SvPVX(namesv);
-#ifdef MACOS_TRADITIONAL
-                   {
-                       /* Convert slashes in the name part, but not the directory part, to colons */
-                       char * colon;
-                       for (colon = tryname+strlen(dir); colon = strchr(colon, '/'); )
-                           *colon++ = ':';
-                   }
-#endif
                    tryrsfp = doopen_pmc(tryname, PERL_SCRIPT_MODE);
                    if (tryrsfp) {
                        if (tryname[0] == '.' && tryname[1] == '/')
                            tryname += 2;
                        break;
                    }
+                 }
                }
            }
        }
@@ -3326,11 +3142,17 @@ trylocal: {
        RETPUSHUNDEF;
     }
     else
-       SETERRNO(0, SS$_NORMAL);
+       SETERRNO(0, SS_NORMAL);
 
     /* Assume success here to prevent recursive requirement. */
-    (void)hv_store(GvHVn(PL_incgv), name, strlen(name),
-                  newSVpv(CopFILE(&PL_compiling), 0), 0 );
+    len = strlen(name);
+    /* Check whether a hook in @INC has already filled %INC */
+    if (!hook_sv || !(svp = hv_fetch(GvHVn(PL_incgv), name, len, 0))) {
+       (void)hv_store(GvHVn(PL_incgv), name, len,
+                      (hook_sv ? SvREFCNT_inc(hook_sv)
+                               : newSVpv(CopFILE(&PL_compiling), 0)),
+                      0 );
+    }
 
     ENTER;
     SAVETMPS;
@@ -3346,6 +3168,8 @@ trylocal: {
         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);
@@ -3368,15 +3192,17 @@ trylocal: {
     CopLINE_set(&PL_compiling, 0);
 
     PUTBACK;
-#ifdef USE_5005THREADS
-    MUTEX_LOCK(&PL_eval_mutex);
-    if (PL_eval_owner && PL_eval_owner != thr)
-       while (PL_eval_owner)
-           COND_WAIT(&PL_eval_cond, &PL_eval_mutex);
-    PL_eval_owner = thr;
-    MUTEX_UNLOCK(&PL_eval_mutex);
-#endif /* USE_5005THREADS */
-    return DOCATCH(doeval(gimme, NULL));
+
+    /* Store and reset encoding. */
+    encoding = PL_encoding;
+    PL_encoding = Nullsv;
+
+    op = DOCATCH(doeval(gimme, NULL, Nullcv, PL_curcop->cop_seq));
+    
+    /* Restore encoding. */
+    PL_encoding = encoding;
+
+    return op;
 }
 
 PP(pp_dofile)
@@ -3395,8 +3221,9 @@ PP(pp_entereval)
     char *safestr;
     STRLEN len;
     OP *ret;
+    CV* runcv;
 
-    if (!SvPV(sv,len) || !len)
+    if (!SvPV(sv,len))
        RETPUSHUNDEF;
     TAINT_PROPER("eval");
 
@@ -3442,6 +3269,7 @@ PP(pp_entereval)
         PL_compiling.cop_io = newSVsv(PL_curcop->cop_io);
         SAVEFREESV(PL_compiling.cop_io);
     }
+    runcv = find_runcv();
 
     push_return(PL_op->op_next);
     PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
@@ -3452,16 +3280,8 @@ PP(pp_entereval)
     if (PERLDB_LINE && PL_curstash != PL_debstash)
        save_lines(CopFILEAV(&PL_compiling), PL_linestr);
     PUTBACK;
-#ifdef USE_5005THREADS
-    MUTEX_LOCK(&PL_eval_mutex);
-    if (PL_eval_owner && PL_eval_owner != thr)
-       while (PL_eval_owner)
-           COND_WAIT(&PL_eval_cond, &PL_eval_mutex);
-    PL_eval_owner = thr;
-    MUTEX_UNLOCK(&PL_eval_mutex);
-#endif /* USE_5005THREADS */
-    ret = doeval(gimme, NULL);
-    if (PERLDB_INTER && was != PL_sub_generation /* Some subs defined here. */
+    ret = doeval(gimme, NULL, runcv, PL_curcop->cop_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. */
     }
@@ -3561,13 +3381,14 @@ PP(pp_leavetry)
     register SV **mark;
     SV **newsp;
     PMOP *newpm;
+    OP* retop;
     I32 gimme;
     register PERL_CONTEXT *cx;
     I32 optype;
 
     POPBLOCK(cx,newpm);
     POPEVAL(cx);
-    pop_return();
+    retop = pop_return();
 
     TAINT_NOT;
     if (gimme == G_VOID)
@@ -3599,7 +3420,7 @@ PP(pp_leavetry)
 
     LEAVE;
     sv_setpv(ERRSV,"");
-    RETURN;
+    RETURNOP(retop);
 }
 
 STATIC void
@@ -3658,14 +3479,14 @@ S_doparseform(pTHX_ SV *sv)
                if (postspace)
                    *fpc++ = FF_SPACE;
                *fpc++ = FF_LITERAL;
-               *fpc++ = arg;
+               *fpc++ = (U16)arg;
            }
            postspace = FALSE;
            if (s <= send)
                skipspaces--;
            if (skipspaces) {
                *fpc++ = FF_SKIP;
-               *fpc++ = skipspaces;
+               *fpc++ = (U16)skipspaces;
            }
            skipspaces = 0;
            if (s <= send)
@@ -3676,7 +3497,7 @@ S_doparseform(pTHX_ SV *sv)
                    arg = fpc - linepc + 1;
                else
                    arg = 0;
-               *fpc++ = arg;
+               *fpc++ = (U16)arg;
            }
            if (s < send) {
                linepc = fpc;
@@ -3699,7 +3520,7 @@ S_doparseform(pTHX_ SV *sv)
            arg = (s - base) - 1;
            if (arg) {
                *fpc++ = FF_LITERAL;
-               *fpc++ = arg;
+               *fpc++ = (U16)arg;
            }
 
            base = s - 1;
@@ -3724,7 +3545,7 @@ S_doparseform(pTHX_ SV *sv)
                }
                *fpc++ = s - base;              /* fieldsize for FETCH */
                *fpc++ = FF_DECIMAL;
-                *fpc++ = arg;
+                *fpc++ = (U16)arg;
             }
             else if (*s == '0' && s[1] == '#') {  /* Zero padded decimals */
                 arg = ischop ? 512 : 0;
@@ -3742,7 +3563,7 @@ S_doparseform(pTHX_ SV *sv)
                 }
                 *fpc++ = s - base;                /* fieldsize for FETCH */
                 *fpc++ = FF_0DECIMAL;
-               *fpc++ = arg;
+               *fpc++ = (U16)arg;
            }
            else {
                I32 prespace = 0;
@@ -3771,7 +3592,7 @@ S_doparseform(pTHX_ SV *sv)
                *fpc++ = ischop ? FF_CHECKCHOP : FF_CHECKNL;
 
                if (prespace)
-                   *fpc++ = prespace;
+                   *fpc++ = (U16)prespace;
                *fpc++ = FF_ITEM;
                if (ismore)
                    *fpc++ = FF_MORE;
@@ -3798,593 +3619,8 @@ S_doparseform(pTHX_ SV *sv)
     SvCOMPILED_on(sv);
 }
 
-/*
- * The mergesort implementation is by Peter M. Mcilroy <pmcilroy@lucent.com>.
- *
- * The original code was written in conjunction with BSD Computer Software
- * Research Group at University of California, Berkeley.
- *
- * See also: "Optimistic Merge Sort" (SODA '92)
- *
- * The integration to Perl is by John P. Linderman <jpl@research.att.com>.
- *
- * The code can be distributed under the same terms as Perl itself.
- *
- */
-
-#ifdef TESTHARNESS
-#include <sys/types.h>
-typedef        void SV;
-#define pTHXo_
-#define pTHX_
-#define STATIC
-#define New(ID,VAR,N,TYPE) VAR=(TYPE *)malloc((N)*sizeof(TYPE))
-#define        Safefree(VAR) free(VAR)
-typedef int  (*SVCOMPARE_t) (pTHXo_ SV*, SV*);
-#endif /* TESTHARNESS */
-
-typedef char * aptr;           /* pointer for arithmetic on sizes */
-typedef SV * gptr;             /* pointers in our lists */
-
-/* Binary merge internal sort, with a few special mods
-** for the special perl environment it now finds itself in.
-**
-** Things that were once options have been hotwired
-** to values suitable for this use.  In particular, we'll always
-** initialize looking for natural runs, we'll always produce stable
-** output, and we'll always do Peter McIlroy's binary merge.
-*/
-
-/* Pointer types for arithmetic and storage and convenience casts */
-
-#define        APTR(P) ((aptr)(P))
-#define        GPTP(P) ((gptr *)(P))
-#define GPPP(P) ((gptr **)(P))
-
-
-/* byte offset from pointer P to (larger) pointer Q */
-#define        BYTEOFF(P, Q) (APTR(Q) - APTR(P))
-
-#define PSIZE sizeof(gptr)
-
-/* If PSIZE is power of 2, make PSHIFT that power, if that helps */
-
-#ifdef PSHIFT
-#define        PNELEM(P, Q)    (BYTEOFF(P,Q) >> (PSHIFT))
-#define        PNBYTE(N)       ((N) << (PSHIFT))
-#define        PINDEX(P, N)    (GPTP(APTR(P) + PNBYTE(N)))
-#else
-/* Leave optimization to compiler */
-#define        PNELEM(P, Q)    (GPTP(Q) - GPTP(P))
-#define        PNBYTE(N)       ((N) * (PSIZE))
-#define        PINDEX(P, N)    (GPTP(P) + (N))
-#endif
-
-/* Pointer into other corresponding to pointer into this */
-#define        POTHER(P, THIS, OTHER) GPTP(APTR(OTHER) + BYTEOFF(THIS,P))
-
-#define FROMTOUPTO(src, dst, lim) do *dst++ = *src++; while(src<lim)
-
-
-/* Runs are identified by a pointer in the auxilliary list.
-** The pointer is at the start of the list,
-** and it points to the start of the next list.
-** NEXT is used as an lvalue, too.
-*/
-
-#define        NEXT(P)         (*GPPP(P))
-
-
-/* PTHRESH is the minimum number of pairs with the same sense to justify
-** checking for a run and extending it.  Note that PTHRESH counts PAIRS,
-** not just elements, so PTHRESH == 8 means a run of 16.
-*/
-
-#define        PTHRESH (8)
-
-/* RTHRESH is the number of elements in a run that must compare low
-** to the low element from the opposing run before we justify
-** doing a binary rampup instead of single stepping.
-** In random input, N in a row low should only happen with
-** probability 2^(1-N), so we can risk that we are dealing
-** with orderly input without paying much when we aren't.
-*/
-
-#define RTHRESH (6)
-
-
-/*
-** Overview of algorithm and variables.
-** The array of elements at list1 will be organized into runs of length 2,
-** or runs of length >= 2 * PTHRESH.  We only try to form long runs when
-** PTHRESH adjacent pairs compare in the same way, suggesting overall order.
-**
-** Unless otherwise specified, pair pointers address the first of two elements.
-**
-** b and b+1 are a pair that compare with sense ``sense''.
-** b is the ``bottom'' of adjacent pairs that might form a longer run.
-**
-** p2 parallels b in the list2 array, where runs are defined by
-** a pointer chain.
-**
-** t represents the ``top'' of the adjacent pairs that might extend
-** the run beginning at b.  Usually, t addresses a pair
-** that compares with opposite sense from (b,b+1).
-** However, it may also address a singleton element at the end of list1,
-** or it may be equal to ``last'', the first element beyond list1.
-**
-** r addresses the Nth pair following b.  If this would be beyond t,
-** we back it off to t.  Only when r is less than t do we consider the
-** run long enough to consider checking.
-**
-** q addresses a pair such that the pairs at b through q already form a run.
-** Often, q will equal b, indicating we only are sure of the pair itself.
-** However, a search on the previous cycle may have revealed a longer run,
-** so q may be greater than b.
-**
-** p is used to work back from a candidate r, trying to reach q,
-** which would mean b through r would be a run.  If we discover such a run,
-** we start q at r and try to push it further towards t.
-** If b through r is NOT a run, we detect the wrong order at (p-1,p).
-** In any event, after the check (if any), we have two main cases.
-**
-** 1) Short run.  b <= q < p <= r <= t.
-**     b through q is a run (perhaps trivial)
-**     q through p are uninteresting pairs
-**     p through r is a run
-**
-** 2) Long run.  b < r <= q < t.
-**     b through q is a run (of length >= 2 * PTHRESH)
-**
-** Note that degenerate cases are not only possible, but likely.
-** For example, if the pair following b compares with opposite sense,
-** then b == q < p == r == t.
-*/
-
-
-static void
-dynprep(pTHX_ gptr *list1, gptr *list2, size_t nmemb, SVCOMPARE_t cmp)
-{
-    int sense;
-    register gptr *b, *p, *q, *t, *p2;
-    register gptr c, *last, *r;
-    gptr *savep;
-
-    b = list1;
-    last = PINDEX(b, nmemb);
-    sense = (cmp(aTHX_ *b, *(b+1)) > 0);
-    for (p2 = list2; b < last; ) {
-       /* We just started, or just reversed sense.
-       ** Set t at end of pairs with the prevailing sense.
-       */
-       for (p = b+2, t = p; ++p < last; t = ++p) {
-           if ((cmp(aTHX_ *t, *p) > 0) != sense) break;
-       }
-       q = b;
-       /* Having laid out the playing field, look for long runs */
-       do {
-           p = r = b + (2 * PTHRESH);
-           if (r >= t) p = r = t;      /* too short to care about */
-           else {
-               while (((cmp(aTHX_ *(p-1), *p) > 0) == sense) &&
-                      ((p -= 2) > q));
-               if (p <= q) {
-                   /* b through r is a (long) run.
-                   ** Extend it as far as possible.
-                   */
-                   p = q = r;
-                   while (((p += 2) < t) &&
-                          ((cmp(aTHX_ *(p-1), *p) > 0) == sense)) q = p;
-                   r = p = q + 2;      /* no simple pairs, no after-run */
-               }
-           }
-           if (q > b) {                /* run of greater than 2 at b */
-               savep = p;
-               p = q += 2;
-               /* pick up singleton, if possible */
-               if ((p == t) &&
-                   ((t + 1) == last) &&
-                   ((cmp(aTHX_ *(p-1), *p) > 0) == sense))
-                   savep = r = p = q = last;
-               p2 = NEXT(p2) = p2 + (p - b);
-               if (sense) while (b < --p) {
-                   c = *b;
-                   *b++ = *p;
-                   *p = c;
-               }
-               p = savep;
-           }
-           while (q < p) {             /* simple pairs */
-               p2 = NEXT(p2) = p2 + 2;
-               if (sense) {
-                   c = *q++;
-                   *(q-1) = *q;
-                   *q++ = c;
-               } else q += 2;
-           }
-           if (((b = p) == t) && ((t+1) == last)) {
-               NEXT(p2) = p2 + 1;
-               b++;
-           }
-           q = r;
-       } while (b < t);
-       sense = !sense;
-    }
-    return;
-}
-
-
-/* Overview of bmerge variables:
-**
-** list1 and list2 address the main and auxiliary arrays.
-** They swap identities after each merge pass.
-** Base points to the original list1, so we can tell if
-** the pointers ended up where they belonged (or must be copied).
-**
-** When we are merging two lists, f1 and f2 are the next elements
-** on the respective lists.  l1 and l2 mark the end of the lists.
-** tp2 is the current location in the merged list.
-**
-** p1 records where f1 started.
-** After the merge, a new descriptor is built there.
-**
-** p2 is a ``parallel'' pointer in (what starts as) descriptor space.
-** It is used to identify and delimit the runs.
-**
-** In the heat of determining where q, the greater of the f1/f2 elements,
-** belongs in the other list, b, t and p, represent bottom, top and probe
-** locations, respectively, in the other list.
-** They make convenient temporary pointers in other places.
-*/
-
-STATIC void
-S_qsortsv(pTHX_ gptr *list1, size_t nmemb, SVCOMPARE_t cmp)
-{
-    int i, run;
-    int sense;
-    register gptr *f1, *f2, *t, *b, *p, *tp2, *l1, *l2, *q;
-    gptr *aux, *list2, *p2, *last;
-    gptr *base = list1;
-    gptr *p1;
-
-    if (nmemb <= 1) return;    /* sorted trivially */
-    New(799,list2,nmemb,gptr); /* allocate auxilliary array */
-    aux = list2;
-    dynprep(aTHX_ list1, list2, nmemb, cmp);
-    last = PINDEX(list2, nmemb);
-    while (NEXT(list2) != last) {
-       /* More than one run remains.  Do some merging to reduce runs. */
-       l2 = p1 = list1;
-       for (tp2 = p2 = list2; p2 != last;) {
-           /* The new first run begins where the old second list ended.
-           ** Use the p2 ``parallel'' pointer to identify the end of the run.
-           */
-           f1 = l2;
-           t = NEXT(p2);
-           f2 = l1 = POTHER(t, list2, list1);
-           if (t != last) t = NEXT(t);
-           l2 = POTHER(t, list2, list1);
-           p2 = t;
-           while (f1 < l1 && f2 < l2) {
-               /* If head 1 is larger than head 2, find ALL the elements
-               ** in list 2 strictly less than head1, write them all,
-               ** then head 1.  Then compare the new heads, and repeat,
-               ** until one or both lists are exhausted.
-               **
-               ** In all comparisons (after establishing
-               ** which head to merge) the item to merge
-               ** (at pointer q) is the first operand of
-               ** the comparison.  When we want to know
-               ** if ``q is strictly less than the other'',
-               ** we can't just do
-               **    cmp(q, other) < 0
-               ** because stability demands that we treat equality
-               ** as high when q comes from l2, and as low when
-               ** q was from l1.  So we ask the question by doing
-               **    cmp(q, other) <= sense
-               ** and make sense == 0 when equality should look low,
-               ** and -1 when equality should look high.
-               */
-
-
-               if (cmp(aTHX_ *f1, *f2) <= 0) {
-                   q = f2; b = f1; t = l1;
-                   sense = -1;
-               } else {
-                   q = f1; b = f2; t = l2;
-                   sense = 0;
-               }
-
-
-               /* ramp up
-               **
-               ** Leave t at something strictly
-               ** greater than q (or at the end of the list),
-               ** and b at something strictly less than q.
-               */
-               for (i = 1, run = 0 ;;) {
-                   if ((p = PINDEX(b, i)) >= t) {
-                       /* off the end */
-                       if (((p = PINDEX(t, -1)) > b) &&
-                           (cmp(aTHX_ *q, *p) <= sense))
-                            t = p;
-                       else b = p;
-                       break;
-                   } else if (cmp(aTHX_ *q, *p) <= sense) {
-                       t = p;
-                       break;
-                   } else b = p;
-                   if (++run >= RTHRESH) i += i;
-               }
-
-
-               /* q is known to follow b and must be inserted before t.
-               ** Increment b, so the range of possibilities is [b,t).
-               ** Round binary split down, to favor early appearance.
-               ** Adjust b and t until q belongs just before t.
-               */
-
-               b++;
-               while (b < t) {
-                   p = PINDEX(b, (PNELEM(b, t) - 1) / 2);
-                   if (cmp(aTHX_ *q, *p) <= sense) {
-                       t = p;
-                   } else b = p + 1;
-               }
-
-
-               /* Copy all the strictly low elements */
-
-               if (q == f1) {
-                   FROMTOUPTO(f2, tp2, t);
-                   *tp2++ = *f1++;
-               } else {
-                   FROMTOUPTO(f1, tp2, t);
-                   *tp2++ = *f2++;
-               }
-           }
-
-
-           /* Run out remaining list */
-           if (f1 == l1) {
-                  if (f2 < l2) FROMTOUPTO(f2, tp2, l2);
-           } else              FROMTOUPTO(f1, tp2, l1);
-           p1 = NEXT(p1) = POTHER(tp2, list2, list1);
-       }
-       t = list1;
-       list1 = list2;
-       list2 = t;
-       last = PINDEX(list2, nmemb);
-    }
-    if (base == list2) {
-       last = PINDEX(list1, nmemb);
-       FROMTOUPTO(list1, list2, last);
-    }
-    Safefree(aux);
-    return;
-}
-
-
-#ifdef PERL_OBJECT
-#undef this
-#define this pPerl
-#include "XSUB.h"
-#endif
-
-
-static I32
-sortcv(pTHXo_ SV *a, SV *b)
-{
-    I32 oldsaveix = PL_savestack_ix;
-    I32 oldscopeix = PL_scopestack_ix;
-    I32 result;
-    GvSV(PL_firstgv) = a;
-    GvSV(PL_secondgv) = b;
-    PL_stack_sp = PL_stack_base;
-    PL_op = PL_sortcop;
-    CALLRUNOPS(aTHX);
-    if (PL_stack_sp != PL_stack_base + 1)
-       Perl_croak(aTHX_ "Sort subroutine didn't return single value");
-    if (!SvNIOKp(*PL_stack_sp))
-       Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value");
-    result = SvIV(*PL_stack_sp);
-    while (PL_scopestack_ix > oldscopeix) {
-       LEAVE;
-    }
-    leave_scope(oldsaveix);
-    return result;
-}
-
-static I32
-sortcv_stacked(pTHXo_ SV *a, SV *b)
-{
-    I32 oldsaveix = PL_savestack_ix;
-    I32 oldscopeix = PL_scopestack_ix;
-    I32 result;
-    AV *av;
-
-#ifdef USE_5005THREADS
-    av = (AV*)PL_curpad[0];
-#else
-    av = GvAV(PL_defgv);
-#endif
-
-    if (AvMAX(av) < 1) {
-       SV** ary = AvALLOC(av);
-       if (AvARRAY(av) != ary) {
-           AvMAX(av) += AvARRAY(av) - AvALLOC(av);
-           SvPVX(av) = (char*)ary;
-       }
-       if (AvMAX(av) < 1) {
-           AvMAX(av) = 1;
-           Renew(ary,2,SV*);
-           SvPVX(av) = (char*)ary;
-       }
-    }
-    AvFILLp(av) = 1;
-
-    AvARRAY(av)[0] = a;
-    AvARRAY(av)[1] = b;
-    PL_stack_sp = PL_stack_base;
-    PL_op = PL_sortcop;
-    CALLRUNOPS(aTHX);
-    if (PL_stack_sp != PL_stack_base + 1)
-       Perl_croak(aTHX_ "Sort subroutine didn't return single value");
-    if (!SvNIOKp(*PL_stack_sp))
-       Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value");
-    result = SvIV(*PL_stack_sp);
-    while (PL_scopestack_ix > oldscopeix) {
-       LEAVE;
-    }
-    leave_scope(oldsaveix);
-    return result;
-}
-
-static I32
-sortcv_xsub(pTHXo_ SV *a, SV *b)
-{
-    dSP;
-    I32 oldsaveix = PL_savestack_ix;
-    I32 oldscopeix = PL_scopestack_ix;
-    I32 result;
-    CV *cv=(CV*)PL_sortcop;
-
-    SP = PL_stack_base;
-    PUSHMARK(SP);
-    EXTEND(SP, 2);
-    *++SP = a;
-    *++SP = b;
-    PUTBACK;
-    (void)(*CvXSUB(cv))(aTHXo_ cv);
-    if (PL_stack_sp != PL_stack_base + 1)
-       Perl_croak(aTHX_ "Sort subroutine didn't return single value");
-    if (!SvNIOKp(*PL_stack_sp))
-       Perl_croak(aTHX_ "Sort subroutine didn't return a numeric value");
-    result = SvIV(*PL_stack_sp);
-    while (PL_scopestack_ix > oldscopeix) {
-       LEAVE;
-    }
-    leave_scope(oldsaveix);
-    return result;
-}
-
-
-static I32
-sv_ncmp(pTHXo_ SV *a, SV *b)
-{
-    NV nv1 = SvNV(a);
-    NV nv2 = SvNV(b);
-    return nv1 < nv2 ? -1 : nv1 > nv2 ? 1 : 0;
-}
-
-static I32
-sv_i_ncmp(pTHXo_ SV *a, SV *b)
-{
-    IV iv1 = SvIV(a);
-    IV iv2 = SvIV(b);
-    return iv1 < iv2 ? -1 : iv1 > iv2 ? 1 : 0;
-}
-#define tryCALL_AMAGICbin(left,right,meth,svp) STMT_START { \
-         *svp = Nullsv;                                \
-          if (PL_amagic_generation) { \
-           if (SvAMAGIC(left)||SvAMAGIC(right))\
-               *svp = amagic_call(left, \
-                                  right, \
-                                  CAT2(meth,_amg), \
-                                  0); \
-         } \
-       } STMT_END
-
-static I32
-amagic_ncmp(pTHXo_ register SV *a, register SV *b)
-{
-    SV *tmpsv;
-    tryCALL_AMAGICbin(a,b,ncmp,&tmpsv);
-    if (tmpsv) {
-       NV d;
-       
-        if (SvIOK(tmpsv)) {
-            I32 i = SvIVX(tmpsv);
-            if (i > 0)
-               return 1;
-            return i? -1 : 0;
-        }
-        d = SvNV(tmpsv);
-        if (d > 0)
-           return 1;
-        return d? -1 : 0;
-     }
-     return sv_ncmp(aTHXo_ a, b);
-}
-
-static I32
-amagic_i_ncmp(pTHXo_ register SV *a, register SV *b)
-{
-    SV *tmpsv;
-    tryCALL_AMAGICbin(a,b,ncmp,&tmpsv);
-    if (tmpsv) {
-       NV d;
-       
-        if (SvIOK(tmpsv)) {
-            I32 i = SvIVX(tmpsv);
-            if (i > 0)
-               return 1;
-            return i? -1 : 0;
-        }
-        d = SvNV(tmpsv);
-        if (d > 0)
-           return 1;
-        return d? -1 : 0;
-    }
-    return sv_i_ncmp(aTHXo_ a, b);
-}
-
-static I32
-amagic_cmp(pTHXo_ register SV *str1, register SV *str2)
-{
-    SV *tmpsv;
-    tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
-    if (tmpsv) {
-       NV d;
-       
-        if (SvIOK(tmpsv)) {
-            I32 i = SvIVX(tmpsv);
-            if (i > 0)
-               return 1;
-            return i? -1 : 0;
-        }
-        d = SvNV(tmpsv);
-        if (d > 0)
-           return 1;
-        return d? -1 : 0;
-    }
-    return sv_cmp(str1, str2);
-}
-
-static I32
-amagic_cmp_locale(pTHXo_ register SV *str1, register SV *str2)
-{
-    SV *tmpsv;
-    tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
-    if (tmpsv) {
-       NV d;
-       
-        if (SvIOK(tmpsv)) {
-            I32 i = SvIVX(tmpsv);
-            if (i > 0)
-               return 1;
-            return i? -1 : 0;
-        }
-        d = SvNV(tmpsv);
-        if (d > 0)
-           return 1;
-        return d? -1 : 0;
-    }
-    return sv_cmp_locale(str1, str2);
-}
-
 static I32
-run_user_filter(pTHXo_ int idx, SV *buf_sv, int maxlen)
+run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
 {
     SV *datasv = FILTER_DATA(idx);
     int filter_has_file = IoLINES(datasv);
@@ -4453,18 +3689,21 @@ run_user_filter(pTHXo_ int idx, SV *buf_sv, int maxlen)
     return len;
 }
 
-#ifdef PERL_OBJECT
-
-static I32
-sv_cmp_locale_static(pTHXo_ register SV *str1, register SV *str2)
-{
-    return sv_cmp_locale(str1, str2);
-}
-
-static I32
-sv_cmp_static(pTHXo_ register SV *str1, register SV *str2)
+/* 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_ char *name)
 {
-    return sv_cmp(str1, str2);
+    if (PERL_FILE_IS_ABSOLUTE(name)
+#ifdef MACOS_TRADITIONAL
+       || (*name == ':'))
+#else
+       || (*name == '.' && (name[1] == '/' ||
+                            (name[1] == '.' && name[2] == '/'))))
+#endif
+    {
+       return TRUE;
+    }
+    else
+       return FALSE;
 }
-
-#endif /* PERL_OBJECT */