This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Undo the sv_2pv() change of #5329, caused numconvert.t
[perl5.git] / sv.c
diff --git a/sv.c b/sv.c
index fddcd7e..d62a145 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1,6 +1,6 @@
 /*    sv.c
  *
- *    Copyright (c) 1991-1999, Larry Wall
+ *    Copyright (c) 1991-2000, 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.
@@ -25,105 +25,6 @@ static void do_clean_named_objs(pTHXo_ SV *sv);
 #endif
 static void do_clean_all(pTHXo_ SV *sv);
 
-
-#ifdef PURIFY
-
-#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;
-
-#define REGHASH(sv,size)  ((((U32)(sv)) >> 2) % (size))
-
-#define REG_REPLACE(sv,a,b) \
-    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)                                 \
-               Perl_die(aTHX_ "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)
-
-STATIC void
-S_reg_add(pTHX_ SV *sv)
-{
-    if (PL_sv_count >= (registry_size >> 1))
-    {
-       SV **oldreg = registry;
-       I32 oldsize = registry_size;
-
-       registry_size = registry_size ? ((registry_size << 2) + 1) : 2037;
-       Newz(707, registry, registry_size, SV*);
-
-       if (oldreg) {
-           I32 i;
-
-           for (i = 0; i < oldsize; ++i) {
-               SV* oldsv = oldreg[i];
-               if (oldsv)
-                   REG_ADD(oldsv);
-           }
-           Safefree(oldreg);
-       }
-    }
-
-    REG_ADD(sv);
-    ++PL_sv_count;
-}
-
-STATIC void
-S_reg_remove(pTHX_ SV *sv)
-{
-    REG_REMOVE(sv);
-    --PL_sv_count;
-}
-
-STATIC void
-S_visit(pTHX_ SVFUNC_t f)
-{
-    I32 i;
-
-    for (i = 0; i < registry_size; ++i) {
-       SV* sv = registry[i];
-       if (sv && SvTYPE(sv) != SVTYPEMASK)
-           (*f)(sv);
-    }
-}
-
-void
-Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
-{
-    if (!(flags & SVf_FAKE))
-       Safefree(ptr);
-}
-
-#else /* ! PURIFY */
-
 /*
  * "A time to plant, and a time to uproot what was planted..."
  */
@@ -206,7 +107,7 @@ Perl_sv_add_arena(pTHX_ char *ptr, U32 size, U32 flags)
     SV* sva = (SV*)ptr;
     register SV* sv;
     register SV* svend;
-    Zero(sva, size, char);
+    Zero(ptr, size, char);
 
     /* The first SV in an arena isn't an SV. */
     SvANY(sva) = (void *) PL_sv_arenaroot;             /* ptr to next arena */
@@ -262,8 +163,6 @@ S_visit(pTHX_ SVFUNC_t f)
     }
 }
 
-#endif /* PURIFY */
-
 void
 Perl_sv_report_used(pTHX)
 {
@@ -801,125 +700,109 @@ S_more_xpvbm(pTHX)
     xpvbm->xpv_pv = 0;
 }
 
-#ifdef PURIFY
-#define new_XIV() (void*)safemalloc(sizeof(XPVIV))
-#define del_XIV(p) Safefree((char*)p)
+#ifdef LEAKTEST
+#  define my_safemalloc(s)     (void*)safexmalloc(717,s)
+#  define my_safefree(p)       safexfree((char*)p)
 #else
-#define new_XIV() (void*)new_xiv()
-#define del_XIV(p) del_xiv((XPVIV*) p)
+#  define my_safemalloc(s)     (void*)safemalloc(s)
+#  define my_safefree(p)       safefree((char*)p)
 #endif
 
 #ifdef PURIFY
-#define new_XNV() (void*)safemalloc(sizeof(XPVNV))
-#define del_XNV(p) Safefree((char*)p)
-#else
-#define new_XNV() (void*)new_xnv()
-#define del_XNV(p) del_xnv((XPVNV*) p)
-#endif
 
-#ifdef PURIFY
-#define new_XRV() (void*)safemalloc(sizeof(XRV))
-#define del_XRV(p) Safefree((char*)p)
-#else
-#define new_XRV() (void*)new_xrv()
-#define del_XRV(p) del_xrv((XRV*) p)
-#endif
+#define new_XIV()      my_safemalloc(sizeof(XPVIV))
+#define del_XIV(p)     my_safefree(p)
 
-#ifdef PURIFY
-#define new_XPV() (void*)safemalloc(sizeof(XPV))
-#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_XNV()      my_safemalloc(sizeof(XPVNV))
+#define del_XNV(p)     my_safefree(p)
 
-#ifdef PURIFY
-#  define my_safemalloc(s) safemalloc(s)
-#  define my_safefree(s) safefree(s)
-#else
-STATIC void* 
-S_my_safemalloc(MEM_SIZE size)
-{
-    char *p;
-    New(717, p, size, char);
-    return (void*)p;
-}
-#  define my_safefree(s) Safefree(s)
-#endif 
+#define new_XRV()      my_safemalloc(sizeof(XRV))
+#define del_XRV(p)     my_safefree(p)
 
-#ifdef PURIFY
-#define new_XPVIV() (void*)safemalloc(sizeof(XPVIV))
-#define del_XPVIV(p) Safefree((char*)p)
-#else
-#define new_XPVIV() (void*)new_xpviv()
-#define del_XPVIV(p) del_xpviv((XPVIV *)p)
-#endif
-  
-#ifdef PURIFY
-#define new_XPVNV() (void*)safemalloc(sizeof(XPVNV))
-#define del_XPVNV(p) Safefree((char*)p)
-#else
-#define new_XPVNV() (void*)new_xpvnv()
-#define del_XPVNV(p) del_xpvnv((XPVNV *)p)
-#endif
+#define new_XPV()      my_safemalloc(sizeof(XPV))
+#define del_XPV(p)     my_safefree(p)
 
+#define new_XPVIV()    my_safemalloc(sizeof(XPVIV))
+#define del_XPVIV(p)   my_safefree(p)
 
-#ifdef PURIFY
-#define new_XPVCV() (void*)safemalloc(sizeof(XPVCV))
-#define del_XPVCV(p) Safefree((char*)p)
-#else
-#define new_XPVCV() (void*)new_xpvcv()
-#define del_XPVCV(p) del_xpvcv((XPVCV *)p)
-#endif
+#define new_XPVNV()    my_safemalloc(sizeof(XPVNV))
+#define del_XPVNV(p)   my_safefree(p)
 
-#ifdef PURIFY
-#define new_XPVAV() (void*)safemalloc(sizeof(XPVAV))
-#define del_XPVAV(p) Safefree((char*)p)
-#else
-#define new_XPVAV() (void*)new_xpvav()
-#define del_XPVAV(p) del_xpvav((XPVAV *)p)
-#endif
+#define new_XPVCV()    my_safemalloc(sizeof(XPVCV))
+#define del_XPVCV(p)   my_safefree(p)
 
-#ifdef PURIFY
-#define new_XPVHV() (void*)safemalloc(sizeof(XPVHV))
-#define del_XPVHV(p) Safefree((char*)p)
-#else
-#define new_XPVHV() (void*)new_xpvhv()
-#define del_XPVHV(p) del_xpvhv((XPVHV *)p)
-#endif
-  
-#ifdef PURIFY
-#define new_XPVMG() (void*)safemalloc(sizeof(XPVMG))
-#define del_XPVMG(p) Safefree((char*)p)
-#else
-#define new_XPVMG() (void*)new_xpvmg()
-#define del_XPVMG(p) del_xpvmg((XPVMG *)p)
-#endif
-  
-#ifdef PURIFY
-#define new_XPVLV() (void*)safemalloc(sizeof(XPVLV))
-#define del_XPVLV(p) Safefree((char*)p)
-#else
-#define new_XPVLV() (void*)new_xpvlv()
-#define del_XPVLV(p) del_xpvlv((XPVLV *)p)
-#endif
-  
-#define new_XPVGV() (void*)my_safemalloc(sizeof(XPVGV))
-#define del_XPVGV(p) my_safefree((char*)p)
+#define new_XPVAV()    my_safemalloc(sizeof(XPVAV))
+#define del_XPVAV(p)   my_safefree(p)
+
+#define new_XPVHV()    my_safemalloc(sizeof(XPVHV))
+#define del_XPVHV(p)   my_safefree(p)
   
