This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Magic flags harmonization.
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 2ecdb87..0def4ac 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -650,10 +650,9 @@ PP(pp_gelem)
 PP(pp_study)
 {
     dVAR; dSP; dPOPss;
-    register unsigned char *s;
     STRLEN len;
 
-    s = (unsigned char*)(SvPV(sv, len));
+    (void)SvPV(sv, len);
     if (len == 0 || len > I32_MAX || !SvPOK(sv) || SvUTF8(sv) || SvVALID(sv)) {
        /* Historically, study was skipped in these cases. */
        RETPUSHNO;
@@ -992,7 +991,7 @@ PP(pp_postinc)
     if (SvROK(TOPs))
        TARG = sv_newmortal();
     sv_setsv(TARG, TOPs);
-    if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
+    if (!SvREADONLY(TOPs) && !SvGMAGICAL(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
         && SvIVX(TOPs) != (inc ? IV_MAX : IV_MIN))
     {
        SvIV_set(TOPs, SvIVX(TOPs) + (inc ? 1 : -1));
@@ -2150,10 +2149,34 @@ PP(pp_bit_or)
     }
 }
 
+PERL_STATIC_INLINE bool
+S_negate_string(pTHX)
+{
+    dTARGET; dSP;
+    STRLEN len;
+    const char *s;
+    SV * const sv = TOPs;
+    if (!SvPOKp(sv) || SvNIOK(sv) || (!SvPOK(sv) && SvNIOKp(sv)))
+       return FALSE;
+    s = SvPV_nomg_const(sv, len);
+    if (isIDFIRST(*s)) {
+       sv_setpvs(TARG, "-");
+       sv_catsv(TARG, sv);
+    }
+    else if (*s == '+' || (*s == '-' && !looks_like_number(sv))) {
+       sv_setsv_nomg(TARG, sv);
+       *SvPV_force_nomg(TARG, len) = *s == '-' ? '+' : '-';
+    }
+    else return FALSE;
+    SETTARG; PUTBACK;
+    return TRUE;
+}
+
 PP(pp_negate)
 {
     dVAR; dSP; dTARGET;
     tryAMAGICun_MG(neg_amg, AMGf_numeric);
+    if (S_negate_string(aTHX)) return NORMAL;
     {
        SV * const sv = TOPs;
 
@@ -2184,23 +2207,8 @@ PP(pp_negate)
        }
        if (SvNIOKp(sv) && (SvNIOK(sv) || !SvPOK(sv)))
            SETn(-SvNV_nomg(sv));
-       else if (SvPOKp(sv)) {
-           STRLEN len;
-           const char * const s = SvPV_nomg_const(sv, len);
-           if (isIDFIRST(*s)) {
-               sv_setpvs(TARG, "-");
-               sv_catsv(TARG, sv);
-           }
-           else if (*s == '+' || (*s == '-' && !looks_like_number(sv))) {
-               sv_setsv_nomg(TARG, sv);
-               *SvPV_force_nomg(TARG, len) = *s == '-' ? '+' : '-';
-           }
-           else if (SvIV_please_nomg(sv))
+       else if (SvPOKp(sv) && SvIV_please_nomg(sv))
                  goto oops_its_an_int;
-           else
-               sv_setnv(TARG, -SvNV_nomg(sv));
-           SETTARG;
-       }
        else
            SETn(-SvNV_nomg(sv));
     }
@@ -2551,6 +2559,7 @@ PP(pp_i_negate)
 {
     dVAR; dSP; dTARGET;
     tryAMAGICun_MG(neg_amg, 0);
+    if (S_negate_string(aTHX)) return NORMAL;
     {
        SV * const sv = TOPs;
        IV const i = SvIV_nomg(sv);
@@ -5788,16 +5797,9 @@ PP(pp_coreargs)
        case OA_SCALAR:
          try_defsv:
            if (!numargs && defgv && whicharg == minargs + 1) {
-               PERL_SI * const oldsi = PL_curstackinfo;
-               I32 const oldcxix = oldsi->si_cxix;
-               CV *caller;
-               if (oldcxix) oldsi->si_cxix--;
-               else PL_curstackinfo = oldsi->si_prev;
-               caller = find_runcv(NULL);
-               PL_curstackinfo = oldsi;
-               oldsi->si_cxix = oldcxix;
                PUSHs(find_rundefsv2(
-                   caller,cxstack[cxstack_ix].blk_oldcop->cop_seq
+                   find_runcv_where(FIND_RUNCV_level_eq, (void *)1, NULL),
+                   cxstack[cxstack_ix].blk_oldcop->cop_seq
                ));
            }
            else PUSHs(numargs ? svp && *svp ? *svp : &PL_sv_undef : NULL);
@@ -5885,13 +5887,7 @@ PP(pp_runcv)
     dSP;
     CV *cv;
     if (PL_op->op_private & OPpOFFBYONE) {
-       PERL_SI * const oldsi = PL_curstackinfo;
-       I32 const oldcxix = oldsi->si_cxix;
-       if (oldcxix) oldsi->si_cxix--;
-       else PL_curstackinfo = oldsi->si_prev;
-       cv = find_runcv(NULL);
-       PL_curstackinfo = oldsi;
-       oldsi->si_cxix = oldcxix;
+       cv = find_runcv_where(FIND_RUNCV_level_eq, (void *)1, NULL);
     }
     else cv = find_runcv(NULL);
     XPUSHs(CvEVAL(cv) ? &PL_sv_undef : sv_2mortal(newRV((SV *)cv)));