remove the return stack PL_retstack, and store return ops in the CX
[p5sagit/p5-mst-13.2.git] / pp_ctl.c
index 5a7fdaa..c8dd1ae 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1,7 +1,7 @@
 /*    pp_ctl.c
  *
  *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- *    2000, 2001, 2002, 2003, by Larry Wall and others
+ *    2000, 2001, 2002, 2003, 2004, by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -59,6 +59,7 @@ PP(pp_regcreset)
     /* XXXX Should store the old value to allow for tie/overload - and
        restore in regcomp, where marked with XXXX. */
     PL_reginterp_cnt = 0;
+    TAINT_NOT;
     return NORMAL;
 }
 
@@ -158,14 +159,11 @@ PP(pp_substcont)
     char *orig = cx->sb_orig;
     register REGEXP *rx = cx->sb_rx;
     SV *nsv = Nullsv;
-
-    { 
-      REGEXP *old = PM_GETRE(pm);
-      if(old != rx) {
+    REGEXP *old = PM_GETRE(pm);
+    if(old != rx) {
        if(old) 
-         ReREFCNT_dec(old);
+           ReREFCNT_dec(old);
        PM_SETRE(pm,rx);
-      }
     }
 
     rxres_restore(&cx->sb_rxres, rx);
@@ -189,10 +187,13 @@ PP(pp_substcont)
        {
            SV *targ = cx->sb_targ;
 
-           if (DO_UTF8(dstr) && !SvUTF8(targ))
-               sv_catpvn_utf8_upgrade(dstr, s, cx->sb_strend - s, nsv);
-           else
-               sv_catpvn(dstr, s, cx->sb_strend - s);
+           assert(cx->sb_strend >= s);
+           if(cx->sb_strend > s) {
+                if (DO_UTF8(dstr) && !SvUTF8(targ))
+                     sv_catpvn_utf8_upgrade(dstr, s, cx->sb_strend - s, nsv);
+                else
+                     sv_catpvn(dstr, s, cx->sb_strend - s);
+           }
            cx->sb_rxtainted |= RX_MATCH_TAINTED(rx);
 
 #ifdef PERL_COPY_ON_WRITE
@@ -258,7 +259,8 @@ PP(pp_substcont)
            sv_pos_b2u(sv, &i);
        mg->mg_len = i;
     }
-    ReREFCNT_inc(rx);
+    if (old != rx)
+       ReREFCNT_inc(rx);
     cx->sb_rxtainted |= RX_MATCH_TAINTED(rx);
     rxres_save(&cx->sb_rxres, rx);
     RETURNOP(pm->op_pmreplstart);
@@ -370,15 +372,20 @@ PP(pp_formline)
     bool item_is_utf8 = FALSE;
     bool targ_is_utf8 = FALSE;
     SV * nsv = Nullsv;
+    OP * parseres = 0;
+    char *fmt;
+    bool oneline;
 
     if (!SvMAGICAL(tmpForm) || !SvCOMPILED(tmpForm)) {
        if (SvREADONLY(tmpForm)) {
            SvREADONLY_off(tmpForm);
-           doparseform(tmpForm);
+           parseres = doparseform(tmpForm);
            SvREADONLY_on(tmpForm);
        }
        else
-           doparseform(tmpForm);
+           parseres = doparseform(tmpForm);
+       if (parseres)
+           return parseres;
     }
     SvPV_force(PL_formtarget, len);
     if (DO_UTF8(PL_formtarget))
@@ -414,6 +421,7 @@ PP(pp_formline)
            case FF_LINEMARK:   name = "LINEMARK";      break;
            case FF_END:        name = "END";           break;
             case FF_0DECIMAL:  name = "0DECIMAL";      break;
+           case FF_LINESNGL:   name = "LINESNGL";      break;
            }
            if (arg >= 0)
                PerlIO_printf(Perl_debug_log, "%-16s%ld\n", name, (long) arg);
