Quickier thread-specific data on OS/2
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index 138db59..5772954 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1,6 +1,6 @@
 /*    sv.c
  *
- *    Copyright (c) 1991-1997, Larry Wall
+ *    Copyright (c) 1991-1999, Larry Wall
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -57,9 +57,7 @@ static void del_xiv _((XPVIV* p));
 static void del_xnv _((XPVNV* p));
 static void del_xpv _((XPV* p));
 static void del_xrv _((XRV* p));
-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);
@@ -71,25 +69,28 @@ typedef void (*SVFUNC) _((SV*));
 
 #endif /* PERL_OBJECT */
 
-#define SV_CHECK_THINKFIRST(sv) if (SvTHINKFIRST(sv)) sv_check_thinkfirst(sv)
+#define SV_CHECK_THINKFIRST(sv) if (SvTHINKFIRST(sv)) sv_force_normal(sv)
 
 #ifdef PURIFY
 
-#define new_SV(p)                      \
-    do {                               \
-       LOCK_SV_MUTEX;                  \
-       (p) = (SV*)safemalloc(sizeof(SV)); \
-       reg_add(p);                     \
-       UNLOCK_SV_MUTEX;                \
-    } while (0)
-
-#define del_SV(p)                      \
-    do {                               \
-       LOCK_SV_MUTEX;                  \
-       reg_remove(p);                  \
-        Safefree((char*)(p));          \
-       UNLOCK_SV_MUTEX;                \
-    } while (0)
+#define new_SV(p) \
+    STMT_START {                                       \
+       LOCK_SV_MUTEX;                                  \
+       (p) = (SV*)safemalloc(sizeof(SV));              \
+       reg_add(p);                                     \
+       UNLOCK_SV_MUTEX;                                \
+       SvANY(p) = 0;                                   \
+       SvREFCNT(p) = 1;                                \
+       SvFLAGS(p) = 0;                                 \
+    } STMT_END
+
+#define del_SV(p) \
+    STMT_START {                                       \
+       LOCK_SV_MUTEX;                                  \
+       reg_remove(p);                                  \
+        Safefree((char*)(p));                          \
+       UNLOCK_SV_MUTEX;                                \
+    } STMT_END
 
 static SV **registry;
 static I32 registry_size;
@@ -97,18 +98,18 @@ 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, registry_size);     \
-       I32 i = h;                      \
-       while (registry[i] != (a)) {    \
-           if (++i >= registry_size)   \
-               i = 0;                  \
-           if (i == h)                 \
-               die("SV registry bug"); \
-       }                               \
-       registry[i] = (b);              \
-    } while (0)
+    STMT_START {                                       \
+       void* p = sv->sv_any;                           \
+       I32 h = REGHASH(sv, registry_size);             \
+       I32 i = h;                                      \
+       while (registry[i] != (a)) {                    \
+           if (++i >= registry_size)                   \
+               i = 0;                                  \
+           if (i == h)                                 \
+               die("SV registry bug");                 \
+       }                                               \
+       registry[i] = (b);                              \
+    } STMT_END
 
 #define REG_ADD(sv)    REG_REPLACE(sv,Nullsv,sv)
 #define REG_REMOVE(sv) REG_REPLACE(sv,sv,Nullsv)
@@ -178,41 +179,46 @@ U32 flags;
  * "A time to plant, and a time to uproot what was planted..."
  */
 
-#define plant_SV(p)                    \
-    do {                               \
-       SvANY(p) = (void *)PL_sv_root;  \
-       SvFLAGS(p) = SVTYPEMASK;        \
-       PL_sv_root = (p);                       \
-       --PL_sv_count;                  \
-    } while (0)
+#define plant_SV(p) \
+    STMT_START {                                       \
+       SvANY(p) = (void *)PL_sv_root;                  \
+       SvFLAGS(p) = SVTYPEMASK;                        \
+       PL_sv_root = (p);                               \
+       --PL_sv_count;                                  \
+    } STMT_END
 
 /* sv_mutex must be held while calling uproot_SV() */
