applied suggested patch with PERL_OBJECT tweaks
[p5sagit/p5-mst-13.2.git] / pp_ctl.c
index c586a72..a4fabd2 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -26,7 +26,7 @@
 #define DOCATCH(o) ((CATCH_GET == TRUE) ? docatch(o) : (o))
 
 #ifdef PERL_OBJECT
-#define CALLOP this->*op
+#define CALLOP this->*PL_op
 #else
 #define CALLOP *PL_op
 static OP *docatch _((OP *o));
@@ -41,6 +41,8 @@ static void save_lines _((AV *array, SV *sv));
 static I32 sortcv _((SV *a, SV *b));
 static void qsortsv _((SV **array, size_t num_elts, I32 (*fun)(SV *a, SV *b)));
 static OP *doeval _((int gimme, OP** startop));
+static I32 amagic_cmp _((SV *str1, SV *str2));
+static I32 amagic_cmp_locale _((SV *str1, SV *str2));
 #endif
 
 PP(pp_wantarray)
@@ -162,8 +164,9 @@ PP(pp_substcont)
 
        /* Are we done */
        if (cx->sb_once || !CALLREGEXEC(rx, s, cx->sb_strend, orig,
-                                    s == m, Nullsv, NULL,
-                                    cx->sb_safebase ? 0 : REXEC_COPY_STR))
+                                    s == m, cx->sb_targ, NULL,
+                                    ((cx->sb_rflags & REXEC_COPY_STR)
+                                     ? 0 : REXEC_COPY_STR)))
        {
            SV *targ = cx->sb_targ;
            sv_catpvn(dstr, s, cx->sb_strend - s);
@@ -287,6 +290,7 @@ PP(pp_formline)
     double value;
     bool gotsome;
     STRLEN len;
+    STRLEN fudge = SvCUR(tmpForm) * (IN_UTF8 ? 3 : 1) + 1;
 
     if (!SvMAGICAL(tmpForm) || !SvCOMPILED(tmpForm)) {
        SvREADONLY_off(tmpForm);
@@ -294,7 +298,7 @@ PP(pp_formline)
     }
 
     SvPV_force(PL_formtarget, len);
-    t = SvGROW(PL_formtarget, len + SvCUR(tmpForm) + 1);  /* XXX SvCUR bad */
+    t = SvGROW(PL_formtarget, len + fudge + 1);  /* XXX SvCUR bad */
     t += len;
     f = SvPV(tmpForm, len);
     /* need to jump to the next word */
@@ -356,14 +360,38 @@ PP(pp_formline)
                sv = *++MARK;
            else {
                sv = &PL_sv_no;
-               if (PL_dowarn)
-                   warn("Not enough format arguments");
+               if (ckWARN(WARN_SYNTAX))
+                   warner(WARN_SYNTAX, "Not enough format arguments");
            }
            break;
 
        case FF_CHECKNL:
            item = s = SvPV(sv, len);
            itemsize = len;
+           if (IN_UTF8) {
+               itemsize = sv_len_utf8(sv);
+               if (itemsize != len) {
+                   I32 itembytes;
+                   if (itemsize > fieldsize) {
+                       itemsize = fieldsize;
+                       itembytes = itemsize;
+                       sv_pos_u2b(sv, &itembytes, 0);
+                   }
+                   else
+                       itembytes = len;
+                   send = chophere = s + itembytes;
+                   while (s < send) {
+                       if (*s & ~31)
+                           gotsome = TRUE;
+                       else if (*s == '\n')
+                           break;
+                       s++;
+                   }
+                   itemsize = s - item;
+                   sv_pos_b2u(sv, &itemsize);
+                   break;
+               }
+           }
            if (itemsize > fieldsize)
                itemsize = fieldsize;
            send = chophere = s + itemsize;
@@ -380,6 +408,47 @@ PP(pp_formline)
        case FF_CHECKCHOP:
            item = s = SvPV(sv, len);
            itemsize = len;
+           if (IN_UTF8) {
+               itemsize = sv_len_utf8(sv);
+               if (itemsize != len) {
+                   I32 itembytes;
+                   if (itemsize <= fieldsize) {
+                       send = chophere = s + itemsize;
+                       while (s < send) {
+                           if (*s == '\r') {
+                               itemsize = s - item;
+                               break;
+                           }
+                           if (*s++ & ~31)
+                               gotsome = TRUE;
+                       }
+                   }
+                   else {
+                       itemsize = fieldsize;
+                       itembytes = itemsize;
+                       sv_pos_u2b(sv, &itembytes, 0);
+                       send = chophere = s + itembytes;
+                       while (s < send || (s == send && isSPACE(*s))) {
+                           if (isSPACE(*s)) {
+                               if (chopspace)
+                                   chophere = s;
+                               if (*s == '\r')
+                                   break;
+                           }
+                           else {
+                               if (*s & ~31)
+                                   gotsome = TRUE;
+                               if (strchr(PL_chopset, *s))
+                                   chophere = s + 1;
+                           }
+                           s++;
+                       }
+                       itemsize = chophere - item;
+                       sv_pos_b2u(sv, &itemsize);
+                   }
+                   break;
+               }
+           }
            if (itemsize <= fieldsize) {
                send = chophere = s + itemsize;
                while (s < send) {
@@ -435,16 +504,34 @@ PP(pp_formline)
        case FF_ITEM:
            arg = itemsize;
            s = item;
+           if (IN_UTF8) {
+               while (arg--) {
+                   if (*s & 0x80) {
+                       switch (UTF8SKIP(s)) {
+                       case 7: *t++ = *s++;
+                       case 6: *t++ = *s++;
+                       case 5: *t++ = *s++;
+                       case 4: *t++ = *s++;
+                       case 3: *t++ = *s++;
+                       case 2: *t++ = *s++;
+                       case 1: *t++ = *s++;
+                       }
+                   }
+                   else {
+                       if ( !((*t++ = *s++) & ~31) )
+                           t[-1] = ' ';
+                   }
+               }
+               break;
+           }
            while (arg--) {
-#if 'z' - 'a' != 25
+#ifdef EBCDIC
                int ch = *t++ = *s++;
-               if (!iscntrl(ch))
-                   t[-1] = ' ';
+               if (iscntrl(ch))
 #else
                if ( !((*t++ = *s++) & ~31) )
-                   t[-1] = ' ';
 #endif
-
+                   t[-1] = ' ';
            }
            break;
 
@@ -473,7 +560,7 @@ PP(pp_formline)
                }
                SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget));
                sv_catpvn(PL_formtarget, item, itemsize);