@@ -520,6 +528,7 @@ PP(pp_formline)
                        while (s < send) {
                            if (*s == '\r') {
                                itemsize = s - item;
+                               chophere = s;
                                break;
                            }
                            if (*s++ & ~31)
@@ -559,6 +568,7 @@ PP(pp_formline)
                while (s < send) {
                    if (*s == '\r') {
                        itemsize = s - item;
+                       chophere = s;
                        break;
                    }
                    if (*s++ & ~31)
@@ -649,7 +659,7 @@ PP(pp_formline)
                sv_catpvn_utf8_upgrade(PL_formtarget, s, arg, nsv);
                for (; t < SvEND(PL_formtarget); t++) {
 #ifdef EBCDIC
-                   int ch = *t++ = *s++;
+                   int ch = *t;
                    if (iscntrl(ch))
 #else
                    if (!(*t & ~31))
@@ -679,7 +689,13 @@ PP(pp_formline)
            SvSETMAGIC(sv);
            break;
 
+       case FF_LINESNGL:
+           chopspace = 0;
+           oneline = TRUE;
+           goto ff_line;
        case FF_LINEGLOB:
+           oneline = FALSE;
+       ff_line:
            item = s = SvPV(sv, len);
            itemsize = len;
            if ((item_is_utf8 = DO_UTF8(sv)))
@@ -688,20 +704,31 @@ PP(pp_formline)
                bool chopped = FALSE;
                gotsome = TRUE;
                send = s + len;
+               chophere = s + itemsize;
                while (s < send) {
                    if (*s++ == '\n') {
-                       if (s == send) {
-                           itemsize--;
+                       if (oneline) {
                            chopped = TRUE;
+                           chophere = s;
+                           break;
+                       } else {
+                           if (s == send) {
+                               itemsize--;
+                               chopped = TRUE;
+                           } else
+                               lines++;
                        }
-                       else
-                           lines++;
                    }
                }
                SvCUR_set(PL_formtarget, t - SvPVX(PL_formtarget));
                if (targ_is_utf8)
                    SvUTF8_on(PL_formtarget);
-               sv_catsv(PL_formtarget, sv);
+               if (oneline) {
+                   SvCUR_set(sv, chophere - item);
+                   sv_catsv(PL_formtarget, sv);
+                   SvCUR_set(sv, itemsize);
+               } else
+                   sv_catsv(PL_formtarget, sv);
                if (chopped)
                    SvCUR_set(PL_formtarget, SvCUR(PL_formtarget) - 1);
                SvGROW(PL_formtarget, SvCUR(PL_formtarget) + fudge + 1);
@@ -711,46 +738,24 @@ PP(pp_formline)
            }
            break;
 
+       case FF_0DECIMAL:
+           arg = *fpc++;
+#if defined(USE_LONG_DOUBLE)
+           fmt = (arg & 256) ? "%#0*.*" PERL_PRIfldbl : "%0*.*" PERL_PRIfldbl;
+#else
+           fmt = (arg & 256) ? "%#0*.*f"              : "%0*.*f";
+#endif
+           goto ff_dec;
        case FF_DECIMAL:
-           /* If the field is marked with ^ and the value is undefined,
-              blank it out. */
            arg = *fpc++;
-           if ((arg & 512) && !SvOK(sv)) {
-               arg = fieldsize;
-               while (arg--)
-                   *t++ = ' ';
-               break;
-           }
-           gotsome = TRUE;
-           value = SvNV(sv);
-           /* Formats aren't yet marked for locales, so assume "yes". */
-           {
-               STORE_NUMERIC_STANDARD_SET_LOCAL();
 #if defined(USE_LONG_DOUBLE)
-               if (arg & 256) {
-                   sprintf(t, "%#*.*" PERL_PRIfldbl,
-                           (int) fieldsize, (int) arg & 255, value);
-               } else {
-                   sprintf(t, "%*.0" PERL_PRIfldbl, (int) fieldsize, value);
-               }
+           fmt = (arg & 256) ? "%#*.*" PERL_PRIfldbl : "%*.*" PERL_PRIfldbl;
 #else
-               if (arg & 256) {
-                   sprintf(t, "%#*.*f",
-                           (int) fieldsize, (int) arg & 255, value);
-               } else {
-                   sprintf(t, "%*.0f",
-                           (int) fieldsize, value);
-               }
+            fmt = (arg & 256) ? "%#*.*f"              : "%*.*f";
 #endif
-               RESTORE_NUMERIC_STANDARD();
-           }
-           t += fieldsize;
-           break;
-
-       case FF_0DECIMAL:
+       ff_dec:
            /* If the field is marked with ^ and the value is undefined,
               blank it out. */
-           arg = *fpc++;
            if ((arg & 512) && !SvOK(sv)) {
                arg = fieldsize;
                while (arg--)
@@ -759,31 +764,22 @@ PP(pp_formline)
            }
            gotsome = TRUE;
            value = SvNV(sv);
+           /* overflow evidence */
+           if (num_overflow(value, fieldsize, arg)) { 
+               arg = fieldsize;
+               while (arg--)
+                   *t++ = '#';
+               break;
+           }
            /* Formats aren't yet marked for locales, so assume "yes". */
            {
                STORE_NUMERIC_STANDARD_SET_LOCAL();
-#if defined(USE_LONG_DOUBLE)
-               if (arg & 256) {
-                   sprintf(t, "%#0*.*" PERL_PRIfldbl,
-                           (int) fieldsize, (int) arg & 255, value);
-/* is this legal? I don't have long doubles */
-               } else {
-                   sprintf(t, "%0*.0" PERL_PRIfldbl, (int) fieldsize, value);
-               }
-#else
-               if (arg & 256) {
-                   sprintf(t, "%#0*.*f",
-                           (int) fieldsize, (int) arg & 255, value);
-               } else {
-                   sprintf(t, "%0*.0f",
-                           (int) fieldsize, value);
-               }
-#endif
+               sprintf(t, fmt, (int) fieldsize, (int) arg & 255, value);
                RESTORE_NUMERIC_STANDARD();
            }
            t += fieldsize;
            break;
-       
+
        case FF_NEWLINE:
            f++;
            while (t-- > linemark && *t == ' ') ;
@@ -870,14 +866,19 @@ PP(pp_grepstart)
     ENTER;                                     /* enter outer scope */
 
     SAVETMPS;
-    /* SAVE_DEFSV does *not* suffice here for USE_5005THREADS */
-    SAVESPTR(DEFSV);
+    if (PL_op->op_private & OPpGREP_LEX)
+       SAVESPTR(PAD_SVl(PL_op->op_targ));
+    else
+       SAVE_DEFSV;
     ENTER;                                     /* enter inner scope */
     SAVEVPTR(PL_curpm);
 
     src = PL_stack_base[*PL_markstack_ptr];
     SvTEMP_off(src);
-    DEFSV = src;
+    if (PL_op->op_private & OPpGREP_LEX)
+       PAD_SVl(PL_op->op_targ) = src;
+    else
+       DEFSV = src;
 
     PUTBACK;
     if (PL_op->op_type == OP_MAPSTART)
@@ -941,8 +942,19 @@ PP(pp_mapwhile)
        }
        /* copy the new items down to the destination list */
        dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1;
-       while (items-- > 0)
-           *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs);
+       if (gimme == G_ARRAY) {
+           while (items-- > 0)
+               *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs);
+       }
+       else { 
+           /* scalar context: we don't care about which values map returns
+            * (we use undef here). And so we certainly don't want to do mortal
+            * copies of meaningless values. */
+           while (items-- > 0) {
+               (void)POPs;
+               *dst-- = &PL_sv_undef;
+           }
+       }
     }
     LEAVE;                                     /* exit inner scope */
 
