tweak win32 config templates for cpp
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index aeb2055..1e5af08 100644 (file)
--- a/sv.c
+++ b/sv.c
 #  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));
@@ -59,38 +65,48 @@ static void sv_mortalgrow _((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
 
 #define new_SV(p)                      \
     do {                               \
-       MUTEX_LOCK(&sv_mutex);          \
+       LOCK_SV_MUTEX;                  \
        (p) = (SV*)safemalloc(sizeof(SV)); \
        reg_add(p);                     \
-       MUTEX_UNLOCK(&sv_mutex);        \
+       UNLOCK_SV_MUTEX;                \
     } while (0)
 
 #define del_SV(p)                      \
     do {                               \
-       MUTEX_LOCK(&sv_mutex);          \
+       LOCK_SV_MUTEX;                  \
        reg_remove(p);                  \
-        free((char*)(p));              \
-       MUTEX_UNLOCK(&sv_mutex);        \
+        Safefree((char*)(p));          \
+       UNLOCK_SV_MUTEX;                \
     } 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"); \
@@ -105,14 +121,13 @@ static void
 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;
@@ -144,9 +159,9 @@ SVFUNC f;
 {
     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);
     }
 }
@@ -158,7 +173,7 @@ U32 size;
 U32 flags;
 {
     if (!(flags & SVf_FAKE))
-       free(ptr);
+       Safefree(ptr);
 }
 
 #else /* ! PURIFY */
@@ -183,27 +198,27 @@ U32 flags;
        ++sv_count;                     \
     } while (0)
 
-#define new_SV(p)      do {            \
-       MUTEX_LOCK(&sv_mutex);          \
-       if (sv_root)                    \
-           uproot_SV(p);               \
-       else                            \
-           (p) = more_sv();            \
-       MUTEX_UNLOCK(&sv_mutex);        \
+#define new_SV(p)      do {    \
+       LOCK_SV_MUTEX;          \
+       if (sv_root)            \
+           uproot_SV(p);       \
+       else                    \
+           (p) = more_sv();    \
+       UNLOCK_SV_MUTEX;        \
     } while (0)
 
 #ifdef DEBUGGING
 
-#define del_SV(p)      do {            \
-       MUTEX_LOCK(&sv_mutex);          \
-       if (debug & 32768)              \
-           del_sv(p);                  \
-       else                            \
-           plant_SV(p);                \
-       MUTEX_UNLOCK(&sv_mutex);        \
+#define del_SV(p)      do {    \
+       LOCK_SV_MUTEX;          \
+       if (debug & 32768)      \
+           del_sv(p);          \
+       else                    \
+           plant_SV(p);        \
+       UNLOCK_SV_MUTEX;        \
     } while (0)
 
-static void
+STATIC void
 del_sv(SV *p)
 {
     if (debug & 32768) {
@@ -259,7 +274,7 @@ sv_add_arena(char *ptr, U32 size, U32 flags)
 }
 
 /* sv_mutex must be held while calling more_sv() */
-static SV*
+STATIC SV*
 more_sv(void)
 {
     register SV* sv;
@@ -277,7 +292,7 @@ more_sv(void)
     return sv;
 }
 
-static void
+STATIC void
 visit(SVFUNC f)
 {
     SV* sva;
@@ -288,14 +303,14 @@ visit(SVFUNC f)
        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) {
@@ -308,10 +323,10 @@ do_report_used(SV *sv)
 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;
@@ -327,28 +342,36 @@ do_clean_objs(SV *sv)
 }
 
 #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));)
@@ -356,13 +379,11 @@ do_clean_all(SV *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;
 }
 
@@ -384,11 +405,15 @@ sv_free_arenas(void)
            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;
@@ -403,7 +428,7 @@ new_xiv(void)
     return more_xiv();
 }
 
