This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add isUTF8_CHAR_flags() macro
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 69b40e2..ea49b01 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -3544,18 +3544,11 @@ PP(pp_index)
            sv_usepvn(temp, pv, llen);
            little_p = SvPVX(little);
        } else {
-           temp = little_utf8
-               ? newSVpvn(big_p, biglen) : newSVpvn(little_p, llen);
+           temp = newSVpvn(little_p, llen);
 
            sv_utf8_upgrade(temp);
-           if (little_utf8) {
-               big = temp;
-               big_utf8 = TRUE;
-               big_p = SvPV_const(big, biglen);
-           } else {
-               little = temp;
-               little_p = SvPV_const(little, llen);
-           }
+           little = temp;
+           little_p = SvPV_const(little, llen);
        }
     }
     if (SvGAMAGIC(big)) {
@@ -4116,8 +4109,7 @@ PP(pp_uc)
                      * allocate without allocating too much.  Such is life.
                      * See corresponding comment in lc code for another option
                      * */
-                    SvGROW(dest, min);
-                    d = (U8*)SvPVX(dest) + o;
+                    d = o + (U8*) SvGROW(dest, min);
                 }
                 Copy(tmpbuf, d, ulen, U8);
                 d += ulen;
@@ -4181,8 +4173,7 @@ PP(pp_uc)
                         * ASCII.  If not enough room, grow the string */
                        if (SvLEN(dest) < ++min) {      
                            const UV o = d - (U8*)SvPVX_const(dest);
-                           SvGROW(dest, min);
-                           d = (U8*)SvPVX(dest) + o;
+                           d = o + (U8*) SvGROW(dest, min);
                        }
                        *d++ = 'S'; *d = 'S'; /* upper case is 'SS' */
                        continue;   /* Back to the tight loop; still in ASCII */
@@ -4332,8 +4323,7 @@ PP(pp_lc)
                 * Another option would be to grow an extra byte or two more
                 * each time we need to grow, which would cut down the million
                 * to 500K, with little waste */
-               SvGROW(dest, min);
-               d = (U8*)SvPVX(dest) + o;
+               d = o + (U8*) SvGROW(dest, min);
            }
 
            /* Copy the newly lowercased letter to the output buffer we're
@@ -4527,8 +4517,7 @@ PP(pp_fc)
 
             if (ulen > u && (SvLEN(dest) < (min += ulen - u))) {
                 const UV o = d - (U8*)SvPVX_const(dest);
-                SvGROW(dest, min);
-                d = (U8*)SvPVX(dest) + o;
+                d = o + (U8*) SvGROW(dest, min);
             }
 
             Copy(tmpbuf, d, ulen, U8);
@@ -4607,8 +4596,7 @@ PP(pp_fc)
                      * becomes "ss", which may require growing the SV. */
                     if (SvLEN(dest) < ++min) {
                         const UV o = d - (U8*)SvPVX_const(dest);
-                        SvGROW(dest, min);
-                        d = (U8*)SvPVX(dest) + o;
+                        d = o + (U8*) SvGROW(dest, min);
                      }
                     *(d)++ = 's';
                     *d = 's';
@@ -5375,6 +5363,8 @@ PP(pp_splice)
                for (i = length - 1, dst = &AvARRAY(ary)[offset]; i > 0; i--)
                    SvREFCNT_dec(*dst++);       /* free them now */
            }
+           if (!*MARK)
+               *MARK = &PL_sv_undef;
        }
        AvFILLp(ary) += diff;
 
@@ -5471,6 +5461,8 @@ PP(pp_splice)
                while (length-- > 0)
                    SvREFCNT_dec(tmparyval[length]);
            }
+           if (!*MARK)
+               *MARK = &PL_sv_undef;
        }
        else
            *MARK = &PL_sv_undef;
