struct magic_state {
SV* mgs_sv;
I32 mgs_ss_ix;
- U32 mgs_magical;
- bool mgs_readonly;
+ U32 mgs_flags;
bool mgs_bumped;
};
/* MGS is typedef'ed to struct magic_state in perl.h */
mgs = SSPTR(mgs_ix, MGS*);
mgs->mgs_sv = sv;
- mgs->mgs_magical = SvMAGICAL(sv);
- mgs->mgs_readonly = SvREADONLY(sv) != 0;
+ mgs->mgs_flags = SvMAGICAL(sv) | SvREADONLY(sv);
mgs->mgs_ss_ix = PL_savestack_ix; /* points after the saved destructor */
mgs->mgs_bumped = bumped;
/* guard against magic having been deleted - eg FETCH calling
* untie */
if (!SvMAGIC(sv)) {
- (SSPTR(mgs_ix, MGS *))->mgs_magical = 0; /* recalculate flags */
+ /* recalculate flags */
+ (SSPTR(mgs_ix, MGS *))->mgs_flags &= ~(SVs_GMG|SVs_SMG|SVs_RMG);
break;
}
/* recalculate flags if this entry was deleted. */
if (mg->mg_flags & MGf_GSKIP)
- (SSPTR(mgs_ix, MGS *))->mgs_magical = 0;
+ (SSPTR(mgs_ix, MGS *))->mgs_flags &=
+ ~(SVs_GMG|SVs_SMG|SVs_RMG);
}
else if (vtbl == &PL_vtbl_utf8) {
/* get-magic can reallocate the PV */
have_new = 1;
cur = mg;
mg = newmg;
- (SSPTR(mgs_ix, MGS *))->mgs_magical = 0; /* recalculate flags */
+ /* recalculate flags */
+ (SSPTR(mgs_ix, MGS *))->mgs_flags &= ~(SVs_GMG|SVs_SMG|SVs_RMG);
}
}
nextmg = mg->mg_moremagic; /* it may delete itself */
if (mg->mg_flags & MGf_GSKIP) {
mg->mg_flags &= ~MGf_GSKIP; /* setting requires another read */
- (SSPTR(mgs_ix, MGS*))->mgs_magical = 0;
+ (SSPTR(mgs_ix, MGS*))->mgs_flags &= ~(SVs_GMG|SVs_SMG|SVs_RMG);
}
if (PL_localizing == 2
&& PERL_MAGIC_TYPE_IS_VALUE_MAGIC(mg->mg_type))
if (sv) {
MAGIC *mg;
- assert(!(SvTYPE(sv) == SVt_PVAV && AvPAD_NAMELIST(sv)));
-
for (mg = SvMAGIC(sv); mg; mg = mg->mg_moremagic) {
if (mg->mg_type == type && (!flags || mg->mg_virtual == vtbl)) {
return mg;
* case we should turn on that flag. This didn't use to happen, and to
* avoid as many possible backward compatibility issues as possible, we
* don't turn on the flag unless we have to. So the flag stays off for
- * an entirely ASCII string. We assume that if the string looks like
- * UTF-8, it really is UTF-8: "text in any other encoding that uses
- * bytes with the high bit set is extremely unlikely to pass a UTF-8
- * validity test" (http://en.wikipedia.org/wiki/Charset_detection).
- * There is a potential that we will get it wrong however, especially
- * on short error message text. (If it turns out to be necessary, we
- * could also keep track if the current LC_MESSAGES locale is UTF-8) */
+ * an entirely invariant string. We assume that if the string looks
+ * like UTF-8, it really is UTF-8: "text in any other encoding that
+ * uses bytes with the high bit set is extremely unlikely to pass a
+ * UTF-8 validity test"
+ * (http://en.wikipedia.org/wiki/Charset_detection). There is a
+ * potential that we will get it wrong however, especially on short
+ * error message text. (If it turns out to be necessary, we could also
+ * keep track if the current LC_MESSAGES locale is UTF-8) */
if (! IN_BYTES /* respect 'use bytes' */
- && ! is_ascii_string((U8*) SvPVX_const(sv), SvCUR(sv))
+ && ! is_invariant_string((U8*) SvPVX_const(sv), SvCUR(sv))
&& is_utf8_string((U8*) SvPVX_const(sv), SvCUR(sv)))
{
SvUTF8_on(sv);
}
}
+SV*
+Perl__get_encoding(pTHX)
+{
+ /* For core Perl use only: Returns the $^ENCODING or 'use encoding' in
+ * effect; NULL if none.
+ *
+ * $^ENCODING maps to PL_encoding, and is the old way to do things, and is
+ * retained for backwards compatibility. Now, there is a shadow variable
+ * ${^E_NCODING} set only by the encoding pragma, used to give this pragma
+ * lexical scope, unlike the global scope it (shudder) used to have. This
+ * variable maps to PL_lex_encoding. Again for backwards compatibility,
+ * PL_encoding has precedence over PL_lex_encoding. The hints hash is used
+ * to determine if PL_lex_encoding is in scope, and hence valid. The hints
+ * hash only accepts simple values, so we can't put an Encode object into
+ * it, so we put the object into the global, and put a simple boolean into
+ * the hints hash giving whether the global is valid or not */
+
+ dVAR;
+ SV *is_encoding;
+
+ if (PL_encoding) {
+ return PL_encoding;
+ }
+
+ if (! PL_lex_encoding) {
+ return NULL;
+ }
+
+ is_encoding = cop_hints_fetch_pvs(PL_curcop, "encoding", 0);
+ if ( is_encoding
+ && is_encoding != &PL_sv_placeholder
+ && SvIOK(is_encoding)
+ && SvIV(is_encoding)) /* non-zero mean valid */
+ {
+ return PL_lex_encoding;
+ }
+
+ return NULL;
+}
+
#ifdef VMS
#include <descrip.h>
#include <starlet.h>
case '\005': /* ^E */
if (nextchar != '\0') {
if (strEQ(remaining, "NCODING"))
- sv_setsv(sv, PL_encoding);
+ sv_setsv(sv, _get_encoding());
+ else if (strEQ(remaining, "_NCODING"))
+ sv_setsv(sv, NULL);
break;
}
#else
dTHX;
#endif
+#if defined(HAS_SIGACTION) && defined(SA_SIGINFO)
#if defined(__cplusplus) && defined(__GNUC__)
/* g++ doesn't support PERL_UNUSED_DECL, so the sip and uap
* parameters would be warned about. */
PERL_UNUSED_ARG(sip);
PERL_UNUSED_ARG(uap);
#endif
+#endif
#ifdef FAKE_PERSISTENT_SIGNAL_HANDLERS
(void) rsignal(sig, PL_csighandlerp);
if (PL_sig_ignoring[sig]) return;
if (flags & G_WRITING_TO_STDERR) {
SAVETMPS;
- save_re_context();
SAVESPTR(PL_stderrgv);
PL_stderrgv = NULL;
}
}
int
+Perl_magic_setlvref(pTHX_ SV *sv, MAGIC *mg)
+{
+ const char *bad = NULL;
+ PERL_ARGS_ASSERT_MAGIC_SETLVREF;
+ if (!SvROK(sv)) Perl_croak(aTHX_ "Assigned value is not a reference");
+ switch (mg->mg_private & OPpLVREF_TYPE) {
+ case OPpLVREF_SV:
+ if (SvTYPE(SvRV(sv)) > SVt_PVLV)
+ bad = " SCALAR";
+ break;
+ case OPpLVREF_AV:
+ if (SvTYPE(SvRV(sv)) != SVt_PVAV)
+ bad = "n ARRAY";
+ break;
+ case OPpLVREF_HV:
+ if (SvTYPE(SvRV(sv)) != SVt_PVHV)
+ bad = " HASH";
+ break;
+ case OPpLVREF_CV:
+ if (SvTYPE(SvRV(sv)) != SVt_PVCV)
+ bad = " CODE";
+ }
+ if (bad)
+ /* diag_listed_as: Assigned value is not %s reference */
+ Perl_croak(aTHX_ "Assigned value is not a%s reference", bad);
+ switch (mg->mg_obj ? SvTYPE(mg->mg_obj) : 0) {
+ case 0:
+ {
+ SV * const old = PAD_SV(mg->mg_len);
+ PAD_SETSV(mg->mg_len, SvREFCNT_inc_NN(SvRV(sv)));
+ SvREFCNT_dec(old);
+ break;
+ }
+ case SVt_PVGV:
+ gv_setref(mg->mg_obj, sv);
+ SvSETMAGIC(mg->mg_obj);
+ break;
+ case SVt_PVAV:
+ av_store((AV *)mg->mg_obj, SvIV((SV *)mg->mg_ptr),
+ SvREFCNT_inc_simple_NN(SvRV(sv)));
+ break;
+ case SVt_PVHV:
+ (void)hv_store_ent((HV *)mg->mg_obj, (SV *)mg->mg_ptr,
+ SvREFCNT_inc_simple_NN(SvRV(sv)), 0);
+ }
+ if (mg->mg_flags & MGf_PERSIST)
+ NOOP; /* This sv is in use as an iterator var and will be reused,
+ so we must leave the magic. */
+ else
+ /* This sv could be returned by the assignment op, so clear the
+ magic, as lvrefs are an implementation detail that must not be
+ leaked to the user. */
+ sv_unmagic(sv, PERL_MAGIC_lvref);
+ return 0;
+}
+
+int
Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
{
#ifdef USE_ITHREADS
# endif
#endif
}
- else if (strEQ(mg->mg_ptr+1, "NCODING")) {
- SvREFCNT_dec(PL_encoding);
- if (SvOK(sv) || SvGMAGICAL(sv)) {
- PL_encoding = newSVsv(sv);
- }
- else {
- PL_encoding = NULL;
- }
- }
+ else {
+ unsigned int offset = 1;
+ bool lex = FALSE;
+
+ /* It may be the shadow variable ${E_NCODING} which has lexical
+ * scope. See comments at Perl__get_encoding in this file */
+ if (*(mg->mg_ptr + 1) == '_') {
+ if (CopSTASH(PL_curcop) != get_hv("encoding::",0))
+ Perl_croak_no_modify();
+ lex = TRUE;
+ offset++;
+ }
+ if (strEQ(mg->mg_ptr + offset, "NCODING")) {
+ if (lex) { /* Use the shadow global */
+ SvREFCNT_dec(PL_lex_encoding);
+ if (SvOK(sv) || SvGMAGICAL(sv)) {
+ PL_lex_encoding = newSVsv(sv);
+ }
+ else {
+ PL_lex_encoding = NULL;
+ }
+ }
+ else { /* Use the regular global */
+ SvREFCNT_dec(PL_encoding);
+ if (SvOK(sv) || SvGMAGICAL(sv)) {
+ if (PL_localizing != 2) {
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED),
+ "Setting ${^ENCODING} is deprecated");
+ }
+ PL_encoding = newSVsv(sv);
+ }
+ else {
+ PL_encoding = NULL;
+ }
+ }
+ }
+ }
break;
case '\006': /* ^F */
PL_maxsysfd = SvIV(sv);
IV val= SvIV(referent);
if (val <= 0) {
tmpsv= &PL_sv_undef;
- Perl_ck_warner(aTHX_ packWARN(WARN_DEPRECATED),
+ Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED),
"Setting $/ to a reference to %s as a form of slurp is deprecated, treating as undef",
SvIV(SvRV(sv)) < 0 ? "a negative integer" : "zero"
);
}
if (!cv || !CvROOT(cv)) {
- Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL), "SIG%s handler \"%s\" not defined.\n",
- PL_sig_name[sig], (gv ? GvENAME(gv)
- : ((cv && CvGV(cv))
- ? GvENAME(CvGV(cv))
- : "__ANON__")));
+ const HEK * const hek = gv
+ ? GvENAME_HEK(gv)
+ : cv && CvNAMED(cv)
+ ? CvNAME_HEK(cv)
+ : cv && CvGV(cv) ? GvENAME_HEK(CvGV(cv)) : NULL;
+ if (hek)
+ Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL),
+ "SIG%s handler \"%"HEKf"\" not defined.\n",
+ PL_sig_name[sig], hek);
+ /* diag_listed_as: SIG%s handler "%s" not defined */
+ else Perl_ck_warner(aTHX_ packWARN(WARN_SIGNAL),
+ "SIG%s handler \"__ANON__\" not defined.\n",
+ PL_sig_name[sig]);
goto cleanup;
}
if (SvIsCOW(sv))
sv_force_normal_flags(sv, 0);
#endif
- if (mgs->mgs_readonly)
- SvREADONLY_on(sv);
- if (mgs->mgs_magical)
- SvFLAGS(sv) |= mgs->mgs_magical;
+ if (mgs->mgs_flags)
+ SvFLAGS(sv) |= mgs->mgs_flags;
else
mg_magical(sv);
}
return 1;
}
+int
+Perl_magic_setdebugvar(pTHX_ SV *sv, MAGIC *mg) {
+ PERL_ARGS_ASSERT_MAGIC_SETDEBUGVAR;
+
+#if DBVARMG_SINGLE != 0
+ assert(mg->mg_private >= DBVARMG_SINGLE);
+#endif
+ assert(mg->mg_private < DBVARMG_COUNT);
+
+ PL_DBcontrol[mg->mg_private] = SvIV_nomg(sv);
+
+ return 1;
+}
+
+int
+Perl_magic_getdebugvar(pTHX_ SV *sv, MAGIC *mg) {
+ PERL_ARGS_ASSERT_MAGIC_GETDEBUGVAR;
+
+#if DBVARMG_SINGLE != 0
+ assert(mg->mg_private >= DBVARMG_SINGLE);
+#endif
+ assert(mg->mg_private < DBVARMG_COUNT);
+ sv_setiv(sv, PL_DBcontrol[mg->mg_private]);
+
+ return 0;
+}
+
/*
* Local variables:
* c-indentation-style: bsd