[win32] merge change#904 from maintbranch
[p5sagit/p5-mst-13.2.git] / pp_ctl.c
index 33247e3..1ee85a6 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -86,11 +86,10 @@ PP(pp_regcomp) {
     else {
        t = SvPV(tmpstr, len);
 
-       /* JMR: Check against the last compiled regexp
-          To know for sure, we'd need the length of precomp.
-          But we don't have it, so we must ... take a guess. */
+       /* Check against the last compiled regexp. */
        if (!pm->op_pmregexp || !pm->op_pmregexp->precomp ||
-           memNE(pm->op_pmregexp->precomp, t, len + 1))
+           pm->op_pmregexp->prelen != len ||
+           memNE(pm->op_pmregexp->precomp, t, len))
        {
            if (pm->op_pmregexp) {
                ReREFCNT_dec(pm->op_pmregexp);
@@ -535,7 +534,7 @@ PP(pp_grepstart)
     djSP;
     SV *src;
 
-    if (stack_base + *markstack_ptr == sp) {
+    if (stack_base + *markstack_ptr == SP) {
        (void)POPMARK;
        if (GIMME_V == G_SCALAR)
            XPUSHs(&sv_no);
@@ -574,7 +573,7 @@ PP(pp_mapstart)
 PP(pp_mapwhile)
 {
     djSP;
-    I32 diff = (sp - stack_base) - *markstack_ptr;
+    I32 diff = (SP - stack_base) - *markstack_ptr;
     I32 count;
     I32 shift;
     SV** src;
@@ -584,11 +583,11 @@ PP(pp_mapwhile)
     if (diff) {
        if (diff > markstack_ptr[-1] - markstack_ptr[-2]) {
            shift = diff - (markstack_ptr[-1] - markstack_ptr[-2]);
-           count = (sp - stack_base) - markstack_ptr[-1] + 2;
+           count = (SP - stack_base) - markstack_ptr[-1] + 2;
            
-           EXTEND(sp,shift);
-           src = sp;
-           dst = (sp += shift);
+           EXTEND(SP,shift);
+           src = SP;
+           dst = (SP += shift);
            markstack_ptr[-1] += shift;
            *markstack_ptr += shift;
            while (--count)
@@ -652,8 +651,9 @@ PP(pp_sort)
        RETPUSHUNDEF;
     }
 
+    ENTER;
+    SAVEPPTR(sortcop);
     if (op->op_flags & OPf_STACKED) {
-       ENTER;
        if (op->op_flags & OPf_SPECIAL) {
            OP *kid = cLISTOP->op_first->op_sibling;    /* pass pushmark */
            kid = kUNOP->op_first;                      /* pass rv2gv */
@@ -705,7 +705,6 @@ PP(pp_sort)
     max = --up - myorigmark;
     if (sortcop) {
        if (max > 1) {
-           AV *oldstack;
            PERL_CONTEXT *cx;
            SV** newsp;
            bool oldcatch = CATCH_GET;
@@ -713,14 +712,8 @@ PP(pp_sort)
            SAVETMPS;
            SAVEOP();
 
-           oldstack = curstack;
-           if (!sortstack) {
-               sortstack = newAV();
-               AvREAL_off(sortstack);
-               av_extend(sortstack, 32);
-           }
            CATCH_SET(TRUE);
-           SWITCHSTACK(curstack, sortstack);
+           PUSHSTACK(SI_SORT);
            if (sortstash != stash) {
                firstgv = gv_fetchpv("a", TRUE, SVt_PV);
                secondgv = gv_fetchpv("b", TRUE, SVt_PV);
@@ -744,10 +737,9 @@ PP(pp_sort)
            qsortsv(myorigmark+1, max, sortcv);
 
            POPBLOCK(cx,curpm);
-           SWITCHSTACK(sortstack, oldstack);
+           POPSTACK();
            CATCH_SET(oldcatch);
        }
-       LEAVE;
     }
     else {
        if (max > 1) {
@@ -756,6 +748,7 @@ PP(pp_sort)
                  (op->op_private & OPpLOCALE) ? sv_cmp_locale : sv_cmp);
        }
     }
+    LEAVE;
     stack_sp = ORIGMARK + max;
     return nextop;
 }
@@ -791,7 +784,7 @@ PP(pp_flip)
            }
            else {
                sv_setiv(targ, 0);
-               sp--;
+               SP--;
                RETURNOP(((CONDOP*)cUNOP->op_first)->op_false);
            }
        }
@@ -1036,7 +1029,7 @@ dounwind(I32 cxix)
 OP *
 die_where(char *message)
 {
-    dTHR;
+    dSP;
     if (in_eval) {
        I32 cxix;
        register PERL_CONTEXT *cx;
@@ -1066,7 +1059,11 @@ die_where(char *message)
        else
            sv_setpv(ERRSV, message);
        
-       cxix = dopoptoeval(cxstack_ix);
+       while ((cxix = dopoptoeval(cxstack_ix)) < 0 && curstackinfo->si_prev) {
+           dounwind(-1);
+           POPSTACK();
+       }
+
        if (cxix >= 0) {
            I32 optype;
 
@@ -1285,7 +1282,7 @@ PP(pp_dbstate)
 
     if (op->op_private || SvIV(DBsingle) || SvIV(DBsignal) || SvIV(DBtrace))
     {
-       SV **sp;
+       djSP;
        register CV *cv;
        register PERL_CONTEXT *cx;
        I32 gimme = G_ARRAY;
@@ -1307,10 +1304,10 @@ PP(pp_dbstate)
        SAVESTACK_POS();
        debug = 0;
        hasargs = 0;
-       sp = stack_sp;
+       SPAGAIN;
 
        push_return(op->op_next);
-       PUSHBLOCK(cx, CXt_SUB, sp);
+       PUSHBLOCK(cx, CXt_SUB, SP);
        PUSHSUB(cx);
        CvDEPTH(cv)++;
        (void)SvREFCNT_inc(cv);
@@ -1360,7 +1357,7 @@ PP(pp_enteriter)
        cx->blk_loop.iterary = (AV*)SvREFCNT_inc(POPs);
     else {
        cx->blk_loop.iterary = curstack;
-       AvFILLp(curstack) = sp - stack_base;
+       AvFILLp(curstack) = SP - stack_base;
        cx->blk_loop.iterix = MARK - stack_base;
     }
 
@@ -1436,7 +1433,7 @@ PP(pp_return)
     PMOP *newpm;
     I32 optype = 0;
 
-    if (curstack == sortstack) {
+    if (curstackinfo->si_type == SI_SORT) {
        if (cxstack_ix == sortcxix || dopoptosub(cxstack_ix) <= sortcxix) {
            if (cxstack_ix > sortcxix)
                dounwind(sortcxix);
@@ -1722,8 +1719,11 @@ 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) 
+               DIE("Can't goto subroutine from an eval-string");
            mark = stack_sp;
-           if (cx->blk_sub.hasargs) {   /* put @_ back onto stack */
+           if (cx->cx_type == CXt_SUB &&
+               cx->blk_sub.hasargs) {   /* put @_ back onto stack */
                AV* av = cx->blk_sub.argarray;
                
                items = AvFILLp(av) + 1;
@@ -1738,7 +1738,8 @@ PP(pp_goto)
                AvREAL_off(av);
                av_clear(av);
            }
-           if (!(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))
+           if (cx->cx_type == CXt_SUB &&
+               !(CvDEPTH(cx->blk_sub.cv) = cx->blk_sub.olddepth))
                SvREFCNT_dec(cx->blk_sub.cv);
            oldsave = scopestack[scopestack_ix - 1];
            LEAVE_SCOPE(oldsave);
@@ -1748,15 +1749,15 @@ PP(pp_goto)
            if (CvXSUB(cv)) {
                if (CvOLDSTYLE(cv)) {
                    I32 (*fp3)_((int,int,int));
-                   while (sp > mark) {
-                       sp[1] = sp[0];
-                       sp--;
+                   while (SP > mark) {
+                       SP[1] = SP[0];
+                       SP--;
                    }
                    fp3 = (I32(*)_((int,int,int)))CvXSUB(cv);
                    items = (*fp3)(CvXSUBANY(cv).any_i32,
                                   mark - stack_base + 1,
                                   items);
-                   sp = stack_base + items;
+                   SP = stack_base + items;
                }
                else {
                    stack_sp--;         /* There is no cv arg. */
@@ -1768,6 +1769,12 @@ PP(pp_goto)
            else {
                AV* padlist = CvPADLIST(cv);
                SV** svp = AvARRAY(padlist);
+               if (cx->cx_type == CXt_EVAL) {
+                   in_eval = cx->blk_eval.old_in_eval;
+                   eval_root = cx->blk_eval.old_eval_root;
+                   cx->cx_type = CXt_SUB;
+                   cx->blk_sub.hasargs = 0;
+               }
                cx->blk_sub.cv = cv;
                cx->blk_sub.olddepth = CvDEPTH(cv);
                CvDEPTH(cv)++;
@@ -1824,9 +1831,9 @@ PP(pp_goto)
                    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;
+                       EXTEND(SP, items);
+                       Copy(AvARRAY(av), SP + 1, items, SV*);
+                       SP += items;
                        PUTBACK ;                   
                    }
                }
@@ -1869,14 +1876,26 @@ PP(pp_goto)
                        mark++;
                    }
                }
-               if (PERLDB_SUB && curstash != debstash) {
+               if (PERLDB_SUB) {       /* Checking curstash breaks DProf. */
                    /*
                     * We do not care about using sv to call CV;
                     * it's for informational purposes only.
                     */
                    SV *sv = GvSV(DBsub);
-                   save_item(sv);
-                   gv_efullname3(sv, CvGV(cv), Nullch);
+                   CV *gotocv;
+                   
+                   if (PERLDB_SUB_NN) {
+                       SvIVX(sv) = (IV)cv; /* Already upgraded, saved */
+                   } else {
+                       save_item(sv);
+                       gv_efullname3(sv, CvGV(cv), Nullch);
+                   }
+                   if (  PERLDB_GOTO
+                         && (gotocv = perl_get_cv("DB::goto", FALSE)) ) {
+                       PUSHMARK( stack_sp );
+                       perl_call_sv((SV*)gotocv, G_SCALAR | G_NODEBUG);
+                       stack_sp--;
+                   }
                }
                RETURNOP(CvSTART(cv));
            }
@@ -1981,7 +2000,7 @@ PP(pp_goto)
        do_undump = FALSE;
     }
 
-    if (curstack == signalstack) {
+    if (top_env->je_prev) {
         restartop = retop;
         JMPENV_JUMP(3);
     }
@@ -2145,7 +2164,11 @@ sv_compile_2op(SV *sv, OP** startop, char *code, AV** avp)
     safestr = savepv(tmpbuf);
     SAVEDELETE(defstash, safestr, strlen(safestr));
     SAVEI32(hints);
+#ifdef OP_IN_REGISTER
+    opsave = op;
+#else
     SAVEPPTR(op);
+#endif
     hints = 0;
 
     op = &dummy;
@@ -2162,6 +2185,9 @@ sv_compile_2op(SV *sv, OP** startop, char *code, AV** avp)
     lex_end();
     *avp = (AV*)SvREFCNT_inc(comppad);
     LEAVE;
+#ifdef OP_IN_REGISTER
+    op = opsave;
+#endif
     return rop;
 }
 
@@ -2320,7 +2346,7 @@ doeval(int gimme, OP** startop)
        CV *cv = perl_get_cv("DB::postponed", FALSE);
        if (cv) {
            dSP;
-           PUSHMARK(sp);
+           PUSHMARK(SP);
            XPUSHs((SV*)compiling.cop_filegv);
            PUTBACK;
            perl_call_sv((SV*)cv, G_DISCARD);
@@ -2348,6 +2374,7 @@ PP(pp_require)
     register PERL_CONTEXT *cx;
     SV *sv;
     char *name;
+    STRLEN len;
     char *tryname;
     SV *namesv = Nullsv;
     SV** svp;
@@ -2362,12 +2389,12 @@ PP(pp_require)
                SvPV(sv,na),patchlevel);
        RETPUSHYES;
     }
-    name = SvPV(sv, na);
-    if (!*name)
+    name = SvPV(sv, len);
+    if (!(name && len > 0 && *name))
        DIE("Null filename used");
     TAINT_PROPER("require");
     if (op->op_type == OP_REQUIRE &&
-      (svp = hv_fetch(GvHVn(incgv), name, SvCUR(sv), 0)) &&
+      (svp = hv_fetch(GvHVn(incgv), name, len, 0)) &&
       *svp != &sv_undef)
        RETPUSHYES;
 
@@ -2427,7 +2454,7 @@ PP(pp_require)
     SvREFCNT_dec(namesv);
     if (!tryrsfp) {
        if (op->op_type == OP_REQUIRE) {
-           SV *msg = sv_2mortal(newSVpvf("Can't locate %s in @INC", name));
+           SV *msg = sv_2mortal(newSVpvf("Can't locate file '%s' in @INC", name));
            SV *dirmsgsv = NEWSV(0, 0);
            AV *ar = GvAVn(incgv);
            I32 i;
@@ -2629,21 +2656,22 @@ PP(pp_leaveeval)
     assert(CvDEPTH(compcv) == 1);
 #endif
     CvDEPTH(compcv) = 0;
+    lex_end();
 
     if (optype == OP_REQUIRE &&
-       !(gimme == G_SCALAR ? SvTRUE(*sp) : sp > newsp))
+       !(gimme == G_SCALAR ? SvTRUE(*SP) : SP > newsp))
     {
        /* Unassume the success we assumed earlier. */
        char *name = cx->blk_eval.old_name;
        (void)hv_delete(GvHVn(incgv), name, strlen(name), G_DISCARD);
        retop = die("%s did not return a true value", name);
+       /* die_where() did LEAVE, or we won't be here */
+    }
+    else {
+       LEAVE;
+       if (!(save_flags & OPf_SPECIAL))
+           sv_setpv(ERRSV,"");
     }
-
-    lex_end();
-    LEAVE;
-
-    if (!(save_flags & OPf_SPECIAL))
-       sv_setpv(ERRSV,"");
 
     RETURNOP(retop);
 }
@@ -3547,9 +3575,10 @@ qsortsv(
             if (j != i) {
                /* Looks like we really need to move some things
                */
+              int k;
               temp = array[i];
-              for (--i; i >= j; --i)
-                 array[i + 1] = array[i];
+              for (k = i - 1; k >= j; --k)
+                 array[k + 1] = array[k];
                array[j] = temp;
             }
          }