-#ifdef PURIFY
-#define new_XPVBM() (void*)safemalloc(sizeof(XPVBM))
-#define del_XPVBM(p) Safefree((char*)p)
-#else
-#define new_XPVBM() (void*)new_xpvbm()
-#define del_XPVBM(p) del_xpvbm((XPVBM *)p)
-#endif
+#define new_XPVMG()    my_safemalloc(sizeof(XPVMG))
+#define del_XPVMG(p)   my_safefree(p)
+
+#define new_XPVLV()    my_safemalloc(sizeof(XPVLV))
+#define del_XPVLV(p)   my_safefree(p)
+
+#define new_XPVBM()    my_safemalloc(sizeof(XPVBM))
+#define del_XPVBM(p)   my_safefree(p)
+
+#else /* !PURIFY */
+
+#define new_XIV()      (void*)new_xiv()
+#define del_XIV(p)     del_xiv((XPVIV*) p)
+
+#define new_XNV()      (void*)new_xnv()
+#define del_XNV(p)     del_xnv((XPVNV*) p)
+
+#define new_XRV()      (void*)new_xrv()
+#define del_XRV(p)     del_xrv((XRV*) p)
+
+#define new_XPV()      (void*)new_xpv()
+#define del_XPV(p)     del_xpv((XPV *)p)
+
+#define new_XPVIV()    (void*)new_xpviv()
+#define del_XPVIV(p)   del_xpviv((XPVIV *)p)
+
+#define new_XPVNV()    (void*)new_xpvnv()
+#define del_XPVNV(p)   del_xpvnv((XPVNV *)p)
+
+#define new_XPVCV()    (void*)new_xpvcv()
+#define del_XPVCV(p)   del_xpvcv((XPVCV *)p)
+
+#define new_XPVAV()    (void*)new_xpvav()
+#define del_XPVAV(p)   del_xpvav((XPVAV *)p)
+
+#define new_XPVHV()    (void*)new_xpvhv()
+#define del_XPVHV(p)   del_xpvhv((XPVHV *)p)
   
-#define new_XPVFM() (void*)my_safemalloc(sizeof(XPVFM))
-#define del_XPVFM(p) my_safefree((char*)p)
+#define new_XPVMG()    (void*)new_xpvmg()
+#define del_XPVMG(p)   del_xpvmg((XPVMG *)p)
+
+#define new_XPVLV()    (void*)new_xpvlv()
+#define del_XPVLV(p)   del_xpvlv((XPVLV *)p)
+
+#define new_XPVBM()    (void*)new_xpvbm()
+#define del_XPVBM(p)   del_xpvbm((XPVBM *)p)
+
+#endif /* PURIFY */
+
+#define new_XPVGV()    my_safemalloc(sizeof(XPVGV))
+#define del_XPVGV(p)   my_safefree(p)
+#define new_XPVFM()    my_safemalloc(sizeof(XPVFM))
+#define del_XPVFM(p)   my_safefree(p)
   
-#define new_XPVIO() (void*)my_safemalloc(sizeof(XPVIO))
-#define del_XPVIO(p) my_safefree((char*)p)
+#define new_XPVIO()    my_safemalloc(sizeof(XPVIO))
+#define del_XPVIO(p)   my_safefree(p)
+
+/*
+=for apidoc sv_upgrade
+
+Upgrade an SV to a more complex form.  Use C<SvUPGRADE>.  See
+C<svtype>.
+
+=cut
+*/
 
 bool
 Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
@@ -1210,6 +1093,16 @@ Perl_sv_backoff(pTHX_ register SV *sv)
     return 0;
 }
 
+/*
+=for apidoc sv_grow
+
+Expands the character buffer in the SV.  This will use C<sv_unref> and will
+upgrade the SV to C<SVt_PV>.  Returns a pointer to the character buffer.
+Use C<SvGROW>.
+
+=cut
+*/
+
 char *
 Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
 {
@@ -1242,7 +1135,7 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
        s = SvPVX(sv);
     if (newlen > SvLEN(sv)) {          /* need more room? */
        if (SvLEN(sv) && s) {
-#if defined(MYMALLOC) && !defined(PURIFY) && !defined(LEAKTEST)
+#if defined(MYMALLOC) && !defined(LEAKTEST)
            STRLEN l = malloced_size((void*)SvPVX(sv));
            if (newlen <= l) {
                SvLEN_set(sv, l);
@@ -1259,6 +1152,15 @@ Perl_sv_grow(pTHX_ register SV *sv, register STRLEN newlen)
     return s;
 }
 
+/*
+=for apidoc sv_setiv
+
+Copies an integer into the given SV.  Does not handle 'set' magic.  See
+C<sv_setiv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setiv(pTHX_ register SV *sv, IV i)
 {
@@ -1292,6 +1194,14 @@ Perl_sv_setiv(pTHX_ register SV *sv, IV i)
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_setiv_mg
+
+Like C<sv_setiv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setiv_mg(pTHX_ register SV *sv, IV i)
 {
@@ -1299,6 +1209,15 @@ Perl_sv_setiv_mg(pTHX_ register SV *sv, IV i)
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_setuv
+
+Copies an unsigned integer into the given SV.  Does not handle 'set' magic.
+See C<sv_setuv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setuv(pTHX_ register SV *sv, UV u)
 {
@@ -1307,6 +1226,14 @@ Perl_sv_setuv(pTHX_ register SV *sv, UV u)
     SvUVX(sv) = u;
 }
 
+/*
+=for apidoc sv_setuv_mg
+
+Like C<sv_setuv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setuv_mg(pTHX_ register SV *sv, UV u)
 {
@@ -1314,6 +1241,15 @@ Perl_sv_setuv_mg(pTHX_ register SV *sv, UV u)
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_setnv
+
+Copies a double into the given SV.  Does not handle 'set' magic.  See
+C<sv_setnv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setnv(pTHX_ register SV *sv, NV num)
 {
@@ -1346,6 +1282,14 @@ Perl_sv_setnv(pTHX_ register SV *sv, NV num)
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_setnv_mg
+
+Like C<sv_setnv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setnv_mg(pTHX_ register SV *sv, NV num)
 {
@@ -1872,6 +1816,15 @@ S_asUV(pTHX_ SV *sv)
  * with a possible addition of IS_NUMBER_NEG.
  */
 
+/*
+=for apidoc looks_like_number
+
+Test if an the content of an SV looks like a number (or is a
+number).
+
+=cut
+*/
+
 I32
 Perl_looks_like_number(pTHX_ SV *sv)
 {
@@ -2258,6 +2211,33 @@ Perl_sv_2pv(pTHX_ register SV *sv, STRLEN *lp)
     }
 }
 
+char *
+Perl_sv_2pvbyte_nolen(pTHX_ register SV *sv)
+{
+    STRLEN n_a;
+    return sv_2pvbyte(sv, &n_a);
+}
+
+char *
+Perl_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp)
+{
+    return sv_2pv(sv,lp);
+}
+
+char *
+Perl_sv_2pvutf8_nolen(pTHX_ register SV *sv)
+{
+    STRLEN n_a;
+    return sv_2pvutf8(sv, &n_a);
+}
+
+char *
+Perl_sv_2pvutf8(pTHX_ register SV *sv, STRLEN *lp)
+{
+    sv_utf8_upgrade(sv);
+    return sv_2pv(sv,lp);
+}
 /* This function is only called on magical items */
 bool
 Perl_sv_2bool(pTHX_ register SV *sv)
@@ -2296,11 +2276,155 @@ Perl_sv_2bool(pTHX_ register SV *sv)
     }
 }
 
