Add a parameter "destructing" to Gv_AMupdate()
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index 0b95142..4699a4e 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3692,6 +3692,7 @@ S_glob_assign_ref(pTHX_ SV *const dstr, SV *const sstr)
        goto common;
     case SVt_PVFM:
        location = (SV **) &GvFORM(dstr);
+       goto common;
     default:
        location = &GvSV(dstr);
        import_flag = GVf_IMPORTED_SV;
@@ -5517,8 +5518,8 @@ Perl_sv_replace(pTHX_ register SV *const sv, register SV *const nsv)
 
     SV_CHECK_THINKFIRST_COW_DROP(sv);
     if (SvREFCNT(nsv) != 1) {
-       Perl_croak(aTHX_ "panic: reference miscount on nsv in sv_replace() (%"
-                  UVuf " != 1)", (UV) SvREFCNT(nsv));
+       Perl_croak(aTHX_ "panic: reference miscount on nsv in sv_replace()"
+                  " (%" UVuf " != 1)", (UV) SvREFCNT(nsv));
     }
     if (SvMAGICAL(sv)) {
        if (SvMAGICAL(nsv))
@@ -9673,9 +9674,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            else {
                eptr = SvPV_const(argsv, elen);
                if (DO_UTF8(argsv)) {
-                   I32 old_precis = precis;
+                   STRLEN old_precis = precis;
                    if (has_precis && precis < elen) {
-                       I32 p = precis;
+                       STRLEN ulen = sv_len_utf8(argsv);
+                       I32 p = precis > ulen ? ulen : precis;
                        sv_pos_u2b(argsv, &p, 0); /* sticks at end */
                        precis = p;
                    }
@@ -9690,7 +9692,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *const sv, const char *const pat, const STRLEN patlen,
            }
 
        string:
-           if (has_precis && elen > precis)
+           if (has_precis && precis < elen)
                elen = precis;
            break;
 
@@ -10297,7 +10299,8 @@ ptr_table_* functions.
 
 /* Certain cases in Perl_ss_dup have been merged, by relying on the fact
    that currently av_dup, gv_dup and hv_dup are the same as sv_dup.
-   If this changes, please unmerge ss_dup.  */
+   If this changes, please unmerge ss_dup.
+   Likewise, sv_dup_inc_multiple() relies on this fact.  */
 #define sv_dup_inc(s,t)        SvREFCNT_inc(sv_dup(s,t))
 #define sv_dup_inc_NN(s,t)     SvREFCNT_inc_NN(sv_dup(s,t))
 #define av_dup(s,t)    MUTABLE_AV(sv_dup((const SV *)s,t))
@@ -10509,62 +10512,59 @@ Perl_gp_dup(pTHX_ GP *const gp, CLONE_PARAMS *const param)
 MAGIC *
 Perl_mg_dup(pTHX_ MAGIC *mg, CLONE_PARAMS *const param)
 {
-    MAGIC *mgprev = (MAGIC*)NULL;
     MAGIC *mgret = NULL;
+    MAGIC **mgprev_p = &mgret;
 
     PERL_ARGS_ASSERT_MG_DUP;
 
     for (; mg; mg = mg->mg_moremagic) {
        MAGIC *nmg;
-       Newxz(nmg, 1, MAGIC);
-       if (mgprev)
-           mgprev->mg_moremagic = nmg;
-       else
-           mgret = nmg;
-       nmg->mg_virtual = mg->mg_virtual;       /* XXX copy dynamic vtable? */
-       nmg->mg_private = mg->mg_private;
-       nmg->mg_type    = mg->mg_type;
-       nmg->mg_flags   = mg->mg_flags;
+       Newx(nmg, 1, MAGIC);
+       *mgprev_p = nmg;
+       mgprev_p = &(nmg->mg_moremagic);
+
+       /* There was a comment "XXX copy dynamic vtable?" but as we don't have
+          dynamic vtables, I'm not sure why Sarathy wrote it. The comment dates
+          from the original commit adding Perl_mg_dup() - revision 4538.
+          Similarly there is the annotation "XXX random ptr?" next to the
+          assignment to nmg->mg_ptr.  */
+       *nmg = *mg;
+
        /* FIXME for plugins
-       if (mg->mg_type == PERL_MAGIC_qr) {
-           nmg->mg_obj = MUTABLE_SV(CALLREGDUPE((REGEXP*)mg->mg_obj, param));
+       if (nmg->mg_type == PERL_MAGIC_qr) {
+           nmg->mg_obj = MUTABLE_SV(CALLREGDUPE((REGEXP*)nmg->mg_obj, param));
        }
        else
        */
-       if(mg->mg_type == PERL_MAGIC_backref) {
+       if(nmg->mg_type == PERL_MAGIC_backref) {
            /* The backref AV has its reference count deliberately bumped by
               1.  */
            nmg->mg_obj
-               = SvREFCNT_inc(av_dup_inc((const AV *) mg->mg_obj, param));
+               = SvREFCNT_inc(av_dup_inc((const AV *) nmg->mg_obj, param));
        }
        else {
-           nmg->mg_obj = (mg->mg_flags & MGf_REFCOUNTED)
-                             ? sv_dup_inc(mg->mg_obj, param)
-                             : sv_dup(mg->mg_obj, param);
-       }
-       nmg->mg_len     = mg->mg_len;
-       nmg->mg_ptr     = mg->mg_ptr;   /* XXX random ptr? */
-       if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) {
-           if (mg->mg_len > 0) {
-               nmg->mg_ptr     = SAVEPVN(mg->mg_ptr, mg->mg_len);
-               if (mg->mg_type == PERL_MAGIC_overload_table &&
-                       AMT_AMAGIC((AMT*)mg->mg_ptr))
+           nmg->mg_obj = (nmg->mg_flags & MGf_REFCOUNTED)
+                             ? sv_dup_inc(nmg->mg_obj, param)
+                             : sv_dup(nmg->mg_obj, param);
+       }
+
+       if (nmg->mg_ptr && nmg->mg_type != PERL_MAGIC_regex_global) {
+           if (nmg->mg_len > 0) {
+               nmg->mg_ptr     = SAVEPVN(nmg->mg_ptr, nmg->mg_len);
+               if (nmg->mg_type == PERL_MAGIC_overload_table &&
+                       AMT_AMAGIC((AMT*)nmg->mg_ptr))
                {
-                   const AMT * const amtp = (AMT*)mg->mg_ptr;
                    AMT * const namtp = (AMT*)nmg->mg_ptr;
-                   I32 i;
-                   for (i = 1; i < NofAMmeth; i++) {
-                       namtp->table[i] = cv_dup_inc(amtp->table[i], param);
-                   }
+                   sv_dup_inc_multiple((SV**)(namtp->table),
+                                       (SV**)(namtp->table), NofAMmeth, param);
                }
            }
-           else if (mg->mg_len == HEf_SVKEY)
-               nmg->mg_ptr = (char*)sv_dup_inc((const SV *)mg->mg_ptr, param);
+           else if (nmg->mg_len == HEf_SVKEY)
+               nmg->mg_ptr = (char*)sv_dup_inc((const SV *)nmg->mg_ptr, param);
        }
-       if ((mg->mg_flags & MGf_DUP) && mg->mg_virtual && mg->mg_virtual->svt_dup) {
+       if ((nmg->mg_flags & MGf_DUP) && nmg->mg_virtual && nmg->mg_virtual->svt_dup) {
            CALL_FPTR(nmg->mg_virtual->svt_dup)(aTHX_ nmg, param);
        }
-       mgprev = nmg;
     }
     return mgret;
 }
@@ -10579,7 +10579,7 @@ Perl_ptr_table_new(pTHX)
     PTR_TBL_t *tbl;
     PERL_UNUSED_CONTEXT;
 
-    Newxz(tbl, 1, PTR_TBL_t);
+    Newx(tbl, 1, PTR_TBL_t);
     tbl->tbl_max       = 511;
     tbl->tbl_items     = 0;
     Newxz(tbl->tbl_ary, tbl->tbl_max + 1, PTR_TBL_ENT_t*);
@@ -10772,6 +10772,20 @@ Perl_rvpv_dup(pTHX_ SV *const dstr, const SV *const sstr, CLONE_PARAMS *const pa
     }
 }
 
+/* duplicate a list of SVs. source and dest may point to the same memory.  */
+static SV **
+S_sv_dup_inc_multiple(pTHX_ SV *const *source, SV **dest,
+                     SSize_t items, CLONE_PARAMS *const param)
+{
+    PERL_ARGS_ASSERT_SV_DUP_INC_MULTIPLE;
+
+    while (items-- > 0) {
+       *dest++ = sv_dup_inc(*source++, param);
+    }
+
+    return dest;
+}
+
 /* duplicate an SV of any type (including AV, HV etc) */
 
 SV *
@@ -10995,8 +11009,8 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    AvARRAY(MUTABLE_AV(dstr)) = dst_ary;
                    AvALLOC((const AV *)dstr) = dst_ary;
                    if (AvREAL((const AV *)sstr)) {
-                       while (items-- > 0)
-                           *dst_ary++ = sv_dup_inc(*src_ary++, param);
+                       dst_ary = sv_dup_inc_multiple(src_ary, dst_ary, items,
+                                                     param);
                    }
                    else {
                        while (items-- > 0)
@@ -12164,7 +12178,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
-    PL_bitcount                = NULL; /* reinits on demand */
 
     if (proto_perl->Ipsig_pend) {
        Newxz(PL_psig_pend, SIG_SIZE, int);
@@ -12173,13 +12186,11 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_psig_pend    = (int*)NULL;
     }
 
-    if (proto_perl->Ipsig_ptr) {
-       Newxz(PL_psig_ptr,  SIG_SIZE, SV*);
-       Newxz(PL_psig_name, SIG_SIZE, SV*);
-       for (i = 1; i < SIG_SIZE; i++) {
-           PL_psig_ptr[i]  = sv_dup_inc(proto_perl->Ipsig_ptr[i], param);
-           PL_psig_name[i] = sv_dup_inc(proto_perl->Ipsig_name[i], param);
-       }
+    if (proto_perl->Ipsig_name) {
+       Newx(PL_psig_name, 2 * SIG_SIZE, SV*);
+       sv_dup_inc_multiple(proto_perl->Ipsig_name, PL_psig_name, 2 * SIG_SIZE,
+                           param);
+       PL_psig_ptr = PL_psig_name + SIG_SIZE;
     }
     else {
        PL_psig_ptr     = (SV**)NULL;
@@ -12193,12 +12204,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
        PL_tmps_ix              = proto_perl->Itmps_ix;
        PL_tmps_max             = proto_perl->Itmps_max;
        PL_tmps_floor           = proto_perl->Itmps_floor;
-       Newxz(PL_tmps_stack, PL_tmps_max, SV*);
-       i = 0;
-       while (i <= PL_tmps_ix) {
-           PL_tmps_stack[i]    = sv_dup_inc(proto_perl->Itmps_stack[i], param);
-           ++i;
-       }
+       Newx(PL_tmps_stack, PL_tmps_max, SV*);
+       sv_dup_inc_multiple(proto_perl->Itmps_stack, PL_tmps_stack, PL_tmps_ix,
+                           param);
 
        /* next PUSHMARK() sets *(PL_markstack_ptr+1) */
        i = proto_perl->Imarkstack_max - proto_perl->Imarkstack;
@@ -12318,6 +12326,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* Pluggable optimizer */
     PL_peepp           = proto_perl->Ipeepp;
+    /* op_free() hook */
+    PL_opfreehook      = proto_perl->Iopfreehook;
 
     PL_stashcache       = newHV();
 
@@ -12977,6 +12987,14 @@ S_find_uninit_var(pTHX_ const OP *const obase, const SV *const uninit_sv,
          Need a better fix at dome point. DAPM 11/2007 */
        break;
 
+    case OP_FLIP:
+    case OP_FLOP:
+    {
+       GV * const gv = gv_fetchpvs(".", GV_NOTQUAL, SVt_PV);
+       if (gv && GvSV(gv) == uninit_sv)
+           return newSVpvs_flags("$.", SVs_TEMP);
+       goto do_op;
+    }
 
     case OP_POS:
        /* def-ness of rval pos() is independent of the def-ness of its arg */