-#define uproot_SV(p)                   \
-    do {                               \
-       (p) = PL_sv_root;                       \
-       PL_sv_root = (SV*)SvANY(p);     \
-       ++PL_sv_count;                  \
-    } while (0)
-
-#define new_SV(p)      do {    \
-       LOCK_SV_MUTEX;          \
-       if (PL_sv_root)         \
-           uproot_SV(p);       \
-       else                    \
-           (p) = more_sv();    \
-       UNLOCK_SV_MUTEX;        \
-    } while (0)
+#define uproot_SV(p) \
+    STMT_START {                                       \
+       (p) = PL_sv_root;                               \
+       PL_sv_root = (SV*)SvANY(p);                     \
+       ++PL_sv_count;                                  \
+    } STMT_END
+
+#define new_SV(p) \
+    STMT_START {                                       \
+       LOCK_SV_MUTEX;                                  \
+       if (PL_sv_root)                                 \
+           uproot_SV(p);                               \
+       else                                            \
+           (p) = more_sv();                            \
+       UNLOCK_SV_MUTEX;                                \
+       SvANY(p) = 0;                                   \
+       SvREFCNT(p) = 1;                                \
+       SvFLAGS(p) = 0;                                 \
+    } STMT_END
 
 #ifdef DEBUGGING
 
-#define del_SV(p)      do {    \
-       LOCK_SV_MUTEX;          \
-       if (PL_debug & 32768)   \
-           del_sv(p);          \
-       else                    \
-           plant_SV(p);        \
-       UNLOCK_SV_MUTEX;        \
-    } while (0)
+#define del_SV(p) \
+    STMT_START {                                       \
+       LOCK_SV_MUTEX;                                  \
+       if (PL_debug & 32768)                           \
+           del_sv(p);                                  \
+       else                                            \
+           plant_SV(p);                                \
+       UNLOCK_SV_MUTEX;                                \
+    } STMT_END
 
 STATIC void
 del_sv(SV *p)
@@ -603,7 +609,7 @@ more_xpv(void)
 
 #ifdef PURIFY
 #  define my_safemalloc(s) safemalloc(s)
-#  define my_safefree(s) free(s)
+#  define my_safefree(s) safefree(s)
 #else
 STATIC void* 
 my_safemalloc(MEM_SIZE size)
@@ -1002,11 +1008,6 @@ sv_setiv(register SV *sv, IV i)
        break;
 
     case SVt_PVGV:
-       if (SvFAKE(sv)) {
-           sv_unglob(sv);
-           break;
-       }
-       /* FALL THROUGH */
     case SVt_PVAV:
     case SVt_PVHV:
     case SVt_PVCV:
@@ -1062,11 +1063,6 @@ sv_setnv(register SV *sv, double num)
        break;
 
     case SVt_PVGV:
-       if (SvFAKE(sv)) {
-           sv_unglob(sv);
-           break;
-       }
-       /* FALL THROUGH */
     case SVt_PVAV:
     case SVt_PVHV:
     case SVt_PVCV:
@@ -1173,11 +1169,9 @@ sv_2iv(register SV *sv)
     }
     if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
-#ifdef OVERLOAD
          SV* tmpstr;
          if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv, numer)))
-           return SvIV(tmpstr);
-#endif /* OVERLOAD */
+             return SvIV(tmpstr);
          return (IV)SvRV(sv);
        }
        if (SvREADONLY(sv)) {
@@ -1254,11 +1248,9 @@ sv_2uv(register SV *sv)
     }
     if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
-#ifdef OVERLOAD
          SV* tmpstr;
          if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv, numer)))
-           return SvUV(tmpstr);
-#endif /* OVERLOAD */
+             return SvUV(tmpstr);
          return (UV)SvRV(sv);
        }
        if (SvREADONLY(sv)) {
@@ -1336,11 +1328,9 @@ sv_2nv(register SV *sv)
     }
     if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
-#ifdef OVERLOAD
          SV* tmpstr;
          if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,numer)))
-           return SvNV(tmpstr);
-#endif /* OVERLOAD */
+             return SvNV(tmpstr);
          return (double)(unsigned long)SvRV(sv);
        }
        if (SvREADONLY(sv)) {
@@ -1513,6 +1503,13 @@ looks_like_number(SV *sv)
 }
 
 char *
