# define FAST_SV_GETS
#endif
+#ifdef PERL_OBJECT
+#define FCALL this->*f
+#define VTBL this->*vtbl
+
+#else /* !PERL_OBJECT */
+
static IV asIV _((SV* sv));
static UV asUV _((SV* sv));
static SV *more_sv _((void));
static void sv_unglob _((SV* sv));
static void sv_check_thinkfirst _((SV *sv));
+#ifndef PURIFY
+static void *my_safemalloc(MEM_SIZE size);
+#endif
+
typedef void (*SVFUNC) _((SV*));
+#define VTBL *vtbl
+#define FCALL *f
+
+#endif /* PERL_OBJECT */
+
+#define SV_CHECK_THINKFIRST(sv) if (SvTHINKFIRST(sv)) sv_check_thinkfirst(sv)
#ifdef PURIFY
} while (0)
static SV **registry;
-static I32 regsize;
+static I32 registry_size;
#define REGHASH(sv,size) ((((U32)(sv)) >> 2) % (size))
#define REG_REPLACE(sv,a,b) \
do { \
void* p = sv->sv_any; \
- I32 h = REGHASH(sv, regsize); \
+ I32 h = REGHASH(sv, registry_size); \
I32 i = h; \
while (registry[i] != (a)) { \
- if (++i >= regsize) \
+ if (++i >= registry_size) \
i = 0; \
if (i == h) \
die("SV registry bug"); \
reg_add(sv)
SV* sv;
{
- if (sv_count >= (regsize >> 1))
+ if (sv_count >= (registry_size >> 1))
{
SV **oldreg = registry;
- I32 oldsize = regsize;
+ I32 oldsize = registry_size;
- regsize = regsize ? ((regsize << 2) + 1) : 2037;
- registry = (SV**)safemalloc(regsize * sizeof(SV*));
- memzero(registry, regsize * sizeof(SV*));
+ registry_size = registry_size ? ((registry_size << 2) + 1) : 2037;
+ Newz(707, registry, registry_size, SV*);
if (oldreg) {
I32 i;
{
I32 i;
- for (i = 0; i < regsize; ++i) {
+ for (i = 0; i < registry_size; ++i) {
SV* sv = registry[i];
- if (sv)
+ if (sv && SvTYPE(sv) != SVTYPEMASK)
(*f)(sv);
}
}
UNLOCK_SV_MUTEX; \
} while (0)
-static void
+STATIC void
del_sv(SV *p)
{
if (debug & 32768) {
}
/* sv_mutex must be held while calling more_sv() */
-static SV*
+STATIC SV*
more_sv(void)
{
register SV* sv;
return sv;
}
-static void
+STATIC void
visit(SVFUNC f)
{
SV* sva;
svend = &sva[SvREFCNT(sva)];
for (sv = sva + 1; sv < svend; ++sv) {
if (SvTYPE(sv) != SVTYPEMASK)
- (*f)(sv);
+ (FCALL)(sv);
}
}
}
#endif /* PURIFY */
-static void
+STATIC void
do_report_used(SV *sv)
{
if (SvTYPE(sv) != SVTYPEMASK) {
void
sv_report_used(void)
{
- visit(do_report_used);
+ visit(FUNC_NAME_TO_PTR(do_report_used));
}
-static void
+STATIC void
do_clean_objs(SV *sv)
{
SV* rv;
}
#ifndef DISABLE_DESTRUCTOR_KLUDGE
-static void
+STATIC void
do_clean_named_objs(SV *sv)
{
- if (SvTYPE(sv) == SVt_PVGV && GvSV(sv))
- do_clean_objs(GvSV(sv));
+ if (SvTYPE(sv) == SVt_PVGV) {
+ if ( SvOBJECT(GvSV(sv)) ||
+ GvAV(sv) && SvOBJECT(GvAV(sv)) ||
+ GvHV(sv) && SvOBJECT(GvHV(sv)) ||
+ GvIO(sv) && SvOBJECT(GvIO(sv)) ||
+ GvCV(sv) && SvOBJECT(GvCV(sv)) )
+ {
+ DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning named glob object:\n "), sv_dump(sv));)
+ SvREFCNT_dec(sv);
+ }
+ }
}
#endif
-static bool in_clean_objs = FALSE;
-
void
sv_clean_objs(void)
{
in_clean_objs = TRUE;
+ visit(FUNC_NAME_TO_PTR(do_clean_objs));
#ifndef DISABLE_DESTRUCTOR_KLUDGE
- visit(do_clean_named_objs);
+ /* some barnacles may yet remain, clinging to typeglobs */
+ visit(FUNC_NAME_TO_PTR(do_clean_named_objs));
#endif
- visit(do_clean_objs);
in_clean_objs = FALSE;
}
-static void
+STATIC void
do_clean_all(SV *sv)
{
DEBUG_D((PerlIO_printf(Perl_debug_log, "Cleaning loops:\n "), sv_dump(sv));)
SvREFCNT_dec(sv);
}
-static bool in_clean_all = FALSE;
-
void
sv_clean_all(void)
{
in_clean_all = TRUE;
- visit(do_clean_all);
+ visit(FUNC_NAME_TO_PTR(do_clean_all));
in_clean_all = FALSE;
}
Safefree((void *)sva);
}
+ if (nice_chunk)
+ Safefree(nice_chunk);
+ nice_chunk = Nullch;
+ nice_chunk_size = 0;
sv_arenaroot = 0;
sv_root = 0;
}
-static XPVIV*
+STATIC XPVIV*
new_xiv(void)
{
IV** xiv;
return more_xiv();
}
-static void
+STATIC void
del_xiv(XPVIV *p)
{
IV** xiv = (IV**)((char*)(p) + sizeof(XPV));
xiv_root = xiv;
}
-static XPVIV*
+STATIC XPVIV*
more_xiv(void)
{
register IV** xiv;
register IV** xivend;
- XPV* ptr = (XPV*)safemalloc(1008);
+ XPV* ptr;
+ New(705, ptr, 1008/sizeof(XPV), XPV);
ptr->xpv_pv = (char*)xiv_arenaroot; /* linked list of xiv arenas */
xiv_arenaroot = ptr; /* to keep Purify happy */
return new_xiv();
}
-static XPVNV*
+STATIC XPVNV*
new_xnv(void)
{
double* xnv;
return more_xnv();
}
-static void
+STATIC void
del_xnv(XPVNV *p)
{
double* xnv = (double*)((char*)(p) + sizeof(XPVIV));
xnv_root = xnv;
}
-static XPVNV*
+STATIC XPVNV*
more_xnv(void)
{
register double* xnv;
register double* xnvend;
- xnv = (double*)safemalloc(1008);
+ New(711, xnv, 1008/sizeof(double), double);
xnvend = &xnv[1008 / sizeof(double) - 1];
xnv += (sizeof(XPVIV) - 1) / sizeof(double) + 1; /* fudge by sizeof XPVIV */
xnv_root = xnv;
return new_xnv();
}
-static XRV*
+STATIC XRV*
new_xrv(void)
{
XRV* xrv;
return more_xrv();
}
-static void
+STATIC void
del_xrv(XRV *p)
{
p->xrv_rv = (SV*)xrv_root;
xrv_root = p;
}
-static XRV*
+STATIC XRV*
more_xrv(void)
{
register XRV* xrv;
register XRV* xrvend;
- xrv_root = (XRV*)safemalloc(1008);
+ New(712, xrv_root, 1008/sizeof(XRV), XRV);
xrv = xrv_root;
xrvend = &xrv[1008 / sizeof(XRV) - 1];
while (xrv < xrvend) {
return new_xrv();
}
-static XPV*
+STATIC XPV*
new_xpv(void)
{
XPV* xpv;
return more_xpv();
}
-static void
+STATIC void
del_xpv(XPV *p)
{
p->xpv_pv = (char*)xpv_root;
xpv_root = p;
}
-static XPV*
+STATIC XPV*
more_xpv(void)
{
register XPV* xpv;
register XPV* xpvend;
- xpv_root = (XPV*)safemalloc(1008);
+ New(713, xpv_root, 1008/sizeof(XPV), XPV);
xpv = xpv_root;
xpvend = &xpv[1008 / sizeof(XPV) - 1];
while (xpv < xpvend) {
#define del_XPV(p) del_xpv((XPV *)p)
#endif
-#define new_XPVIV() (void*)safemalloc(sizeof(XPVIV))
-#define del_XPVIV(p) Safefree((char*)p)
-
-#define new_XPVNV() (void*)safemalloc(sizeof(XPVNV))
-#define del_XPVNV(p) Safefree((char*)p)
-
-#define new_XPVMG() (void*)safemalloc(sizeof(XPVMG))
-#define del_XPVMG(p) Safefree((char*)p)
-
-#define new_XPVLV() (void*)safemalloc(sizeof(XPVLV))
-#define del_XPVLV(p) Safefree((char*)p)
-
-#define new_XPVAV() (void*)safemalloc(sizeof(XPVAV))
-#define del_XPVAV(p) Safefree((char*)p)
-
-#define new_XPVHV() (void*)safemalloc(sizeof(XPVHV))
-#define del_XPVHV(p) Safefree((char*)p)
-
-#define new_XPVCV() (void*)safemalloc(sizeof(XPVCV))
-#define del_XPVCV(p) Safefree((char*)p)
-
-#define new_XPVGV() (void*)safemalloc(sizeof(XPVGV))
-#define del_XPVGV(p) Safefree((char*)p)
-
-#define new_XPVBM() (void*)safemalloc(sizeof(XPVBM))
-#define del_XPVBM(p) Safefree((char*)p)
-
-#define new_XPVFM() (void*)safemalloc(sizeof(XPVFM))
-#define del_XPVFM(p) Safefree((char*)p)
-
-#define new_XPVIO() (void*)safemalloc(sizeof(XPVIO))
-#define del_XPVIO(p) Safefree((char*)p)
+#ifdef PURIFY
+# define my_safemalloc(s) safemalloc(s)
+# define my_safefree(s) free(s)
+#else
+STATIC void*
+my_safemalloc(MEM_SIZE size)
+{
+ char *p;
+ New(717, p, size, char);
+ return (void*)p;
+}
+# define my_safefree(s) Safefree(s)
+#endif
+
+#define new_XPVIV() (void*)my_safemalloc(sizeof(XPVIV))
+#define del_XPVIV(p) my_safefree((char*)p)
+
+#define new_XPVNV() (void*)my_safemalloc(sizeof(XPVNV))
+#define del_XPVNV(p) my_safefree((char*)p)
+
+#define new_XPVMG() (void*)my_safemalloc(sizeof(XPVMG))
+#define del_XPVMG(p) my_safefree((char*)p)
+
+#define new_XPVLV() (void*)my_safemalloc(sizeof(XPVLV))
+#define del_XPVLV(p) my_safefree((char*)p)
+
+#define new_XPVAV() (void*)my_safemalloc(sizeof(XPVAV))
+#define del_XPVAV(p) my_safefree((char*)p)
+
+#define new_XPVHV() (void*)my_safemalloc(sizeof(XPVHV))
+#define del_XPVHV(p) my_safefree((char*)p)
+
+#define new_XPVCV() (void*)my_safemalloc(sizeof(XPVCV))
+#define del_XPVCV(p) my_safefree((char*)p)
+
+#define new_XPVGV() (void*)my_safemalloc(sizeof(XPVGV))
+#define del_XPVGV(p) my_safefree((char*)p)
+
+#define new_XPVBM() (void*)my_safemalloc(sizeof(XPVBM))
+#define del_XPVBM(p) my_safefree((char*)p)
+
+#define new_XPVFM() (void*)my_safemalloc(sizeof(XPVFM))
+#define del_XPVFM(p) my_safefree((char*)p)
+
+#define new_XPVIO() (void*)my_safemalloc(sizeof(XPVIO))
+#define del_XPVIO(p) my_safefree((char*)p)
bool
sv_upgrade(register SV *sv, U32 mt)
return TRUE;
}
-#ifdef DEBUGGING
char *
sv_peek(SV *sv)
{
+#ifdef DEBUGGING
SV *t = sv_newmortal();
STRLEN prevlen;
int unref = 0;
sv_catpv(t, ")");
}
return SvPV(t, na);
+#else /* DEBUGGING */
+ return "";
+#endif /* DEBUGGING */
}
-#endif
int
sv_backoff(register SV *sv)
s = SvPVX(sv);
if (newlen > SvLEN(sv))
newlen += 10 * (newlen - SvCUR(sv)); /* avoid copy each time */
+#ifdef HAS_64K_LIMIT
+ if (newlen >= 0x10000)
+ newlen = 0xFFFF;
+#endif
}
else
s = SvPVX(sv);
if (newlen > SvLEN(sv)) { /* need more room? */
- if (SvLEN(sv) && s)
+ if (SvLEN(sv) && s) {
+#ifdef MYMALLOC
+ STRLEN l = malloced_size((void*)SvPVX(sv));
+ if (newlen <= l) {
+ SvLEN_set(sv, l);
+ return s;
+ } else
+#endif
Renew(s,newlen,char);
+ }
else
New(703,s,newlen,char);
SvPV_set(sv, s);
void
sv_setiv(register SV *sv, IV i)
{
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
switch (SvTYPE(sv)) {
case SVt_NULL:
sv_upgrade(sv, SVt_IV);
}
void
+sv_setiv_mg(register SV *sv, IV i)
+{
+ sv_setiv(sv,i);
+ SvSETMAGIC(sv);
+}
+
+void
sv_setuv(register SV *sv, UV u)
{
if (u <= IV_MAX)
}
void
+sv_setuv_mg(register SV *sv, UV u)
+{
+ sv_setuv(sv,u);
+ SvSETMAGIC(sv);
+}
+
+void
sv_setnv(register SV *sv, double num)
{
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
switch (SvTYPE(sv)) {
case SVt_NULL:
case SVt_IV:
sv_upgrade(sv, SVt_NV);
break;
- case SVt_NV:
case SVt_RV:
case SVt_PV:
case SVt_PVIV:
SvTAINT(sv);
}
-static void
+void
+sv_setnv_mg(register SV *sv, double num)
+{
+ sv_setnv(sv,num);
+ SvSETMAGIC(sv);
+}
+
+STATIC void
not_a_number(SV *sv)
{
dTHR;
return SvNVX(sv);
}
-static IV
+STATIC IV
asIV(SV *sv)
{
I32 numtype = looks_like_number(sv);
return (IV) U_V(d);
}
-static UV
+STATIC UV
asUV(SV *sv)
{
I32 numtype = looks_like_number(sv);
if (!sv)
s = "NULLREF";
else {
+ MAGIC *mg;
+
switch (SvTYPE(sv)) {
+ case SVt_PVMG:
+ if ( ((SvFLAGS(sv) &
+ (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'))) {
+ regexp *re = (regexp *)mg->mg_obj;
+
+ *lp = re->prelen;
+ return re->precomp;
+ }
+ /* Fall through */
case SVt_NULL:
case SVt_IV:
case SVt_NV:
case SVt_PV:
case SVt_PVIV:
case SVt_PVNV:
- case SVt_PVBM:
- case SVt_PVMG: s = "SCALAR"; break;
+ case SVt_PVBM: s = "SCALAR"; break;
case SVt_PVLV: s = "LVALUE"; break;
case SVt_PVAV: s = "ARRAY"; break;
case SVt_PVHV: s = "HASH"; break;
case SVt_PVCV: s = "CODE"; break;
case SVt_PVGV: s = "GLOB"; break;
- case SVt_PVFM: s = "FORMATLINE"; break;
+ case SVt_PVFM: s = "FORMAT"; break;
case SVt_PVIO: s = "IO"; break;
default: s = "UNKNOWN"; break;
}
return "";
}
}
- if (!SvUPGRADE(sv, SVt_PV))
- return 0;
+ (void)SvUPGRADE(sv, SVt_PV);
if (SvNOKp(sv)) {
if (SvTYPE(sv) < SVt_PVNV)
sv_upgrade(sv, SVt_PVNV);
if (sstr == dstr)
return;
- sv_check_thinkfirst(dstr);
+ SV_CHECK_THINKFIRST(dstr);
if (!sstr)
sstr = &sv_undef;
stype = SvTYPE(sstr);
switch (stype) {
case SVt_NULL:
- (void)SvOK_off(dstr);
- return;
+ if (dtype != SVt_PVGV) {
+ (void)SvOK_off(dstr);
+ return;
+ }
+ break;
case SVt_IV:
if (dtype != SVt_IV && dtype < SVt_PVIV) {
if (dtype < SVt_IV)
if (dtype < SVt_PVNV)
sv_upgrade(dstr, SVt_PVNV);
break;
-
case SVt_PVAV:
case SVt_PVHV:
case SVt_PVCV:
STRLEN len = GvNAMELEN(sstr);
sv_upgrade(dstr, SVt_PVGV);
sv_magic(dstr, dstr, '*', name, len);
- GvSTASH(dstr) = GvSTASH(sstr);
+ GvSTASH(dstr) = (HV*)SvREFCNT_inc(GvSTASH(sstr));
GvNAME(dstr) = savepvn(name, len);
GvNAMELEN(dstr) = len;
SvFAKE_on(dstr); /* can coerce to non-glob */
}
/* ahem, death to those who redefine active sort subs */
- else if (curstack == sortstack
+ else if (curstackinfo->si_type == SI_SORT
&& GvCV(dstr) && sortcop == CvSTART(GvCV(dstr)))
croak("Can't redefine active sort subroutine %s",
GvNAME(dstr));
goto glob_assign;
}
}
- if (dtype < stype)
- sv_upgrade(dstr, stype);
+ if (stype == SVt_PVLV)
+ SvUPGRADE(dstr, SVt_PVNV);
+ else
+ SvUPGRADE(dstr, stype);
}
sflags = SvFLAGS(sstr);
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),
+ Nullcv));
/* ahem, death to those who redefine
* active sort subs */
- if (curstack == sortstack &&
+ if (curstackinfo->si_type == SI_SORT &&
sortcop == CvSTART(cv))
croak(
"Can't redefine active sort subroutine %s",
GvENAME((GV*)dstr));
- if (cv_const_sv(cv))
- warn("Constant subroutine %s redefined",
- GvENAME((GV*)dstr));
- else if (dowarn)
- warn("Subroutine %s redefined",
- GvENAME((GV*)dstr));
+ if (dowarn || (const_changed && const_sv)) {
+ if (!(CvGV(cv) && GvSTASH(CvGV(cv))
+ && HvNAME(GvSTASH(CvGV(cv)))
+ && strEQ(HvNAME(GvSTASH(CvGV(cv))),
+ "autouse")))
+ warn(const_sv ?
+ "Constant subroutine %s redefined"
+ : "Subroutine %s redefined",
+ GvENAME((GV*)dstr));
+ }
}
cv_ckproto(cv, (GV*)dstr,
SvPOK(sref) ? SvPVX(sref) : Nullch);
SvIVX(dstr) = SvIVX(sstr);
}
else {
- (void)SvOK_off(dstr);
+ if (dtype == SVt_PVGV) {
+ if (dowarn)
+ warn("Undefined value assigned to typeglob");
+ }
+ else
+ (void)SvOK_off(dstr);
}
SvTAINT(dstr);
}
void
+sv_setsv_mg(SV *dstr, register SV *sstr)
+{
+ sv_setsv(dstr,sstr);
+ SvSETMAGIC(dstr);
+}
+
+void
sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
{
+ register char *dptr;
assert(len >= 0); /* STRLEN is probably unsigned, so this may
elicit a warning, but it won't hurt. */
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
if (!ptr) {
(void)SvOK_off(sv);
return;
if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
sv_unglob(sv);
}
- else if (!sv_upgrade(sv, SVt_PV))
- return;
+ else
+ sv_upgrade(sv, SVt_PV);
+
SvGROW(sv, len + 1);
- Move(ptr,SvPVX(sv),len,char);
+ dptr = SvPVX(sv);
+ Move(ptr,dptr,len,char);
+ dptr[len] = '\0';
SvCUR_set(sv, len);
- *SvEND(sv) = '\0';
(void)SvPOK_only(sv); /* validate pointer */
SvTAINT(sv);
}
void
+sv_setpvn_mg(register SV *sv, register const char *ptr, register STRLEN len)
+{
+ sv_setpvn(sv,ptr,len);
+ SvSETMAGIC(sv);
+}
+
+void
sv_setpv(register SV *sv, register const char *ptr)
{
register STRLEN len;
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
if (!ptr) {
(void)SvOK_off(sv);
return;
if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
sv_unglob(sv);
}
- else if (!sv_upgrade(sv, SVt_PV))
- return;
+ else
+ sv_upgrade(sv, SVt_PV);
+
SvGROW(sv, len + 1);
Move(ptr,SvPVX(sv),len+1,char);
SvCUR_set(sv, len);
}
void
+sv_setpv_mg(register SV *sv, register const char *ptr)
+{
+ sv_setpv(sv,ptr);
+ SvSETMAGIC(sv);
+}
+
+void
sv_usepvn(register SV *sv, register char *ptr, register STRLEN len)
{
- sv_check_thinkfirst(sv);
- if (!SvUPGRADE(sv, SVt_PV))
- return;
+ SV_CHECK_THINKFIRST(sv);
+ (void)SvUPGRADE(sv, SVt_PV);
if (!ptr) {
(void)SvOK_off(sv);
return;
SvTAINT(sv);
}
-static void
+void
+sv_usepvn_mg(register SV *sv, register char *ptr, register STRLEN len)
+{
+ sv_usepvn(sv,ptr,len);
+ SvSETMAGIC(sv);
+}
+
+STATIC void
sv_check_thinkfirst(register SV *sv)
{
- if (SvTHINKFIRST(sv)) {
- if (SvREADONLY(sv)) {
- dTHR;
- if (curcop != &compiling)
- croak(no_modify);
- }
- if (SvROK(sv))
- sv_unref(sv);
+ if (SvREADONLY(sv)) {
+ dTHR;
+ if (curcop != &compiling)
+ croak(no_modify);
}
+ if (SvROK(sv))
+ sv_unref(sv);
}
void
if (!ptr || !SvPOKp(sv))
return;
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
if (SvTYPE(sv) < SVt_PVIV)
sv_upgrade(sv,SVt_PVIV);
}
void
+sv_catpvn_mg(register SV *sv, register char *ptr, register STRLEN len)
+{
+ sv_catpvn(sv,ptr,len);
+ SvSETMAGIC(sv);
+}
+
+void
sv_catsv(SV *dstr, register SV *sstr)
{
char *s;
}
void
+sv_catsv_mg(SV *dstr, register SV *sstr)
+{
+ sv_catsv(dstr,sstr);
+ SvSETMAGIC(dstr);
+}
+
+void
sv_catpv(register SV *sv, register char *ptr)
{
register STRLEN len;
SvTAINT(sv);
}
+void
+sv_catpv_mg(register SV *sv, register char *ptr)
+{
+ sv_catpv(sv,ptr);
+ SvSETMAGIC(sv);
+}
+
SV *
-#ifdef LEAKTEST
-newSV(x,len)
-I32 x;
-#else
newSV(STRLEN len)
-#endif
-
{
register SV *sv;
}
}
else {
- if (!SvUPGRADE(sv, SVt_PVMG))
- return;
+ (void)SvUPGRADE(sv, SVt_PVMG);
}
Newz(702,mg, 1, MAGIC);
mg->mg_moremagic = SvMAGIC(sv);
if (mg->mg_type == type) {
MGVTBL* vtbl = mg->mg_virtual;
*mgp = mg->mg_moremagic;
- if (vtbl && vtbl->svt_free)
- (*vtbl->svt_free)(sv, mg);
+ if (vtbl && (vtbl->svt_free != NULL))
+ (VTBL->svt_free)(sv, mg);
if (mg->mg_ptr && mg->mg_type != 'g')
if (mg->mg_len >= 0)
Safefree(mg->mg_ptr);
register char *midend;
register char *bigend;
register I32 i;
+ STRLEN curlen;
+
if (!bigstr)
croak("Can't modify non-existent substring");
- SvPV_force(bigstr, na);
+ SvPV_force(bigstr, curlen);
+ if (offset + len > curlen) {
+ SvGROW(bigstr, offset+len+1);
+ Zero(SvPVX(bigstr)+curlen, offset+len-curlen, char);
+ SvCUR_set(bigstr, offset+len);
+ }
i = littlelen - len;
if (i > 0) { /* string might grow */
sv_replace(register SV *sv, register SV *nsv)
{
U32 refcnt = SvREFCNT(sv);
- sv_check_thinkfirst(sv);
+ SV_CHECK_THINKFIRST(sv);
if (SvREFCNT(nsv) != 1)
warn("Reference miscount in sv_replace()");
if (SvMAGICAL(sv)) {
void
sv_clear(register SV *sv)
{
+ HV* stash;
assert(sv);
assert(SvREFCNT(sv) == 0);
if (defstash) { /* Still have a symbol table? */
djSP;
GV* destructor;
+ SV tmpref;
- ENTER;
- SAVEFREESV(SvSTASH(sv));
-
- destructor = gv_fetchmethod(SvSTASH(sv), "DESTROY");
- if (destructor) {
- SV ref;
-
- Zero(&ref, 1, SV);
- sv_upgrade(&ref, SVt_RV);
- SvRV(&ref) = SvREFCNT_inc(sv);
- SvROK_on(&ref);
- SvREFCNT(&ref) = 1; /* Fake, but otherwise
- creating+destructing a ref
- leads to disaster. */
-
- EXTEND(SP, 2);
- PUSHMARK(SP);
- PUSHs(&ref);
- PUTBACK;
- perl_call_sv((SV*)GvCV(destructor),
- G_DISCARD|G_EVAL|G_KEEPERR);
- del_XRV(SvANY(&ref));
- SvREFCNT(sv)--;
- }
+ Zero(&tmpref, 1, SV);
+ sv_upgrade(&tmpref, SVt_RV);
+ SvROK_on(&tmpref);
+ SvREADONLY_on(&tmpref); /* DESTROY() could be naughty */
+ SvREFCNT(&tmpref) = 1;
- LEAVE;
+ do {
+ stash = SvSTASH(sv);
+ destructor = gv_fetchmethod(SvSTASH(sv), "DESTROY");
+ if (destructor) {
+ ENTER;
+ PUSHSTACK(SI_DESTROY);
+ SvRV(&tmpref) = SvREFCNT_inc(sv);
+ EXTEND(SP, 2);
+ PUSHMARK(SP);
+ PUSHs(&tmpref);
+ PUTBACK;
+ perl_call_sv((SV*)GvCV(destructor),
+ G_DISCARD|G_EVAL|G_KEEPERR);
+ SvREFCNT(sv)--;
+ POPSTACK();
+ LEAVE;
+ }
+ } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
+
+ del_XRV(SvANY(&tmpref));
}
- else
- SvREFCNT_dec(SvSTASH(sv));
+
if (SvOBJECT(sv)) {
+ SvREFCNT_dec(SvSTASH(sv)); /* possibly of changed persuasion */
SvOBJECT_off(sv); /* Curse the object. */
if (SvTYPE(sv) != SVt_PVIO)
--sv_objcount; /* XXX Might want something more general */
}
if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
mg_free(sv);
+ stash = NULL;
switch (SvTYPE(sv)) {
case SVt_PVIO:
if (IoIFP(sv) != PerlIO_stdin() &&
case SVt_PVGV:
gp_free((GV*)sv);
Safefree(GvNAME(sv));
+ /* cannot decrease stash refcount yet, as we might recursively delete
+ ourselves when the refcnt drops to zero. Delay SvREFCNT_dec
+ of stash until current sv is completely gone.
+ -- JohnPC, 27 Mar 1998 */
+ stash = GvSTASH(sv);
/* FALL THROUGH */
case SVt_PVLV:
case SVt_PVMG:
break;
case SVt_PVGV:
del_XPVGV(SvANY(sv));
- break;
+ /* code duplication for increased performance. */
+ SvFLAGS(sv) &= SVf_BREAK;
+ SvFLAGS(sv) |= SVTYPEMASK;
+ /* decrease refcount of the stash that owns this GV, if any */
+ if (stash)
+ SvREFCNT_dec(stash);
+ return; /* not break, SvFLAGS reset already happened */
case SVt_PVBM:
del_XPVBM(SvANY(sv));
break;
sv_newref(SV *sv)
{
if (sv)
- SvREFCNT(sv)++;
+ ATOMIC_INC(SvREFCNT(sv));
return sv;
}
void
sv_free(SV *sv)
{
+ int refcount_is_zero;
+
if (!sv)
return;
if (SvREADONLY(sv)) {
warn("Attempt to free unreferenced scalar");
return;
}
- if (--SvREFCNT(sv) > 0)
+ ATOMIC_DEC_AND_TEST(refcount_is_zero, SvREFCNT(sv));
+ if (!refcount_is_zero)
return;
#ifdef DEBUGGING
if (SvTEMP(sv)) {
return 0;
if (SvGMAGICAL(sv))
- len = mg_len(sv);
+ len = mg_length(sv);
else
junk = SvPV(sv, len);
return len;
register I32 cnt;
I32 i;
- sv_check_thinkfirst(sv);
- if (!SvUPGRADE(sv, SVt_PV))
- return 0;
+ SV_CHECK_THINKFIRST(sv);
+ (void)SvUPGRADE(sv, SVt_PV);
SvSCREAM_off(sv);
if (RsSNARF(rs)) {
rsptr = NULL;
rslen = 0;
}
+ else if (RsRECORD(rs)) {
+ I32 recsize, bytesread;
+ char *buffer;
+
+ /* Grab the size of the record we're getting */
+ recsize = SvIV(SvRV(rs));
+ (void)SvPOK_only(sv); /* Validate pointer */
+ /* Make sure we've got the room to yank in the whole thing */
+ if (SvLEN(sv) <= recsize + 3) {
+ /* No, so make it bigger */
+ SvGROW(sv, recsize + 3);
+ }
+ buffer = SvPVX(sv); /* Get the location of the final buffer */
+ /* Go yank in */
+#ifdef VMS
+ /* VMS wants read instead of fread, because fread doesn't respect */
+ /* RMS record boundaries. This is not necessarily a good thing to be */
+ /* doing, but we've got no other real choice */
+ bytesread = PerlLIO_read(PerlIO_fileno(fp), buffer, recsize);
+#else
+ bytesread = PerlIO_read(fp, buffer, recsize);
+#endif
+ SvCUR_set(sv, bytesread);
+ return(SvCUR(sv) ? SvPVX(sv) : Nullch);
+ }
else if (RsPARA(rs)) {
rsptr = "\n\n";
rslen = 2;
* hopefully we won't free it until it has been assigned to a
* permanent location. */
-static void
+STATIC void
sv_mortalgrow(void)
{
dTHR;
return sv;
}
-#ifdef I_STDARG
SV *
-newSVpvf(const char* pat, ...)
-#else
-/*VARARGS0*/
+newSVpvn(char *s, STRLEN len)
+{
+ register SV *sv;
+
+ new_SV(sv);
+ SvANY(sv) = 0;
+ SvREFCNT(sv) = 1;
+ SvFLAGS(sv) = 0;
+ sv_setpvn(sv,s,len);
+ return sv;
+}
+
SV *
-newSVpvf(pat, va_alist)
-const char *pat;
-va_dcl
-#endif
+newSVpvf(const char* pat, ...)
{
register SV *sv;
va_list args;
SvANY(sv) = 0;
SvREFCNT(sv) = 1;
SvFLAGS(sv) = 0;
-#ifdef I_STDARG
va_start(args, pat);
-#else
- va_start(args);
-#endif
sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
va_end(args);
return sv;
}
SV *
-newRV(SV *ref)
+newRV(SV *tmpRef)
{
dTHR;
register SV *sv;
SvREFCNT(sv) = 1;
SvFLAGS(sv) = 0;
sv_upgrade(sv, SVt_RV);
- SvTEMP_off(ref);
- SvRV(sv) = SvREFCNT_inc(ref);
+ SvTEMP_off(tmpRef);
+ SvRV(sv) = SvREFCNT_inc(tmpRef);
SvROK_on(sv);
return sv;
}
SV *
-Perl_newRV_noinc(SV *ref)
+Perl_newRV_noinc(SV *tmpRef)
{
register SV *sv;
- sv = newRV(ref);
- SvREFCNT_dec(ref);
+ sv = newRV(tmpRef);
+ SvREFCNT_dec(tmpRef);
return sv;
}
register I32 max;
char todo[256];
+ if (!stash)
+ return;
+
if (!*s) { /* reset ?? searches */
for (pm = HvPMROOT(stash); pm; pm = pm->op_pmnext) {
- pm->op_pmflags &= ~PMf_USED;
+ pm->op_pmdynflags &= ~PMdf_USED;
}
return;
}
case SVt_PVHV: return "HASH";
case SVt_PVCV: return "CODE";
case SVt_PVGV: return "GLOB";
- case SVt_PVFM: return "FORMLINE";
+ case SVt_PVFM: return "FORMAT";
default: return "UNKNOWN";
}
}
SvREFCNT(sv) = 0;
SvFLAGS(sv) = 0;
- sv_check_thinkfirst(rv);
+ SV_CHECK_THINKFIRST(rv);
#ifdef OVERLOAD
SvAMAGIC_off(rv);
#endif /* OVERLOAD */
sv_bless(SV *sv, HV *stash)
{
dTHR;
- SV *ref;
+ SV *tmpRef;
if (!SvROK(sv))
croak("Can't bless non-reference value");
- ref = SvRV(sv);
- if (SvFLAGS(ref) & (SVs_OBJECT|SVf_READONLY)) {
- if (SvREADONLY(ref))
+ tmpRef = SvRV(sv);
+ if (SvFLAGS(tmpRef) & (SVs_OBJECT|SVf_READONLY)) {
+ if (SvREADONLY(tmpRef))
croak(no_modify);
- if (SvOBJECT(ref)) {
- if (SvTYPE(ref) != SVt_PVIO)
+ if (SvOBJECT(tmpRef)) {
+ if (SvTYPE(tmpRef) != SVt_PVIO)
--sv_objcount;
- SvREFCNT_dec(SvSTASH(ref));
+ SvREFCNT_dec(SvSTASH(tmpRef));
}
}
- SvOBJECT_on(ref);
- if (SvTYPE(ref) != SVt_PVIO)
+ SvOBJECT_on(tmpRef);
+ if (SvTYPE(tmpRef) != SVt_PVIO)
++sv_objcount;
- (void)SvUPGRADE(ref, SVt_PVMG);
- SvSTASH(ref) = (HV*)SvREFCNT_inc(stash);
+ (void)SvUPGRADE(tmpRef, SVt_PVMG);
+ SvSTASH(tmpRef) = (HV*)SvREFCNT_inc(stash);
#ifdef OVERLOAD
if (Gv_AMG(stash))
return sv;
}
-static void
+STATIC void
sv_unglob(SV *sv)
{
assert(SvTYPE(sv) == SVt_PVGV);
SvFAKE_off(sv);
if (GvGP(sv))
gp_free((GV*)sv);
+ if (GvSTASH(sv)) {
+ SvREFCNT_dec(GvSTASH(sv));
+ GvSTASH(sv) = Nullhv;
+ }
sv_unmagic(sv, '*');
Safefree(GvNAME(sv));
GvMULTI_off(sv);
SvCUR(sv) = p - SvPVX(sv);
}
-#ifdef I_STDARG
+
+void
+sv_setpviv_mg(SV *sv, IV iv)
+{
+ sv_setpviv(sv,iv);
+ SvSETMAGIC(sv);
+}
+
void
sv_setpvf(SV *sv, const char* pat, ...)
-#else
-/*VARARGS0*/
+{
+ va_list args;
+ va_start(args, pat);
+ sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ va_end(args);
+}
+
+
void
-sv_setpvf(sv, pat, va_alist)
- SV *sv;
- const char *pat;
- va_dcl
-#endif
+sv_setpvf_mg(SV *sv, const char* pat, ...)
{
va_list args;
-#ifdef I_STDARG
va_start(args, pat);
-#else
- va_start(args);
-#endif
sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
va_end(args);
+ SvSETMAGIC(sv);
}
-#ifdef I_STDARG
void
sv_catpvf(SV *sv, const char* pat, ...)
-#else
-/*VARARGS0*/
+{
+ va_list args;
+ va_start(args, pat);
+ sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
+ va_end(args);
+}
+
void
-sv_catpvf(sv, pat, va_alist)
- SV *sv;
- const char *pat;
- va_dcl
-#endif
+sv_catpvf_mg(SV *sv, const char* pat, ...)
{
va_list args;
-#ifdef I_STDARG
va_start(args, pat);
-#else
- va_start(args);
-#endif
sv_vcatpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
va_end(args);
+ SvSETMAGIC(sv);
}
void
switch (base) {
unsigned dig;
case 16:
+ if (!uv)
+ alt = FALSE;
p = (c == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
do {
dig = uv & 15;
break;
}
elen = (ebuf + sizeof ebuf) - eptr;
- if (has_precis && precis > elen)
- zeros = precis - elen;
+ if (has_precis) {
+ if (precis > elen)
+ zeros = precis - elen;
+ else if (precis == 0 && elen == 1 && *eptr == '0')
+ elen = 0;
+ }
break;
/* FLOATING POINT */
}
}
-#ifdef DEBUGGING
void
sv_dump(SV *sv)
{
+#ifdef DEBUGGING
SV *d = sv_newmortal();
char *s;
U32 flags;
case SVt_PVGV:
PerlIO_printf(Perl_debug_log, " NAME = \"%s\"\n", GvNAME(sv));
PerlIO_printf(Perl_debug_log, " NAMELEN = %ld\n", (long)GvNAMELEN(sv));
- PerlIO_printf(Perl_debug_log, " STASH = \"%s\"\n", HvNAME(GvSTASH(sv)));
+ PerlIO_printf(Perl_debug_log, " STASH = \"%s\"\n",
+ SvTYPE(GvSTASH(sv)) == SVt_PVHV ? HvNAME(GvSTASH(sv)) : "(deleted)");
PerlIO_printf(Perl_debug_log, " GP = 0x%lx\n", (long)GvGP(sv));
PerlIO_printf(Perl_debug_log, " SV = 0x%lx\n", (long)GvSV(sv));
PerlIO_printf(Perl_debug_log, " REFCNT = %ld\n", (long)GvREFCNT(sv));
PerlIO_printf(Perl_debug_log, " FLAGS = 0x%lx\n", (long)IoFLAGS(sv));
break;
}
+#endif /* DEBUGGING */
}
-#else
-void
-sv_dump(SV *sv)
-{
-}
-#endif
-
-
-
-