X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=mg.c;h=2f2d5ba471f13ff9bd4466940aae9336a82dfcef;hb=2767dea0ecb27303bd680fbd54b2844c30f29b75;hp=b04e24faa4e9884dc8b0262a148fec4df25d8025;hpb=aadb217dbe1b43fbd45cb1644a86dd26d09068d0;p=p5sagit%2Fp5-mst-13.2.git diff --git a/mg.c b/mg.c index b04e24f..2f2d5ba 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 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. @@ -40,22 +40,26 @@ tie. #include "perl.h" #if defined(HAS_GETGROUPS) || defined(HAS_SETGROUPS) -# ifndef NGROUPS -# define NGROUPS 32 -# endif # ifdef I_GRP # include # endif #endif +#if defined(HAS_SETGROUPS) +# ifndef NGROUPS +# define NGROUPS 32 +# endif +#endif + #ifdef __hpux # 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 */ @@ -79,15 +83,15 @@ struct magic_state { STATIC void S_save_magic(pTHX_ I32 mgs_ix, SV *sv) { + dVAR; MGS* mgs; assert(SvMAGICAL(sv)); -#ifdef PERL_COPY_ON_WRITE - /* Turning READONLY off for a copy-on-write scalar is a bad idea. */ + /* Turning READONLY off for a copy-on-write scalar (including shared + hash keys) is a bad idea. */ if (SvIsCOW(sv)) - sv_force_normal(sv); -#endif + sv_force_normal_flags(sv, 0); - 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; @@ -96,7 +100,10 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) SvMAGICAL_off(sv); SvREADONLY_off(sv); - SvFLAGS(sv) |= (SvFLAGS(sv) & (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; + } } /* @@ -111,6 +118,7 @@ void Perl_mg_magical(pTHX_ SV *sv) { const MAGIC* mg; + PERL_UNUSED_CONTEXT; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { const MGVTBL* const vtbl = mg->mg_virtual; if (vtbl) { @@ -124,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 @@ -135,6 +176,7 @@ Do magic after a value is retrieved from the SV. See C. int Perl_mg_get(pTHX_ SV *sv) { + dVAR; const I32 mgs_ix = SSNEW(sizeof(MGS)); const bool was_temp = (bool)SvTEMP(sv); int have_new = 0; @@ -146,7 +188,7 @@ Perl_mg_get(pTHX_ SV *sv) cause the SV's buffer to get stolen (and maybe other stuff). So restore it. */ - sv_2mortal(SvREFCNT_inc(sv)); + sv_2mortal(SvREFCNT_inc_simple_NN(sv)); if (!was_temp) { SvTEMP_off(sv); } @@ -194,7 +236,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 @@ -215,6 +257,7 @@ Do magic after a value is assigned to the SV. See C. int Perl_mg_set(pTHX_ SV *sv) { + dVAR; const I32 mgs_ix = SSNEW(sizeof(MGS)); MAGIC* mg; MAGIC* nextmg; @@ -232,7 +275,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; } @@ -247,6 +290,7 @@ Report on the SV's length. See C. U32 Perl_mg_length(pTHX_ SV *sv) { + dVAR; MAGIC* mg; STRLEN len; @@ -257,17 +301,17 @@ 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; } } if (DO_UTF8(sv)) { - U8 *s = (U8*)SvPV(sv, len); - len = Perl_utf8_length(aTHX_ s, s + len); + const U8 *s = (U8*)SvPV_const(sv, len); + len = utf8_length(s, s + len); } else - (void)SvPV(sv, len); + (void)SvPV_const(sv, len); return len; } @@ -284,7 +328,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 +369,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; } @@ -340,6 +384,7 @@ Finds the magic pointer for type matching the SV. See C. MAGIC* Perl_mg_find(pTHX_ const SV *sv, int type) { + PERL_UNUSED_CONTEXT; if (sv) { MAGIC *mg; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { @@ -347,7 +392,7 @@ Perl_mg_find(pTHX_ const SV *sv, int type) return mg; } } - return 0; + return NULL; } /* @@ -368,19 +413,62 @@ 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) && type != PERL_MAGIC_uvar) { + 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) +{ + dVAR; + MAGIC *mg; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { + 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); + 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. @@ -417,14 +505,25 @@ Perl_mg_free(pTHX_ SV *sv) U32 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) { - register const REGEXP *rx; - (void)sv; - - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - if (mg->mg_obj) /* @+ */ - return rx->nparens; - else /* @- */ - return rx->lastparen; + dVAR; + PERL_UNUSED_ARG(sv); + + if (PL_curpm) { + register const REGEXP * const rx = PM_GETRE(PL_curpm); + if (rx) { + if (mg->mg_obj) { /* @+ */ + /* return the number possible */ + return rx->nparens; + } else { /* @- */ + I32 paren = rx->lastparen; + + /* return the last filled */ + while ( paren >= 0 + && (rx->startp[paren] == -1 || rx->endp[paren] == -1) ) + paren--; + return (U32)paren; + } + } } return (U32)-1; @@ -433,32 +532,34 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) { - register REGEXP *rx; - - if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - register const I32 paren = mg->mg_len; - register I32 s; - register I32 t; - if (paren < 0) - return 0; - if (paren <= (I32)rx->nparens && - (s = rx->startp[paren]) != -1 && - (t = rx->endp[paren]) != -1) - { - register I32 i; - if (mg->mg_obj) /* @+ */ - i = t; - else /* @- */ - i = s; + dVAR; + if (PL_curpm) { + register const REGEXP * const rx = PM_GETRE(PL_curpm); + if (rx) { + register const I32 paren = mg->mg_len; + register I32 s; + register I32 t; + if (paren < 0) + return 0; + if (paren <= (I32)rx->nparens && + (s = rx->startp[paren]) != -1 && + (t = rx->endp[paren]) != -1) + { + register I32 i; + if (mg->mg_obj) /* @+ */ + i = t; + else /* @- */ + i = s; + + if (i > 0 && RX_MATCH_UTF8(rx)) { + const char * const b = rx->subbeg; + if (b) + i = utf8_length((U8*)b, (U8*)(b+i)); + } - if (i > 0 && RX_MATCH_UTF8(rx)) { - char *b = rx->subbeg; - if (b) - i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i)); + sv_setiv(sv, i); } - - sv_setiv(sv, i); - } + } } return 0; } @@ -466,19 +567,16 @@ 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); - /* NOT REACHED */ -#ifndef HASATTRIBUTE - /* No __attribute__, so the compiler doesn't know that croak never returns - */ - return 0; -#endif + NORETURN_FUNCTION_END; } U32 Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) { + dVAR; register I32 paren; register I32 i; register const REGEXP *rx; @@ -498,12 +596,13 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) i = t1 - s1; getlen: if (i > 0 && RX_MATCH_UTF8(rx)) { - char *s = rx->subbeg + s1; - char *send = rx->subbeg + t1; + const char * const s = rx->subbeg + s1; + const U8 *ep; + STRLEN el; i = t1 - s1; - if (is_utf8_string((U8*)s, i)) - i = Perl_utf8_length(aTHX_ (U8*)s, (U8*)send); + if (is_utf8_string_loclen((U8*)s, i, &ep, &el)) + i = el; } if (i < 0) Perl_croak(aTHX_ "panic: magic_len: %"IVdf, (IV)i); @@ -560,45 +659,86 @@ 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 { \ + if (SvPOK(sv)) { \ + STRLEN len = SvCUR(sv); \ + char * const p = SvPVX(sv); \ + while (len > 0 && isSPACE(p[len-1])) \ + --len; \ + SvCUR_set(sv, len); \ + p[len] = '\0'; \ + } \ +} 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) { 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; switch (*mg->mg_ptr) { case '\001': /* ^A */ sv_setsv(sv, PL_bodytarget); break; - case '\003': /* ^C */ - sv_setiv(sv, (IV)PL_minus_c); + case '\003': /* ^C, ^CHILD_ERROR_NATIVE */ + if (nextchar == '\0') { + sv_setiv(sv, (IV)PL_minus_c); + } + else if (strEQ(remaining, "HILD_ERROR_NATIVE")) { + sv_setiv(sv, (IV)STATUS_NATIVE); + } break; case '\004': /* ^D */ sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK)); break; case '\005': /* ^E */ - if (*(mg->mg_ptr+1) == '\0') { -#ifdef MACOS_TRADITIONAL + if (nextchar == '\0') { +#if defined(MACOS_TRADITIONAL) { char msg[256]; sv_setnv(sv,(double)gMacPerl_OSErr); sv_setpv(sv, gMacPerl_OSErr ? GetSysErrText(gMacPerl_OSErr, msg) : ""); } -#else -#ifdef VMS +#elif defined(VMS) { # include # include @@ -608,49 +748,44 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) if (sys$getmsg(vaxc$errno,&msgdsc.dsc$w_length,&msgdsc,0,0) & 1) sv_setpvn(sv,msgdsc.dsc$a_pointer,msgdsc.dsc$w_length); else - sv_setpv(sv,""); + sv_setpvn(sv,"",0); } -#else -#ifdef OS2 +#elif defined(OS2) if (!(_emx_env & 0x200)) { /* Under DOS */ sv_setnv(sv, (NV)errno); 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; } sv_setnv(sv, (NV)Perl_rc); sv_setpv(sv, os2error(Perl_rc)); } -#else -#ifdef WIN32 +#elif defined(WIN32) { - DWORD dwErr = GetLastError(); + const DWORD dwErr = GetLastError(); sv_setnv(sv, (NV)dwErr); - if (dwErr) - { + if (dwErr) { PerlProc_GetOSError(sv, dwErr); } else - sv_setpv(sv, ""); + sv_setpvn(sv, "", 0); SetLastError(dwErr); } #else { - int saveerrno = errno; + const int saveerrno = errno; sv_setnv(sv, (NV)errno); sv_setpv(sv, errno ? Strerror(errno) : ""); errno = saveerrno; } #endif -#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 */ @@ -666,23 +801,25 @@ 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")) { - if (!PL_compiling.cop_io) - sv_setsv(sv, &PL_sv_undef); - else { - sv_setsv(sv, PL_compiling.cop_io); - } + else if (strEQ(remaining, "PEN")) { + 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 (*(mg->mg_ptr+1) == '\0') { + if (nextchar == '\0') { if (PL_lex_state != LEX_NOTPARSING) SvOK_off(sv); else if (PL_in_eval) @@ -692,139 +829,115 @@ 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")) + case '\025': /* $^UNICODE, $^UTF8LOCALE, $^UTF8CACHE */ + 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); + else if (strEQ(remaining, "TF8CACHE")) + sv_setiv(sv, (IV) PL_utf8cache); 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); - if (bits && (bits_all=hv_fetch(bits, "all", 3, FALSE))) { - sv_setsv(sv, *bits_all); + HV * const bits=get_hv("warnings::Bits", FALSE); + 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) ; } } else { - sv_setsv(sv, PL_compiling.cop_warnings); + sv_setpvn(sv, (char *) (PL_compiling.cop_warnings + 1), + *PL_compiling.cop_warnings); } 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; - if (!rx->subbeg) - break; - - getrx: - if (i >= 0) { - sv_setpvn(sv, s, i); - 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* 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(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) { + CALLREG_NUMBUF(rx,rx->lastparen,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) { + CALLREG_NUMBUF(rx,rx->lastcloseparen,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(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(rx,-1,sv); + break; } sv_setsv(sv,&PL_sv_undef); break; case '.': -#ifndef lint if (GvIO(PL_last_in_gv)) { sv_setiv(sv, (IV)IoLINES(GvIOp(PL_last_in_gv))); } -#endif break; case '?': { @@ -852,7 +965,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) s = GvENAME(PL_defoutgv); sv_setpv(sv,s); break; -#ifndef lint case '=': if (GvIOp(PL_defoutgv)) sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv))); @@ -865,13 +977,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) if (GvIOp(PL_defoutgv)) sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv))); break; -#endif case ':': break; case '/': break; case '[': - WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase)); + sv_setiv(sv, (IV)CopARYBASE_get(PL_curcop)); break; case '|': if (GvIOp(PL_defoutgv)) @@ -883,16 +994,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) @@ -903,6 +1011,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) errno = saveerrno; } #endif + SvRTRIM(sv); SvNOK_on(sv); /* what a wonderful hack! */ break; case '<': @@ -913,25 +1022,22 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) break; case '(': sv_setiv(sv, (IV)PL_gid); -#ifdef HAS_GETGROUPS - Perl_sv_setpvf(aTHX_ sv, "%"Gid_t_f, PL_gid); -#endif goto add_groups; case ')': sv_setiv(sv, (IV)PL_egid); -#ifdef HAS_GETGROUPS - Perl_sv_setpvf(aTHX_ sv, "%"Gid_t_f, PL_egid); -#endif add_groups: #ifdef HAS_GETGROUPS { - Groups_t gary[NGROUPS]; - i = getgroups(NGROUPS,gary); - while (--i >= 0) - Perl_sv_catpvf(aTHX_ sv, " %"Gid_t_f, gary[i]); + Groups_t *gary = NULL; + I32 i, num_groups = getgroups(0, gary); + Newx(gary, num_groups, Groups_t); + num_groups = getgroups(num_groups, gary); + for (i = 0; i < num_groups; i++) + Perl_sv_catpvf(aTHX_ sv, " %"IVdf, (IV)gary[i]); + Safefree(gary); } -#endif (void)SvIOK_on(sv); /* what a wonderful hack! */ +#endif break; #ifndef MACOS_TRADITIONAL case '0': @@ -944,7 +1050,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); @@ -955,21 +1061,18 @@ int Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) { dVAR; - register char *s; - char *ptr; - STRLEN len, klen; - - s = SvPV(sv,len); - ptr = MgPV(mg,klen); + STRLEN len = 0, klen; + const char *s = SvOK(sv) ? SvPV_const(sv,len) : ""; + const char * const ptr = MgPV_const(mg,klen); my_setenv(ptr, s); #ifdef DYNAMIC_ENV_FETCH /* We just undefd an environment var. Is a replacement */ /* waiting in the wings? */ if (!len) { - SV **valp; - if ((valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE))) - s = SvPV(*valp, len); + SV ** const valp = hv_fetch(GvHVn(PL_envgv), ptr, klen, FALSE); + if (valp) + s = SvOK(*valp) ? SvPV_const(*valp, len) : ""; } #endif @@ -980,10 +1083,12 @@ 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; + 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 */ if ( ((cp = strchr(elt,'[')) || (cp = strchr(elt,'<'))) ) { @@ -993,7 +1098,7 @@ Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) return 0; } } - if ((cp = strchr(elt, ':')) != Nullch) + if ((cp = strchr(elt, ':')) != NULL) *cp = '\0'; if (my_trnlnm(elt, eltbuf, j++)) elt = eltbuf; @@ -1005,17 +1110,26 @@ 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]; 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 >= sizeof tmpbuf /* too long -- assume the worst */ - || *tmpbuf != '/' + if (i >= (I32)sizeof tmpbuf /* too long -- assume the worst */ +#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; @@ -1031,27 +1145,27 @@ 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),NULL); return 0; } int Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) { -#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) + dVAR; + PERL_UNUSED_ARG(mg); +#if defined(VMS) 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); + my_clearenv(); 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 @@ -1062,39 +1176,13 @@ int Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) { dVAR; -#ifndef PERL_MICRO -#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); +#if defined(VMS) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else -# if defined(PERL_IMPLICIT_SYS) || defined(WIN32) - PerlEnv_clearenv(); -# else -# ifdef USE_ENVIRON_ARRAY -# if defined(USE_ITHREADS) - /* only the parent thread can clobber the process environment */ - if (PL_curinterp == aTHX) -# endif - { -# ifndef PERL_USE_SAFE_PUTENV - if (!PL_use_safe_putenv) { - I32 i; - - if (environ == PL_origenviron) - environ = (char**)safesysmalloc(sizeof(char*)); - else - for (i = 0; environ[i]; i++) - safesysfree(environ[i]); - } -# endif /* PERL_USE_SAFE_PUTENV */ - - environ[0] = Nullch; - } -# endif /* USE_ENVIRON_ARRAY */ -# endif /* PERL_IMPLICIT_SYS || WIN32 */ -#endif /* VMS || EPOC */ -#endif /* !PERL_MICRO */ - (void)sv; - (void)mg; + my_clearenv(); +#endif return 0; } @@ -1103,35 +1191,35 @@ 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 ); - (void)sigprocmask(SIG_SETMASK, ossetp, (sigset_t *)0); + const sigset_t * const ossetp = (const sigset_t *) SvPV_nolen_const( save_sv ); + (void)sigprocmask(SIG_SETMASK, ossetp, NULL); } #endif int Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) { - I32 i; - STRLEN n_a; + dVAR; /* 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]); 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 == SIG_IGN) - sv_setpv(sv,"IGNORE"); + if(sigstate == (Sighandler_t) SIG_IGN) + sv_setpvs(sv,"IGNORE"); else sv_setsv(sv,&PL_sv_undef); - PL_psig_ptr[i] = SvREFCNT_inc(sv); + PL_psig_ptr[i] = SvREFCNT_inc_simple_NN(sv); SvTEMP_off(sv); } } @@ -1144,27 +1232,23 @@ 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; + 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 *to_dec = *svp; - *svp = 0; - SvREFCNT_dec(to_dec); + SV *const to_dec = *svp; + *svp = NULL; + 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; @@ -1186,14 +1270,14 @@ 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]); PL_psig_name[i]=0; } if(PL_psig_ptr[i]) { - SV *to_dec=PL_psig_ptr[i]; + SV * const to_dec=PL_psig_ptr[i]; PL_psig_ptr[i]=0; LEAVE; SvREFCNT_dec(to_dec); @@ -1205,17 +1289,41 @@ 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 + 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; + if (++PL_sig_pending >= SIG_PENDING_DIE_COUNT) + Perl_croak(aTHX_ "Maximal count of pending signals (%lu) exceeded", + (unsigned long)SIG_PENDING_DIE_COUNT); } 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); @@ -1234,7 +1342,17 @@ 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. */ (*PL_sighandlerp)(sig); @@ -1266,6 +1384,7 @@ Perl_csighandler_init(void) void Perl_despatch_signals(pTHX) { + dVAR; int sig; PL_sig_pending = 0; for (sig = 1; sig < SIG_SIZE; sig++) { @@ -1284,19 +1403,19 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) { dVAR; I32 i; - SV** svp = 0; + SV** svp = NULL; /* Need to be careful with SvREFCNT_dec(), because that can have side * effects (due to closures). We must make sure that the new disposition * is in place before it is called. */ - SV* to_dec = 0; + SV* to_dec = NULL; STRLEN len; #ifdef HAS_SIGPROCMASK sigset_t set, save; 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; @@ -1306,13 +1425,14 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) Perl_croak(aTHX_ "No such hook: %s", s); i = 0; if (*svp) { - to_dec = *svp; - *svp = 0; + if (*svp != PERL_WARNHOOK_FATAL) + to_dec = *svp; + *svp = NULL; } } else { i = whichsig(s); /* ...no, a brick */ - if (i < 0) { + if (i <= 0) { if (ckWARN(WARN_SIGNAL)) Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s); return 0; @@ -1339,7 +1459,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(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]); @@ -1352,19 +1472,19 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) #endif } else - *svp = SvREFCNT_inc(sv); + *svp = SvREFCNT_inc_simple_NN(sv); if(to_dec) 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 PL_sig_ignoring[i] = 1; (void)rsignal(i, PL_csighandlerp); #else - (void)rsignal(i, SIG_IGN); + (void)rsignal(i, (Sighandler_t) SIG_IGN); #endif } } @@ -1376,7 +1496,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 { @@ -1386,11 +1506,11 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) * tell whether HINT_STRICT_REFS is in force or not. */ if (!strchr(s,':') && !strchr(s,'\'')) - sv_insert(sv, 0, 0, "main::", 6); + Perl_sv_insert(aTHX_ sv, 0, 0, STR_WITH_LEN("main::")); if (i) (void)rsignal(i, PL_csighandlerp); else - *svp = SvREFCNT_inc(sv); + *svp = SvREFCNT_inc_simple_NN(sv); } #ifdef HAS_SIGPROCMASK if(i) @@ -1405,8 +1525,9 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; - (void)mg; + dVAR; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); PL_sub_generation++; return 0; } @@ -1414,8 +1535,9 @@ Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; - (void)mg; + dVAR; + PERL_UNUSED_ARG(sv); + PERL_UNUSED_ARG(mg); /* HV_badAMAGIC_on(Sv_STASH(sv)); */ PL_amagic_generation++; @@ -1427,7 +1549,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); @@ -1446,7 +1568,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)); } @@ -1457,6 +1579,7 @@ Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) STATIC int S_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, I32 flags, int n, SV *val) { + dVAR; dSP; PUSHMARK(SP); @@ -1590,7 +1713,7 @@ 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) { return magic_methpack(sv,mg,"EXISTS"); } @@ -1599,19 +1722,19 @@ SV * 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 *retval; + SV * const tied = SvTIED_obj((SV*)hv, mg); + HV * const pkg = SvSTASH((SV*)SvRV(tied)); if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) { SV *key; - if (HvEITER(hv)) + if (HvEITER_get(hv)) /* we are in an iteration so the hash cannot be empty */ return &PL_sv_yes; /* no xhv_eiter so now use FIRSTKEY */ key = sv_newmortal(); magic_nextpack((SV*)hv, mg, key); - HvEITER(hv) = NULL; /* need to reset iterator */ + HvEITER_set(hv, NULL); /* need to reset iterator */ return SvOK(key) ? &PL_sv_yes : &PL_sv_no; } @@ -1625,6 +1748,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; @@ -1633,52 +1758,88 @@ 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; + dVAR; + 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); + dVAR; + const AV * const obj = (AV*)mg->mg_obj; + if (obj) { + sv_setiv(sv, AvFILL(obj) + CopARYBASE_get(PL_curcop)); + } 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); + dVAR; + AV * const obj = (AV*)mg->mg_obj; + if (obj) { + av_fill(obj, SvIV(sv) - CopARYBASE_get(PL_curcop)); + } 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) +{ + dVAR; + 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); + dVAR; + SV* const lsv = LvTARG(sv); + PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) { - mg = mg_find(lsv, PERL_MAGIC_regex_global); - if (mg && mg->mg_len >= 0) { - I32 i = mg->mg_len; + MAGIC * const found = mg_find(lsv, PERL_MAGIC_regex_global); + if (found && found->mg_len >= 0) { + I32 i = found->mg_len; if (DO_UTF8(lsv)) sv_pos_b2u(lsv, &i); - sv_setiv(sv, i + PL_curcop->cop_arybase); + sv_setiv(sv, i + CopARYBASE_get(PL_curcop)); return 0; } } @@ -1689,28 +1850,36 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) { - SV* lsv = LvTARG(sv); + dVAR; + SV* const lsv = LvTARG(sv); SSize_t pos; STRLEN len; STRLEN ulen = 0; + MAGIC* found; - mg = 0; + PERL_UNUSED_ARG(mg); if (SvTYPE(lsv) >= SVt_PVMG && SvMAGIC(lsv)) - mg = mg_find(lsv, PERL_MAGIC_regex_global); - if (!mg) { + found = mg_find(lsv, PERL_MAGIC_regex_global); + else + found = NULL; + if (!found) { if (!SvOK(sv)) return 0; - sv_magic(lsv, (SV*)0, PERL_MAGIC_regex_global, Nullch, 0); - mg = mg_find(lsv, PERL_MAGIC_regex_global); +#ifdef PERL_OLD_COPY_ON_WRITE + if (SvIsCOW(lsv)) + sv_force_normal_flags(lsv, 0); +#endif + found = sv_magicext(lsv, NULL, PERL_MAGIC_regex_global, &PL_vtbl_mglob, + NULL, 0); } else if (!SvOK(sv)) { - mg->mg_len = -1; + found->mg_len = -1; return 0; } len = SvPOK(lsv) ? SvCUR(lsv) : sv_len(lsv); - pos = SvIV(sv) - PL_curcop->cop_arybase; + pos = SvIV(sv) - CopARYBASE_get(PL_curcop); if (DO_UTF8(lsv)) { ulen = sv_len_utf8(lsv); @@ -1732,23 +1901,9 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) pos = p; } - mg->mg_len = pos; - mg->mg_flags &= ~MGf_MINMATCH; - - return 0; -} + found->mg_len = pos; + found->mg_flags &= ~MGf_MINMATCH; -int -Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg) -{ - (void)mg; - if (SvFAKE(sv)) { /* FAKE globs can get coerced */ - SvFAKE_off(sv); - gv_efullname3(sv,((GV*)sv), "*"); - SvFAKE_on(sv); - } - else - gv_efullname3(sv,((GV*)sv), "*"); /* a gv value, be nice */ return 0; } @@ -1756,11 +1911,16 @@ 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); + if (isGV_with_GP(sv)) { + /* 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)) @@ -1774,10 +1934,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); @@ -1794,12 +1954,13 @@ Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { + dVAR; STRLEN len; - char *tmps = SvPV(sv, len); + const char * const 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); @@ -1809,11 +1970,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); @@ -1827,25 +1989,24 @@ 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 */ + dVAR; + 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; + 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; + mg->mg_len &= ~1; } - else if (PL_tainted) - mg->mg_len |= 1; - else - mg->mg_len &= ~1; return 0; } @@ -1853,21 +2014,20 @@ int Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) { SV * const lsv = LvTARG(sv); - (void)mg; + PERL_UNUSED_ARG(mg); - if (!lsv) { + if (lsv) + sv_setuv(sv, do_vecget(lsv, LvTARGOFF(sv), LvTARGLEN(sv))); + else SvOK_off(sv); - return 0; - } - sv_setuv(sv, do_vecget(lsv, LvTARGOFF(sv), LvTARGLEN(sv))); return 0; } 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,26 +2035,27 @@ Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) { - SV *targ = Nullsv; + dVAR; + SV *targ = NULL; 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)]; } - 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(targ); + LvTARG(sv) = SvREFCNT_inc_simple_NN(targ); LvTARGLEN(sv) = 0; SvREFCNT_dec(mg->mg_obj); - mg->mg_obj = Nullsv; + mg->mg_obj = NULL; mg->mg_flags &= ~MGf_REFCOUNTED; } } @@ -1907,7 +2068,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)) { @@ -1920,66 +2081,49 @@ Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg) void Perl_vivify_defelem(pTHX_ SV *sv) { + dVAR; MAGIC *mg; - SV *value = Nullsv; + SV *value = NULL; if (!LvTARGLEN(sv) || !(mg = mg_find(sv, PERL_MAGIC_defelem))) return; if (mg->mg_obj) { - SV *ahv = LvTARG(sv); - STRLEN n_a; - 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, SvPV(mg->mg_obj, n_a)); + Perl_croak(aTHX_ PL_no_helem_sv, SVfARG(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 */ + LvTARG(sv) = NULL; /* array can't be extended */ else { - SV** svp = av_fetch(av, LvTARGOFF(sv), TRUE); + SV* const * const svp = av_fetch(av, LvTARGOFF(sv), TRUE); if (!svp || (value = *svp) == &PL_sv_undef) Perl_croak(aTHX_ PL_no_aelem, (I32)LvTARGOFF(sv)); } } - (void)SvREFCNT_inc(value); + SvREFCNT_inc_simple_void(value); SvREFCNT_dec(LvTARG(sv)); LvTARG(sv) = value; LvTARGLEN(sv) = 0; SvREFCNT_dec(mg->mg_obj); - mg->mg_obj = Nullsv; + mg->mg_obj = NULL; mg->mg_flags &= ~MGf_REFCOUNTED; } int Perl_magic_killbackrefs(pTHX_ SV *sv, MAGIC *mg) { - AV *av = (AV*)mg->mg_obj; - SV **svp = AvARRAY(av); - I32 i = AvFILLp(av); - (void)sv; - - 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; - } - i--; - } - SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */ - return 0; + return Perl_sv_kill_backrefs(aTHX_ sv, (AV*)mg->mg_obj); } int Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) { + PERL_UNUSED_CONTEXT; mg->mg_len = -1; SvSCREAM_off(sv); return 0; @@ -1988,8 +2132,9 @@ 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); + SvTAIL_off(sv); SvVALID_off(sv); return 0; } @@ -1997,7 +2142,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; @@ -2016,7 +2161,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; } @@ -2024,9 +2169,11 @@ Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg) { - regexp *re = (regexp *)mg->mg_obj; + dVAR; + regexp * const re = (regexp *)mg->mg_obj; + PERL_UNUSED_ARG(sv); + ReREFCNT_dec(re); - (void)sv; return 0; } @@ -2038,7 +2185,8 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) * RenE Descartes said "I think not." * and vanished with a faint plop. */ - (void)sv; + PERL_UNUSED_CONTEXT; + PERL_UNUSED_ARG(sv); if (mg->mg_ptr) { Safefree(mg->mg_ptr); mg->mg_ptr = NULL; @@ -2052,9 +2200,10 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) { - (void)sv; + PERL_UNUSED_CONTEXT; + PERL_UNUSED_ARG(sv); Safefree(mg->mg_ptr); /* The mg_ptr holds the pos cache. */ - mg->mg_ptr = 0; + mg->mg_ptr = NULL; mg->mg_len = -1; /* The mg_len holds the len cache. */ return 0; } @@ -2062,6 +2211,7 @@ Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) { + dVAR; register const char *s; I32 i; STRLEN len; @@ -2070,34 +2220,34 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) sv_setsv(PL_bodytarget, sv); break; case '\003': /* ^C */ - PL_minus_c = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + PL_minus_c = (bool)SvIV(sv); break; 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 - PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG; + PL_debug = (SvIV(sv)) | DEBUG_TOP_FLAG; #endif break; case '\005': /* ^E */ if (*(mg->mg_ptr+1) == '\0') { #ifdef MACOS_TRADITIONAL - gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + gMacPerl_OSErr = SvIV(sv); #else # ifdef VMS - set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + set_vaxc_errno(SvIV(sv)); # else # ifdef WIN32 SetLastError( SvIV(sv) ); # else # ifdef OS2 - os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + os2_setsyserrno(SvIV(sv)); # else /* will anyone ever use this? */ - SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4); + SETERRNO(SvIV(sv), 4); # endif # endif # endif @@ -2110,44 +2260,61 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_encoding = newSVsv(sv); } else { - PL_encoding = Nullsv; + PL_encoding = NULL; } } break; case '\006': /* ^F */ - PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_maxsysfd = SvIV(sv); break; case '\010': /* ^H */ - PL_hints = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_hints = SvIV(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) : NULL; break; case '\017': /* ^O */ if (*(mg->mg_ptr+1) == '\0') { - if (PL_osname) { - Safefree(PL_osname); - PL_osname = Nullch; - } + Safefree(PL_osname); + PL_osname = NULL; if (SvOK(sv)) { TAINT_PROPER("assigning to $^O"); PL_osname = savesvpv(sv); } } 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 = 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_ tmp_he, + sv_2mortal(newSVpvs("open<")), tmp); } break; case '\020': /* ^P */ - PL_perldb = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_perldb = SvIV(sv); if (PL_perldb && !PL_DBsingle) init_debugger(); break; @@ -2155,13 +2322,18 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #ifdef BIG_TIME PL_basetime = (Time_t)(SvNOK(sv) ? SvNVX(sv) : sv_2nv(sv)); #else - PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + PL_basetime = (Time_t)SvIV(sv); #endif break; + case '\025': /* ^UTF8CACHE */ + if (strEQ(mg->mg_ptr+1, "TF8CACHE")) { + PL_utf8cache = (signed char) sv_2iv(sv); + } + break; case '\027': /* ^W & $^WARNING_BITS */ if (*(mg->mg_ptr+1) == '\0') { if ( ! (PL_dowarn & G_WARN_ALL_MASK)) { - i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + i = SvIV(sv); PL_dowarn = (PL_dowarn & ~G_WARN_ON) | (i ? G_WARN_ON : G_WARN_OFF) ; } @@ -2177,22 +2349,32 @@ 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) ; } - if (!accumulate) - PL_compiling.cop_warnings = pWARN_NONE; - else if (isWARN_on(sv, WARN_ALL) && !any_fatals) { + 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 ; } else { - if (specialWARN(PL_compiling.cop_warnings)) - PL_compiling.cop_warnings = newSVsv(sv) ; - else - sv_setsv(PL_compiling.cop_warnings, sv); + STRLEN len; + const char *const p = SvPV_const(sv, len); + + PL_compiling.cop_warnings + = Perl_new_warnings_bitfield(aTHX_ PL_compiling.cop_warnings, + p, len); + if (isWARN_on(PL_compiling.cop_warnings, WARN_ONCE)) PL_dowarn |= G_WARN_ONCE ; } @@ -2212,30 +2394,30 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case '^': Safefree(IoTOP_NAME(GvIOp(PL_defoutgv))); s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); - IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO); + IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); break; case '~': Safefree(IoFMT_NAME(GvIOp(PL_defoutgv))); s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); - IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO); + IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv, GV_ADD, SVt_PVIO); break; case '=': - IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIV(sv)); break; case '-': - IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoLINES_LEFT(GvIOp(PL_defoutgv)) = (SvIV(sv)); if (IoLINES_LEFT(GvIOp(PL_defoutgv)) < 0L) IoLINES_LEFT(GvIOp(PL_defoutgv)) = 0L; break; case '%': - IoPAGE(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + IoPAGE(GvIOp(PL_defoutgv)) = (SvIV(sv)); 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) + if ((SvIV(sv)) == 0) IoFLAGS(io) &= ~IOf_FLUSH; else { if (!(IoFLAGS(io) & IOf_FLUSH)) { @@ -2258,7 +2440,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_ors_sv = newSVsv(sv); } else { - PL_ors_sv = Nullsv; + PL_ors_sv = NULL; } break; case ',': @@ -2268,16 +2450,11 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_ofs_sv = newSVsv(sv); } else { - PL_ofs_sv = Nullsv; + PL_ofs_sv = NULL; } 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); + CopARYBASE_set(&PL_compiling, SvIV(sv)); break; case '?': #ifdef COMPLEX_STATUS @@ -2289,10 +2466,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_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + STATUS_UNIX_EXIT_SET(SvIV(sv)); break; case '!': { @@ -2306,7 +2483,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } break; case '<': - PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_uid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_RUID; break; /* don't do magic till later */ @@ -2338,7 +2515,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid)); break; case '>': - PL_euid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_euid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_EUID; break; /* don't do magic till later */ @@ -2365,7 +2542,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_tainting |= (PL_uid && (PL_euid != PL_uid || PL_egid != PL_gid)); break; case '(': - PL_gid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_gid = SvIV(sv); if (PL_delaymagic) { PL_delaymagic |= DM_RGID; break; /* don't do magic till later */ @@ -2394,26 +2571,31 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case ')': #ifdef HAS_SETGROUPS { - const char *p = SvPV(sv, len); - Groups_t gary[NGROUPS]; - - while (isSPACE(*p)) - ++p; - PL_egid = Atol(p); - for (i = 0; i < NGROUPS; ++i) { - while (*p && !isSPACE(*p)) - ++p; - while (isSPACE(*p)) - ++p; - if (!*p) - break; - gary[i] = Atol(p); - } - if (i) - (void)setgroups(i, gary); + const char *p = SvPV_const(sv, len); + Groups_t *gary = NULL; + + while (isSPACE(*p)) + ++p; + PL_egid = Atol(p); + for (i = 0; i < NGROUPS; ++i) { + while (*p && !isSPACE(*p)) + ++p; + while (isSPACE(*p)) + ++p; + if (!*p) + break; + if(!gary) + Newx(gary, i + 1, Groups_t); + else + Renew(gary, i + 1, Groups_t); + gary[i] = Atol(p); + } + if (i) + (void)setgroups(i, gary); + Safefree(gary); } #else /* HAS_SETGROUPS */ - PL_egid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_egid = SvIV(sv); #endif /* HAS_SETGROUPS */ if (PL_delaymagic) { PL_delaymagic |= DM_EGID; @@ -2450,8 +2632,8 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) /* The BSDs don't show the argv[] in ps(1) output, they * show a string from the process struct and provide * the setproctitle() routine to manipulate that. */ - { - s = SvPV(sv, len); + if (PL_origalen != 1) { + 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,37 +2651,44 @@ 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(sv, len); + s = SvPV_const(sv, len); un.pst_command = (char *)s; pstat(PSTAT_SETCMD, un, len, 0, 0); } -#endif - /* PL_origalen is set in perl_parse(). */ - s = SvPV_force(sv,len); - if (len >= (STRLEN)PL_origalen-1) { - /* Longer than original, will be truncated. We assume that - * PL_origalen bytes are available. */ - Copy(s, PL_origargv[0], PL_origalen-1, char); +#else + if (PL_origalen > 1) { + /* PL_origalen is set in perl_parse(). */ + s = SvPV_force(sv,len); + if (len >= (STRLEN)PL_origalen-1) { + /* Longer than original, will be truncated. We assume that + * PL_origalen bytes are available. */ + Copy(s, PL_origargv[0], PL_origalen-1, char); + } + 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, + pad, PL_origalen - len - 1); + } + PL_origargv[0][PL_origalen-1] = 0; + for (i = 1; i < PL_origargc; i++) + PL_origargv[i] = 0; } - else { - /* Shorter than original, will be padded. */ - 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); - } - PL_origargv[0][PL_origalen-1] = 0; - for (i = 1; i < PL_origargc; i++) - PL_origargv[i] = 0; +#endif UNLOCK_DOLLARZERO_MUTEX; break; #endif @@ -2511,6 +2700,7 @@ I32 Perl_whichsig(pTHX_ const char *sig) { register char* const* sigv; + PERL_UNUSED_CONTEXT; for (sigv = (char* const*)PL_sig_name; *sigv; sigv++) if (strEQ(sig,*sigv)) @@ -2527,7 +2717,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); @@ -2535,13 +2729,13 @@ Perl_sighandler(int sig) dTHX; #endif dSP; - GV *gv = Nullgv; - HV *st; - SV *sv = Nullsv, *tSv = PL_Sv; - CV *cv = Nullcv; + GV *gv = NULL; + SV *sv = NULL; + SV * const tSv = PL_Sv; + CV *cv = NULL; 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; @@ -2560,7 +2754,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. */ @@ -2568,8 +2762,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) - cv = sv_2cv(PL_psig_ptr[sig],&st,&gv,TRUE); + || SvTYPE(cv) != SVt_PVCV) { + HV *st; + cv = sv_2cv(PL_psig_ptr[sig], &st, &gv, GV_ADD); + } if (!cv || !CvROOT(cv)) { if (ckWARN(WARN_SIGNAL)) @@ -2582,7 +2778,7 @@ Perl_sighandler(int sig) } if(PL_psig_name[sig]) { - sv = SvREFCNT_inc(PL_psig_name[sig]); + sv = SvREFCNT_inc_NN(PL_psig_name[sig]); flags |= 64; #if !defined(PERL_IMPLICIT_CONTEXT) PL_sig_sv = sv; @@ -2595,6 +2791,40 @@ 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((char *)sip, sizeof(*sip))); + } + + va_end(args); + } + } +#endif PUTBACK; call_sv((SV*)cv, G_DISCARD|G_EVAL); @@ -2617,7 +2847,7 @@ Perl_sighandler(int sig) (void)rsignal(sig, PL_csighandlerp); #endif #endif /* !PERL_MICRO */ - DieNull; + Perl_die(aTHX_ NULL); } cleanup: if (flags & 1) @@ -2637,29 +2867,38 @@ 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; + dVAR; + MGS* const mgs = SSPTR(PTR2IV(p), MGS*); + SV* const sv = mgs->mgs_sv; if (!sv) return; if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { -#ifdef PERL_COPY_ON_WRITE +#ifdef PERL_OLD_COPY_ON_WRITE /* While magic was saved (and off) sv_setsv may well have seen this SV as a prime candidate for COW. */ if (SvIsCOW(sv)) - sv_force_normal(sv); + sv_force_normal_flags(sv, 0); #endif if (mgs->mgs_flags) 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 */ + + 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 ); + } + } } mgs->mgs_sv = NULL; /* mark the MGS structure as restored */ @@ -2685,18 +2924,81 @@ 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; if (flags & 1) PL_savestack_ix -= 5; /* Unprotect save in progress. */ - /* cxstack_ix-- Not needed, die already unwound it. */ #if !defined(PERL_IMPLICIT_CONTEXT) if (flags & 64) SvREFCNT_dec(PL_sig_sv); #endif } +/* +=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. + +=cut +*/ +int +Perl_magic_sethint(pTHX_ SV *sv, MAGIC *mg) +{ + dVAR; + assert(mg->mg_len == HEf_SVKEY); + + /* 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 + it's NULL. If needed for threads, the alternative could lock a mutex, + or take other more complex action. */ + + /* Something changed in %^H, so it will need to be restored on scope exit. + 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_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + (SV *)mg->mg_ptr, sv); + return 0; +} + +/* +=for apidoc magic_sethint + +Triggered by a delete from %^H, records the key to +C. +=cut +*/ +int +Perl_magic_clearhint(pTHX_ SV *sv, MAGIC *mg) +{ + dVAR; + PERL_UNUSED_ARG(sv); + + assert(mg->mg_len == HEf_SVKEY); + + PERL_UNUSED_ARG(sv); + + PL_hints |= HINT_LOCALIZE_HH; + PL_compiling.cop_hints_hash + = Perl_refcounted_he_new(aTHX_ PL_compiling.cop_hints_hash, + (SV *)mg->mg_ptr, &PL_sv_placeholder); + return 0; +} + +/* + * Local variables: + * c-indentation-style: bsd + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + * + * ex: set ts=8 sts=4 sw=4 noet: + */