+sv_2pv_nolen(register SV *sv)
+{
+    STRLEN n_a;
+    return sv_2pv(sv, &n_a);
+}
+
+char *
 sv_2pv(register SV *sv, STRLEN *lp)
 {
     register char *s;
@@ -1553,11 +1550,9 @@ sv_2pv(register SV *sv, STRLEN *lp)
     }
     if (SvTHINKFIRST(sv)) {
        if (SvROK(sv)) {
-#ifdef OVERLOAD
            SV* tmpstr;
            if (SvAMAGIC(sv) && (tmpstr=AMG_CALLun(sv,string)))
-             return SvPV(tmpstr,*lp);
-#endif /* OVERLOAD */
+               return SvPV(tmpstr,*lp);
            sv = (SV*)SvRV(sv);
            if (!sv)
                s = "NULLREF";
@@ -1569,7 +1564,7 @@ sv_2pv(register SV *sv, STRLEN *lp)
                    if ( ((SvFLAGS(sv) &
                           (SVs_OBJECT|SVf_OK|SVs_GMG|SVs_SMG|SVs_RMG)) 
                          == (SVs_OBJECT|SVs_RMG))
-                        && strEQ(s=HvNAME(SvSTASH(sv)), "re")
+                        && strEQ(s=HvNAME(SvSTASH(sv)), "Regexp")
                         && (mg = mg_find(sv, 'r'))) {
                        dTHR;
                        regexp *re = (regexp *)mg->mg_obj;
@@ -1762,14 +1757,10 @@ sv_2bool(register SV *sv)
     if (!SvOK(sv))
        return 0;
     if (SvROK(sv)) {
-#ifdef OVERLOAD
-      {
        dTHR;
        SV* tmpsv;
        if (SvAMAGIC(sv) && (tmpsv = AMG_CALLun(sv,bool_)))
-         return SvTRUE(tmpsv);
-      }
-#endif /* OVERLOAD */
+           return SvTRUE(tmpsv);
       return SvRV(sv) != 0;
     }
     if (SvPOKp(sv)) {
@@ -1815,16 +1806,8 @@ sv_setsv(SV *dstr, register SV *sstr)
     stype = SvTYPE(sstr);
     dtype = SvTYPE(dstr);
 
-    if (dtype == SVt_PVGV && (SvFLAGS(dstr) & SVf_FAKE)) {
-        sv_unglob(dstr);     /* so fake GLOB won't perpetuate */
-       sv_setpvn(dstr, "", 0);
-        (void)SvPOK_only(dstr);
-        dtype = SvTYPE(dstr);
-    }
-
-#ifdef OVERLOAD
     SvAMAGIC_off(dstr);
-#endif /* OVERLOAD */
+
     /* There's a lot of redundancy below but we're going for speed here */
 
     switch (stype) {
@@ -1955,9 +1938,9 @@ sv_setsv(SV *dstr, register SV *sstr)
            }
        }
        if (stype == SVt_PVLV)
-           SvUPGRADE(dstr, SVt_PVNV);
+           (void)SvUPGRADE(dstr, SVt_PVNV);
        else
-           SvUPGRADE(dstr, stype);
+           (void)SvUPGRADE(dstr, stype);
     }
 
     sflags = SvFLAGS(sstr);
@@ -2093,11 +2076,9 @@ sv_setsv(SV *dstr, register SV *sstr)
            (void)SvIOK_on(dstr);
            SvIVX(dstr) = SvIVX(sstr);
        }
-#ifdef OVERLOAD
        if (SvAMAGIC(sstr)) {
            SvAMAGIC_on(dstr);
        }
-#endif /* OVERLOAD */
     }
     else if (sflags & SVp_POK) {
 
@@ -2191,12 +2172,7 @@ sv_setpvn(register SV *sv, register const char *ptr, register STRLEN len)
        (void)SvOK_off(sv);
        return;
     }
-    if (SvTYPE(sv) >= SVt_PV) {
-       if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
-           sv_unglob(sv);
-    }
-    else
-       sv_upgrade(sv, SVt_PV);
+    (void)SvUPGRADE(sv, SVt_PV);
 
     SvGROW(sv, len + 1);
     dptr = SvPVX(sv);
@@ -2225,12 +2201,7 @@ sv_setpv(register SV *sv, register const char *ptr)
        return;
     }
     len = strlen(ptr);
-    if (SvTYPE(sv) >= SVt_PV) {
-       if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
-           sv_unglob(sv);
-    }
-    else 
-       sv_upgrade(sv, SVt_PV);
+    (void)SvUPGRADE(sv, SVt_PV);
 
     SvGROW(sv, len + 1);
     Move(ptr,SvPVX(sv),len+1,char);