@@ -956,8 +968,15 @@ PP(pp_mapwhile)
        (void)POPMARK;                          /* pop dst */
        SP = PL_stack_base + POPMARK;           /* pop original mark */
        if (gimme == G_SCALAR) {
-           dTARGET;
-           XPUSHi(items);
+           if (PL_op->op_private & OPpGREP_LEX) {
+               SV* sv = sv_newmortal();
+               sv_setiv(sv, items);
+               PUSHs(sv);
+           }
+           else {
+               dTARGET;
+               XPUSHi(items);
+           }
        }
        else if (gimme == G_ARRAY)
            SP += items;
@@ -972,7 +991,10 @@ PP(pp_mapwhile)
        /* set $_ to the new source item */
        src = PL_stack_base[PL_markstack_ptr[-1]];
        SvTEMP_off(src);
-       DEFSV = src;
+       if (PL_op->op_private & OPpGREP_LEX)
+           PAD_SVl(PL_op->op_targ) = src;
+       else
+           DEFSV = src;
 
        RETURNOP(cLOGOP->op_other);
     }
@@ -1032,31 +1054,35 @@ PP(pp_flip)
     }
 }
 
+/* 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. */
+
+#define RANGE_IS_NUMERIC(left,right) ( \
+       SvNIOKp(left)  || (SvOK(left)  && !SvPOKp(left))  || \
+       SvNIOKp(right) || (SvOK(right) && !SvPOKp(right)) || \
+       (((!SvOK(left) && SvOK(right)) || ((!SvOK(left) || \
+          looks_like_number(left)) && SvPOKp(left) && *SvPVX(left) != '0')) \
+         && (!SvOK(right) || looks_like_number(right))))
+
 PP(pp_flop)
 {
     dSP;
 
     if (GIMME == G_ARRAY) {
        dPOPPOPssrl;
-       register I32 i, j;
+       register IV i, j;
        register SV *sv;
-       I32 max;
+       IV max;
 
        if (SvGMAGICAL(left))
            mg_get(left);
        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)))