-static void
+STATIC void
 del_xiv(XPVIV *p)
 {
     IV** xiv = (IV**)((char*)(p) + sizeof(XPV));
@@ -411,12 +436,13 @@ del_xiv(XPVIV *p)
     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 */
 
@@ -432,7 +458,7 @@ more_xiv(void)
     return new_xiv();
 }
 
-static XPVNV*
+STATIC XPVNV*
 new_xnv(void)
 {
     double* xnv;
@@ -444,7 +470,7 @@ new_xnv(void)
     return more_xnv();
 }
 
-static void
+STATIC void
 del_xnv(XPVNV *p)
 {
     double* xnv = (double*)((char*)(p) + sizeof(XPVIV));
@@ -452,12 +478,12 @@ del_xnv(XPVNV *p)
     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;
@@ -469,7 +495,7 @@ more_xnv(void)
     return new_xnv();
 }
 
-static XRV*
+STATIC XRV*
 new_xrv(void)
 {
     XRV* xrv;
@@ -481,19 +507,19 @@ new_xrv(void)
     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) {
@@ -504,7 +530,7 @@ more_xrv(void)
     return new_xrv();
 }
 
-static XPV*
+STATIC XPV*
 new_xpv(void)
 {
     XPV* xpv;
@@ -516,19 +542,19 @@ new_xpv(void)
     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) {
@@ -541,7 +567,7 @@ more_xpv(void)
 
 #ifdef PURIFY
 #define new_XIV() (void*)safemalloc(sizeof(XPVIV))
-#define del_XIV(p) free((char*)p)
+#define del_XIV(p) Safefree((char*)p)
 #else
 #define new_XIV() (void*)new_xiv()
 #define del_XIV(p) del_xiv((XPVIV*) p)
@@ -549,7 +575,7 @@ more_xpv(void)
 
 #ifdef PURIFY
 #define new_XNV() (void*)safemalloc(sizeof(XPVNV))
-#define del_XNV(p) free((char*)p)
+#define del_XNV(p) Safefree((char*)p)
 #else
 #define new_XNV() (void*)new_xnv()
 #define del_XNV(p) del_xnv((XPVNV*) p)
@@ -557,7 +583,7 @@ more_xpv(void)
 
 #ifdef PURIFY
 #define new_XRV() (void*)safemalloc(sizeof(XRV))
-#define del_XRV(p) free((char*)p)
+#define del_XRV(p) Safefree((char*)p)
 #else
 #define new_XRV() (void*)new_xrv()
 #define del_XRV(p) del_xrv((XRV*) p)
@@ -565,44 +591,58 @@ more_xpv(void)
 
 #ifdef PURIFY
 #define new_XPV() (void*)safemalloc(sizeof(XPV))
-#define del_XPV(p) free((char*)p)
+#define del_XPV(p) Safefree((char*)p)
 #else
 #define new_XPV() (void*)new_xpv()
 #define del_XPV(p) del_xpv((XPV *)p)
 #endif
 
-#define new_XPVIV() (void*)safemalloc(sizeof(XPVIV))
-#define del_XPVIV(p) free((char*)p)
-
-#define new_XPVNV() (void*)safemalloc(sizeof(XPVNV))
-#define del_XPVNV(p) free((char*)p)
-
-#define new_XPVMG() (void*)safemalloc(sizeof(XPVMG))
-#define del_XPVMG(p) free((char*)p)
-
-#define new_XPVLV() (void*)safemalloc(sizeof(XPVLV))
-#define del_XPVLV(p) free((char*)p)
-
-#define new_XPVAV() (void*)safemalloc(sizeof(XPVAV))
-#define del_XPVAV(p) free((char*)p)
-
-#define new_XPVHV() (void*)safemalloc(sizeof(XPVHV))
-#define del_XPVHV(p) free((char*)p)
-
-#define new_XPVCV() (void*)safemalloc(sizeof(XPVCV))
-#define del_XPVCV(p) free((char*)p)
-
-#define new_XPVGV() (void*)safemalloc(sizeof(XPVGV))
-#define del_XPVGV(p) free((char*)p)
-
-#define new_XPVBM() (void*)safemalloc(sizeof(XPVBM))
-#define del_XPVBM(p) free((char*)p)
-
-#define new_XPVFM() (void*)safemalloc(sizeof(XPVFM))
-#define del_XPVFM(p) free((char*)p)
-
-#define new_XPVIO() (void*)safemalloc(sizeof(XPVIO))
-#define del_XPVIO(p) free((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)
@@ -785,7 +825,7 @@ sv_upgrade(register SV *sv, U32 mt)
            Safefree(pv);
        SvPVX(sv)       = 0;
        AvMAX(sv)       = -1;
-       AvFILL(sv)      = -1;
+       AvFILLp(sv)     = -1;
        SvIVX(sv)       = 0;
        SvNVX(sv)       = 0.0;
        SvMAGIC(sv)     = magic;
@@ -878,10 +918,10 @@ 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;
@@ -1023,8 +1063,10 @@ sv_peek(SV *sv)
            sv_catpv(t, ")");
     }
     return SvPV(t, na);
