This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #119043] Exempt shared hash key consts from ro
[perl5.git] / pp_ctl.c
index 721a8a9..ff3d661 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -153,6 +153,9 @@ PP(pp_regcomp)
               modified by get-magic), to avoid incorrectly setting the
               RXf_TAINTED flag with RX_TAINT_on further down. */
            TAINT_set(was_tainted);
+#if NO_TAINT_SUPPORT
+            PERL_UNUSED_VAR(was_tainted);
+#endif
        }
        tmp = reg_temp_copy(NULL, new_re);
        ReREFCNT_dec(new_re);
@@ -211,7 +214,6 @@ PP(pp_substcont)
     }
 
     rxres_restore(&cx->sb_rxres, rx);
-    RX_MATCH_UTF8_set(rx, DO_UTF8(cx->sb_targ));
 
     if (cx->sb_iters++) {
        const I32 saviters = cx->sb_iters;
@@ -224,14 +226,10 @@ PP(pp_substcont)
        if (SvTAINTED(TOPs))
            cx->sb_rxtainted |= SUBST_TAINT_REPL;
        sv_catsv_nomg(dstr, POPs);
-       /* XXX: adjust for positive offsets of \G for instance s/(.)\G//g with positive pos() */
-       s -= RX_GOFS(rx);
-
-       /* Are we done */
        if (CxONCE(cx) || s < orig ||
-               !CALLREGEXEC(rx, s, cx->sb_strend, orig,
-                            (s == m) + RX_GOFS(rx), cx->sb_targ, NULL,
-                                (REXEC_IGNOREPOS|REXEC_NOT_FIRST)))
+                !CALLREGEXEC(rx, s, cx->sb_strend, orig,
+                            (s == m), cx->sb_targ, NULL,
+                    (REXEC_IGNOREPOS|REXEC_NOT_FIRST|REXEC_FAIL_ON_UNDERFLOW)))
        {
            SV *targ = cx->sb_targ;
 
@@ -297,6 +295,7 @@ PP(pp_substcont)
            TAINT_NOT;
            LEAVE_SCOPE(cx->sb_oldsave);
            POPSUBST(cx);
+           PERL_ASYNC_CHECK();
            RETURNOP(pm->op_next);
            assert(0); /* NOTREACHED */
        }
@@ -322,14 +321,8 @@ PP(pp_substcont)
        SV * const sv
            = (pm->op_pmflags & PMf_NONDESTRUCT) ? cx->sb_dstr : cx->sb_targ;
        MAGIC *mg;
-       SvUPGRADE(sv, SVt_PVMG);
-       if (!(mg = mg_find(sv, PERL_MAGIC_regex_global))) {
-#ifdef PERL_OLD_COPY_ON_WRITE
-           if (SvIsCOW(sv))
-               sv_force_normal_flags(sv, 0);
-#endif
-           mg = sv_magicext(sv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob,
-                            NULL, 0);
+       if (!(mg = mg_find_mglob(sv))) {
+           mg = sv_magicext_mglob(sv);
        }
        mg->mg_len = m - orig;
     }
@@ -996,6 +989,10 @@ PP(pp_grepstart)
     SAVEVPTR(PL_curpm);
 
     src = PL_stack_base[*PL_markstack_ptr];
+    if (SvPADTMP(src) && !IS_PADGV(src)) {
+       src = PL_stack_base[*PL_markstack_ptr] = sv_mortalcopy(src);
+       PL_tmps_floor++;
+    }
     SvTEMP_off(src);
     if (PL_op->op_private & OPpGREP_LEX)
        PAD_SVl(PL_op->op_targ) = src;
@@ -1144,6 +1141,7 @@ PP(pp_mapwhile)
 
        /* set $_ to the new source item */
        src = PL_stack_base[PL_markstack_ptr[-1]];
+       if (SvPADTMP(src) && !IS_PADGV(src)) src = sv_mortalcopy(src);
        SvTEMP_off(src);
        if (PL_op->op_private & OPpGREP_LEX)
            PAD_SVl(PL_op->op_targ) = src;
