SvSTASH_set(io, MUTABLE_HV(SvREFCNT_inc(GvHV(iogv))));
IoPAGE_LEN(sv) = 60;
}
- if (UNLIKELY(new_type == SVt_REGEXP))
- sv->sv_u.svu_rx = (regexp *)new_body;
- else if (old_type < SVt_PV) {
+ if (old_type < SVt_PV) {
/* referent will be NULL unless the old type was SVt_IV emulating
SVt_RV */
sv->sv_u.svu_rv = referent;
case SVt_PVGV:
if (!isGV_with_GP(sv))
break;
+ /* FALLTHROUGH */
case SVt_PVAV:
case SVt_PVHV:
case SVt_PVCV:
case SVt_PVGV:
if (!isGV_with_GP(sv))
break;
+ /* FALLTHROUGH */
case SVt_PVAV:
case SVt_PVHV:
case SVt_PVCV:
Regexps have no SvIVX and SvNVX fields.
*/
- assert(isREGEXP(sv) || SvPOKp(sv));
+ assert(SvPOKp(sv));
{
UV value;
const char * const ptr =
/* FBMs use the space for SvIVX and SvNVX for other purposes, and use
the same flag bit as SVf_IVisUV, so must not let them cache IVs.
Regexps have no SvIVX and SvNVX fields. */
- assert(isREGEXP(sv) || SvPOKp(sv));
+ assert(SvPOKp(sv));
{
UV value;
const char * const ptr =
return SvNVX(sv);
if (SvPOKp(sv) && !SvIOKp(sv)) {
ptr = SvPVX_const(sv);
- grokpv:
if (!SvIOKp(sv) && ckWARN(WARN_NUMERIC) &&
!grok_number(ptr, SvCUR(sv), NULL))
not_a_number(sv);
if (SvROK(sv)) {
goto return_rok;
}
- if (isREGEXP(sv)) {
- ptr = RX_WRAPPED((REGEXP *)sv);
- goto grokpv;
- }
assert(SvTYPE(sv) >= SVt_PVMG);
/* This falls through to the report_uninit near the end of the
function. */
/* The logic to use SVt_PVNV if necessary is in sv_upgrade. */
sv_upgrade(sv, SVt_NV);
DEBUG_c({
- STORE_NUMERIC_LOCAL_SET_STANDARD();
+ STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD();
PerlIO_printf(Perl_debug_log,
"0x%" UVxf " num(%" NVgf ")\n",
PTR2UV(sv), SvNVX(sv));
- RESTORE_NUMERIC_LOCAL();
+ RESTORE_LC_NUMERIC_UNDERLYING();
});
}
else if (SvTYPE(sv) < SVt_PVNV)
return 0.0;
}
DEBUG_c({
- STORE_NUMERIC_LOCAL_SET_STANDARD();
+ STORE_LC_NUMERIC_UNDERLYING_SET_STANDARD();
PerlIO_printf(Perl_debug_log, "0x%" UVxf " 2nv(%" NVgf ")\n",
PTR2UV(sv), SvNVX(sv));
- RESTORE_NUMERIC_LOCAL();
+ RESTORE_LC_NUMERIC_UNDERLYING();
});
return SvNVX(sv);
}
DECLARATION_FOR_LC_NUMERIC_MANIPULATION;
STORE_LC_NUMERIC_SET_TO_NEEDED();
- local_radix = PL_numeric_local && PL_numeric_radix_sv;
+ local_radix = PL_numeric_underlying && PL_numeric_radix_sv;
if (local_radix && SvCUR(PL_numeric_radix_sv) > 1) {
size += SvCUR(PL_numeric_radix_sv) - 1;
s = SvGROW_mutable(sv, size);
*lp = SvCUR(buffer);
return SvPVX(buffer);
}
- else if (isREGEXP(sv)) {
- if (lp) *lp = RX_WRAPLEN((REGEXP *)sv);
- return RX_WRAPPED((REGEXP *)sv);
- }
else {
if (lp)
*lp = 0;
return cBOOL(svb);
}
}
- return SvRV(sv) != 0;
+ assert(SvRV(sv));
+ return TRUE;
}
if (isREGEXP(sv))
return
RX_WRAPLEN(sv) > 1 || (RX_WRAPLEN(sv) && *RX_WRAPPED(sv) != '0');
+
+ if (SvNOK(sv) && !SvPOK(sv))
+ return SvNVX(sv) != 0.0;
+
return SvTRUE_common(sv, isGV_with_GP(sv) ? 1 : 0);
}
}
}
- if (SvUTF8(sv)) {
+ /* SVt_REGEXP's shouldn't be upgraded to UTF8 - they're already
+ * compiled and individual nodes will remain non-utf8 even if the
+ * stringified version of the pattern gets upgraded. Whether the
+ * PVX of a REGEXP should be grown or we should just croak, I don't
+ * know - DAPM */
+ if (SvUTF8(sv) || isREGEXP(sv)) {
if (extra) SvGROW(sv, SvCUR(sv) + extra);
return SvCUR(sv);
}
U8 * s = (U8 *) SvPVX_const(sv);
U8 * e = (U8 *) SvEND(sv);
U8 *t = s;
- STRLEN two_byte_count = 0;
+ STRLEN two_byte_count;
- if (flags & SV_FORCE_UTF8_UPGRADE) goto must_be_utf8;
-
- /* See if really will need to convert to utf8. We mustn't rely on our
- * incoming SV being well formed and having a trailing '\0', as certain
- * code in pp_formline can send us partially built SVs. */
-
- while (t < e) {
- const U8 ch = *t++;
- if (NATIVE_BYTE_IS_INVARIANT(ch)) continue;
-
- t--; /* t already incremented; re-point to first variant */
- two_byte_count = 1;
- goto must_be_utf8;
- }
+ if (flags & SV_FORCE_UTF8_UPGRADE) {
+ two_byte_count = 0;
+ }
+ else {
+ if (is_utf8_invariant_string_loc(s, SvCUR(sv), (const U8 **) &t)) {
- /* utf8 conversion not needed because all are invariants. Mark as
- * UTF-8 even if no variant - saves scanning loop */
- SvUTF8_on(sv);
- if (extra) SvGROW(sv, SvCUR(sv) + extra);
- return SvCUR(sv);
+ /* utf8 conversion not needed because all are invariants. Mark
+ * as UTF-8 even if no variant - saves scanning loop */
+ SvUTF8_on(sv);
+ if (extra) SvGROW(sv, SvCUR(sv) + extra);
+ return SvCUR(sv);
+ }
- must_be_utf8:
+ /* Here, there is at least one variant, and t points to the first
+ * one */
+ two_byte_count = 1;
+ }
- /* Here, the string should be converted to utf8, either because of an
- * input flag (two_byte_count = 0), or because a character that
- * requires 2 bytes was found (two_byte_count = 1). t points either to
- * the beginning of the string (if we didn't examine anything), or to
- * the first variant. In either case, everything from s to t - 1 will
- * occupy only 1 byte each on output.
+ /* Note that the incoming SV may not have a trailing '\0', as certain
+ * code in pp_formline can send us partially built SVs.
+ *
+ * Here, the string should be converted to utf8, either because of an
+ * input flag (which causes two_byte_count to be set to 0), or because
+ * a character that requires 2 bytes was found (two_byte_count = 1). t
+ * points either to the beginning of the string (if we didn't examine
+ * anything), or to the first variant. In either case, everything from
+ * s to t - 1 will occupy only 1 byte each on output.
*
* There are two main ways to convert. One is to create a new string
* and go through the input starting from the beginning, appending each
* from s to t - 1 is invariant, the destination can be initialized
* with these using a fast memory copy
*
- * The other way is to figure out exactly how big the string should be
+ * The other way is to figure out exactly how big the string should be,
* by parsing the entire input. Then you don't have to make it big
* enough to handle the worst possible case, and more importantly, if
* the string you already have is large enough, you don't have to
* value. We go backwards through the string, converting until we
* get to the position we are at now, and then stop. If this
* position is far enough along in the string, this method is
- * faster than the other method. If the memory copy were the same
- * speed as the byte-by-byte loop, that position would be about
- * half-way, as at the half-way mark, parsing to the end and back
- * is one complete string's parse, the same amount as starting
- * over and going all the way through. Actually, it would be
- * somewhat less than half-way, as it's faster to just count bytes
- * than to also copy, and we don't have the overhead of allocating
- * a new string, changing the scalar to use it, and freeing the
- * existing one. But if the memory copy is fast, the break-even
- * point is somewhere after half way. The counting loop could be
- * sped up by vectorization, etc, to move the break-even point
- * further towards the beginning.
+ * faster than the first method above. If the memory copy were
+ * the same speed as the byte-by-byte loop, that position would be
+ * about half-way, as at the half-way mark, parsing to the end and
+ * back is one complete string's parse, the same amount as
+ * starting over and going all the way through. Actually, it
+ * would be somewhat less than half-way, as it's faster to just
+ * count bytes than to also copy, and we don't have the overhead
+ * of allocating a new string, changing the scalar to use it, and
+ * freeing the existing one. But if the memory copy is fast, the
+ * break-even point is somewhere after half way. The counting
+ * loop could be sped up by vectorization, etc, to move the
+ * break-even point further towards the beginning.
* 2) if the string doesn't have enough space to handle the converted
* value. A new string will have to be allocated, and one might
* as well, given that, start from the beginning doing the first
glob to begin with. */
if(dtype == SVt_PVGV) {
const char * const name = GvNAME((const GV *)dstr);
- if(
- strEQ(name,"ISA")
+ const STRLEN len = GvNAMELEN(dstr);
+ if(memEQs(name, len, "ISA")
/* The stash may have been detached from the symbol table, so
check its name. */
&& GvSTASH(dstr) && HvENAME(GvSTASH(dstr))
)
mro_changes = 2;
else {
- const STRLEN len = GvNAMELEN(dstr);
if ((len > 1 && name[len-2] == ':' && name[len-1] == ':')
|| (len == 1 && name[0] == ':')) {
mro_changes = 3;
}
else if (
stype == SVt_PVAV && sref != dref
- && strEQ(GvNAME((GV*)dstr), "ISA")
+ && memEQs(GvNAME((GV*)dstr), GvNAMELEN((GV*)dstr), "ISA")
/* The stash may have been detached from the symbol table, so
check its name before doing anything. */
&& GvSTASH(dstr) && HvENAME(GvSTASH(dstr))
case SVt_REGEXP:
upgregexp:
if (dtype < SVt_REGEXP)
- {
- if (dtype >= SVt_PV) {
- SvPV_free(dstr);
- SvPV_set(dstr, 0);
- SvLEN_set(dstr, 0);
- SvCUR_set(dstr, 0);
- }
sv_upgrade(dstr, SVt_REGEXP);
- }
break;
case SVt_INVLIST:
) {
/* Either it's a shared hash key, or it's suitable for
copy-on-write. */
+#ifdef DEBUGGING
if (DEBUG_C_TEST) {
PerlIO_printf(Perl_debug_log, "Copy on write: sstr --> dstr\n");
sv_dump(sstr);
sv_dump(dstr);
}
+#endif
#ifdef PERL_ANY_COW
if (!(sflags & SVf_IsCOW)) {
SvIsCOW_on(sstr);
#endif
PERL_ARGS_ASSERT_SV_SETSV_COW;
-
+#ifdef DEBUGGING
if (DEBUG_C_TEST) {
PerlIO_printf(Perl_debug_log, "Fast copy on write: %p -> %p\n",
(void*)sstr, (void*)dstr);
if (dstr)
sv_dump(dstr);
}
-
+#endif
if (dstr) {
if (SvTHINKFIRST(dstr))
sv_force_normal_flags(dstr, SV_COW_DROP_PV);
SvUTF8_on(dstr);
SvLEN_set(dstr, len);
SvCUR_set(dstr, cur);
- if (DEBUG_C_TEST) {
- sv_dump(dstr);
- }
+#ifdef DEBUGGING
+ if (DEBUG_C_TEST)
+ sv_dump(dstr);
+#endif
return dstr;
}
#endif
const STRLEN len = SvLEN(sv);
const STRLEN cur = SvCUR(sv);
+#ifdef DEBUGGING
if (DEBUG_C_TEST) {
PerlIO_printf(Perl_debug_log,
"Copy on write: Force normal %ld\n",
(long) flags);
sv_dump(sv);
}
+#endif
SvIsCOW_off(sv);
# ifdef PERL_COPY_ON_WRITE
if (len) {
} else {
unshare_hek(SvSHARED_HEK_FROM_PV(pvx));
}
- if (DEBUG_C_TEST) {
+#ifdef DEBUGGING
+ if (DEBUG_C_TEST)
sv_dump(sv);
- }
+#endif
}
#else
const char * const pvx = SvPVX_const(sv);
const svtype new_type =
islv ? SVt_NULL : SvMAGIC(sv) || SvSTASH(sv) ? SVt_PVMG : SVt_PV;
SV *const temp = newSV_type(new_type);
- regexp *const temp_p = ReANY((REGEXP *)sv);
+ regexp *old_rx_body;
if (new_type == SVt_PVMG) {
SvMAGIC_set(temp, SvMAGIC(sv));
SvSTASH_set(temp, SvSTASH(sv));
SvSTASH_set(sv, NULL);
}
- if (!islv) SvCUR_set(temp, SvCUR(sv));
- /* Remember that SvPVX is in the head, not the body. But
- RX_WRAPPED is in the body. */
+ if (!islv)
+ SvCUR_set(temp, SvCUR(sv));
+ /* Remember that SvPVX is in the head, not the body. */
assert(ReANY((REGEXP *)sv)->mother_re);
+
+ if (islv) {
+ /* LV-as-regex has sv->sv_any pointing to an XPVLV body,
+ * whose xpvlenu_rx field points to the regex body */
+ XPV *xpv = (XPV*)(SvANY(sv));
+ old_rx_body = xpv->xpv_len_u.xpvlenu_rx;
+ xpv->xpv_len_u.xpvlenu_rx = NULL;
+ }
+ else
+ old_rx_body = ReANY((REGEXP *)sv);
+
/* Their buffer is already owned by someone else. */
if (flags & SV_COW_DROP_PV) {
/* SvLEN is already 0. For SVt_REGEXP, we have a brand new
- zeroed body. For SVt_PVLV, it should have been set to 0
- before turning into a regexp. */
+ zeroed body. For SVt_PVLV, we zeroed it above (len field
+ a union with xpvlenu_rx) */
assert(!SvLEN(islv ? sv : temp));
sv->sv_u.svu_pv = 0;
}
SvFLAGS(temp) &= ~(SVTYPEMASK);
SvFLAGS(temp) |= SVt_REGEXP|SVf_FAKE;
- SvANY(temp) = temp_p;
- temp->sv_u.svu_rx = (regexp *)temp_p;
+ SvANY(temp) = old_rx_body;
SvREFCNT_dec_NN(temp);
}
referred-to SV C<PERL_MAGIC_backref> magic if it hasn't already; and
push a back-reference to this RV onto the array of backreferences
associated with that magic. If the RV is magical, set magic will be
-called after the RV is cleared.
+called after the RV is cleared. Silently ignores C<undef> and warns
+on already-weak references.
=cut
*/
}
/*
+=for apidoc sv_rvunweaken
+
+Unweaken a reference: Clear the C<SvWEAKREF> flag on this RV; remove
+the backreference to this RV from the array of backreferences
+associated with the target SV, increment the refcount of the target.
+Silently ignores C<undef> and warns on non-weak references.
+
+=cut
+*/
+
+SV *
+Perl_sv_rvunweaken(pTHX_ SV *const sv)
+{
+ SV *tsv;
+
+ PERL_ARGS_ASSERT_SV_RVUNWEAKEN;
+
+ if (!SvOK(sv)) /* let undefs pass */
+ return sv;
+ if (!SvROK(sv))
+ Perl_croak(aTHX_ "Can't unweaken a nonreference");
+ else if (!SvWEAKREF(sv)) {
+ Perl_ck_warner(aTHX_ packWARN(WARN_MISC), "Reference is not weak");
+ return sv;
+ }
+ else if (SvREADONLY(sv)) croak_no_modify();
+
+ tsv = SvRV(sv);
+ SvWEAKREF_off(sv);
+ SvROK_on(sv);
+ SvREFCNT_inc_NN(tsv);
+ Perl_sv_del_backref(aTHX_ tsv, sv);
+ return sv;
+}
+
+/*
=for apidoc sv_get_backrefs
If C<sv> is the target of a weak reference then it returns the back
goto freescalar;
case SVt_REGEXP:
/* FIXME for plugins */
- freeregexp:
pregfree2((REGEXP*) sv);
goto freescalar;
case SVt_PVCV:
}
else if (LvTYPE(sv) != 't') /* unless tie: unrefcnted fake SV** */
SvREFCNT_dec(LvTARG(sv));
- if (isREGEXP(sv)) goto freeregexp;
+ if (isREGEXP(sv)) {
+ /* SvLEN points to a regex body. Free the body, then
+ * set SvLEN to whatever value was in the now-freed
+ * regex body. The PVX buffer is shared by multiple re's
+ * and only freed once, by the re whose len in non-null */
+ STRLEN len = ReANY(sv)->xpv_len;
+ pregfree2((REGEXP*) sv);
+ SvLEN_set((sv), len);
+ goto freescalar;
+ }
/* FALLTHROUGH */
case SVt_PVGV:
if (isGV_with_GP(sv)) {
&& !(IoFLAGS(sv) & IOf_FAKE_DIRP)))
{
if (SvIsCOW(sv)) {
+#ifdef DEBUGGING
if (DEBUG_C_TEST) {
PerlIO_printf(Perl_debug_log, "Copy on write: clear\n");
sv_dump(sv);
}
+#endif
if (SvLEN(sv)) {
if (CowREFCNT(sv)) {
sv_buf_to_rw(sv);
if (flags & SVp_NOK) {
const NV was = SvNVX(sv);
if (LIKELY(!Perl_isinfnan(was)) &&
- NV_OVERFLOWS_INTEGERS_AT &&
+ NV_OVERFLOWS_INTEGERS_AT != 0.0 &&
was >= NV_OVERFLOWS_INTEGERS_AT) {
/* diag_listed_as: Lost precision when %s %f by 1 */
Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
{
const NV was = SvNVX(sv);
if (LIKELY(!Perl_isinfnan(was)) &&
- NV_OVERFLOWS_INTEGERS_AT &&
+ NV_OVERFLOWS_INTEGERS_AT != 0.0 &&
was <= -NV_OVERFLOWS_INTEGERS_AT) {
/* diag_listed_as: Lost precision when %s %f by 1 */
Perl_ck_warner(aTHX_ packWARN(WARN_IMPRECISION),
/* In this case there is an implicit bit,
* and therefore the exponent is shifted by one. */
exponent--;
-# else
-# ifdef NV_X86_80_BIT
+# elif defined(NV_X86_80_BIT)
if (subnormal) {
/* The subnormals of the x86-80 have a base exponent of -16382,
* (while the physical exponent bits are zero) but the frexp()
} else {
exponent -= 4;
}
-# endif
/* TBD: other non-implicit-bit platforms than the x86-80. */
# endif
#endif
#ifndef USE_LOCALE_NUMERIC
*p++ = '.';
#else
- if (PL_numeric_radix_sv) {
+ if (PL_numeric_radix_sv && IN_LC(LC_NUMERIC)) {
STRLEN n;
const char* r = SvPV(PL_numeric_radix_sv, n);
- assert(IN_LC(LC_NUMERIC));
Copy(r, p, n, char);
p += n;
}
bool has_utf8 = DO_UTF8(sv); /* has the result utf8? */
const bool pat_utf8 = has_utf8; /* the pattern is in utf8? */
/* Times 4: a decimal digit takes more than 3 binary digits.
- * NV_DIG: mantissa takes than many decimal digits.
+ * NV_DIG: mantissa takes that many decimal digits.
* Plus 32: Playing safe. */
char ebuf[IV_DIG * 4 + NV_DIG + 32];
bool no_redundant_warning = FALSE; /* did we use any explicit format parameter index? */
if (args) {
eptr = va_arg(*args, char*);
if (eptr)
- elen = strlen(eptr);
+ if (has_precis)
+ elen = my_strnlen(eptr, precis);
+ else
+ elen = strlen(eptr);
else {
eptr = (char *)nullstr;
elen = sizeof nullstr - 1;
* over the individual characters of a vector arg */
vector:
if (!veclen)
- goto donevalidconversion;
+ goto done_valid_conversion;
if (vec_utf8)
uv = utf8n_to_uvchr(vecstr, veclen, &ulen,
UTF8_ALLOW_ANYUV);
lc_numeric_set = TRUE;
}
- if (PL_numeric_radix_sv) {
- assert(IN_LC(LC_NUMERIC));
+ if (PL_numeric_radix_sv && IN_LC(LC_NUMERIC)) {
/* this can't wrap unless PL_numeric_radix_sv is a string
* consuming virtually all the 32-bit or 64-bit address
* space
if (float_need < width)
float_need = width;
- if (PL_efloatsize < float_need) {
+ if (PL_efloatsize <= float_need) {
+ /* PL_efloatbuf should be at least 1 greater than
+ * float_need to allow a trailing \0 to be returned by
+ * snprintf(). If we need to grow, overgrow for the
+ * benefit of future generations */
+ const STRLEN extra = 0x20;
+ if (float_need >= ((STRLEN)~0) - extra)
+ croak_memory_wrap();
+ float_need += extra;
Safefree(PL_efloatbuf);
PL_efloatsize = float_need;
Newx(PL_efloatbuf, PL_efloatsize, char);
? my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, fv)
: my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, (double)fv));
#else
- elen = my_sprintf(PL_efloatbuf, ptr, fv);
+ elen = my_snprintf(PL_efloatbuf, PL_efloatsize, ptr, fv);
#endif
GCC_DIAG_RESTORE;
}
S_sv_catpvn_simple(aTHX_ sv, eptr, elen);
- goto donevalidconversion;
+ goto done_valid_conversion;
}
/* SPECIAL */
PL_op ? OP_DESC(PL_op) : "sv_vcatpvfn()");
sv_setuv_mg(argsv, has_utf8 ? (UV)sv_len_utf8(sv) : (UV)len);
}
- goto donevalidconversion;
+ goto done_valid_conversion;
}
/* UNKNOWN */
goto vector; /* do next iteration */
}
- donevalidconversion:
+ done_valid_conversion:
if (arg_missing)
S_warn_vcatpvfn_missing_argument(aTHX);
case SVt_REGEXP:
duprex:
/* FIXME for plugins */
- dstr->sv_u.svu_rx = ((REGEXP *)dstr)->sv_any;
re_dup_guts((REGEXP*) sstr, (REGEXP*) dstr, param);
break;
case SVt_PVLV:
else
LvTARG(dstr) = sv_dup_inc(LvTARG(dstr), param);
if (isREGEXP(sstr)) goto duprex;
+ /* FALLTHROUGH */
case SVt_PVGV:
/* non-GP case already handled above */
if(isGV_with_GP(sstr)) {
#ifdef USE_LOCALE_NUMERIC
PL_numeric_standard = proto_perl->Inumeric_standard;
- PL_numeric_local = proto_perl->Inumeric_local;
+ PL_numeric_underlying = proto_perl->Inumeric_underlying;
#endif /* !USE_LOCALE_NUMERIC */
/* Did the locale setup indicate UTF-8? */
init_constants();
ptr_table_store(PL_ptr_table, &proto_perl->Isv_undef, &PL_sv_undef);
ptr_table_store(PL_ptr_table, &proto_perl->Isv_no, &PL_sv_no);
+ ptr_table_store(PL_ptr_table, &proto_perl->Isv_zero, &PL_sv_zero);
ptr_table_store(PL_ptr_table, &proto_perl->Isv_yes, &PL_sv_yes);
ptr_table_store(PL_ptr_table, &proto_perl->Ipadname_const,
&PL_padname_const);
PL_numeric_radix_sv = sv_dup_inc(proto_perl->Inumeric_radix_sv, param);
#endif /* !USE_LOCALE_NUMERIC */
+ PL_langinfo_buf = NULL;
+ PL_langinfo_bufsize = 0;
+
/* Unicode inversion lists */
PL_Latin1 = sv_dup_inc(proto_perl->ILatin1, param);
PL_UpperLatin1 = sv_dup_inc(proto_perl->IUpperLatin1, param);
|SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
|SVp_POK|SVf_POK;
+ SvANY(&PL_sv_zero) = new_XPVNV();
+ SvREFCNT(&PL_sv_zero) = SvREFCNT_IMMORTAL;
+ SvFLAGS(&PL_sv_zero) = SVt_PVNV|SVf_READONLY|SVf_PROTECT
+ |SVp_IOK|SVf_IOK|SVp_NOK|SVf_NOK
+ |SVp_POK|SVf_POK
+ |SVs_PADTMP;
+
SvPV_set(&PL_sv_no, (char*)PL_No);
SvCUR_set(&PL_sv_no, 0);
SvLEN_set(&PL_sv_no, 0);
SvIV_set(&PL_sv_yes, 1);
SvNV_set(&PL_sv_yes, 1);
+ SvPV_set(&PL_sv_zero, (char*)PL_Zero);
+ SvCUR_set(&PL_sv_zero, 1);
+ SvLEN_set(&PL_sv_zero, 0);
+ SvIV_set(&PL_sv_zero, 0);
+ SvNV_set(&PL_sv_zero, 0);
+
PadnamePV(&PL_padname_const) = (char *)PL_No;
+
+ assert(SvIMMORTAL_INTERP(&PL_sv_yes));
+ assert(SvIMMORTAL_INTERP(&PL_sv_undef));
+ assert(SvIMMORTAL_INTERP(&PL_sv_no));
+ assert(SvIMMORTAL_INTERP(&PL_sv_zero));
+
+ assert(SvIMMORTAL(&PL_sv_yes));
+ assert(SvIMMORTAL(&PL_sv_undef));
+ assert(SvIMMORTAL(&PL_sv_no));
+ assert(SvIMMORTAL(&PL_sv_zero));
+
+ assert( SvIMMORTAL_TRUE(&PL_sv_yes));
+ assert(!SvIMMORTAL_TRUE(&PL_sv_undef));
+ assert(!SvIMMORTAL_TRUE(&PL_sv_no));
+ assert(!SvIMMORTAL_TRUE(&PL_sv_zero));
+
+ assert( SvTRUE_nomg_NN(&PL_sv_yes));
+ assert(!SvTRUE_nomg_NN(&PL_sv_undef));
+ assert(!SvTRUE_nomg_NN(&PL_sv_no));
+ assert(!SvTRUE_nomg_NN(&PL_sv_zero));
}
/*
/* def-ness of rval pos() is independent of the def-ness of its arg */
if ( !(obase->op_flags & OPf_MOD))
break;
+ /* FALLTHROUGH */
case OP_SCHOMP:
case OP_CHOMP:
if (PL_op) {
desc = PL_op->op_type == OP_STRINGIFY && PL_op->op_folded
? "join or string"
+ : PL_op->op_type == OP_MULTICONCAT
+ && (PL_op->op_private & OPpMULTICONCAT_FAKE)
+ ? "sprintf"
: OP_DESC(PL_op);
if (uninit_sv && PL_curpad) {
varname = find_uninit_var(PL_op, uninit_sv, 0, &desc);