-       {
-           if (SvNV(left) < IV_MIN || SvNV(right) > IV_MAX)
+       if (RANGE_IS_NUMERIC(left,right)) {
+           if ((SvOK(left) && SvNV(left) < IV_MIN) ||
+               (SvOK(right) && SvNV(right) > IV_MAX))
                DIE(aTHX_ "Range iterator outside integer range");
            i = SvIV(left);
            max = SvIV(right);
@@ -1408,7 +1434,8 @@ Perl_die_where(pTHX_ char *message, STRLEN msglen)
                DIE(aTHX_ "%sCompilation failed in require",
                    *msg ? msg : "Unknown error\n");
            }
-           return pop_return();
+           assert(CxTYPE(cx) == CXt_EVAL);
+           return cx->blk_eval.retop;
        }
     }
     if (!message)
@@ -1702,11 +1729,10 @@ PP(pp_dbstate)
        hasargs = 0;
        SPAGAIN;
 
-       push_return(PL_op->op_next);
        PUSHBLOCK(cx, CXt_SUB, SP);
        PUSHSUB_DB(cx);
+       cx->blk_sub.retop = PL_op->op_next;
        CvDEPTH(cv)++;
-       (void)SvREFCNT_inc(cv);
        PAD_SET_CUR(CvPADLIST(cv),1);
        RETURNOP(CvSTART(cv));
     }
@@ -1770,26 +1796,37 @@ 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)))
-           {
-                if (SvNV(sv) < IV_MIN ||
-                    SvNV((SV*)cx->blk_loop.iterary) >= IV_MAX)
-                    DIE(aTHX_ "Range iterator outside integer range");
-                cx->blk_loop.iterix = SvIV(sv);
-                cx->blk_loop.itermax = SvIV((SV*)cx->blk_loop.iterary);
+           SV *right = (SV*)cx->blk_loop.iterary;
+           if (RANGE_IS_NUMERIC(sv,right)) {
+               if ((SvOK(sv) && SvNV(sv) < IV_MIN) ||
+                   (SvOK(right) && SvNV(right) >= IV_MAX))
+                   DIE(aTHX_ "Range iterator outside integer range");
+               cx->blk_loop.iterix = SvIV(sv);
+               cx->blk_loop.itermax = SvIV(right);
            }
-           else
+           else {
+               STRLEN n_a;
                cx->blk_loop.iterlval = newSVsv(sv);
+               (void) SvPV_force(cx->blk_loop.iterlval,n_a);
+               (void) SvPV(right,n_a);
+           }
+       }
+       else if (PL_op->op_private & OPpITER_REVERSED) {
+           cx->blk_loop.itermax = -1;
+           cx->blk_loop.iterix = AvFILL(cx->blk_loop.iterary);
+
        }
     }
     else {
        cx->blk_loop.iterary = PL_curstack;
        AvFILLp(PL_curstack) = SP - PL_stack_base;
-       cx->blk_loop.iterix = MARK - PL_stack_base;
+       if (PL_op->op_private & OPpITER_REVERSED) {
+           cx->blk_loop.itermax = MARK - PL_stack_base;
+           cx->blk_loop.iterix = cx->blk_oldsp;
+       }
+       else {
+           cx->blk_loop.iterix = MARK - PL_stack_base;
+       }
     }
 
     RETURN;