+void
+Perl_sv_utf8_upgrade(pTHX_ register SV *sv)
+{
+    int hicount;
+    char *c;
+
+    if (!sv || !SvPOK(sv) || SvUTF8(sv))
+       return;
+
+    /* This function could be much more efficient if we had a FLAG
+     * to signal if there are any hibit chars in the string
+     */
+    hicount = 0;
+    for (c = SvPVX(sv); c < SvEND(sv); c++) {
+       if (*c & 0x80)
+           hicount++;
+    }
+
+    if (hicount) {
+       char *src, *dst;
+       SvGROW(sv, SvCUR(sv) + hicount + 1);
+
+       src = SvEND(sv) - 1;
+       SvCUR_set(sv, SvCUR(sv) + hicount);
+       dst = SvEND(sv) - 1;
+
+       while (src < dst) {
+           if (*src & 0x80) {
+               dst--;
+               uv_to_utf8((U8*)dst, (U8)*src--);
+               dst--;
+           }
+           else {
+               *dst-- = *src--;
+           }
+       }
+
+       SvUTF8_on(sv);
+    }
+}
+
+bool
+Perl_sv_utf8_downgrade(pTHX_ register SV* sv, bool fail_ok)
+{
+    if (SvPOK(sv) && SvUTF8(sv)) {
+        char *c = SvPVX(sv);
+        char *first_hi = 0;
+        /* need to figure out if this is possible at all first */
+        while (c < SvEND(sv)) {
+            if (*c & 0x80) {
+                I32 len;
+                UV uv = utf8_to_uv((U8*)c, &len);
+                if (uv >= 256) {
+                   if (fail_ok)
+                       return FALSE;
+                   else {
+                       /* XXX might want to make a callback here instead */
+                       Perl_croak(aTHX_ "Big byte");
+                   }
+               }
+                if (!first_hi)
+                    first_hi = c;
+                c += len;
+            }
+            else {
+                c++;
+            }
+        }
+
+        if (first_hi) {
+            char *src = first_hi;
+            char *dst = first_hi;
+            while (src < SvEND(sv)) {
+                if (*src & 0x80) {
+                    I32 len;
+                    U8 u = (U8)utf8_to_uv((U8*)src, &len);
+                    *dst++ = u;
+                    src += len;
+                }
+                else {
+                    *dst++ = *src++;
+                }
+            }
+            SvCUR_set(sv, dst - SvPVX(sv));
+        }
+        SvUTF8_off(sv);
+    }
+    return TRUE;
+}
+
+void
+Perl_sv_utf8_encode(pTHX_ register SV *sv)
+{
+    sv_utf8_upgrade(sv);
+    SvUTF8_off(sv);
+}
+
+bool
+Perl_sv_utf8_decode(pTHX_ register SV *sv)
+{
+    if (SvPOK(sv)) {
+        char *c;
+        bool has_utf = FALSE;
+        if (!sv_utf8_downgrade(sv, TRUE))
+           return FALSE;
+
+        /* it is actually just a matter of turning the utf8 flag on, but
+         * we want to make sure everything inside is valid utf8 first.
+         */
+        c = SvPVX(sv);
+        while (c < SvEND(sv)) {
+            if (*c & 0x80) {
+                I32 len;
+                (void)utf8_to_uv((U8*)c, &len);
+                if (len == 1) {
+                    /* bad utf8 */
+                    return FALSE;
+                }
+                c += len;
+                has_utf = TRUE;
+            }
+            else {
+                c++;
+            }
+        }
+
+        if (has_utf)
+            SvUTF8_on(sv);
+    }
+    return TRUE;
+}
+
+
 /* Note: sv_setsv() should not be called with a source string that needs
  * to be reused, since it may destroy the source string if it is marked
  * as temporary.
  */
 
+/*
+=for apidoc sv_setsv
+
+Copies the contents of the source SV C<ssv> into the destination SV C<dsv>.
+The source SV may be destroyed if it is mortal.  Does not handle 'set'
+magic.  See the macro forms C<SvSetSV>, C<SvSetSV_nosteal> and
+C<sv_setsv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
 {
@@ -2538,16 +2662,11 @@ Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
                                    Perl_croak(aTHX_ 
                                    "Can't redefine active sort subroutine %s",
                                          GvENAME((GV*)dstr));
-                               if (ckWARN(WARN_REDEFINE) || (const_changed && const_sv)) {
-                                   if (!(CvGV(cv) && GvSTASH(CvGV(cv))
-                                         && HvNAME(GvSTASH(CvGV(cv)))
-                                         && strEQ(HvNAME(GvSTASH(CvGV(cv))),
-                                                  "autouse")))
-                                       Perl_warner(aTHX_ WARN_REDEFINE, const_sv ? 
+                               if ((const_changed || const_sv) && ckWARN(WARN_REDEFINE))
+                                   Perl_warner(aTHX_ WARN_REDEFINE, const_sv ? 
                                             "Constant subroutine %s redefined"
                                             : "Subroutine %s redefined", 
                                             GvENAME((GV*)dstr));
-                               }
                            }
                            cv_ckproto(cv, (GV*)dstr,
                                       SvPOK(sref) ? SvPVX(sref) : Nullch);
@@ -2639,6 +2758,11 @@ Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
            SvPV_set(dstr, SvPVX(sstr));
            SvLEN_set(dstr, SvLEN(sstr));
            SvCUR_set(dstr, SvCUR(sstr));
+           if (SvUTF8(sstr))
+               SvUTF8_on(dstr);
+           else
+               SvUTF8_off(dstr);
+
            SvTEMP_off(dstr);
            (void)SvOK_off(sstr);
            SvPV_set(sstr, Nullch);
@@ -2655,6 +2779,8 @@ Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
            *SvEND(dstr) = '\0';
            (void)SvPOK_only(dstr);
        }
+       if (DO_UTF8(sstr))
+           SvUTF8_on(dstr);
        /*SUPPRESS 560*/
        if (sflags & SVp_NOK) {
            SvNOK_on(dstr);
@@ -2686,8 +2812,8 @@ Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
     }
     else {
        if (dtype == SVt_PVGV) {
-           if (ckWARN(WARN_UNSAFE))
-               Perl_warner(aTHX_ WARN_UNSAFE, "Undefined value assigned to typeglob");
+           if (ckWARN(WARN_MISC))
+               Perl_warner(aTHX_ WARN_MISC, "Undefined value assigned to typeglob");
        }
        else
            (void)SvOK_off(dstr);
@@ -2695,6 +2821,14 @@ Perl_sv_setsv(pTHX_ SV *dstr, register SV *sstr)
     SvTAINT(dstr);
 }
 
+/*
+=for apidoc sv_setsv_mg
+
+Like C<sv_setsv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setsv_mg(pTHX_ SV *dstr, register SV *sstr)
 {
@@ -2702,6 +2836,15 @@ Perl_sv_setsv_mg(pTHX_ SV *dstr, register SV *sstr)
     SvSETMAGIC(dstr);
 }
 
+/*
+=for apidoc sv_setpvn
+
+Copies a string into an SV.  The C<len> parameter indicates the number of
+bytes to be copied.  Does not handle 'set' magic.  See C<sv_setpvn_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN len)
 {
@@ -2724,6 +2867,14 @@ Perl_sv_setpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_setpvn_mg
+
+Like C<sv_setpvn>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRLEN len)
 {
@@ -2731,6 +2882,15 @@ Perl_sv_setpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRL
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_setpv
+
+Copies a string into an SV.  The string must be null-terminated.  Does not
+handle 'set' magic.  See C<sv_setpv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setpv(pTHX_ register SV *sv, register const char *ptr)
 {
@@ -2751,6 +2911,14 @@ Perl_sv_setpv(pTHX_ register SV *sv, register const char *ptr)
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_setpv_mg
+
+Like C<sv_setpv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setpv_mg(pTHX_ register SV *sv, register const char *ptr)
 {
@@ -2758,6 +2926,20 @@ Perl_sv_setpv_mg(pTHX_ register SV *sv, register const char *ptr)
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_usepvn
+
+Tells an SV to use C<ptr> to find its string value.  Normally the string is
+stored inside the SV but sv_usepvn allows the SV to use an outside string. 
+The C<ptr> should point to memory that was allocated by C<malloc>.  The
+string length, C<len>, must be supplied.  This function will realloc the
+memory pointed to by C<ptr>, so that pointer should not be freed or used by
+the programmer after giving it to sv_usepvn.  Does not handle 'set' magic.
+See C<sv_usepvn_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
 {
@@ -2779,6 +2961,14 @@ Perl_sv_usepvn(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_usepvn_mg
+
+Like C<sv_usepvn>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_usepvn_mg(pTHX_ register SV *sv, register char *ptr, register STRLEN len)
 {
@@ -2800,6 +2990,17 @@ Perl_sv_force_normal(pTHX_ register SV *sv)
        sv_unglob(sv);
 }
     
+/*
+=for apidoc sv_chop
+
+Efficient removal of characters from the beginning of the string buffer. 
+SvPOK(sv) must be true and the C<ptr> must be a pointer to somewhere inside
+the string buffer.  The C<ptr> becomes the first character of the adjusted
+string.
+
+=cut
+*/
+
 void
 Perl_sv_chop(pTHX_ register SV *sv, register char *ptr)        /* like set but assuming ptr is in sv */
                 
