X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=sv.c;h=0e7ca25bfe896ec8fa29cf71515630398ac22861;hb=463ee0b2acbd047c27e8b5393cdd8398881824c5;hp=9440f8a210ebfaf95558422af2de4992972db0ce;hpb=93a17b20b6d176db3f04f51a63b0a781e5ffd11c;p=p5sagit%2Fp5-mst-13.2.git diff --git a/sv.c b/sv.c index 9440f8a..0e7ca25 100644 --- a/sv.c +++ b/sv.c @@ -50,6 +50,246 @@ static void ucase(); static void lcase(); +static SV* sv_root; + +static SV* more_sv(); + +static SV* +new_sv() +{ + SV* sv; + if (sv_root) { + sv = sv_root; + sv_root = (SV*)SvANY(sv); + return sv; + } + return more_sv(); +} + +static void +del_sv(p) +SV* p; +{ + SvANY(p) = sv_root; + sv_root = p; +} + +static SV* +more_sv() +{ + register int i; + register SV* sv; + register SV* svend; + sv_root = (SV*)malloc(1008); + sv = sv_root; + svend = &sv[1008 / sizeof(SV) - 1]; + while (sv < svend) { + SvANY(sv) = (SV*)(sv + 1); + sv++; + } + SvANY(sv) = 0; + return new_sv(); +} + +static I32* xiv_root; + +static XPVIV* more_xiv(); + +static XPVIV* +new_xiv() +{ + I32* xiv; + if (xiv_root) { + xiv = xiv_root; + xiv_root = *(I32**)xiv; + return (XPVIV*)((char*)xiv - sizeof(XPV)); + } + return more_xiv(); +} + +static void +del_xiv(p) +XPVIV* p; +{ + I32* xiv = (I32*)((char*)(p) + sizeof(XPV)); + *(I32**)xiv = xiv_root; + xiv_root = xiv; +} + +static XPVIV* +more_xiv() +{ + register int i; + register I32* xiv; + register I32* xivend; + xiv = (I32*)malloc(1008); + xivend = &xiv[1008 / sizeof(I32) - 1]; + xiv += (sizeof(XPV) - 1) / sizeof(I32) + 1; /* fudge by size of XPV */ + xiv_root = xiv; + while (xiv < xivend) { + *(I32**)xiv = (I32*)(xiv + 1); /* XXX busted on Alpha? */ + xiv++; + } + *(I32**)xiv = 0; + return new_xiv(); +} + +static double* xnv_root; + +static XPVNV* more_xnv(); + +static XPVNV* +new_xnv() +{ + double* xnv; + if (xnv_root) { + xnv = xnv_root; + xnv_root = *(double**)xnv; + return (XPVNV*)((char*)xnv - sizeof(XPVIV)); + } + return more_xnv(); +} + +static void +del_xnv(p) +XPVNV* p; +{ + double* xnv = (double*)((char*)(p) + sizeof(XPVIV)); + *(double**)xnv = xnv_root; + xnv_root = xnv; +} + +static XPVNV* +more_xnv() +{ + register int i; + register double* xnv; + register double* xnvend; + xnv = (double*)malloc(1008); + xnvend = &xnv[1008 / sizeof(double) - 1]; + xnv += (sizeof(XPVIV) - 1) / sizeof(double) + 1; /* fudge by sizeof XPVIV */ + xnv_root = xnv; + while (xnv < xnvend) { + *(double**)xnv = (double*)(xnv + 1); + xnv++; + } + *(double**)xnv = 0; + return new_xnv(); +} + +static XPV* xpv_root; + +static XPV* more_xpv(); + +static XPV* +new_xpv() +{ + XPV* xpv; + if (xpv_root) { + xpv = xpv_root; + xpv_root = (XPV*)xpv->xpv_pv; + return xpv; + } + return more_xpv(); +} + +static void +del_xpv(p) +XPV* p; +{ + p->xpv_pv = (char*)xpv_root; + xpv_root = p; +} + +static XPV* +more_xpv() +{ + register int i; + register XPV* xpv; + register XPV* xpvend; + xpv_root = (XPV*)malloc(1008); + xpv = xpv_root; + xpvend = &xpv[1008 / sizeof(XPV) - 1]; + while (xpv < xpvend) { + xpv->xpv_pv = (char*)(xpv + 1); + xpv++; + } + xpv->xpv_pv = 0; + return new_xpv(); +} + +#ifdef PURIFY + +#define new_SV() sv = (SV*)malloc(sizeof(SV)) +#define del_SV(p) free((char*)p) + +#else + +#define new_SV() \ + if (sv_root) { \ + sv = sv_root; \ + sv_root = (SV*)SvANY(sv); \ + } \ + else \ + sv = more_sv(); +#define del_SV(p) del_sv(p) + +#endif + +#ifdef PURIFY +#define new_XIV() (void*)malloc(sizeof(XPVIV)) +#define del_XIV(p) free((char*)p) +#else +#define new_XIV() new_xiv() +#define del_XIV(p) del_xiv(p) +#endif + +#ifdef PURIFY +#define new_XNV() (void*)malloc(sizeof(XPVNV)) +#define del_XNV(p) free((char*)p) +#else +#define new_XNV() new_xnv() +#define del_XNV(p) del_xnv(p) +#endif + +#ifdef PURIFY +#define new_XPV() (void*)malloc(sizeof(XPV)) +#define del_XPV(p) free((char*)p) +#else +#define new_XPV() new_xpv() +#define del_XPV(p) del_xpv(p) +#endif + +#define new_XPVIV() (void*)malloc(sizeof(XPVIV)) +#define del_XPVIV(p) free((char*)p) + +#define new_XPVNV() (void*)malloc(sizeof(XPVNV)) +#define del_XPVNV(p) free((char*)p) + +#define new_XPVMG() (void*)malloc(sizeof(XPVMG)) +#define del_XPVMG(p) free((char*)p) + +#define new_XPVLV() (void*)malloc(sizeof(XPVLV)) +#define del_XPVLV(p) free((char*)p) + +#define new_XPVAV() (void*)malloc(sizeof(XPVAV)) +#define del_XPVAV(p) free((char*)p) + +#define new_XPVHV() (void*)malloc(sizeof(XPVHV)) +#define del_XPVHV(p) free((char*)p) + +#define new_XPVCV() (void*)malloc(sizeof(XPVCV)) +#define del_XPVCV(p) free((char*)p) + +#define new_XPVGV() (void*)malloc(sizeof(XPVGV)) +#define del_XPVGV(p) free((char*)p) + +#define new_XPVBM() (void*)malloc(sizeof(XPVBM)) +#define del_XPVBM(p) free((char*)p) + +#define new_XPVFM() (void*)malloc(sizeof(XPVFM)) +#define del_XPVFM(p) free((char*)p) + bool sv_upgrade(sv, mt) register SV* sv; @@ -81,8 +321,8 @@ U32 mt; pv = 0; cur = 0; len = 0; - iv = SvANYI32(sv); - nv = (double)SvANYI32(sv); + iv = (I32)SvANY(sv); + nv = (double)(unsigned long)SvANY(sv); SvNOK_only(sv); magic = 0; stash = 0; @@ -93,23 +333,22 @@ U32 mt; pv = 0; cur = 0; len = 0; - iv = SvIV(sv); - nv = (double)SvIV(sv); + iv = SvIVX(sv); + nv = (double)SvIVX(sv); del_XIV(SvANY(sv)); magic = 0; stash = 0; if (mt == SVt_PV) mt = SVt_PVIV; + else if (mt == SVt_NV) + mt = SVt_PVNV; break; case SVt_NV: pv = 0; cur = 0; len = 0; - if (SvIOK(sv)) - iv = SvIV(sv); - else - iv = (I32)SvNV(sv); - nv = SvNV(sv); + nv = SvNVX(sv); + iv = (I32)nv; magic = 0; stash = 0; del_XNV(SvANY(sv)); @@ -119,7 +358,7 @@ U32 mt; break; case SVt_PV: nv = 0.0; - pv = SvPV(sv); + pv = SvPVX(sv); cur = SvCUR(sv); len = SvLEN(sv); iv = 0; @@ -130,96 +369,95 @@ U32 mt; break; case SVt_PVIV: nv = 0.0; - pv = SvPV(sv); + pv = SvPVX(sv); cur = SvCUR(sv); len = SvLEN(sv); - iv = SvIV(sv); + iv = SvIVX(sv); nv = 0.0; magic = 0; stash = 0; del_XPVIV(SvANY(sv)); break; case SVt_PVNV: - nv = SvNV(sv); - pv = SvPV(sv); + nv = SvNVX(sv); + pv = SvPVX(sv); cur = SvCUR(sv); len = SvLEN(sv); - iv = SvIV(sv); - nv = SvNV(sv); + iv = SvIVX(sv); + nv = SvNVX(sv); magic = 0; stash = 0; del_XPVNV(SvANY(sv)); break; case SVt_PVMG: - pv = SvPV(sv); + pv = SvPVX(sv); cur = SvCUR(sv); len = SvLEN(sv); - iv = SvIV(sv); - nv = SvNV(sv); + iv = SvIVX(sv); + nv = SvNVX(sv); magic = SvMAGIC(sv); stash = SvSTASH(sv); del_XPVMG(SvANY(sv)); break; default: - fatal("Can't upgrade that kind of scalar"); + croak("Can't upgrade that kind of scalar"); } switch (mt) { case SVt_NULL: - fatal("Can't upgrade to undef"); + croak("Can't upgrade to undef"); case SVt_REF: - SvIOK_on(sv); + SvOK_on(sv); break; case SVt_IV: SvANY(sv) = new_XIV(); - SvIV(sv) = iv; + SvIVX(sv) = iv; break; case SVt_NV: SvANY(sv) = new_XNV(); - SvIV(sv) = iv; - SvNV(sv) = nv; + SvNVX(sv) = nv; break; case SVt_PV: SvANY(sv) = new_XPV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; break; case SVt_PVIV: SvANY(sv) = new_XPVIV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; + SvIVX(sv) = iv; if (SvNIOK(sv)) SvIOK_on(sv); SvNOK_off(sv); break; case SVt_PVNV: SvANY(sv) = new_XPVNV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; break; case SVt_PVMG: SvANY(sv) = new_XPVMG(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; break; case SVt_PVLV: SvANY(sv) = new_XPVLV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; LvTARGOFF(sv) = 0; @@ -229,49 +467,42 @@ U32 mt; break; case SVt_PVAV: SvANY(sv) = new_XPVAV(); - SvPV(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; - SvMAGIC(sv) = magic; - SvSTASH(sv) = stash; - AvMAGIC(sv) = 0; + if (pv) + Safefree(pv); AvARRAY(sv) = 0; - AvALLOC(sv) = 0; AvMAX(sv) = 0; AvFILL(sv) = 0; + SvIVX(sv) = 0; + SvNVX(sv) = 0.0; + SvMAGIC(sv) = magic; + SvSTASH(sv) = stash; + AvALLOC(sv) = 0; AvARYLEN(sv) = 0; AvFLAGS(sv) = 0; break; case SVt_PVHV: SvANY(sv) = new_XPVHV(); - SvPV(sv) = pv; - SvCUR(sv) = cur; - SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + if (pv) + Safefree(pv); + SvPVX(sv) = 0; + HvFILL(sv) = 0; + HvMAX(sv) = 0; + HvKEYS(sv) = 0; + SvNVX(sv) = 0.0; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; - HvMAGIC(sv) = 0; - HvARRAY(sv) = 0; - HvMAX(sv) = 0; - HvDOSPLIT(sv) = 0; - HvFILL(sv) = 0; HvRITER(sv) = 0; HvEITER(sv) = 0; HvPMROOT(sv) = 0; HvNAME(sv) = 0; - HvDBM(sv) = 0; - HvCOEFFSIZE(sv) = 0; break; case SVt_PVCV: SvANY(sv) = new_XPVCV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; CvSTASH(sv) = 0; @@ -286,11 +517,11 @@ U32 mt; break; case SVt_PVGV: SvANY(sv) = new_XPVGV(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; GvGP(sv) = 0; @@ -300,11 +531,11 @@ U32 mt; break; case SVt_PVBM: SvANY(sv) = new_XPVBM(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; BmRARE(sv) = 0; @@ -313,11 +544,11 @@ U32 mt; break; case SVt_PVFM: SvANY(sv) = new_XPVFM(); - SvPV(sv) = pv; + SvPVX(sv) = pv; SvCUR(sv) = cur; SvLEN(sv) = len; - SvIV(sv) = iv; - SvNV(sv) = nv; + SvIVX(sv) = iv; + SvNVX(sv) = nv; SvMAGIC(sv) = magic; SvSTASH(sv) = stash; FmLINES(sv) = 0; @@ -409,17 +640,17 @@ register SV *sv; t += strlen(t); if (SvPOK(sv)) { - if (!SvPV(sv)) + if (!SvPVX(sv)) return "(null)"; if (SvOOK(sv)) - sprintf(t,"(%d+\"%0.127s\")",SvIV(sv),SvPV(sv)); + sprintf(t,"(%d+\"%0.127s\")",SvIVX(sv),SvPVX(sv)); else - sprintf(t,"(\"%0.127s\")",SvPV(sv)); + sprintf(t,"(\"%0.127s\")",SvPVX(sv)); } else if (SvNOK(sv)) - sprintf(t,"(%g)",SvNV(sv)); + sprintf(t,"(%g)",SvNVX(sv)); else if (SvIOK(sv)) - sprintf(t,"(%ld)",(long)SvIV(sv)); + sprintf(t,"(%ld)",(long)SvIVX(sv)); else strcpy(t,"()"); return tokenbuf; @@ -430,12 +661,12 @@ sv_backoff(sv) register SV *sv; { assert(SvOOK(sv)); - if (SvIV(sv)) { - char *s = SvPV(sv); - SvLEN(sv) += SvIV(sv); - SvPV(sv) -= SvIV(sv); + if (SvIVX(sv)) { + char *s = SvPVX(sv); + SvLEN(sv) += SvIVX(sv); + SvPVX(sv) -= SvIVX(sv); SvIV_set(sv, 0); - Move(s, SvPV(sv), SvCUR(sv)+1, char); + Move(s, SvPVX(sv), SvCUR(sv)+1, char); } SvFLAGS(sv) &= ~SVf_OOK; } @@ -458,19 +689,19 @@ unsigned long newlen; } #endif /* MSDOS */ if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (SvTYPE(sv) < SVt_PV) { sv_upgrade(sv, SVt_PV); - s = SvPV(sv); + s = SvPVX(sv); } else if (SvOOK(sv)) { /* pv is offset? */ sv_backoff(sv); - s = SvPV(sv); + s = SvPVX(sv); if (newlen > SvLEN(sv)) newlen += 10 * (newlen - SvCUR(sv)); /* avoid copy each time */ } else - s = SvPV(sv); + s = SvPVX(sv); if (newlen > SvLEN(sv)) { /* need more room? */ if (SvLEN(sv)) Renew(s,newlen,char); @@ -488,14 +719,22 @@ register SV *sv; I32 i; { if (SvREADONLY(sv)) - fatal(no_modify); - if (SvTYPE(sv) < SVt_IV) + croak(no_modify); + switch (SvTYPE(sv)) { + case SVt_NULL: + case SVt_REF: sv_upgrade(sv, SVt_IV); - else if (SvTYPE(sv) == SVt_PV) + break; + case SVt_NV: + sv_upgrade(sv, SVt_PVNV); + break; + case SVt_PV: sv_upgrade(sv, SVt_PVIV); - SvIV(sv) = i; + break; + } + SvIVX(sv) = i; SvIOK_only(sv); /* validate number */ - SvTDOWN(sv); + SvTAINT(sv); } void @@ -504,7 +743,7 @@ register SV *sv; double num; { if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (SvTYPE(sv) < SVt_NV) sv_upgrade(sv, SVt_NV); else if (SvTYPE(sv) < SVt_PVNV) @@ -512,9 +751,9 @@ double num; else if (SvPOK(sv)) { SvOOK_off(sv); } - SvNV(sv) = num; + SvNVX(sv) = num; SvNOK_only(sv); /* validate number */ - SvTDOWN(sv); + SvTAINT(sv); } I32 @@ -523,26 +762,40 @@ register SV *sv; { if (!sv) return 0; + if (SvMAGICAL(sv)) { + mg_get(sv); + if (SvIOKp(sv)) + return SvIVX(sv); + if (SvNOKp(sv)) + return (I32)SvNVX(sv); + if (SvPOKp(sv) && SvLEN(sv)) + return (I32)atol(SvPVX(sv)); + return 0; + } if (SvREADONLY(sv)) { if (SvNOK(sv)) - return (I32)SvNV(sv); + return (I32)SvNVX(sv); if (SvPOK(sv) && SvLEN(sv)) - return atof(SvPV(sv)); + return (I32)atol(SvPVX(sv)); if (dowarn) warn("Use of uninitialized variable"); return 0; } - if (SvTYPE(sv) < SVt_IV) { - if (SvTYPE(sv) == SVt_REF) - return (I32)SvANYI32(sv); + switch (SvTYPE(sv)) { + case SVt_REF: + return (I32)SvANY(sv); + case SVt_NULL: sv_upgrade(sv, SVt_IV); - DEBUG_c((stderr,"0x%lx num(%g)\n",sv,SvIV(sv))); - return SvIV(sv); - } - else if (SvTYPE(sv) == SVt_PV) + return SvIVX(sv); + case SVt_PV: sv_upgrade(sv, SVt_PVIV); + break; + case SVt_NV: + sv_upgrade(sv, SVt_PVNV); + break; + } if (SvNOK(sv)) - SvIV(sv) = (I32)SvNV(sv); + SvIVX(sv) = (I32)SvNVX(sv); else if (SvPOK(sv) && SvLEN(sv)) { if (dowarn && !looks_like_number(sv)) { if (op) @@ -550,17 +803,17 @@ register SV *sv; else warn("Argument wasn't numeric"); } - SvIV(sv) = atol(SvPV(sv)); + SvIVX(sv) = (I32)atol(SvPVX(sv)); } else { if (dowarn) warn("Use of uninitialized variable"); SvUPGRADE(sv, SVt_IV); - SvIV(sv) = 0; + SvIVX(sv) = 0; } SvIOK_on(sv); - DEBUG_c((stderr,"0x%lx 2iv(%d)\n",sv,SvIV(sv))); - return SvIV(sv); + DEBUG_c((stderr,"0x%lx 2iv(%d)\n",sv,SvIVX(sv))); + return SvIVX(sv); } double @@ -569,26 +822,39 @@ register SV *sv; { if (!sv) return 0.0; + if (SvMAGICAL(sv)) { + mg_get(sv); + if (SvNOKp(sv)) + return SvNVX(sv); + if (SvPOKp(sv) && SvLEN(sv)) + return atof(SvPVX(sv)); + if (SvIOKp(sv)) + return (double)SvIVX(sv); + return 0; + } if (SvREADONLY(sv)) { if (SvPOK(sv) && SvLEN(sv)) - return atof(SvPV(sv)); + return atof(SvPVX(sv)); if (dowarn) warn("Use of uninitialized variable"); return 0.0; } if (SvTYPE(sv) < SVt_NV) { if (SvTYPE(sv) == SVt_REF) - return (double)SvANYI32(sv); - sv_upgrade(sv, SVt_NV); - DEBUG_c((stderr,"0x%lx num(%g)\n",sv,SvNV(sv))); - return SvNV(sv); + return (double)(unsigned long)SvANY(sv); + if (SvTYPE(sv) == SVt_IV) + sv_upgrade(sv, SVt_PVNV); + else + sv_upgrade(sv, SVt_NV); + DEBUG_c((stderr,"0x%lx num(%g)\n",sv,SvNVX(sv))); + return SvNVX(sv); } else if (SvTYPE(sv) < SVt_PVNV) sv_upgrade(sv, SVt_PVNV); if (SvIOK(sv) && - (!SvPOK(sv) || !strchr(SvPV(sv),'.') || !looks_like_number(sv))) + (!SvPOK(sv) || !strchr(SvPVX(sv),'.') || !looks_like_number(sv))) { - SvNV(sv) = (double)SvIV(sv); + SvNVX(sv) = (double)SvIVX(sv); } else if (SvPOK(sv) && SvLEN(sv)) { if (dowarn && !SvIOK(sv) && !looks_like_number(sv)) { @@ -597,63 +863,96 @@ register SV *sv; else warn("Argument wasn't numeric"); } - SvNV(sv) = atof(SvPV(sv)); + SvNVX(sv) = atof(SvPVX(sv)); } else { if (dowarn) warn("Use of uninitialized variable"); - SvNV(sv) = 0.0; + SvNVX(sv) = 0.0; } SvNOK_on(sv); - DEBUG_c((stderr,"0x%lx 2nv(%g)\n",sv,SvNV(sv))); - return SvNV(sv); + DEBUG_c((stderr,"0x%lx 2nv(%g)\n",sv,SvNVX(sv))); + return SvNVX(sv); } char * -sv_2pv(sv) +sv_2pv(sv, lp) register SV *sv; +STRLEN *lp; { register char *s; int olderrno; - if (!sv) + if (!sv) { + *lp = 0; + return ""; + } + if (SvMAGICAL(sv)) { + mg_get(sv); + if (SvPOKp(sv)) { + *lp = SvCUR(sv); + return SvPVX(sv); + } + if (SvIOKp(sv)) { + (void)sprintf(tokenbuf,"%ld",SvIVX(sv)); + *lp = strlen(tokenbuf); + return tokenbuf; + } + if (SvNOKp(sv)) { + (void)sprintf(tokenbuf,"%.20g",SvNVX(sv)); + *lp = strlen(tokenbuf); + return tokenbuf; + } + *lp = 0; return ""; + } if (SvTYPE(sv) == SVt_REF) { sv = (SV*)SvANY(sv); if (!sv) - return ""; - switch (SvTYPE(sv)) { - case SVt_NULL: s = "an undefined value"; break; - case SVt_REF: s = "a reference"; break; - case SVt_IV: s = "an integer value"; break; - case SVt_NV: s = "a numeric value"; break; - case SVt_PV: s = "a string value"; break; - case SVt_PVIV: s = "a string+integer value"; break; - case SVt_PVNV: s = "a scalar value"; break; - case SVt_PVMG: s = "a magic value"; break; - case SVt_PVLV: s = "an lvalue"; break; - case SVt_PVAV: s = "an array value"; break; - case SVt_PVHV: s = "an associative array value"; break; - case SVt_PVCV: s = "a code value"; break; - case SVt_PVGV: s = "a glob value"; break; - case SVt_PVBM: s = "a search string"; break; - case SVt_PVFM: s = "a formatline"; break; - default: s = "something weird"; break; + s = "NULLREF"; + else { + switch (SvTYPE(sv)) { + case SVt_NULL: + case SVt_REF: + case SVt_IV: + case SVt_NV: + case SVt_PV: + case SVt_PVIV: + case SVt_PVNV: + case SVt_PVMG: 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_PVBM: s = "SEARCHSTRING"; break; + case SVt_PVFM: s = "FORMATLINE"; break; + default: s = "UNKNOWN"; break; + } + if (SvSTORAGE(sv) == 'O') + sprintf(tokenbuf, "%s=%s(0x%lx)", + HvNAME(SvSTASH(sv)), s, (unsigned long)sv); + else + sprintf(tokenbuf, "%s(0x%lx)", s, (unsigned long)sv); + s = tokenbuf; } - sprintf(tokenbuf,"", s, (unsigned long)sv); - return tokenbuf; + *lp = strlen(s); + return s; } if (SvREADONLY(sv)) { if (SvIOK(sv)) { - (void)sprintf(tokenbuf,"%ld",SvIV(sv)); + (void)sprintf(tokenbuf,"%ld",SvIVX(sv)); + *lp = strlen(tokenbuf); return tokenbuf; } if (SvNOK(sv)) { - (void)sprintf(tokenbuf,"%.20g",SvNV(sv)); + (void)sprintf(tokenbuf,"%.20g",SvNVX(sv)); + *lp = strlen(tokenbuf); return tokenbuf; } if (dowarn) warn("Use of uninitialized variable"); + *lp = 0; return ""; } if (!SvUPGRADE(sv, SVt_PV)) @@ -662,17 +961,17 @@ register SV *sv; if (SvTYPE(sv) < SVt_PVNV) sv_upgrade(sv, SVt_PVNV); SvGROW(sv, 28); - s = SvPV(sv); + s = SvPVX(sv); olderrno = errno; /* some Xenix systems wipe out errno here */ #if defined(scs) && defined(ns32000) - gcvt(SvNV(sv),20,s); + gcvt(SvNVX(sv),20,s); #else #ifdef apollo - if (SvNV(sv) == 0.0) + if (SvNVX(sv) == 0.0) (void)strcpy(s,"0"); else #endif /*apollo*/ - (void)sprintf(s,"%.20g",SvNV(sv)); + (void)sprintf(s,"%.20g",SvNVX(sv)); #endif /*scs*/ errno = olderrno; while (*s) s++; @@ -685,9 +984,9 @@ register SV *sv; if (SvTYPE(sv) < SVt_PVIV) sv_upgrade(sv, SVt_PVIV); SvGROW(sv, 11); - s = SvPV(sv); + s = SvPVX(sv); olderrno = errno; /* some Xenix systems wipe out errno here */ - (void)sprintf(s,"%ld",SvIV(sv)); + (void)sprintf(s,"%ld",SvIVX(sv)); errno = olderrno; while (*s) s++; } @@ -695,17 +994,50 @@ register SV *sv; if (dowarn) warn("Use of uninitialized variable"); sv_grow(sv, 1); - s = SvPV(sv); + s = SvPVX(sv); } *s = '\0'; - SvCUR_set(sv, s - SvPV(sv)); + *lp = s - SvPVX(sv); + SvCUR_set(sv, *lp); SvPOK_on(sv); - DEBUG_c((stderr,"0x%lx 2pv(%s)\n",sv,SvPV(sv))); - return SvPV(sv); + DEBUG_c((stderr,"0x%lx 2pv(%s)\n",sv,SvPVX(sv))); + return SvPVX(sv); +} + +/* This function is only called on magical items */ +bool +sv_2bool(sv) +register SV *sv; +{ + if (SvMAGICAL(sv)) + mg_get(sv); + + if (SvTYPE(sv) == SVt_REF) + return SvANY(sv) != 0; + if (SvPOKp(sv)) { + register XPV* Xpv; + if ((Xpv = (XPV*)SvANY(sv)) && + (*Xpv->xpv_pv > '0' || + Xpv->xpv_cur > 1 || + (Xpv->xpv_cur && *Xpv->xpv_pv != '0'))) + return 1; + else + return 0; + } + else { + if (SvIOKp(sv)) + return SvIVX(sv) != 0; + else { + if (SvNOKp(sv)) + return SvNVX(sv) != 0.0; + else + return FALSE; + } + } } /* Note: sv_setsv() should not be called with a source string that needs - * be reused, since it may destroy the source string if it is marked + * to be reused, since it may destroy the source string if it is marked * as temporary. */ @@ -714,23 +1046,16 @@ sv_setsv(dstr,sstr) SV *dstr; register SV *sstr; { + int flags; + if (sstr == dstr) return; if (SvREADONLY(dstr)) - fatal(no_modify); + croak(no_modify); if (!sstr) sstr = &sv_undef; - if (SvTYPE(dstr) < SvTYPE(sstr)) - sv_upgrade(dstr, SvTYPE(sstr)); - else if (SvTYPE(dstr) == SVt_PV && SvTYPE(sstr) <= SVt_NV) { - if (SvTYPE(sstr) <= SVt_IV) - sv_upgrade(dstr, SVt_PVIV); /* handle discontinuities */ - else - sv_upgrade(dstr, SVt_PVNV); - } - else if (SvTYPE(dstr) == SVt_PVIV && SvTYPE(sstr) == SVt_NV) - sv_upgrade(dstr, SVt_PVNV); + /* There's a lot of redundancy below but we're going for speed here */ switch (SvTYPE(sstr)) { case SVt_NULL: @@ -743,23 +1068,63 @@ register SV *sstr; SvOK_off(dstr); return; case SVt_REF: - SvTUP(sstr); + if (SvTYPE(dstr) < SVt_REF) + sv_upgrade(dstr, SVt_REF); if (SvTYPE(dstr) == SVt_REF) { + sv_free((SV*)SvANY(dstr)); + SvANY(dstr) = 0; SvANY(dstr) = (void*)sv_ref((SV*)SvANY(sstr)); } else { if (SvMAGICAL(dstr)) - fatal("Can't assign a reference to a magical variable"); + croak("Can't assign a reference to a magical variable"); + if (SvREFCNT(dstr) != 1) + warn("Reference miscount in sv_setsv()"); + SvREFCNT(dstr) = 0; sv_clear(dstr); SvTYPE(dstr) = SVt_REF; SvANY(dstr) = (void*)sv_ref((SV*)SvANY(sstr)); SvOK_off(dstr); } - SvTDOWN(sstr); + SvTAINT(sstr); return; + case SVt_IV: + if (SvTYPE(dstr) < SVt_IV) + sv_upgrade(dstr, SVt_IV); + else if (SvTYPE(dstr) == SVt_PV) + sv_upgrade(dstr, SVt_PVIV); + else if (SvTYPE(dstr) == SVt_NV) + sv_upgrade(dstr, SVt_PVNV); + flags = SvFLAGS(sstr); + break; + case SVt_NV: + if (SvTYPE(dstr) < SVt_NV) + sv_upgrade(dstr, SVt_NV); + else if (SvTYPE(dstr) == SVt_PV) + sv_upgrade(dstr, SVt_PVNV); + else if (SvTYPE(dstr) == SVt_PVIV) + sv_upgrade(dstr, SVt_PVNV); + flags = SvFLAGS(sstr); + break; + case SVt_PV: + if (SvTYPE(dstr) < SVt_PV) + sv_upgrade(dstr, SVt_PV); + flags = SvFLAGS(sstr); + break; + case SVt_PVIV: + if (SvTYPE(dstr) < SVt_PVIV) + sv_upgrade(dstr, SVt_PVIV); + flags = SvFLAGS(sstr); + break; + case SVt_PVNV: + if (SvTYPE(dstr) < SVt_PVNV) + sv_upgrade(dstr, SVt_PVNV); + flags = SvFLAGS(sstr); + break; case SVt_PVGV: - SvTUP(sstr); - if (SvTYPE(dstr) == SVt_PVGV) { + if (SvTYPE(dstr) <= SVt_PVGV) { + if (SvTYPE(dstr) < SVt_PVGV) + sv_upgrade(dstr, SVt_PVGV); SvOK_off(dstr); if (!GvAV(sstr)) gv_AVadd(sstr); @@ -770,83 +1135,81 @@ register SV *sstr; if (GvGP(dstr)) gp_free(dstr); GvGP(dstr) = gp_ref(GvGP(sstr)); - SvTDOWN(sstr); + SvTAINT(sstr); return; } /* FALL THROUGH */ default: - if (SvMAGICAL(sstr)) + if (SvTYPE(dstr) < SvTYPE(sstr)) + sv_upgrade(dstr, SvTYPE(sstr)); + if (SvMAGICAL(sstr)) { mg_get(sstr); - /* XXX */ - break; + flags = SvPRIVATE(sstr); + } + else + flags = SvFLAGS(sstr); } - SvPRIVATE(dstr) = SvPRIVATE(sstr); - SvSTORAGE(dstr) = SvSTORAGE(sstr); - if (SvPOK(sstr)) { + SvPRIVATE(dstr) = SvPRIVATE(sstr) & ~(SVf_IOK|SVf_POK|SVf_NOK); - SvTUP(sstr); + if (flags & SVf_POK) { /* * Check to see if we can just swipe the string. If so, it's a * possible small lose on short strings, but a big win on long ones. - * It might even be a win on short strings if SvPV(dstr) - * has to be allocated and SvPV(sstr) has to be freed. + * It might even be a win on short strings if SvPVX(dstr) + * has to be allocated and SvPVX(sstr) has to be freed. */ if (SvTEMP(sstr)) { /* slated for free anyway? */ if (SvPOK(dstr)) { SvOOK_off(dstr); - Safefree(SvPV(dstr)); + Safefree(SvPVX(dstr)); } - SvPV_set(dstr, SvPV(sstr)); + SvPV_set(dstr, SvPVX(sstr)); SvLEN_set(dstr, SvLEN(sstr)); SvCUR_set(dstr, SvCUR(sstr)); - SvTYPE(dstr) = SvTYPE(sstr); SvPOK_only(dstr); SvTEMP_off(dstr); SvPV_set(sstr, Nullch); SvLEN_set(sstr, 0); SvPOK_off(sstr); /* wipe out any weird flags */ - SvTYPE(sstr) = 0; /* so sstr frees uneventfully */ + SvPVX(sstr) = 0; /* so sstr frees uneventfully */ } else { /* have to copy actual string */ - if (SvPV(dstr)) { /* XXX ck type */ + if (SvPVX(dstr)) { /* XXX ck type */ SvOOK_off(dstr); } - sv_setpvn(dstr,SvPV(sstr),SvCUR(sstr)); + sv_setpvn(dstr,SvPVX(sstr),SvCUR(sstr)); } /*SUPPRESS 560*/ - if (SvNOK(sstr)) { + if (flags & SVf_NOK) { SvNOK_on(dstr); - SvNV(dstr) = SvNV(sstr); + SvNVX(dstr) = SvNVX(sstr); } - if (SvIOK(sstr)) { + if (flags & SVf_IOK) { SvIOK_on(dstr); - SvIV(dstr) = SvIV(sstr); + SvIVX(dstr) = SvIVX(sstr); } } - else if (SvNOK(sstr)) { - SvTUP(sstr); - SvNV(dstr) = SvNV(sstr); + else if (flags & SVf_NOK) { + SvNVX(dstr) = SvNVX(sstr); SvNOK_only(dstr); if (SvIOK(sstr)) { SvIOK_on(dstr); - SvIV(dstr) = SvIV(sstr); + SvIVX(dstr) = SvIVX(sstr); } } - else if (SvIOK(sstr)) { - SvTUP(sstr); + else if (flags & SVf_IOK) { SvIOK_only(dstr); - SvIV(dstr) = SvIV(sstr); + SvIVX(dstr) = SvIVX(sstr); } else { - SvTUP(sstr); SvOK_off(dstr); } - SvTDOWN(dstr); + SvTAINT(dstr); } void @@ -855,15 +1218,21 @@ register SV *sv; register char *ptr; register STRLEN len; { + if (SvREADONLY(sv)) + croak(no_modify); + if (!ptr) { + SvOK_off(sv); + return; + } if (!SvUPGRADE(sv, SVt_PV)) return; SvGROW(sv, len + 1); if (ptr) - Move(ptr,SvPV(sv),len,char); + Move(ptr,SvPVX(sv),len,char); SvCUR_set(sv, len); *SvEND(sv) = '\0'; SvPOK_only(sv); /* validate pointer */ - SvTDOWN(sv); + SvTAINT(sv); } void @@ -874,17 +1243,44 @@ register char *ptr; register STRLEN len; if (SvREADONLY(sv)) - fatal(no_modify); - if (!ptr) - ptr = ""; + croak(no_modify); + if (!ptr) { + SvOK_off(sv); + return; + } len = strlen(ptr); if (!SvUPGRADE(sv, SVt_PV)) return; SvGROW(sv, len + 1); - Move(ptr,SvPV(sv),len+1,char); + Move(ptr,SvPVX(sv),len+1,char); SvCUR_set(sv, len); SvPOK_only(sv); /* validate pointer */ - SvTDOWN(sv); + SvTAINT(sv); +} + +void +sv_usepvn(sv,ptr,len) +register SV *sv; +register char *ptr; +register STRLEN len; +{ + if (SvREADONLY(sv)) + croak(no_modify); + if (!SvUPGRADE(sv, SVt_PV)) + return; + if (!ptr) { + SvOK_off(sv); + return; + } + if (SvPVX(sv)) + Safefree(SvPVX(sv)); + Renew(ptr, len+1, char); + SvPVX(sv) = ptr; + SvCUR_set(sv, len); + SvLEN_set(sv, len+1); + *SvEND(sv) = '\0'; + SvPOK_only(sv); /* validate pointer */ + SvTAINT(sv); } void @@ -897,20 +1293,20 @@ register char *ptr; if (!ptr || !SvPOK(sv)) return; if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (SvTYPE(sv) < SVt_PVIV) sv_upgrade(sv,SVt_PVIV); if (!SvOOK(sv)) { - SvIV(sv) = 0; + SvIVX(sv) = 0; SvFLAGS(sv) |= SVf_OOK; } SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK); - delta = ptr - SvPV(sv); + delta = ptr - SvPVX(sv); SvLEN(sv) -= delta; SvCUR(sv) -= delta; - SvPV(sv) += delta; - SvIV(sv) += delta; + SvPVX(sv) += delta; + SvIVX(sv) += delta; } void @@ -919,16 +1315,17 @@ register SV *sv; register char *ptr; register STRLEN len; { + STRLEN tlen; + char *s; if (SvREADONLY(sv)) - fatal(no_modify); - if (!(SvPOK(sv))) - (void)sv_2pv(sv); - SvGROW(sv, SvCUR(sv) + len + 1); - Move(ptr,SvPV(sv)+SvCUR(sv),len,char); + croak(no_modify); + s = SvPV(sv, tlen); + SvGROW(sv, tlen + len + 1); + Move(ptr,SvPVX(sv)+tlen,len,char); SvCUR(sv) += len; *SvEND(sv) = '\0'; SvPOK_only(sv); /* validate pointer */ - SvTDOWN(sv); + SvTAINT(sv); } void @@ -937,14 +1334,11 @@ SV *dstr; register SV *sstr; { char *s; + STRLEN len; if (!sstr) return; - if (s = SvPVn(sstr)) { - if (SvPOK(sstr)) - sv_catpvn(dstr,s,SvCUR(sstr)); - else - sv_catpv(dstr,s); - } + if (s = SvPV(sstr, len)) + sv_catpvn(dstr,s,len); } void @@ -953,19 +1347,20 @@ register SV *sv; register char *ptr; { register STRLEN len; + STRLEN tlen; + char *s; if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (!ptr) return; - if (!(SvPOK(sv))) - (void)sv_2pv(sv); + s = SvPV(sv, tlen); len = strlen(ptr); - SvGROW(sv, SvCUR(sv) + len + 1); - Move(ptr,SvPV(sv)+SvCUR(sv),len+1,char); + SvGROW(sv, tlen + len + 1); + Move(ptr,SvPVX(sv)+tlen,len+1,char); SvCUR(sv) += len; SvPOK_only(sv); /* validate pointer */ - SvTDOWN(sv); + SvTAINT(sv); } SV * @@ -979,7 +1374,7 @@ STRLEN len; { register SV *sv; - sv = (SV*)new_SV(); + new_SV(); Zero(sv, 1, SV); SvREFCNT(sv)++; if (len) { @@ -995,24 +1390,33 @@ register SV *sv; SV *obj; char how; char *name; -STRLEN namlen; +I32 namlen; { MAGIC* mg; if (SvREADONLY(sv)) - fatal(no_modify); - if (!SvUPGRADE(sv, SVt_PVMG)) - return; + croak(no_modify); + if (SvMAGICAL(sv)) { + if (SvMAGIC(sv) && mg_find(sv, how)) + return; + } + else { + if (!SvUPGRADE(sv, SVt_PVMG)) + return; + SvMAGICAL_on(sv); + SvPRIVATE(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + SvPRIVATE(sv) |= SvFLAGS(sv) & (SVf_IOK|SVf_NOK|SVf_POK); + SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + } Newz(702,mg, 1, MAGIC); mg->mg_moremagic = SvMAGIC(sv); - SvMAGICAL_on(sv); + SvMAGIC(sv) = mg; - mg->mg_obj = obj; + mg->mg_obj = sv_ref(obj); mg->mg_type = how; - if (name) { + mg->mg_len = namlen; + if (name && namlen >= 0) mg->mg_ptr = nsavestr(name, namlen); - mg->mg_len = namlen; - } switch (how) { case 0: mg->mg_virtual = &vtbl_sv; @@ -1020,12 +1424,6 @@ STRLEN namlen; case 'B': mg->mg_virtual = &vtbl_bm; break; - case 'D': - mg->mg_virtual = &vtbl_dbm; - break; - case 'd': - mg->mg_virtual = &vtbl_dbmelem; - break; case 'E': mg->mg_virtual = &vtbl_env; break; @@ -1035,18 +1433,33 @@ STRLEN namlen; case 'g': mg->mg_virtual = &vtbl_mglob; break; + case 'I': + mg->mg_virtual = &vtbl_isa; + break; + case 'i': + mg->mg_virtual = &vtbl_isaelem; + break; case 'L': mg->mg_virtual = 0; break; case 'l': mg->mg_virtual = &vtbl_dbline; break; + case 'P': + mg->mg_virtual = &vtbl_pack; + break; + case 'p': + mg->mg_virtual = &vtbl_packelem; + break; case 'S': mg->mg_virtual = &vtbl_sig; break; case 's': mg->mg_virtual = &vtbl_sigelem; break; + case 't': + mg->mg_virtual = &vtbl_taint; + break; case 'U': mg->mg_virtual = &vtbl_uvar; break; @@ -1063,8 +1476,42 @@ STRLEN namlen; mg->mg_virtual = &vtbl_arylen; break; default: - fatal("Don't know how to handle magic of type '%c'", how); + croak("Don't know how to handle magic of type '%c'", how); + } +} + +int +sv_unmagic(sv, type) +SV* sv; +char type; +{ + MAGIC* mg; + MAGIC** mgp; + if (!SvMAGICAL(sv)) + return 0; + mgp = &SvMAGIC(sv); + for (mg = *mgp; mg; mg = *mgp) { + 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 (mg->mg_ptr && mg->mg_type != 'g') + Safefree(mg->mg_ptr); + sv_free(mg->mg_obj); + Safefree(mg); + } + else + mgp = &mg->mg_moremagic; } + if (!SvMAGIC(sv)) { + SvMAGICAL_off(sv); + SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + SvFLAGS(sv) |= SvPRIVATE(sv) & (SVf_IOK|SVf_NOK|SVf_POK); + SvPRIVATE(sv) &= ~(SVf_IOK|SVf_NOK|SVf_POK); + } + + return 0; } void @@ -1082,7 +1529,7 @@ STRLEN littlelen; register I32 i; if (SvREADONLY(bigstr)) - fatal(no_modify); + croak(no_modify); SvPOK_only(bigstr); i = littlelen - len; @@ -1090,7 +1537,7 @@ STRLEN littlelen; if (!SvUPGRADE(bigstr, SVt_PV)) return; SvGROW(bigstr, SvCUR(bigstr) + i + 1); - big = SvPV(bigstr); + big = SvPVX(bigstr); mid = big + offset + len; midend = bigend = big + SvCUR(bigstr); bigend += i; @@ -1103,18 +1550,18 @@ STRLEN littlelen; return; } else if (i == 0) { - Move(little,SvPV(bigstr)+offset,len,char); + Move(little,SvPVX(bigstr)+offset,len,char); SvSETMAGIC(bigstr); return; } - big = SvPV(bigstr); + big = SvPVX(bigstr); mid = big + offset; midend = mid + len; bigend = big + SvCUR(bigstr); if (midend > bigend) - fatal("panic: sv_insert"); + croak("panic: sv_insert"); if (mid - big > bigend - midend) { /* faster to shorten from end */ if (littlelen) { @@ -1160,7 +1607,7 @@ register SV *nsv; { U32 refcnt = SvREFCNT(sv); if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (SvREFCNT(nsv) != 1) warn("Reference miscount in sv_replace()"); if (SvMAGICAL(sv)) { @@ -1174,7 +1621,7 @@ register SV *nsv; sv_clear(sv); StructCopy(nsv,sv,SV); SvREFCNT(sv) = refcnt; - Safefree(nsv); + del_SV(nsv); } void @@ -1184,6 +1631,47 @@ register SV *sv; assert(sv); assert(SvREFCNT(sv) == 0); + if (SvSTORAGE(sv) == 'O') { + dSP; + BINOP myop; /* fake syntax tree node */ + GV* destructor; + + SvSTORAGE(sv) = 0; /* Curse the object. */ + + ENTER; + SAVETMPS; + SAVESPTR(curcop); + SAVESPTR(op); + curcop = &compiling; + curstash = SvSTASH(sv); + destructor = gv_fetchpv("DESTROY", FALSE); + + if (destructor && GvCV(destructor)) { + SV* ref = sv_mortalcopy(&sv_undef); + sv_upgrade(ref, SVt_REF); + SvANY(ref) = (void*)sv_ref(sv); + + op = (OP*)&myop; + Zero(op, 1, OP); + myop.op_last = (OP*)&myop; + myop.op_flags = OPf_STACKED; + myop.op_next = Nullop; + + EXTEND(SP, 2); + PUSHs((SV*)destructor); + pp_pushmark(); + PUSHs(ref); + PUTBACK; + op = pp_entersubr(); + if (op) + run(); + stack_sp--; + SvREFCNT(sv) = 0; + SvTYPE(ref) = SVt_NULL; + free_tmps(); + } + LEAVE; + } switch (SvTYPE(sv)) { case SVt_PVFM: goto freemagic; @@ -1193,27 +1681,27 @@ register SV *sv; gp_free(sv); goto freemagic; case SVt_PVCV: - op_free(CvSTART(sv)); + cv_clear((CV*)sv); goto freemagic; case SVt_PVHV: - hv_clear(sv, FALSE); + hv_clear((HV*)sv); goto freemagic; case SVt_PVAV: - av_clear(sv); + av_clear((AV*)sv); goto freemagic; case SVt_PVLV: goto freemagic; case SVt_PVMG: freemagic: if (SvMAGICAL(sv)) - mg_freeall(sv); + mg_free(sv); case SVt_PVNV: case SVt_PVIV: SvOOK_off(sv); /* FALL THROUGH */ case SVt_PV: - if (SvPV(sv)) - Safefree(SvPV(sv)); + if (SvPVX(sv)) + Safefree(SvPVX(sv)); break; case SVt_NV: break; @@ -1278,7 +1766,8 @@ SV * sv_ref(sv) SV* sv; { - SvREFCNT(sv)++; + if (sv) + SvREFCNT(sv)++; return sv; } @@ -1296,47 +1785,14 @@ SV *sv; warn("Attempt to free unreferenced scalar"); return; } - if (--SvREFCNT(sv) > 0) +#ifdef DEBUGGING + if (SvTEMP(sv)) { + warn("Attempt to free temp prematurely"); return; - if (SvSTORAGE(sv) == 'O') { - dSP; - BINOP myop; /* fake syntax tree node */ - GV* destructor; - - SvSTORAGE(sv) = 0; /* Curse the object. */ - - ENTER; - SAVESPTR(curcop); - SAVESPTR(op); - curcop = &compiling; - curstash = SvSTASH(sv); - destructor = gv_fetchpv("DESTROY", FALSE); - - if (GvCV(destructor)) { - SV* ref = sv_mortalcopy(&sv_undef); - SvREFCNT(ref) = 1; - sv_upgrade(ref, SVt_REF); - SvANY(ref) = (void*)sv_ref(sv); - - op = (OP*)&myop; - Zero(op, 1, OP); - myop.op_last = (OP*)&myop; - myop.op_flags = OPf_STACKED; - myop.op_next = Nullop; - - EXTEND(SP, 2); - PUSHs((SV*)destructor); - pp_pushmark(); - PUSHs(ref); - PUTBACK; - op = pp_entersubr(); - run(); - stack_sp--; - LEAVE; /* Will eventually free sv as ordinary item. */ - return; - } - LEAVE; } +#endif + if (--SvREFCNT(sv) > 0) + return; sv_clear(sv); DEB(SvTYPE(sv) = 0xff;) del_SV(sv); @@ -1346,25 +1802,14 @@ STRLEN sv_len(sv) register SV *sv; { - I32 paren; - I32 i; char *s; + STRLEN len; if (!sv) return 0; - if (SvMAGICAL(sv)) - return mg_len(sv); - - if (!(SvPOK(sv))) { - (void)sv_2pv(sv); - if (!SvOK(sv)) - return 0; - } - if (SvPV(sv)) - return SvCUR(sv); - else - return 0; + s = SvPV(sv, len); + return len; } I32 @@ -1373,39 +1818,21 @@ register SV *str1; register SV *str2; { char *pv1; - U32 cur1; + STRLEN cur1; char *pv2; - U32 cur2; + STRLEN cur2; if (!str1) { pv1 = ""; cur1 = 0; } - else { - if (SvMAGICAL(str1)) - mg_get(str1); - if (!SvPOK(str1)) { - (void)sv_2pv(str1); - if (!SvPOK(str1)) - str1 = &sv_no; - } - pv1 = SvPV(str1); - cur1 = SvCUR(str1); - } + else + pv1 = SvPV(str1, cur1); if (!str2) return !cur1; - else { - if (SvMAGICAL(str2)) - mg_get(str2); - if (!SvPOK(str2)) { - (void)sv_2pv(str2); - if (!SvPOK(str2)) - return !cur1; - } - pv2 = SvPV(str2); - cur2 = SvCUR(str2); - } + else + pv2 = SvPV(str2, cur2); if (cur1 != cur2) return 0; @@ -1420,41 +1847,23 @@ register SV *str2; { I32 retval; char *pv1; - U32 cur1; + STRLEN cur1; char *pv2; - U32 cur2; + STRLEN cur2; if (!str1) { pv1 = ""; cur1 = 0; } - else { - if (SvMAGICAL(str1)) - mg_get(str1); - if (!SvPOK(str1)) { - (void)sv_2pv(str1); - if (!SvPOK(str1)) - str1 = &sv_no; - } - pv1 = SvPV(str1); - cur1 = SvCUR(str1); - } + else + pv1 = SvPV(str1, cur1); if (!str2) { pv2 = ""; cur2 = 0; } - else { - if (SvMAGICAL(str2)) - mg_get(str2); - if (!SvPOK(str2)) { - (void)sv_2pv(str2); - if (!SvPOK(str2)) - str2 = &sv_no; - } - pv2 = SvPV(str2); - cur2 = SvCUR(str2); - } + else + pv2 = SvPV(str2, cur2); if (!cur1) return cur2 ? -1 : 0; @@ -1492,7 +1901,7 @@ I32 append; I32 shortbuffered; if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (!SvUPGRADE(sv, SVt_PV)) return; if (rspara) { /* have to do this both before and after */ @@ -1519,7 +1928,7 @@ I32 append; } else shortbuffered = 0; - bp = SvPV(sv) + append; /* move these two too to registers */ + bp = SvPVX(sv) + append; /* move these two too to registers */ ptr = fp->_ptr; for (;;) { screamer: @@ -1533,10 +1942,10 @@ I32 append; if (shortbuffered) { /* oh well, must extend */ cnt = shortbuffered; shortbuffered = 0; - bpx = bp - SvPV(sv); /* prepare for possible relocation */ + bpx = bp - SvPVX(sv); /* prepare for possible relocation */ SvCUR_set(sv, bpx); SvGROW(sv, SvLEN(sv) + append + cnt + 2); - bp = SvPV(sv) + bpx; /* reconstitute our pointer */ + bp = SvPVX(sv) + bpx; /* reconstitute our pointer */ continue; } @@ -1546,10 +1955,10 @@ I32 append; cnt = fp->_cnt; ptr = fp->_ptr; /* reregisterize cnt and ptr */ - bpx = bp - SvPV(sv); /* prepare for possible relocation */ + bpx = bp - SvPVX(sv); /* prepare for possible relocation */ SvCUR_set(sv, bpx); SvGROW(sv, bpx + cnt + 2); - bp = SvPV(sv) + bpx; /* reconstitute our pointer */ + bp = SvPVX(sv) + bpx; /* reconstitute our pointer */ if (i == newline) { /* all done for now? */ *bp++ = i; @@ -1561,7 +1970,7 @@ I32 append; } thats_all_folks: - if (rslen > 1 && (bp - SvPV(sv) < rslen || bcmp(bp - rslen, rs, rslen))) + if (rslen > 1 && (bp - SvPVX(sv) < rslen || bcmp(bp - rslen, rs, rslen))) goto screamer; /* go back to the fray */ thats_really_all_folks: if (shortbuffered) @@ -1569,7 +1978,7 @@ thats_really_all_folks: fp->_cnt = cnt; /* put these back or we're in trouble */ fp->_ptr = ptr; *bp = '\0'; - SvCUR_set(sv, bp - SvPV(sv)); /* set length */ + SvCUR_set(sv, bp - SvPVX(sv)); /* set length */ #else /* !STDSTDIO */ /* The big, slow, and stupid way */ @@ -1593,7 +2002,7 @@ screamer: && (SvCUR(sv) < rslen || - bcmp(SvPV(sv) + SvCUR(sv) - rslen, rs, rslen) + bcmp(SvPVX(sv) + SvCUR(sv) - rslen, rs, rslen) ) ) ) @@ -1615,7 +2024,7 @@ screamer: } } } - return SvCUR(sv) - append ? SvPV(sv) : Nullch; + return SvCUR(sv) - append ? SvPVX(sv) : Nullch; } void @@ -1623,39 +2032,44 @@ sv_inc(sv) register SV *sv; { register char *d; + int flags; if (!sv) return; if (SvREADONLY(sv)) - fatal(no_modify); - if (SvMAGICAL(sv)) + croak(no_modify); + if (SvMAGICAL(sv)) { mg_get(sv); - if (SvIOK(sv)) { - ++SvIV(sv); + flags = SvPRIVATE(sv); + } + else + flags = SvFLAGS(sv); + if (flags & SVf_IOK) { + ++SvIVX(sv); SvIOK_only(sv); return; } - if (SvNOK(sv)) { - SvNV(sv) += 1.0; + if (flags & SVf_NOK) { + SvNVX(sv) += 1.0; SvNOK_only(sv); return; } - if (!SvPOK(sv) || !*SvPV(sv)) { + if (!(flags & SVf_POK) || !*SvPVX(sv)) { if (!SvUPGRADE(sv, SVt_NV)) return; - SvNV(sv) = 1.0; + SvNVX(sv) = 1.0; SvNOK_only(sv); return; } - d = SvPV(sv); + d = SvPVX(sv); while (isALPHA(*d)) d++; while (isDIGIT(*d)) d++; if (*d) { - sv_setnv(sv,atof(SvPV(sv)) + 1.0); /* punt */ + sv_setnv(sv,atof(SvPVX(sv)) + 1.0); /* punt */ return; } d--; - while (d >= SvPV(sv)) { + while (d >= SvPVX(sv)) { if (isDIGIT(*d)) { if (++*d <= '9') return; @@ -1671,7 +2085,7 @@ register SV *sv; /* oh,oh, the number grew */ SvGROW(sv, SvCUR(sv) + 2); SvCUR(sv)++; - for (d = SvPV(sv) + SvCUR(sv); d > SvPV(sv); d--) + for (d = SvPVX(sv) + SvCUR(sv); d > SvPVX(sv); d--) *d = d[-1]; if (isDIGIT(d[1])) *d = '1'; @@ -1683,30 +2097,36 @@ void sv_dec(sv) register SV *sv; { + int flags; + if (!sv) return; if (SvREADONLY(sv)) - fatal(no_modify); - if (SvMAGICAL(sv)) + croak(no_modify); + if (SvMAGICAL(sv)) { mg_get(sv); - if (SvIOK(sv)) { - --SvIV(sv); + flags = SvPRIVATE(sv); + } + else + flags = SvFLAGS(sv); + if (flags & SVf_IOK) { + --SvIVX(sv); SvIOK_only(sv); return; } - if (SvNOK(sv)) { - SvNV(sv) -= 1.0; + if (flags & SVf_NOK) { + SvNVX(sv) -= 1.0; SvNOK_only(sv); return; } - if (!SvPOK(sv)) { + if (!(flags & SVf_POK)) { if (!SvUPGRADE(sv, SVt_NV)) return; - SvNV(sv) = -1.0; + SvNVX(sv) = -1.0; SvNOK_only(sv); return; } - sv_setnv(sv,atof(SvPV(sv)) - 1.0); + sv_setnv(sv,atof(SvPVX(sv)) - 1.0); } /* Make a string that will exist for the duration of the expression @@ -1718,8 +2138,11 @@ SV * sv_mortalcopy(oldstr) SV *oldstr; { - register SV *sv = NEWSV(78,0); + register SV *sv; + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; sv_setsv(sv,oldstr); if (++tmps_ix > tmps_max) { tmps_max = tmps_ix; @@ -1745,7 +2168,7 @@ register SV *sv; if (!sv) return sv; if (SvREADONLY(sv)) - fatal(no_modify); + croak(no_modify); if (++tmps_ix > tmps_max) { tmps_max = tmps_ix; if (!(tmps_max & 127)) { @@ -1766,8 +2189,11 @@ newSVpv(s,len) char *s; STRLEN len; { - register SV *sv = NEWSV(79,0); + register SV *sv; + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; if (!len) len = strlen(s); sv_setpvn(sv,s,len); @@ -1778,8 +2204,11 @@ SV * newSVnv(n) double n; { - register SV *sv = NEWSV(80,0); + register SV *sv; + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; sv_setnv(sv,n); return sv; } @@ -1788,8 +2217,11 @@ SV * newSViv(i) I32 i; { - register SV *sv = NEWSV(80,0); + register SV *sv; + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; sv_setiv(sv,i); return sv; } @@ -1800,7 +2232,7 @@ SV * newSVsv(old) register SV *old; { - register SV *new; + register SV *sv; if (!old) return Nullsv; @@ -1808,15 +2240,17 @@ register SV *old; warn("semi-panic: attempt to dup freed string"); return Nullsv; } - new = NEWSV(80,0); + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; if (SvTEMP(old)) { SvTEMP_off(old); - sv_setsv(new,old); + sv_setsv(sv,old); SvTEMP_on(old); } else - sv_setsv(new,old); - return new; + sv_setsv(sv,old); + return sv; } void @@ -1830,6 +2264,7 @@ HV *stash; register I32 i; register PMOP *pm; register I32 max; + char todo[256]; if (!*s) { /* reset ?? searches */ for (pm = HvPMROOT(stash); pm; pm = pm->op_pmnext) { @@ -1842,6 +2277,8 @@ HV *stash; if (!HvARRAY(stash)) return; + + Zero(todo, 256, char); while (*s) { i = *s; if (s[1] == '-') { @@ -1849,23 +2286,28 @@ HV *stash; } max = *s++; for ( ; i <= max; i++) { + todo[i] = 1; + } + for (i = 0; i <= HvMAX(stash); i++) { for (entry = HvARRAY(stash)[i]; entry; entry = entry->hent_next) { + if (!todo[(U8)*entry->hent_key]) + continue; gv = (GV*)entry->hent_val; sv = GvSV(gv); SvOK_off(sv); if (SvTYPE(sv) >= SVt_PV) { SvCUR_set(sv, 0); - SvTDOWN(sv); - if (SvPV(sv) != Nullch) - *SvPV(sv) = '\0'; + SvTAINT(sv); + if (SvPVX(sv) != Nullch) + *SvPVX(sv) = '\0'; } if (GvAV(gv)) { av_clear(GvAV(gv)); } if (GvHV(gv)) { - hv_clear(GvHV(gv), FALSE); + hv_clear(GvHV(gv)); if (gv == envgv) environ[0] = Nullch; } @@ -1874,76 +2316,6 @@ HV *stash; } } -#ifdef OLD -AV * -sv_2av(sv, st, gvp, lref) -SV *sv; -HV **st; -GV **gvp; -I32 lref; -{ - GV *gv; - - switch (SvTYPE(sv)) { - case SVt_PVAV: - *st = sv->sv_u.sv_stash; - *gvp = Nullgv; - return sv->sv_u.sv_av; - case SVt_PVHV: - case SVt_PVCV: - *gvp = Nullgv; - return Nullav; - default: - if (isGV(sv)) - gv = (GV*)sv; - else - gv = gv_fetchpv(SvPVn(sv), lref); - *gvp = gv; - if (!gv) - return Nullav; - *st = GvESTASH(gv); - if (lref) - return GvAVn(gv); - else - return GvAV(gv); - } -} - -HV * -sv_2hv(sv, st, gvp, lref) -SV *sv; -HV **st; -GV **gvp; -I32 lref; -{ - GV *gv; - - switch (SvTYPE(sv)) { - case SVt_PVHV: - *st = sv->sv_u.sv_stash; - *gvp = Nullgv; - return sv->sv_u.sv_hv; - case SVt_PVAV: - case SVt_PVCV: - *gvp = Nullgv; - return Nullhv; - default: - if (isGV(sv)) - gv = (GV*)sv; - else - gv = gv_fetchpv(SvPVn(sv), lref); - *gvp = gv; - if (!gv) - return Nullhv; - *st = GvESTASH(gv); - if (lref) - return GvHVn(gv); - else - return GvHV(gv); - } -} -#endif; - CV * sv_2cv(sv, st, gvp, lref) SV *sv; @@ -1960,7 +2332,7 @@ I32 lref; case SVt_REF: cv = (CV*)SvANY(sv); if (SvTYPE(cv) != SVt_PVCV) - fatal("Not a subroutine reference"); + croak("Not a subroutine reference"); *gvp = Nullgv; *st = CvSTASH(cv); return cv; @@ -1976,7 +2348,7 @@ I32 lref; if (isGV(sv)) gv = (GV*)sv; else - gv = gv_fetchpv(SvPVn(sv), lref); + gv = gv_fetchpv(SvPV(sv, na), lref); *gvp = gv; if (!gv) return Nullcv; @@ -2004,41 +2376,79 @@ register SV *sv; } else { if (SvIOK(sv)) - return SvIV(sv) != 0; + return SvIVX(sv) != 0; else { if (SvNOK(sv)) - return SvNV(sv) != 0.0; + return SvNVX(sv) != 0.0; else - return 0; + return sv_2bool(sv); } } } #endif /* SvTRUE */ -#ifndef SvNVn -double SvNVn(Sv) +#ifndef SvNV +double SvNV(Sv) register SV *Sv; { - SvTUP(Sv); - if (SvMAGICAL(sv)) - mg_get(sv); if (SvNOK(Sv)) - return SvNV(Sv); + return SvNVX(Sv); if (SvIOK(Sv)) - return (double)SvIV(Sv); + return (double)SvIVX(Sv); return sv_2nv(Sv); } -#endif /* SvNVn */ +#endif /* SvNV */ -#ifndef SvPVn +#ifdef CRIPPLED_CC char * -SvPVn(sv) +sv_pvn(sv, lp) SV *sv; +STRLEN *lp; { - SvTUP(sv); - if (SvMAGICAL(sv)) - mg_get(sv); - return SvPOK(sv) ? SvPV(sv) : sv_2pv(sv); + if (SvPOK(sv)) + return SvPVX(sv) + return sv_2pv(sv, lp); } #endif +int +sv_isa(sv, name) +SV *sv; +char *name; +{ + if (SvTYPE(sv) != SVt_REF) + return 0; + sv = (SV*)SvANY(sv); + if (SvSTORAGE(sv) != 'O') + return 0; + + return strEQ(HvNAME(SvSTASH(sv)), name); +} + +SV* +sv_setptrobj(rv, ptr, name) +SV *rv; +void *ptr; +char *name; +{ + HV *stash; + SV *sv; + + if (!ptr) + return rv; + + new_SV(); + Zero(sv, 1, SV); + SvREFCNT(sv)++; + sv_setnv(sv, (double)(unsigned long)ptr); + sv_upgrade(rv, SVt_REF); + SvANY(rv) = (void*)sv_ref(sv); + + stash = fetch_stash(newSVpv(name,0), TRUE); + SvSTORAGE(sv) = 'O'; + SvUPGRADE(sv, SVt_PVMG); + SvSTASH(sv) = stash; + + return rv; +} +