@@ -1863,6 +1900,7 @@ PP(pp_return)
     PMOP *newpm;
     I32 optype = 0;
     SV *sv;
+    OP *retop;
 
     if (PL_curstackinfo->si_type == PERLSI_SORT) {
        if (cxstack_ix == PL_sortcxix
@@ -1886,12 +1924,14 @@ PP(pp_return)
     switch (CxTYPE(cx)) {
     case CXt_SUB:
        popsub2 = TRUE;
+       retop = cx->blk_sub.retop;
        cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
        break;
     case CXt_EVAL:
        if (!(PL_in_eval & EVAL_KEEPERR))
            clear_errsv = TRUE;
        POPEVAL(cx);
+       retop = cx->blk_eval.retop;
        if (CxTRYBLOCK(cx))
            break;
        lex_end();
@@ -1906,6 +1946,7 @@ PP(pp_return)
        break;
     case CXt_FORMAT:
        POPFORMAT(cx);
+       retop = cx->blk_sub.retop;
        break;
     default:
        DIE(aTHX_ "panic: return");
@@ -1959,7 +2000,7 @@ PP(pp_return)
     LEAVESUB(sv);
     if (clear_errsv)
        sv_setpv(ERRSV,"");
-    return pop_return();
+    return retop;
 }
 
 PP(pp_last)
@@ -2000,15 +2041,15 @@ PP(pp_last)
        break;
     case CXt_SUB:
        pop2 = CXt_SUB;
-       nextop = pop_return();
+       nextop = cx->blk_sub.retop;
        break;
     case CXt_EVAL:
        POPEVAL(cx);
-       nextop = pop_return();
+       nextop = cx->blk_eval.retop;
        break;
     case CXt_FORMAT:
        POPFORMAT(cx);
-       nextop = pop_return();
+       nextop = cx->blk_sub.retop;
        break;
     default:
        DIE(aTHX_ "panic: last");
@@ -2100,6 +2141,7 @@ PP(pp_redo)
     TOPBLOCK(cx);
     oldsave = PL_scopestack[PL_scopestack_ix - 1];
     LEAVE_SCOPE(oldsave);
+    FREETMPS;
     return cx->blk_loop.redo_op;
 }
 
@@ -2167,6 +2209,7 @@ PP(pp_goto)
     char *label;
     int do_dump = (PL_op->op_type == OP_DUMP);
     static char must_have_label[] = "goto must have label";
+    AV *oldav = Nullav;
 
     label = 0;
     if (PL_op->op_flags & OPf_STACKED) {
@@ -2227,7 +2270,7 @@ PP(pp_goto)
                GvAV(PL_defgv) = cx->blk_sub.savearray;
                /* abandon @_ if it got reified */
                if (AvREAL(av)) {
-                   (void)sv_2mortal((SV*)av);  /* delay until return */
+                   oldav = av; /* delay until return */
                    av = newAV();
                    av_extend(av, items-1);
                    AvFLAGS(av) = AVf_REIFY;
@@ -2253,6 +2296,9 @@ PP(pp_goto)
 
            /* Now do some callish stuff. */
            SAVETMPS;
+           /* For reified @_, delay freeing till return from new sub */
+           if (oldav)
+               SAVEFREESV((SV*)oldav);
            SAVEFREESV(cv); /* later, undo the 'avoid premature free' hack */
            if (CvXSUB(cv)) {
 #ifdef PERL_XSUB_OLDSTYLE
@@ -2283,7 +2329,8 @@ PP(pp_goto)
                    /* Do _not_ use PUTBACK, keep the XSUB's return stack! */
                }
                LEAVE;
-               return pop_return();
+               assert(CxTYPE(cx) == CXt_SUB);
+               return cx->blk_sub.retop;
            }
            else {
                AV* padlist = CvPADLIST(cv);
@@ -2302,7 +2349,7 @@ PP(pp_goto)
                else {
                    if (CvDEPTH(cv) == 100 && ckWARN(WARN_RECURSION))
                        sub_crush_depth(cv);
-                   pad_push(padlist, CvDEPTH(cv), cx->blk_sub.hasargs);
+                   pad_push(padlist, CvDEPTH(cv), 1);
                }
                PAD_SET_CUR(padlist, CvDEPTH(cv));
                if (cx->blk_sub.hasargs)
@@ -2618,8 +2665,10 @@ S_docatch(pTHX_ OP *o)
      * the op to Nullop, we force an exit from the inner runops()
      * loop. DAPM.
      */
-    retop = pop_return();
-    push_return(Nullop);
+    assert(cxstack_ix >= 0);
+    assert(CxTYPE(&cxstack[cxstack_ix]) == CXt_EVAL);
+    retop = cxstack[cxstack_ix].blk_eval.retop;
+    cxstack[cxstack_ix].blk_eval.retop = Nullop;
 
 #ifdef PERL_FLEXIBLE_EXCEPTIONS
  redo_body:
@@ -2710,7 +2759,6 @@ Perl_sv_compile_2op(pTHX_ SV *sv, OP** startop, char *code, PAD** padp)
 #else
     SAVEVPTR(PL_op);
 #endif
-    PL_hints &= HINT_UTF8;
 
     /* we get here either during compilation, or via pp_regcomp at runtime */
     runtime = IN_PERL_RUNTIME;
@@ -2752,7 +2800,7 @@ Locate the CV corresponding to the currently executing sub or eval.
 If db_seqp is non_null, skip CVs that are in the DB package and populate
 *db_seqp with the cop sequence number at the point that the DB:: code was
 entered. (allows debuggers to eval in the scope of the breakpoint rather
-than in in the scope of the debuger itself).
+than in in the scope of the debugger itself).
 
 =cut
 */
@@ -2858,7 +2906,6 @@ S_doeval(pTHX_ int gimme, OP** startop, CV* outside, U32 seq)
        if (!startop) {
            POPBLOCK(cx,PL_curpm);
            POPEVAL(cx);
-           pop_return();
        }
        lex_end();
        LEAVE;
@@ -3176,6 +3223,7 @@ PP(pp_require)
                                                      PERL_SCRIPT_MODE);
                            }
                        }