@@ -2832,6 +3033,16 @@ Perl_sv_chop(pTHX_ register SV *sv, register char *ptr)  /* like set but assuming
     SvIVX(sv) += delta;
 }
 
+/*
+=for apidoc sv_catpvn
+
+Concatenates the string onto the end of the string which is in the SV.  The
+C<len> indicates number of bytes to copy.  Handles 'get' magic, but not
+'set' magic.  See C<sv_catpvn_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_catpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN len)
 {
@@ -2845,10 +3056,18 @@ Perl_sv_catpvn(pTHX_ register SV *sv, register const char *ptr, register STRLEN
     Move(ptr,SvPVX(sv)+tlen,len,char);
     SvCUR(sv) += len;
     *SvEND(sv) = '\0';
-    (void)SvPOK_only(sv);              /* validate pointer */
+    (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_catpvn_mg
+
+Like C<sv_catpvn>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_catpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRLEN len)
 {
@@ -2856,6 +3075,15 @@ Perl_sv_catpvn_mg(pTHX_ register SV *sv, register const char *ptr, register STRL
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_catsv
+
+Concatenates the string from SV C<ssv> onto the end of the string in SV
+C<dsv>.  Handles 'get' magic, but not 'set' magic.  See C<sv_catsv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_catsv(pTHX_ SV *dstr, register SV *sstr)
 {
@@ -2863,10 +3091,23 @@ Perl_sv_catsv(pTHX_ SV *dstr, register SV *sstr)
     STRLEN len;
     if (!sstr)
        return;
-    if (s = SvPV(sstr, len))
+    if (s = SvPV(sstr, len)) {
+       if (SvUTF8(sstr))
+           sv_utf8_upgrade(dstr);
        sv_catpvn(dstr,s,len);
+       if (SvUTF8(sstr))
+           SvUTF8_on(dstr);
+    }
 }
 
+/*
+=for apidoc sv_catsv_mg
+
+Like C<sv_catsv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_catsv_mg(pTHX_ SV *dstr, register SV *sstr)
 {
@@ -2874,6 +3115,15 @@ Perl_sv_catsv_mg(pTHX_ SV *dstr, register SV *sstr)
     SvSETMAGIC(dstr);
 }
 
+/*
+=for apidoc sv_catpv
+
+Concatenates the string onto the end of the string which is in the SV.
+Handles 'get' magic, but not 'set' magic.  See C<sv_catpv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr)
 {
@@ -2890,10 +3140,18 @@ Perl_sv_catpv(pTHX_ register SV *sv, register const char *ptr)
        ptr = SvPVX(sv);
     Move(ptr,SvPVX(sv)+tlen,len+1,char);
     SvCUR(sv) += len;
-    (void)SvPOK_only(sv);              /* validate pointer */
+    (void)SvPOK_only_UTF8(sv);         /* validate pointer */
     SvTAINT(sv);
 }
 
+/*
+=for apidoc sv_catpv_mg
+
+Like C<sv_catpv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_catpv_mg(pTHX_ register SV *sv, register const char *ptr)
 {
@@ -2916,6 +3174,14 @@ Perl_newSV(pTHX_ STRLEN len)
 
 /* name is assumed to contain an SV* if (name && namelen == HEf_SVKEY) */
 
+/*
+=for apidoc sv_magic
+
+Adds magic to an SV.
+
+=cut
+*/
+
 void
 Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 namlen)
 {
@@ -3164,6 +3430,15 @@ S_sv_del_backref(pTHX_ SV *sv)
     }
 }
 
+/*
+=for apidoc sv_insert
+
+Inserts a string at the specified offset/length within the SV. Similar to
+the Perl substr() function.
+
+=cut
+*/
+
 void
 Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN littlelen)
 {
@@ -3184,6 +3459,7 @@ Perl_sv_insert(pTHX_ SV *bigstr, STRLEN offset, STRLEN len, char *little, STRLEN
        SvCUR_set(bigstr, offset+len);
     }
 
+    SvTAINT(bigstr);
     i = littlelen - len;
     if (i > 0) {                       /* string might grow */
        big = SvGROW(bigstr, SvCUR(bigstr) + i + 1);
@@ -3513,6 +3789,14 @@ Perl_sv_free(pTHX_ SV *sv)
        del_SV(sv);
 }
 
+/*
+=for apidoc sv_len
+
+Returns the length of the string in the SV.  See also C<SvCUR>.
+
+=cut
+*/
+
 STRLEN
 Perl_sv_len(pTHX_ register SV *sv)
 {
@@ -3614,6 +3898,15 @@ Perl_sv_pos_b2u(pTHX_ register SV *sv, I32* offsetp)
     return;
 }
 
+/*
+=for apidoc sv_eq
+
+Returns a boolean indicating whether the strings in the two SVs are
+identical.
+
+=cut
+*/
+
 I32
 Perl_sv_eq(pTHX_ register SV *str1, register SV *str2)
 {
@@ -3640,14 +3933,55 @@ Perl_sv_eq(pTHX_ register SV *str1, register SV *str2)
     return memEQ(pv1, pv2, cur1);
 }
 
+/*
+=for apidoc sv_cmp
+
+Compares the strings in two SVs.  Returns -1, 0, or 1 indicating whether the
+string in C<sv1> is less than, equal to, or greater than the string in
+C<sv2>.
+
+=cut
+*/
+
 I32
 Perl_sv_cmp(pTHX_ register SV *str1, register SV *str2)
 {
-    STRLEN cur1 = 0;
-    char *pv1 = str1 ? SvPV(str1, cur1) : (char *) NULL;
-    STRLEN cur2 = 0;
-    char *pv2 = str2 ? SvPV(str2, cur2) : (char *) NULL;
+    STRLEN cur1, cur2;
+    char *pv1, *pv2;
     I32 retval;
+    bool utf1;
+
+    if (str1) {
+        pv1 = SvPV(str1, cur1);
+    }
+    else {
+       cur1 = 0;
+    }
+
+    if (str2) {
+       if (SvPOK(str2)) {
+           if (SvPOK(str1) && SvUTF8(str1) != SvUTF8(str2) && !IN_BYTE) {
+               /* must upgrade other to UTF8 first */
+               if (SvUTF8(str1)) {
+                   sv_utf8_upgrade(str2);
+               }
+               else {
+                   sv_utf8_upgrade(str1);
+                   /* refresh pointer and length */
+                   pv1  = SvPVX(str1);
+                   cur1 = SvCUR(str1);
+               }
+           }
+           pv2  = SvPVX(str2);
+           cur2 = SvCUR(str2);
+       }
+       else {
+           pv2 = sv_2pv(str2, &cur2);
+       }
+    }
+    else {
+       cur2 = 0;
+    }
 
     if (!cur1)
        return cur2 ? -1 : 0;
@@ -4032,14 +4366,18 @@ screamer2:
        }
     }
 
-#ifdef WIN32
-    win32_strip_return(sv);
-#endif
-
     return (SvCUR(sv) - append) ? SvPVX(sv) : Nullch;
 }
 
 
+/*
+=for apidoc sv_inc
+
+Auto-increment of the value in the SV.
+
+=cut
+*/
+
 void
 Perl_sv_inc(pTHX_ register SV *sv)
 {
@@ -4141,6 +4479,14 @@ Perl_sv_inc(pTHX_ register SV *sv)
        *d = d[1];
 }
 