@@ -6628,10 +6620,6 @@ PP(pp_anonconst)
  * or
  *    my @foo = @_[N..$#_]
  * etc
- *
- * It assumes that the pad var is currently uninitialised, so this op
- * should only be used at the start of a sub, where its not possible to
- * skip the op (e.g. no 'my $x if $cond' stuff for example).
  */
 
 PP(pp_argelem)
@@ -6641,11 +6629,8 @@ PP(pp_argelem)
     SV ** padentry;
     OP *o = PL_op;
     AV *defav = GvAV(PL_defgv); /* @_ */
-    UV ix = PTR2UV(cUNOP_AUXo->op_aux);
+    IV ix = PTR2IV(cUNOP_AUXo->op_aux);
     IV argc;
-    SV **argv;
-
-    assert(!SvMAGICAL(defav));
 
     /* do 'my $var, @var or %var' action */
     padentry = &(PAD_SVl(o->op_targ));
@@ -6659,11 +6644,15 @@ PP(pp_argelem)
             PUTBACK;
         }
         else {
+            SV **svp;
             /* should already have been checked */
-            assert(ix < I32_MAX && AvFILLp(defav) >= (I32)ix);
-            val = AvARRAY(defav)[ix];
-            if (UNLIKELY(!val))
-                val = &PL_sv_undef;
+            assert(ix >= 0);
+#if IVSIZE > PTRSIZE
+            assert(ix <= SSize_t_MAX);
+#endif
+
+            svp = av_fetch(defav, ix, FALSE);
+            val = svp ? *svp : &PL_sv_undef;
         }
 
         /* $var = $val */
@@ -6673,81 +6662,91 @@ PP(pp_argelem)
         if (UNLIKELY(TAINT_get) && !SvTAINTED(val))
             TAINT_NOT;
 
-        /* Short-cut assignment of IV and RV values as these are
-         * common and simple. For RVs, it's likely that on
-         * subsequent calls to a function, targ is already of the
-         * correct storage class */
-        if (LIKELY(!SvMAGICAL(val))) {
-            /* just an IV */
-            if ((SvFLAGS(val) & (SVf_IOK|SVf_NOK|SVf_POK|SVf_IVisUV)) == SVf_IOK) {
-                IV i = SvIVX(val);
-                if (LIKELY(SvTYPE(targ) == SVt_IV)) {
-                    assert(!SvOK(targ));
-                    assert(!SvMAGICAL(targ));
-                    (void)SvIOK_only(targ);
-                    SvIV_set(targ, i);
-                }
-                else
-                    sv_setiv(targ, i);
-            }
-            else if (SvROK(val) && SvTYPE(targ) == SVt_IV) {
-                /* quick ref assignment */
-                assert(!SvOK(targ));
-                SvRV_set(targ, SvREFCNT_inc(SvRV(val)));
-                SvROK_on(targ);
-            }
-            else
-                sv_setsv(targ, val);
-        }
-        else
-            sv_setsv(targ, val);
+        SvSetMagicSV(targ, val);
         return o->op_next;
     }
 
     /* must be AV or HV */
 
     assert(!(o->op_flags & OPf_STACKED));