+                       SP--;
                    }
 
                    PUTBACK;
@@ -3315,9 +3363,9 @@ PP(pp_require)
     }
 
     /* switch to eval mode */
-    push_return(PL_op->op_next);
     PUSHBLOCK(cx, CXt_EVAL, SP);
     PUSHEVAL(cx, name, Nullgv);
+    cx->blk_eval.retop = PL_op->op_next;
 
     SAVECOPLINE(&PL_compiling);
     CopLINE_set(&PL_compiling, 0);
@@ -3408,9 +3456,9 @@ PP(pp_entereval)
      * to do the dirty work for us */
     runcv = find_runcv(&seq);
 
-    push_return(PL_op->op_next);
     PUSHBLOCK(cx, (CXt_EVAL|CXp_REAL), SP);
     PUSHEVAL(cx, 0, Nullgv);
+    cx->blk_eval.retop = PL_op->op_next;
 
     /* prepare to compile string */
 
@@ -3439,7 +3487,7 @@ PP(pp_leaveeval)
 
     POPBLOCK(cx,newpm);
     POPEVAL(cx);
-    retop = pop_return();
+    retop = cx->blk_eval.retop;
 
     TAINT_NOT;
     if (gimme == G_VOID)
@@ -3502,9 +3550,9 @@ PP(pp_entertry)
     ENTER;
     SAVETMPS;
 
-    push_return(cLOGOP->op_other->op_next);
     PUSHBLOCK(cx, (CXt_EVAL|CXp_TRYBLOCK), SP);
     PUSHEVAL(cx, 0, 0);
+    cx->blk_eval.retop = cLOGOP->op_other->op_next;
 
     PL_in_eval = EVAL_INEVAL;
     sv_setpv(ERRSV,"");
