#define new_XPVHV() my_safemalloc(sizeof(XPVHV))
#define del_XPVHV(p) my_safefree(p)
-
+
#define new_XPVMG() my_safemalloc(sizeof(XPVMG))
#define del_XPVMG(p) my_safefree(p)
#define new_XPVHV() (void*)new_xpvhv()
#define del_XPVHV(p) del_xpvhv((XPVHV *)p)
-
+
#define new_XPVMG() (void*)new_xpvmg()
#define del_XPVMG(p) del_xpvmg((XPVMG *)p)
#define new_XPVGV() my_safemalloc(sizeof(XPVGV))
#define del_XPVGV(p) my_safefree(p)
-
+
#define new_XPVFM() my_safemalloc(sizeof(XPVFM))
#define del_XPVFM(p) my_safefree(p)
-
+
#define new_XPVIO() my_safemalloc(sizeof(XPVIO))
#define del_XPVIO(p) my_safefree(p)
MAGIC* magic;
HV* stash;
+ if (mt != SVt_PV && SvREADONLY(sv) && SvFAKE(sv)) {
+ sv_force_normal(sv);
+ }
+
if (SvTYPE(sv) == mt)
return TRUE;
if (SvTHINKFIRST(sv)) {
if (SvROK(sv)) {
SV* tmpstr;
- if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv, numer)))
+ if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) &&
+ (SvRV(tmpstr) != SvRV(sv)))
return SvIV(tmpstr);
return PTR2IV(SvRV(sv));
}
SvUVX(sv) = U_V(SvNVX(sv));
SvIsUV_on(sv);
ret_iv_max:
- DEBUG_c(PerlIO_printf(Perl_debug_log,
+ DEBUG_c(PerlIO_printf(Perl_debug_log,
"0x%"UVxf" 2iv(%"UVuf" => %"IVdf") (as unsigned)\n",
PTR2UV(sv),
SvUVX(sv),
/* We want to avoid a possible problem when we cache an IV which
may be later translated to an NV, and the resulting NV is not
the translation of the initial data.
-
+
This means that if we cache such an IV, we need to cache the
NV as well. Moreover, we trade speed for space, and do not
cache the NV if not needed.
if (SvTHINKFIRST(sv)) {
if (SvROK(sv)) {
SV* tmpstr;
- if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv, numer)))
+ if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) &&
+ (SvRV(tmpstr) != SvRV(sv)))
return SvUV(tmpstr);
return PTR2UV(SvRV(sv));
}
else {
SvIVX(sv) = I_V(SvNVX(sv));
ret_zero:
- DEBUG_c(PerlIO_printf(Perl_debug_log,
+ DEBUG_c(PerlIO_printf(Perl_debug_log,
"0x%"UVxf" 2uv(%"IVdf" => %"IVdf") (as signed)\n",
PTR2UV(sv),
SvIVX(sv),
/* We want to avoid a possible problem when we cache a UV which
may be later translated to an NV, and the resulting NV is not
the translation of the initial data.
-
+
This means that if we cache such a UV, we need to cache the
NV as well. Moreover, we trade speed for space, and do not
cache the NV if not needed.
return Atof(SvPVX(sv));
}
if (SvIOKp(sv)) {
- if (SvIsUV(sv))
+ if (SvIsUV(sv))
return (NV)SvUVX(sv);
else
return (NV)SvIVX(sv);
if (SvTHINKFIRST(sv)) {
if (SvROK(sv)) {
SV* tmpstr;
- if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)))
+ if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)) &&
+ (SvRV(tmpstr) != SvRV(sv)))
return SvNV(tmpstr);
return PTR2NV(SvRV(sv));
}
sv_upgrade(sv, SVt_NV);
#if defined(USE_LONG_DOUBLE)
DEBUG_c({
- RESTORE_NUMERIC_STANDARD();
+ STORE_NUMERIC_LOCAL_SET_STANDARD();
PerlIO_printf(Perl_debug_log,
"0x%"UVxf" num(%" PERL_PRIgldbl ")\n",
PTR2UV(sv), SvNVX(sv));
});
#else
DEBUG_c({
- RESTORE_NUMERIC_STANDARD();
+ STORE_NUMERIC_LOCAL_SET_STANDARD();
PerlIO_printf(Perl_debug_log, "0x%"UVxf" num(%g)\n",
PTR2UV(sv), SvNVX(sv));
RESTORE_NUMERIC_LOCAL();
SvNOK_on(sv);
#if defined(USE_LONG_DOUBLE)
DEBUG_c({
- RESTORE_NUMERIC_STANDARD();
+ STORE_NUMERIC_LOCAL_SET_STANDARD();
PerlIO_printf(Perl_debug_log, "0x%"UVxf" 2nv(%" PERL_PRIgldbl ")\n",
PTR2UV(sv), SvNVX(sv));
RESTORE_NUMERIC_LOCAL();
});
#else
DEBUG_c({
- RESTORE_NUMERIC_STANDARD();
+ STORE_NUMERIC_LOCAL_SET_STANDARD();
PerlIO_printf(Perl_debug_log, "0x%"UVxf" 1nv(%g)\n",
PTR2UV(sv), SvNVX(sv));
RESTORE_NUMERIC_LOCAL();
STRLEN len;
if (SvPOK(sv)) {
- sbegin = SvPVX(sv);
+ sbegin = SvPVX(sv);
len = SvCUR(sv);
}
else if (SvPOKp(sv))
numtype |= IS_NUMBER_TO_INT_BY_ATOL;
if (*s == '.'
-#ifdef USE_LOCALE_NUMERIC
+#ifdef USE_LOCALE_NUMERIC
|| IS_NUMERIC_RADIX(*s)
#endif
) {
}
}
else if (*s == '.'
-#ifdef USE_LOCALE_NUMERIC
+#ifdef USE_LOCALE_NUMERIC
|| IS_NUMERIC_RADIX(*s)
#endif
) {
return SvPVX(sv);
}
if (SvIOKp(sv)) {
- if (SvIsUV(sv))
+ if (SvIsUV(sv))
(void)sprintf(tmpbuf,"%"UVuf, (UV)SvUVX(sv));
else
(void)sprintf(tmpbuf,"%"IVdf, (IV)SvIVX(sv));
if (SvTHINKFIRST(sv)) {
if (SvROK(sv)) {
SV* tmpstr;
- if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)))
+ if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)) &&
+ (SvRV(tmpstr) != SvRV(sv)))
return SvPV(tmpstr,*lp);
sv = (SV*)SvRV(sv);
if (!sv)
switch (SvTYPE(sv)) {
case SVt_PVMG:
if ( ((SvFLAGS(sv) &
- (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
+ (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG))
== (SVs_OBJECT|SVs_RMG))
&& strEQ(s=HvNAME(SvSTASH(sv)), "Regexp")
&& (mg = mg_find(sv, 'r'))) {
}
if (SvNOKp(sv)) { /* See note in sv_2uv() */
/* XXXX 64-bit? IV may have better precision... */
- /* I tried changing this for to be 64-bit-aware and
+ /* I tried changing this to be 64-bit-aware and
* the t/op/numconvert.t became very, very, angry.
* --jhi Sep 1999 */
if (SvTYPE(sv) < SVt_PVNV)
sv_upgrade(sv, SVt_PVNV);
- SvGROW(sv, 28);
+ /* The +20 is pure guesswork. Configure test needed. --jhi */
+ SvGROW(sv, NV_DIG + 20);
s = SvPVX(sv);
olderrno = errno; /* some Xenix systems wipe out errno here */
#ifdef apollo
sv_utf8_upgrade(sv);
return sv_2pv(sv,lp);
}
-
+
/* This function is only called on magical items */
bool
Perl_sv_2bool(pTHX_ register SV *sv)
if (SvROK(sv)) {
dTHR;
SV* tmpsv;
- if (SvAMAGIC(sv) && (tmpsv = AMG_CALLun(sv,bool_)))
+ if (SvAMAGIC(sv) && (tmpsv=AMG_CALLun(sv,bool_)) &&
+ (SvRV(tmpsv) != SvRV(sv)))
return SvTRUE(tmpsv);
return SvRV(sv) != 0;
}
void
Perl_sv_utf8_upgrade(pTHX_ register SV *sv)
{
- int hicount;
- char *c;
+ char *s, *t;
+ bool hibit;
if (!sv || !SvPOK(sv) || SvUTF8(sv))
return;
- /* This function could be much more efficient if we had a FLAG
- * to signal if there are any hibit chars in the string
+ /* This function could be much more efficient if we had a FLAG in SVs
+ * to signal if there are any hibit chars in the PV.
*/
- hicount = 0;
- for (c = SvPVX(sv); c < SvEND(sv); c++) {
- if (*c & 0x80)
- hicount++;
- }
-
- if (hicount) {
- char *src, *dst;
- SvGROW(sv, SvCUR(sv) + hicount + 1);
-
- src = SvEND(sv) - 1;
- SvCUR_set(sv, SvCUR(sv) + hicount);
- dst = SvEND(sv) - 1;
-
- while (src < dst) {
- if (*src & 0x80) {
- dst--;
- uv_to_utf8((U8*)dst, (U8)*src--);
- dst--;
- }
- else {
- *dst-- = *src--;
- }
- }
-
+ for (s = t = SvPVX(sv), hibit = FALSE; t < SvEND(sv) && !hibit; t++)
+ if (*t & 0x80)
+ hibit = TRUE;
+
+ if (hibit) {
+ STRLEN len = SvCUR(sv) + 1; /* Plus the \0 */
+ SvPVX(sv) = (char*)bytes_to_utf8((U8*)s, &len);
+ SvCUR(sv) = len - 1;
+ SvLEN(sv) = len; /* No longer know the real size. */
SvUTF8_on(sv);
+ Safefree(s); /* No longer using what was there before. */
}
}
{
if (SvPOK(sv) && SvUTF8(sv)) {
char *c = SvPVX(sv);
- char *first_hi = 0;
- /* need to figure out if this is possible at all first */
- while (c < SvEND(sv)) {
- if (*c & 0x80) {
- I32 len;
- UV uv = utf8_to_uv((U8*)c, &len);
- if (uv >= 256) {
- if (fail_ok)
- return FALSE;
- else {
- /* XXX might want to make a callback here instead */
- Perl_croak(aTHX_ "Big byte");
- }
- }
- if (!first_hi)
- first_hi = c;
- c += len;
- }
- else {
- c++;
- }
- }
-
- if (first_hi) {
- char *src = first_hi;
- char *dst = first_hi;
- while (src < SvEND(sv)) {
- if (*src & 0x80) {
- I32 len;
- U8 u = (U8)utf8_to_uv((U8*)src, &len);
- *dst++ = u;
- src += len;
- }
- else {
- *dst++ = *src++;
- }
- }
- SvCUR_set(sv, dst - SvPVX(sv));
- }
- SvUTF8_off(sv);
+ STRLEN len = SvCUR(sv) + 1; /* include trailing NUL */
+ if (!utf8_to_bytes((U8*)c, &len)) {
+ if (fail_ok)
+ return FALSE;
+ else {
+ if (PL_op)
+ Perl_croak(aTHX_ "Wide character in %s",
+ PL_op_desc[PL_op->op_type]);
+ else
+ Perl_croak(aTHX_ "Wide character");
+ }
+ }
+ SvCUR(sv) = len - 1;
+ SvUTF8_off(sv);
}
return TRUE;
}
=for apidoc sv_utf8_encode
Convert the PV of an SV to UTF8-encoded, but then turn off the C<SvUTF8>
-flag so that it looks like bytes again. Nothing calls this.
+flag so that it looks like bytes again. Nothing calls this.
=cut
*/
* we want to make sure everything inside is valid utf8 first.
*/
c = SvPVX(sv);
+ if (!is_utf8_string((U8*)c, SvCUR(sv)+1))
+ return FALSE;
+
while (c < SvEND(sv)) {
- if (*c & 0x80) {
- I32 len;
- (void)utf8_to_uv((U8*)c, &len);
- if (len == 1) {
- /* bad utf8 */
- return FALSE;
- }
- c += len;
- has_utf = TRUE;
- }
- else {
- c++;
- }
+ if (*c++ & 0x80) {
+ SvUTF8_on(sv);
+ break;
+ }
}
-
- if (has_utf)
- SvUTF8_on(sv);
}
return TRUE;
}
if (!GvCVGEN((GV*)dstr) &&
(CvROOT(cv) || CvXSUB(cv)))
{
- SV *const_sv = cv_const_sv(cv);
- bool const_changed = TRUE;
- if(const_sv)
- const_changed = sv_cmp(const_sv,
- op_const_sv(CvSTART((CV*)sref),
- (CV*)sref));
+ SV *const_sv;
/* ahem, death to those who redefine
* active sort subs */
if (PL_curstackinfo->si_type == PERLSI_SORT &&
PL_sortcop == CvSTART(cv))
- Perl_croak(aTHX_
+ Perl_croak(aTHX_
"Can't redefine active sort subroutine %s",
GvENAME((GV*)dstr));
- if ((const_changed && const_sv) || ckWARN(WARN_REDEFINE))
- Perl_warner(aTHX_ WARN_REDEFINE, const_sv ?
- "Constant subroutine %s redefined"
- : "Subroutine %s redefined",
- GvENAME((GV*)dstr));
+ /* Redefining a sub - warning is mandatory if
+ it was a const and its value changed. */
+ if (ckWARN(WARN_REDEFINE)
+ || (CvCONST(cv)
+ && (!CvCONST((CV*)sref)
+ || sv_cmp(cv_const_sv(cv),
+ cv_const_sv((CV*)sref)))))
+ {
+ Perl_warner(aTHX_ WARN_REDEFINE,
+ CvCONST(cv)
+ ? "Constant subroutine %s redefined"
+ : "Subroutine %s redefined",
+ GvENAME((GV*)dstr));
+ }
}
cv_ckproto(cv, (GV*)dstr,
SvPOK(sref) ? SvPVX(sref) : Nullch);
if (SvTEMP(sstr) && /* slated for free anyway? */
SvREFCNT(sstr) == 1 && /* and no other references to it? */
- !(sflags & SVf_OOK)) /* and not involved in OOK hack? */
+ !(sflags & SVf_OOK) && /* and not involved in OOK hack? */
+ SvLEN(sstr)) /* and really is a string */
{
if (SvPVX(dstr)) { /* we know that dtype >= SVt_PV */
if (SvOOK(dstr)) {
=for apidoc sv_usepvn
Tells an SV to use C<ptr> to find its string value. Normally the string is
-stored inside the SV but sv_usepvn allows the SV to use an outside string.
+stored inside the SV but sv_usepvn allows the SV to use an outside string.
The C<ptr> should point to memory that was allocated by C<malloc>. The
string length, C<len>, must be supplied. This function will realloc the
memory pointed to by C<ptr>, so that pointer should not be freed or used by
{
if (SvREADONLY(sv)) {
dTHR;
- if (PL_curcop != &PL_compiling)
+ if (SvFAKE(sv)) {
+ char *pvx = SvPVX(sv);
+ STRLEN len = SvCUR(sv);
+ U32 hash = SvUVX(sv);
+ SvGROW(sv, len + 1);
+ Move(pvx,SvPVX(sv),len,char);
+ *SvEND(sv) = '\0';
+ SvFAKE_off(sv);
+ SvREADONLY_off(sv);
+ unsharepvn(pvx,len,hash);
+ }
+ else if (PL_curcop != &PL_compiling)
Perl_croak(aTHX_ PL_no_modify);
}
if (SvROK(sv))
else if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
sv_unglob(sv);
}
-
+
/*
=for apidoc sv_chop
-Efficient removal of characters from the beginning of the string buffer.
+Efficient removal of characters from the beginning of the string buffer.
SvPOK(sv) must be true and the C<ptr> must be a pointer to somewhere inside
the string buffer. The C<ptr> becomes the first character of the adjusted
string.
void
Perl_sv_chop(pTHX_ register SV *sv, register char *ptr) /* like set but assuming ptr is in sv */
-
-
+
+
{
register STRLEN delta;
Perl_newSV(pTHX_ STRLEN len)
{
register SV *sv;
-
+
new_SV(sv);
if (len) {
sv_upgrade(sv, SVt_PV);
Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 namlen)
{
MAGIC* mg;
-
+
if (SvREADONLY(sv)) {
dTHR;
if (PL_curcop != &PL_compiling && !strchr("gBf", how))
mg->mg_ptr = savepvn(name, namlen);
else if (namlen == HEf_SVKEY)
mg->mg_ptr = (char*)SvREFCNT_inc((SV*)name);
-
+
switch (how) {
case 0:
mg->mg_virtual = &PL_vtbl_sv;
tsv = SvRV(sv);
sv_add_backref(tsv, sv);
SvWEAKREF_on(sv);
- SvREFCNT_dec(tsv);
+ SvREFCNT_dec(tsv);
return sv;
}
av_push(av,sv);
}
-STATIC void
+STATIC void
S_sv_del_backref(pTHX_ SV *sv)
{
AV *av;
register char *bigend;
register I32 i;
STRLEN curlen;
-
+
if (!bigstr)
Perl_croak(aTHX_ "Can't modify non-existent substring");
}
else if (SvPVX(sv) && SvLEN(sv))
Safefree(SvPVX(sv));
+ else if (SvPVX(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
+ unsharepvn(SvPVX(sv),SvCUR(sv),SvUVX(sv));
+ SvFAKE_off(sv);
+ }
break;
/*
case SVt_NV:
}
if (s != send) {
dTHR;
- if (ckWARN_d(WARN_UTF8))
+ if (ckWARN_d(WARN_UTF8))
Perl_warner(aTHX_ WARN_UTF8, "Malformed UTF-8 character");
--len;
}
pv2 = SvPV(sv2, cur2);
/* do not utf8ize the comparands as a side-effect */
- if (cur1 && cur2 && SvUTF8(sv1) != SvUTF8(sv2) && !IN_BYTE && 0) {
+ if (cur1 && cur2 && SvUTF8(sv1) != SvUTF8(sv2) && !IN_BYTE) {
if (SvUTF8(sv1)) {
pv2 = (char*)bytes_to_utf8((U8*)pv2, &cur2);
pv2tmp = TRUE;
{
STRLEN cur1, cur2;
char *pv1, *pv2;
- I32 cmp;
+ I32 cmp;
bool pv1tmp = FALSE;
bool pv2tmp = FALSE;
/* See if we know enough about I/O mechanism to cheat it ! */
/* This used to be #ifdef test - it is made run-time test for ease
- of abstracting out stdio interface. One call should be cheap
+ of abstracting out stdio interface. One call should be cheap
enough here - and may even be a macro allowing compile
time optimization.
*/
"Screamer: entering, ptr=%"UVuf", cnt=%ld\n",PTR2UV(ptr),(long)cnt));
DEBUG_P(PerlIO_printf(Perl_debug_log,
"Screamer: entering: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
- PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+ PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
PTR2UV(PerlIO_has_base(fp) ? PerlIO_get_base(fp) : 0)));
for (;;) {
screamer:
}
}
else {
- Copy(ptr, bp, cnt, char); /* this | eat */
- bp += cnt; /* screams | dust */
+ Copy(ptr, bp, cnt, char); /* this | eat */
+ bp += cnt; /* screams | dust */
ptr += cnt; /* louder | sed :-) */
cnt = 0;
}
PerlIO_set_ptrcnt(fp, ptr, cnt); /* deregisterize cnt and ptr */
DEBUG_P(PerlIO_printf(Perl_debug_log,
"Screamer: pre: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
- PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+ PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
- /* This used to call 'filbuf' in stdio form, but as that behaves like
+ /* This used to call 'filbuf' in stdio form, but as that behaves like
getc when cnt <= 0 we use PerlIO_getc here to avoid introducing
another abstraction. */
i = PerlIO_getc(fp); /* get more characters */
DEBUG_P(PerlIO_printf(Perl_debug_log,
"Screamer: post: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
- PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+ PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
cnt = PerlIO_get_cnt(fp);
ptr = (STDCHAR*)PerlIO_get_ptr(fp); /* reregisterize cnt and ptr */
PerlIO_set_ptrcnt(fp, ptr, cnt); /* put these back or we're in trouble */
DEBUG_P(PerlIO_printf(Perl_debug_log,
"Screamer: end: FILE * thinks ptr=%"UVuf", cnt=%ld, base=%"UVuf"\n",
- PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
+ PTR2UV(PerlIO_get_ptr(fp)), (long)PerlIO_get_cnt(fp),
PTR2UV(PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0)));
*bp = '\0';
SvCUR_set(sv, bp - (STDCHAR*)SvPVX(sv)); /* set length */
}
}
- if (RsPARA(PL_rs)) { /* have to do this both before and after */
+ if (RsPARA(PL_rs)) { /* have to do this both before and after */
while (i != EOF) { /* to make sure file boundaries work right */
i = PerlIO_getc(fp);
if (i != '\n') {
else {
(void)SvIOK_only(sv);
++SvIVX(sv);
- }
+ }
}
return;
}
/* MKS: The original code here died if letters weren't consecutive.
* at least it didn't have to worry about non-C locales. The
* new code assumes that ('z'-'a')==('Z'-'A'), letters are
- * arranged in order (although not consecutively) and that only
+ * arranged in order (although not consecutively) and that only
* [A-Za-z] are accepted by isALPHA in the C locale.
*/
if (*d != 'z' && *d != 'Z') {
else {
(void)SvIOK_only_UV(sv);
--SvUVX(sv);
- }
+ }
} else {
if (SvIVX(sv) == IV_MIN)
sv_setnv(sv, (NV)IV_MIN - 1.0);
else {
(void)SvIOK_only(sv);
--SvIVX(sv);
- }
+ }
}
return;
}
=for apidoc newSVpvn
Creates a new SV and copies a string into it. The reference count for the
-SV is set to 1. Note that if C<len> is zero, Perl will create a zero length
+SV is set to 1. Note that if C<len> is zero, Perl will create a zero length
string. You are responsible for ensuring that the source string is at least
C<len> bytes long.
return sv;
}
+/*
+=for apidoc newSVpvn_share
+
+Creates a new SV and populates it with a string from
+the string table. Turns on READONLY and FAKE.
+The idea here is that as string table is used for shared hash
+keys these strings will have SvPVX == HeKEY and hash lookup
+will avoid string compare.
+
+=cut
+*/
+
+SV *
+Perl_newSVpvn_share(pTHX_ const char *src, STRLEN len, U32 hash)
+{
+ register SV *sv;
+ if (!hash)
+ PERL_HASH(hash, src, len);
+ new_SV(sv);
+ sv_upgrade(sv, SVt_PVIV);
+ SvPVX(sv) = sharepvn(src, len, hash);
+ SvCUR(sv) = len;
+ SvUVX(sv) = hash;
+ SvLEN(sv) = 0;
+ SvREADONLY_on(sv);
+ SvFAKE_on(sv);
+ SvPOK_on(sv);
+ return sv;
+}
+
#if defined(PERL_IMPLICIT_CONTEXT)
SV *
Perl_newSVpvf_nocontext(const char* pat, ...)
}
if (GvHV(gv) && !HvNAME(GvHV(gv))) {
hv_clear(GvHV(gv));
-#ifndef VMS /* VMS has no environ array */
+#if !defined( VMS) && !defined(EPOC) /* VMS has no environ array */
if (gv == PL_envgv)
environ[0] = Nullch;
#endif
if (SvTHINKFIRST(sv) && !SvROK(sv))
sv_force_normal(sv);
-
+
if (SvPOK(sv)) {
*lp = SvCUR(sv);
}
s = sv_2pv(sv, lp);
if (s != SvPVX(sv)) { /* Almost, but not quite, sv_setpvn() */
STRLEN len = *lp;
-
+
if (SvROK(sv))
sv_unref(sv);
(void)SvUPGRADE(sv, SVt_PV); /* Never FALSE */
SV_CHECK_THINKFIRST(rv);
SvAMAGIC_off(rv);
+ if (SvTYPE(rv) >= SVt_PVMG) {
+ U32 refcnt = SvREFCNT(rv);
+ SvREFCNT(rv) = 0;
+ sv_clear(rv);
+ SvFLAGS(rv) = 0;
+ SvREFCNT(rv) = refcnt;
+ }
+
if (SvTYPE(rv) < SVt_RV)
- sv_upgrade(rv, SVt_RV);
+ sv_upgrade(rv, SVt_RV);
+ else if (SvTYPE(rv) > SVt_RV) {
+ (void)SvOOK_off(rv);
+ if (SvPVX(rv) && SvLEN(rv))
+ Safefree(SvPVX(rv));
+ SvCUR_set(rv, 0);
+ SvLEN_set(rv, 0);
+ }
(void)SvOK_off(rv);
SvRV(rv) = sv;
bool has_precis = FALSE;
STRLEN precis = 0;
bool is_utf = FALSE;
-
+
char esignbuf[4];
U8 utf8buf[UTF8_MAXLEN];
STRLEN esignlen = 0;
STRLEN gap;
char *dotstr = ".";
STRLEN dotstrlen = 1;
+ I32 epix = 0; /* explicit parameter index */
+ I32 ewix = 0; /* explicit width index */
+ bool asterisk = FALSE;
for (q = p; q < patend && *q != '%'; ++q) ;
if (q > p) {
/* WIDTH */
+ scanwidth:
+
+ if (*q == '*') {
+ if (asterisk)
+ goto unknown;
+ asterisk = TRUE;
+ q++;
+ }
+
switch (*q) {
case '1': case '2': case '3':
case '4': case '5': case '6':
width = 0;
while (isDIGIT(*q))
width = width * 10 + (*q++ - '0');
- break;
+ if (*q == '$') {
+ if (asterisk && ewix == 0) {
+ ewix = width;
+ width = 0;
+ q++;
+ goto scanwidth;
+ } else if (epix == 0) {
+ epix = width;
+ width = 0;
+ q++;
+ goto scanwidth;
+ } else
+ goto unknown;
+ }
+ }
- case '*':
+ if (asterisk) {
if (args)
i = va_arg(*args, int);
else
- i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ i = (ewix ? ewix <= svmax : svix < svmax) ?
+ SvIVx(svargs[ewix ? ewix-1 : svix++]) : 0;
left |= (i < 0);
width = (i < 0) ? -i : i;
- q++;
- break;
}
/* PRECISION */
if (args)
i = va_arg(*args, int);
else
- i = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ i = (ewix ? ewix <= svmax : svix < svmax)
+ ? SvIVx(svargs[ewix ? ewix-1 : svix++]) : 0;
precis = (i < 0) ? 0 : i;
q++;
}
vecstr = (U8*)SvPVx(vecsv,veclen);
utf = DO_UTF8(vecsv);
}
- else if (svix < svmax) {
- vecsv = svargs[svix++];
+ else if (epix ? epix <= svmax : svix < svmax) {
+ vecsv = svargs[epix ? epix-1 : svix++];
vecstr = (U8*)SvPVx(vecsv,veclen);
utf = DO_UTF8(vecsv);
}
/* SIZE */
switch (*q) {
-#ifdef HAS_QUAD
+#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE))
case 'L': /* Ld */
+ /* FALL THROUGH */
+#endif
+#ifdef HAS_QUAD
case 'q': /* qd */
intsize = 'q';
q++;
break;
#endif
case 'l':
-#ifdef HAS_QUAD
- if (*(q + 1) == 'l') { /* lld */
+#if defined(HAS_QUAD) || (defined(HAS_LONG_DOUBLE) && defined(USE_LONG_DOUBLE))
+ if (*(q + 1) == 'l') { /* lld, llf */
intsize = 'q';
q += 2;
break;
if (args)
uv = va_arg(*args, int);
else
- uv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ SvIVx(svargs[epix ? epix-1 : svix++]) : 0;
if ((uv > 255 || (uv > 127 && SvUTF8(sv))) && !IN_BYTE) {
eptr = (char*)utf8buf;
elen = uv_to_utf8((U8*)eptr, uv) - utf8buf;
elen = sizeof nullstr - 1;
}
}
- else if (svix < svmax) {
- argsv = svargs[svix++];
+ else if (epix ? epix <= svmax : svix < svmax) {
+ argsv = svargs[epix ? epix-1 : svix++];
eptr = SvPVx(argsv, elen);
if (DO_UTF8(argsv)) {
if (has_precis && precis < elen) {
if (args)
uv = PTR2UV(va_arg(*args, void*));
else
- uv = (svix < svmax) ? PTR2UV(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ PTR2UV(svargs[epix ? epix-1 : svix++]) : 0;
base = 16;
goto integer;
case 'd':
case 'i':
if (vectorize) {
- I32 ulen;
+ STRLEN ulen;
if (!veclen) {
vectorize = FALSE;
break;
}
if (utf)
- iv = (IV)utf8_to_uv(vecstr, &ulen);
+ iv = (IV)utf8_to_uv(vecstr, veclen, &ulen, 0);
else {
iv = *vecstr;
ulen = 1;
}
}
else {
- iv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+ iv = (epix ? epix <= svmax : svix < svmax) ?
+ SvIVx(svargs[epix ? epix-1 : svix++]) : 0;
switch (intsize) {
case 'h': iv = (short)iv; break;
default: break;
uns_integer:
if (vectorize) {
- I32 ulen;
+ STRLEN ulen;
vector:
if (!veclen) {
vectorize = FALSE;
break;
}
if (utf)
- uv = utf8_to_uv(vecstr, &ulen);
+ uv = utf8_to_uv(vecstr, veclen, &ulen, 0);
else {
uv = *vecstr;
ulen = 1;
}
}
else {
- uv = (svix < svmax) ? SvUVx(svargs[svix++]) : 0;
+ uv = (epix ? epix <= svmax : svix < svmax) ?
+ SvUVx(svargs[epix ? epix-1 : svix++]) : 0;
switch (intsize) {
case 'h': uv = (unsigned short)uv; break;
default: break;
if (args)
nv = va_arg(*args, NV);
else
- nv = (svix < svmax) ? SvNVx(svargs[svix++]) : 0.0;
+ nv = (epix ? epix <= svmax : svix < svmax) ?
+ SvNVx(svargs[epix ? epix-1 : svix++]) : 0.0;
need = 0;
if (c != 'e' && c != 'E') {
eptr = ebuf + sizeof ebuf;
*--eptr = '\0';
*--eptr = c;
-#ifdef USE_LONG_DOUBLE
+#if defined(USE_LONG_DOUBLE) && defined(PERL_PRIfldbl)
{
- static char const my_prifldbl[] = PERL_PRIfldbl;
- char const *p = my_prifldbl + sizeof my_prifldbl - 3;
- while (p >= my_prifldbl) { *--eptr = *p--; }
+ /* Copy the one or more characters in a long double
+ * format before the 'base' ([efgEFG]) character to
+ * the format string. */
+ static char const prifldbl[] = PERL_PRIfldbl;
+ char const *p = prifldbl + sizeof(prifldbl) - 3;
+ while (p >= prifldbl) { *--eptr = *p--; }
}
#endif
if (has_precis) {
*--eptr = '%';
{
- RESTORE_NUMERIC_STANDARD();
+ STORE_NUMERIC_STANDARD_SET_LOCAL();
+#ifdef USE_LOCALE_NUMERIC
+ if (!was_standard && maybe_tainted)
+ *maybe_tainted = TRUE;
+#endif
(void)sprintf(PL_efloatbuf, eptr, nv);
- RESTORE_NUMERIC_LOCAL();
+ RESTORE_NUMERIC_STANDARD();
}
+
eptr = PL_efloatbuf;
elen = strlen(PL_efloatbuf);
-
-#if PRINTF_EXP_DIGITS == 3 /* Shorten exponent */
- if (((p = index(eptr, 'e')) || (p = index(eptr, 'E'))) &&
- (*++p == '+' || *p == '-') && /* Is there exponent */
- *++p == '0') { /* with leading zero? */
- DEBUG_c(PerlIO_printf(Perl_debug_log,
- ">%s<: '0' at %d from start; "
- "elen == %d, width == %d\n",
- eptr, p-eptr, elen, width));
- Move(p+1, p, 3, char); /* Suppress leading zero */
- if (elen == width && /* Fix up padding if */
- *(p+2) == '\0') { /* necessary */
- if (!left) {
- if (fill == '0') {
- Move(eptr+1, eptr+2, elen-1, char);
- *(eptr+1) = '0';
- }
- else {
- Move(eptr, eptr+1, elen, char);
- *eptr = ' ';
- }
- }
- else {
- *(p+2) == ' '; *(p+3) = '\0';
- }
- }
- else if (elen > width)
- elen--;
- }
-# endif
break;
/* SPECIAL */
#endif
}
}
- else if (svix < svmax)
- sv_setuv_mg(svargs[svix++], (UV)i);
+ else if (epix ? epix <= svmax : svix < svmax)
+ sv_setuv_mg(svargs[epix ? epix-1 : svix++], (UV)i);
continue; /* not "break" */
/* UNKNOWN */
(PL_op->op_type == OP_PRTF) ? "printf" : "sprintf");
if (c) {
if (isPRINT(c))
- Perl_sv_catpvf(aTHX_ msg,
+ Perl_sv_catpvf(aTHX_ msg,
"\"%%%c\"", c & 0xFF);
else
Perl_sv_catpvf(aTHX_ msg,
if (SvROK(sv) && SvOBJECT(rv = SvRV(sv))) {
DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning object ref:\n "), sv_dump(sv));)
- SvROK_off(sv);
- SvRV(sv) = 0;
- SvREFCNT_dec(rv);
+ if (SvWEAKREF(sv)) {
+ sv_del_backref(sv);
+ SvWEAKREF_off(sv);
+ SvRV(sv) = 0;
+ } else {
+ SvROK_off(sv);
+ SvRV(sv) = 0;
+ SvREFCNT_dec(rv);
+ }
}
/* XXX Might want to check arrays, etc. */
SvFLAGS(sv) |= SVf_BREAK;
SvREFCNT_dec(sv);
}
+