+#else  /* DEBUGGING */
+    return "";
+#endif /* DEBUGGING */
 }
-#endif
 
 int
 sv_backoff(register SV *sv)
@@ -1067,12 +1109,24 @@ sv_grow(SV* sv, unsigned long newlen)
        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);
@@ -1084,8 +1138,7 @@ sv_grow(SV* sv, unsigned long newlen)
 void
 sv_setiv(register SV *sv, IV i)
 {
-    dTHR;      /* just for taint */
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     switch (SvTYPE(sv)) {
     case SVt_NULL:
        sv_upgrade(sv, SVt_IV);
@@ -1121,6 +1174,13 @@ sv_setiv(register SV *sv, IV i)
 }
 
 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)
@@ -1130,16 +1190,21 @@ sv_setuv(register SV *sv, UV u)
 }
 
 void
+sv_setuv_mg(register SV *sv, UV u)
+{
+    sv_setuv(sv,u);
+    SvSETMAGIC(sv);
+}
+
+void
 sv_setnv(register SV *sv, double num)
 {
-    dTHR;      /* just for taint */
-    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:
@@ -1174,7 +1239,14 @@ sv_setnv(register SV *sv, double num)
     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;
@@ -1247,9 +1319,11 @@ sv_2iv(register SV *sv)
        if (SvPOKp(sv) && SvLEN(sv))
            return asIV(sv);
        if (!SvROK(sv)) {
-           dTHR;               /* just for localizing */
-           if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
-               warn(warn_uninit);
+           if (dowarn && !(SvFLAGS(sv) & SVs_PADTMP)) {
+               dTHR;
+               if (!localizing)
+                   warn(warn_uninit);
+           }
            return 0;
        }
     }
@@ -1323,9 +1397,11 @@ sv_2uv(register SV *sv)
        if (SvPOKp(sv) && SvLEN(sv))
            return asUV(sv);
        if (!SvROK(sv)) {
-           dTHR;               /* just for localizing */
-           if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
-               warn(warn_uninit);
+           if (dowarn && !(SvFLAGS(sv) & SVs_PADTMP)) {
+               dTHR;
+               if (!localizing)
+                   warn(warn_uninit);
+           }
            return 0;
        }
     }
@@ -1369,9 +1445,11 @@ sv_2uv(register SV *sv)
        SvUVX(sv) = asUV(sv);
     }
     else  {
-       dTHR;           /* just for localizing */
-       if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
-           warn(warn_uninit);
+       if (dowarn && !(SvFLAGS(sv) & SVs_PADTMP)) {
+           dTHR;
+           if (!localizing)
+               warn(warn_uninit);
+       }
        return 0;
     }
     DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2uv(%lu)\n",