@@ -2274,8 +2245,8 @@ sv_usepvn_mg(register SV *sv, register char *ptr, register STRLEN len)
     SvSETMAGIC(sv);
 }
 
-STATIC void
-sv_check_thinkfirst(register SV *sv)
+void
+sv_force_normal(register SV *sv)
 {
     if (SvREADONLY(sv)) {
        dTHR;
@@ -2284,6 +2255,8 @@ sv_check_thinkfirst(register SV *sv)
     }
     if (SvROK(sv))
        sv_unref(sv);
+    else if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV)
+       sv_unglob(sv);
 }
     
 void
@@ -2312,7 +2285,7 @@ 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)
+sv_catpvn(register SV *sv, register const char *ptr, register STRLEN len)
 {
     STRLEN tlen;
     char *junk;
@@ -2329,7 +2302,7 @@ 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_mg(register SV *sv, register const char *ptr, register STRLEN len)
 {
     sv_catpvn(sv,ptr,len);
     SvSETMAGIC(sv);
@@ -2354,7 +2327,7 @@ sv_catsv_mg(SV *dstr, register SV *sstr)
 }
 
 void
-sv_catpv(register SV *sv, register char *ptr)
+sv_catpv(register SV *sv, register const char *ptr)
 {
     register STRLEN len;
     STRLEN tlen;
@@ -2374,7 +2347,7 @@ sv_catpv(register SV *sv, register char *ptr)
 }
 
 void
-sv_catpv_mg(register SV *sv, register char *ptr)
+sv_catpv_mg(register SV *sv, register const char *ptr)
 {
     sv_catpv(sv,ptr);
     SvSETMAGIC(sv);
@@ -2386,9 +2359,6 @@ newSV(STRLEN len)
     register SV *sv;
     
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     if (len) {
        sv_upgrade(sv, SVt_PV);
        SvGROW(sv, len + 1);
@@ -2399,7 +2369,7 @@ newSV(STRLEN len)
 /* name is assumed to contain an SV* if (name && namelen == HEf_SVKEY) */
 
 void
-sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
+sv_magic(register SV *sv, SV *obj, int how, const char *name, I32 namlen)
 {
     MAGIC* mg;
     
@@ -2441,7 +2411,6 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
     case 0:
        mg->mg_virtual = &PL_vtbl_sv;
        break;
-#ifdef OVERLOAD
     case 'A':
         mg->mg_virtual = &PL_vtbl_amagic;
         break;
@@ -2451,7 +2420,6 @@ sv_magic(register SV *sv, SV *obj, int how, char *name, I32 namlen)
     case 'c':
         mg->mg_virtual = 0;
         break;
-#endif /* OVERLOAD */
     case 'B':
        mg->mg_virtual = &PL_vtbl_bm;
        break;
@@ -2740,6 +2708,14 @@ sv_clear(register SV *sv)
            } while (SvOBJECT(sv) && SvSTASH(sv) != stash);
 
            del_XRV(SvANY(&tmpref));
+
+           if (SvREFCNT(sv)) {
+               if (PL_in_clean_objs)
+                   croak("DESTROY created new reference to dead object '%s'",
+                         HvNAME(stash));
+               /* DESTROY gave object new lease on life */
+               return;
+           }
        }
 
        if (SvOBJECT(sv)) {
@@ -2748,12 +2724,6 @@ sv_clear(register SV *sv)
            if (SvTYPE(sv) != SVt_PVIO)
                --PL_sv_objcount;       /* XXX Might want something more general */
        }
-       if (SvREFCNT(sv)) {
-               if (PL_in_clean_objs)
-                   croak("DESTROY created new reference to dead object");
-               /* DESTROY gave object new lease on life */
-               return;
-       }
     }
     if (SvTYPE(sv) >= SVt_PVMG && SvMAGIC(sv))
        mg_free(sv);
@@ -2764,7 +2734,13 @@ sv_clear(register SV *sv)
            IoIFP(sv) != PerlIO_stdin() &&
            IoIFP(sv) != PerlIO_stdout() &&
            IoIFP(sv) != PerlIO_stderr())
+       {
          io_close((IO*)sv);
+       }
+       if (IoDIRP(sv)) {
+           PerlDir_close(IoDIRP(sv));
+           IoDIRP(sv) = 0;
+       }
        Safefree(IoTOP_NAME(sv));
        Safefree(IoFMT_NAME(sv));
        Safefree(IoBOTTOM_NAME(sv));