-    argc = ((IV)AvFILLp(defav) + 1) - (IV)ix;
-    assert(!SvMAGICAL(targ));
-    if (argc <= 0)
-        return o->op_next;
-    argv = AvARRAY(defav) + ix;
-    assert(argv);
+    argc = ((IV)AvFILL(defav) + 1) - ix;
 
     /* This is a copy of the relevant parts of pp_aassign().
-     * We *know* that @foo / %foo is a plain empty lexical at this point,
-     * so we can avoid a lot of the extra baggage.
-     * We know, because all the usual tricks like 'my @a if 0',
-     * 'foo: my @a = ...; goto foo' can't be done with signatures.
      */
     if ((o->op_private & OPpARGELEM_MASK) == OPpARGELEM_AV) {
-        UV i = 0;
+        IV i;
+
+        if (AvFILL((AV*)targ) > -1) {
+            /* target should usually be empty. If we get get
+             * here, someone's been doing some weird closure tricks.
+             * Make a copy of all args before clearing the array,
+             * to avoid the equivalent of @a = ($a[0]) prematurely freeing
+             * elements. See similar code in pp_aassign.
+             */
+            for (i = 0; i < argc; i++) {
+                SV **svp = av_fetch(defav, ix + i, FALSE);
+                SV *newsv = newSV(0);
+                sv_setsv_flags(newsv,
+                                svp ? *svp : &PL_sv_undef,
+                                (SV_DO_COW_SVSETSV|SV_NOSTEAL));
+                if (!av_store(defav, ix + i, newsv))
+                    SvREFCNT_dec_NN(newsv);
+            }
+            av_clear((AV*)targ);
+        }
+
+        if (argc <= 0)
+            return o->op_next;
 
-        assert(AvFILLp((AV*)targ) == -1); /* can skip av_clear() */
         av_extend((AV*)targ, argc);
 
+        i = 0;
         while (argc--) {
             SV *tmpsv;
-            SV *arg = *argv++;
+            SV **svp = av_fetch(defav, ix + i, FALSE);
+            SV *val = svp ? *svp : &PL_sv_undef;
             tmpsv = newSV(0);
-            sv_setsv(tmpsv, arg);
+            sv_setsv(tmpsv, val);
             av_store((AV*)targ, i++, tmpsv);
             TAINT_NOT;
         }
 
     }
     else {
+        IV i;
+
         assert((o->op_private & OPpARGELEM_MASK) == OPpARGELEM_HV);
 
+        if (SvRMAGICAL(targ) || HvUSEDKEYS((HV*)targ)) {
+            /* see "target should usually be empty" comment above */
+            for (i = 0; i < argc; i++) {
+                SV **svp = av_fetch(defav, ix + i, FALSE);
+                SV *newsv = newSV(0);
+                sv_setsv_flags(newsv,
+                                svp ? *svp : &PL_sv_undef,
+                                (SV_DO_COW_SVSETSV|SV_NOSTEAL));
+                if (!av_store(defav, ix + i, newsv))
+                    SvREFCNT_dec_NN(newsv);
+            }
+            hv_clear((HV*)targ);
+        }
+
+        if (argc <= 0)
+            return o->op_next;
         assert(argc % 2 == 0);
-        assert(!HvTOTALKEYS(targ)); /* can skip hv_clear() */
 
+        i = 0;
         while (argc) {
             SV *tmpsv;
-            SV *key = *argv++;
-            SV *val = *argv++;
+            SV **svp;
+            SV *key;
+            SV *val;
+
+            svp = av_fetch(defav, ix + i++, FALSE);
+            key = svp ? *svp : &PL_sv_undef;
+            svp = av_fetch(defav, ix + i++, FALSE);
+            val = svp ? *svp : &PL_sv_undef;
 
-            assert(key); assert(val);
             argc -= 2;
             if (UNLIKELY(SvGMAGICAL(key)))
                 key = sv_mortalcopy(key);
@@ -6776,13 +6775,18 @@ PP(pp_argdefelem)
 {
     OP * const o = PL_op;
     AV *defav = GvAV(PL_defgv); /* @_ */
-    PADOFFSET ix = o->op_targ;
+    IV ix = (IV)o->op_targ;
 
-    assert(!SvMAGICAL(defav));
-    assert(ix < I32_MAX);
-    if (AvFILLp(defav) >= (I32)ix) {
+    assert(ix >= 0);
+#if IVSIZE > PTRSIZE
+    assert(ix <= SSize_t_MAX);
+#endif
+
+    if (AvFILL(defav) >= ix) {
         dSP;
-        XPUSHs(AvARRAY(defav)[ix]);
+        SV **svp = av_fetch(defav, ix, FALSE);
+        SV  *val = svp ? *svp : &PL_sv_undef;
+        XPUSHs(val);
         RETURN;
     }
     return cLOGOPo->op_other;
@@ -6799,15 +6803,15 @@ PP(pp_argcheck)
 {
     OP * const o       = PL_op;
     UNOP_AUX_item *aux = cUNOP_AUXo->op_aux;
-    UV   params        = aux[0].uv;
-    UV   opt_params    = aux[1].uv;
+    IV   params        = aux[0].iv;
+    IV   opt_params    = aux[1].iv;
     char slurpy        = (char)(aux[2].iv);
     AV  *defav         = GvAV(PL_defgv); /* @_ */
-    UV argc;
+    IV   argc;
     bool too_few;
 
     assert(!SvMAGICAL(defav));
-    argc = (UV)(AvFILLp(defav) + 1);
+    argc = (AvFILLp(defav) + 1);
     too_few = (argc < (params - opt_params));
 
     if (UNLIKELY(too_few || (!slurpy && argc > params)))