@@ -1438,8 +1436,14 @@ S_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock)
        switch (CxTYPE(cx)) {
        default:
            continue;
-       case CXt_EVAL:
        case CXt_SUB:
+            /* in sub foo { /(?{...})/ }, foo ends up on the CX stack
+             * twice; the first for the normal foo() call, and the second
+             * for a faked up re-entry into the sub to execute the
+             * code block. Hide this faked entry from the world. */
+            if (cx->cx_type & CXp_SUB_RE_FAKE)
+                continue;
+       case CXt_EVAL:
        case CXt_FORMAT:
            DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i));
            return i;
@@ -1653,6 +1657,11 @@ Perl_die_unwind(pTHX_ SV *msv)
            sv_setsv(ERRSV, exceptsv);
        }
 
+       if (in_eval & EVAL_KEEPERR) {
+           Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
+                          SVfARG(exceptsv));
+       }
+
        while ((cxix = dopoptoeval(cxstack_ix)) < 0
               && PL_curstackinfo->si_prev)
        {
@@ -1711,13 +1720,8 @@ Perl_die_unwind(pTHX_ SV *msv)
                           SVfARG(exceptsv ? exceptsv : newSVpvs_flags("Unknown error\n",
                                                                     SVs_TEMP)));
            }
-           if (in_eval & EVAL_KEEPERR) {
-               Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "\t(in cleanup) %"SVf,
-                              SVfARG(exceptsv));
-           }
-           else {
+           if (!(in_eval & EVAL_KEEPERR))
                sv_setsv(ERRSV, exceptsv);
-           }
            PL_restartjmpenv = restartjmpenv;
            PL_restartop = restartop;
            JMPENV_JUMP(3);
@@ -2676,6 +2680,7 @@ PP(pp_next)
     if (PL_scopestack_ix < inner)
        leave_scope(PL_scopestack[PL_scopestack_ix]);
     PL_curcop = cx->blk_oldcop;
+    PERL_ASYNC_CHECK();
     return (cx)->blk_loop.my_op->op_nextop;
 }
 
@@ -2699,6 +2704,7 @@ PP(pp_redo)
     LEAVE_SCOPE(oldsave);
     FREETMPS;
     PL_curcop = cx->blk_oldcop;
+    PERL_ASYNC_CHECK();
     return redo_op;
 }
 
@@ -2712,7 +2718,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
     PERL_ARGS_ASSERT_DOFINDLABEL;
 
     if (ops >= oplimit)
-       Perl_croak(aTHX_ too_deep);
+       Perl_croak(aTHX_ "%s", too_deep);
     if (o->op_type == OP_LEAVE ||
        o->op_type == OP_SCOPE ||
        o->op_type == OP_LEAVELOOP ||
@@ -2721,7 +2727,7 @@ S_dofindlabel(pTHX_ OP *o, const char *label, STRLEN len, U32 flags, OP **opstac
     {
        *ops++ = cUNOPo->op_first;
        if (ops >= oplimit)
-           Perl_croak(aTHX_ too_deep);
+           Perl_croak(aTHX_ "%s", too_deep);
     }
     *ops = 0;
     if (o->op_flags & OPf_KIDS) {
@@ -2915,6 +2921,7 @@ PP(pp_goto)
                PUTBACK;
                (void)(*CvXSUB(cv))(aTHX_ cv);
                LEAVE;
+               PERL_ASYNC_CHECK();
                return retop;
            }
            else {
@@ -2966,6 +2973,7 @@ PP(pp_goto)
                        }
                    }
                }
+               PERL_ASYNC_CHECK();
                RETURNOP(CvSTART(cv));
            }
        }
@@ -2979,7 +2987,7 @@ PP(pp_goto)
         label_flags = (cPVOP->op_private & OPpPV_IS_UTF8) ? SVf_UTF8 : 0;
         label_len   = strlen(label);
     }
-    if (!(do_dump || label_len)) DIE(aTHX_ must_have_label);
+    if (!(do_dump || label_len)) DIE(aTHX_ "%s", must_have_label);
 
     PERL_ASYNC_CHECK();
 
@@ -3057,9 +3065,8 @@ PP(pp_goto)
            PL_lastgotoprobe = gotoprobe;
        }
        if (!retop)