@@ -3185,6 +3161,7 @@ sv_gets(register SV *sv, register PerlIO *fp, I32 append)
 
     SV_CHECK_THINKFIRST(sv);
     (void)SvUPGRADE(sv, SVt_PV);
+
     SvSCREAM_off(sv);
 
     if (RsSNARF(PL_rs)) {
@@ -3453,9 +3430,8 @@ sv_inc(register SV *sv)
        }
        if (SvROK(sv)) {
            IV i;
-#ifdef OVERLOAD
-           if (SvAMAGIC(sv) && AMG_CALLun(sv,inc)) return;
-#endif /* OVERLOAD */
+           if (SvAMAGIC(sv) && AMG_CALLun(sv,inc))
+               return;
            i = (IV)SvRV(sv);
            sv_unref(sv);
            sv_setiv(sv, i);
@@ -3547,9 +3523,8 @@ sv_dec(register SV *sv)
        }
        if (SvROK(sv)) {
            IV i;
-#ifdef OVERLOAD
-           if (SvAMAGIC(sv) && AMG_CALLun(sv,dec)) return;
-#endif /* OVERLOAD */
+           if (SvAMAGIC(sv) && AMG_CALLun(sv,dec))
+               return;
            i = (IV)SvRV(sv);
            sv_unref(sv);
            sv_setiv(sv, i);
@@ -3586,14 +3561,6 @@ sv_dec(register SV *sv)
  * hopefully we won't free it until it has been assigned to a
  * permanent location. */
 
-STATIC void
-sv_mortalgrow(void)
-{
-    dTHR;
-    PL_tmps_max += (PL_tmps_max < 512) ? 128 : 512;
-    Renew(PL_tmps_stack, PL_tmps_max, SV*);
-}
-
 SV *
 sv_mortalcopy(SV *oldstr)
 {
@@ -3601,13 +3568,9 @@ sv_mortalcopy(SV *oldstr)
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     sv_setsv(sv,oldstr);
-    if (++PL_tmps_ix >= PL_tmps_max)
-       sv_mortalgrow();
-    PL_tmps_stack[PL_tmps_ix] = sv;
+    EXTEND_MORTAL(1);
+    PL_tmps_stack[++PL_tmps_ix] = sv;
     SvTEMP_on(sv);
     return sv;
 }
@@ -3619,12 +3582,9 @@ sv_newmortal(void)
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
     SvFLAGS(sv) = SVs_TEMP;
-    if (++PL_tmps_ix >= PL_tmps_max)
-       sv_mortalgrow();
-    PL_tmps_stack[PL_tmps_ix] = sv;
+    EXTEND_MORTAL(1);
+    PL_tmps_stack[++PL_tmps_ix] = sv;
     return sv;
 }
 
@@ -3638,22 +3598,18 @@ sv_2mortal(register SV *sv)
        return sv;
     if (SvREADONLY(sv) && SvIMMORTAL(sv))
        return sv;
-    if (++PL_tmps_ix >= PL_tmps_max)
-       sv_mortalgrow();
-    PL_tmps_stack[PL_tmps_ix] = sv;
+    EXTEND_MORTAL(1);
+    PL_tmps_stack[++PL_tmps_ix] = sv;
     SvTEMP_on(sv);
     return sv;
 }
 
 SV *
-newSVpv(char *s, STRLEN len)
+newSVpv(const char *s, STRLEN len)
 {
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     if (!len)
        len = strlen(s);
     sv_setpvn(sv,s,len);
@@ -3661,14 +3617,11 @@ newSVpv(char *s, STRLEN len)
 }
 
 SV *
-newSVpvn(char *s, STRLEN len)
+newSVpvn(const 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;
 }
@@ -3680,9 +3633,6 @@ newSVpvf(const char* pat, ...)
     va_list args;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     va_start(args, pat);
     sv_vsetpvfn(sv, pat, strlen(pat), &args, Null(SV**), 0, Null(bool*));
     va_end(args);
@@ -3696,9 +3646,6 @@ newSVnv(double n)
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     sv_setnv(sv,n);
     return sv;
 }
@@ -3709,9 +3656,6 @@ newSViv(IV i)
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     sv_setiv(sv,i);
     return sv;
 }