+/*
+=for apidoc sv_dec
+
+Auto-decrement of the value in the SV.
+
+=cut
+*/
+
 void
 Perl_sv_dec(pTHX_ register SV *sv)
 {
@@ -4201,6 +4547,15 @@ Perl_sv_dec(pTHX_ register SV *sv)
     sv_setnv(sv,Atof(SvPVX(sv)) - 1.0);        /* punt */
 }
 
+/*
+=for apidoc sv_mortalcopy
+
+Creates a new SV which is a copy of the original SV.  The new SV is marked
+as mortal.
+
+=cut
+*/
+
 /* Make a string that will exist for the duration of the expression
  * evaluation.  Actually, it may have to last longer than that, but
  * hopefully we won't free it until it has been assigned to a
@@ -4220,6 +4575,14 @@ Perl_sv_mortalcopy(pTHX_ SV *oldstr)
     return sv;
 }
 
+/*
+=for apidoc sv_newmortal
+
+Creates a new SV which is mortal.  The reference count of the SV is set to 1.
+
+=cut
+*/
+
 SV *
 Perl_sv_newmortal(pTHX)
 {
@@ -4233,6 +4596,15 @@ Perl_sv_newmortal(pTHX)
     return sv;
 }
 
+/*
+=for apidoc sv_2mortal
+
+Marks an SV as mortal.  The SV will be destroyed when the current context
+ends.
+
+=cut
+*/
+
 /* same thing without the copying */
 
 SV *
@@ -4249,6 +4621,16 @@ Perl_sv_2mortal(pTHX_ register SV *sv)
     return sv;
 }
 
+/*
+=for apidoc newSVpv
+
+Creates a new SV and copies a string into it.  The reference count for the
+SV is set to 1.  If C<len> is zero, Perl will compute the length using
+strlen().  For efficiency, consider using C<newSVpvn> instead.
+
+=cut
+*/
+
 SV *
 Perl_newSVpv(pTHX_ const char *s, STRLEN len)
 {
@@ -4261,6 +4643,17 @@ Perl_newSVpv(pTHX_ const char *s, STRLEN len)
     return sv;
 }
 
+/*
+=for apidoc newSVpvn
+
+Creates a new SV and copies a string into it.  The reference count for the
+SV is set to 1.  Note that if C<len> is zero, Perl will create a zero length 
+string.  You are responsible for ensuring that the source string is at least
+C<len> bytes long.
+
+=cut
+*/
+
 SV *
 Perl_newSVpvn(pTHX_ const char *s, STRLEN len)
 {
@@ -4285,6 +4678,15 @@ Perl_newSVpvf_nocontext(const char* pat, ...)
 }
 #endif
 
+/*
+=for apidoc newSVpvf
+
+Creates a new SV an initialize it with the string formatted like
+C<sprintf>.
+
+=cut
+*/
+
 SV *
 Perl_newSVpvf(pTHX_ const char* pat, ...)
 {
@@ -4305,6 +4707,15 @@ Perl_vnewSVpvf(pTHX_ const char* pat, va_list* args)
     return sv;
 }
 
+/*
+=for apidoc newSVnv
+
+Creates a new SV and copies a floating point value into it.
+The reference count for the SV is set to 1.
+
+=cut
+*/
+
 SV *
 Perl_newSVnv(pTHX_ NV n)
 {
@@ -4315,6 +4726,15 @@ Perl_newSVnv(pTHX_ NV n)
     return sv;
 }
 
+/*
+=for apidoc newSViv
+
+Creates a new SV and copies an integer into it.  The reference count for the
+SV is set to 1.
+
+=cut
+*/
+
 SV *
 Perl_newSViv(pTHX_ IV i)
 {
@@ -4325,6 +4745,15 @@ Perl_newSViv(pTHX_ IV i)
     return sv;
 }
 
+/*
+=for apidoc newRV_noinc
+
+Creates an RV wrapper for an SV.  The reference count for the original
+SV is B<not> incremented.
+
+=cut
+*/
+
 SV *
 Perl_newRV_noinc(pTHX_ SV *tmpRef)
 {
@@ -4339,12 +4768,21 @@ Perl_newRV_noinc(pTHX_ SV *tmpRef)
     return sv;
 }
 
+/* newRV_inc is #defined to newRV in sv.h */
 SV *
 Perl_newRV(pTHX_ SV *tmpRef)
 {
     return newRV_noinc(SvREFCNT_inc(tmpRef));
 }
 
+/*
+=for apidoc newSVsv
+
+Creates a new SV which is an exact duplicate of the original SV.
+
+=cut
+*/
+
 /* make an exact duplicate of old */
 
 SV *
@@ -4559,8 +4997,7 @@ Perl_sv_true(pTHX_ register SV *sv)
     if (SvPOK(sv)) {
        register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
-               (*tXpv->xpv_pv > '0' ||
-               tXpv->xpv_cur > 1 ||
+               (tXpv->xpv_cur > 1 ||
                (tXpv->xpv_cur && *tXpv->xpv_pv != '0')))
            return 1;
        else
@@ -4670,6 +5107,45 @@ Perl_sv_pvn_force(pTHX_ SV *sv, STRLEN *lp)
 }
 
 char *
+Perl_sv_pvbyte(pTHX_ SV *sv)
+{
+    return sv_pv(sv);
+}
+
+char *
+Perl_sv_pvbyten(pTHX_ SV *sv, STRLEN *lp)
+{
+    return sv_pvn(sv,lp);
+}
+
+char *
+Perl_sv_pvbyten_force(pTHX_ SV *sv, STRLEN *lp)
+{
+    return sv_pvn_force(sv,lp);
+}
+
+char *
+Perl_sv_pvutf8(pTHX_ SV *sv)
+{
+    sv_utf8_upgrade(sv);
+    return sv_pv(sv);
+}
+
+char *
+Perl_sv_pvutf8n(pTHX_ SV *sv, STRLEN *lp)
+{
+    sv_utf8_upgrade(sv);
+    return sv_pvn(sv,lp);
+}
+
+char *
+Perl_sv_pvutf8n_force(pTHX_ SV *sv, STRLEN *lp)
+{
+    sv_utf8_upgrade(sv);
+    return sv_pvn_force(sv,lp);
+}
+
+char *
 Perl_sv_reftype(pTHX_ SV *sv, int ob)
 {
     if (ob && SvOBJECT(sv))
@@ -4700,6 +5176,16 @@ Perl_sv_reftype(pTHX_ SV *sv, int ob)
     }
 }
 
+/*
+=for apidoc sv_isobject
+
+Returns a boolean indicating whether the SV is an RV pointing to a blessed
+object.  If the SV is not an RV, or if the object is not blessed, then this
+will return false.
+
+=cut
+*/
+
 int
 Perl_sv_isobject(pTHX_ SV *sv)
 {
@@ -4715,6 +5201,16 @@ Perl_sv_isobject(pTHX_ SV *sv)
     return 1;
 }
 
+/*
+=for apidoc sv_isa
+
+Returns a boolean indicating whether the SV is blessed into the specified
+class.  This does not check for subtypes; use C<sv_derived_from> to verify
+an inheritance relationship.
+
+=cut
+*/
+
 int
 Perl_sv_isa(pTHX_ SV *sv, const char *name)
 {
@@ -4731,6 +5227,17 @@ Perl_sv_isa(pTHX_ SV *sv, const char *name)
     return strEQ(HvNAME(SvSTASH(sv)), name);
 }
 
+/*
+=for apidoc newSVrv
+
+Creates a new SV for the RV, C<rv>, to point to.  If C<rv> is not an RV then
+it will be upgraded to one.  If C<classname> is non-null then the new SV will
+be blessed in the specified package.  The new SV is returned and its
+reference count is 1.
+
+=cut
+*/
+
 SV*
 Perl_newSVrv(pTHX_ SV *rv, const char *classname)
 {
@@ -4756,6 +5263,24 @@ Perl_newSVrv(pTHX_ SV *rv, const char *classname)
     return sv;
 }
 