@@ -1397,9 +1475,11 @@ sv_2nv(register SV *sv)
        if (SvIOKp(sv))
            return (double)SvIVX(sv);
         if (!SvROK(sv)) {
-           dTHR;               /* just for localizing */
-           if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
-               warn(warn_uninit);
+           if (dowarn && !(SvFLAGS(sv) & SVs_PADTMP)) {
+               dTHR;
+               if (!localizing)
+                   warn(warn_uninit);
+           }
             return 0;
         }
     }
@@ -1461,7 +1541,7 @@ sv_2nv(register SV *sv)
     return SvNVX(sv);
 }
 
-static IV
+STATIC IV
 asIV(SV *sv)
 {
     I32 numtype = looks_like_number(sv);
@@ -1479,7 +1559,7 @@ asIV(SV *sv)
        return (IV) U_V(d);
 }
 
-static UV
+STATIC UV
 asUV(SV *sv)
 {
     I32 numtype = looks_like_number(sv);
@@ -1603,9 +1683,11 @@ sv_2pv(register SV *sv, STRLEN *lp)
            goto tokensave;
        }
         if (!SvROK(sv)) {
-           dTHR;               /* just for localizing */
-           if (dowarn && !localizing && !(SvFLAGS(sv) & SVs_PADTMP))
-               warn(warn_uninit);
+           if (dowarn && !(SvFLAGS(sv) & SVs_PADTMP)) {
+               dTHR;
+               if (!localizing)
+                   warn(warn_uninit);
+           }
             *lp = 0;
             return "";
         }
@@ -1621,7 +1703,21 @@ sv_2pv(register SV *sv, STRLEN *lp)
            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:
@@ -1629,14 +1725,13 @@ sv_2pv(register SV *sv, STRLEN *lp)
                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;
                }
@@ -1669,8 +1764,7 @@ sv_2pv(register SV *sv, STRLEN *lp)
            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);
@@ -1820,7 +1914,7 @@ sv_setsv(SV *dstr, register SV *sstr)
 
     if (sstr == dstr)
        return;
-    sv_check_thinkfirst(dstr);
+    SV_CHECK_THINKFIRST(dstr);
     if (!sstr)
        sstr = &sv_undef;
     stype = SvTYPE(sstr);
@@ -1840,8 +1934,11 @@ sv_setsv(SV *dstr, register SV *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)
@@ -1888,11 +1985,6 @@ sv_setsv(SV *dstr, register SV *sstr)
        if (dtype < SVt_PVNV)
            sv_upgrade(dstr, SVt_PVNV);
        break;
-
-    case SVt_PVLV:
-       sv_upgrade(dstr, SVt_PVLV);
-       break;
-
     case SVt_PVAV:
     case SVt_PVHV:
     case SVt_PVCV:
@@ -1912,13 +2004,13 @@ sv_setsv(SV *dstr, register SV *sstr)
                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));
@@ -1943,8 +2035,10 @@ sv_setsv(SV *dstr, register SV *sstr)
                    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);
