X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/c623ac675720b3145d48cc2ea9474a0f3e0cbbca..a7fce7e16a936eb048fedb9b30adc592bcb2c657:/mg.c diff --git a/mg.c b/mg.c index 523c90e..b04e24f 100644 --- a/mg.c +++ b/mg.c @@ -1,6 +1,7 @@ /* mg.c * - * Copyright (c) 1991-2002, Larry Wall + * Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, + * 2000, 2001, 2002, 2003, 2004, 2005 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. @@ -14,6 +15,24 @@ /* =head1 Magical Functions + +"Magic" is special data attached to SV structures in order to give them +"magical" properties. When any Perl code tries to read from, or assign to, +an SV marked as magical, it calls the 'get' or 'set' function associated +with that SV's magic. A get is called prior to reading an SV, in order to +give it a chance to update its internal value (get on $. writes the line +number of the last read filehandle into to the SV's IV slot), while +set is called after an SV has been written to, in order to allow it to make +use of its changed value (set on $/ copies the SV's new value to the +PL_rs global variable). + +Magic is implemented as a linked list of MAGIC structures attached to the +SV. Each MAGIC struct holds the type of the magic, a pointer to an array +of functions that implement the get(), set(), length() etc functions, +plus space for some flags and pointers. For example, a tied variable has +a MAGIC structure that contains a pointer to the object associated with the +tie. + */ #include "EXTERN.h" @@ -29,17 +48,22 @@ # endif #endif -/* if you only have signal() and it resets on each signal, FAKE_PERSISTENT_SIGNAL_HANDLERS fixes */ -#if !defined(HAS_SIGACTION) && defined(VMS) -# define FAKE_PERSISTENT_SIGNAL_HANDLERS -#endif -/* if we're doing kill() with sys$sigprc on VMS, FAKE_DEFAULT_SIGNAL_HANDLERS */ -#if defined(KILL_BY_SIGPRC) -# define FAKE_DEFAULT_SIGNAL_HANDLERS +#ifdef __hpux +# include #endif -static void restore_magic(pTHX_ void *p); -static void unwind_handler_stack(pTHX_ void *p); +Signal_t Perl_csighandler(int sig); + +static void restore_magic(pTHX_ const void *p); +static void unwind_handler_stack(pTHX_ const void *p); + +#ifdef __Lynx__ +/* Missing protos on LynxOS */ +void setruid(uid_t id); +void seteuid(uid_t id); +void setrgid(uid_t id); +void setegid(uid_t id); +#endif /* * Use the "DESTRUCTOR" scope cleanup to reinstate magic. @@ -57,6 +81,11 @@ S_save_magic(pTHX_ I32 mgs_ix, SV *sv) { MGS* mgs; assert(SvMAGICAL(sv)); +#ifdef PERL_COPY_ON_WRITE + /* Turning READONLY off for a copy-on-write scalar is a bad idea. */ + if (SvIsCOW(sv)) + sv_force_normal(sv); +#endif SAVEDESTRUCTOR_X(restore_magic, INT2PTR(void*, (IV)mgs_ix)); @@ -81,9 +110,9 @@ Turns on the magical status of an SV. See C. void Perl_mg_magical(pTHX_ SV *sv) { - MAGIC* mg; + const MAGIC* mg; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* const vtbl = mg->mg_virtual; if (vtbl) { if (vtbl->svt_get && !(mg->mg_flags & MGf_GSKIP)) SvGMAGICAL_on(sv); @@ -106,9 +135,21 @@ Do magic after a value is retrieved from the SV. See C. int Perl_mg_get(pTHX_ SV *sv) { - int new = 0; + const I32 mgs_ix = SSNEW(sizeof(MGS)); + const bool was_temp = (bool)SvTEMP(sv); + int have_new = 0; MAGIC *newmg, *head, *cur, *mg; - I32 mgs_ix = SSNEW(sizeof(MGS)); + /* guard against sv having being freed midway by holding a private + reference. */ + + /* sv_2mortal has this side effect of turning on the TEMP flag, which can + cause the SV's buffer to get stolen (and maybe other stuff). + So restore it. + */ + sv_2mortal(SvREFCNT_inc(sv)); + if (!was_temp) { + SvTEMP_off(sv); + } save_magic(mgs_ix, sv); @@ -118,10 +159,16 @@ Perl_mg_get(pTHX_ SV *sv) newmg = cur = head = mg = SvMAGIC(sv); while (mg) { - MGVTBL *vtbl = mg->mg_virtual; + const MGVTBL * const vtbl = mg->mg_virtual; if (!(mg->mg_flags & MGf_GSKIP) && vtbl && vtbl->svt_get) { CALL_FPTR(vtbl->svt_get)(aTHX_ sv, mg); + + /* guard against magic having been deleted - eg FETCH calling + * untie */ + if (!SvMAGIC(sv)) + break; + /* Don't restore the flags for this entry if it was deleted. */ if (mg->mg_flags & MGf_GSKIP) (SSPTR(mgs_ix, MGS *))->mgs_flags = 0; @@ -129,25 +176,31 @@ Perl_mg_get(pTHX_ SV *sv) mg = mg->mg_moremagic; - if (new) { + if (have_new) { /* Have we finished with the new entries we saw? Start again where we left off (unless there are more new entries). */ if (mg == head) { - new = 0; + have_new = 0; mg = cur; head = newmg; } } /* Were any new entries added? */ - if (!new && (newmg = SvMAGIC(sv)) != head) { - new = 1; + if (!have_new && (newmg = SvMAGIC(sv)) != head) { + have_new = 1; cur = mg; mg = newmg; } } restore_magic(aTHX_ INT2PTR(void *, (IV)mgs_ix)); + + if (SvREFCNT(sv) == 1) { + /* We hold the last reference to this SV, which implies that the + SV was deleted as a side effect of the routines we called. */ + SvOK_off(sv); + } return 0; } @@ -162,15 +215,14 @@ Do magic after a value is assigned to the SV. See C. int Perl_mg_set(pTHX_ SV *sv) { - I32 mgs_ix; + const I32 mgs_ix = SSNEW(sizeof(MGS)); MAGIC* mg; MAGIC* nextmg; - mgs_ix = SSNEW(sizeof(MGS)); save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = nextmg) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* vtbl = mg->mg_virtual; nextmg = mg->mg_moremagic; /* it may delete itself */ if (mg->mg_flags & MGf_GSKIP) { mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */ @@ -199,11 +251,9 @@ Perl_mg_length(pTHX_ SV *sv) STRLEN len; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL * const vtbl = mg->mg_virtual; if (vtbl && vtbl->svt_len) { - I32 mgs_ix; - - mgs_ix = SSNEW(sizeof(MGS)); + const I32 mgs_ix = SSNEW(sizeof(MGS)); save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg); @@ -212,8 +262,7 @@ Perl_mg_length(pTHX_ SV *sv) } } - if (DO_UTF8(sv)) - { + if (DO_UTF8(sv)) { U8 *s = (U8*)SvPV(sv, len); len = Perl_utf8_length(aTHX_ s, s + len); } @@ -226,14 +275,12 @@ I32 Perl_mg_size(pTHX_ SV *sv) { MAGIC* mg; - I32 len; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* const vtbl = mg->mg_virtual; if (vtbl && vtbl->svt_len) { - I32 mgs_ix; - - mgs_ix = SSNEW(sizeof(MGS)); + const I32 mgs_ix = SSNEW(sizeof(MGS)); + I32 len; save_magic(mgs_ix, sv); /* omit MGf_GSKIP -- not changed here */ len = CALL_FPTR(vtbl->svt_len)(aTHX_ sv, mg); @@ -244,8 +291,7 @@ Perl_mg_size(pTHX_ SV *sv) switch(SvTYPE(sv)) { case SVt_PVAV: - len = AvFILLp((AV *) sv); /* Fallback to non-tied array */ - return len; + return AvFILLp((AV *) sv); /* Fallback to non-tied array */ case SVt_PVHV: /* FIXME */ default: @@ -266,14 +312,13 @@ Clear something magical that the SV represents. See C. int Perl_mg_clear(pTHX_ SV *sv) { - I32 mgs_ix; + const I32 mgs_ix = SSNEW(sizeof(MGS)); MAGIC* mg; - mgs_ix = SSNEW(sizeof(MGS)); save_magic(mgs_ix, sv); for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* const vtbl = mg->mg_virtual; /* omit GSKIP -- never set here */ if (vtbl && vtbl->svt_clear) @@ -293,14 +338,14 @@ Finds the magic pointer for type matching the SV. See C. */ MAGIC* -Perl_mg_find(pTHX_ SV *sv, int type) +Perl_mg_find(pTHX_ const SV *sv, int type) { - MAGIC* mg; - if (!sv) - return 0; - for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - if (mg->mg_type == type) - return mg; + if (sv) { + MAGIC *mg; + for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { + if (mg->mg_type == type) + return mg; + } } return 0; } @@ -319,7 +364,7 @@ Perl_mg_copy(pTHX_ SV *sv, SV *nsv, const char *key, I32 klen) int count = 0; MAGIC* mg; for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* const vtbl = mg->mg_virtual; if ((mg->mg_flags & MGf_COPY) && vtbl->svt_copy){ count += CALL_FPTR(vtbl->svt_copy)(aTHX_ sv, mg, nsv, key, klen); } @@ -349,12 +394,12 @@ Perl_mg_free(pTHX_ SV *sv) MAGIC* mg; MAGIC* moremagic; for (mg = SvMAGIC(sv); mg; mg = moremagic) { - MGVTBL* vtbl = mg->mg_virtual; + const MGVTBL* const vtbl = mg->mg_virtual; moremagic = mg->mg_moremagic; if (vtbl && vtbl->svt_free) CALL_FPTR(vtbl->svt_free)(aTHX_ sv, mg); if (mg->mg_ptr && mg->mg_type != PERL_MAGIC_regex_global) { - if (mg->mg_len > 0) + if (mg->mg_len > 0 || mg->mg_type == PERL_MAGIC_utf8) Safefree(mg->mg_ptr); else if (mg->mg_len == HEf_SVKEY) SvREFCNT_dec((SV*)mg->mg_ptr); @@ -363,19 +408,17 @@ Perl_mg_free(pTHX_ SV *sv) SvREFCNT_dec(mg->mg_obj); Safefree(mg); } - SvMAGIC(sv) = 0; + SvMAGIC_set(sv, NULL); return 0; } - -#if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX) #include -#endif U32 Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) { - register REGEXP *rx; + register const REGEXP *rx; + (void)sv; if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { if (mg->mg_obj) /* @+ */ @@ -390,26 +433,25 @@ Perl_magic_regdata_cnt(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) { - register I32 paren; - register I32 s; - register I32 i; register REGEXP *rx; - I32 t; if (PL_curpm && (rx = PM_GETRE(PL_curpm))) { - paren = mg->mg_len; + register const I32 paren = mg->mg_len; + register I32 s; + register I32 t; if (paren < 0) return 0; - if (paren <= rx->nparens && + 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 && PL_reg_match_utf8) { + if (i > 0 && RX_MATCH_UTF8(rx)) { char *b = rx->subbeg; if (b) i = Perl_utf8_length(aTHX_ (U8*)b, (U8*)(b+i)); @@ -424,9 +466,14 @@ Perl_magic_regdatum_get(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_regdatum_set(pTHX_ SV *sv, MAGIC *mg) { + (void)sv; (void)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 } U32 @@ -434,7 +481,7 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) { register I32 paren; register I32 i; - register REGEXP *rx; + register const REGEXP *rx; I32 s1, t1; switch (*mg->mg_ptr) { @@ -444,13 +491,13 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) paren = atoi(mg->mg_ptr); /* $& is in [0] */ getparen: - if (paren <= rx->nparens && + if (paren <= (I32)rx->nparens && (s1 = rx->startp[paren]) != -1 && (t1 = rx->endp[paren]) != -1) { i = t1 - s1; getlen: - if (i > 0 && PL_reg_match_utf8) { + if (i > 0 && RX_MATCH_UTF8(rx)) { char *s = rx->subbeg + s1; char *send = rx->subbeg + t1; @@ -464,12 +511,12 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) } else { if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); + report_uninit(sv); } } else { if (ckWARN(WARN_UNINITIALIZED)) - report_uninit(); + report_uninit(sv); } return 0; case '+': @@ -524,8 +571,9 @@ Perl_magic_len(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) { + dVAR; register I32 paren; - register char *s; + register char *s = NULL; register I32 i; register REGEXP *rx; @@ -539,9 +587,6 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) case '\004': /* ^D */ sv_setiv(sv, (IV)(PL_debug & DEBUG_MASK)); -#if defined(YYDEBUG) && defined(DEBUGGING) - PL_yydebug = DEBUG_p_TEST; -#endif break; case '\005': /* ^E */ if (*(mg->mg_ptr+1) == '\0') { @@ -593,8 +638,12 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) SetLastError(dwErr); } #else - sv_setnv(sv, (NV)errno); - sv_setpv(sv, errno ? Strerror(errno) : ""); + { + int saveerrno = errno; + sv_setnv(sv, (NV)errno); + sv_setpv(sv, errno ? Strerror(errno) : ""); + errno = saveerrno; + } #endif #endif #endif @@ -617,8 +666,10 @@ 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 (*(mg->mg_ptr+1) == '\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); @@ -631,9 +682,9 @@ 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 (PL_lex_state != LEX_NOTPARSING) - (void)SvOK_off(sv); + SvOK_off(sv); else if (PL_in_eval) sv_setiv(sv, PL_in_eval & ~(EVAL_INREQUIRE)); else @@ -649,9 +700,17 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) #endif } else if (strEQ(mg->mg_ptr, "\024AINT")) - sv_setiv(sv, PL_tainting); + sv_setiv(sv, PL_tainting + ? (PL_taint_warn || PL_unsafe ? -1 : 1) + : 0); + break; + case '\025': /* $^UNICODE, $^UTF8LOCALE */ + if (strEQ(mg->mg_ptr, "\025NICODE")) + sv_setuv(sv, (UV) PL_unicode); + else if (strEQ(mg->mg_ptr, "\025TF8LOCALE")) + sv_setuv(sv, (UV) PL_utf8locale); break; - case '\027': /* ^W & $^WARNING_BITS & ^WIDE_SYSTEM_CALLS */ + case '\027': /* ^W & $^WARNING_BITS */ if (*(mg->mg_ptr+1) == '\0') sv_setiv(sv, (IV)((PL_dowarn & G_WARN_ON) ? TRUE : FALSE)); else if (strEQ(mg->mg_ptr+1, "ARNING_BITS")) { @@ -661,15 +720,22 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) sv_setpvn(sv, WARN_NONEstring, WARNsize) ; } else if (PL_compiling.cop_warnings == pWARN_ALL) { - sv_setpvn(sv, WARN_ALLstring, WARNsize) ; + /* 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); + } + else { + sv_setpvn(sv, WARN_ALLstring, WARNsize) ; + } } else { sv_setsv(sv, PL_compiling.cop_warnings); } SvPOK_only(sv); } - else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS")) - sv_setiv(sv, (IV)PL_widesyscalls); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '&': @@ -682,7 +748,7 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) */ paren = atoi(mg->mg_ptr); /* $& is in [0] */ getparen: - if (paren <= rx->nparens && + if (paren <= (I32)rx->nparens && (s1 = rx->startp[paren]) != -1 && (t1 = rx->endp[paren]) != -1) { @@ -693,18 +759,25 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) getrx: if (i >= 0) { - bool was_tainted = FALSE; - if (PL_tainting) { - was_tainted = PL_tainted; - PL_tainted = FALSE; - } sv_setpvn(sv, s, i); - if (PL_reg_match_utf8 && is_utf8_string((U8*)s, i)) + if (RX_MATCH_UTF8(rx) && is_utf8_string((U8*)s, i)) SvUTF8_on(sv); else SvUTF8_off(sv); - if (PL_tainting) - PL_tainted = (was_tainted || RX_MATCH_TAINTED(rx)); + 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; } } @@ -763,7 +836,8 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '^': - s = IoTOP_NAME(GvIOp(PL_defoutgv)); + if (GvIOp(PL_defoutgv)) + s = IoTOP_NAME(GvIOp(PL_defoutgv)); if (s) sv_setpv(sv,s); else { @@ -772,20 +846,24 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) } break; case '~': - s = IoFMT_NAME(GvIOp(PL_defoutgv)); + if (GvIOp(PL_defoutgv)) + s = IoFMT_NAME(GvIOp(PL_defoutgv)); if (!s) s = GvENAME(PL_defoutgv); sv_setpv(sv,s); break; #ifndef lint case '=': - sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoPAGE_LEN(GvIOp(PL_defoutgv))); break; case '-': - sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoLINES_LEFT(GvIOp(PL_defoutgv))); break; case '%': - sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv))); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)IoPAGE(GvIOp(PL_defoutgv))); break; #endif case ':': @@ -796,13 +874,14 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) WITH_THR(sv_setiv(sv, (IV)PL_curcop->cop_arybase)); break; case '|': - sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 ); + if (GvIOp(PL_defoutgv)) + sv_setiv(sv, (IV)(IoFLAGS(GvIOp(PL_defoutgv)) & IOf_FLUSH) != 0 ); break; case ',': break; case '\\': if (PL_ors_sv) - sv_setpv(sv,SvPVX(PL_ors_sv)); + sv_copypv(sv, PL_ors_sv); break; case '#': sv_setpv(sv,PL_ofmt); @@ -854,17 +933,10 @@ Perl_magic_get(pTHX_ SV *sv, MAGIC *mg) #endif (void)SvIOK_on(sv); /* what a wonderful hack! */ break; - case '*': - break; #ifndef MACOS_TRADITIONAL case '0': break; #endif -#ifdef USE_5005THREADS - case '@': - sv_setsv(sv, thr->errsv); - break; -#endif /* USE_5005THREADS */ } return 0; } @@ -882,6 +954,7 @@ Perl_magic_getuvar(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setenv(pTHX_ SV *sv, MAGIC *mg) { + dVAR; register char *s; char *ptr; STRLEN len, klen; @@ -959,6 +1032,7 @@ int Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg) { STRLEN n_a; + (void)sv; my_setenv(MgPV(mg,n_a),Nullch); return 0; } @@ -966,7 +1040,7 @@ Perl_magic_clearenv(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) { -#if defined(VMS) +#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else if (PL_localizing) { @@ -987,14 +1061,22 @@ Perl_magic_set_all_env(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) { -#if defined(VMS) || defined(EPOC) + dVAR; +#ifndef PERL_MICRO +#if defined(VMS) || defined(EPOC) || defined(SYMBIAN) Perl_die(aTHX_ "Can't make list assignment to %%ENV on this system"); #else -# if defined(PERL_IMPLICIT_SYS) || defined(WIN32) +# if defined(PERL_IMPLICIT_SYS) || defined(WIN32) PerlEnv_clearenv(); -# else -# ifdef USE_ENVIRON_ARRAY -# ifndef PERL_USE_SAFE_PUTENV +# 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) @@ -1002,27 +1084,29 @@ Perl_magic_clear_all_env(pTHX_ SV *sv, MAGIC *mg) else for (i = 0; environ[i]; i++) safesysfree(environ[i]); -# endif /* PERL_USE_SAFE_PUTENV */ + } +# endif /* PERL_USE_SAFE_PUTENV */ environ[0] = Nullch; - -# endif /* USE_ENVIRON_ARRAY */ + } +# endif /* USE_ENVIRON_ARRAY */ # endif /* PERL_IMPLICIT_SYS || WIN32 */ -#endif /* VMS || EPC */ +#endif /* VMS || EPOC */ +#endif /* !PERL_MICRO */ + (void)sv; + (void)mg; return 0; } -#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS)||defined(FAKE_DEFAULT_SIGNAL_HANDLERS) -static int sig_handlers_initted = 0; -#endif -#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS -static int sig_ignoring[SIG_SIZE]; /* which signals we are ignoring */ -#endif -#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS -static int sig_defaulting[SIG_SIZE]; -#endif - #ifndef PERL_MICRO +#ifdef HAS_SIGPROCMASK +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); +} +#endif int Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) { @@ -1030,17 +1114,17 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) STRLEN n_a; /* Are we fetching a signal entry? */ i = whichsig(MgPV(mg,n_a)); - if (i) { + if (i > 0) { if(PL_psig_ptr[i]) sv_setsv(sv,PL_psig_ptr[i]); else { Sighandler_t sigstate; sigstate = rsignal_state(i); #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - if (sig_handlers_initted && 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 (sig_handlers_initted && 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) @@ -1056,25 +1140,73 @@ Perl_magic_getsig(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_clearsig(pTHX_ SV *sv, MAGIC *mg) { - I32 i; + /* XXX Some of this code was copied from Perl_magic_setsig. A little + * refactoring might be in order. + */ + dVAR; STRLEN n_a; - /* Are we clearing a signal entry? */ - i = whichsig(MgPV(mg,n_a)); - if (i) { - if(PL_psig_ptr[i]) { - SvREFCNT_dec(PL_psig_ptr[i]); - PL_psig_ptr[i]=0; - } - if(PL_psig_name[i]) { - SvREFCNT_dec(PL_psig_name[i]); - PL_psig_name[i]=0; - } + register const char *s = MgPV(mg,n_a); + (void)sv; + if (*s == '_') { + SV** svp = 0; + if (strEQ(s,"__DIE__")) + svp = &PL_diehook; + else if (strEQ(s,"__WARN__")) + 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); + } + } + else { + I32 i; + /* Are we clearing a signal entry? */ + i = whichsig(s); + if (i > 0) { +#ifdef HAS_SIGPROCMASK + sigset_t set, save; + SV* save_sv; + /* Avoid having the signal arrive at a bad time, if possible. */ + sigemptyset(&set); + sigaddset(&set,i); + sigprocmask(SIG_BLOCK, &set, &save); + ENTER; + save_sv = newSVpv((char *)(&save), sizeof(sigset_t)); + SAVEFREESV(save_sv); + SAVEDESTRUCTOR_X(restore_sigmask, save_sv); +#endif + PERL_ASYNC_CHECK(); +#if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS) + if (!PL_sig_handlers_initted) Perl_csighandler_init(); +#endif +#ifdef FAKE_DEFAULT_SIGNAL_HANDLERS + PL_sig_defaulting[i] = 1; + (void)rsignal(i, PL_csighandlerp); +#else + (void)rsignal(i, 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]; + PL_psig_ptr[i]=0; + LEAVE; + SvREFCNT_dec(to_dec); + } + else + LEAVE; + } } return 0; } -void -Perl_raise_signal(pTHX_ int sig) +static void +S_raise_signal(pTHX_ int sig) { /* Set a flag to say this signal is pending */ PL_psig_pend[sig]++; @@ -1091,24 +1223,23 @@ Perl_csighandler(int sig) dTHX; #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - (void) rsignal(sig, &Perl_csighandler); - if (sig_ignoring[sig]) return; + (void) rsignal(sig, PL_csighandlerp); + if (PL_sig_ignoring[sig]) return; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS - if (sig_defaulting[sig]) + if (PL_sig_defaulting[sig]) #ifdef KILL_BY_SIGPRC exit((Perl_sig_to_vmscondition(sig)&STS$M_COND_ID)|STS$K_SEVERE|STS$M_INHIB_MSG); #else exit(1); #endif #endif - -#ifdef PERL_OLD_SIGNALS - /* Call the perl level handler now with risk we may be in malloc() etc. */ - (*PL_sighandlerp)(sig); -#else - Perl_raise_signal(aTHX_ sig); -#endif + if (PL_signals & PERL_SIGNALS_UNSAFE_FLAG) + /* Call the perl level handler now-- + * with risk we may be in malloc() etc. */ + (*PL_sighandlerp)(sig); + else + S_raise_signal(aTHX_ sig); } #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS) @@ -1116,19 +1247,19 @@ void Perl_csighandler_init(void) { int sig; - if (sig_handlers_initted) return; + if (PL_sig_handlers_initted) return; for (sig = 1; sig < SIG_SIZE; sig++) { #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS dTHX; - sig_defaulting[sig] = 1; - (void) rsignal(sig, &Perl_csighandler); + PL_sig_defaulting[sig] = 1; + (void) rsignal(sig, PL_csighandlerp); #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - sig_ignoring[sig] = 0; + PL_sig_ignoring[sig] = 0; #endif } - sig_handlers_initted = 1; + PL_sig_handlers_initted = 1; } #endif @@ -1139,8 +1270,11 @@ Perl_despatch_signals(pTHX) PL_sig_pending = 0; for (sig = 1; sig < SIG_SIZE; sig++) { if (PL_psig_pend[sig]) { - PL_psig_pend[sig] = 0; + PERL_BLOCKSIG_ADD(set, sig); + PL_psig_pend[sig] = 0; + PERL_BLOCKSIG_BLOCK(set); (*PL_sighandlerp)(sig); + PERL_BLOCKSIG_UNBLOCK(set); } } } @@ -1148,12 +1282,21 @@ Perl_despatch_signals(pTHX) int Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) { - register char *s; + dVAR; I32 i; SV** svp = 0; + /* 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; STRLEN len; +#ifdef HAS_SIGPROCMASK + sigset_t set, save; + SV* save_sv; +#endif - s = MgPV(mg,len); + register const char *s = MgPV(mg,len); if (*s == '_') { if (strEQ(s,"__DIE__")) svp = &PL_diehook; @@ -1163,64 +1306,78 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) Perl_croak(aTHX_ "No such hook: %s", s); i = 0; if (*svp) { - SvREFCNT_dec(*svp); + to_dec = *svp; *svp = 0; } } else { i = whichsig(s); /* ...no, a brick */ - if (!i) { + if (i < 0) { if (ckWARN(WARN_SIGNAL)) Perl_warner(aTHX_ packWARN(WARN_SIGNAL), "No such signal: SIG%s", s); return 0; } +#ifdef HAS_SIGPROCMASK + /* Avoid having the signal arrive at a bad time, if possible. */ + sigemptyset(&set); + sigaddset(&set,i); + sigprocmask(SIG_BLOCK, &set, &save); + ENTER; + save_sv = newSVpv((char *)(&save), sizeof(sigset_t)); + SAVEFREESV(save_sv); + SAVEDESTRUCTOR_X(restore_sigmask, save_sv); +#endif + PERL_ASYNC_CHECK(); #if defined(FAKE_PERSISTENT_SIGNAL_HANDLERS) || defined(FAKE_DEFAULT_SIGNAL_HANDLERS) - if (!sig_handlers_initted) Perl_csighandler_init(); + if (!PL_sig_handlers_initted) Perl_csighandler_init(); #endif #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - sig_ignoring[i] = 0; + PL_sig_ignoring[i] = 0; #endif #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS - sig_defaulting[i] = 0; + PL_sig_defaulting[i] = 0; #endif SvREFCNT_dec(PL_psig_name[i]); - SvREFCNT_dec(PL_psig_ptr[i]); + to_dec = PL_psig_ptr[i]; PL_psig_ptr[i] = SvREFCNT_inc(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]); } if (SvTYPE(sv) == SVt_PVGV || SvROK(sv)) { - if (i) - (void)rsignal(i, &Perl_csighandler); + if (i) { + (void)rsignal(i, PL_csighandlerp); +#ifdef HAS_SIGPROCMASK + LEAVE; +#endif + } else *svp = SvREFCNT_inc(sv); + if(to_dec) + SvREFCNT_dec(to_dec); return 0; } s = SvPV_force(sv,len); if (strEQ(s,"IGNORE")) { if (i) { #ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS - sig_ignoring[i] = 1; - (void)rsignal(i, &Perl_csighandler); + PL_sig_ignoring[i] = 1; + (void)rsignal(i, PL_csighandlerp); #else (void)rsignal(i, SIG_IGN); #endif - } else - *svp = 0; + } } else if (strEQ(s,"DEFAULT") || !*s) { if (i) #ifdef FAKE_DEFAULT_SIGNAL_HANDLERS { - sig_defaulting[i] = 1; - (void)rsignal(i, &Perl_csighandler); + PL_sig_defaulting[i] = 1; + (void)rsignal(i, PL_csighandlerp); } #else (void)rsignal(i, SIG_DFL); #endif - else - *svp = 0; } else { /* @@ -1231,10 +1388,16 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) if (!strchr(s,':') && !strchr(s,'\'')) sv_insert(sv, 0, 0, "main::", 6); if (i) - (void)rsignal(i, &Perl_csighandler); + (void)rsignal(i, PL_csighandlerp); else *svp = SvREFCNT_inc(sv); } +#ifdef HAS_SIGPROCMASK + if(i) + LEAVE; +#endif + if(to_dec) + SvREFCNT_dec(to_dec); return 0; } #endif /* !PERL_MICRO */ @@ -1242,6 +1405,8 @@ Perl_magic_setsig(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) { + (void)sv; + (void)mg; PL_sub_generation++; return 0; } @@ -1249,6 +1414,8 @@ Perl_magic_setisa(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) { + (void)sv; + (void)mg; /* HV_badAMAGIC_on(Sv_STASH(sv)); */ PL_amagic_generation++; @@ -1258,8 +1425,9 @@ Perl_magic_setamagic(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) { - HV *hv = (HV*)LvTARG(sv); + HV * const hv = (HV*)LvTARG(sv); I32 i = 0; + (void)mg; if (hv) { (void) hv_iterinit(hv); @@ -1278,6 +1446,7 @@ Perl_magic_getnkeys(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) { + (void)mg; if (LvTARG(sv)) { hv_ksplit((HV*)LvTARG(sv), SvIV(sv)); } @@ -1286,7 +1455,7 @@ Perl_magic_setnkeys(pTHX_ SV *sv, MAGIC *mg) /* caller is responsible for stack switching/cleanup */ STATIC int -S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val) +S_magic_methcall(pTHX_ SV *sv, const MAGIC *mg, const char *meth, I32 flags, int n, SV *val) { dSP; @@ -1313,9 +1482,9 @@ S_magic_methcall(pTHX_ SV *sv, MAGIC *mg, char *meth, I32 flags, int n, SV *val) } STATIC int -S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth) +S_magic_methpack(pTHX_ SV *sv, const MAGIC *mg, const char *meth) { - dSP; + dVAR; dSP; ENTER; SAVETMPS; @@ -1334,16 +1503,16 @@ S_magic_methpack(pTHX_ SV *sv, MAGIC *mg, char *meth) int Perl_magic_getpack(pTHX_ SV *sv, MAGIC *mg) { - magic_methpack(sv,mg,"FETCH"); if (mg->mg_ptr) mg->mg_flags |= MGf_GSKIP; + magic_methpack(sv,mg,"FETCH"); return 0; } int Perl_magic_setpack(pTHX_ SV *sv, MAGIC *mg) { - dSP; + dVAR; dSP; ENTER; PUSHSTACKi(PERLSI_MAGIC); magic_methcall(sv, mg, "STORE", G_SCALAR|G_DISCARD, 3, sv); @@ -1362,7 +1531,7 @@ Perl_magic_clearpack(pTHX_ SV *sv, MAGIC *mg) U32 Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg) { - dSP; + dVAR; dSP; U32 retval = 0; ENTER; @@ -1381,7 +1550,7 @@ Perl_magic_sizepack(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg) { - dSP; + dVAR; dSP; ENTER; PUSHSTACKi(PERLSI_MAGIC); @@ -1391,14 +1560,15 @@ Perl_magic_wipepack(pTHX_ SV *sv, MAGIC *mg) call_method("CLEAR", G_SCALAR|G_DISCARD); POPSTACK; LEAVE; + return 0; } int Perl_magic_nextpack(pTHX_ SV *sv, MAGIC *mg, SV *key) { - dSP; - const char *meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY"; + dVAR; dSP; + const char * const meth = SvOK(key) ? "NEXTKEY" : "FIRSTKEY"; ENTER; SAVETMPS; @@ -1425,6 +1595,41 @@ Perl_magic_existspack(pTHX_ SV *sv, MAGIC *mg) return magic_methpack(sv,mg,"EXISTS"); } +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)); + + if (!gv_fetchmethod_autoload(pkg, "SCALAR", FALSE)) { + SV *key; + if (HvEITER(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 */ + return SvOK(key) ? &PL_sv_yes : &PL_sv_no; + } + + /* there is a SCALAR method that we can call */ + ENTER; + PUSHSTACKi(PERLSI_MAGIC); + PUSHMARK(SP); + EXTEND(SP, 1); + PUSHs(tied); + PUTBACK; + + if (call_method("SCALAR", G_SCALAR)) + retval = *PL_stack_sp--; + POPSTACK; + LEAVE; + return retval; +} + int Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) { @@ -1438,8 +1643,13 @@ Perl_magic_setdbline(pTHX_ SV *sv, MAGIC *mg) i = SvTRUE(sv); svp = av_fetch(GvAV(gv), atoi(MgPV(mg,n_a)), FALSE); - if (svp && SvIOKp(*svp) && (o = INT2PTR(OP*,SvIVX(*svp)))) - o->op_private = i; + 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; + } return 0; } @@ -1472,7 +1682,7 @@ Perl_magic_getpos(pTHX_ SV *sv, MAGIC *mg) return 0; } } - (void)SvOK_off(sv); + SvOK_off(sv); return 0; } @@ -1513,7 +1723,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) if (pos < 0) pos = 0; } - else if (pos > len) + else if (pos > (SSize_t)len) pos = len; if (ulen) { @@ -1531,6 +1741,7 @@ Perl_magic_setpos(pTHX_ SV *sv, MAGIC *mg) 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), "*"); @@ -1544,16 +1755,12 @@ Perl_magic_getglob(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setglob(pTHX_ SV *sv, MAGIC *mg) { - register char *s; GV* gv; - STRLEN n_a; - + (void)mg; + if (!SvOK(sv)) return 0; - s = SvPV(sv, n_a); - if (*s == '*' && s[1]) - s++; - gv = gv_fetchpv(s,TRUE, SVt_PVGV); + gv = gv_fetchsv(sv,TRUE, SVt_PVGV); if (sv == (SV*)gv) return 0; if (GvGP(sv)) @@ -1566,16 +1773,17 @@ int Perl_magic_getsubstr(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; - SV *lsv = LvTARG(sv); - char *tmps = SvPV(lsv,len); + SV * const lsv = LvTARG(sv); + const char * const tmps = SvPV(lsv,len); I32 offs = LvTARGOFF(sv); I32 rem = LvTARGLEN(sv); + (void)mg; if (SvUTF8(lsv)) sv_pos_u2b(lsv, &offs, &rem); - if (offs > len) + if (offs > (I32)len) offs = len; - if (rem + offs > len) + if (rem + offs > (I32)len) rem = len - offs; sv_setpvn(sv, tmps + offs, (STRLEN)rem); if (SvUTF8(lsv)) @@ -1588,24 +1796,30 @@ Perl_magic_setsubstr(pTHX_ SV *sv, MAGIC *mg) { STRLEN len; char *tmps = SvPV(sv, len); - SV *lsv = LvTARG(sv); + SV * const lsv = LvTARG(sv); I32 lvoff = LvTARGOFF(sv); I32 lvlen = LvTARGLEN(sv); + (void)mg; if (DO_UTF8(sv)) { sv_utf8_upgrade(lsv); sv_pos_u2b(lsv, &lvoff, &lvlen); sv_insert(lsv, lvoff, lvlen, tmps, len); + LvTARGLEN(sv) = sv_len_utf8(sv); SvUTF8_on(lsv); } else if (lsv && SvUTF8(lsv)) { 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); } - else - sv_insert(lsv, lvoff, lvlen, tmps, len); + else { + sv_insert(lsv, lvoff, lvlen, tmps, len); + LvTARGLEN(sv) = len; + } + return 0; } @@ -1621,6 +1835,7 @@ Perl_magic_gettaint(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) { + (void)sv; if (PL_localizing) { if (PL_localizing == 1) mg->mg_len <<= 1; @@ -1637,10 +1852,11 @@ Perl_magic_settaint(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) { - SV *lsv = LvTARG(sv); + SV * const lsv = LvTARG(sv); + (void)mg; if (!lsv) { - (void)SvOK_off(sv); + SvOK_off(sv); return 0; } @@ -1651,6 +1867,7 @@ Perl_magic_getvec(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setvec(pTHX_ SV *sv, MAGIC *mg) { + (void)mg; do_vecset(sv); /* XXX slurp this routine */ return 0; } @@ -1662,16 +1879,9 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) if (LvTARGLEN(sv)) { if (mg->mg_obj) { SV *ahv = LvTARG(sv); - if (SvTYPE(ahv) == SVt_PVHV) { - HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0); - if (he) - targ = HeVAL(he); - } - else { - SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, FALSE, 0); - if (svp) - targ = *svp; - } + HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, FALSE, 0); + if (he) + targ = HeVAL(he); } else { AV* av = (AV*)LvTARG(sv); @@ -1697,6 +1907,7 @@ Perl_magic_getdefelem(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setdefelem(pTHX_ SV *sv, MAGIC *mg) { + (void)mg; if (LvTARGLEN(sv)) vivify_defelem(sv); if (LvTARG(sv)) { @@ -1717,16 +1928,9 @@ Perl_vivify_defelem(pTHX_ SV *sv) if (mg->mg_obj) { SV *ahv = LvTARG(sv); STRLEN n_a; - if (SvTYPE(ahv) == SVt_PVHV) { - HE *he = hv_fetch_ent((HV*)ahv, mg->mg_obj, TRUE, 0); - if (he) - value = HeVAL(he); - } - else { - SV **svp = avhv_fetch_ent((AV*)ahv, mg->mg_obj, TRUE, 0); - if (svp) - value = *svp; - } + HE *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)); } @@ -1755,18 +1959,21 @@ 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] && svp[i] != &PL_sv_undef) { + if (svp[i]) { if (!SvWEAKREF(svp[i])) Perl_croak(aTHX_ "panic: magic_killbackrefs"); /* XXX Should we check that it hasn't changed? */ - SvRV(svp[i]) = 0; - (void)SvOK_off(svp[i]); + SvRV_set(svp[i], 0); + SvOK_off(svp[i]); SvWEAKREF_off(svp[i]); - svp[i] = &PL_sv_undef; + svp[i] = Nullsv; } i--; } + SvREFCNT_dec(av); /* remove extra count added by sv_add_backref() */ return 0; } @@ -1781,6 +1988,7 @@ Perl_magic_setmglob(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg) { + (void)mg; sv_unmagic(sv, PERL_MAGIC_bm); SvVALID_off(sv); return 0; @@ -1789,6 +1997,7 @@ Perl_magic_setbm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg) { + (void)mg; sv_unmagic(sv, PERL_MAGIC_fm); SvCOMPILED_off(sv); return 0; @@ -1797,7 +2006,7 @@ Perl_magic_setfm(pTHX_ SV *sv, MAGIC *mg) int Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg) { - struct ufuncs *uf = (struct ufuncs *)mg->mg_ptr; + const struct ufuncs * const uf = (struct ufuncs *)mg->mg_ptr; if (uf && uf->uf_set) (*uf->uf_set)(aTHX_ uf->uf_index, sv); @@ -1805,10 +2014,19 @@ Perl_magic_setuvar(pTHX_ SV *sv, MAGIC *mg) } int +Perl_magic_setregexp(pTHX_ SV *sv, MAGIC *mg) +{ + (void)mg; + sv_unmagic(sv, PERL_MAGIC_qr); + return 0; +} + +int Perl_magic_freeregexp(pTHX_ SV *sv, MAGIC *mg) { regexp *re = (regexp *)mg->mg_obj; ReREFCNT_dec(re); + (void)sv; return 0; } @@ -1820,6 +2038,7 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) * RenE Descartes said "I think not." * and vanished with a faint plop. */ + (void)sv; if (mg->mg_ptr) { Safefree(mg->mg_ptr); mg->mg_ptr = NULL; @@ -1829,10 +2048,21 @@ Perl_magic_setcollxfrm(pTHX_ SV *sv, MAGIC *mg) } #endif /* USE_LOCALE_COLLATE */ +/* Just clear the UTF-8 cache data. */ +int +Perl_magic_setutf8(pTHX_ SV *sv, MAGIC *mg) +{ + (void)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. */ + return 0; +} + int Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) { - register char *s; + register const char *s; I32 i; STRLEN len; switch (*mg->mg_ptr) { @@ -1840,40 +2070,50 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) sv_setsv(PL_bodytarget, sv); break; case '\003': /* ^C */ - PL_minus_c = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + PL_minus_c = (bool)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); break; case '\004': /* ^D */ - PL_debug = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)) | DEBUG_TOP_FLAG; +#ifdef DEBUGGING + s = SvPV_nolen(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; +#endif break; case '\005': /* ^E */ - if (*(mg->mg_ptr+1) == '\0') { + if (*(mg->mg_ptr+1) == '\0') { #ifdef MACOS_TRADITIONAL - gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); + gMacPerl_OSErr = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); #else # ifdef VMS - set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + set_vaxc_errno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); # else # ifdef WIN32 - SetLastError( SvIV(sv) ); + SetLastError( SvIV(sv) ); # else # ifdef OS2 - os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); + os2_setsyserrno(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); # else - /* will anyone ever use this? */ - SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4); + /* will anyone ever use this? */ + SETERRNO(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv), 4); # endif # endif # endif #endif - } - else if (strEQ(mg->mg_ptr+1, "NCODING")) { - if (PL_encoding) - sv_setsv(PL_encoding, sv); - else - PL_encoding = newSVsv(sv); - } + } + else if (strEQ(mg->mg_ptr+1, "NCODING")) { + if (PL_encoding) + SvREFCNT_dec(PL_encoding); + if (SvOK(sv) || SvGMAGICAL(sv)) { + PL_encoding = newSVsv(sv); + } + else { + PL_encoding = Nullsv; + } + } + break; case '\006': /* ^F */ PL_maxsysfd = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); break; @@ -1884,18 +2124,20 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) if (PL_inplace) Safefree(PL_inplace); if (SvOK(sv)) - PL_inplace = savepv(SvPV(sv,len)); + PL_inplace = savesvpv(sv); else PL_inplace = Nullch; break; case '\017': /* ^O */ if (*(mg->mg_ptr+1) == '\0') { - if (PL_osname) + if (PL_osname) { Safefree(PL_osname); - if (SvOK(sv)) - PL_osname = savepv(SvPV(sv,len)); - else PL_osname = Nullch; + } + if (SvOK(sv)) { + TAINT_PROPER("assigning to $^O"); + PL_osname = savesvpv(sv); + } } else if (strEQ(mg->mg_ptr, "\017PEN")) { if (!PL_compiling.cop_io) @@ -1916,7 +2158,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) PL_basetime = (Time_t)(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); #endif break; - case '\027': /* ^W & $^WARNING_BITS & ^WIDE_SYSTEM_CALLS */ + 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); @@ -1935,7 +2177,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) STRLEN len, i; int accumulate = 0 ; int any_fatals = 0 ; - char * ptr = (char*)SvPV(sv, len) ; + const char * const ptr = (char*)SvPV(sv, len) ; for (i = 0 ; i < len ; ++i) { accumulate |= ptr[i] ; any_fatals |= (ptr[i] & 0xAA) ; @@ -1958,8 +2200,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } } } - else if (strEQ(mg->mg_ptr+1, "IDE_SYSTEM_CALLS")) - PL_widesyscalls = SvTRUE(sv); break; case '.': if (PL_localizing) { @@ -1971,13 +2211,13 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; case '^': Safefree(IoTOP_NAME(GvIOp(PL_defoutgv))); - IoTOP_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len)); - IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO); + s = IoTOP_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); + IoTOP_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO); break; case '~': Safefree(IoFMT_NAME(GvIOp(PL_defoutgv))); - IoFMT_NAME(GvIOp(PL_defoutgv)) = s = savepv(SvPV(sv,len)); - IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchpv(s,TRUE, SVt_PVIO); + s = IoFMT_NAME(GvIOp(PL_defoutgv)) = savesvpv(sv); + IoFMT_GV(GvIOp(PL_defoutgv)) = gv_fetchsv(sv,TRUE, SVt_PVIO); break; case '=': IoPAGE_LEN(GvIOp(PL_defoutgv)) = (SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); @@ -2007,10 +2247,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) } } break; - case '*': - i = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); - PL_multiline = (i != 0); - break; case '/': SvREFCNT_dec(PL_rs); PL_rs = newSVsv(sv); @@ -2038,7 +2274,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case '#': if (PL_ofmt) Safefree(PL_ofmt); - PL_ofmt = savepv(SvPV(sv,len)); + PL_ofmt = savesvpv(sv); break; case '[': PL_compiling.cop_arybase = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); @@ -2059,8 +2295,15 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) STATUS_POSIX_SET(SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv)); break; case '!': + { +#ifdef VMS +# define PERL_VMS_BANG vaxc$errno +#else +# define PERL_VMS_BANG 0 +#endif SETERRNO(SvIOK(sv) ? SvIVX(sv) : SvOK(sv) ? sv_2iv(sv) : 0, - (SvIV(sv) == EVMSERR) ? 4 : vaxc$errno); + (SvIV(sv) == EVMSERR) ? 4 : PERL_VMS_BANG); + } break; case '<': PL_uid = SvIOK(sv) ? SvIVX(sv) : sv_2iv(sv); @@ -2077,9 +2320,14 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) #ifdef HAS_SETRESUID (void)setresuid((Uid_t)PL_uid, (Uid_t)-1, (Uid_t)-1); #else - if (PL_uid == PL_euid) /* special case $< = $> */ + if (PL_uid == PL_euid) { /* special case $< = $> */ +#ifdef PERL_DARWIN + /* workaround for Darwin's setuid peculiarity, cf [perl #24122] */ + if (PL_uid != 0 && PerlProc_getuid() == 0) + (void)PerlProc_setuid(0); +#endif (void)PerlProc_setuid(PL_uid); - else { + } else { PL_uid = PerlProc_getuid(); Perl_croak(aTHX_ "setruid() not implemented"); } @@ -2146,7 +2394,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) case ')': #ifdef HAS_SETGROUPS { - char *p = SvPV(sv, len); + const char *p = SvPV(sv, len); Groups_t gary[NGROUPS]; while (isSPACE(*p)) @@ -2197,6 +2445,7 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) break; #ifndef MACOS_TRADITIONAL case '0': + LOCK_DOLLARZERO_MUTEX; #ifdef HAS_SETPROCTITLE /* The BSDs don't show the argv[] in ps(1) output, they * show a string from the process struct and provide @@ -2221,91 +2470,51 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg) # endif } #endif - if (!PL_origalen) { - s = PL_origargv[0]; - s += strlen(s); - /* See if all the arguments are contiguous in memory */ - for (i = 1; i < PL_origargc; i++) { - if (PL_origargv[i] == s + 1 -#ifdef OS2 - || PL_origargv[i] == s + 2 -#endif - ) - { - ++s; - s += strlen(s); /* this one is ok too */ - } - else - break; - } - /* can grab env area too? */ - if (PL_origenviron && (PL_origenviron[0] == s + 1)) { - my_setenv("NoNe SuCh", Nullch); - /* force copy of environment */ - for (i = 0; PL_origenviron[i]; i++) - if (PL_origenviron[i] == s + 1) { - ++s; - s += strlen(s); - } - else - break; - } - PL_origalen = s - PL_origargv[0]; +#if defined(__hpux) && defined(PSTAT_SETCMD) + { + union pstun un; + s = SvPV(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); - i = len; - if (i >= PL_origalen) { - i = PL_origalen; - /* don't allow system to limit $0 seen by script */ - /* SvCUR_set(sv, i); *SvEND(sv) = '\0'; */ - Copy(s, PL_origargv[0], i, char); - s = PL_origargv[0]+i; - *s = '\0'; + 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 { - Copy(s, PL_origargv[0], i, char); - s = PL_origargv[0]+i; - *s++ = '\0'; - while (++i < PL_origalen) - *s++ = ' '; - s = PL_origargv[0]+i; - for (i = 1; i < PL_origargc; i++) - PL_origargv[i] = Nullch; - } + /* 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; + UNLOCK_DOLLARZERO_MUTEX; break; #endif -#ifdef USE_5005THREADS - case '@': - sv_setsv(thr->errsv, sv); - break; -#endif /* USE_5005THREADS */ } return 0; } -#ifdef USE_5005THREADS -int -Perl_magic_mutexfree(pTHX_ SV *sv, MAGIC *mg) -{ - DEBUG_S(PerlIO_printf(Perl_debug_log, - "0x%"UVxf": magic_mutexfree 0x%"UVxf"\n", - PTR2UV(thr), PTR2UV(sv))); - if (MgOWNER(mg)) - Perl_croak(aTHX_ "panic: magic_mutexfree"); - MUTEX_DESTROY(MgMUTEXP(mg)); - COND_DESTROY(MgCONDP(mg)); - return 0; -} -#endif /* USE_5005THREADS */ - I32 -Perl_whichsig(pTHX_ char *sig) +Perl_whichsig(pTHX_ const char *sig) { - register char **sigv; + register char* const* sigv; - for (sigv = PL_sig_name+1; *sigv; sigv++) + for (sigv = (char* const*)PL_sig_name; *sigv; sigv++) if (strEQ(sig,*sigv)) - return PL_sig_num[sigv - PL_sig_name]; + return PL_sig_num[sigv - (char* const*)PL_sig_name]; #ifdef SIGCLD if (strEQ(sig,"CHLD")) return SIGCLD; @@ -2314,13 +2523,9 @@ Perl_whichsig(pTHX_ char *sig) if (strEQ(sig,"CLD")) return SIGCHLD; #endif - return 0; + return -1; } -#if !defined(PERL_IMPLICIT_CONTEXT) -static SV* sig_sv; -#endif - Signal_t Perl_sighandler(int sig) { @@ -2342,8 +2547,6 @@ Perl_sighandler(int sig) flags |= 1; if (PL_markstack_ptr < PL_markstack_max - 2) flags |= 4; - if (PL_retstack_ix < PL_retstack_max - 2) - flags |= 8; if (PL_scopestack_ix < PL_scopestack_max - 3) flags |= 16; @@ -2361,10 +2564,6 @@ Perl_sighandler(int sig) } if (flags & 4) PL_markstack_ptr++; /* Protect mark. */ - if (flags & 8) { - PL_retstack_ix++; - PL_retstack[PL_retstack_ix] = NULL; - } if (flags & 16) PL_scopestack_ix += 1; /* sv_2cv is too complicated, try a simpler variant first: */ @@ -2386,7 +2585,7 @@ Perl_sighandler(int sig) sv = SvREFCNT_inc(PL_psig_name[sig]); flags |= 64; #if !defined(PERL_IMPLICIT_CONTEXT) - sig_sv = sv; + PL_sig_sv = sv; #endif } else { sv = sv_newmortal(); @@ -2415,18 +2614,16 @@ Perl_sighandler(int sig) #else /* Not clear if this will work */ (void)rsignal(sig, SIG_IGN); - (void)rsignal(sig, &Perl_csighandler); + (void)rsignal(sig, PL_csighandlerp); #endif #endif /* !PERL_MICRO */ - Perl_die(aTHX_ Nullformat); + DieNull; } cleanup: if (flags & 1) PL_savestack_ix -= 8; /* Unprotect save in progress. */ if (flags & 4) PL_markstack_ptr--; - if (flags & 8) - PL_retstack_ix--; if (flags & 16) PL_scopestack_ix -= 1; if (flags & 64) @@ -2440,7 +2637,7 @@ cleanup: static void -restore_magic(pTHX_ void *p) +restore_magic(pTHX_ const void *p) { MGS* mgs = SSPTR(PTR2IV(p), MGS*); SV* sv = mgs->mgs_sv; @@ -2450,6 +2647,13 @@ restore_magic(pTHX_ void *p) if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) { +#ifdef PERL_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); +#endif + if (mgs->mgs_flags) SvFLAGS(sv) |= mgs->mgs_flags; else @@ -2481,16 +2685,17 @@ restore_magic(pTHX_ void *p) } static void -unwind_handler_stack(pTHX_ void *p) +unwind_handler_stack(pTHX_ const void *p) { - U32 flags = *(U32*)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(sig_sv); + SvREFCNT_dec(PL_sig_sv); #endif }