Defined-or patch (cleaned up)
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index f2387b4..8f042b9 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -320,6 +320,42 @@ PP(pp_or)
     }
 }
 
+PP(pp_dor)
+{
+    /* Most of this is lifted straight from pp_defined */
+    dSP;
+    register SV* sv;
+
+    sv = TOPs;
+    if (!sv || !SvANY(sv)) {
+       --SP;
+       RETURNOP(cLOGOP->op_other);
+    }
+    
+    switch (SvTYPE(sv)) {
+    case SVt_PVAV:
+       if (AvMAX(sv) >= 0 || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+           RETURN;
+       break;
+    case SVt_PVHV:
+       if (HvARRAY(sv) || SvGMAGICAL(sv) || (SvRMAGICAL(sv) && mg_find(sv, PERL_MAGIC_tied)))
+           RETURN;
+       break;
+    case SVt_PVCV:
+       if (CvROOT(sv) || CvXSUB(sv))
+           RETURN;
+       break;
+    default:
+       if (SvGMAGICAL(sv))
+           mg_get(sv);
+       if (SvOK(sv))
+           RETURN;
+    }
+    
+    --SP;
+    RETURNOP(cLOGOP->op_other);
+}
+
 PP(pp_add)
 {
     dSP; dATARGET; bool useleft; tryAMAGICbin(add,opASSIGN);
@@ -1643,13 +1679,25 @@ PP(pp_helem)
     I32 preeminent = 0;
 
     if (SvTYPE(hv) == SVt_PVHV) {
-       if (PL_op->op_private & OPpLVAL_INTRO)
+       if (PL_op->op_private & OPpLVAL_INTRO) {
+           MAGIC *mg;
+           HV *stash;
+           /* does the element we're localizing already exist? */
            preeminent =  
-               ( SvRMAGICAL(hv)
-                 && !mg_find((SV*)hv, PERL_MAGIC_tied)
-                 && !mg_find((SV*)hv, PERL_MAGIC_env)
-               ) ? 1 : hv_exists_ent(hv, keysv, 0);
+               /* can we determine whether it exists? */
+               (    !SvRMAGICAL(hv)
+                 || mg_find((SV*)hv, PERL_MAGIC_env)
+                 || (     (mg = mg_find((SV*)hv, PERL_MAGIC_tied))
+                       /* Try to preserve the existenceness of a tied hash
+                        * element by using EXISTS and DELETE if possible.
+                        * Fallback to FETCH and STORE otherwise */
+                       && (stash = SvSTASH(SvRV(SvTIED_obj((SV*)hv, mg))))
+                       && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
+                       && gv_fetchmethod_autoload(stash, "DELETE", TRUE)
+                   )
+               ) ? hv_exists_ent(hv, keysv, 0) : 1;
 
+       }
        he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
        svp = he ? &HeVAL(he) : 0;
     }
@@ -1687,17 +1735,8 @@ PP(pp_helem)
                    STRLEN keylen;
                    char *key = SvPV(keysv, keylen);
                    SAVEDELETE(hv, savepvn(key,keylen), keylen);
-               } else {
-                   SV *sv;
+               } else
                    save_helem(hv, keysv, svp);
-                   sv = *svp;
-                   /* If we're localizing a tied hash element, this new
-                    * sv won't actually be stored in the hash - so it
-                    * won't get reaped when the localize ends. Ensure it
-                    * gets reaped by mortifying it instead. DAPM */
-                   if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
-                       sv_2mortal(sv);
-               }
             }
        }
        else if (PL_op->op_private & OPpDEREF)
@@ -1980,8 +2019,21 @@ PP(pp_subst)
 
     /* known replacement string? */
     if (dstr) {
-        c = SvPV(dstr, clen);
-       doutf8 = DO_UTF8(dstr);
+       /* replacement needing upgrading? */
+       if (DO_UTF8(TARG) && !doutf8) {
+            SV *nsv = sv_newmortal();
+            SvSetSV(nsv, dstr);
+            if (PL_encoding)
+                 sv_recode_to_utf8(nsv, PL_encoding);
+            else
+                 sv_utf8_upgrade(nsv);
+            c = SvPV(nsv, clen);
+            doutf8 = TRUE;
+       }
+       else {
+           c = SvPV(dstr, clen);
+           doutf8 = DO_UTF8(dstr);
+       }
     }
     else {
         c = Nullch;
@@ -2086,6 +2138,8 @@ PP(pp_subst)
            SPAGAIN;
        }
        SvTAINT(TARG);
+       if (doutf8)
+           SvUTF8_on(TARG);
        LEAVE_SCOPE(oldsave);
        RETURN;
     }
@@ -2952,17 +3006,8 @@ PP(pp_aelem)
            PUSHs(lv);
            RETURN;
        }
-       if (PL_op->op_private & OPpLVAL_INTRO) {
-           SV *sv;
+       if (PL_op->op_private & OPpLVAL_INTRO)
            save_aelem(av, elem, svp);
-           sv = *svp;
-           /* If we're localizing a tied array element, this new sv
-            * won't actually be stored in the array - so it won't get
-            * reaped when the localize ends. Ensure it gets reaped by
-            * mortifying it instead. DAPM */
-           if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
-               sv_2mortal(sv);
-       }
        else if (PL_op->op_private & OPpDEREF)
            vivify_ref(*svp, PL_op->op_private & OPpDEREF);
     }