was Re: UNIVERSAL::VERSION causing "Use of uninitialized value..." warning
[p5sagit/p5-mst-13.2.git] / pp.c
diff --git a/pp.c b/pp.c
index 1a35902..9425bca 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -1391,19 +1391,46 @@ PP(pp_repeat)
 {
   dSP; dATARGET; tryAMAGICbin(repeat,opASSIGN);
   {
-    register IV count = POPi;
-    if (count < 0)
-       count = 0;
+    register IV count;
+    dPOPss;
+    if (SvGMAGICAL(sv))
+        mg_get(sv);
+    if (SvIOKp(sv)) {
+        if (SvUOK(sv)) {
+             UV uv = SvUV(sv);
+             if (uv > IV_MAX)
+                  count = IV_MAX; /* The best we can do? */
+             else
+                  count = uv;
+        } else {
+             IV iv = SvIV(sv);
+             if (iv < 0)
+                  count = 0;
+             else
+                  count = iv;
+        }
+    }
+    else if (SvNOKp(sv)) {
+        NV nv = SvNV(sv);
+        if (nv < 0.0)
+             count = 0;
+        else
+             count = (IV)nv;
+    }
+    else
+        count = SvIVx(sv);
     if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
        dMARK;
        I32 items = SP - MARK;
        I32 max;
-       static const char list_extend[] = "panic: list extend";
+       static const char oom_list_extend[] =
+         "Out of memory during list extend";
 
        max = items * count;
-       MEM_WRAP_CHECK_1(max, SV*, list_extend);
+       MEM_WRAP_CHECK_1(max, SV*, oom_list_extend);
+       /* Did the max computation overflow? */
        if (items > 0 && max > 0 && (max < items || max < count))
-          Perl_croak(aTHX_ list_extend);
+          Perl_croak(aTHX_ oom_list_extend);
        MEXTEND(MARK, max);
        if (count > 1) {
            while (SP > MARK) {
@@ -1448,6 +1475,8 @@ PP(pp_repeat)
        SV *tmpstr = POPs;
        STRLEN len;
        bool isutf;
+       static const char oom_string_extend[] =
+         "Out of memory during string extend";
 
        SvSetSV(TARG, tmpstr);
        SvPV_force(TARG, len);
@@ -1456,7 +1485,10 @@ PP(pp_repeat)
            if (count < 1)
                SvCUR_set(TARG, 0);
            else {
-               MEM_WRAP_CHECK_1(count, len, "panic: string extend");
+               IV max = count * len;
+               if (len > ((MEM_SIZE)~0)/count)
+                    Perl_croak(aTHX_ oom_string_extend);
+               MEM_WRAP_CHECK_1(max, char, oom_string_extend);
                SvGROW(TARG, (count * len) + 1);
                repeatcpy(SvPVX(TARG) + len, SvPVX(TARG), len, count - 1);
                SvCUR(TARG) *= count;
@@ -2800,7 +2832,9 @@ PP(pp_int)
         else preferring IV has introduced a subtle behaviour change bug. OTOH
         relying on floating point to be accurate is a bug.  */
 
-      if (SvIOK(TOPs)) {
+      if (!SvOK(TOPs))
+        SETu(0);
+      else if (SvIOK(TOPs)) {
        if (SvIsUV(TOPs)) {
            UV uv = TOPu;
            SETu(uv);
@@ -2834,7 +2868,9 @@ PP(pp_abs)
       /* This will cache the NV value if string isn't actually integer  */
       IV iv = TOPi;
 
-      if (SvIOK(TOPs)) {
+      if (!SvOK(TOPs))
+        SETu(0);
+      else if (SvIOK(TOPs)) {
        /* IVX is precise  */
        if (SvIsUV(TOPs)) {
          SETu(TOPu);   /* force it to be numeric only */
@@ -3795,7 +3831,10 @@ PP(pp_delete)
            SP = ORIGMARK;
        else if (gimme == G_SCALAR) {
            MARK = ORIGMARK;
-           *++MARK = *SP;
+           if (SP > MARK)
+               *++MARK = *SP;
+           else
+               *++MARK = &PL_sv_undef;
            SP = MARK;
        }
     }
@@ -4327,12 +4366,17 @@ PP(pp_reverse)
        register I32 tmp;
        dTARGET;
        STRLEN len;
+       I32 padoff_du;
 
        SvUTF8_off(TARG);                               /* decontaminate */
        if (SP - MARK > 1)
            do_join(TARG, &PL_sv_no, MARK, SP);
        else
-           sv_setsv(TARG, (SP > MARK) ? *SP : DEFSV);
+           sv_setsv(TARG, (SP > MARK)
+                   ? *SP
+                   : (padoff_du = find_rundefsvoffset(),
+                       (padoff_du == NOT_IN_PAD || PAD_COMPNAME_FLAGS(padoff_du) & SVpad_OUR)
+                       ? DEFSV : PAD_SVl(padoff_du)));
        up = SvPV_force(TARG, len);
        if (len > 1) {
            if (DO_UTF8(TARG)) {        /* first reverse each character */
@@ -4395,7 +4439,6 @@ PP(pp_split)
     I32 origlimit = limit;
     I32 realarray = 0;
     I32 base;
-    AV *oldstack = PL_curstack;
     I32 gimme = GIMME_V;
     I32 oldsave = PL_savestack_ix;
     I32 make_mortal = 1;
@@ -4444,8 +4487,7 @@ PP(pp_split)
                    AvARRAY(ary)[i] = &PL_sv_undef;     /* don't free mere refs */
            }
            /* temporarily switch stacks */
-           SWITCHSTACK(PL_curstack, ary);
-           PL_curstackinfo->si_stack = ary;
+           SAVESWITCHSTACK(PL_curstack, ary);
            make_mortal = 0;
        }
     }
@@ -4614,7 +4656,6 @@ PP(pp_split)
        }
     }
 
-    LEAVE_SCOPE(oldsave);
     iters = (SP - PL_stack_base) - base;
     if (iters > maxiters)
        DIE(aTHX_ "Split loop");
@@ -4636,14 +4677,15 @@ PP(pp_split)
            if (TOPs && !make_mortal)
                sv_2mortal(TOPs);
            iters--;
-           SP--;
+           *SP-- = &PL_sv_undef;
        }
     }
 
+    PUTBACK;
+    LEAVE_SCOPE(oldsave); /* may undo an earlier SWITCHSTACK */
+    SPAGAIN;
     if (realarray) {
        if (!mg) {
-           SWITCHSTACK(ary, oldstack);
-           PL_curstackinfo->si_stack = oldstack;
            if (SvSMAGICAL(ary)) {
                PUTBACK;
                mg_set((SV*)ary);