# define FAST_SV_GETS
#endif
+static IV asIV _((SV* sv));
+static UV asUV _((SV* sv));
static SV *more_sv _((void));
static XPVIV *more_xiv _((void));
static XPVNV *more_xnv _((void));
}
#endif
+static bool in_clean_objs = FALSE;
+
void
sv_clean_objs()
{
+ in_clean_objs = TRUE;
#ifndef DISABLE_DESTRUCTOR_KLUDGE
visit(do_clean_named_objs);
#endif
visit(do_clean_objs);
+ in_clean_objs = FALSE;
}
static void
SvREFCNT_dec(sv);
}
-static int in_clean_all = 0;
+static bool in_clean_all = FALSE;
void
sv_clean_all()
{
- in_clean_all = 1;
+ in_clean_all = TRUE;
visit(do_clean_all);
- in_clean_all = 0;
+ in_clean_all = FALSE;
}
void
if (!SvFAKE(sva))
Safefree((void *)sva);
}
+
+ sv_arenaroot = 0;
+ sv_root = 0;
}
static XPVIV*
else
sprintf(t,"(\"%.127s\")",SvPVX(sv));
}
- else if (SvNOKp(sv))
+ else if (SvNOKp(sv)) {
+ SET_NUMERIC_STANDARD();
sprintf(t,"(%g)",SvNVX(sv));
+ }
else if (SvIOKp(sv))
sprintf(t,"(%ld)",(long)SvIVX(sv));
else
{
register char *s;
-#ifdef MSDOS
+#ifdef HAS_64K_LIMIT
if (newlen >= 0x10000) {
PerlIO_printf(Perl_debug_log, "Allocation too large: %lx\n", newlen);
my_exit(1);
}
-#endif /* MSDOS */
+#endif /* HAS_64K_LIMIT */
if (SvROK(sv))
sv_unref(sv);
if (SvTYPE(sv) < SVt_PV) {
}
void
+sv_setuv(sv,u)
+register SV *sv;
+UV u;
+{
+ if (u <= IV_MAX)
+ sv_setiv(sv, u);
+ else
+ sv_setnv(sv, (double)u);
+}
+
+void
sv_setnv(sv,num)
register SV *sv;
double num;
char tmpbuf[64];
char *d = tmpbuf;
char *s;
- int i;
+ char *limit = tmpbuf + sizeof(tmpbuf) - 8;
+ /* each *s can expand to 4 chars + "...\0",
+ i.e. need room for 8 chars */
- for (s = SvPVX(sv), i = 50; *s && i; s++,i--) {
- int ch = *s;
- if (ch & 128 && !isprint(ch)) {
+ for (s = SvPVX(sv); *s && d < limit; s++) {
+ int ch = *s & 0xFF;
+ if (ch & 128 && !isPRINT_LC(ch)) {
*d++ = 'M';
*d++ = '-';
ch &= 127;
}
- if (isprint(ch))
+ if (ch == '\n') {
+ *d++ = '\\';
+ *d++ = 'n';
+ }
+ else if (ch == '\r') {
+ *d++ = '\\';
+ *d++ = 'r';
+ }
+ else if (ch == '\f') {
+ *d++ = '\\';
+ *d++ = 'f';
+ }
+ else if (ch == '\\') {
+ *d++ = '\\';
+ *d++ = '\\';
+ }
+ else if (isPRINT_LC(ch))
*d++ = ch;
else {
*d++ = '^';
- *d++ = ch ^ 64;
+ *d++ = toCTRL(ch);
}
}
if (*s) {
else
return (IV) U_V(SvNVX(sv));
}
- if (SvPOKp(sv) && SvLEN(sv)) {
- if (dowarn && !looks_like_number(sv))
- not_a_number(sv);
- return (IV)atol(SvPVX(sv));
- }
- if (!SvROK(sv)) {
- return 0;
- }
+ if (SvPOKp(sv) && SvLEN(sv))
+ return asIV(sv);
+ if (!SvROK(sv))
+ return 0;
}
if (SvTHINKFIRST(sv)) {
if (SvROK(sv)) {
else
return (IV) U_V(SvNVX(sv));
}
- if (SvPOKp(sv) && SvLEN(sv)) {
- if (dowarn && !looks_like_number(sv))
- not_a_number(sv);
- return (IV)atol(SvPVX(sv));
- }
+ if (SvPOKp(sv) && SvLEN(sv))
+ return asIV(sv);
if (dowarn)
warn(warn_uninit);
return 0;
switch (SvTYPE(sv)) {
case SVt_NULL:
sv_upgrade(sv, SVt_IV);
- return SvIVX(sv);
+ break;
case SVt_PV:
sv_upgrade(sv, SVt_PVIV);
break;
if (SvNVX(sv) < 0.0)
SvIVX(sv) = I_V(SvNVX(sv));
else
- SvIVX(sv) = (IV) U_V(SvNVX(sv));
+ SvUVX(sv) = U_V(SvNVX(sv));
}
else if (SvPOKp(sv) && SvLEN(sv)) {
- if (dowarn && !looks_like_number(sv))
- not_a_number(sv);
(void)SvIOK_on(sv);
- SvIVX(sv) = (IV)atol(SvPVX(sv));
+ SvIVX(sv) = asIV(sv);
}
else {
if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
warn(warn_uninit);
return 0;
}
- (void)SvIOK_on(sv);
DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2iv(%ld)\n",
(unsigned long)sv,(long)SvIVX(sv)));
return SvIVX(sv);
}
+UV
+sv_2uv(sv)
+register SV *sv;
+{
+ if (!sv)
+ return 0;
+ if (SvGMAGICAL(sv)) {
+ mg_get(sv);
+ if (SvIOKp(sv))
+ return SvUVX(sv);
+ if (SvNOKp(sv))
+ return U_V(SvNVX(sv));
+ if (SvPOKp(sv) && SvLEN(sv))
+ return asUV(sv);
+ if (!SvROK(sv))
+ return 0;
+ }
+ if (SvTHINKFIRST(sv)) {
+ if (SvROK(sv)) {
+#ifdef OVERLOAD
+ SV* tmpstr;
+ if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv, numer)))
+ return SvUV(tmpstr);
+#endif /* OVERLOAD */
+ return (UV)SvRV(sv);
+ }
+ if (SvREADONLY(sv)) {
+ if (SvNOKp(sv)) {
+ return U_V(SvNVX(sv));
+ }
+ if (SvPOKp(sv) && SvLEN(sv))
+ return asUV(sv);
+ if (dowarn)
+ warn(warn_uninit);
+ return 0;
+ }
+ }
+ switch (SvTYPE(sv)) {
+ case SVt_NULL:
+ sv_upgrade(sv, SVt_IV);
+ break;
+ case SVt_PV:
+ sv_upgrade(sv, SVt_PVIV);
+ break;
+ case SVt_NV:
+ sv_upgrade(sv, SVt_PVNV);
+ break;
+ }
+ if (SvNOKp(sv)) {
+ (void)SvIOK_on(sv);
+ SvUVX(sv) = U_V(SvNVX(sv));
+ }
+ else if (SvPOKp(sv) && SvLEN(sv)) {
+ (void)SvIOK_on(sv);
+ SvUVX(sv) = asUV(sv);
+ }
+ else {
+ if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
+ warn(warn_uninit);
+ return 0;
+ }
+ DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2uv(%lu)\n",
+ (unsigned long)sv,SvUVX(sv)));
+ return SvUVX(sv);
+}
+
double
sv_2nv(sv)
register SV *sv;
if (SvPOKp(sv) && SvLEN(sv)) {
if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
not_a_number(sv);
+ SET_NUMERIC_STANDARD();
return atof(SvPVX(sv));
}
if (SvIOKp(sv))
if (SvPOKp(sv) && SvLEN(sv)) {
if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
not_a_number(sv);
+ SET_NUMERIC_STANDARD();
return atof(SvPVX(sv));
}
if (SvIOKp(sv))
sv_upgrade(sv, SVt_PVNV);
else
sv_upgrade(sv, SVt_NV);
- DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx num(%g)\n",(unsigned long)sv,SvNVX(sv)));
+ DEBUG_c(SET_NUMERIC_STANDARD());
+ DEBUG_c(PerlIO_printf(Perl_debug_log,
+ "0x%lx num(%g)\n",(unsigned long)sv,SvNVX(sv)));
}
else if (SvTYPE(sv) < SVt_PVNV)
sv_upgrade(sv, SVt_PVNV);
else if (SvPOKp(sv) && SvLEN(sv)) {
if (dowarn && !SvIOKp(sv) && !looks_like_number(sv))
not_a_number(sv);
+ SET_NUMERIC_STANDARD();
SvNVX(sv) = atof(SvPVX(sv));
}
else {
return 0.0;
}
SvNOK_on(sv);
- DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2nv(%g)\n",(unsigned long)sv,SvNVX(sv)));
+ DEBUG_c(SET_NUMERIC_STANDARD());
+ DEBUG_c(PerlIO_printf(Perl_debug_log,
+ "0x%lx 2nv(%g)\n",(unsigned long)sv,SvNVX(sv)));
return SvNVX(sv);
}
+static IV
+asIV(sv)
+SV *sv;
+{
+ I32 numtype = looks_like_number(sv);
+ double d;
+
+ if (numtype == 1)
+ return atol(SvPVX(sv));
+ if (!numtype && dowarn)
+ not_a_number(sv);
+ SET_NUMERIC_STANDARD();
+ d = atof(SvPVX(sv));
+ if (d < 0.0)
+ return I_V(d);
+ else
+ return (IV) U_V(d);
+}
+
+static UV
+asUV(sv)
+SV *sv;
+{
+ I32 numtype = looks_like_number(sv);
+
+ if (numtype == 1)
+ return atol(SvPVX(sv));
+ if (!numtype && dowarn)
+ not_a_number(sv);
+ SET_NUMERIC_STANDARD();
+ return U_V(atof(SvPVX(sv)));
+}
+
+I32
+looks_like_number(sv)
+SV *sv;
+{
+ register char *s;
+ register char *send;
+ register char *sbegin;
+ I32 numtype;
+ STRLEN len;
+
+ if (SvPOK(sv)) {
+ sbegin = SvPVX(sv);
+ len = SvCUR(sv);
+ }
+ else if (SvPOKp(sv))
+ sbegin = SvPV(sv, len);
+ else
+ return 1;
+ send = sbegin + len;
+
+ s = sbegin;
+ while (isSPACE(*s))
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+
+ /* next must be digit or '.' */
+ if (isDIGIT(*s)) {
+ do {
+ s++;
+ } while (isDIGIT(*s));
+ if (*s == '.') {
+ s++;
+ while (isDIGIT(*s)) /* optional digits after "." */
+ s++;
+ }
+ }
+ else if (*s == '.') {
+ s++;
+ /* no digits before '.' means we need digits after it */
+ if (isDIGIT(*s)) {
+ do {
+ s++;
+ } while (isDIGIT(*s));
+ }
+ else
+ return 0;
+ }
+ else
+ return 0;
+
+ /*
+ * we return 1 if the number can be converted to _integer_ with atol()
+ * and 2 if you need (int)atof().
+ */
+ numtype = 1;
+
+ /* we can have an optional exponent part */
+ if (*s == 'e' || *s == 'E') {
+ numtype = 2;
+ s++;
+ if (*s == '+' || *s == '-')
+ s++;
+ if (isDIGIT(*s)) {
+ do {
+ s++;
+ } while (isDIGIT(*s));
+ }
+ else
+ return 0;
+ }
+ while (isSPACE(*s))
+ s++;
+ if (s >= send)
+ return numtype;
+ if (len == 10 && memEQ(sbegin, "0 but true", 10))
+ return 1;
+ return 0;
+}
+
char *
sv_2pv(sv, lp)
register SV *sv;
goto tokensave;
}
if (SvNOKp(sv)) {
+ SET_NUMERIC_STANDARD();
Gconvert(SvNVX(sv), DBL_DIG, 0, tokenbuf);
goto tokensave;
}
case SVt_PVCV: s = "CODE"; break;
case SVt_PVGV: s = "GLOB"; break;
case SVt_PVFM: s = "FORMATLINE"; break;
- case SVt_PVIO: s = "FILEHANDLE"; break;
+ case SVt_PVIO: s = "IO"; break;
default: s = "UNKNOWN"; break;
}
if (SvOBJECT(sv))
}
if (SvREADONLY(sv)) {
if (SvNOKp(sv)) {
+ SET_NUMERIC_STANDARD();
Gconvert(SvNVX(sv), DBL_DIG, 0, tokenbuf);
goto tokensave;
}
(void)strcpy(s,"0");
else
#endif /*apollo*/
+ {
+ SET_NUMERIC_STANDARD();
Gconvert(SvNVX(sv), DBL_DIG, 0, s);
+ }
errno = olderrno;
#ifdef FIXNEGATIVEZERO
if (*s == '-' && s[1] == '0' && !s[2])
(void)SvOK_off(dstr);
return;
case SVt_IV:
- if (dtype <= SVt_PV) {
+ if (dtype != SVt_IV && dtype < SVt_PVIV) {
if (dtype < SVt_IV)
sv_upgrade(dstr, SVt_IV);
else if (dtype == SVt_NV)
sv_upgrade(dstr, SVt_PVNV);
- else if (dtype <= SVt_PV)
+ else
sv_upgrade(dstr, SVt_PVIV);
}
break;
case SVt_NV:
- if (dtype <= SVt_PVIV) {
+ if (dtype != SVt_NV && dtype < SVt_PVNV) {
if (dtype < SVt_NV)
sv_upgrade(dstr, SVt_NV);
- else if (dtype == SVt_PVIV)
- sv_upgrade(dstr, SVt_PVNV);
- else if (dtype <= SVt_PV)
+ else
sv_upgrade(dstr, SVt_PVNV);
}
break;
GvGP(dstr)->gp_refcnt--;
GvINTRO_off(dstr); /* one-shot flag */
Newz(602,gp, 1, GP);
- GvGP(dstr) = gp;
- GvREFCNT(dstr) = 1;
+ GvGP(dstr) = gp_ref(gp);
GvSV(dstr) = NEWSV(72,0);
GvLINE(dstr) = curcop->cop_line;
GvEGV(dstr) = (GV*)dstr;
GvIMPORTED_HV_on(dstr);
break;
case SVt_PVCV:
- if (intro)
+ if (intro) {
+ if (GvCVGEN(dstr) && GvCV(dstr) != (CV*)sref) {
+ SvREFCNT_dec(GvCV(dstr));
+ GvCV(dstr) = Nullcv;
+ GvCVGEN(dstr) = 0;
+ }
SAVESPTR(GvCV(dstr));
+ }
else {
CV* cv = GvCV(dstr);
if (cv) {
(CvROOT(cv) || CvXSUB(cv)) )
warn("Subroutine %s redefined",
GvENAME((GV*)dstr));
- SvFAKE_on(cv);
}
}
if (GvCV(dstr) != (CV*)sref) {
GvCV(dstr) = (CV*)sref;
+ GvCVGEN(dstr) = 0; /* Switch off cacheness. */
GvASSUMECV_on(dstr);
+ sub_generation++;
}
if (curcop->cop_stash != GvSTASH(dstr))
GvIMPORTED_CV_on(dstr);
void
sv_setpvn(sv,ptr,len)
register SV *sv;
-register char *ptr;
+register const char *ptr;
register STRLEN len;
{
assert(len >= 0); /* STRLEN is probably unsigned, so this may
void
sv_setpv(sv,ptr)
register SV *sv;
-register char *ptr;
+register const char *ptr;
{
register STRLEN len;
{
MAGIC* mg;
- if (SvREADONLY(sv) && curcop != &compiling && !strchr("gB", how))
+ if (SvREADONLY(sv) && curcop != &compiling && !strchr("gBf", how))
croak(no_modify);
if (SvMAGICAL(sv) || (how == 't' && SvTYPE(sv) >= SVt_PVMG)) {
if (SvMAGIC(sv) && (mg = mg_find(sv, how))) {
case 'E':
mg->mg_virtual = &vtbl_env;
break;
+ case 'f':
+ mg->mg_virtual = &vtbl_fm;
+ break;
case 'e':
mg->mg_virtual = &vtbl_envelem;
break;
case 'l':
mg->mg_virtual = &vtbl_dbline;
break;
+#ifdef USE_LOCALE_COLLATE
+ case 'o':
+ mg->mg_virtual = &vtbl_collxfrm;
+ break;
+#endif /* USE_LOCALE_COLLATE */
case 'P':
mg->mg_virtual = &vtbl_pack;
break;
case 'x':
mg->mg_virtual = &vtbl_substr;
break;
+ case 'y':
+ mg->mg_virtual = &vtbl_itervar;
+ break;
case '*':
mg->mg_virtual = &vtbl_glob;
break;
}
SvREFCNT(sv) = 0;
sv_clear(sv);
+ assert(!SvREFCNT(sv));
StructCopy(nsv,sv,SV);
SvREFCNT(sv) = refcnt;
SvFLAGS(nsv) |= SVTYPEMASK; /* Mark as freed */
assert(SvREFCNT(sv) == 0);
if (SvOBJECT(sv)) {
- dSP;
- GV* destructor;
-
if (defstash) { /* Still have a symbol table? */
- destructor = gv_fetchmethod(SvSTASH(sv), "DESTROY");
+ dSP;
+ GV* destructor;
ENTER;
SAVEFREESV(SvSTASH(sv));
- if (destructor && GvCV(destructor)) {
+
+ 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*)destructor, G_DISCARD|G_EVAL|G_KEEPERR);
+ perl_call_sv((SV*)GvCV(destructor),
+ G_DISCARD|G_EVAL|G_KEEPERR);
del_XRV(SvANY(&ref));
SvREFCNT(sv)--;
}
+
LEAVE;
}
else
--sv_objcount; /* XXX Might want something more general */
}
if (SvREFCNT(sv)) {
- SV *ret;
+ SV *ret;
if ( perldb
&& (ret = perl_get_sv("DB::ret", FALSE))
&& SvROK(ret) && SvRV(ret) == sv && SvREFCNT(sv) == 1) {
SvRV(ret) = 0;
SvROK_off(ret);
SvREFCNT(sv) = 0;
- } else {
- croak("panic: dangling references in DESTROY");
+ }
+ else {
+ if (in_clean_objs)
+ croak("DESTROY created new reference to dead object");
+ /* DESTROY gave object new lease on life */
+ return;
}
}
}
mg_free(sv);
switch (SvTYPE(sv)) {
case SVt_PVIO:
- io_close((IO*)sv);
+ if (IoIFP(sv) != PerlIO_stdin() &&
+ IoIFP(sv) != PerlIO_stdout() &&
+ IoIFP(sv) != PerlIO_stderr())
+ io_close((IO*)sv);
Safefree(IoTOP_NAME(sv));
Safefree(IoFMT_NAME(sv));
Safefree(IoBOTTOM_NAME(sv));
}
#endif
sv_clear(sv);
- del_SV(sv);
+ if (! SvREFCNT(sv))
+ del_SV(sv);
}
STRLEN
if (cur1 != cur2)
return 0;
- return !memcmp(pv1, pv2, cur1);
+ return memEQ(pv1, pv2, cur1);
}
I32
-sv_cmp(str1,str2)
+sv_cmp(str1, str2)
register SV *str1;
register SV *str2;
{
+ STRLEN cur1 = 0;
+ char *pv1 = str1 ? SvPV(str1, cur1) : NULL;
+ STRLEN cur2 = 0;
+ char *pv2 = str2 ? SvPV(str2, cur2) : NULL;
I32 retval;
- char *pv1;
- STRLEN cur1;
- char *pv2;
- STRLEN cur2;
-
- if (lc_collate_active) { /* NOTE: this is the LC_COLLATE branch */
-
- if (!str1) {
- pv1 = "";
- cur1 = 0;
- } else {
- pv1 = SvPV(str1, cur1);
-
- {
- STRLEN cur1x;
- char * pv1x = mem_collxfrm(pv1, cur1, &cur1x);
-
- pv1 = pv1x;
- cur1 = cur1x;
- }
- }
- if (!str2) {
- pv2 = "";
- cur2 = 0;
- } else {
- pv2 = SvPV(str2, cur2);
-
- {
- STRLEN cur2x;
- char * pv2x = mem_collxfrm(pv2, cur2, &cur2x);
-
- pv2 = pv2x;
- cur2 = cur2x;
- }
- }
-
- if (!cur1) {
- Safefree(pv2);
+ if (!cur1)
return cur2 ? -1 : 0;
- }
- if (!cur2) {
- Safefree(pv1);
+ if (!cur2)
return 1;
- }
-
- retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
- Safefree(pv1);
- Safefree(pv2);
+ retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
- if (retval)
+ if (retval)
return retval < 0 ? -1 : 1;
- if (cur1 == cur2)
+ if (cur1 == cur2)
return 0;
else
return cur1 < cur2 ? -1 : 1;
+}
- } else { /* NOTE: this is the non-LC_COLLATE branch */
+I32
+sv_cmp_locale(sv1, sv2)
+register SV *sv1;
+register SV *sv2;
+{
+#ifdef USE_LOCALE_COLLATE
- if (!str1) {
- pv1 = "";
- cur1 = 0;
- } else
- pv1 = SvPV(str1, cur1);
+ char *pv1, *pv2;
+ STRLEN len1, len2;
+ I32 retval;
- if (!str2) {
- pv2 = "";
- cur2 = 0;
- } else
- pv2 = SvPV(str2, cur2);
+ if (collation_standard)
+ goto raw_compare;
- if (!cur1)
- return cur2 ? -1 : 0;
+ len1 = 0;
+ pv1 = sv1 ? sv_collxfrm(sv1, &len1) : NULL;
+ len2 = 0;
+ pv2 = sv2 ? sv_collxfrm(sv2, &len2) : NULL;
- if (!cur2)
- return 1;
+ if (!pv1 || !len1) {
+ if (pv2 && len2)
+ return -1;
+ else
+ goto raw_compare;
+ }
+ else {
+ if (!pv2 || !len2)
+ return 1;
+ }
- retval = memcmp((void*)pv1, (void*)pv2, cur1 < cur2 ? cur1 : cur2);
+ retval = memcmp((void*)pv1, (void*)pv2, len1 < len2 ? len1 : len2);
- if (retval)
+ if (retval)
return retval < 0 ? -1 : 1;
- if (cur1 == cur2)
- return 0;
- else
- return cur1 < cur2 ? -1 : 1;
+ /*
+ * When the result of collation is equality, that doesn't mean
+ * that there are no differences -- some locales exclude some
+ * characters from consideration. So to avoid false equalities,
+ * we use the raw string as a tiebreaker.
+ */
+
+ raw_compare:
+ /* FALL THROUGH */
+
+#endif /* USE_LOCALE_COLLATE */
+
+ return sv_cmp(sv1, sv2);
+}
+
+#ifdef USE_LOCALE_COLLATE
+/*
+ * Any scalar variable may carry an 'o' magic that contains the
+ * scalar data of the variable transformed to such a format that
+ * a normal memory comparison can be used to compare the data
+ * according to the locale settings.
+ */
+char *
+sv_collxfrm(sv, nxp)
+ SV *sv;
+ STRLEN *nxp;
+{
+ MAGIC *mg;
+
+ mg = SvMAGICAL(sv) ? mg_find(sv, 'o') : NULL;
+ if (!mg || !mg->mg_ptr || *(U32*)mg->mg_ptr != collation_ix) {
+ char *s, *xf;
+ STRLEN len, xlen;
+
+ if (mg)
+ Safefree(mg->mg_ptr);
+ s = SvPV(sv, len);
+ if ((xf = mem_collxfrm(s, len, &xlen))) {
+ if (SvREADONLY(sv)) {
+ SAVEFREEPV(xf);
+ *nxp = xlen;
+ return xf;
+ }
+ if (! mg) {
+ sv_magic(sv, 0, 'o', 0, 0);
+ mg = mg_find(sv, 'o');
+ assert(mg);
+ }
+ mg->mg_ptr = xf;
+ mg->mg_len = xlen;
+ }
+ else {
+ if (mg) {
+ mg->mg_ptr = NULL;
+ mg->mg_len = -1;
+ }
+ }
+ }
+ if (mg && mg->mg_ptr) {
+ *nxp = mg->mg_len;
+ return mg->mg_ptr + sizeof(collation_ix);
+ }
+ else {
+ *nxp = 0;
+ return NULL;
}
}
+#endif /* USE_LOCALE_COLLATE */
+
char *
sv_gets(sv,fp,append)
register SV *sv;
}
if (!SvUPGRADE(sv, SVt_PV))
return 0;
+ SvSCREAM_off(sv);
if (RsSNARF(rs)) {
rsptr = NULL;
}
else {
shortbuffered = 0;
- SvGROW(sv, append+cnt+2);/* (remembering cnt can be -1) */
+ /* remember that cnt can be negative */
+ SvGROW(sv, append + (cnt <= 0 ? 2 : (cnt + 1)));
}
}
else
"Screamer: entering, ptr=%d, cnt=%d\n",ptr,cnt));
DEBUG_P(PerlIO_printf(Perl_debug_log,
"Screamer: entering: FILE * thinks ptr=%d, cnt=%d, base=%d\n",
- PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+ PerlIO_get_ptr(fp), PerlIO_get_cnt(fp),
+ PerlIO_has_base(fp) ? PerlIO_get_base(fp) : 0));
for (;;) {
screamer:
if (cnt > 0) {
}
}
else {
- memcpy((char*)bp, (char*)ptr, cnt); /* this | eat */
+ 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=%d, cnt=%d, base=%d\n",
- PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+ PerlIO_get_ptr(fp), PerlIO_get_cnt(fp),
+ PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
/* This used to call 'filbuf' in stdio form, but as that behaves like
- getc when cnt <= 0 we use PerlIO_getc here to avoid another
- abstraction. This may also avoid issues with different named
- 'filbuf' equivalents, though Configure tries to handle them now
- anyway.
- */
+ 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=%d, cnt=%d, base=%d\n",
- PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+ PerlIO_get_ptr(fp), PerlIO_get_cnt(fp),
+ PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
cnt = PerlIO_get_cnt(fp);
ptr = (STDCHAR*)PerlIO_get_ptr(fp); /* reregisterize cnt and ptr */
DEBUG_P(PerlIO_printf(Perl_debug_log,
thats_all_folks:
if ((rslen > 1 && (bp - (STDCHAR*)SvPVX(sv) < rslen)) ||
- memcmp((char*)bp - rslen, rsptr, rslen))
+ memNE((char*)bp - rslen, rsptr, rslen))
goto screamer; /* go back to the fray */
thats_really_all_folks:
if (shortbuffered)
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=%d, cnt=%d, base=%d\n",
- PerlIO_get_ptr(fp), PerlIO_get_cnt(fp), PerlIO_get_base(fp)));
+ PerlIO_get_ptr(fp), PerlIO_get_cnt(fp),
+ PerlIO_has_base (fp) ? PerlIO_get_base(fp) : 0));
*bp = '\0';
SvCUR_set(sv, bp - (STDCHAR*)SvPVX(sv)); /* set length */
DEBUG_P(PerlIO_printf(Perl_debug_log,
if (i != EOF && /* joy */
(!rslen ||
SvCUR(sv) < rslen ||
- memcmp(SvPVX(sv) + SvCUR(sv) - rslen, rsptr, rslen)))
+ memNE(SvPVX(sv) + SvCUR(sv) - rslen, rsptr, rslen)))
{
append = -1;
goto screamer2;
if (SvGMAGICAL(sv))
mg_get(sv);
flags = SvFLAGS(sv);
- if (flags & SVp_IOK) {
- (void)SvIOK_only(sv);
- ++SvIVX(sv);
- return;
- }
if (flags & SVp_NOK) {
- SvNVX(sv) += 1.0;
(void)SvNOK_only(sv);
+ SvNVX(sv) += 1.0;
+ return;
+ }
+ if (flags & SVp_IOK) {
+ if (SvIVX(sv) == IV_MAX)
+ sv_setnv(sv, (double)IV_MAX + 1.0);
+ else {
+ (void)SvIOK_only(sv);
+ ++SvIVX(sv);
+ }
return;
}
if (!(flags & SVp_POK) || !*SvPVX(sv)) {
while (isALPHA(*d)) d++;
while (isDIGIT(*d)) d++;
if (*d) {
- sv_setnv(sv,atof(SvPVX(sv)) + 1.0); /* punt */
+ SET_NUMERIC_STANDARD();
+ sv_setnv(sv,atof(SvPVX(sv)) + 1.0); /* punt */
return;
}
d--;
if (SvGMAGICAL(sv))
mg_get(sv);
flags = SvFLAGS(sv);
- if (flags & SVp_IOK) {
- (void)SvIOK_only(sv);
- --SvIVX(sv);
- return;
- }
if (flags & SVp_NOK) {
SvNVX(sv) -= 1.0;
(void)SvNOK_only(sv);
return;
}
+ if (flags & SVp_IOK) {
+ if (SvIVX(sv) == IV_MIN)
+ sv_setnv(sv, (double)IV_MIN - 1.0);
+ else {
+ (void)SvIOK_only(sv);
+ --SvIVX(sv);
+ }
+ return;
+ }
if (!(flags & SVp_POK)) {
if ((flags & SVTYPEMASK) < SVt_PVNV)
sv_upgrade(sv, SVt_NV);
(void)SvNOK_only(sv);
return;
}
- sv_setnv(sv,atof(SvPVX(sv)) - 1.0);
+ SET_NUMERIC_STANDARD();
+ sv_setnv(sv,atof(SvPVX(sv)) - 1.0); /* punt */
}
/* Make a string that will exist for the duration of the expression
static void
sv_mortalgrow()
{
- tmps_max += 128;
+ tmps_max += (tmps_max < 512) ? 128 : 512;
Renew(tmps_stack, tmps_max, SV*);
}
return sv;
}
+#ifdef CRIPPLED_CC
+SV *
+newRV_noinc(ref)
+SV *ref;
+{
+ register SV *sv;
+
+ sv = newRV(ref);
+ SvREFCNT_dec(ref);
+ return sv;
+}
+#endif /* CRIPPLED_CC */
+
/* make an exact duplicate of old */
SV *
(void)SvOK_off(sv);
if (SvTYPE(sv) >= SVt_PV) {
SvCUR_set(sv, 0);
- SvTAINT(sv);
if (SvPVX(sv) != Nullch)
*SvPVX(sv) = '\0';
+ SvTAINT(sv);
}
if (GvAV(gv)) {
av_clear(GvAV(gv));
}
- if (GvHV(gv)) {
- if (HvNAME(GvHV(gv)))
- continue;
+ if (GvHV(gv) && !HvNAME(GvHV(gv))) {
hv_clear(GvHV(gv));
#ifndef VMS /* VMS has no environ array */
if (gv == envgv)
return Nullcv;
*st = GvESTASH(gv);
fix_gv:
- if (lref && !GvCV(gv)) {
+ if (lref && !GvCVu(gv)) {
SV *tmpsv;
ENTER;
tmpsv = NEWSV(704,0);
gv_efullname3(tmpsv, gv, Nullch);
- newSUB(start_subparse(),
+ newSUB(start_subparse(FALSE, 0),
newSVOP(OP_CONST, 0, tmpsv),
Nullop,
Nullop);
LEAVE;
- if (!GvCV(gv))
+ if (!GvCVu(gv))
croak("Unable to create sub named \"%s\"", SvPV(sv,na));
}
- return GvCV(gv);
+ return GvCVu(gv);
}
}
}
}
}
-#endif /* SvTRUE */
+#endif /* !SvTRUE */
#ifndef SvIV
-IV SvIV(Sv)
-register SV *Sv;
+IV
+SvIV(sv)
+register SV *sv;
{
- if (SvIOK(Sv))
- return SvIVX(Sv);
- return sv_2iv(Sv);
+ if (SvIOK(sv))
+ return SvIVX(sv);
+ return sv_2iv(sv);
}
-#endif /* SvIV */
+#endif /* !SvIV */
+#ifndef SvUV
+UV
+SvUV(sv)
+register SV *sv;
+{
+ if (SvIOK(sv))
+ return SvUVX(sv);
+ return sv_2uv(sv);
+}
+#endif /* !SvUV */
#ifndef SvNV
-double SvNV(Sv)
-register SV *Sv;
+double
+SvNV(sv)
+register SV *sv;
{
- if (SvNOK(Sv))
- return SvNVX(Sv);
- if (SvIOK(Sv))
- return (double)SvIVX(Sv);
- return sv_2nv(Sv);
+ if (SvNOK(sv))
+ return SvNVX(sv);
+ return sv_2nv(sv);
}
-#endif /* SvNV */
+#endif /* !SvNV */
#ifdef CRIPPLED_CC
char *
if (SvFLAGS(ref) & (SVs_OBJECT|SVf_READONLY)) {
if (SvREADONLY(ref))
croak(no_modify);
- if (SvOBJECT(ref) && SvTYPE(ref) != SVt_PVIO)
- --sv_objcount;
+ if (SvOBJECT(ref)) {
+ if (SvTYPE(ref) != SVt_PVIO)
+ --sv_objcount;
+ SvREFCNT_dec(SvSTASH(ref));
+ }
}
SvOBJECT_on(ref);
- ++sv_objcount;
+ if (SvTYPE(ref) != SVt_PVIO)
+ ++sv_objcount;
(void)SvUPGRADE(ref, SVt_PVMG);
SvSTASH(ref) = (HV*)SvREFCNT_inc(stash);
#ifdef OVERLOAD
- SvAMAGIC_off(sv);
- if (Gv_AMG(stash)) {
- SvAMAGIC_on(sv);
- }
+ if (Gv_AMG(stash))
+ SvAMAGIC_on(sv);
+ else
+ SvAMAGIC_off(sv);
#endif /* OVERLOAD */
return sv;
sv_2mortal(rv); /* Schedule for freeing later */
}
+IO*
+sv_2io(sv)
+SV *sv;
+{
+ IO* io;
+ GV* gv;
+
+ switch (SvTYPE(sv)) {
+ case SVt_PVIO:
+ io = (IO*)sv;
+ break;
+ case SVt_PVGV:
+ gv = (GV*)sv;
+ io = GvIO(gv);
+ if (!io)
+ croak("Bad filehandle: %s", GvNAME(gv));
+ break;
+ default:
+ if (!SvOK(sv))
+ croak(no_usym, "filehandle");
+ if (SvROK(sv))
+ return sv_2io(SvRV(sv));
+ gv = gv_fetchpv(SvPV(sv,na), FALSE, SVt_PVIO);
+ if (gv)
+ io = GvIO(gv);
+ else
+ io = 0;
+ if (!io)
+ croak("Bad filehandle: %s", SvPV(sv,na));
+ break;
+ }
+ return io;
+}
+
+void
+sv_taint(sv)
+SV *sv;
+{
+ sv_magic((sv), Nullsv, 't', Nullch, 0);
+}
+
+void
+sv_untaint(sv)
+SV *sv;
+{
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+ MAGIC *mg = mg_find(sv, 't');
+ if (mg)
+ mg->mg_len &= ~1;
+ }
+}
+
+bool
+sv_tainted(sv)
+SV *sv;
+{
+ if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv)) {
+ MAGIC *mg = mg_find(sv, 't');
+ if (mg && ((mg->mg_len & 1) || (mg->mg_len & 2) && mg->mg_obj == sv))
+ return TRUE;
+ }
+ return FALSE;
+}
+
#ifdef DEBUGGING
void
sv_dump(sv)
switch (type) {
case SVt_PVCV:
- if (CvANON(sv)) strcat(d, "ANON,");
- if (CvCLONE(sv)) strcat(d, "CLONE,");
- if (CvCLONED(sv)) strcat(d, "CLONED,");
+ case SVt_PVFM:
+ if (CvANON(sv)) strcat(d, "ANON,");
+ if (CvUNIQUE(sv)) strcat(d, "UNIQUE,");
+ if (CvCLONE(sv)) strcat(d, "CLONE,");
+ if (CvCLONED(sv)) strcat(d, "CLONED,");
+ if (CvNODEBUG(sv)) strcat(d, "NODEBUG,");
+ break;
+ case SVt_PVHV:
+ if (HvSHAREKEYS(sv)) strcat(d, "SHAREKEYS,");
+ if (HvLAZYDEL(sv)) strcat(d, "LAZYDEL,");
break;
case SVt_PVGV:
- if (GvMULTI(sv)) strcat(d, "MULTI,");
-#ifdef OVERLOAD
- if (flags & SVpgv_AM) strcat(d, "withOVERLOAD,");
-#endif /* OVERLOAD */
+ if (GvINTRO(sv)) strcat(d, "INTRO,");
+ if (GvMULTI(sv)) strcat(d, "MULTI,");
+ if (GvASSUMECV(sv)) strcat(d, "ASSUMECV,");
+ if (GvIMPORTED(sv)) {
+ strcat(d, "IMPORT");
+ if (GvIMPORTED(sv) == GVf_IMPORTED)
+ strcat(d, "ALL,");
+ else {
+ strcat(d, "(");
+ if (GvIMPORTED_SV(sv)) strcat(d, " SV");
+ if (GvIMPORTED_AV(sv)) strcat(d, " AV");
+ if (GvIMPORTED_HV(sv)) strcat(d, " HV");
+ if (GvIMPORTED_CV(sv)) strcat(d, " CV");
+ strcat(d, " ),");
+ }
+ }
}
d += strlen(d);
}
if (type >= SVt_PVIV || type == SVt_IV)
PerlIO_printf(Perl_debug_log, " IV = %ld\n", (long)SvIVX(sv));
- if (type >= SVt_PVNV || type == SVt_NV)
+ if (type >= SVt_PVNV || type == SVt_NV) {
+ SET_NUMERIC_STANDARD();
PerlIO_printf(Perl_debug_log, " NV = %.*g\n", DBL_DIG, SvNVX(sv));
+ }
if (SvROK(sv)) {
PerlIO_printf(Perl_debug_log, " RV = 0x%lx\n", (long)SvRV(sv));
sv_dump(SvRV(sv));
if (HvNAME(sv))
PerlIO_printf(Perl_debug_log, " NAME = \"%s\"\n", HvNAME(sv));
break;
- case SVt_PVFM:
case SVt_PVCV:
if (SvPOK(sv))
PerlIO_printf(Perl_debug_log, " PROTOTYPE = \"%s\"\n", SvPV(sv,na));
+ /* FALL THROUGH */
+ case SVt_PVFM:
PerlIO_printf(Perl_debug_log, " STASH = 0x%lx\n", (long)CvSTASH(sv));
PerlIO_printf(Perl_debug_log, " START = 0x%lx\n", (long)CvSTART(sv));
PerlIO_printf(Perl_debug_log, " ROOT = 0x%lx\n", (long)CvROOT(sv));
PerlIO_printf(Perl_debug_log, " CVGEN = 0x%lx\n", (long)GvCVGEN(sv));
PerlIO_printf(Perl_debug_log, " LASTEXPR = %ld\n", (long)GvLASTEXPR(sv));
PerlIO_printf(Perl_debug_log, " LINE = %ld\n", (long)GvLINE(sv));
- PerlIO_printf(Perl_debug_log, " FLAGS = 0x%x\n", (int)GvFLAGS(sv));
- PerlIO_printf(Perl_debug_log, " STASH = \"%s\"\n", HvNAME(GvSTASH(sv)));
+ PerlIO_printf(Perl_debug_log, " FILEGV = 0x%lx\n", (long)GvFILEGV(sv));
PerlIO_printf(Perl_debug_log, " EGV = 0x%lx\n", (long)GvEGV(sv));
break;
case SVt_PVIO:
{
}
#endif
-
-IO*
-sv_2io(sv)
-SV *sv;
-{
- IO* io;
- GV* gv;
-
- switch (SvTYPE(sv)) {
- case SVt_PVIO:
- io = (IO*)sv;
- break;
- case SVt_PVGV:
- gv = (GV*)sv;
- io = GvIO(gv);
- if (!io)
- croak("Bad filehandle: %s", GvNAME(gv));
- break;
- default:
- if (!SvOK(sv))
- croak(no_usym, "filehandle");
- if (SvROK(sv))
- return sv_2io(SvRV(sv));
- gv = gv_fetchpv(SvPV(sv,na), FALSE, SVt_PVIO);
- if (gv)
- io = GvIO(gv);
- else
- io = 0;
- if (!io)
- croak("Bad filehandle: %s", SvPV(sv,na));
- break;
- }
- return io;
-}
-