@@ -3525,7 +3573,7 @@ PP(pp_leavetry)
 
     POPBLOCK(cx,newpm);
     POPEVAL(cx);
-    retop = pop_return();
+    retop = cx->blk_eval.retop;
 
     TAINT_NOT;
     if (gimme == G_VOID)
@@ -3560,7 +3608,7 @@ PP(pp_leavetry)
     RETURNOP(retop);
 }
 
-STATIC void
+STATIC OP *
 S_doparseform(pTHX_ SV *sv)
 {
     STRLEN len;
@@ -3576,7 +3624,8 @@ S_doparseform(pTHX_ SV *sv)
     U32 *linepc = 0;
     register I32 arg;
     bool ischop;
-    int maxops = 2; /* FF_LINEMARK + FF_END) */
+    bool unchopnum = FALSE;
+    int maxops = 12; /* FF_LINEMARK + FF_END + 10 (\0 without preceding \n) */
 
     if (len == 0)
        Perl_croak(aTHX_ "Null picture in formline");
@@ -3616,8 +3665,12 @@ S_doparseform(pTHX_ SV *sv)
        case ' ': case '\t':
            skipspaces++;
            continue;
-       
-       case '\n': case 0:
+        case 0:
+           if (s < send) {
+               skipspaces = 0;
+                continue;
+            } /* else FALL THROUGH */
+       case '\n':
            arg = s - base;
            skipspaces++;
            arg -= skipspaces;
@@ -3673,8 +3726,12 @@ S_doparseform(pTHX_ SV *sv)
            *fpc++ = FF_FETCH;
            if (*s == '*') {
                s++;
-               *fpc++ = 0;
-               *fpc++ = FF_LINEGLOB;
+               *fpc++ = 2;  /* skip the @* or ^* */
+               if (ischop) {
+                   *fpc++ = FF_LINESNGL;
+                   *fpc++ = FF_CHOP;
+               } else
+                   *fpc++ = FF_LINEGLOB;
            }
            else if (*s == '#' || (*s == '.' && s[1] == '#')) {
                arg = ischop ? 512 : 0;
@@ -3692,6 +3749,7 @@ S_doparseform(pTHX_ SV *sv)
                *fpc++ = s - base;              /* fieldsize for FETCH */
                *fpc++ = FF_DECIMAL;
                 *fpc++ = (U16)arg;
+                unchopnum |= ! ischop;
             }
             else if (*s == '0' && s[1] == '#') {  /* Zero padded decimals */
                 arg = ischop ? 512 : 0;
@@ -3710,6 +3768,7 @@ S_doparseform(pTHX_ SV *sv)
                 *fpc++ = s - base;                /* fieldsize for FETCH */
                 *fpc++ = FF_0DECIMAL;
                *fpc++ = (U16)arg;
+                unchopnum |= ! ischop;
            }
            else {
                I32 prespace = 0;
@@ -3764,6 +3823,38 @@ S_doparseform(pTHX_ SV *sv)
     Safefree(fops);
     sv_magic(sv, Nullsv, PERL_MAGIC_fm, Nullch, 0);
     SvCOMPILED_on(sv);
+
+    if (unchopnum && repeat) 
+        DIE(aTHX_ "Repeated format line will never terminate (~~ and @#)");
+    return 0;
+}
+
+
+STATIC bool
+S_num_overflow(NV value, I32 fldsize, I32 frcsize)
+{
+    /* Can value be printed in fldsize chars, using %*.*f ? */
+    NV pwr = 1;
+    NV eps = 0.5;
+    bool res = FALSE;
+    int intsize = fldsize - (value < 0 ? 1 : 0);
+
+    if (frcsize & 256)
+        intsize--;
+    frcsize &= 255;
+    intsize -= frcsize;
+
+    while (intsize--) pwr *= 10.0;
+    while (frcsize--) eps /= 10.0;
+
+    if( value >= 0 ){
+        if (value + eps >= pwr)
+           res = TRUE;
+    } else {
+        if (value - eps <= -pwr)
+           res = TRUE;
+    }
+    return res;
 }
 
 static I32