@@ -3723,9 +3667,6 @@ newRV_noinc(SV *tmpRef)
     register SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     sv_upgrade(sv, SVt_RV);
     SvTEMP_off(tmpRef);
     SvRV(sv) = tmpRef;
@@ -3753,9 +3694,6 @@ newSVsv(register SV *old)
        return Nullsv;
     }
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 1;
-    SvFLAGS(sv) = 0;
     if (SvTEMP(old)) {
        SvTEMP_off(old);
        sv_setsv(sv,old);
@@ -3843,6 +3781,7 @@ sv_2io(SV *sv)
 {
     IO* io;
     GV* gv;
+    STRLEN n_a;
 
     switch (SvTYPE(sv)) {
     case SVt_PVIO:
@@ -3859,13 +3798,13 @@ sv_2io(SV *sv)
            croak(PL_no_usym, "filehandle");
        if (SvROK(sv))
            return sv_2io(SvRV(sv));
-       gv = gv_fetchpv(SvPV(sv,PL_na), FALSE, SVt_PVIO);
+       gv = gv_fetchpv(SvPV(sv,n_a), FALSE, SVt_PVIO);
        if (gv)
            io = GvIO(gv);
        else
            io = 0;
        if (!io)
-           croak("Bad filehandle: %s", SvPV(sv,PL_na));
+           croak("Bad filehandle: %s", SvPV(sv,n_a));
        break;
     }
     return io;
@@ -3876,6 +3815,7 @@ sv_2cv(SV *sv, HV **st, GV **gvp, I32 lref)
 {
     GV *gv;
     CV *cv;
+    STRLEN n_a;
 
     if (!sv)
        return *gvp = Nullgv, Nullcv;
@@ -3917,7 +3857,7 @@ sv_2cv(SV *sv, HV **st, GV **gvp, I32 lref)
        else if (isGV(sv))
            gv = (GV*)sv;
        else
-           gv = gv_fetchpv(SvPV(sv, PL_na), lref, SVt_PVCV);
+           gv = gv_fetchpv(SvPV(sv, n_a), lref, SVt_PVCV);
        *gvp = gv;
        if (!gv)
            return Nullcv;
@@ -3934,7 +3874,7 @@ sv_2cv(SV *sv, HV **st, GV **gvp, I32 lref)
                   Nullop);
            LEAVE;
            if (!GvCVu(gv))
-               croak("Unable to create sub named \"%s\"", SvPV(sv,PL_na));
+               croak("Unable to create sub named \"%s\"", SvPV(sv,n_a));
        }
        return GvCVu(gv);
     }
@@ -3993,6 +3933,17 @@ sv_nv(register SV *sv)
 }
 
 char *