-               SvGROW(PL_formtarget, SvCUR(PL_formtarget) + SvCUR(tmpForm) + 1);
+               SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1);
                t = SvPVX(PL_formtarget) + SvCUR(PL_formtarget);
            }
            break;
@@ -531,7 +618,13 @@ PP(pp_formline)
            break;
 
        case FF_MORE:
-           if (itemsize) {
+           s = chophere;
+           send = item + len;
+           if (chopspace) {
+               while (*s && isSPACE(*s) && s < send)
+                   s++;
+           }
+           if (s < send) {
                arg = fieldsize - itemsize;
                if (arg) {
                    fieldsize -= arg;
@@ -663,6 +756,61 @@ PP(pp_mapwhile)
     }
 }
 
+#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_cmp(register SV *str1, register SV *str2)
+{
+    SV *tmpsv;
+    tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
+    if (tmpsv) {
+       double 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(register SV *str1, register SV *str2)
+{
+    SV *tmpsv;
+    tryCALL_AMAGICbin(str1,str2,scmp,&tmpsv);
+    if (tmpsv) {
+       double 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);
+}
+
 PP(pp_sort)
 {
     djSP; dMARK; dORIGMARK;
@@ -674,6 +822,7 @@ PP(pp_sort)
     CV *cv;
     I32 gimme = GIMME;
     OP* nextop = PL_op->op_next;
+    I32 overloading = 0;
 
     if (gimme != G_ARRAY) {
        SP = MARK;
@@ -710,7 +859,7 @@ PP(pp_sort)
            }
            PL_sortcop = CvSTART(cv);
            SAVESPTR(CvROOT(cv)->op_ppaddr);
-           CvROOT(cv)->op_ppaddr = ppaddr[OP_NULL];
+           CvROOT(cv)->op_ppaddr = PL_ppaddr[OP_NULL];
 
            SAVESPTR(PL_curpad);
            PL_curpad = AvARRAY((AV*)AvARRAY(CvPADLIST(cv))[1]);
@@ -726,8 +875,12 @@ PP(pp_sort)
        /*SUPPRESS 560*/
        if (*up = *++MARK) {                    /* Weed out nulls. */
            SvTEMP_off(*up);
-           if (!PL_sortcop && !SvPOK(*up))
-               (void)sv_2pv(*up, &PL_na);
+           if (!PL_sortcop && !SvPOK(*up)) {
+               if (SvAMAGIC(*up))
+                   overloading = 1;
+               else
+                   (void)sv_2pv(*up, &PL_na);
+           }
            up++;
        }
     }
@@ -765,6 +918,7 @@ PP(pp_sort)
            qsortsv((myorigmark+1), max, FUNC_NAME_TO_PTR(sortcv));
 
            POPBLOCK(cx,PL_curpm);
+           PL_stack_sp = newsp;
            POPSTACK;
            CATCH_SET(oldcatch);
        }
@@ -774,8 +928,12 @@ PP(pp_sort)
            MEXTEND(SP, 20);    /* Can't afford stack realloc on signal. */
            qsortsv(ORIGMARK+1, max,
                    (PL_op->op_private & OPpLOCALE)
-                   ? FUNC_NAME_TO_PTR(sv_cmp_locale)
-                   : FUNC_NAME_TO_PTR(sv_cmp));
+                   ? ( overloading
+                       ? FUNC_NAME_TO_PTR(amagic_cmp_locale)
+                       : FUNC_NAME_TO_PTR(sv_cmp_locale))
+                   : ( overloading 
+                       ? FUNC_NAME_TO_PTR(amagic_cmp)
+                       : FUNC_NAME_TO_PTR(sv_cmp) ));
        }
     }
     LEAVE;