@@ -2005,19 +2099,29 @@ sv_setsv(SV *dstr, register SV *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);
@@ -2087,6 +2191,7 @@ sv_setsv(SV *dstr, register SV *sstr)
         */
 
        if (SvTEMP(sstr) &&             /* slated for free anyway? */
+           SvREFCNT(sstr) == 1 &&      /* and no other references to it? */
            !(sflags & SVf_OOK))        /* and not involved in OOK hack? */
        {
            if (SvPVX(dstr)) {          /* we know that dtype >= SVt_PV */
@@ -2140,18 +2245,30 @@ sv_setsv(SV *dstr, register SV *sstr)
        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)
 {
-    dTHR;      /* just for taint */
+    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;
@@ -2160,23 +2277,31 @@ sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
        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)
 {
-    dTHR;      /* just for taint */
     register STRLEN len;
 
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (!ptr) {
        (void)SvOK_off(sv);
        return;
@@ -2186,8 +2311,9 @@ sv_setpv(register SV *sv, register const char *ptr)
        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);
@@ -2196,12 +2322,17 @@ sv_setpv(register SV *sv, register const char *ptr)
 }
 
 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)
 {
-    dTHR;      /* just for taint */
-    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;
@@ -2217,18 +2348,23 @@ sv_usepvn(register SV *sv, register char *ptr, register STRLEN len)
     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
@@ -2240,7 +2376,7 @@ sv_chop(register SV *sv, register char *ptr)      /* like set but assuming ptr is in
 
     if (!ptr || !SvPOKp(sv))
        return;
-    sv_check_thinkfirst(sv);
+    SV_CHECK_THINKFIRST(sv);
     if (SvTYPE(sv) < SVt_PVIV)
        sv_upgrade(sv,SVt_PVIV);
 
@@ -2259,7 +2395,6 @@ sv_chop(register SV *sv, register char *ptr)      /* like set but assuming ptr is in
 void
 sv_catpvn(register SV *sv, register char *ptr, register STRLEN len)
 {
-    dTHR;      /* just for taint */
     STRLEN tlen;
     char *junk;
 
@@ -2275,6 +2410,13 @@ sv_catpvn(register SV *sv, register char *ptr, register STRLEN len)
 }
 
 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;
@@ -2286,9 +2428,15 @@ sv_catsv(SV *dstr, register SV *sstr)
 }
 
 void
+sv_catsv_mg(SV *dstr, register SV *sstr)
+{
+    sv_catsv(dstr,sstr);
+    SvSETMAGIC(dstr);
+}
+
+void
 sv_catpv(register SV *sv, register char *ptr)
 {
-    dTHR;      /* just for taint */
     register STRLEN len;
     STRLEN tlen;
     char *junk;
@@ -2306,14 +2454,15 @@ sv_catpv(register SV *sv, register char *ptr)
     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;
     
@@ -2348,14 +2497,13 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
        }
     }
     else {
-       if (!SvUPGRADE(sv, SVt_PVMG))
-           return;
+        (void)SvUPGRADE(sv, SVt_PVMG);
     }
     Newz(702,mg, 1, MAGIC);
     mg->mg_moremagic = SvMAGIC(sv);
 
     SvMAGIC(sv) = mg;