+sv_pv(SV *sv)
+{
+    STRLEN n_a;
+
+    if (SvPOK(sv))
+       return SvPVX(sv);
+
+    return sv_2pv(sv, &n_a);
+}
+
+char *
 sv_pvn(SV *sv, STRLEN *lp)
 {
     if (SvPOK(sv)) {
@@ -4007,27 +3958,17 @@ sv_pvn_force(SV *sv, STRLEN *lp)
 {
     char *s;
 
-    if (SvREADONLY(sv)) {
-       dTHR;
-       if (PL_curcop != &PL_compiling)
-           croak(PL_no_modify);
-    }
+    if (SvTHINKFIRST(sv) && !SvROK(sv))
+       sv_force_normal(sv);
     
     if (SvPOK(sv)) {
        *lp = SvCUR(sv);
     }
     else {
        if (SvTYPE(sv) > SVt_PVLV && SvTYPE(sv) != SVt_PVFM) {
-           if (SvFAKE(sv) && SvTYPE(sv) == SVt_PVGV) {
-               sv_unglob(sv);
-               s = SvPVX(sv);
-               *lp = SvCUR(sv);
-           }
-           else {
-               dTHR;
-               croak("Can't coerce %s to string in %s", sv_reftype(sv,0),
-                   PL_op_name[PL_op->op_type]);
-           }
+           dTHR;
+           croak("Can't coerce %s to string in %s", sv_reftype(sv,0),
+               PL_op_name[PL_op->op_type]);
        }
        else
            s = sv_2pv(sv, lp);
@@ -4099,7 +4040,7 @@ sv_isobject(SV *sv)
 }
 
 int
-sv_isa(SV *sv, char *name)
+sv_isa(SV *sv, const char *name)
 {
     if (!sv)
        return 0;
@@ -4115,26 +4056,21 @@ sv_isa(SV *sv, char *name)
 }
 
 SV*
-newSVrv(SV *rv, char *classname)
+newSVrv(SV *rv, const char *classname)
 {
     dTHR;
     SV *sv;
 
     new_SV(sv);
-    SvANY(sv) = 0;
-    SvREFCNT(sv) = 0;
-    SvFLAGS(sv) = 0;
 
     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);
+    SvRV(rv) = sv;
     SvROK_on(rv);
 
     if (classname) {
@@ -4145,7 +4081,7 @@ newSVrv(SV *rv, char *classname)
 }
 
 SV*
-sv_setref_pv(SV *rv, char *classname, void *pv)
+sv_setref_pv(SV *rv, const char *classname, void *pv)
 {
     if (!pv) {
        sv_setsv(rv, &PL_sv_undef);
@@ -4157,21 +4093,21 @@ sv_setref_pv(SV *rv, char *classname, void *pv)
 }
 
 SV*
-sv_setref_iv(SV *rv, char *classname, IV iv)
+sv_setref_iv(SV *rv, const char *classname, IV iv)
 {
     sv_setiv(newSVrv(rv,classname), iv);
     return rv;
 }
 
 SV*
-sv_setref_nv(SV *rv, char *classname, double nv)
+sv_setref_nv(SV *rv, const char *classname, double nv)
 {
     sv_setnv(newSVrv(rv,classname), nv);
     return rv;
 }
 
 SV*
-sv_setref_pvn(SV *rv, char *classname, char *pv, I32 n)
+sv_setref_pvn(SV *rv, const char *classname, char *pv, STRLEN n)
 {
     sv_setpvn(newSVrv(rv,classname), pv, n);
     return rv;
@@ -4200,12 +4136,10 @@ sv_bless(SV *sv, HV *stash)
     (void)SvUPGRADE(tmpRef, SVt_PVMG);
     SvSTASH(tmpRef) = (HV*)SvREFCNT_inc(stash);
 
-#ifdef OVERLOAD
     if (Gv_AMG(stash))
        SvAMAGIC_on(sv);
     else
        SvAMAGIC_off(sv);
-#endif /* OVERLOAD */
 
     return sv;
 }
@@ -4411,10 +4345,6 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
        char *eptr = Nullch;
        STRLEN elen = 0;
        char ebuf[TYPE_DIGITS(int) * 2 + 16]; /* large enough for "%#.#f" */
-
-       static char *efloatbuf = Nullch;
-       static STRLEN efloatsize = 0;
-
        char c;
        int i;
        unsigned base;
@@ -4643,6 +4573,10 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
            base = 10;
            goto uns_integer;
 
+       case 'b':
+           base = 2;
+           goto uns_integer;
+
        case 'O':
            intsize = 'l';
            /* FALL THROUGH */
@@ -4698,6 +4632,14 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
                if (alt && *eptr != '0')
                    *--eptr = '0';
                break;
+           case 2:
+               do {
+                   dig = uv & 1;
+                   *--eptr = '0' + dig;
+               } while (uv >>= 1);
+               if (alt && *eptr != '0')
+                   *--eptr = '0';
+               break;
            default:            /* it had better be ten or less */
                do {
                    dig = uv % base;
@@ -4744,10 +4686,10 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
                need = width;
 
            need += 20; /* fudge factor */
-           if (efloatsize < need) {
-               Safefree(efloatbuf);
-               efloatsize = need + 20; /* more fudge */
-               New(906, efloatbuf, efloatsize, char);
+           if (PL_efloatsize < need) {
+               Safefree(PL_efloatbuf);
+               PL_efloatsize = need + 20; /* more fudge */
+               New(906, PL_efloatbuf, PL_efloatsize, char);
            }
 
            eptr = ebuf + sizeof ebuf;
@@ -4772,10 +4714,10 @@ sv_vcatpvfn(SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs,
                *--eptr = '#';
            *--eptr = '%';
 
-           (void)sprintf(efloatbuf, eptr, nv);
+           (void)sprintf(PL_efloatbuf, eptr, nv);
 
-           eptr = efloatbuf;
-           elen = strlen(efloatbuf);
+           eptr = PL_efloatbuf;
+           elen = strlen(PL_efloatbuf);
 
 #ifdef LC_NUMERIC
            /*