@@ -856,6 +1014,7 @@ PP(pp_flop)
            char *tmps = SvPV(final, len);
 
            sv = sv_mortalcopy(left);
+           SvPV_force(sv,PL_na);
            while (!SvNIOKp(sv) && SvCUR(sv) <= len) {
                XPUSHs(sv);
                if (strEQ(SvPVX(sv),tmps))
@@ -892,22 +1051,26 @@ dopoptolabel(char *label)
 
     for (i = cxstack_ix; i >= 0; i--) {
        cx = &cxstack[i];
-       switch (cx->cx_type) {
+       switch (CxTYPE(cx)) {
        case CXt_SUBST:
-           if (PL_dowarn)
-               warn("Exiting substitution via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting substitution via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_SUB:
-           if (PL_dowarn)
-               warn("Exiting subroutine via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting subroutine via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_EVAL:
-           if (PL_dowarn)
-               warn("Exiting eval via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting eval via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_NULL:
-           if (PL_dowarn)
-               warn("Exiting pseudo-block via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting pseudo-block via %s", 
+                       PL_op_name[PL_op->op_type]);
            return -1;
        case CXt_LOOP:
            if (!cx->blk_loop.label ||
@@ -969,7 +1132,7 @@ dopoptosub_at(PERL_CONTEXT *cxstk, I32 startingblock)
     register PERL_CONTEXT *cx;
     for (i = startingblock; i >= 0; i--) {
        cx = &cxstk[i];
-       switch (cx->cx_type) {
+       switch (CxTYPE(cx)) {
        default:
            continue;
        case CXt_EVAL:
@@ -989,7 +1152,7 @@ dopoptoeval(I32 startingblock)
     register PERL_CONTEXT *cx;
     for (i = startingblock; i >= 0; i--) {
        cx = &cxstack[i];
-       switch (cx->cx_type) {
+       switch (CxTYPE(cx)) {
        default:
            continue;
        case CXt_EVAL:
@@ -1008,22 +1171,26 @@ dopoptoloop(I32 startingblock)
     register PERL_CONTEXT *cx;
     for (i = startingblock; i >= 0; i--) {
        cx = &cxstack[i];
-       switch (cx->cx_type) {
+       switch (CxTYPE(cx)) {
        case CXt_SUBST:
-           if (PL_dowarn)
-               warn("Exiting substitution via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting substitution via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_SUB:
-           if (PL_dowarn)
-               warn("Exiting subroutine via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting subroutine via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_EVAL:
-           if (PL_dowarn)
-               warn("Exiting eval via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting eval via %s", 
+                       PL_op_name[PL_op->op_type]);
            break;
        case CXt_NULL:
-           if (PL_dowarn)
-               warn("Exiting pseudo-block via %s", op_name[PL_op->op_type]);
+           if (ckWARN(WARN_UNSAFE))
+               warner(WARN_UNSAFE, "Exiting pseudo-block via %s", 
+                       PL_op_name[PL_op->op_type]);
            return -1;
        case CXt_LOOP:
            DEBUG_l( deb("(Found loop #%ld)\n", (long)i));
@@ -1044,9 +1211,9 @@ dounwind(I32 cxix)
     while (cxstack_ix > cxix) {
        cx = &cxstack[cxstack_ix];
        DEBUG_l(PerlIO_printf(Perl_debug_log, "Unwinding block %ld, type %s\n",
-                             (long) cxstack_ix, block_type[cx->cx_type]));
+                             (long) cxstack_ix, PL_block_type[CxTYPE(cx)]));
        /* Note: we don't need to restore the base context info till the end. */
-       switch (cx->cx_type) {
+       switch (CxTYPE(cx)) {
        case CXt_SUBST:
            POPSUBST(cx);
            continue;  /* not break */
@@ -1093,6 +1260,10 @@ die_where(char *message)
                        SvGROW(err, SvCUR(err)+sizeof(prefix)+klen);
                        sv_catpvn(err, prefix, sizeof(prefix)-1);
                        sv_catpvn(err, message, klen);
+                       if (ckWARN(WARN_UNSAFE)) {
+                           STRLEN start = SvCUR(err)-klen-sizeof(prefix)+1;
+                           warner(WARN_UNSAFE, SvPVX(err)+start);
+                       }
                    }
                    sv_inc(*svp);
                }
@@ -1115,7 +1286,7 @@ die_where(char *message)
                dounwind(cxix);
 
            POPBLOCK(cx,PL_curpm);
-           if (cx->cx_type != CXt_EVAL) {
+           if (CxTYPE(cx) != CXt_EVAL) {
                PerlIO_printf(PerlIO_stderr(), "panic: die %s", message);
                my_exit(1);
            }
@@ -1134,6 +1305,8 @@ die_where(char *message)
            return pop_return();
        }
     }
+    if (!message)
+       message = SvPVx(ERRSV, PL_na);
     PerlIO_printf(PerlIO_stderr(), "%s",message);
     PerlIO_flush(PerlIO_stderr());
     my_failure_exit();
@@ -1205,7 +1378,7 @@ PP(pp_caller)
     }
 
     cx = &ccstack[cxix];
-    if (ccstack[cxix].cx_type == CXt_SUB) {
+    if (CxTYPE(cx) == CXt_SUB) {
         dbcxix = dopoptosub_at(ccstack, cxix - 1);
        /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the
           field below is defined for any cx. */
@@ -1234,7 +1407,7 @@ PP(pp_caller)
     PUSHs(sv_2mortal(newSViv((I32)cx->blk_oldcop->cop_line)));
     if (!MAXARG)
        RETURN;
-    if (cx->cx_type == CXt_SUB) { /* So is ccstack[dbcxix]. */
+    if (CxTYPE(cx) == CXt_SUB) { /* So is ccstack[dbcxix]. */
        sv = NEWSV(49, 0);
        gv_efullname3(sv, CvGV(ccstack[cxix].blk_sub.cv), Nullch);
        PUSHs(sv_2mortal(sv));
@@ -1249,7 +1422,7 @@ PP(pp_caller)
        PUSHs(&PL_sv_undef);
     else
        PUSHs(sv_2mortal(newSViv(gimme & G_ARRAY)));
-    if (cx->cx_type == CXt_EVAL) {
+    if (CxTYPE(cx) == CXt_EVAL) {
        if (cx->blk_eval.old_op_type == OP_ENTEREVAL) {
            PUSHs(cx->blk_eval.cur_text);
            PUSHs(&PL_sv_no);
@@ -1260,7 +1433,7 @@ PP(pp_caller)
            PUSHs(&PL_sv_yes);
        }
     }
-    else if (cx->cx_type == CXt_SUB &&
+    else if (CxTYPE(cx) == CXt_SUB &&
            cx->blk_sub.hasargs &&
            PL_curcop->cop_stash == PL_debstash)
     {
@@ -1517,7 +1690,7 @@ PP(pp_return)
        dounwind(cxix);
 
     POPBLOCK(cx,newpm);
-    switch (cx->cx_type) {
+    switch (CxTYPE(cx)) {
     case CXt_SUB:
        POPSUB1(cx);    /* Delay POPSUB2 until stack values are safe */
        popsub2 = TRUE;
@@ -1605,7 +1778,7 @@ PP(pp_last)
        dounwind(cxix);
 
     POPBLOCK(cx,newpm);
-    switch (cx->cx_type) {
+    switch (CxTYPE(cx)) {
     case CXt_LOOP:
        POPLOOP1(cx);   /* Delay POPLOOP2 until stack values are safe */
        pop2 = CXt_LOOP;
@@ -1780,11 +1953,23 @@ PP(pp_goto)
            SV** mark;
            I32 items = 0;
            I32 oldsave;
+           int arg_was_real = 0;
 
+       retry:
            if (!CvROOT(cv) && !CvXSUB(cv)) {
-               if (CvGV(cv)) {
-                   SV *tmpstr = sv_newmortal();
-                   gv_efullname3(tmpstr, CvGV(cv), Nullch);
+               GV *gv = CvGV(cv);
+               GV *autogv;
+               if (gv) {
+                   SV *tmpstr;
+                   /* autoloaded stub? */
+                   if (cv != GvCV(gv) && (cv = GvCV(gv)))
+                       goto retry;
+                   autogv = gv_autoload4(GvSTASH(gv), GvNAME(gv),
+                                         GvNAMELEN(gv), FALSE);
+                   if (autogv && (cv = GvCV(autogv)))
+                       goto retry;
+                   tmpstr = sv_newmortal();
+                   gv_efullname3(tmpstr, gv, Nullch);
                    DIE("Goto undefined subroutine &%s",SvPVX(tmpstr));
                }
                DIE("Goto undefined subroutine");
@@ -1797,10 +1982,10 @@ PP(pp_goto)
            if (cxix < cxstack_ix)
                dounwind(cxix);
            TOPBLOCK(cx);
-           if (cx->cx_type == CXt_EVAL && cx->blk_eval.old_op_type == OP_ENTEREVAL) 
+           if (CxTYPE(cx) == CXt_EVAL && cx->blk_eval.old_op_type == OP_ENTEREVAL) 
                DIE("Can't goto subroutine from an eval-string");
            mark = PL_stack_sp;
-           if (cx->cx_type == CXt_SUB &&
+           if (CxTYPE(cx) == CXt_SUB &&
                cx->blk_sub.hasargs) {   /* put @_ back onto stack */
                AV* av = cx->blk_sub.argarray;
                
@@ -1813,7 +1998,10 @@ PP(pp_goto)
                SvREFCNT_dec(GvAV(PL_defgv));
                GvAV(PL_defgv) = cx->blk_sub.savearray;
 #endif /* USE_THREADS */
-               AvREAL_off(av);
+               if (AvREAL(av)) {
+                   arg_was_real = 1;
+                   AvREAL_off(av);     /* so av_clear() won't clobber elts */
+               }
                av_clear(av);
            }
            else if (CvXSUB(cv)) {      /* put GvAV(defgv) back onto stack */
@@ -1830,7 +2018,7 @@ PP(pp_goto)
                Copy(AvARRAY(av), PL_stack_sp, items, SV*);
                PL_stack_sp += items;
            }
-           if (cx->cx_type == CXt_SUB &&
+           if (CxTYPE(cx) == CXt_SUB &&
                !(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))
                SvREFCNT_dec(cx->blk_sub.cv);
            oldsave = PL_scopestack[PL_scopestack_ix - 1];
@@ -1869,7 +2057,7 @@ PP(pp_goto)
            else {
                AV* padlist = CvPADLIST(cv);
                SV** svp = AvARRAY(padlist);
-               if (cx->cx_type == CXt_EVAL) {
+               if (CxTYPE(cx) == CXt_EVAL) {
                    PL_in_eval = cx->blk_eval.old_in_eval;
                    PL_eval_root = cx->blk_eval.old_eval_root;
                    cx->cx_type = CXt_SUB;
@@ -1881,7 +2069,7 @@ PP(pp_goto)
                if (CvDEPTH(cv) < 2)
                    (void)SvREFCNT_inc(cv);
                else {  /* save temporaries on recursion? */
-                   if (CvDEPTH(cv) == 100 && PL_dowarn)
+                   if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
                        sub_crush_depth(cv);
                    if (CvDEPTH(cv) > AvFILLp(padlist)) {
                        AV *newpad = newAV();
@@ -1969,7 +2157,11 @@ PP(pp_goto)
                    }
                    Copy(mark,AvARRAY(av),items,SV*);
                    AvFILLp(av) = items - 1;
-                   
+                   /* preserve @_ nature */
+                   if (arg_was_real) {
+                       AvREIFY_off(av);
+                       AvREAL_on(av);
+                   }
                    while (items--) {
                        if (*mark)
                            SvTEMP_off(*mark);
@@ -2019,7 +2211,7 @@ PP(pp_goto)
        *enterops = 0;
        for (ix = cxstack_ix; ix >= 0; ix--) {
            cx = &cxstack[ix];
-           switch (cx->cx_type) {
+           switch (CxTYPE(cx)) {
            case CXt_EVAL:
                gotoprobe = PL_eval_root; /* XXX not good for nested eval */
                break;
@@ -2089,7 +2281,7 @@ PP(pp_goto)
 
     if (do_dump) {
 #ifdef VMS
-       if (!retop) retop = main_start;
+       if (!retop) retop = PL_main_start;
 #endif
        PL_restartop = retop;
        PL_do_undump = TRUE;
@@ -2100,11 +2292,6 @@ PP(pp_goto)
        PL_do_undump = FALSE;
     }
 
-    if (PL_top_env->je_prev) {
-        PL_restartop = retop;
-        JMPENV_JUMP(3);
-    }
-
     RETURNOP(retop);
 }
 
@@ -2143,8 +2330,8 @@ PP(pp_nswitch)
        match = 0;
     else if (match > cCOP->uop.scop.scop_max)
        match = cCOP->uop.scop.scop_max;
-    op = cCOP->uop.scop.scop_next[match];
-    RETURNOP(op);
+    PL_op = cCOP->uop.scop.scop_next[match];
+    RETURNOP(PL_op);
 }
 
 PP(pp_cswitch)
@@ -2152,18 +2339,18 @@ PP(pp_cswitch)
     djSP;
     register I32 match;
 
-    if (multiline)
-       op = op->op_next;                       /* can't assume anything */
+    if (PL_multiline)
+       PL_op = PL_op->op_next;                 /* can't assume anything */
     else {
-       match = *(SvPVx(GvSV(cCOP->cop_gv), na)) & 255;
+       match = *(SvPVx(GvSV(cCOP->cop_gv), PL_na)) & 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;
-       op = cCOP->uop.scop.scop_next[match];
+       PL_op = cCOP->uop.scop.scop_next[match];
     }
-    RETURNOP(op);
+    RETURNOP(PL_op);
 }
 #endif
 
@@ -2209,15 +2396,14 @@ docatch(OP *o)
     JMPENV_PUSH(ret);
     switch (ret) {
     default:                           /* topmost level handles it */
+pass_the_buck:
        JMPENV_POP;
        PL_op = oldop;
        JMPENV_JUMP(ret);
        /* NOTREACHED */
     case 3:
-       if (!PL_restartop) {
-           PerlIO_printf(PerlIO_stderr(), "panic: restartop\n");
-           break;
-       }
+       if (!PL_restartop)
+           goto pass_the_buck;
        PL_op = PL_restartop;
        PL_restartop = 0;
        /* FALL THROUGH */
@@ -2251,6 +2437,10 @@ sv_compile_2op(SV *sv, OP** startop, char *code, AV** avp)
     SAVETMPS;
     /* switch to eval mode */
 
+    if (PL_curcop == &PL_compiling) {
+       SAVESPTR(PL_compiling.cop_stash);
+       PL_compiling.cop_stash = PL_curstash;
+    }
     SAVESPTR(PL_compiling.cop_filegv);
     SAVEI16(PL_compiling.cop_line);
     sprintf(tmpbuf, "_<(%.10s_eval %lu)", code, (unsigned long)++PL_evalseq);
@@ -2265,28 +2455,30 @@ sv_compile_2op(SV *sv, OP** startop, char *code, AV** avp)
     SAVEDELETE(PL_defstash, safestr, strlen(safestr));
     SAVEHINTS();
 #ifdef OP_IN_REGISTER
-    opsave = op;
+    PL_opsave = op;
 #else
     SAVEPPTR(PL_op);
 #endif
     PL_hints = 0;
 
     PL_op = &dummy;
-    PL_op->op_type = 0;                        /* Avoid uninit warning. */
+    PL_op->op_type = OP_ENTEREVAL;
     PL_op->op_flags = 0;                       /* Avoid uninit warning. */
     PUSHBLOCK(cx, CXt_EVAL, SP);
-    PUSHEVAL(cx, 0, compiling.cop_filegv);
+    PUSHEVAL(cx, 0, PL_compiling.cop_filegv);
     rop = doeval(G_SCALAR, startop);
     POPBLOCK(cx,PL_curpm);
     POPEVAL(cx);
 
     (*startop)->op_type = OP_NULL;
-    (*startop)->op_ppaddr = ppaddr[OP_NULL];
+    (*startop)->op_ppaddr = PL_ppaddr[OP_NULL];
     lex_end();
     *avp = (AV*)SvREFCNT_inc(PL_comppad);
     LEAVE;
+    if (PL_curcop == &PL_compiling)
+       PL_compiling.op_private = PL_hints;
 #ifdef OP_IN_REGISTER
-    op = opsave;
+    op = PL_opsave;
 #endif
     return rop;
 }
@@ -2319,9 +2511,9 @@ doeval(int gimme, OP** startop)
     caller = PL_compcv;
     for (i = cxstack_ix - 1; i >= 0; i--) {
        PERL_CONTEXT *cx = &cxstack[i];
-       if (cx->cx_type == CXt_EVAL)
+       if (CxTYPE(cx) == CXt_EVAL)
            break;
-       else if (cx->cx_type == CXt_SUB) {
+       else if (CxTYPE(cx) == CXt_SUB) {
            caller = cx->blk_sub.cv;
            break;
        }
@@ -2539,6 +2731,7 @@ PP(pp_require)
 #else
                sv_setpvf(namesv, "%s/%s", dir, name);
 #endif
+               TAINT_PROPER("require");
                tryname = SvPVX(namesv);
                tryrsfp = PerlIO_open(tryname, PERL_SCRIPT_MODE);
                if (tryrsfp) {
@@ -2575,6 +2768,8 @@ PP(pp_require)
 
        RETPUSHUNDEF;
     }
+    else
+       SETERRNO(0, SS$_NORMAL);
 
     /* Assume success here to prevent recursive requirement. */
     (void)hv_store(GvHVn(PL_incgv), name, strlen(name),
@@ -2583,23 +2778,25 @@ PP(pp_require)
     ENTER;
     SAVETMPS;
     lex_start(sv_2mortal(newSVpv("",0)));
-    if (PL_rsfp_filters){
-       save_aptr(&PL_rsfp_filters);
-       PL_rsfp_filters = NULL;
-    }
+    SAVEGENERICSV(PL_rsfp_filters);
+    PL_rsfp_filters = Nullav;
 
     PL_rsfp = tryrsfp;
     name = savepv(name);
     SAVEFREEPV(name);
     SAVEHINTS();
     PL_hints = 0;
+    SAVEPPTR(PL_compiling.cop_warnings);
+    PL_compiling.cop_warnings = ((PL_dowarn & G_WARN_ALL_ON) ? WARN_ALL 
+                                                            : WARN_NONE);
  
     /* switch to eval mode */
 
     push_return(PL_op->op_next);
     PUSHBLOCK(cx, CXt_EVAL, SP);
-    PUSHEVAL(cx, name, compiling.cop_filegv);
+    PUSHEVAL(cx, name, PL_compiling.cop_filegv);
 
+    SAVEI16(PL_compiling.cop_line);
     PL_compiling.cop_line = 0;
 
     PUTBACK;
@@ -2653,10 +2850,16 @@ PP(pp_entereval)
     SAVEDELETE(PL_defstash, safestr, strlen(safestr));
     SAVEHINTS();
     PL_hints = PL_op->op_targ;
+    SAVEPPTR(PL_compiling.cop_warnings);
+    if (PL_compiling.cop_warnings != WARN_ALL 
+       && PL_compiling.cop_warnings != WARN_NONE){
+        PL_compiling.cop_warnings = newSVsv(PL_compiling.cop_warnings) ;
+        SAVEFREESV(PL_compiling.cop_warnings) ;
+    }
 
     push_return(PL_op->op_next);
-    PUSHBLOCK(cx, CXt_EVAL, SP);
-    PUSHEVAL(cx, 0, compiling.cop_filegv);
+    PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
+    PUSHEVAL(cx, 0, PL_compiling.cop_filegv);
 
     /* prepare to compile string */