-    if (!obj || obj == sv || how == '#')
+    if (!obj || obj == sv || how == '#' || how == 'r')
        mg->mg_obj = obj;
     else {
        dTHR;
@@ -2367,10 +2515,8 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
     if (name)
        if (namlen >= 0)
            mg->mg_ptr = savepvn(name, namlen);
-       else if (namlen == HEf_SVKEY) {
-           dTHR;               /* just for SvREFCNT_inc */
+       else if (namlen == HEf_SVKEY)
            mg->mg_ptr = (char*)SvREFCNT_inc((SV*)name);
-       }
     
     switch (how) {
     case 0:
@@ -2435,6 +2581,9 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
     case 'q':
        mg->mg_virtual = &vtbl_packelem;
        break;
+    case 'r':
+       mg->mg_virtual = &vtbl_regexp;
+       break;
     case 'S':
        mg->mg_virtual = &vtbl_sig;
        break;
@@ -2492,8 +2641,8 @@ sv_unmagic(SV *sv, int type)
        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);
@@ -2522,10 +2671,17 @@ sv_insert(SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN littlelen)
     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 */
@@ -2596,7 +2752,7 @@ void
 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)) {
@@ -2621,6 +2777,7 @@ sv_replace(register SV *sv, register SV *nsv)
 void
 sv_clear(register SV *sv)
 {
+    HV* stash;
     assert(sv);
     assert(SvREFCNT(sv) == 0);
 
@@ -2629,37 +2786,38 @@ sv_clear(register SV *sv)
        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 */
@@ -2673,6 +2831,7 @@ sv_clear(register SV *sv)
     }
     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
        mg_free(sv);
+    stash = NULL;
     switch (SvTYPE(sv)) {
     case SVt_PVIO:
        if (IoIFP(sv) != PerlIO_stdin() &&
@@ -2698,6 +2857,11 @@ sv_clear(register SV *sv)
     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:
@@ -2759,7 +2923,13 @@ sv_clear(register SV *sv)
        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;
@@ -2778,13 +2948,15 @@ SV *
 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)) {
@@ -2799,7 +2971,8 @@ sv_free(SV *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)) {
@@ -2822,7 +2995,7 @@ sv_len(register SV *sv)
        return 0;
 
     if (SvGMAGICAL(sv))
-       len = mg_len(sv);
+       len = mg_length(sv);
     else
        junk = SvPV(sv, len);
     return len;
@@ -2982,7 +3155,7 @@ sv_collxfrm(SV *sv, STRLEN *nxp)
 #endif /* USE_LOCALE_COLLATE */
 
 char *
-sv_gets(register SV *sv, register FILE *fp, I32 append)
+sv_gets(register SV *sv, register PerlIO *fp, I32 append)
 {
     dTHR;
     char *rsptr;
@@ -2992,15 +3165,39 @@ sv_gets(register SV *sv, register FILE *fp, I32 append)
     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;
@@ -3216,6 +3413,10 @@ screamer2:
        }
     }
 
+#ifdef WIN32
+    win32_strip_return(sv);
+#endif
+
     return (SvCUR(sv) - append) ? SvPVX(sv) : Nullch;
 }
 
@@ -3351,7 +3552,7 @@ sv_dec(register SV *sv)
  * hopefully we won't free it until it has been assigned to a
  * permanent location. */
 
-static void
+STATIC void
 sv_mortalgrow(void)
 {
     dTHR;
@@ -3425,16 +3626,21 @@ newSVpv(char *s, STRLEN len)
     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;
@@ -3443,11 +3649,7 @@ va_dcl
     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;
@@ -3481,7 +3683,7 @@ newSViv(IV i)
 }
 
 SV *
-newRV(SV *ref)
+newRV(SV *tmpRef)
 {
     dTHR;
     register SV *sv;
@@ -3491,8 +3693,8 @@ newRV(SV *ref)
     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;
 }
@@ -3500,12 +3702,12 @@ newRV(SV *ref)
 
 
 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;
 }
 
@@ -3547,9 +3749,12 @@ sv_reset(register char *s, HV *stash)
     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;
     }
