X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/6c9570dc5de7137a22f5d4e76431529d4f7342b7..e4c5322dee1b8e87ff0e7aee20effad846301447:/mg.c diff --git a/mg.c b/mg.c index 918510f..1aaf0ac 100644 --- a/mg.c +++ b/mg.c @@ -132,6 +132,39 @@ Perl_mg_magical(pTHX_ SV *sv) } } + +/* is this container magic (%ENV, $1 etc), or value magic (pos, taint etc)? */ + +STATIC bool +S_is_container_magic(const MAGIC *mg) +{ + switch (mg->mg_type) { + case PERL_MAGIC_bm: + case PERL_MAGIC_fm: + case PERL_MAGIC_regex_global: + case PERL_MAGIC_nkeys: +#ifdef USE_LOCALE_COLLATE + case PERL_MAGIC_collxfrm: +#endif + case PERL_MAGIC_qr: + case PERL_MAGIC_taint: + case PERL_MAGIC_vec: + case PERL_MAGIC_vstring: + case PERL_MAGIC_utf8: + case PERL_MAGIC_substr: + case PERL_MAGIC_defelem: + case PERL_MAGIC_arylen: + case PERL_MAGIC_pos: + case PERL_MAGIC_backref: + case PERL_MAGIC_arylen_p: + case PERL_MAGIC_rhash: + case PERL_MAGIC_symtab: + return 0; + default: + return 1; + } +} + /* =for apidoc mg_get @@ -238,6 +271,8 @@ Perl_mg_set(pTHX_ SV *sv) mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */ (SSPTR(mgs_ix, MGS*))->mgs_flags = 0; } + if (PL_localizing == 2 && !S_is_container_magic(mg)) + continue; if (vtbl && vtbl->svt_set) CALL_FPTR(vtbl->svt_set)(aTHX_ sv, mg); } @@ -413,31 +448,9 @@ Perl_mg_localize(pTHX_ SV *sv, SV *nsv) dVAR; MAGIC *mg; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* const vtbl = mg->mg_virtual; - switch (mg->mg_type) { - /* value magic types: don't copy */ - case PERL_MAGIC_bm: - case PERL_MAGIC_fm: - case PERL_MAGIC_regex_global: - case PERL_MAGIC_nkeys: -#ifdef USE_LOCALE_COLLATE - case PERL_MAGIC_collxfrm: -#endif - case PERL_MAGIC_qr: - case PERL_MAGIC_taint: - case PERL_MAGIC_vec: - case PERL_MAGIC_vstring: - case PERL_MAGIC_utf8: - case PERL_MAGIC_substr: - case PERL_MAGIC_defelem: - case PERL_MAGIC_arylen: - case PERL_MAGIC_pos: - case PERL_MAGIC_backref: - case PERL_MAGIC_arylen_p: - case PERL_MAGIC_rhash: - case PERL_MAGIC_symtab: + const MGVTBL* const vtbl = mg->mg_virtual; + if (!S_is_container_magic(mg)) continue; - } if ((mg->mg_flags & MGf_LOCAL) && vtbl->svt_local) (void)CALL_FPTR(vtbl->svt_local)(aTHX_ nsv, mg); @@ -508,7 +521,8 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) /* return the last filled */ while ( paren >= 0 - && (rx->startp[paren] == -1 || rx->endp[paren] == -1) ) + && (rx->offs[paren].start == -1 + || rx->offs[paren].end == -1) ) paren--; return (U32)paren; } @@ -531,8 +545,8 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) if (paren < 0) return 0; if (paren <= (I32)rx->nparens && - (s = rx->startp[paren]) != -1 && - (t = rx->endp[paren]) != -1) + (s = rx->offs[paren].start) != -1 && + (t = rx->offs[paren].end) != -1) { register I32 i; if (mg->mg_obj) /* @+ */ @@ -579,8 +593,8 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) paren = atoi(mg->mg_ptr); /* $& is in [0] */ getparen: if (paren <= (I32)rx->nparens && - (s1 = rx->startp[paren]) != -1 && - (t1 = rx->endp[paren]) != -1) + (s1 = rx->offs[paren].start) != -1 && + (t1 = rx->offs[paren].end) != -1) { i = t1 - s1; getlen: @@ -623,8 +637,8 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) return 0; case '`': if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (rx->startp[0] != -1) { - i = rx->startp[0]; + if (rx->offs[0].start != -1) { + i = rx->offs[0].start; if (i > 0) { s1 = 0; t1 = i; @@ -635,10 +649,10 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) return 0; case '\'': if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (rx->endp[0] != -1) { - i = rx->sublen - rx->endp[0]; + if (rx->offs[0].end != -1) { + i = rx->sublen - rx->offs[0].end; if (i > 0) { - s1 = rx->endp[0]; + s1 = rx->offs[0].end; t1 = rx->sublen; goto getlen; } @@ -666,6 +680,32 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) } \ } STMT_END +void +Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv) +{ + if (!(CopHINTS_get(c) & (HINT_LEXICAL_IO_IN|HINT_LEXICAL_IO_OUT))) + sv_setsv(sv, &PL_sv_undef); + else { + sv_setpvs(sv, ""); + SvUTF8_off(sv); + if ((CopHINTS_get(c) & HINT_LEXICAL_IO_IN)) { + SV *const value = Perl_refcounted_he_fetch(aTHX_ + c->cop_hints_hash, + 0, "open<", 5, 0, 0); + assert(value); + sv_catsv(sv, value); + } + sv_catpvs(sv, "\0"); + if ((CopHINTS_get(c) & HINT_LEXICAL_IO_OUT)) { + SV *const value = Perl_refcounted_he_fetch(aTHX_ + c->cop_hints_hash, + 0, "open>", 5, 0, 0); + assert(value); + sv_catsv(sv, value); + } + } +} + int Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { @@ -769,18 +809,17 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvTAINTED_off(sv); } else if (strEQ(remaining, "PEN")) { - if (!(CopHINTS_get(&PL_compiling) & HINT_LEXICAL_IO)) - sv_setsv(sv, &PL_sv_undef); - else { - sv_setsv(sv, - Perl_refcounted_he_fetch(aTHX_ - PL_compiling.cop_hints_hash, - 0, "open", 4, 0, 0)); - } + Perl_emulate_cop_io(aTHX_ &PL_compiling, sv); } break; - case '\020': /* ^P */ - sv_setiv(sv, (IV)PL_perldb); + case '\020': + if (nextchar == '\0') { /* ^P */ + sv_setiv(sv, (IV)PL_perldb); + } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */ + goto do_prematch_fetch; + } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */ + goto do_postmatch_fetch; + } break; case '\023': /* ^S */ if (nextchar == '\0') { @@ -847,23 +886,26 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvPOK_only(sv); } break; + case '\015': /* $^MATCH */ + if (strEQ(remaining, "ATCH")) { case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '&': - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - /* - * Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj)); - * XXX Does the new way break anything? - */ - paren = atoi(mg->mg_ptr); /* $& is in [0] */ - reg_numbered_buff_get( paren, rx, sv, 0); - break; + if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { + /* + * Pre-threads, this was paren = atoi(GvENAME((GV*)mg->mg_obj)); + * XXX Does the new way break anything? + */ + paren = atoi(mg->mg_ptr); /* $& is in [0] */ + CALLREG_NUMBUF(rx,paren,sv); + break; + } + sv_setsv(sv,&PL_sv_undef); } - sv_setsv(sv,&PL_sv_undef); break; case '+': if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { if (rx->lastparen) { - reg_numbered_buff_get( rx->lastparen, rx, sv, 0); + CALLREG_NUMBUF(rx,rx->lastparen,sv); break; } } @@ -872,7 +914,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '\016': /* ^N */ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { if (rx->lastcloseparen) { - reg_numbered_buff_get( rx->lastcloseparen, rx, sv, 0); + CALLREG_NUMBUF(rx,rx->lastcloseparen,sv); break; } @@ -880,16 +922,18 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setsv(sv,&PL_sv_undef); break; case '`': + do_prematch_fetch: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - reg_numbered_buff_get( -2, rx, sv, 0); - break; + CALLREG_NUMBUF(rx,-2,sv); + break; } sv_setsv(sv,&PL_sv_undef); break; case '\'': + do_postmatch_fetch: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - reg_numbered_buff_get( -1, rx, sv, 0); - break; + CALLREG_NUMBUF(rx,-1,sv); + break; } sv_setsv(sv,&PL_sv_undef); break; @@ -1175,7 +1219,7 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) #endif /* cache state so we don't fetch it again */ if(sigstate == (Sighandler_t) SIG_IGN) - sv_setpv(sv,"IGNORE"); + sv_setpvs(sv,"IGNORE"); else sv_setsv(sv,&PL_sv_undef); PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); @@ -1248,6 +1292,19 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) return 0; } +/* + * The signal handling nomenclature has gotten a bit confusing since the advent of + * safe signals. S_raise_signal only raises signals by analogy with what the + * underlying system's signal mechanism does. It might be more proper to say that + * it defers signals that have already been raised and caught. + * + * PL_sig_pending and PL_psig_pend likewise do not track signals that are pending + * in the sense of being on the system's signal queue in between raising and delivery. + * They are only pending on Perl's deferral list, i.e., they track deferred signals + * awaiting delivery after the current Perl opcode completes and say nothing about + * signals raised but not yet caught in the underlying signal implementation. + */ + #ifndef SIG_PENDING_DIE_COUNT # define SIG_PENDING_DIE_COUNT 120 #endif @@ -1946,13 +2003,11 @@ Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) { dVAR; PERL_UNUSED_ARG(sv); - /* update taint status unless we're restoring at scope exit */ - if (PL_localizing != 2) { - if (PL_tainted) - mg->mg_len |= 1; - else - mg->mg_len &= ~1; - } + /* update taint status */ + if (PL_tainted) + mg->mg_len |= 1; + else + mg->mg_len &= ~1; return 0; } @@ -2039,7 +2094,7 @@ Perl_vivify_defelem(pTHX_ SV *sv) if (he) value = HeVAL(he); if (!value || value == &PL_sv_undef) - Perl_croak(aTHX_ PL_no_helem_sv, (void*)mg->mg_obj); + Perl_croak(aTHX_ PL_no_helem_sv, SVfARG(mg->mg_obj)); } else { AV* const av = (AV*)LvTARG(sv); @@ -2230,11 +2285,33 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } } else if (strEQ(mg->mg_ptr, "\017PEN")) { - PL_compiling.cop_hints |= HINT_LEXICAL_IO; - PL_hints |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO; + STRLEN len; + const char *const start = SvPV(sv, len); + const char *out = (const char*)memchr(start, '\0', len); + SV *tmp; + struct refcounted_he *tmp_he; + + + PL_compiling.cop_hints |= HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT; + PL_hints + |= HINT_LOCALIZE_HH | HINT_LEXICAL_IO_IN | HINT_LEXICAL_IO_OUT; + + /* Opening for input is more common than opening for output, so + ensure that hints for input are sooner on linked list. */ + tmp = sv_2mortal(out ? newSVpvn(out + 1, start + len - out - 1) + : newSVpvs("")); + SvFLAGS(tmp) |= SvUTF8(sv); + + tmp_he + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + sv_2mortal(newSVpvs("open>")), tmp); + + /* The UTF-8 setting is carried over */ + sv_setpvn(tmp, start, out ? (STRLEN)(out - start) : len); + PL_compiling.cop_hints_hash - = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, - sv_2mortal(newSVpvs("open")), sv); + = Perl_refcounted_he_new(aTHX_ tmp_he, + sv_2mortal(newSVpvs("open<")), tmp); } break; case '\020': /* ^P */