-           DIE(aTHX_ "Can't find label %"SVf,
-                            SVfARG(newSVpvn_flags(label, label_len,
-                                        SVs_TEMP | label_flags)));
+           DIE(aTHX_ "Can't find label %"UTF8f, 
+                      UTF8fARG(label_flags, label_len, label));
 
        /* if we're leaving an eval, check before we pop any frames
            that we're not going to punt, otherwise the error
@@ -3121,6 +3128,7 @@ PP(pp_goto)
        PL_do_undump = FALSE;
     }
 
+    PERL_ASYNC_CHECK();
     RETURNOP(retop);
 }
 
@@ -3279,6 +3287,8 @@ Perl_find_runcv_where(pTHX_ U8 cond, IV arg, U32 *db_seqp)
                    *db_seqp = cx->blk_oldcop->cop_seq;
                    continue;
                }
+                if (cx->cx_type & CXp_SUB_RE)
+                    continue;
            }
            else if (CxTYPE(cx) == CXt_EVAL && !CxTRYBLOCK(cx))
                cv = cx->blk_eval.cv;
@@ -3386,7 +3396,9 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
 
     if (CopSTASH_ne(PL_curcop, PL_curstash)) {
        SAVEGENERICSV(PL_curstash);
-       PL_curstash = (HV *)SvREFCNT_inc_simple(CopSTASH(PL_curcop));
+       PL_curstash = (HV *)CopSTASH(PL_curcop);
+       if (SvTYPE(PL_curstash) != SVt_PVHV) PL_curstash = NULL;
+       else SvREFCNT_inc_simple_void(PL_curstash);
     }
     /* XXX:ajgo do we really need to alloc an AV for begin/checkunit */
     SAVESPTR(PL_beginav);
