X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=6012d32f9ec666ac536cb337be9c4328cd98a0f8;hb=e08926902e591e5c2d12e9e6e88a0d5ec7998770;hp=b63a87c46c465305033a76abbe1c96f824fa8e3b;hpb=bb7a0f5422600fd7de7806825a1300a577b7e61f;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index b63a87c..6012d32 100644 --- a/mg.c +++ b/mg.c @@ -1,7 +1,7 @@ /* mg.c * * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - * 2000, 2001, 2002, 2003, 2004, 2005, 2006, by Larry Wall and others + * 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, by Larry Wall and others * * You may distribute under the terms of either the GNU General Public * License or the Artistic License, as specified in the README file. @@ -56,7 +56,7 @@ tie. #endif #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) -Signal_t Perl_csighandler(int sig, ...); +Signal_t Perl_csighandler(int sig, siginfo_t *, void *); #else Signal_t Perl_csighandler(int sig); #endif @@ -85,6 +85,9 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) { dVAR; MGS* mgs; + + PERL_ARGS_ASSERT_SAVE_MAGIC; + assert(SvMAGICAL(sv)); /* Turning READONLY off for a copy-on-write scalar (including shared hash keys) is a bad idea. */ @@ -100,7 +103,10 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) SvMAGICAL_off(sv); SvREADONLY_off(sv); - SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; + if (!(SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK))) { + /* No public flags are set, so promote any private flags to public. */ + SvFLAGS(sv) |= (SvFLAGS(sv) & (SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT; + } } /* @@ -115,17 +121,57 @@ void Perl_mg_magical(pTHX_ SV *sv) { const MAGIC* mg; + PERL_ARGS_ASSERT_MG_MAGICAL; PERL_UNUSED_CONTEXT; - for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - const MGVTBL* const vtbl = mg->mg_virtual; - if (vtbl) { - if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP)) - SvGMAGICAL_on(sv); - if (vtbl->svt_set) - SvSMAGICAL_on(sv); - if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG)) || vtbl->svt_clear) - SvRMAGICAL_on(sv); - } + if ((mg = SvMAGIC(sv))) { + SvRMAGICAL_off(sv); + do { + const MGVTBL* const vtbl = mg->mg_virtual; + if (vtbl) { + if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP)) + SvGMAGICAL_on(sv); + if (vtbl->svt_set) + SvSMAGICAL_on(sv); + if (vtbl->svt_clear) + SvRMAGICAL_on(sv); + } + } while ((mg = mg->mg_moremagic)); + if (!(SvFLAGS(sv) & (SVs_GMG|SVs_SMG))) + SvRMAGICAL_on(sv); + } +} + + +/* is this container magic (%ENV, $1 etc), or value magic (pos, taint etc)? */ + +STATIC bool +S_is_container_magic(const MAGIC *mg) +{ + assert(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; } } @@ -148,11 +194,13 @@ Perl_mg_get(pTHX_ SV *sv) /* guard against sv having being freed midway by holding a private reference. */ + PERL_ARGS_ASSERT_MG_GET; + /* sv_2mortal has this side effect of turning on the TEMP flag, which can cause the SV's buffer to get stolen (and maybe other stuff). So restore it. */ - sv_2mortal(SvREFCNT_inc_simple(sv)); + sv_2mortal(SvREFCNT_inc_simple_NN(sv)); if (!was_temp) { SvTEMP_off(sv); } @@ -226,6 +274,8 @@ Perl_mg_set(pTHX_ SV *sv) MAGIC* mg; MAGIC* nextmg; + PERL_ARGS_ASSERT_MG_SET; + save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = nextmg) { @@ -235,6 +285,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); } @@ -258,6 +310,8 @@ Perl_mg_length(pTHX_ SV *sv) MAGIC* mg; STRLEN len; + PERL_ARGS_ASSERT_MG_LENGTH; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const MGVTBL * const vtbl = mg->mg_virtual; if (vtbl && vtbl->svt_len) { @@ -270,12 +324,15 @@ Perl_mg_length(pTHX_ SV *sv) } } - if (DO_UTF8(sv)) { + { + /* You can't know whether it's UTF-8 until you get the string again... + */ const U8 *s = (U8*)SvPV_const(sv, len); - len = Perl_utf8_length(aTHX_ s, s + len); + + if (DO_UTF8(sv)) { + len = utf8_length(s, s + len); + } } - else - (void)SvPV_const(sv, len); return len; } @@ -284,6 +341,8 @@ Perl_mg_size(pTHX_ SV *sv) { MAGIC* mg; + PERL_ARGS_ASSERT_MG_SIZE; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const MGVTBL* const vtbl = mg->mg_virtual; if (vtbl && vtbl->svt_len) { @@ -323,6 +382,8 @@ Perl_mg_clear(pTHX_ SV *sv) const I32 mgs_ix = SSNEW(sizeof(MGS)); MAGIC* mg; + PERL_ARGS_ASSERT_MG_CLEAR; + save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { @@ -372,6 +433,9 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen) { int count = 0; MAGIC* mg; + + PERL_ARGS_ASSERT_MG_COPY; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const MGVTBL* const vtbl = mg->mg_virtual; if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){ @@ -379,7 +443,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen) } else { const char type = mg->mg_type; - if (isUPPER(type)) { + if (isUPPER(type) && type != PERL_MAGIC_uvar) { sv_magic(nsv, (type == PERL_MAGIC_tied) ? SvTIED_obj(sv, mg) @@ -409,32 +473,13 @@ Perl_mg_localize(pTHX_ SV *sv, SV *nsv) { dVAR; MAGIC *mg; + + PERL_ARGS_ASSERT_MG_LOCALIZE; + 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); @@ -467,6 +512,9 @@ Perl_mg_free(pTHX_ SV *sv) { MAGIC* mg; MAGIC* moremagic; + + PERL_ARGS_ASSERT_MG_FREE; + for (mg = SvMAGIC(sv); mg; mg = moremagic) { const MGVTBL* const vtbl = mg->mg_virtual; moremagic = mg->mg_moremagic; @@ -481,8 +529,10 @@ Perl_mg_free(pTHX_ SV *sv) if (mg->mg_flags & MGf_REFCOUNTED) SvREFCNT_dec(mg->mg_obj); Safefree(mg); + SvMAGIC_set(sv, moremagic); } SvMAGIC_set(sv, NULL); + SvMAGICAL_off(sv); return 0; } @@ -494,12 +544,24 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) dVAR; PERL_UNUSED_ARG(sv); + PERL_ARGS_ASSERT_MAGIC_REGDATA_CNT; + if (PL_curpm) { register const REGEXP * const rx = PM_GETRE(PL_curpm); if (rx) { - return mg->mg_obj - ? rx->nparens /* @+ */ - : rx->lastparen; /* @- */ + if (mg->mg_obj) { /* @+ */ + /* return the number possible */ + return RX_NPARENS(rx); + } else { /* @- */ + I32 paren = RX_LASTPAREN(rx); + + /* return the last filled */ + while ( paren >= 0 + && (RX_OFFS(rx)[paren].start == -1 + || RX_OFFS(rx)[paren].end == -1) ) + paren--; + return (U32)paren; + } } } @@ -510,6 +572,9 @@ int Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) { dVAR; + + PERL_ARGS_ASSERT_MAGIC_REGDATUM_GET; + if (PL_curpm) { register const REGEXP * const rx = PM_GETRE(PL_curpm); if (rx) { @@ -518,9 +583,9 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) register I32 t; if (paren < 0) return 0; - if (paren <= (I32)rx->nparens && - (s = rx->startp[paren]) != -1 && - (t = rx->endp[paren]) != -1) + if (paren <= (I32)RX_NPARENS(rx) && + (s = RX_OFFS(rx)[paren].start) != -1 && + (t = RX_OFFS(rx)[paren].end) != -1) { register I32 i; if (mg->mg_obj) /* @+ */ @@ -529,9 +594,9 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) i = s; if (i > 0 && RX_MATCH_UTF8(rx)) { - const char * const b = rx->subbeg; + const char * const b = RX_SUBBEG(rx); if (b) - i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i)); + i = utf8_length((U8*)b, (U8*)(b+i)); } sv_setiv(sv, i); @@ -544,6 +609,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_REGDATUM_SET; PERL_UNUSED_ARG(sv); PERL_UNUSED_ARG(mg); Perl_croak(aTHX_ PL_no_modify); @@ -556,83 +622,69 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) dVAR; register I32 paren; register I32 i; - register const REGEXP *rx; - I32 s1, t1; + register const REGEXP * rx; + const char * const remaining = mg->mg_ptr + 1; + + PERL_ARGS_ASSERT_MAGIC_LEN; switch (*mg->mg_ptr) { + case '\020': + if (*remaining == '\0') { /* ^P */ + break; + } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */ + goto do_prematch; + } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */ + goto do_postmatch; + } + break; + case '\015': /* $^MATCH */ + if (strEQ(remaining, "ATCH")) { + goto do_match; + } else { + break; + } + case '`': + do_prematch: + paren = RX_BUFF_IDX_PREMATCH; + goto maybegetparen; + case '\'': + do_postmatch: + paren = RX_BUFF_IDX_POSTMATCH; + goto maybegetparen; + case '&': + do_match: + paren = RX_BUFF_IDX_FULLMATCH; + goto maybegetparen; case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': case '&': + case '5': case '6': case '7': case '8': case '9': + paren = atoi(mg->mg_ptr); + maybegetparen: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { + getparen: + i = CALLREG_NUMBUF_LENGTH((REGEXP * const)rx, sv, paren); - paren = atoi(mg->mg_ptr); /* $& is in [0] */ - getparen: - if (paren <= (I32)rx->nparens && - (s1 = rx->startp[paren]) != -1 && - (t1 = rx->endp[paren]) != -1) - { - i = t1 - s1; - getlen: - if (i > 0 && RX_MATCH_UTF8(rx)) { - const char * const s = rx->subbeg + s1; - const U8 *ep; - STRLEN el; - - i = t1 - s1; - if (is_utf8_string_loclen((U8*)s, i, &ep, &el)) - i = el; - } if (i < 0) Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i); return i; - } - else { + } else { if (ckWARN(WARN_UNINITIALIZED)) report_uninit(sv); - } - } - else { - if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(sv); + return 0; } - return 0; case '+': if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = rx->lastparen; + paren = RX_LASTPAREN(rx); if (paren) goto getparen; } return 0; case '\016': /* ^N */ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = rx->lastcloseparen; + paren = RX_LASTCLOSEPAREN(rx); if (paren) goto getparen; } return 0; - case '`': - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (rx->startp[0] != -1) { - i = rx->startp[0]; - if (i > 0) { - s1 = 0; - t1 = i; - goto getlen; - } - } - } - return 0; - case '\'': - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (rx->endp[0] != -1) { - i = rx->sublen - rx->endp[0]; - if (i > 0) { - s1 = rx->endp[0]; - t1 = rx->sublen; - goto getlen; - } - } - } - return 0; } magic_get(sv,mg); if (!SvPOK(sv) && SvNIOK(sv)) { @@ -654,17 +706,46 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) } \ } STMT_END +void +Perl_emulate_cop_io(pTHX_ const COP *const c, SV *const sv) +{ + PERL_ARGS_ASSERT_EMULATE_COP_IO; + + 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) { dVAR; register I32 paren; register char *s = NULL; - register I32 i; register REGEXP *rx; const char * const remaining = mg->mg_ptr + 1; const char nextchar = *remaining; + PERL_ARGS_ASSERT_MAGIC_GET; + switch (*mg->mg_ptr) { case '\001': /* ^A */ sv_setsv(sv, PL_bodytarget); @@ -747,10 +828,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setiv(sv, (IV)PL_hints); break; case '\011': /* ^I */ /* NOT \t in EBCDIC */ - if (PL_inplace) - sv_setpv(sv, PL_inplace); - else - sv_setsv(sv, &PL_sv_undef); + sv_setpv(sv, PL_inplace); /* Will undefine sv if PL_inplace is NULL */ break; case '\017': /* ^O & ^OPEN */ if (nextchar == '\0') { @@ -758,19 +836,21 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvTAINTED_off(sv); } else if (strEQ(remaining, "PEN")) { - if (!PL_compiling.cop_io) - sv_setsv(sv, &PL_sv_undef); - else { - sv_setsv(sv, PL_compiling.cop_io); - } + 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') { - if (PL_lex_state != LEX_NOTPARSING) + if (PL_parser && PL_parser->lex_state != LEX_NOTPARSING) SvOK_off(sv); else if (PL_in_eval) sv_setiv(sv, PL_in_eval & ~(EVAL_INREQUIRE)); @@ -816,10 +896,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) else if (PL_compiling.cop_warnings == pWARN_ALL) { /* Get the bit mask for $warnings::Bits{all}, because * it could have been extended by warnings::register */ - SV **bits_all; HV * const bits=get_hv("warnings::Bits", FALSE); - if (bits && (bits_all=hv_fetchs(bits, "all", FALSE))) { - sv_setsv(sv, *bits_all); + if (bits) { + SV ** const bits_all = hv_fetchs(bits, "all", FALSE); + if (bits_all) + sv_setsv(sv, *bits_all); } else { sv_setpvn(sv, WARN_ALLstring, WARNsize) ; @@ -832,87 +913,54 @@ 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))) { - I32 s1, t1; - - /* - * 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] */ - getparen: - if (paren <= (I32)rx->nparens && - (s1 = rx->startp[paren]) != -1 && - (t1 = rx->endp[paren]) != -1) - { - i = t1 - s1; - s = rx->subbeg + s1; - assert(rx->subbeg); - - getrx: - if (i >= 0) { - const int oldtainted = PL_tainted; - TAINT_NOT; - sv_setpvn(sv, s, i); - PL_tainted = oldtainted; - if (RX_MATCH_UTF8(rx) && is_utf8_string((U8*)s, i)) - SvUTF8_on(sv); - else - SvUTF8_off(sv); - if (PL_tainting) { - if (RX_MATCH_TAINTED(rx)) { - MAGIC* const mg = SvMAGIC(sv); - MAGIC* mgt; - PL_tainted = 1; - SvMAGIC_set(sv, mg->mg_moremagic); - SvTAINT(sv); - if ((mgt = SvMAGIC(sv))) { - mg->mg_moremagic = mgt; - SvMAGIC_set(sv, mg); - } - } else - SvTAINTED_off(sv); - } - 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_FETCH(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))) { - paren = rx->lastparen; - if (paren) - goto getparen; + if (RX_LASTPAREN(rx)) { + CALLREG_NUMBUF_FETCH(rx,RX_LASTPAREN(rx),sv); + break; + } } sv_setsv(sv,&PL_sv_undef); break; case '\016': /* ^N */ if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = rx->lastcloseparen; - if (paren) - goto getparen; + if (RX_LASTCLOSEPAREN(rx)) { + CALLREG_NUMBUF_FETCH(rx,RX_LASTCLOSEPAREN(rx),sv); + break; + } + } sv_setsv(sv,&PL_sv_undef); break; case '`': + do_prematch_fetch: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if ((s = rx->subbeg) && rx->startp[0] != -1) { - i = rx->startp[0]; - goto getrx; - } + CALLREG_NUMBUF_FETCH(rx,-2,sv); + break; } sv_setsv(sv,&PL_sv_undef); break; case '\'': + do_postmatch_fetch: if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (rx->subbeg && rx->endp[0] != -1) { - s = rx->subbeg + rx->endp[0]; - i = rx->sublen - rx->endp[0]; - goto getrx; - } + CALLREG_NUMBUF_FETCH(rx,-1,sv); + break; } sv_setsv(sv,&PL_sv_undef); break; @@ -937,7 +985,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setpv(sv,s); else { sv_setpv(sv,GvENAME(PL_defoutgv)); - sv_catpv(sv,"_TOP"); + sv_catpvs(sv,"_TOP"); } break; case '~': @@ -964,7 +1012,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '/': break; case '[': - WITH_THR(sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop))); + sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop)); break; case '|': if (GvIOp(PL_defoutgv)) @@ -1034,6 +1082,8 @@ Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg) { struct ufuncs * const uf = (struct ufuncs *)mg->mg_ptr; + PERL_ARGS_ASSERT_MAGIC_GETUVAR; + if (uf && uf->uf_val) (*uf->uf_val)(aTHX_ uf->uf_index, sv); return 0; @@ -1048,6 +1098,8 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) const char * const ptr = MgPV_const(mg,klen); my_setenv(ptr, s); + PERL_ARGS_ASSERT_MAGIC_SETENV; + #ifdef DYNAMIC_ENV_FETCH /* We just undefd an environment var. Is a replacement */ /* waiting in the wings? */ @@ -1069,8 +1121,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) Stat_t sbuf; int i = 0, j = 0; - strncpy(eltbuf, s, 255); - eltbuf[255] = 0; + my_strlcpy(eltbuf, s, sizeof(eltbuf)); elt = eltbuf; do { /* DCL$PATH may be a search list */ while (1) { /* as may dev portion of any element */ @@ -1099,11 +1150,20 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) char tmpbuf[256]; Stat_t st; I32 i; +#ifdef VMS /* Hmm. How do we get $Config{path_sep} from C? */ + const char path_sep = '|'; +#else + const char path_sep = ':'; +#endif s = delimcpy(tmpbuf, tmpbuf + sizeof tmpbuf, - s, strend, ':', &i); + s, strend, path_sep, &i); s++; if (i >= (I32)sizeof tmpbuf /* too long -- assume the worst */ - || *tmpbuf != '/' +#ifdef VMS + || !strchr(tmpbuf, ':') /* no colon thus no device name -- assume relative path */ +#else + || *tmpbuf != '/' /* no starting slash -- assume relative path */ +#endif || (PerlLIO_stat(tmpbuf, &st) == 0 && (st.st_mode & 2)) ) { MgTAINTEDDIR_on(mg); return 0; @@ -1119,6 +1179,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_CLEARENV; PERL_UNUSED_ARG(sv); my_setenv(MgPV_nolen_const(mg),NULL); return 0; @@ -1128,6 +1189,7 @@ int Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) { dVAR; + PERL_ARGS_ASSERT_MAGIC_SET_ALL_ENV; PERL_UNUSED_ARG(mg); #if defined(VMS) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); @@ -1150,6 +1212,7 @@ int Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) { dVAR; + PERL_ARGS_ASSERT_MAGIC_CLEAR_ALL_ENV; PERL_UNUSED_ARG(sv); PERL_UNUSED_ARG(mg); #if defined(VMS) @@ -1166,7 +1229,7 @@ static void restore_sigmask(pTHX_ SV *save_sv) { const sigset_t * const ossetp = (const sigset_t *) SvPV_nolen_const( save_sv ); - (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0); + (void)sigprocmask(SIG_SETMASK, ossetp, NULL); } #endif int @@ -1175,24 +1238,28 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) dVAR; /* Are we fetching a signal entry? */ const I32 i = whichsig(MgPV_nolen_const(mg)); + + PERL_ARGS_ASSERT_MAGIC_GETSIG; + if (i > 0) { if(PL_psig_ptr[i]) sv_setsv(sv,PL_psig_ptr[i]); else { - Sighandler_t sigstate; - sigstate = rsignal_state(i); + Sighandler_t sigstate = rsignal_state(i); #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - if (PL_sig_handlers_initted && PL_sig_ignoring[i]) sigstate = SIG_IGN; + if (PL_sig_handlers_initted && PL_sig_ignoring[i]) + sigstate = SIG_IGN; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS - if (PL_sig_handlers_initted && PL_sig_defaulting[i]) sigstate = SIG_DFL; + if (PL_sig_handlers_initted && PL_sig_defaulting[i]) + sigstate = SIG_DFL; #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(sv); + PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); SvTEMP_off(sv); } } @@ -1206,19 +1273,18 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) */ dVAR; register const char * const s = MgPV_nolen_const(mg); + PERL_ARGS_ASSERT_MAGIC_CLEARSIG; PERL_UNUSED_ARG(sv); if (*s == '_') { SV** svp = NULL; if (strEQ(s,"__DIE__")) svp = &PL_diehook; - else if (strEQ(s,"__WARN__")) + else if (strEQ(s,"__WARN__") && PL_warnhook != PERL_WARNHOOK_FATAL) svp = &PL_warnhook; - else - Perl_croak(aTHX_ "No such hook: %s", s); if (svp && *svp) { - SV * const to_dec = *svp; + SV *const to_dec = *svp; *svp = NULL; - SvREFCNT_dec(to_dec); + SvREFCNT_dec(to_dec); } } else { @@ -1233,7 +1299,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) sigaddset(&set,i); sigprocmask(SIG_BLOCK, &set, &save); ENTER; - save_sv = newSVpv((char *)(&save), sizeof(sigset_t)); + save_sv = newSVpvn((char *)(&save), sizeof(sigset_t)); SAVEFREESV(save_sv); SAVEDESTRUCTOR_X(restore_sigmask, save_sv); #endif @@ -1264,19 +1330,9 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) return 0; } -static void -S_raise_signal(pTHX_ int sig) -{ - dVAR; - /* Set a flag to say this signal is pending */ - PL_psig_pend[sig]++; - /* And one to say _a_ signal is pending */ - PL_sig_pending = 1; -} - Signal_t #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) -Perl_csighandler(int sig, ...) +Perl_csighandler(int sig, siginfo_t *sip PERL_UNUSED_DECL, void *uap PERL_UNUSED_DECL) #else Perl_csighandler(int sig) #endif @@ -1298,12 +1354,37 @@ Perl_csighandler(int sig) exit(1); #endif #endif - if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) + if ( +#ifdef SIGILL + sig == SIGILL || +#endif +#ifdef SIGBUS + sig == SIGBUS || +#endif +#ifdef SIGSEGV + sig == SIGSEGV || +#endif + (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)) /* Call the perl level handler now-- * with risk we may be in malloc() etc. */ +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) + (*PL_sighandlerp)(sig, NULL, NULL); +#else (*PL_sighandlerp)(sig); - else - S_raise_signal(aTHX_ sig); +#endif + else { + /* Set a flag to say this signal is pending, that is awaiting delivery after + * the current Perl opcode completes */ + PL_psig_pend[sig]++; + +#ifndef SIG_PENDING_DIE_COUNT +# define SIG_PENDING_DIE_COUNT 120 +#endif + /* And one to say _a_ signal is pending */ + if (++PL_sig_pending >= SIG_PENDING_DIE_COUNT) + Perl_croak(aTHX_ "Maximal count of pending signals (%lu) exceeded", + (unsigned long)SIG_PENDING_DIE_COUNT); + } } #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS) @@ -1338,7 +1419,11 @@ Perl_despatch_signals(pTHX) PERL_BLOCKSIG_ADD(set, sig); PL_psig_pend[sig] = 0; PERL_BLOCKSIG_BLOCK(set); +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) + (*PL_sighandlerp)(sig, NULL, NULL); +#else (*PL_sighandlerp)(sig); +#endif PERL_BLOCKSIG_UNBLOCK(set); } } @@ -1360,8 +1445,10 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) sigset_t set, save; SV* save_sv; #endif - register const char *s = MgPV_const(mg,len); + + PERL_ARGS_ASSERT_MAGIC_SETSIG; + if (*s == '_') { if (strEQ(s,"__DIE__")) svp = &PL_diehook; @@ -1371,7 +1458,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) Perl_croak(aTHX_ "No such hook: %s", s); i = 0; if (*svp) { - to_dec = *svp; + if (*svp != PERL_WARNHOOK_FATAL) + to_dec = *svp; *svp = NULL; } } @@ -1388,7 +1476,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) sigaddset(&set,i); sigprocmask(SIG_BLOCK, &set, &save); ENTER; - save_sv = newSVpv((char *)(&save), sizeof(sigset_t)); + save_sv = newSVpvn((char *)(&save), sizeof(sigset_t)); SAVEFREESV(save_sv); SAVEDESTRUCTOR_X(restore_sigmask, save_sv); #endif @@ -1404,7 +1492,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) #endif SvREFCNT_dec(PL_psig_name[i]); to_dec = PL_psig_ptr[i]; - PL_psig_ptr[i] = SvREFCNT_inc_simple(sv); + PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); SvTEMP_off(sv); /* Make sure it doesn't go away on us */ PL_psig_name[i] = newSVpvn(s, len); SvREADONLY_on(PL_psig_name[i]); @@ -1422,7 +1510,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) SvREFCNT_dec(to_dec); return 0; } - s = SvPV_force(sv,len); + s = SvOK(sv) ? SvPV_force(sv,len) : "DEFAULT"; if (strEQ(s,"IGNORE")) { if (i) { #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS @@ -1451,11 +1539,12 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) * tell whether HINT_STRICT_REFS is in force or not. */ if (!strchr(s,':') && !strchr(s,'\'')) - Perl_sv_insert(aTHX_ sv, 0, 0, STR_WITH_LEN("main::")); + Perl_sv_insert_flags(aTHX_ sv, 0, 0, STR_WITH_LEN("main::"), + SV_GMAGIC); if (i) (void)rsignal(i, PL_csighandlerp); else - *svp = SvREFCNT_inc_simple(sv); + *svp = SvREFCNT_inc_simple_NN(sv); } #ifdef HAS_SIGPROCMASK if(i) @@ -1471,9 +1560,61 @@ int Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) { dVAR; + HV* stash; + + PERL_ARGS_ASSERT_MAGIC_SETISA; PERL_UNUSED_ARG(sv); - PERL_UNUSED_ARG(mg); - PL_sub_generation++; + + /* Bail out if destruction is going on */ + if(PL_dirty) return 0; + + /* Skip _isaelem because _isa will handle it shortly */ + if (PL_delaymagic & DM_ARRAY && mg->mg_type == PERL_MAGIC_isaelem) + return 0; + + /* XXX Once it's possible, we need to + detect that our @ISA is aliased in + other stashes, and act on the stashes + of all of the aliases */ + + /* The first case occurs via setisa, + the second via setisa_elem, which + calls this same magic */ + stash = GvSTASH( + SvTYPE(mg->mg_obj) == SVt_PVGV + ? (GV*)mg->mg_obj + : (GV*)mg_find(mg->mg_obj, PERL_MAGIC_isa)->mg_obj + ); + + if (stash) + mro_isa_changed_in(stash); + + return 0; +} + +int +Perl_magic_clearisa(pTHX_ SV *sv, MAGIC *mg) +{ + dVAR; + HV* stash; + + PERL_ARGS_ASSERT_MAGIC_CLEARISA; + + /* Bail out if destruction is going on */ + if(PL_dirty) return 0; + + av_clear((AV*)sv); + + /* XXX see comments in magic_setisa */ + stash = GvSTASH( + SvTYPE(mg->mg_obj) == SVt_PVGV + ? (GV*)mg->mg_obj + : (GV*)mg_find(mg->mg_obj, PERL_MAGIC_isa)->mg_obj + ); + + if (stash) + mro_isa_changed_in(stash); + return 0; } @@ -1481,9 +1622,9 @@ int Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) { dVAR; + PERL_ARGS_ASSERT_MAGIC_SETAMAGIC; PERL_UNUSED_ARG(sv); PERL_UNUSED_ARG(mg); - /* HV_badAMAGIC_on(Sv_STASH(sv)); */ PL_amagic_generation++; return 0; @@ -1494,6 +1635,8 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) { HV * const hv = (HV*)LvTARG(sv); I32 i = 0; + + PERL_ARGS_ASSERT_MAGIC_GETNKEYS; PERL_UNUSED_ARG(mg); if (hv) { @@ -1513,6 +1656,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETNKEYS; PERL_UNUSED_ARG(mg); if (LvTARG(sv)) { hv_ksplit((HV*)LvTARG(sv), SvIV(sv)); @@ -1527,18 +1671,20 @@ S_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, I32 flags, int dVAR; dSP; + PERL_ARGS_ASSERT_MAGIC_METHCALL; + PUSHMARK(SP); EXTEND(SP, n); PUSHs(SvTIED_obj(sv, mg)); if (n > 1) { if (mg->mg_ptr) { if (mg->mg_len >= 0) - PUSHs(sv_2mortal(newSVpvn(mg->mg_ptr, mg->mg_len))); + mPUSHp(mg->mg_ptr, mg->mg_len); else if (mg->mg_len == HEf_SVKEY) PUSHs((SV*)mg->mg_ptr); } else if (mg->mg_type == PERL_MAGIC_tiedelem) { - PUSHs(sv_2mortal(newSViv(mg->mg_len))); + mPUSHi(mg->mg_len); } } if (n > 2) { @@ -1554,6 +1700,8 @@ S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth) { dVAR; dSP; + PERL_ARGS_ASSERT_MAGIC_METHPACK; + ENTER; SAVETMPS; PUSHSTACKi(PERLSI_MAGIC); @@ -1571,6 +1719,8 @@ S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth) int Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_GETPACK; + if (mg->mg_ptr) mg->mg_flags |= MGf_GSKIP; magic_methpack(sv,mg,"FETCH"); @@ -1581,6 +1731,9 @@ int Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg) { dVAR; dSP; + + PERL_ARGS_ASSERT_MAGIC_SETPACK; + ENTER; PUSHSTACKi(PERLSI_MAGIC); magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv); @@ -1592,6 +1745,8 @@ Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_CLEARPACK; + return magic_methpack(sv,mg,"DELETE"); } @@ -1600,19 +1755,23 @@ U32 Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg) { dVAR; dSP; - U32 retval = 0; + I32 retval = 0; + + PERL_ARGS_ASSERT_MAGIC_SIZEPACK; ENTER; SAVETMPS; PUSHSTACKi(PERLSI_MAGIC); if (magic_methcall(sv, mg, "FETCHSIZE", G_SCALAR, 2, NULL)) { sv = *PL_stack_sp--; - retval = (U32) SvIV(sv)-1; + retval = SvIV(sv)-1; + if (retval < -1) + Perl_croak(aTHX_ "FETCHSIZE returned a negative value"); } POPSTACK; FREETMPS; LEAVE; - return retval; + return (U32) retval; } int @@ -1620,6 +1779,8 @@ Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg) { dVAR; dSP; + PERL_ARGS_ASSERT_MAGIC_WIPEPACK; + ENTER; PUSHSTACKi(PERLSI_MAGIC); PUSHMARK(SP); @@ -1638,6 +1799,8 @@ Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key) dVAR; dSP; const char * const meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY"; + PERL_ARGS_ASSERT_MAGIC_NEXTPACK; + ENTER; SAVETMPS; PUSHSTACKi(PERLSI_MAGIC); @@ -1658,8 +1821,10 @@ Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key) } int -Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg) +Perl_magic_existspack(pTHX_ SV *sv, const MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_EXISTSPACK; + return magic_methpack(sv,mg,"EXISTS"); } @@ -1667,10 +1832,12 @@ SV * Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) { dVAR; dSP; - SV *retval = &PL_sv_undef; + SV *retval; SV * const tied = SvTIED_obj((SV*)hv, mg); HV * const pkg = SvSTASH((SV*)SvRV(tied)); + PERL_ARGS_ASSERT_MAGIC_SCALARPACK; + if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) { SV *key; if (HvEITER_get(hv)) @@ -1693,6 +1860,8 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) if (call_method("SCALAR", G_SCALAR)) retval = *PL_stack_sp--; + else + retval = &PL_sv_undef; POPSTACK; LEAVE; return retval; @@ -1706,6 +1875,9 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) const I32 i = SvTRUE(sv); SV ** const svp = av_fetch(GvAV(gv), atoi(MgPV_nolen_const(mg)), FALSE); + + PERL_ARGS_ASSERT_MAGIC_SETDBLINE; + if (svp && SvIOKp(*svp)) { OP * const o = INT2PTR(OP*,SvIVX(*svp)); if (o) { @@ -1724,6 +1896,9 @@ Perl_magic_getarylen(pTHX_ SV *sv, const MAGIC *mg) { dVAR; const AV * const obj = (AV*)mg->mg_obj; + + PERL_ARGS_ASSERT_MAGIC_GETARYLEN; + if (obj) { sv_setiv(sv, AvFILL(obj) + CopARYBASE_get(PL_curcop)); } else { @@ -1737,6 +1912,9 @@ Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg) { dVAR; AV * const obj = (AV*)mg->mg_obj; + + PERL_ARGS_ASSERT_MAGIC_SETARYLEN; + if (obj) { av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop)); } else { @@ -1751,7 +1929,10 @@ int Perl_magic_freearylen_p(pTHX_ SV *sv, MAGIC *mg) { dVAR; + + PERL_ARGS_ASSERT_MAGIC_FREEARYLEN_P; PERL_UNUSED_ARG(sv); + /* during global destruction, mg_obj may already have been freed */ if (PL_in_clean_all) return 0; @@ -1774,6 +1955,8 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) { dVAR; SV* const lsv = LvTARG(sv); + + PERL_ARGS_ASSERT_MAGIC_GETPOS; PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) { @@ -1798,8 +1981,9 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) SSize_t pos; STRLEN len; STRLEN ulen = 0; - MAGIC *found; + MAGIC* found; + PERL_ARGS_ASSERT_MAGIC_SETPOS; PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) @@ -1814,7 +1998,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) sv_force_normal_flags(lsv, 0); #endif found = sv_magicext(lsv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, - NULL, 0); + NULL, 0); } else if (!SvOK(sv)) { found->mg_len = -1; @@ -1851,29 +2035,6 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) } int -Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg) -{ - GV* gv; - PERL_UNUSED_ARG(mg); - - if (!SvOK(sv)) - return 0; - if (SvFLAGS(sv) & SVp_SCREAM - && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVGV)) { - /* We're actually already a typeglob, so don't need the stuff below. - */ - return 0; - } - gv = gv_fetchsv(sv, GV_ADD, SVt_PVGV); - if (sv == (SV*)gv) - return 0; - if (GvGP(sv)) - gp_free((GV*)sv); - GvGP(sv) = gp_ref(GvGP(gv)); - return 0; -} - -int Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; @@ -1881,6 +2042,8 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) const char * const tmps = SvPV_const(lsv,len); I32 offs = LvTARGOFF(sv); I32 rem = LvTARGLEN(sv); + + PERL_ARGS_ASSERT_MAGIC_GETSUBSTR; PERL_UNUSED_ARG(mg); if (SvUTF8(lsv)) @@ -1900,10 +2063,12 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { dVAR; STRLEN len; - const char *tmps = SvPV_const(sv, len); + const char * const tmps = SvPV_const(sv, len); SV * const lsv = LvTARG(sv); I32 lvoff = LvTARGOFF(sv); I32 lvlen = LvTARGLEN(sv); + + PERL_ARGS_ASSERT_MAGIC_SETSUBSTR; PERL_UNUSED_ARG(mg); if (DO_UTF8(sv)) { @@ -1914,11 +2079,12 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) SvUTF8_on(lsv); } else if (lsv && SvUTF8(lsv)) { + const char *utf8; sv_pos_u2b(lsv, &lvoff, &lvlen); LvTARGLEN(sv) = len; - tmps = (char*)bytes_to_utf8((U8*)tmps, &len); - sv_insert(lsv, lvoff, lvlen, tmps, len); - Safefree(tmps); + utf8 = (char*)bytes_to_utf8((U8*)tmps, &len); + sv_insert(lsv, lvoff, lvlen, utf8, len); + Safefree(utf8); } else { sv_insert(lsv, lvoff, lvlen, tmps, len); @@ -1933,7 +2099,10 @@ int Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg) { dVAR; + + PERL_ARGS_ASSERT_MAGIC_GETTAINT; PERL_UNUSED_ARG(sv); + TAINT_IF((PL_localizing != 1) && (mg->mg_len & 1)); return 0; } @@ -1942,14 +2111,15 @@ int Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) { dVAR; + + PERL_ARGS_ASSERT_MAGIC_SETTAINT; 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; } @@ -1957,6 +2127,8 @@ int Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) { SV * const lsv = LvTARG(sv); + + PERL_ARGS_ASSERT_MAGIC_GETVEC; PERL_UNUSED_ARG(mg); if (lsv) @@ -1970,6 +2142,7 @@ Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETVEC; PERL_UNUSED_ARG(mg); do_vecset(sv); /* XXX slurp this routine */ return 0; @@ -1980,6 +2153,9 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) { dVAR; SV *targ = NULL; + + PERL_ARGS_ASSERT_MAGIC_GETDEFELEM; + if (LvTARGLEN(sv)) { if (mg->mg_obj) { SV * const ahv = LvTARG(sv); @@ -1992,7 +2168,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) if ((I32)LvTARGOFF(sv) <= AvFILL(av)) targ = AvARRAY(av)[LvTARGOFF(sv)]; } - if (targ && targ != &PL_sv_undef) { + if (targ && (targ != &PL_sv_undef)) { /* somebody else defined it for us */ SvREFCNT_dec(LvTARG(sv)); LvTARG(sv) = SvREFCNT_inc_simple_NN(targ); @@ -2011,6 +2187,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETDEFELEM; PERL_UNUSED_ARG(mg); if (LvTARGLEN(sv)) vivify_defelem(sv); @@ -2028,6 +2205,8 @@ Perl_vivify_defelem(pTHX_ SV *sv) MAGIC *mg; SV *value = NULL; + PERL_ARGS_ASSERT_VIVIFY_DEFELEM; + if (!LvTARGLEN(sv) || !(mg = mg_find(sv, PERL_MAGIC_defelem))) return; if (mg->mg_obj) { @@ -2036,7 +2215,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, mg->mg_obj); + Perl_croak(aTHX_ PL_no_helem_sv, SVfARG(mg->mg_obj)); } else { AV* const av = (AV*)LvTARG(sv); @@ -2060,12 +2239,14 @@ Perl_vivify_defelem(pTHX_ SV *sv) int Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_KILLBACKREFS; return Perl_sv_kill_backrefs(aTHX_ sv, (AV*)mg->mg_obj); } int Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETMGLOB; PERL_UNUSED_CONTEXT; mg->mg_len = -1; SvSCREAM_off(sv); @@ -2073,28 +2254,12 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) } int -Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg) -{ - PERL_UNUSED_ARG(mg); - sv_unmagic(sv, PERL_MAGIC_bm); - SvVALID_off(sv); - return 0; -} - -int -Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg) -{ - PERL_UNUSED_ARG(mg); - sv_unmagic(sv, PERL_MAGIC_fm); - SvCOMPILED_off(sv); - return 0; -} - -int Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg) { const struct ufuncs * const uf = (struct ufuncs *)mg->mg_ptr; + PERL_ARGS_ASSERT_MAGIC_SETUVAR; + if (uf && uf->uf_set) (*uf->uf_set)(aTHX_ uf->uf_index, sv); return 0; @@ -2103,26 +2268,27 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg) { - PERL_UNUSED_ARG(mg); - sv_unmagic(sv, PERL_MAGIC_qr); - return 0; -} + const char type = mg->mg_type; -int -Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg) -{ - dVAR; - regexp * const re = (regexp *)mg->mg_obj; - PERL_UNUSED_ARG(sv); + PERL_ARGS_ASSERT_MAGIC_SETREGEXP; - ReREFCNT_dec(re); - return 0; + if (type == PERL_MAGIC_qr) { + } else if (type == PERL_MAGIC_bm) { + SvTAIL_off(sv); + SvVALID_off(sv); + } else { + assert(type == PERL_MAGIC_fm); + SvCOMPILED_off(sv); + } + return sv_unmagic(sv, type); } #ifdef USE_LOCALE_COLLATE int Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETCOLLXFRM; + /* * RenE Descartes said "I think not." * and vanished with a faint plop. @@ -2142,6 +2308,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) { + PERL_ARGS_ASSERT_MAGIC_SETUTF8; PERL_UNUSED_CONTEXT; PERL_UNUSED_ARG(sv); Safefree(mg->mg_ptr); /* The mg_ptr holds the pos cache. */ @@ -2155,9 +2322,45 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) { dVAR; register const char *s; + register I32 paren; + register const REGEXP * rx; + const char * const remaining = mg->mg_ptr + 1; I32 i; STRLEN len; + + PERL_ARGS_ASSERT_MAGIC_SET; + switch (*mg->mg_ptr) { + case '\015': /* $^MATCH */ + if (strEQ(remaining, "ATCH")) + goto do_match; + case '`': /* ${^PREMATCH} caught below */ + do_prematch: + paren = RX_BUFF_IDX_PREMATCH; + goto setparen; + case '\'': /* ${^POSTMATCH} caught below */ + do_postmatch: + paren = RX_BUFF_IDX_POSTMATCH; + goto setparen; + case '&': + do_match: + paren = RX_BUFF_IDX_FULLMATCH; + goto setparen; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + paren = atoi(mg->mg_ptr); + setparen: + if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { + CALLREG_NUMBUF_STORE((REGEXP * const)rx,paren,sv); + break; + } else { + /* Croak with a READONLY error when a numbered match var is + * set without a previous pattern match. Unless it's C + */ + if (!PL_localizing) { + Perl_croak(aTHX_ PL_no_modify); + } + } case '\001': /* ^A */ sv_setsv(PL_bodytarget, sv); break; @@ -2226,17 +2429,48 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } } else if (strEQ(mg->mg_ptr, "\017PEN")) { - if (!PL_compiling.cop_io) - PL_compiling.cop_io = newSVsv(sv); - else - sv_setsv(PL_compiling.cop_io,sv); + 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 = out ? newSVpvn_flags(out + 1, start + len - out - 1, + SVs_TEMP | SvUTF8(sv)) + : newSVpvn_flags("", 0, SVs_TEMP | SvUTF8(sv)); + + tmp_he + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + newSVpvs_flags("open>", SVs_TEMP), + 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_ tmp_he, + newSVpvs_flags("open<", SVs_TEMP), + tmp); } break; case '\020': /* ^P */ - PL_perldb = SvIV(sv); - if (PL_perldb && !PL_DBsingle) - init_debugger(); - break; + if (*remaining == '\0') { /* ^P */ + PL_perldb = SvIV(sv); + if (PL_perldb && !PL_DBsingle) + init_debugger(); + break; + } else if (strEQ(remaining, "REMATCH")) { /* $^PREMATCH */ + goto do_prematch; + } else if (strEQ(remaining, "OSTMATCH")) { /* $^POSTMATCH */ + goto do_postmatch; + } case '\024': /* ^T */ #ifdef BIG_TIME PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv)); @@ -2273,11 +2507,16 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) accumulate |= ptr[i] ; any_fatals |= (ptr[i] & 0xAA) ; } - if (!accumulate) - PL_compiling.cop_warnings = pWARN_NONE; + if (!accumulate) { + if (!specialWARN(PL_compiling.cop_warnings)) + PerlMemShared_free(PL_compiling.cop_warnings); + PL_compiling.cop_warnings = pWARN_NONE; + } /* Yuck. I can't see how to abstract this: */ else if (isWARN_on(((STRLEN *)SvPV_nolen_const(sv)) - 1, WARN_ALL) && !any_fatals) { + if (!specialWARN(PL_compiling.cop_warnings)) + PerlMemShared_free(PL_compiling.cop_warnings); PL_compiling.cop_warnings = pWARN_ALL; PL_dowarn |= G_WARN_ONCE ; } @@ -2506,8 +2745,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } if (i) (void)setgroups(i, gary); - if (gary) - Safefree(gary); + Safefree(gary); } #else /* HAS_SETGROUPS */ PL_egid = SvIV(sv); @@ -2566,15 +2804,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) setproctitle("%s", s); # endif } -#endif -#if defined(__hpux) && defined(PSTAT_SETCMD) +#elif defined(__hpux) && defined(PSTAT_SETCMD) if (PL_origalen != 1) { union pstun un; s = SvPV_const(sv, len); un.pst_command = (char *)s; pstat(PSTAT_SETCMD, un, len, 0, 0); } -#endif +#else if (PL_origalen > 1) { /* PL_origalen is set in perl_parse(). */ s = SvPV_force(sv,len); @@ -2585,20 +2822,26 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } else { /* Shorter than original, will be padded. */ +#ifdef PERL_DARWIN + /* Special case for Mac OS X: see [perl #38868] */ + const int pad = 0; +#else + /* Is the space counterintuitive? Yes. + * (You were expecting \0?) + * Does it work? Seems to. (In Linux 2.4.20 at least.) + * --jhi */ + const int pad = ' '; +#endif Copy(s, PL_origargv[0], len, char); PL_origargv[0][len] = 0; memset(PL_origargv[0] + len + 1, - /* Is the space counterintuitive? Yes. - * (You were expecting \0?) - * Does it work? Seems to. (In Linux 2.4.20 at least.) - * --jhi */ - (int)' ', - PL_origalen - len - 1); + pad, PL_origalen - len - 1); } PL_origargv[0][PL_origalen-1] = 0; for (i = 1; i < PL_origargc; i++) PL_origargv[i] = 0; } +#endif UNLOCK_DOLLARZERO_MUTEX; break; #endif @@ -2610,6 +2853,8 @@ I32 Perl_whichsig(pTHX_ const char *sig) { register char* const* sigv; + + PERL_ARGS_ASSERT_WHICHSIG; PERL_UNUSED_CONTEXT; for (sigv = (char* const*)PL_sig_name; *sigv; sigv++) @@ -2628,7 +2873,7 @@ Perl_whichsig(pTHX_ const char *sig) Signal_t #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) -Perl_sighandler(int sig, ...) +Perl_sighandler(int sig, siginfo_t *sip, void *uap PERL_UNUSED_DECL) #else Perl_sighandler(int sig) #endif @@ -2706,32 +2951,26 @@ Perl_sighandler(int sig) struct sigaction oact; if (sigaction(sig, 0, &oact) == 0 && oact.sa_flags & SA_SIGINFO) { - siginfo_t *sip; - va_list args; - - va_start(args, sig); - sip = (siginfo_t*)va_arg(args, siginfo_t*); if (sip) { HV *sih = newHV(); SV *rv = newRV_noinc((SV*)sih); /* The siginfo fields signo, code, errno, pid, uid, * addr, status, and band are defined by POSIX/SUSv3. */ - hv_store(sih, "signo", 5, newSViv(sip->si_signo), 0); - hv_store(sih, "code", 4, newSViv(sip->si_code), 0); + (void)hv_stores(sih, "signo", newSViv(sip->si_signo)); + (void)hv_stores(sih, "code", newSViv(sip->si_code)); #if 0 /* XXX TODO: Configure scan for the existence of these, but even that does not help if the SA_SIGINFO is not implemented according to the spec. */ - hv_store(sih, "errno", 5, newSViv(sip->si_errno), 0); - hv_store(sih, "status", 6, newSViv(sip->si_status), 0); - hv_store(sih, "uid", 3, newSViv(sip->si_uid), 0); - hv_store(sih, "pid", 3, newSViv(sip->si_pid), 0); - hv_store(sih, "addr", 4, newSVuv(PTR2UV(sip->si_addr)), 0); - hv_store(sih, "band", 4, newSViv(sip->si_band), 0); + hv_stores(sih, "errno", newSViv(sip->si_errno)); + hv_stores(sih, "status", newSViv(sip->si_status)); + hv_stores(sih, "uid", newSViv(sip->si_uid)); + hv_stores(sih, "pid", newSViv(sip->si_pid)); + hv_stores(sih, "addr", newSVuv(PTR2UV(sip->si_addr))); + hv_stores(sih, "band", newSViv(sip->si_band)); #endif EXTEND(SP, 2); PUSHs((SV*)rv); - PUSHs(newSVpv((void*)sip, sizeof(*sip))); + mPUSHp((char *)sip, sizeof(*sip)); } - va_end(args); } } #endif @@ -2803,10 +3042,10 @@ S_restore_magic(pTHX_ const void *p) /* downgrade public flags to private, and discard any other private flags */ - U32 public = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK); - if (public) { - SvFLAGS(sv) &= ~( public | SVp_IOK|SVp_NOK|SVp_POK ); - SvFLAGS(sv) |= ( public << PRIVSHIFT ); + const U32 pubflags = SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK); + if (pubflags) { + SvFLAGS(sv) &= ~( pubflags | (SVp_IOK|SVp_NOK|SVp_POK) ); + SvFLAGS(sv) |= ( pubflags << PRIVSHIFT ); } } } @@ -2839,6 +3078,8 @@ S_unwind_handler_stack(pTHX_ const void *p) dVAR; const U32 flags = *(const U32*)p; + PERL_ARGS_ASSERT_UNWIND_HANDLER_STACK; + if (flags & 1) PL_savestack_ix -= 5; /* Unprotect save in progress. */ #if !defined(PERL_IMPLICIT_CONTEXT) @@ -2851,8 +3092,9 @@ S_unwind_handler_stack(pTHX_ const void *p) =for apidoc magic_sethint Triggered by a store to %^H, records the key/value pair to -C. It is assumed that hints aren't storing anything -that would need a deep copy. Maybe we should warn if we find a reference. +C. It is assumed that hints aren't storing +anything that would need a deep copy. Maybe we should warn if we find a +reference. =cut */ @@ -2860,7 +3102,10 @@ int Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg) { dVAR; - assert(mg->mg_len == HEf_SVKEY); + SV *key = (mg->mg_len == HEf_SVKEY) ? (SV *)mg->mg_ptr + : newSVpvn_flags(mg->mg_ptr, mg->mg_len, SVs_TEMP); + + PERL_ARGS_ASSERT_MAGIC_SETHINT; /* mg->mg_obj isn't being used. If needed, it would be possible to store an alternative leaf in there, with PL_compiling.cop_hints being used if @@ -2871,16 +3116,16 @@ Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg) Doing this here saves a lot of doing it manually in perl code (and forgetting to do it, and consequent subtle errors. */ PL_hints |= HINT_LOCALIZE_HH; - PL_compiling.cop_hints - = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints, - (SV *)mg->mg_ptr, newSVsv(sv)); + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, key, sv); return 0; } /* -=for apidoc magic_sethint +=for apidoc magic_clearhint -Triggered by a delete from %^H, records the key to C. +Triggered by a delete from %^H, records the key to +C. =cut */ @@ -2888,13 +3133,17 @@ int Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg) { dVAR; + + PERL_ARGS_ASSERT_MAGIC_CLEARHINT; + PERL_UNUSED_ARG(sv); + assert(mg->mg_len == HEf_SVKEY); PERL_UNUSED_ARG(sv); PL_hints |= HINT_LOCALIZE_HH; - PL_compiling.cop_hints - = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints, + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, (SV *)mg->mg_ptr, &PL_sv_placeholder); return 0; }