+/*
+=for apidoc sv_setref_pv
+
+Copies a pointer into a new SV, optionally blessing the SV.  The C<rv>
+argument will be upgraded to an RV.  That RV will be modified to point to
+the new SV.  If the C<pv> argument is NULL then C<PL_sv_undef> will be placed
+into the SV.  The C<classname> argument indicates the package for the
+blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+will be returned and will have a reference count of 1.
+
+Do not use with other Perl types such as HV, AV, SV, CV, because those
+objects will become corrupted by the pointer copy process.
+
+Note that C<sv_setref_pvn> copies the string while this copies the pointer.
+
+=cut
+*/
+
 SV*
 Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
 {
@@ -4768,6 +5293,18 @@ Perl_sv_setref_pv(pTHX_ SV *rv, const char *classname, void *pv)
     return rv;
 }
 
+/*
+=for apidoc sv_setref_iv
+
+Copies an integer into a new SV, optionally blessing the SV.  The C<rv>
+argument will be upgraded to an RV.  That RV will be modified to point to
+the new SV.  The C<classname> argument indicates the package for the
+blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+will be returned and will have a reference count of 1.
+
+=cut
+*/
+
 SV*
 Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv)
 {
@@ -4775,6 +5312,18 @@ Perl_sv_setref_iv(pTHX_ SV *rv, const char *classname, IV iv)
     return rv;
 }
 
+/*
+=for apidoc sv_setref_nv
+
+Copies a double into a new SV, optionally blessing the SV.  The C<rv>
+argument will be upgraded to an RV.  That RV will be modified to point to
+the new SV.  The C<classname> argument indicates the package for the
+blessing.  Set C<classname> to C<Nullch> to avoid the blessing.  The new SV
+will be returned and will have a reference count of 1.
+
+=cut
+*/
+
 SV*
 Perl_sv_setref_nv(pTHX_ SV *rv, const char *classname, NV nv)
 {
@@ -4782,6 +5331,21 @@ Perl_sv_setref_nv(pTHX_ SV *rv, const char *classname, NV nv)
     return rv;
 }
 
+/*
+=for apidoc sv_setref_pvn
+
+Copies a string into a new SV, optionally blessing the SV.  The length of the
+string must be specified with C<n>.  The C<rv> argument will be upgraded to
+an RV.  That RV will be modified to point to the new SV.  The C<classname>
+argument indicates the package for the blessing.  Set C<classname> to
+C<Nullch> to avoid the blessing.  The new SV will be returned and will have
+a reference count of 1.
+
+Note that C<sv_setref_pv> copies the pointer while this copies the string.
+
+=cut
+*/
+
 SV*
 Perl_sv_setref_pvn(pTHX_ SV *rv, const char *classname, char *pv, STRLEN n)
 {
@@ -4789,6 +5353,16 @@ Perl_sv_setref_pvn(pTHX_ SV *rv, const char *classname, char *pv, STRLEN n)
     return rv;
 }
 
+/*
+=for apidoc sv_bless
+
+Blesses an SV into a specified package.  The SV must be an RV.  The package
+must be designated by its stash (see C<gv_stashpv()>).  The reference count
+of the SV is unaffected.
+
+=cut
+*/
+
 SV*
 Perl_sv_bless(pTHX_ SV *sv, HV *stash)
 {
@@ -4823,6 +5397,8 @@ Perl_sv_bless(pTHX_ SV *sv, HV *stash)
 STATIC void
 S_sv_unglob(pTHX_ SV *sv)
 {
+    void *xpvmg;
+
     assert(SvTYPE(sv) == SVt_PVGV);
     SvFAKE_off(sv);
     if (GvGP(sv))
@@ -4834,10 +5410,27 @@ S_sv_unglob(pTHX_ SV *sv)
     sv_unmagic(sv, '*');
     Safefree(GvNAME(sv));
     GvMULTI_off(sv);
+
+    /* need to keep SvANY(sv) in the right arena */
+    xpvmg = new_XPVMG();
+    StructCopy(SvANY(sv), xpvmg, XPVMG);
+    del_XPVGV(SvANY(sv));
+    SvANY(sv) = xpvmg;
+
     SvFLAGS(sv) &= ~SVTYPEMASK;
     SvFLAGS(sv) |= SVt_PVMG;
 }
 
+/*
+=for apidoc sv_unref
+
+Unsets the RV status of the SV, and decrements the reference count of
+whatever was being referenced by the RV.  This can almost be thought of
+as a reversal of C<newSVrv>.  See C<SvROK_off>.
+
+=cut
+*/
+
 void
 Perl_sv_unref(pTHX_ SV *sv)
 {
@@ -4884,6 +5477,15 @@ Perl_sv_tainted(pTHX_ SV *sv)
     return FALSE;
 }
 
+/*
+=for apidoc sv_setpviv
+
+Copies an integer into the given SV, also updating its string value.
+Does not handle 'set' magic.  See C<sv_setpviv_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setpviv(pTHX_ SV *sv, IV iv)
 {
@@ -4895,6 +5497,14 @@ Perl_sv_setpviv(pTHX_ SV *sv, IV iv)
 }
 
 
+/*
+=for apidoc sv_setpviv_mg
+
+Like C<sv_setpviv>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setpviv_mg(pTHX_ SV *sv, IV iv)
 {
@@ -4929,6 +5539,15 @@ Perl_sv_setpvf_mg_nocontext(SV *sv, const char* pat, ...)
 }
 #endif
 
+/*
+=for apidoc sv_setpvf
+
+Processes its arguments like C<sprintf> and sets an SV to the formatted
+output.  Does not handle 'set' magic.  See C<sv_setpvf_mg>.
+
+=cut
+*/
+
 void
 Perl_sv_setpvf(pTHX_ SV *sv, const char* pat, ...)
 {
@@ -4944,6 +5563,14 @@ Perl_sv_vsetpvf(pTHX_ SV *sv, const char* pat, va_list* args)
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
 }
 
+/*
+=for apidoc sv_setpvf_mg
+
+Like C<sv_setpvf>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_setpvf_mg(pTHX_ SV *sv, const char* pat, ...)
 {
@@ -4982,6 +5609,16 @@ Perl_sv_catpvf_mg_nocontext(SV *sv, const char* pat, ...)
 }
 #endif
 
+/*
+=for apidoc sv_catpvf
+
+Processes its arguments like C<sprintf> and appends the formatted output
+to an SV.  Handles 'get' magic, but not 'set' magic.  C<SvSETMAGIC()> must
+typically be called after calling this function to handle 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_catpvf(pTHX_ SV *sv, const char* pat, ...)
 {
@@ -4997,6 +5634,14 @@ Perl_sv_vcatpvf(pTHX_ SV *sv, const char* pat, va_list* args)
     sv_vcatpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
 }
 
+/*
+=for apidoc sv_catpvf_mg
+
+Like C<sv_catpvf>, but also handles 'set' magic.
+
+=cut
+*/
+
 void
 Perl_sv_catpvf_mg(pTHX_ SV *sv, const char* pat, ...)
 {
@@ -5013,6 +5658,15 @@ Perl_sv_vcatpvf_mg(pTHX_ SV *sv, const char* pat, va_list* args)
     SvSETMAGIC(sv);
 }
 
+/*
+=for apidoc sv_vsetpvfn
+
+Works like C<vcatpvfn> but copies the text into the SV instead of
+appending it.
+
+=cut
+*/
+
 void
 Perl_sv_vsetpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted)
 {
@@ -5020,6 +5674,18 @@ Perl_sv_vsetpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     sv_vcatpvfn(sv, pat, patlen, args, svargs, svmax, maybe_tainted);
 }
 
+/*
+=for apidoc sv_vcatpvfn
+
+Processes its arguments like C<vsprintf> and appends the formatted output
+to an SV.  Uses an array of SVs if the C style variable argument list is
+missing (NULL).  When running with taint checks enabled, indicates via
+C<maybe_tainted> if results are untrustworthy (often due to the use of
+locales).
+
+=cut
+*/
+
 void
 Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV **svargs, I32 svmax, bool *maybe_tainted)
 {
@@ -5030,6 +5696,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     STRLEN origlen;
     I32 svix = 0;
     static char nullstr[] = "(null)";
+    SV *argsv;
 
     /* no matter what, this is a string now */
     (void)SvPV_force(sv, origlen);
@@ -5044,12 +5711,18 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                char *s = va_arg(*args, char*);
                sv_catpv(sv, s ? s : nullstr);
            }
