Document the do BAREWORD change, from Rafael.
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index ec18858..de2dec4 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -734,7 +734,7 @@ PP(pp_rv2av)
        EXTEND(SP, maxarg);
        if (SvRMAGICAL(av)) {
            U32 i;
-           for (i=0; i < maxarg; i++) {
+           for (i=0; i < (U32)maxarg; i++) {
                SV **svp = av_fetch(av, i, FALSE);
                SP[i+1] = (svp) ? *svp : &PL_sv_undef;
            }
@@ -1184,6 +1184,7 @@ PP(pp_match)
 {
     dSP; dTARG;
     register PMOP *pm = cPMOP;
+    PMOP *dynpm = pm;
     register char *t;
     register char *s;
     char *strend;
@@ -1217,6 +1218,7 @@ PP(pp_match)
 
     PL_reg_match_utf8 = DO_UTF8(TARG);
 
+    /* PMdf_USED is set after a ?? matches once */
     if (pm->op_pmdynflags & PMdf_USED) {
       failure:
        if (gimme == G_ARRAY)
@@ -1224,17 +1226,19 @@ PP(pp_match)
        RETPUSHNO;
     }
 
+    /* empty pattern special-cased to use last successful pattern if possible */
     if (!rx->prelen && PL_curpm) {
        pm = PL_curpm;
        rx = PM_GETRE(pm);
     }
-    if (rx->minlen > len)
-      goto failure;
+
+    if (rx->minlen > (I32)len)
+       goto failure;
 
     truebase = t = s;
 
     /* XXXX What part of this is needed with true \G-support? */
-    if ((global = pm->op_pmflags & PMf_GLOBAL)) {
+    if ((global = dynpm->op_pmflags & PMf_GLOBAL)) {
        rx->startp[0] = -1;
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
            MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global);
@@ -1287,8 +1291,8 @@ play_it_again:
     if (CALLREGEXEC(aTHX_ rx, s, strend, truebase, minmatch, TARG, NULL, r_flags))
     {
        PL_curpm = pm;
-       if (pm->op_pmflags & PMf_ONCE)
-           pm->op_pmdynflags |= PMdf_USED;
+       if (dynpm->op_pmflags & PMf_ONCE)
+           dynpm->op_pmdynflags |= PMdf_USED;
        goto gotcha;
     }
     else
@@ -1325,7 +1329,7 @@ play_it_again:
            }
        }
        if (global) {
-           if (pm->op_pmflags & PMf_CONTINUE) {
+           if (dynpm->op_pmflags & PMf_CONTINUE) {
                MAGIC* mg = 0;
                if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG))
                    mg = mg_find(TARG, PERL_MAGIC_regex_global);
@@ -1378,8 +1382,8 @@ yup:                                      /* Confirmed by INTUIT */
        RX_MATCH_TAINTED_on(rx);
     TAINT_IF(RX_MATCH_TAINTED(rx));
     PL_curpm = pm;
-    if (pm->op_pmflags & PMf_ONCE)
-       pm->op_pmdynflags |= PMdf_USED;
+    if (dynpm->op_pmflags & PMf_ONCE)
+       dynpm->op_pmdynflags |= PMdf_USED;
     if (RX_MATCH_COPIED(rx))
        Safefree(rx->subbeg);
     RX_MATCH_COPIED_off(rx);
@@ -1416,7 +1420,7 @@ yup:                                      /* Confirmed by INTUIT */
 
 nope:
 ret_no:
-    if (global && !(pm->op_pmflags & PMf_CONTINUE)) {
+    if (global && !(dynpm->op_pmflags & PMf_CONTINUE)) {
        if (SvTYPE(TARG) >= SVt_PVMG && SvMAGIC(TARG)) {
            MAGIC* mg = mg_find(TARG, PERL_MAGIC_regex_global);
            if (mg)
@@ -1639,8 +1643,25 @@ PP(pp_helem)
     I32 preeminent = 0;
 
     if (SvTYPE(hv) == SVt_PVHV) {
-       if (PL_op->op_private & OPpLVAL_INTRO)
-           preeminent = SvRMAGICAL(hv) ? 1 : hv_exists_ent(hv, keysv, 0);
+       if (PL_op->op_private & OPpLVAL_INTRO) {
+           MAGIC *mg;
+           HV *stash;
+           /* does the element we're localizing already exist? */
+           preeminent =  
+               /* 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;
     }
@@ -1971,7 +1992,7 @@ PP(pp_subst)
     }
     
     /* can do inplace substitution? */
-    if (c && clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
+    if (c && (I32)clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
        && !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) {
        if (!CALLREGEXEC(aTHX_ rx, s, strend, orig, 0, TARG, NULL,
                         r_flags | REXEC_CHECKED))
@@ -2113,7 +2134,14 @@ PP(pp_subst)
                break;
        } while (CALLREGEXEC(aTHX_ rx, s, strend, orig, s == m,
                             TARG, NULL, r_flags));
-       sv_catpvn(dstr, s, strend - s);
+       if (doutf8 && !DO_UTF8(dstr)) {
+           SV* nsv = sv_2mortal(newSVpvn(s, strend - s));
+           
+           sv_utf8_upgrade(nsv);
+           sv_catpvn(dstr, SvPVX(nsv), SvCUR(nsv));
+       }
+       else
+           sv_catpvn(dstr, s, strend - s);
 
        (void)SvOOK_off(TARG);
        Safefree(SvPVX(TARG));