@@ -3579,7 +3784,6 @@ sv_reset(register char *s, HV *stash)
                sv = GvSV(gv);
                (void)SvOK_off(sv);
                if (SvTYPE(sv) >= SVt_PV) {
-                   dTHR;       /* just for taint */
                    SvCUR_set(sv, 0);
                    if (SvPVX(sv) != Nullch)
                        *SvPVX(sv) = '\0';
@@ -3699,8 +3903,6 @@ sv_true(register SV *sv)
     dTHR;
     if (!sv)
        return 0;
-    if (SvGMAGICAL(sv))
-       mg_get(sv);
     if (SvPOK(sv)) {
        register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
@@ -3798,7 +4000,6 @@ sv_pvn_force(SV *sv, STRLEN *lp)
            *SvEND(sv) = '\0';
        }
        if (!SvPOK(sv)) {
-           dTHR;       /* just for taint */
            SvPOK_on(sv);               /* validate pointer */
            SvTAINT(sv);
            DEBUG_c(PerlIO_printf(Perl_debug_log, "0x%lx 2pv(%s)\n",
@@ -3833,7 +4034,7 @@ sv_reftype(SV *sv, int ob)
        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";
        }
     }
@@ -3880,7 +4081,16 @@ newSVrv(SV *rv, char *classname)
     SvANY(sv) = 0;
     SvREFCNT(sv) = 0;
     SvFLAGS(sv) = 0;
-    sv_upgrade(rv, SVt_RV);
+
+    SV_CHECK_THINKFIRST(rv);
+#ifdef OVERLOAD
+    SvAMAGIC_off(rv);
+#endif /* OVERLOAD */
+
+    if (SvTYPE(rv) < SVt_RV)
+      sv_upgrade(rv, SVt_RV);
+
+    (void)SvOK_off(rv);
     SvRV(rv) = SvREFCNT_inc(sv);
     SvROK_on(rv);
 
@@ -3894,8 +4104,10 @@ newSVrv(SV *rv, char *classname)
 SV*
 sv_setref_pv(SV *rv, char *classname, void *pv)
 {
-    if (!pv)
+    if (!pv) {
        sv_setsv(rv, &sv_undef);
+       SvSETMAGIC(rv);
+    }
     else
        sv_setiv(newSVrv(rv,classname), (IV)pv);
     return rv;
@@ -3926,24 +4138,24 @@ SV*
 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))
@@ -3955,13 +4167,17 @@ sv_bless(SV *sv, HV *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);
@@ -4042,59 +4258,62 @@ sv_setpviv(SV *sv, IV iv)
     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
-sv_vsetpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, char *used_locale)
+sv_vsetpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *used_locale)
 {
     sv_setpvn(sv, "", 0);
     sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, used_locale);
 }
 
 void
-sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, char *used_locale)
+sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *used_locale)
 {
     dTHR;
     char *p;
@@ -4394,6 +4613,8 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
            switch (base) {
                unsigned dig;
            case 16:
+               if (!uv)
+                   alt = FALSE;
                p = (c == 'X') ? "0123456789ABCDEF" : "0123456789abcdef";
                do {
                    dig = uv & 15;
@@ -4420,8 +4641,12 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
                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 */
@@ -4583,10 +4808,10 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
     }
 }
 
-#ifdef DEBUGGING
 void
 sv_dump(SV *sv)
 {
+#ifdef DEBUGGING
     SV *d = sv_newmortal();
     char *s;
     U32 flags;
@@ -4657,6 +4882,10 @@ sv_dump(SV *sv)
                sv_catpv(d, " ),");
            }
        }
+    case SVt_PVBM:
+       if (SvTAIL(sv)) sv_catpv(d, "TAIL,");
+       if (SvCOMPILED(sv))     sv_catpv(d, "COMPILED,");
+       break;
     }
 
     if (*(SvEND(d) - 1) == ',')
@@ -4756,7 +4985,7 @@ sv_dump(SV *sv)
     case SVt_PVAV:
        PerlIO_printf(Perl_debug_log, "  ARRAY = 0x%lx\n", (long)AvARRAY(sv));
        PerlIO_printf(Perl_debug_log, "  ALLOC = 0x%lx\n", (long)AvALLOC(sv));
-       PerlIO_printf(Perl_debug_log, "  FILL = %ld\n", (long)AvFILL(sv));
+       PerlIO_printf(Perl_debug_log, "  FILL = %ld\n", (long)AvFILLp(sv));
        PerlIO_printf(Perl_debug_log, "  MAX = %ld\n", (long)AvMAX(sv));
        PerlIO_printf(Perl_debug_log, "  ARYLEN = 0x%lx\n", (long)AvARYLEN(sv));
        flags = AvFLAGS(sv);
@@ -4811,7 +5040,8 @@ sv_dump(SV *sv)
     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));
@@ -4845,14 +5075,5 @@ sv_dump(SV *sv)
        PerlIO_printf(Perl_debug_log, "  FLAGS = 0x%lx\n", (long)IoFLAGS(sv));
        break;
     }
+#endif /* DEBUGGING */
 }
-#else
-void
-sv_dump(SV *sv)
-{
-}
-#endif
-
-
-
-