@@ -3422,6 +3434,15 @@ S_doeval(pTHX_ int gimme, CV* outside, U32 seq, HV *hh)
     else {
        PL_hints = saveop->op_private & OPpEVAL_COPHH
                     ? oldcurcop->cop_hints : saveop->op_targ;
+
+        /* making 'use re eval' not be in scope when compiling the
+         * qr/mabye_has_runtime_code_block/ ensures that we don't get
+         * infinite recursion when S_has_runtime_code() gives a false
+         * positive: the second time round, HINT_RE_EVAL isn't set so we
+         * don't bother calling S_has_runtime_code() */
+        if (PL_in_eval & EVAL_RE_REPARSING)
+            PL_hints &= ~HINT_RE_EVAL;
+
        if (hh) {
            /* SAVEHINTS created a new HV in PL_hintgv, which we need to GC */
            SvREFCNT_dec(GvHV(PL_hintgv));
@@ -3599,6 +3620,32 @@ S_doopen_pm(pTHX_ SV *name)
 #  define doopen_pm(name) check_type_and_open(name)
 #endif /* !PERL_DISABLE_PMC */
 
+/* require doesn't search for absolute names, or when the name is
+   explicity relative the current directory */
+PERL_STATIC_INLINE bool
+S_path_is_searchable(const char *name)
+{
+    PERL_ARGS_ASSERT_PATH_IS_SEARCHABLE;
+
+    if (PERL_FILE_IS_ABSOLUTE(name)
+#ifdef WIN32
+       || (*name == '.' && ((name[1] == '/' ||
+                            (name[1] == '.' && name[2] == '/'))
+                        || (name[1] == '\\' ||
+                            ( name[1] == '.' && name[2] == '\\')))
+           )
+#else
+       || (*name == '.' && (name[1] == '/' ||
+                            (name[1] == '.' && name[2] == '/')))
+#endif
+        )
+    {
+       return FALSE;
+    }
+    else
+       return TRUE;
+}
+
 PP(pp_require)
 {
     dVAR; dSP;
@@ -3626,6 +3673,7 @@ PP(pp_require)
     SV *encoding;
     OP *op;
     int saved_errno;
+    bool path_searchable;
 
     sv = POPs;
     if ( (SvNIOKp(sv) || SvVOK(sv)) && PL_op->op_type != OP_DOFILE) {
@@ -3690,6 +3738,7 @@ PP(pp_require)
        DIE(aTHX_ "Null filename used");
     TAINT_PROPER("require");
 
+    path_searchable = path_is_searchable(name);
 
 #ifdef VMS
     /* The key in the %ENV hash is in the syntax of file passed as the argument
@@ -3729,12 +3778,12 @@ PP(pp_require)
 
     /* prepare to compile file */
 
-    if (path_is_absolute(name)) {
+    if (!path_searchable) {
        /* At this point, name is SvPVX(sv)  */
        tryname = name;
        tryrsfp = doopen_pm(sv);
     }
-    if (!tryrsfp && !(errno == EACCES && path_is_absolute(name))) {
+    if (!tryrsfp && !(errno == EACCES && !path_searchable)) {
        AV * const ar = GvAVn(PL_incgv);
        I32 i;
 #ifdef VMS
@@ -3787,7 +3836,6 @@ PP(pp_require)
                        if (SvROK(arg) && (SvTYPE(SvRV(arg)) <= SVt_PVLV)
                            && !isGV_with_GP(SvRV(arg))) {
                            filter_cache = SvRV(arg);
-                           SvREFCNT_inc_simple_void_NN(filter_cache);
 
                            if (i < count) {
                                arg = SP[i++];
@@ -3850,10 +3898,7 @@ PP(pp_require)
                    }
 
                    filter_has_file = 0;
-                   if (filter_cache) {
-                       SvREFCNT_dec(filter_cache);
-                       filter_cache = NULL;
-                   }
+                   filter_cache = NULL;
                    if (filter_state) {
                        SvREFCNT_dec(filter_state);
                        filter_state = NULL;
@@ -3864,8 +3909,7 @@ PP(pp_require)
                    }
                }
                else {
-                 if (!path_is_absolute(name)
-                 ) {
+                 if (path_searchable) {
                    const char *dir;
                    STRLEN dirlen;
 
@@ -4020,7 +4064,10 @@ PP(pp_require)
           than hanging another SV from it. In turn, filter_add() optionally
           takes the SV to use as the filter (or creates a new SV if passed
           NULL), so simply pass in whatever value filter_cache has.  */
-       SV * const datasv = filter_add(S_run_user_filter, filter_cache);
+       SV * const fc = filter_cache ? newSV(0) : NULL;
+       SV *datasv;
+       if (fc) sv_copypv(fc, filter_cache);
+       datasv = filter_add(S_run_user_filter, fc);
        IoLINES(datasv) = filter_has_file;
        IoTOP_GV(datasv) = MUTABLE_GV(filter_state);
        IoBOTTOM_GV(datasv) = MUTABLE_GV(filter_sub);
@@ -4957,10 +5004,13 @@ PP(pp_leavewhen)
            leave_scope(PL_scopestack[PL_scopestack_ix]);
        PL_curcop = cx->blk_oldcop;
 
+       PERL_ASYNC_CHECK();
        return cx->blk_loop.my_op->op_nextop;
     }
-    else
+    else {
+       PERL_ASYNC_CHECK();
        RETURNOP(cx->blk_givwhen.leave_op);
+    }
 }
 
 PP(pp_continue)
@@ -5481,32 +5531,6 @@ S_run_user_filter(pTHX_ int idx, SV *buf_sv, int maxlen)
     return status;
 }
 
-/* perhaps someone can come up with a better name for
-   this?  it is not really "absolute", per se ... */
-static bool
-S_path_is_absolute(const char *name)
-{
-    PERL_ARGS_ASSERT_PATH_IS_ABSOLUTE;
-
-    if (PERL_FILE_IS_ABSOLUTE(name)
-#ifdef WIN32
-       || (*name == '.' && ((name[1] == '/' ||
-                            (name[1] == '.' && name[2] == '/'))
-                        || (name[1] == '\\' ||
-                            ( name[1] == '.' && name[2] == '\\')))
-           )
-#else
-       || (*name == '.' && (name[1] == '/' ||
-                            (name[1] == '.' && name[2] == '/')))
-#endif
-        )
-    {
-       return TRUE;
-    }
-    else
-       return FALSE;
-}
-
 /*
  * Local variables:
  * c-indentation-style: bsd