X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=5754732d2f00e86d2421de1ad234e153c812f974;hb=360321b398f5e797c408b6d6c60b7da3cca5e324;hp=5a224e294204103e8347ea38d353067b2acc1d5d;hpb=f8c7b90fa8a3676239aeea262e148f9a4e497558;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index 5a224e2..5754732 100644 --- a/mg.c +++ b/mg.c @@ -52,10 +52,11 @@ tie. # include #endif +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) +Signal_t Perl_csighandler(int sig, ...); +#else Signal_t Perl_csighandler(int sig); - -static void restore_magic(pTHX_ const void *p); -static void unwind_handler_stack(pTHX_ const void *p); +#endif #ifdef __Lynx__ /* Missing protos on LynxOS */ @@ -87,7 +88,7 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) sv_force_normal(sv); #endif - SAVEDESTRUCTOR_X(restore_magic, INT2PTR(void*, (IV)mgs_ix)); + SAVEDESTRUCTOR_X(S_restore_magic, INT2PTR(void*, (IV)mgs_ix)); mgs = SSPTR(mgs_ix, MGS*); mgs->mgs_sv = sv; @@ -194,7 +195,7 @@ Perl_mg_get(pTHX_ SV *sv) } } - restore_magic(aTHX_ INT2PTR(void *, (IV)mgs_ix)); + restore_magic(INT2PTR(void *, (IV)mgs_ix)); if (SvREFCNT(sv) == 1) { /* We hold the last reference to this SV, which implies that the @@ -232,7 +233,7 @@ Perl_mg_set(pTHX_ SV *sv) CALL_FPTR(vtbl->svt_set)(aTHX_ sv, mg); } - restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix)); + restore_magic(INT2PTR(void*, (IV)mgs_ix)); return 0; } @@ -257,7 +258,7 @@ Perl_mg_length(pTHX_ SV *sv) save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg); - restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix)); + restore_magic(INT2PTR(void*, (IV)mgs_ix)); return len; } } @@ -284,7 +285,7 @@ Perl_mg_size(pTHX_ SV *sv) save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg); - restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix)); + restore_magic(INT2PTR(void*, (IV)mgs_ix)); return len; } } @@ -325,7 +326,7 @@ Perl_mg_clear(pTHX_ SV *sv) CALL_FPTR(vtbl->svt_clear)(aTHX_ sv, mg); } - restore_magic(aTHX_ INT2PTR(void*, (IV)mgs_ix)); + restore_magic(INT2PTR(void*, (IV)mgs_ix)); return 0; } @@ -368,19 +369,86 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen) if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){ count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen); } - else if (isUPPER(mg->mg_type)) { - sv_magic(nsv, - mg->mg_type == PERL_MAGIC_tied ? SvTIED_obj(sv, mg) : - (mg->mg_type == PERL_MAGIC_regdata && mg->mg_obj) - ? sv : mg->mg_obj, - toLOWER(mg->mg_type), key, klen); - count++; + else { + const char type = mg->mg_type; + if (isUPPER(type)) { + sv_magic(nsv, + (type == PERL_MAGIC_tied) + ? SvTIED_obj(sv, mg) + : (type == PERL_MAGIC_regdata && mg->mg_obj) + ? sv + : mg->mg_obj, + toLOWER(type), key, klen); + count++; + } } } return count; } /* +=for apidoc mg_localize + +Copy some of the magic from an existing SV to new localized version of +that SV. Container magic (eg %ENV, $1, tie) gets copied, value magic +doesn't (eg taint, pos). + +=cut +*/ + +void +Perl_mg_localize(pTHX_ SV *sv, SV *nsv) +{ + MAGIC *mg; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { + const 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: + continue; + } + + if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy) { + /* XXX calling the copy method is probably not correct. DAPM */ + (void)CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, + mg->mg_ptr, mg->mg_len); + } + else { + sv_magicext(nsv, mg->mg_obj, mg->mg_type, vtbl, + mg->mg_ptr, mg->mg_len); + } + /* container types should remain read-only across localization */ + SvFLAGS(nsv) |= SvREADONLY(sv); + } + + if (SvTYPE(nsv) >= SVt_PVMG && SvMAGIC(nsv)) { + SvFLAGS(nsv) |= SvMAGICAL(sv); + PL_localizing = 1; + SvSETMAGIC(nsv); + PL_localizing = 0; + } +} + +/* =for apidoc mg_free Free any magic storage used by the SV. See C. @@ -418,7 +486,7 @@ U32 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) { register const REGEXP *rx; - (void)sv; + PERL_UNUSED_ARG(sv); if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { if (mg->mg_obj) /* @+ */ @@ -452,7 +520,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) i = s; if (i > 0 && RX_MATCH_UTF8(rx)) { - char *b = rx->subbeg; + const char * const b = rx->subbeg; if (b) i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i)); } @@ -466,7 +534,7 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; (void)mg; + PERL_UNUSED_ARG(sv); PERL_UNUSED_ARG(mg); Perl_croak(aTHX_ PL_no_modify); NORETURN_FUNCTION_END; } @@ -493,7 +561,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) i = t1 - s1; getlen: if (i > 0 && RX_MATCH_UTF8(rx)) { - char *s = rx->subbeg + s1; + const char * const s = rx->subbeg + s1; const U8 *ep; STRLEN el; @@ -556,14 +624,20 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) } magic_get(sv,mg); if (!SvPOK(sv) && SvNIOK(sv)) { - STRLEN n_a; - sv_2pv(sv, &n_a); + sv_2pv(sv, 0); } if (SvPOK(sv)) return SvCUR(sv); return 0; } +#define SvRTRIM(sv) STMT_START { \ + STRLEN len = SvCUR(sv); \ + while (len > 0 && isSPACE(SvPVX(sv)[len-1])) \ + --len; \ + SvCUR_set(sv, len); \ +} STMT_END + int Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { @@ -572,16 +646,18 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) register char *s = NULL; register I32 i; register REGEXP *rx; + const char * const remaining = mg->mg_ptr + 1; + const char nextchar = *remaining; switch (*mg->mg_ptr) { case '\001': /* ^A */ sv_setsv(sv, PL_bodytarget); break; case '\003': /* ^C, ^CHILD_ERROR_NATIVE */ - if (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { sv_setiv(sv, (IV)PL_minus_c); } - else if (strEQ(mg->mg_ptr, "\003HILD_ERROR_NATIVE")) { + else if (strEQ(remaining, "HILD_ERROR_NATIVE")) { sv_setiv(sv, (IV)STATUS_NATIVE); } break; @@ -590,7 +666,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK)); break; case '\005': /* ^E */ - if (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { #ifdef MACOS_TRADITIONAL { char msg[256]; @@ -618,7 +694,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setpv(sv, errno ? Strerror(errno) : ""); } else { if (errno != errno_isOS2) { - int tmp = _syserrno(); + const int tmp = _syserrno(); if (tmp) /* 2nd call to _syserrno() makes it 0 */ Perl_rc = tmp; } @@ -630,8 +706,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { DWORD dwErr = GetLastError(); sv_setnv(sv, (NV)dwErr); - if (dwErr) - { + if (dwErr) { PerlProc_GetOSError(sv, dwErr); } else @@ -640,7 +715,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } #else { - int saveerrno = errno; + const int saveerrno = errno; sv_setnv(sv, (NV)errno); sv_setpv(sv, errno ? Strerror(errno) : ""); errno = saveerrno; @@ -649,9 +724,10 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) #endif #endif #endif + SvRTRIM(sv); SvNOK_on(sv); /* what a wonderful hack! */ } - else if (strEQ(mg->mg_ptr+1, "NCODING")) + else if (strEQ(remaining, "NCODING")) sv_setsv(sv, PL_encoding); break; case '\006': /* ^F */ @@ -667,11 +743,11 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setsv(sv, &PL_sv_undef); break; case '\017': /* ^O & ^OPEN */ - if (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { sv_setpv(sv, PL_osname); SvTAINTED_off(sv); } - else if (strEQ(mg->mg_ptr, "\017PEN")) { + else if (strEQ(remaining, "PEN")) { if (!PL_compiling.cop_io) sv_setsv(sv, &PL_sv_undef); else { @@ -683,7 +759,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setiv(sv, (IV)PL_perldb); break; case '\023': /* ^S */ - if (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { if (PL_lex_state != LEX_NOTPARSING) SvOK_off(sv); else if (PL_in_eval) @@ -693,38 +769,43 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '\024': /* ^T */ - if (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { #ifdef BIG_TIME sv_setnv(sv, PL_basetime); #else sv_setiv(sv, (IV)PL_basetime); #endif } - else if (strEQ(mg->mg_ptr, "\024AINT")) + else if (strEQ(remaining, "AINT")) sv_setiv(sv, PL_tainting ? (PL_taint_warn || PL_unsafe ? -1 : 1) : 0); break; case '\025': /* $^UNICODE, $^UTF8LOCALE */ - if (strEQ(mg->mg_ptr, "\025NICODE")) + if (strEQ(remaining, "NICODE")) sv_setuv(sv, (UV) PL_unicode); - else if (strEQ(mg->mg_ptr, "\025TF8LOCALE")) + else if (strEQ(remaining, "TF8LOCALE")) sv_setuv(sv, (UV) PL_utf8locale); break; case '\027': /* ^W & $^WARNING_BITS */ - if (*(mg->mg_ptr+1) == '\0') + if (nextchar == '\0') sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) ? TRUE : FALSE)); - else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) { - if (PL_compiling.cop_warnings == pWARN_NONE || - PL_compiling.cop_warnings == pWARN_STD) - { + else if (strEQ(remaining, "ARNING_BITS")) { + if (PL_compiling.cop_warnings == pWARN_NONE) { sv_setpvn(sv, WARN_NONEstring, WARNsize) ; - } + } + else if (PL_compiling.cop_warnings == pWARN_STD) { + sv_setpvn( + sv, + (PL_dowarn & G_WARN_ON) ? WARN_ALLstring : WARN_NONEstring, + WARNsize + ); + } 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 *bits=get_hv("warnings::Bits", FALSE); + HV * const bits=get_hv("warnings::Bits", FALSE); if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) { sv_setsv(sv, *bits_all); } @@ -767,7 +848,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SvUTF8_off(sv); if (PL_tainting) { if (RX_MATCH_TAINTED(rx)) { - MAGIC* mg = SvMAGIC(sv); + MAGIC* const mg = SvMAGIC(sv); MAGIC* mgt; PL_tainted = 1; SvMAGIC_set(sv, mg->mg_moremagic); @@ -880,16 +961,13 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) if (PL_ors_sv) sv_copypv(sv, PL_ors_sv); break; - case '#': - sv_setpv(sv,PL_ofmt); - break; case '!': #ifdef VMS sv_setnv(sv, (NV)((errno == EVMSERR) ? vaxc$errno : errno)); sv_setpv(sv, errno ? Strerror(errno) : ""); #else { - int saveerrno = errno; + const int saveerrno = errno; sv_setnv(sv, (NV)errno); #ifdef OS2 if (errno == errno_isOS2 || errno == errno_isOS2_set) @@ -900,6 +978,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) errno = saveerrno; } #endif + SvRTRIM(sv); SvNOK_on(sv); /* what a wonderful hack! */ break; case '<': @@ -941,7 +1020,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg) { - struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr; + struct ufuncs * const uf = (struct ufuncs *)mg->mg_ptr; if (uf && uf->uf_val) (*uf->uf_val)(aTHX_ uf->uf_index, sv); @@ -952,11 +1031,11 @@ int Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) { dVAR; - register char *s; + const char *s; const char *ptr; STRLEN len, klen; - s = SvPV(sv,len); + s = SvPV_const(sv,len); ptr = MgPV_const(mg,klen); my_setenv(ptr, s); @@ -966,7 +1045,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) if (!len) { SV **valp; if ((valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE))) - s = SvPV(*valp, len); + s = SvPV_const(*valp, len); } #endif @@ -977,10 +1056,13 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) MgTAINTEDDIR_off(mg); #ifdef VMS if (s && klen == 8 && strEQ(ptr, "DCL$PATH")) { - char pathbuf[256], eltbuf[256], *cp, *elt = s; + char pathbuf[256], eltbuf[256], *cp, *elt; Stat_t sbuf; int i = 0, j = 0; + strncpy(eltbuf, s, 255); + eltbuf[255] = 0; + elt = eltbuf; do { /* DCL$PATH may be a search list */ while (1) { /* as may dev portion of any element */ if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) { @@ -1002,7 +1084,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) } #endif /* VMS */ if (s && klen == 4 && strEQ(ptr,"PATH")) { - char *strend = s + len; + const char * const strend = s + len; while (s < strend) { char tmpbuf[256]; @@ -1028,27 +1110,25 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg) { - STRLEN n_a; - (void)sv; - my_setenv(MgPV(mg,n_a),Nullch); + PERL_UNUSED_ARG(sv); + my_setenv(MgPV_nolen_const(mg),Nullch); return 0; } int Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) { -#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) +#if defined(VMS) || defined(EPOC) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else if (PL_localizing) { HE* entry; - STRLEN n_a; magic_clear_all_env(sv,mg); hv_iterinit((HV*)sv); while ((entry = hv_iternext((HV*)sv))) { I32 keylen; my_setenv(hv_iterkey(entry, &keylen), - SvPV(hv_iterval((HV*)sv, entry), n_a)); + SvPV_nolen_const(hv_iterval((HV*)sv, entry))); } } #endif @@ -1060,7 +1140,7 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) { dVAR; #ifndef PERL_MICRO -#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) +#if defined(VMS) || defined(EPOC) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else # if defined(PERL_IMPLICIT_SYS) || defined(WIN32) @@ -1090,8 +1170,8 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) # endif /* PERL_IMPLICIT_SYS || WIN32 */ #endif /* VMS || EPOC */ #endif /* !PERL_MICRO */ - (void)sv; - (void)mg; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); return 0; } @@ -1100,17 +1180,15 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) static void restore_sigmask(pTHX_ SV *save_sv) { - sigset_t *ossetp = (sigset_t *) SvPV_nolen( save_sv ); + const sigset_t *ossetp = (const sigset_t *) SvPV_nolen_const( save_sv ); (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0); } #endif int Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) { - I32 i; - STRLEN n_a; /* Are we fetching a signal entry? */ - i = whichsig(MgPV(mg,n_a)); + const I32 i = whichsig(MgPV_nolen_const(mg)); if (i > 0) { if(PL_psig_ptr[i]) sv_setsv(sv,PL_psig_ptr[i]); @@ -1124,7 +1202,7 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) if (PL_sig_handlers_initted && PL_sig_defaulting[i]) sigstate = SIG_DFL; #endif /* cache state so we don't fetch it again */ - if(sigstate == SIG_IGN) + if(sigstate == (Sighandler_t) SIG_IGN) sv_setpv(sv,"IGNORE"); else sv_setsv(sv,&PL_sv_undef); @@ -1141,9 +1219,8 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) * refactoring might be in order. */ dVAR; - STRLEN n_a; - register const char *s = MgPV(mg,n_a); - (void)sv; + register const char * const s = MgPV_nolen_const(mg); + PERL_UNUSED_ARG(sv); if (*s == '_') { SV** svp = 0; if (strEQ(s,"__DIE__")) @@ -1153,15 +1230,14 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) else Perl_croak(aTHX_ "No such hook: %s", s); if (svp && *svp) { - SV *to_dec = *svp; + SV * const to_dec = *svp; *svp = 0; SvREFCNT_dec(to_dec); } } else { - I32 i; /* Are we clearing a signal entry? */ - i = whichsig(s); + const I32 i = whichsig(s); if (i > 0) { #ifdef HAS_SIGPROCMASK sigset_t set, save; @@ -1183,7 +1259,7 @@ Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) PL_sig_defaulting[i] = 1; (void)rsignal(i, PL_csighandlerp); #else - (void)rsignal(i, SIG_DFL); + (void)rsignal(i, (Sighandler_t) SIG_DFL); #endif if(PL_psig_name[i]) { SvREFCNT_dec(PL_psig_name[i]); @@ -1212,7 +1288,11 @@ S_raise_signal(pTHX_ int sig) } Signal_t +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) +Perl_csighandler(int sig, ...) +#else Perl_csighandler(int sig) +#endif { #ifdef PERL_GET_SIG_CONTEXT dTHXa(PERL_GET_SIG_CONTEXT); @@ -1293,7 +1373,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) SV* save_sv; #endif - register const char *s = MgPV(mg,len); + register const char *s = MgPV_const(mg,len); if (*s == '_') { if (strEQ(s,"__DIE__")) svp = &PL_diehook; @@ -1361,7 +1441,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) PL_sig_ignoring[i] = 1; (void)rsignal(i, PL_csighandlerp); #else - (void)rsignal(i, SIG_IGN); + (void)rsignal(i, (Sighandler_t) SIG_IGN); #endif } } @@ -1373,7 +1453,7 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) (void)rsignal(i, PL_csighandlerp); } #else - (void)rsignal(i, SIG_DFL); + (void)rsignal(i, (Sighandler_t) SIG_DFL); #endif } else { @@ -1402,8 +1482,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; - (void)mg; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); PL_sub_generation++; return 0; } @@ -1411,8 +1491,8 @@ Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; - (void)mg; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); /* HV_badAMAGIC_on(Sv_STASH(sv)); */ PL_amagic_generation++; @@ -1424,7 +1504,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) { HV * const hv = (HV*)LvTARG(sv); I32 i = 0; - (void)mg; + PERL_UNUSED_ARG(mg); if (hv) { (void) hv_iterinit(hv); @@ -1443,7 +1523,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); if (LvTARG(sv)) { hv_ksplit((HV*)LvTARG(sv), SvIV(sv)); } @@ -1597,8 +1677,8 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) { dVAR; dSP; SV *retval = &PL_sv_undef; - SV *tied = SvTIED_obj((SV*)hv, mg); - HV *pkg = SvSTASH((SV*)SvRV(tied)); + SV * const tied = SvTIED_obj((SV*)hv, mg); + HV * const pkg = SvSTASH((SV*)SvRV(tied)); if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) { SV *key; @@ -1630,44 +1710,74 @@ Perl_magic_scalarpack(pTHX_ HV *hv, MAGIC *mg) int Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) { - OP *o; - I32 i; - GV* gv; - SV** svp; - STRLEN n_a; - - gv = PL_DBline; - i = SvTRUE(sv); - svp = av_fetch(GvAV(gv), - atoi(MgPV(mg,n_a)), FALSE); - if (svp && SvIOKp(*svp) && (o = INT2PTR(OP*,SvIVX(*svp)))) { - /* set or clear breakpoint in the relevant control op */ - if (i) - o->op_flags |= OPf_SPECIAL; - else - o->op_flags &= ~OPf_SPECIAL; + GV * const gv = PL_DBline; + const I32 i = SvTRUE(sv); + SV ** const svp = av_fetch(GvAV(gv), + atoi(MgPV_nolen_const(mg)), FALSE); + if (svp && SvIOKp(*svp)) { + OP * const o = INT2PTR(OP*,SvIVX(*svp)); + if (o) { + /* set or clear breakpoint in the relevant control op */ + if (i) + o->op_flags |= OPf_SPECIAL; + else + o->op_flags &= ~OPf_SPECIAL; + } } return 0; } int -Perl_magic_getarylen(pTHX_ SV *sv, MAGIC *mg) +Perl_magic_getarylen(pTHX_ SV *sv, const MAGIC *mg) { - sv_setiv(sv, AvFILL((AV*)mg->mg_obj) + PL_curcop->cop_arybase); + const AV * const obj = (AV*)mg->mg_obj; + if (obj) { + sv_setiv(sv, AvFILL(obj) + PL_curcop->cop_arybase); + } else { + SvOK_off(sv); + } return 0; } int Perl_magic_setarylen(pTHX_ SV *sv, MAGIC *mg) { - av_fill((AV*)mg->mg_obj, SvIV(sv) - PL_curcop->cop_arybase); + AV * const obj = (AV*)mg->mg_obj; + if (obj) { + av_fill(obj, SvIV(sv) - PL_curcop->cop_arybase); + } else { + if (ckWARN(WARN_MISC)) + Perl_warner(aTHX_ packWARN(WARN_MISC), + "Attempt to set length of freed array"); + } + return 0; +} + +int +Perl_magic_freearylen_p(pTHX_ SV *sv, MAGIC *mg) +{ + PERL_UNUSED_ARG(sv); + /* during global destruction, mg_obj may already have been freed */ + if (PL_in_clean_all) + return 0; + + mg = mg_find (mg->mg_obj, PERL_MAGIC_arylen); + + if (mg) { + /* arylen scalar holds a pointer back to the array, but doesn't own a + reference. Hence the we (the array) are about to go away with it + still pointing at us. Clear its pointer, else it would be pointing + at free memory. See the comment in sv_magic about reference loops, + and why it can't own a reference to us. */ + mg->mg_obj = 0; + } return 0; } int Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) { - SV* lsv = LvTARG(sv); + SV* const lsv = LvTARG(sv); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) { mg = mg_find(lsv, PERL_MAGIC_regex_global); @@ -1686,7 +1796,7 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) { - SV* lsv = LvTARG(sv); + SV* const lsv = LvTARG(sv); SSize_t pos; STRLEN len; STRLEN ulen = 0; @@ -1738,7 +1848,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); if (SvFAKE(sv)) { /* FAKE globs can get coerced */ SvFAKE_off(sv); gv_efullname3(sv,((GV*)sv), "*"); @@ -1753,8 +1863,8 @@ int Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg) { GV* gv; - (void)mg; - + PERL_UNUSED_ARG(mg); + if (!SvOK(sv)) return 0; gv = gv_fetchsv(sv,TRUE, SVt_PVGV); @@ -1771,10 +1881,10 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; SV * const lsv = LvTARG(sv); - const char * const tmps = SvPV(lsv,len); + const char * const tmps = SvPV_const(lsv,len); I32 offs = LvTARGOFF(sv); I32 rem = LvTARGLEN(sv); - (void)mg; + PERL_UNUSED_ARG(mg); if (SvUTF8(lsv)) sv_pos_u2b(lsv, &offs, &rem); @@ -1792,11 +1902,11 @@ int Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; - char *tmps = SvPV(sv, len); + const char *tmps = SvPV_const(sv, len); SV * const lsv = LvTARG(sv); I32 lvoff = LvTARGOFF(sv); I32 lvlen = LvTARGLEN(sv); - (void)mg; + PERL_UNUSED_ARG(mg); if (DO_UTF8(sv)) { sv_utf8_upgrade(lsv); @@ -1824,25 +1934,22 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg) { - TAINT_IF((mg->mg_len & 1) || - ((mg->mg_len & 2) && mg->mg_obj == sv)); /* kludge */ + PERL_UNUSED_ARG(sv); + TAINT_IF((PL_localizing != 1) && (mg->mg_len & 1)); return 0; } int Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; - if (PL_localizing) { - if (PL_localizing == 1) - mg->mg_len <<= 1; + 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; + mg->mg_len &= ~1; } - else if (PL_tainted) - mg->mg_len |= 1; - else - mg->mg_len &= ~1; return 0; } @@ -1850,7 +1957,7 @@ int Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) { SV * const lsv = LvTARG(sv); - (void)mg; + PERL_UNUSED_ARG(mg); if (!lsv) { SvOK_off(sv); @@ -1864,7 +1971,7 @@ Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); do_vecset(sv); /* XXX slurp this routine */ return 0; } @@ -1875,13 +1982,13 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) SV *targ = Nullsv; if (LvTARGLEN(sv)) { if (mg->mg_obj) { - SV *ahv = LvTARG(sv); - HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0); + SV * const ahv = LvTARG(sv); + HE * const he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0); if (he) targ = HeVAL(he); } else { - AV* av = (AV*)LvTARG(sv); + AV* const av = (AV*)LvTARG(sv); if ((I32)LvTARGOFF(sv) <= AvFILL(av)) targ = AvARRAY(av)[LvTARGOFF(sv)]; } @@ -1904,7 +2011,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); if (LvTARGLEN(sv)) vivify_defelem(sv); if (LvTARG(sv)) { @@ -1923,19 +2030,19 @@ Perl_vivify_defelem(pTHX_ SV *sv) if (!LvTARGLEN(sv) || !(mg = mg_find(sv, PERL_MAGIC_defelem))) return; if (mg->mg_obj) { - SV *ahv = LvTARG(sv); - HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0); + SV * const ahv = LvTARG(sv); + HE * const he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0); if (he) value = HeVAL(he); if (!value || value == &PL_sv_undef) Perl_croak(aTHX_ PL_no_helem_sv, mg->mg_obj); } else { - AV* av = (AV*)LvTARG(sv); + AV* const av = (AV*)LvTARG(sv); if ((I32)LvTARGLEN(sv) < 0 && (I32)LvTARGOFF(sv) > AvFILL(av)) LvTARG(sv) = Nullsv; /* array can't be extended */ else { - SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE); + SV** const svp = av_fetch(av, LvTARGOFF(sv), TRUE); if (!svp || (value = *svp) == &PL_sv_undef) Perl_croak(aTHX_ PL_no_aelem, (I32)LvTARGOFF(sv)); } @@ -1952,22 +2059,37 @@ Perl_vivify_defelem(pTHX_ SV *sv) int Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg) { - AV *av = (AV*)mg->mg_obj; + AV *const av = (AV*)mg->mg_obj; SV **svp = AvARRAY(av); - I32 i = AvFILLp(av); - (void)sv; + PERL_UNUSED_ARG(sv); + + if (svp) { + SV *const *const last = svp + AvFILLp(av); + + while (svp <= last) { + if (*svp) { + SV *const referrer = *svp; + if (SvWEAKREF(referrer)) { + /* XXX Should we check that it hasn't changed? */ + SvRV_set(referrer, 0); + SvOK_off(referrer); + SvWEAKREF_off(referrer); + } else if (SvTYPE(referrer) == SVt_PVGV || + SvTYPE(referrer) == SVt_PVLV) { + /* You lookin' at me? */ + assert(GvSTASH(referrer)); + assert(GvSTASH(referrer) == (HV*)sv); + GvSTASH(referrer) = 0; + } else { + Perl_croak(aTHX_ + "panic: magic_killbackrefs (flags=%"UVxf")", + (UV)SvFLAGS(referrer)); + } - while (i >= 0) { - if (svp[i]) { - if (!SvWEAKREF(svp[i])) - Perl_croak(aTHX_ "panic: magic_killbackrefs"); - /* XXX Should we check that it hasn't changed? */ - SvRV_set(svp[i], 0); - SvOK_off(svp[i]); - SvWEAKREF_off(svp[i]); - svp[i] = Nullsv; + *svp = Nullsv; + } + svp++; } - i--; } SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */ return 0; @@ -1984,7 +2106,7 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); sv_unmagic(sv, PERL_MAGIC_bm); SvVALID_off(sv); return 0; @@ -1993,7 +2115,7 @@ Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); sv_unmagic(sv, PERL_MAGIC_fm); SvCOMPILED_off(sv); return 0; @@ -2012,7 +2134,7 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg) { - (void)mg; + PERL_UNUSED_ARG(mg); sv_unmagic(sv, PERL_MAGIC_qr); return 0; } @@ -2020,9 +2142,10 @@ Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg) { - regexp *re = (regexp *)mg->mg_obj; + regexp * const re = (regexp *)mg->mg_obj; + PERL_UNUSED_ARG(sv); + ReREFCNT_dec(re); - (void)sv; return 0; } @@ -2034,7 +2157,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) * RenE Descartes said "I think not." * and vanished with a faint plop. */ - (void)sv; + PERL_UNUSED_ARG(sv); if (mg->mg_ptr) { Safefree(mg->mg_ptr); mg->mg_ptr = NULL; @@ -2048,7 +2171,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; + PERL_UNUSED_ARG(sv); Safefree(mg->mg_ptr); /* The mg_ptr holds the pos cache. */ mg->mg_ptr = 0; mg->mg_len = -1; /* The mg_len holds the len cache. */ @@ -2071,7 +2194,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case '\004': /* ^D */ #ifdef DEBUGGING - s = SvPV_nolen(sv); + s = SvPV_nolen_const(sv); PL_debug = get_debug_opts(&s, 0) | DEBUG_TOP_FLAG; DEBUG_x(dump_all()); #else @@ -2117,19 +2240,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); break; case '\011': /* ^I */ /* NOT \t in EBCDIC */ - if (PL_inplace) - Safefree(PL_inplace); - if (SvOK(sv)) - PL_inplace = savesvpv(sv); - else - PL_inplace = Nullch; + Safefree(PL_inplace); + PL_inplace = SvOK(sv) ? savesvpv(sv) : Nullch; break; case '\017': /* ^O */ if (*(mg->mg_ptr+1) == '\0') { - if (PL_osname) { - Safefree(PL_osname); - PL_osname = Nullch; - } + Safefree(PL_osname); + PL_osname = Nullch; if (SvOK(sv)) { TAINT_PROPER("assigning to $^O"); PL_osname = savesvpv(sv); @@ -2173,7 +2290,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) STRLEN len, i; int accumulate = 0 ; int any_fatals = 0 ; - const char * const ptr = (char*)SvPV(sv, len) ; + const char * const ptr = SvPV_const(sv, len) ; for (i = 0 ; i < len ; ++i) { accumulate |= ptr[i] ; any_fatals |= (ptr[i] & 0xAA) ; @@ -2228,7 +2345,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; case '|': { - IO *io = GvIOp(PL_defoutgv); + IO * const io = GvIOp(PL_defoutgv); if(!io) break; if ((SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) == 0) @@ -2267,11 +2384,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_ofs_sv = Nullsv; } break; - case '#': - if (PL_ofmt) - Safefree(PL_ofmt); - PL_ofmt = savesvpv(sv); - break; case '[': PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); break; @@ -2285,10 +2397,10 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #endif #ifdef VMSISH_STATUS if (VMSISH_STATUS) - STATUS_NATIVE_SET((U32)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv))); + STATUS_NATIVE_CHILD_SET((U32)SvIV(sv)); else #endif - STATUS_UNIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + STATUS_UNIX_EXIT_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); break; case '!': { @@ -2390,7 +2502,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case ')': #ifdef HAS_SETGROUPS { - const char *p = SvPV(sv, len); + const char *p = SvPV_const(sv, len); Groups_t gary[NGROUPS]; while (isSPACE(*p)) @@ -2447,7 +2559,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) * show a string from the process struct and provide * the setproctitle() routine to manipulate that. */ { - s = SvPV(sv, len); + s = SvPV_const(sv, len); # if __FreeBSD_version > 410001 /* The leading "-" removes the "perl: " prefix, * but not the "(perl) suffix from the ps(1) @@ -2469,7 +2581,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #if defined(__hpux) && defined(PSTAT_SETCMD) { union pstun un; - s = SvPV(sv, len); + s = SvPV_const(sv, len); un.pst_command = (char *)s; pstat(PSTAT_SETCMD, un, len, 0, 0); } @@ -2523,7 +2635,11 @@ Perl_whichsig(pTHX_ const char *sig) } Signal_t +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) +Perl_sighandler(int sig, ...) +#else Perl_sighandler(int sig) +#endif { #ifdef PERL_GET_SIG_CONTEXT dTHXa(PERL_GET_SIG_CONTEXT); @@ -2532,12 +2648,12 @@ Perl_sighandler(int sig) #endif dSP; GV *gv = Nullgv; - HV *st; - SV *sv = Nullsv, *tSv = PL_Sv; + SV *sv = Nullsv; + SV * const tSv = PL_Sv; CV *cv = Nullcv; OP *myop = PL_op; U32 flags = 0; - XPV *tXpv = PL_Xpv; + XPV * const tXpv = PL_Xpv; if (PL_savestack_ix + 15 <= PL_savestack_max) flags |= 1; @@ -2556,7 +2672,7 @@ Perl_sighandler(int sig) infinity, so we fix 4 (in fact 5): */ if (flags & 1) { PL_savestack_ix += 5; /* Protect save in progress. */ - SAVEDESTRUCTOR_X(unwind_handler_stack, (void*)&flags); + SAVEDESTRUCTOR_X(S_unwind_handler_stack, (void*)&flags); } if (flags & 4) PL_markstack_ptr++; /* Protect mark. */ @@ -2564,8 +2680,10 @@ Perl_sighandler(int sig) PL_scopestack_ix += 1; /* sv_2cv is too complicated, try a simpler variant first: */ if (!SvROK(PL_psig_ptr[sig]) || !(cv = (CV*)SvRV(PL_psig_ptr[sig])) - || SvTYPE(cv) != SVt_PVCV) + || SvTYPE(cv) != SVt_PVCV) { + HV *st; cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE); + } if (!cv || !CvROOT(cv)) { if (ckWARN(WARN_SIGNAL)) @@ -2591,6 +2709,38 @@ Perl_sighandler(int sig) PUSHSTACKi(PERLSI_SIGNAL); PUSHMARK(SP); PUSHs(sv); +#if defined(HAS_SIGACTION) && defined(SA_SIGINFO) + { + 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); +#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); +#endif + EXTEND(SP, 2); + PUSHs((SV*)rv); + PUSHs(newSVpv((void*)sip, sizeof(*sip))); + } + } + } +#endif PUTBACK; call_sv((SV*)cv, G_DISCARD|G_EVAL); @@ -2613,7 +2763,7 @@ Perl_sighandler(int sig) (void)rsignal(sig, PL_csighandlerp); #endif #endif /* !PERL_MICRO */ - DieNull; + Perl_die(aTHX_ Nullch); } cleanup: if (flags & 1) @@ -2633,10 +2783,10 @@ cleanup: static void -restore_magic(pTHX_ const void *p) +S_restore_magic(pTHX_ const void *p) { - MGS* mgs = SSPTR(PTR2IV(p), MGS*); - SV* sv = mgs->mgs_sv; + MGS* const mgs = SSPTR(PTR2IV(p), MGS*); + SV* const sv = mgs->mgs_sv; if (!sv) return; @@ -2654,8 +2804,16 @@ restore_magic(pTHX_ const void *p) SvFLAGS(sv) |= mgs->mgs_flags; else mg_magical(sv); - if (SvGMAGICAL(sv)) - SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + if (SvGMAGICAL(sv)) { + /* 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 ); + } + } } mgs->mgs_sv = NULL; /* mark the MGS structure as restored */ @@ -2681,7 +2839,7 @@ restore_magic(pTHX_ const void *p) } static void -unwind_handler_stack(pTHX_ const void *p) +S_unwind_handler_stack(pTHX_ const void *p) { dVAR; const U32 flags = *(const U32*)p;