-           else if (svix < svmax)
+           else if (svix < svmax) {
                sv_catsv(sv, *svargs);
+               if (DO_UTF8(*svargs))
+                   SvUTF8_on(sv);
+           }
            return;
        case '_':
            if (args) {
-               sv_catsv(sv, va_arg(*args, SV*));
+               argsv = va_arg(*args, SV*);
+               sv_catsv(sv, argsv);
+               if (DO_UTF8(argsv))
+                   SvUTF8_on(sv);
                return;
            }
            /* See comment on '_' below */
@@ -5061,6 +5734,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
     for (p = (char*)pat; p < patend; p = q) {
        bool alt = FALSE;
        bool left = FALSE;
+       bool vectorize = FALSE;
+       bool utf = FALSE;
        char fill = ' ';
        char plus = 0;
        char intsize = 0;
@@ -5068,9 +5743,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        STRLEN zeros = 0;
        bool has_precis = FALSE;
        STRLEN precis = 0;
+       bool is_utf = FALSE;
 
        char esignbuf[4];
-       U8 utf8buf[10];
+       U8 utf8buf[UTF8_MAXLEN];
        STRLEN esignlen = 0;
 
        char *eptr = Nullch;
@@ -5081,6 +5757,10 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        char ebuf[IV_DIG * 4 + NV_DIG + 32];
         /* large enough for "%#.#f" --chip */
        /* what about long double NVs? --jhi */
+
+       SV *vecsv;
+       U8 *vecstr = Null(U8*);
+       STRLEN veclen = 0;
        char c;
        int i;
        unsigned base;
@@ -5090,6 +5770,8 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        STRLEN have;
        STRLEN need;
        STRLEN gap;
+       char *dotstr = ".";
+       STRLEN dotstrlen = 1;
 
        for (q = p; q < patend && *q != '%'; ++q) ;
        if (q > p) {
@@ -5122,6 +5804,30 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                q++;
                continue;
 
+           case '*':                   /* printf("%*vX",":",$ipv6addr) */
+               if (q[1] != 'v')
+                   break;
+               q++;
+               if (args)
+                   vecsv = va_arg(*args, SV*);
+               else if (svix < svmax)
+                   vecsv = svargs[svix++];
+               dotstr = SvPVx(vecsv,dotstrlen);
+               if (DO_UTF8(vecsv))
+                   is_utf = TRUE;
+               /* FALL THROUGH */
+
+           case 'v':
+               vectorize = TRUE;
+               q++;
+               if (args)
+                   vecsv = va_arg(*args, SV*);
+               else if (svix < svmax)
+                   vecsv = svargs[svix++];
+               vecstr = (U8*)SvPVx(vecsv,veclen);
+               utf = DO_UTF8(vecsv);
+               continue;
+
            default:
                break;
            }
@@ -5208,22 +5914,20 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            goto string;
 
        case 'c':
-           if (IN_UTF8) {
-               if (args)
-                   uv = va_arg(*args, int);
-               else
-                   uv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
-
+           if (args)
+               uv = va_arg(*args, int);
+           else
+               uv = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
+           if ((uv > 255 || (uv > 127 && SvUTF8(sv))) && !IN_BYTE) {
                eptr = (char*)utf8buf;
                elen = uv_to_utf8((U8*)eptr, uv) - utf8buf;
-               goto string;
+               is_utf = TRUE;
+           }
+           else {
+               c = (char)uv;
+               eptr = &c;
+               elen = 1;
            }
-           if (args)
-               c = va_arg(*args, int);
-           else
-               c = (svix < svmax) ? SvIVx(svargs[svix++]) : 0;
-           eptr = &c;
-           elen = 1;
            goto string;
 
        case 's':
@@ -5243,16 +5947,18 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                }
            }
            else if (svix < svmax) {
-               eptr = SvPVx(svargs[svix++], elen);
-               if (IN_UTF8) {
+               argsv = svargs[svix++];
+               eptr = SvPVx(argsv, elen);
+               if (DO_UTF8(argsv)) {
                    if (has_precis && precis < elen) {
                        I32 p = precis;
-                       sv_pos_u2b(svargs[svix - 1], &p, 0); /* sticks at end */
+                       sv_pos_u2b(argsv, &p, 0); /* sticks at end */
                        precis = p;
                    }
                    if (width) { /* fudge width (can't fudge elen) */
-                       width += elen - sv_len_utf8(svargs[svix - 1]);
+                       width += elen - sv_len_utf8(argsv);
                    }
+                   is_utf = TRUE;
                }
            }
            goto string;
@@ -5265,9 +5971,13 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
             */
            if (!args)
                goto unknown;
-           eptr = SvPVx(va_arg(*args, SV*), elen);
+           argsv = va_arg(*args,SV*);
+           eptr = SvPVx(argsv, elen);
+           if (DO_UTF8(argsv))
+               is_utf = TRUE;
 
        string:
+           vectorize = FALSE;
            if (has_precis && elen > precis)
                elen = precis;
            break;
@@ -5291,7 +6001,22 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* FALL THROUGH */
        case 'd':
        case 'i':
-           if (args) {
+           if (vectorize) {
+               I32 ulen;
+               if (!veclen) {
+                   vectorize = FALSE;
+                   break;
+               }
+               if (utf)
+                   iv = (IV)utf8_to_uv(vecstr, &ulen);
+               else {
+                   iv = *vecstr;
+                   ulen = 1;
+               }
+               vecstr += ulen;
+               veclen -= ulen;
+           }
+           else if (args) {
                switch (intsize) {
                case 'h':       iv = (short)va_arg(*args, int); break;
                default:        iv = va_arg(*args, int); break;
@@ -5357,7 +6082,23 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            base = 16;
 
        uns_integer:
-           if (args) {
+           if (vectorize) {
+               I32 ulen;
+       vector:
+               if (!veclen) {
+                   vectorize = FALSE;
+                   break;
+               }
+               if (utf)
+                   uv = utf8_to_uv(vecstr, &ulen);
+               else {
+                   uv = *vecstr;
+                   ulen = 1;
+               }
+               vecstr += ulen;
+               veclen -= ulen;
+           }
+           else if (args) {
                switch (intsize) {
                case 'h':  uv = (unsigned short)va_arg(*args, unsigned); break;
                default:   uv = va_arg(*args, unsigned); break;
@@ -5419,13 +6160,13 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                break;
            default:            /* it had better be ten or less */
 #if defined(PERL_Y2KWARN)
-               if (ckWARN(WARN_MISC)) {
+               if (ckWARN(WARN_Y2K)) {
                    STRLEN n;
                    char *s = SvPV(sv,n);
                    if (n >= 2 && s[n-2] == '1' && s[n-1] == '9'
                        && (n == 2 || !isDIGIT(s[n-3])))
                    {
-                       Perl_warner(aTHX_ WARN_MISC,
+                       Perl_warner(aTHX_ WARN_Y2K,
                                    "Possible Y2K bug: %%%c %s",
                                    c, "format string following '19'");
                    }
@@ -5457,6 +6198,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 
            /* This is evil, but floating point is even more evil */
 
+           vectorize = FALSE;
            if (args)
                nv = va_arg(*args, NV);
            else
@@ -5524,6 +6266,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            /* SPECIAL */
 
        case 'n':
+           vectorize = FALSE;
            i = SvCUR(sv) - origlen;
            if (args) {
                switch (intsize) {
@@ -5544,6 +6287,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
 
        default:
       unknown:
+           vectorize = FALSE;
            if (!args && ckWARN(WARN_PRINTF) &&
                  (PL_op->op_type == OP_PRTF || PL_op->op_type == OP_SPRINTF)) {
                SV *msg = sv_newmortal();
@@ -5559,7 +6303,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
                                       (UV)c & 0xFF);
                } else
                    sv_catpv(msg, "end of string");
-               Perl_warner(aTHX_ WARN_PRINTF, "%_", msg); /* yes, this is reentrant */
+               Perl_warner(aTHX_ WARN_PRINTF, "%"SVf, msg); /* yes, this is reentrant */
            }
 
            /* output mangled stuff ... */
@@ -5582,7 +6326,7 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
        need = (have > width ? have : width);
        gap = need - have;
 
-       SvGROW(sv, SvCUR(sv) + need + 1);
+       SvGROW(sv, SvCUR(sv) + need + dotstrlen + 1);
        p = SvEND(sv);
        if (esignlen && fill == '0') {
            for (i = 0; i < esignlen; i++)
@@ -5608,8 +6352,22 @@ Perl_sv_vcatpvfn(pTHX_ SV *sv, const char *pat, STRLEN patlen, va_list *args, SV
            memset(p, ' ', gap);
            p += gap;
        }
+       if (vectorize) {
+           if (veclen) {
+               memcpy(p, dotstr, dotstrlen);
+               p += dotstrlen;
+           }
+           else
+               vectorize = FALSE;              /* done iterating over vecstr */
+       }
+       if (is_utf)
+           SvUTF8_on(sv);
        *p = '\0';
        SvCUR(sv) = p - SvPVX(sv);
+       if (vectorize) {
+           esignlen = 0;
+           goto vector;
+       }
     }
 }
 
@@ -5775,7 +6533,7 @@ void *
 Perl_ptr_table_fetch(pTHX_ PTR_TBL_t *tbl, void *sv)
 {
     PTR_TBL_ENT_t *tblent;
-    UV hash = (UV)sv;
+    UV hash = PTR2UV(sv);
     assert(tbl);
     tblent = tbl->tbl_ary[hash & tbl->tbl_max];
     for (; tblent; tblent = tblent->next) {
@@ -5792,7 +6550,7 @@ Perl_ptr_table_store(pTHX_ PTR_TBL_t *tbl, void *oldv, void *newv)
     /* XXX this may be pessimal on platforms where pointers aren't good
      * hash values e.g. if they grow faster in the most significant
      * bits */
-    UV hash = (UV)oldv;
+    UV hash = PTR2UV(oldv);
     bool i = 1;
 
     assert(tbl);
@@ -5832,7 +6590,7 @@ Perl_ptr_table_split(pTHX_ PTR_TBL_t *tbl)
            continue;
        curentp = ary + oldsize;
        for (entp = ary, ent = *ary; ent; ent = *entp) {
-           if ((newsize & (UV)ent->oldval) != i) {
+           if ((newsize & PTR2UV(ent->oldval)) != i) {
                *entp = ent->next;
                ent->next = *curentp;
                *curentp = ent;
@@ -6204,7 +6962,7 @@ Perl_cx_dup(pTHX_ PERL_CONTEXT *cxs, I32 ix, I32 max)
            case CXt_EVAL:
                ncx->blk_eval.old_in_eval = cx->blk_eval.old_in_eval;
                ncx->blk_eval.old_op_type = cx->blk_eval.old_op_type;
-               ncx->blk_eval.old_name  = SAVEPV(cx->blk_eval.old_name);
+               ncx->blk_eval.old_namesv = sv_dup_inc(cx->blk_eval.old_namesv);
                ncx->blk_eval.old_eval_root = cx->blk_eval.old_eval_root;
                ncx->blk_eval.cur_text  = sv_dup(cx->blk_eval.cur_text);
                break;
@@ -6445,8 +7203,22 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl)
            break;
        case SAVEt_FREEOP:
            ptr = POPPTR(ss,ix);
-           if (ptr && (((OP*)ptr)->op_private & OPpREFCOUNTED))
-               TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
+           if (ptr && (((OP*)ptr)->op_private & OPpREFCOUNTED)) {
+               /* these are assumed to be refcounted properly */
+               switch (((OP*)ptr)->op_type) {
+               case OP_LEAVESUB:
+               case OP_LEAVESUBLV:
+               case OP_LEAVEEVAL:
+               case OP_LEAVE:
+               case OP_SCOPE:
+               case OP_LEAVEWRITE:
+                   TOPPTR(nss,ix) = any_dup(ptr, proto_perl);
+                   break;
+               default:
+                   TOPPTR(nss,ix) = Nullop;
+                   break;
+               }
+           }
            else
                TOPPTR(nss,ix) = Nullop;
            break;
@@ -6470,13 +7242,13 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl)
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);  /* XXX quite arbitrary */
            dptr = POPDPTR(ss,ix);
-           TOPDPTR(nss,ix) = (void (*)(void*))any_dup(dptr, proto_perl);
+           TOPDPTR(nss,ix) = (void (*)(void*))any_dup((void *)dptr, proto_perl);
            break;
        case SAVEt_DESTRUCTOR_X:
            ptr = POPPTR(ss,ix);
            TOPPTR(nss,ix) = any_dup(ptr, proto_perl);  /* XXX quite arbitrary */
            dxptr = POPDXPTR(ss,ix);
-           TOPDXPTR(nss,ix) = (void (*)(pTHXo_ void*))any_dup(dxptr, proto_perl);
+           TOPDXPTR(nss,ix) = (void (*)(pTHXo_ void*))any_dup((void *)dxptr, proto_perl);
            break;
        case SAVEt_REGCONTEXT:
        case SAVEt_ALLOC:
@@ -6512,6 +7284,10 @@ Perl_ss_dup(pTHX_ PerlInterpreter *proto_perl)
            i = POPINT(ss,ix);
            TOPINT(nss,ix) = i;
            break;
+       case SAVEt_COMPPAD:
+           av = (AV*)POPPTR(ss,ix);
+           TOPPTR(nss,ix) = av_dup(av);
+           break;
        default:
            Perl_croak(aTHX_ "panic: ss_dup inconsistency");
        }
@@ -6696,7 +7472,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* switches */
     PL_minus_c         = proto_perl->Iminus_c;
-    Copy(proto_perl->Ipatchlevel, PL_patchlevel, 10, char);
+    PL_patchlevel      = sv_dup_inc(proto_perl->Ipatchlevel);
     PL_localpatches    = proto_perl->Ilocalpatches;
     PL_splitstr                = proto_perl->Isplitstr;
     PL_preprocess      = proto_perl->Ipreprocess;
@@ -6760,7 +7536,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_beginav         = av_dup_inc(proto_perl->Ibeginav);
     PL_endav           = av_dup_inc(proto_perl->Iendav);
-    PL_stopav          = av_dup_inc(proto_perl->Istopav);
+    PL_checkav         = av_dup_inc(proto_perl->Icheckav);
     PL_initav          = av_dup_inc(proto_perl->Iinitav);
 
     PL_sub_generation  = proto_perl->Isub_generation;
@@ -6836,7 +7612,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     /* more statics moved here */
     PL_generation      = proto_perl->Igeneration;
     PL_DBcv            = cv_dup(proto_perl->IDBcv);
-    PL_archpat_auto    = SAVEPV(proto_perl->Iarchpat_auto);
 
     PL_in_clean_objs   = proto_perl->Iin_clean_objs;
     PL_in_clean_all    = proto_perl->Iin_clean_all;
@@ -7100,7 +7875,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     PL_dirty           = proto_perl->Tdirty;
     PL_localizing      = proto_perl->Tlocalizing;
 
+#ifdef PERL_FLEXIBLE_EXCEPTIONS
     PL_protect         = proto_perl->Tprotect;
+#endif
     PL_errors          = sv_dup_inc(proto_perl->Terrors);
     PL_av_fetch_sv     = Nullsv;
     PL_hv_fetch_sv     = Nullsv;
@@ -7231,7 +8008,7 @@ do_clean_objs(pTHXo_ SV *sv)
 static void
 do_clean_named_objs(pTHXo_ SV *sv)
 {
-    if (SvTYPE(sv) == SVt_PVGV) {
+    if (SvTYPE(sv) == SVt_PVGV && GvGP(sv)) {
        if ( SvOBJECT(GvSV(sv)) ||
             GvAV(sv) && SvOBJECT(GvAV(sv)) ||
             GvHV(sv) && SvOBJECT(GvHV(sv)) ||