This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add a ; that 26281 was lacking.
[perl5.git] / util.c
diff --git a/util.c b/util.c
index 4da13d4..5b8aed0 100644 (file)
--- a/util.c
+++ b/util.c
@@ -57,6 +57,16 @@ int putenv(char *);
  * XXX This advice seems to be widely ignored :-(   --AD  August 1996.
  */
 
+static char *
+S_write_no_mem(pTHX)
+{
+    /* Can't use PerlIO to write as it allocates memory */
+    PerlLIO_write(PerlIO_fileno(Perl_error_log),
+                 PL_no_mem, strlen(PL_no_mem));
+    my_exit(1);
+    NORETURN_FUNCTION_END;
+}
+
 /* paranoid version of system's malloc() */
 
 Malloc_t
@@ -71,6 +81,9 @@ Perl_safesysmalloc(MEM_SIZE size)
            my_exit(1);
        }
 #endif /* HAS_64K_LIMIT */
+#ifdef PERL_TRACK_MEMPOOL
+    size += sTHX;
+#endif
 #ifdef DEBUGGING
     if ((long)size < 0)
        Perl_croak_nocontext("panic: malloc");
@@ -78,16 +91,17 @@ Perl_safesysmalloc(MEM_SIZE size)
     ptr = (Malloc_t)PerlMem_malloc(size?size:1);       /* malloc(0) is NASTY on our system */
     PERL_ALLOC_CHECK(ptr);
     DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) malloc %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)size));
-    if (ptr != Nullch)
+    if (ptr != Nullch) {
+#ifdef PERL_TRACK_MEMPOOL
+        *(tTHX*)ptr = aTHX;
+        ptr = (Malloc_t)((char*)ptr+sTHX);
+#endif
        return ptr;
+}
     else if (PL_nomemok)
        return Nullch;
     else {
-       /* Can't use PerlIO to write as it allocates memory */
-       PerlLIO_write(PerlIO_fileno(Perl_error_log),
-                     PL_no_mem, strlen(PL_no_mem));
-       my_exit(1);
-       return Nullch;
+       return write_no_mem();
     }
     /*NOTREACHED*/
 }
@@ -117,6 +131,14 @@ Perl_safesysrealloc(Malloc_t where,MEM_SIZE size)
 
     if (!where)
        return safesysmalloc(size);
+#ifdef PERL_TRACK_MEMPOOL
+    where = (Malloc_t)((char*)where-sTHX);
+    size += sTHX;
+    if (*(tTHX*)where != aTHX) {
+       /* int *nowhere = NULL; *nowhere = 0; */
+        Perl_croak_nocontext("panic: realloc from wrong pool");
+    }
+#endif
 #ifdef DEBUGGING
     if ((long)size < 0)
        Perl_croak_nocontext("panic: realloc");
@@ -127,16 +149,16 @@ Perl_safesysrealloc(Malloc_t where,MEM_SIZE size)
     DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) rfree\n",PTR2UV(where),(long)PL_an++));
     DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) realloc %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)size));
 
-    if (ptr != Nullch)
+    if (ptr != Nullch) {
+#ifdef PERL_TRACK_MEMPOOL
+        ptr = (Malloc_t)((char*)ptr+sTHX);
+#endif
        return ptr;
+    }
     else if (PL_nomemok)
        return Nullch;
     else {
-       /* Can't use PerlIO to write as it allocates memory */
-       PerlLIO_write(PerlIO_fileno(Perl_error_log),
-                     PL_no_mem, strlen(PL_no_mem));
-       my_exit(1);
-       return Nullch;
+       return write_no_mem();
     }
     /*NOTREACHED*/
 }
@@ -147,11 +169,18 @@ Free_t
 Perl_safesysfree(Malloc_t where)
 {
     dVAR;
-#ifdef PERL_IMPLICIT_SYS
+#if defined(PERL_IMPLICIT_SYS) || defined(PERL_TRACK_MEMPOOL)
     dTHX;
 #endif
     DEBUG_m( PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) free\n",PTR2UV(where),(long)PL_an++));
     if (where) {
+#ifdef PERL_TRACK_MEMPOOL
+        where = (Malloc_t)((char*)where-sTHX);
+        if (*(tTHX*)where != aTHX) {
+           /* int *nowhere = NULL; *nowhere = 0; */
+            Perl_croak_nocontext("panic: free from wrong pool");
+       }
+#endif
        PerlMem_free(where);
     }
 }
@@ -176,23 +205,23 @@ Perl_safesyscalloc(MEM_SIZE count, MEM_SIZE size)
        Perl_croak_nocontext("panic: calloc");
 #endif
     size *= count;
+#ifdef PERL_TRACK_MEMPOOL
+    size += sTHX;
+#endif
     ptr = (Malloc_t)PerlMem_malloc(size?size:1);       /* malloc(0) is NASTY on our system */
     PERL_ALLOC_CHECK(ptr);
     DEBUG_m(PerlIO_printf(Perl_debug_log, "0x%"UVxf": (%05ld) calloc %ld x %ld bytes\n",PTR2UV(ptr),(long)PL_an++,(long)count,(long)size));
     if (ptr != Nullch) {
        memset((void*)ptr, 0, size);
+#ifdef PERL_TRACK_MEMPOOL
+        *(tTHX*)ptr = aTHX;
+        ptr = (Malloc_t)((char*)ptr+sTHX);
+#endif
        return ptr;
     }
     else if (PL_nomemok)
        return Nullch;
-    else {
-       /* Can't use PerlIO to write as it allocates memory */
-       PerlLIO_write(PerlIO_fileno(Perl_error_log),
-                     PL_no_mem, strlen(PL_no_mem));
-       my_exit(1);
-       return Nullch;
-    }
-    /*NOTREACHED*/
+    return write_no_mem();
 }
 
 /* These must be defined when not using Perl's malloc for binary
@@ -291,7 +320,7 @@ char *
 Perl_ninstr(pTHX_ register const char *big, register const char *bigend, const char *little, const char *lend)
 {
     register const I32 first = *little;
-    register const char *littleend = lend;
+    register const char * const littleend = lend;
 
     if (!first && little >= littleend)
        return (char*)big;
@@ -321,7 +350,7 @@ Perl_rninstr(pTHX_ register const char *big, const char *bigend, const char *lit
 {
     register const char *bigbeg;
     register const I32 first = *little;
-    register const char *littleend = lend;
+    register const char * const littleend = lend;
 
     if (!first && little >= littleend)
        return (char*)bigend;
@@ -365,15 +394,14 @@ Analyses the string in order to make fast searches on it using fbm_instr()
 void
 Perl_fbm_compile(pTHX_ SV *sv, U32 flags)
 {
-    const register U8 *s;
-    register U8 *table;
+    register const U8 *s;
     register U32 i;
     STRLEN len;
     I32 rarest = 0;
     U32 frequency = 256;
 
     if (flags & FBMcf_TAIL) {
-       MAGIC *mg = SvUTF8(sv) && SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL;
+       MAGIC * const mg = SvUTF8(sv) && SvMAGICAL(sv) ? mg_find(sv, PERL_MAGIC_utf8) : NULL;
        sv_catpvn(sv, "\n", 1);         /* Taken into account in fbm_instr() */
        if (mg && mg->mg_len >= 0)
            mg->mg_len++;
@@ -385,6 +413,7 @@ Perl_fbm_compile(pTHX_ SV *sv, U32 flags)
     if (len > 2) {
        const unsigned char *sb;
        const U8 mlen = (len>255) ? 255 : (U8)len;
+       register U8 *table;
 
        Sv_Grow(sv, len + 256 + FBM_TABLE_OFFSET);
        table = (unsigned char*)(SvPVX_mutable(sv) + len + FBM_TABLE_OFFSET);
@@ -552,7 +581,7 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
        return Nullch;
     }
     if (SvTYPE(littlestr) != SVt_PVBM || !SvVALID(littlestr)) {
-       char *b = ninstr((char*)big,(char*)bigend,
+       char * const b = ninstr((char*)big,(char*)bigend,
                         (char*)little, (char*)little + littlelen);
 
        if (!b && SvTAIL(littlestr)) {  /* Automatically multiline!  */
@@ -569,8 +598,8 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
     }
 
     {  /* Do actual FBM.  */
-       register const unsigned char *table = little + littlelen + FBM_TABLE_OFFSET;
-       const register unsigned char *oldlittle;
+       register const unsigned char * const table = little + littlelen + FBM_TABLE_OFFSET;
+       register const unsigned char *oldlittle;
 
        if (littlelen > (STRLEN)(bigend - big))
            return Nullch;
@@ -632,13 +661,13 @@ Perl_fbm_instr(pTHX_ unsigned char *big, register unsigned char *bigend, SV *lit
 char *
 Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift, I32 *old_posp, I32 last)
 {
-    const register unsigned char *big;
+    register const unsigned char *big;
     register I32 pos;
     register I32 previous;
     register I32 first;
-    const register unsigned char *little;
+    register const unsigned char *little;
     register I32 stop_pos;
-    const register unsigned char *littleend;
+    register const unsigned char *littleend;
     I32 found = 0;
 
     if (*old_posp == -1
@@ -680,7 +709,7 @@ Perl_screaminstr(pTHX_ SV *bigstr, SV *littlestr, I32 start_shift, I32 end_shift
     }
     big -= previous;
     do {
-       const register unsigned char *s, *x;
+       register const unsigned char *s, *x;
        if (pos >= stop_pos) break;
        if (big[pos] != first)
            continue;
@@ -764,7 +793,7 @@ Perl_savepv(pTHX_ const char *pv)
     else {
        char *newaddr;
        const STRLEN pvlen = strlen(pv)+1;
-       New(902,newaddr,pvlen,char);
+       Newx(newaddr,pvlen,char);
        return memcpy(newaddr,pv,pvlen);
     }
 
@@ -788,7 +817,7 @@ Perl_savepvn(pTHX_ const char *pv, register I32 len)
 {
     register char *newaddr;
 
-    New(903,newaddr,len+1,char);
+    Newx(newaddr,len+1,char);
     /* Give a meaning to NULL pointer mainly for the use in sv_magic() */
     if (pv) {
        /* might not be null terminated */
@@ -819,9 +848,7 @@ Perl_savesharedpv(pTHX_ const char *pv)
     pvlen = strlen(pv)+1;
     newaddr = (char*)PerlMemShared_malloc(pvlen);
     if (!newaddr) {
-       PerlLIO_write(PerlIO_fileno(Perl_error_log),
-                     PL_no_mem, strlen(PL_no_mem));
-       my_exit(1);
+       return write_no_mem();
     }
     return memcpy(newaddr,pv,pvlen);
 }
@@ -839,11 +866,11 @@ char *
 Perl_savesvpv(pTHX_ SV *sv)
 {
     STRLEN len;
-    const char *pv = SvPV_const(sv, len);
+    const char * const pv = SvPV_const(sv, len);
     register char *newaddr;
 
     ++len;
-    New(903,newaddr,len,char);
+    Newx(newaddr,len,char);
     return (char *) CopyD(pv,newaddr,len,char);
 }
 
@@ -863,8 +890,8 @@ S_mess_alloc(pTHX)
        return PL_mess_sv;
 
     /* Create as PVMG now, to avoid any upgrading later */
-    New(905, sv, 1, SV);
-    Newz(905, any, 1, XPVMG);
+    Newx(sv, 1, SV);
+    Newxz(any, 1, XPVMG);
     SvFLAGS(sv) = SVt_PVMG;
     SvANY(sv) = (void*)any;
     SvPV_set(sv, 0);
@@ -921,7 +948,7 @@ Perl_form(pTHX_ const char* pat, ...)
 char *
 Perl_vform(pTHX_ const char *pat, va_list *args)
 {
-    SV *sv = mess_alloc();
+    SV * const sv = mess_alloc();
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
     return SvPVX(sv);
 }
@@ -985,7 +1012,7 @@ S_closest_cop(pTHX_ COP *cop, const OP *o)
 SV *
 Perl_vmess(pTHX_ const char *pat, va_list *args)
 {
-    SV *sv = mess_alloc();
+    SV * const sv = mess_alloc();
     static const char dgd[] = " during global destruction.\n";
 
     sv_vsetpvfn(sv, pat, strlen(pat), args, Null(SV**), 0, Null(bool*));
@@ -1074,7 +1101,7 @@ S_vdie_common(pTHX_ const char *message, STRLEN msglen, I32 utf8)
     GV *gv;
     CV *cv;
     /* sv_2cv might call Perl_croak() */
-    SV *olddiehook = PL_diehook;
+    SV * const olddiehook = PL_diehook;
 
     assert(PL_diehook);
     ENTER;
@@ -1116,7 +1143,7 @@ S_vdie_croak_common(pTHX_ const char* pat, va_list* args, STRLEN* msglen,
     const char *message;
 
     if (pat) {
-       SV *msv = vmess(pat, args);
+       SV * const msv = vmess(pat, args);
        if (PL_errors && SvCUR(PL_errors)) {
            sv_catsv(PL_errors, msv);
            message = SvPV_const(PL_errors, *msglen);
@@ -1151,7 +1178,7 @@ Perl_vdie(pTHX_ const char* pat, va_list *args)
                          "%p: die: curstack = %p, mainstack = %p\n",
                          thr, PL_curstack, PL_mainstack));
 
-    message = S_vdie_croak_common(aTHX_ pat, args, &msglen, &utf8);
+    message = vdie_croak_common(pat, args, &msglen, &utf8);
 
     PL_restartop = die_where(message, msglen);
     SvFLAGS(ERRSV) |= utf8;
@@ -1278,6 +1305,8 @@ Perl_vwarn(pTHX_ const char* pat, va_list *args)
            SV *msg;
 
            ENTER;
+           SAVESPTR(PL_warnhook);
+           PL_warnhook = Nullsv;
            save_re_context();
            msg = newSVpvn(message, msglen);
            SvFLAGS(msg) |= utf8;
@@ -1356,7 +1385,7 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
     if (ckDEAD(err)) {
        SV * const msv = vmess(pat, args);
        STRLEN msglen;
-       const char *message = SvPV_const(msv, msglen);
+       const char * const message = SvPV_const(msv, msglen);
        const I32 utf8 = SvUTF8(msv);
 
        if (PL_diehook) {
@@ -1376,6 +1405,58 @@ Perl_vwarner(pTHX_ U32  err, const char* pat, va_list* args)
     }
 }
 
+/* implements the ckWARN? macros */
+
+bool
+Perl_ckwarn(pTHX_ U32 w)
+{
+    return
+       (
+              isLEXWARN_on
+           && PL_curcop->cop_warnings != pWARN_NONE
+           && (
+                  PL_curcop->cop_warnings == pWARN_ALL
+               || isWARN_on(PL_curcop->cop_warnings, unpackWARN1(w))
+               || (unpackWARN2(w) &&
+                    isWARN_on(PL_curcop->cop_warnings, unpackWARN2(w)))
+               || (unpackWARN3(w) &&
+                    isWARN_on(PL_curcop->cop_warnings, unpackWARN3(w)))
+               || (unpackWARN4(w) &&
+                    isWARN_on(PL_curcop->cop_warnings, unpackWARN4(w)))
+               )
+       )
+       ||
+       (
+           isLEXWARN_off && PL_dowarn & G_WARN_ON
+       )
+       ;
+}
+
+/* implements the ckWARN?_d macro */
+
+bool
+Perl_ckwarn_d(pTHX_ U32 w)
+{
+    return
+          isLEXWARN_off
+       || PL_curcop->cop_warnings == pWARN_ALL
+       || (
+             PL_curcop->cop_warnings != pWARN_NONE 
+          && (
+                  isWARN_on(PL_curcop->cop_warnings, unpackWARN1(w))
+             || (unpackWARN2(w) &&
+                  isWARN_on(PL_curcop->cop_warnings, unpackWARN2(w)))
+             || (unpackWARN3(w) &&
+                  isWARN_on(PL_curcop->cop_warnings, unpackWARN3(w)))
+             || (unpackWARN4(w) &&
+                  isWARN_on(PL_curcop->cop_warnings, unpackWARN4(w)))
+             )
+          )
+       ;
+}
+
+
+
 /* since we've already done strlen() for both nam and val
  * we can use that info to make things faster than
  * sprintf(s, "%s=%s", nam, val)
@@ -1441,20 +1522,41 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
     my_setenv_format(environ[i], nam, nlen, val, vlen);
     } else {
 # endif
-#   if defined(__CYGWIN__) || defined(EPOC) || defined(SYMBIAN) 
-    setenv(nam, val, 1);
+#   if defined(__CYGWIN__) || defined(EPOC) || defined(__SYMBIAN32__)
+#       if defined(HAS_UNSETENV)
+        if (val == NULL) {
+            (void)unsetenv(nam);
+        } else {
+            (void)setenv(nam, val, 1);
+        }
+#       else /* ! HAS_UNSETENV */
+        (void)setenv(nam, val, 1);
+#       endif /* HAS_UNSETENV */
 #   else
-    char *new_env;
-    const int nlen = strlen(nam);
-    int vlen;
-    if (!val) {
-       val = "";
-    }
-    vlen = strlen(val);
-    new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
-    /* all that work just for this */
-    my_setenv_format(new_env, nam, nlen, val, vlen);
-    (void)putenv(new_env);
+#       if defined(HAS_UNSETENV)
+        if (val == NULL) {
+            (void)unsetenv(nam);
+        } else {
+           const int nlen = strlen(nam);
+           const int vlen = strlen(val);
+           char * const new_env =
+                (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
+            my_setenv_format(new_env, nam, nlen, val, vlen);
+            (void)putenv(new_env);
+        }
+#       else /* ! HAS_UNSETENV */
+        char *new_env;
+       const int nlen = strlen(nam);
+       int vlen;
+        if (!val) {
+          val = "";
+        }
+        vlen = strlen(val);
+        new_env = (char*)safesysmalloc((nlen + vlen + 2) * sizeof(char));
+        /* all that work just for this */
+        my_setenv_format(new_env, nam, nlen, val, vlen);
+        (void)putenv(new_env);
+#       endif /* HAS_UNSETENV */
 #   endif /* __CYGWIN__ */
 #ifndef PERL_USE_SAFE_PUTENV
     }
@@ -1476,7 +1578,7 @@ Perl_my_setenv(pTHX_ const char *nam, const char *val)
        val = "";
     }
     vlen = strlen(val);
-    New(904, envstr, nlen+vlen+2, char);
+    Newx(envstr, nlen+vlen+2, char);
     my_setenv_format(envstr, nam, nlen, val, vlen);
     (void)PerlEnv_putenv(envstr);
     Safefree(envstr);
@@ -1489,7 +1591,7 @@ I32
 Perl_setenv_getix(pTHX_ const char *nam)
 {
     register I32 i;
-    const register I32 len = strlen(nam);
+    register const I32 len = strlen(nam);
 
     for (i = 0; environ[i]; i++) {
        if (
@@ -1509,7 +1611,7 @@ Perl_setenv_getix(pTHX_ const char *nam)
 
 #ifdef UNLINK_ALL_VERSIONS
 I32
-Perl_unlnk(pTHX_ char *f)      /* unlink all versions of a file */
+Perl_unlnk(pTHX_ const char *f)        /* unlink all versions of a file */
 {
     I32 i;
 
@@ -1523,7 +1625,7 @@ Perl_unlnk(pTHX_ char *f) /* unlink all versions of a file */
 char *
 Perl_my_bcopy(register const char *from,register char *to,register I32 len)
 {
-    char *retval = to;
+    char * const retval = to;
 
     if (from - to >= 0) {
        while (len--)
@@ -1544,7 +1646,7 @@ Perl_my_bcopy(register const char *from,register char *to,register I32 len)
 void *
 Perl_my_memset(register char *loc, register I32 ch, register I32 len)
 {
-    char *retval = loc;
+    char * const retval = loc;
 
     while (len--)
        *loc++ = ch;
@@ -1557,7 +1659,7 @@ Perl_my_memset(register char *loc, register I32 ch, register I32 len)
 char *
 Perl_my_bzero(register char *loc, register I32 len)
 {
-    char *retval = loc;
+    char * const retval = loc;
 
     while (len--)
        *loc++ = 0;
@@ -2069,13 +2171,13 @@ Perl_my_popen_list(pTHX_ char *mode, int n, SV **args)
     /* VMS' my_popen() is in VMS.c, same with OS/2. */
 #if (!defined(DOSISH) || defined(HAS_FORK) || defined(AMIGAOS)) && !defined(VMS) && !defined(__OPEN_VM) && !defined(EPOC) && !defined(MACOS_TRADITIONAL)
 PerlIO *
-Perl_my_popen(pTHX_ char *cmd, char *mode)
+Perl_my_popen(pTHX_ const char *cmd, const char *mode)
 {
     int p[2];
     register I32 This, that;
     register Pid_t pid;
     SV *sv;
-    I32 doexec = !(*cmd == '-' && cmd[1] == '\0');
+    const I32 doexec = !(*cmd == '-' && cmd[1] == '\0');
     I32 did_pipes = 0;
     int pp[2];
 
@@ -2158,7 +2260,9 @@ Perl_my_popen(pTHX_ char *cmd, char *mode)
        PL_ppid = (IV)getppid();
 #endif
        PL_forkprocess = 0;
+#ifdef PERL_USES_PL_PIDSTATUS
        hv_clear(PL_pidstatus); /* we have no children */
+#endif
        return Nullfp;
 #undef THIS
 #undef THAT
@@ -2359,10 +2463,10 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
 #ifdef USE_ITHREADS
     /* only "parent" interpreter can diddle signals */
     if (PL_curinterp != aTHX)
-       return SIG_ERR;
+       return (Sighandler_t) SIG_ERR;
 #endif
 
-    act.sa_handler = handler;
+    act.sa_handler = (void(*)(int))handler;
     sigemptyset(&act.sa_mask);
     act.sa_flags = 0;
 #ifdef SA_RESTART
@@ -2370,13 +2474,13 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
         act.sa_flags |= SA_RESTART;    /* SVR4, 4.3+BSD */
 #endif
 #if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
-    if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
+    if (signo == SIGCHLD && handler == (Sighandler_t) SIG_IGN)
        act.sa_flags |= SA_NOCLDWAIT;
 #endif
     if (sigaction(signo, &act, &oact) == -1)
-       return SIG_ERR;
+       return (Sighandler_t) SIG_ERR;
     else
-       return oact.sa_handler;
+       return (Sighandler_t) oact.sa_handler;
 }
 
 Sighandler_t
@@ -2385,9 +2489,9 @@ Perl_rsignal_state(pTHX_ int signo)
     struct sigaction oact;
 
     if (sigaction(signo, (struct sigaction *)NULL, &oact) == -1)
-       return SIG_ERR;
+       return (Sighandler_t) SIG_ERR;
     else
-       return oact.sa_handler;
+       return (Sighandler_t) oact.sa_handler;
 }
 
 int
@@ -2402,7 +2506,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
        return -1;
 #endif
 
-    act.sa_handler = handler;
+    act.sa_handler = (void(*)(int))handler;
     sigemptyset(&act.sa_mask);
     act.sa_flags = 0;
 #ifdef SA_RESTART
@@ -2410,7 +2514,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
         act.sa_flags |= SA_RESTART;    /* SVR4, 4.3+BSD */
 #endif
 #if defined(SA_NOCLDWAIT) && !defined(BSDish) /* See [perl #18849] */
-    if (signo == SIGCHLD && handler == (Sighandler_t)SIG_IGN)
+    if (signo == SIGCHLD && handler == (Sighandler_t) SIG_IGN)
        act.sa_flags |= SA_NOCLDWAIT;
 #endif
     return sigaction(signo, &act, save);
@@ -2437,7 +2541,7 @@ Perl_rsignal(pTHX_ int signo, Sighandler_t handler)
 #if defined(USE_ITHREADS) && !defined(WIN32)
     /* only "parent" interpreter can diddle signals */
     if (PL_curinterp != aTHX)
-       return SIG_ERR;
+       return (Sighandler_t) SIG_ERR;
 #endif
 
     return PerlProc_signal(signo, handler);
@@ -2460,7 +2564,7 @@ Perl_rsignal_state(pTHX_ int signo)
 #if defined(USE_ITHREADS) && !defined(WIN32)
     /* only "parent" interpreter can diddle signals */
     if (PL_curinterp != aTHX)
-       return SIG_ERR;
+       return (Sighandler_t) SIG_ERR;
 #endif
 
     PL_sig_trapped = 0;
@@ -2480,7 +2584,7 @@ Perl_rsignal_save(pTHX_ int signo, Sighandler_t handler, Sigsave_t *save)
        return -1;
 #endif
     *save = PerlProc_signal(signo, handler);
-    return (*save == SIG_ERR) ? -1 : 0;
+    return (*save == (Sighandler_t) SIG_ERR) ? -1 : 0;
 }
 
 int
@@ -2491,7 +2595,7 @@ Perl_rsignal_restore(pTHX_ int signo, Sigsave_t *save)
     if (PL_curinterp != aTHX)
        return -1;
 #endif
-    return (PerlProc_signal(signo, *save) == SIG_ERR) ? -1 : 0;
+    return (PerlProc_signal(signo, *save) == (Sighandler_t) SIG_ERR) ? -1 : 0;
 }
 
 #endif /* !HAS_SIGACTION */
@@ -2534,9 +2638,9 @@ Perl_my_pclose(pTHX_ PerlIO *ptr)
     if(PerlProc_kill(pid, 0) < 0) { return(pid); }   /* HOM 12/23/91 */
 #endif
 #ifndef PERL_MICRO
-    rsignal_save(SIGHUP, SIG_IGN, &hstat);
-    rsignal_save(SIGINT, SIG_IGN, &istat);
-    rsignal_save(SIGQUIT, SIG_IGN, &qstat);
+    rsignal_save(SIGHUP,  (Sighandler_t) SIG_IGN, &hstat);
+    rsignal_save(SIGINT,  (Sighandler_t) SIG_IGN, &istat);
+    rsignal_save(SIGQUIT, (Sighandler_t) SIG_IGN, &qstat);
 #endif
     do {
        pid2 = wait4pid(pid, &status, 0);
@@ -2561,17 +2665,16 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
     I32 result = 0;
     if (!pid)
        return -1;
-#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME)
+#ifdef PERL_USES_PL_PIDSTATUS
     {
-       char spid[TYPE_CHARS(IV)];
-
        if (pid > 0) {
-           SV** svp;
-           sprintf(spid, "%"IVdf, (IV)pid);
-           svp = hv_fetch(PL_pidstatus,spid,strlen(spid),FALSE);
+           /* The keys in PL_pidstatus are now the raw 4 (or 8) bytes of the
+              pid, rather than a string form.  */
+           SV * const * const svp = hv_fetch(PL_pidstatus,(const char*) &pid,sizeof(Pid_t),FALSE);
            if (svp && *svp != &PL_sv_undef) {
                *statusp = SvIVX(*svp);
-               (void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD);
+               (void)hv_delete(PL_pidstatus,(const char*) &pid,sizeof(Pid_t),
+                               G_DISCARD);
                return pid;
            }
        }
@@ -2580,12 +2683,21 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
 
            hv_iterinit(PL_pidstatus);
            if ((entry = hv_iternext(PL_pidstatus))) {
-               SV *sv = hv_iterval(PL_pidstatus,entry);
+               SV * const sv = hv_iterval(PL_pidstatus,entry);
+               I32 len;
+               const char * const spid = hv_iterkey(entry,&len);
 
-               pid = atoi(hv_iterkey(entry,(I32*)statusp));
+               assert (len == sizeof(Pid_t));
+               memcpy((char *)&pid, spid, len);
                *statusp = SvIVX(sv);
-               sprintf(spid, "%"IVdf, (IV)pid);
-               (void)hv_delete(PL_pidstatus,spid,strlen(spid),G_DISCARD);
+               /* The hash iterator is currently on this entry, so simply
+                  calling hv_delete would trigger the lazy delete, which on
+                  aggregate does more work, beacuse next call to hv_iterinit()
+                  would spot the flag, and have to call the delete routine,
+                  while in the meantime any new entries can't re-use that
+                  memory.  */
+               hv_iterinit(PL_pidstatus);
+               (void)hv_delete(PL_pidstatus,spid,len,G_DISCARD);
                return pid;
            }
        }
@@ -2603,7 +2715,7 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
     result = wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
     goto finish;
 #endif
-#if !defined(HAS_WAITPID) && !defined(HAS_WAIT4) || defined(HAS_WAITPID_RUNTIME)
+#ifdef PERL_USES_PL_PIDSTATUS
 #if defined(HAS_WAITPID) && defined(HAS_WAITPID_RUNTIME)
   hard_way:
 #endif
@@ -2628,18 +2740,18 @@ Perl_wait4pid(pTHX_ Pid_t pid, int *statusp, int flags)
 }
 #endif /* !DOSISH || OS2 || WIN32 || NETWARE */
 
+#ifdef PERL_USES_PL_PIDSTATUS
 void
 Perl_pidgone(pTHX_ Pid_t pid, int status)
 {
     register SV *sv;
-    char spid[TYPE_CHARS(IV)];
 
-    sprintf(spid, "%"IVdf, (IV)pid);
-    sv = *hv_fetch(PL_pidstatus,spid,strlen(spid),TRUE);
+    sv = *hv_fetch(PL_pidstatus,(const char*)&pid,sizeof(Pid_t),TRUE);
     SvUPGRADE(sv,SVt_IV);
     SvIV_set(sv, status);
     return;
 }
+#endif
 
 #if defined(atarist) || defined(OS2) || defined(EPOC)
 int pclose();
@@ -2653,8 +2765,8 @@ Perl_my_pclose(pTHX_ PerlIO *ptr)
 #endif
 {
     /* Needs work for PerlIO ! */
-    FILE *f = PerlIO_findFILE(ptr);
-    I32 result = pclose(f);
+    FILE * const f = PerlIO_findFILE(ptr);
+    const I32 result = pclose(f);
     PerlIO_releaseFILE(ptr,f);
     return result;
 }
@@ -2666,7 +2778,7 @@ I32
 Perl_my_pclose(pTHX_ PerlIO *ptr)
 {
     /* Needs work for PerlIO ! */
-    FILE *f = PerlIO_findFILE(ptr);
+    FILE * const f = PerlIO_findFILE(ptr);
     I32 result = djgpp_pclose(f);
     result = (result << 8) & 0xff00;
     PerlIO_releaseFILE(ptr,f);
@@ -2678,7 +2790,7 @@ void
 Perl_repeatcpy(pTHX_ register char *to, register const char *from, I32 len, register I32 count)
 {
     register I32 todo;
-    register const char *frombase = from;
+    register const char * const frombase = from;
 
     if (len == 1) {
        register const char c = *from;
@@ -2702,7 +2814,7 @@ Perl_same_dirent(pTHX_ const char *a, const char *b)
     char *fb = strrchr(b,'/');
     Stat_t tmpstatbuf1;
     Stat_t tmpstatbuf2;
-    SV *tmpsv = sv_newmortal();
+    SV * const tmpsv = sv_newmortal();
 
     if (fa)
        fa++;
@@ -2732,7 +2844,8 @@ Perl_same_dirent(pTHX_ const char *a, const char *b)
 #endif /* !HAS_RENAME */
 
 char*
-Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **search_ext, I32 flags)
+Perl_find_script(pTHX_ const char *scriptname, bool dosearch,
+                const char *const *const search_ext, I32 flags)
 {
     const char *xfound = Nullch;
     char *xfailed = Nullch;
@@ -2754,8 +2867,8 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **searc
 #endif
     /* additional extensions to try in each dir if scriptname not found */
 #ifdef SEARCH_EXTS
-    const char *exts[] = { SEARCH_EXTS };
-    const char **ext = search_ext ? search_ext : exts;
+    static const char *const exts[] = { SEARCH_EXTS };
+    const char *const *const ext = search_ext ? search_ext : exts;
     int extidx = 0, i = 0;
     const char *curext = Nullch;
 #else
@@ -2787,16 +2900,16 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **searc
 #  ifdef ALWAYS_DEFTYPES
     len = strlen(scriptname);
     if (!(len == 1 && *scriptname == '-') && scriptname[len-1] != ':') {
-       int hasdir, idx = 0, deftypes = 1;
+       int idx = 0, deftypes = 1;
        bool seen_dot = 1;
 
-       hasdir = !dosearch || (strpbrk(scriptname,":[</") != Nullch) ;
+       const int hasdir = !dosearch || (strpbrk(scriptname,":[</") != Nullch);
 #  else
     if (dosearch) {
-       int hasdir, idx = 0, deftypes = 1;
+       int idx = 0, deftypes = 1;
        bool seen_dot = 1;
 
-       hasdir = (strpbrk(scriptname,":[</") != Nullch) ;
+       const int hasdir = (strpbrk(scriptname,":[</") != Nullch);
 #  endif
        /* The first time through, just add SEARCH_EXTS to whatever we
         * already have, so we can check for default file types. */
@@ -2959,8 +3072,7 @@ Perl_find_script(pTHX_ const char *scriptname, bool dosearch, const char **searc
            }
            scriptname = Nullch;
        }
-       if (xfailed)
-           Safefree(xfailed);
+       Safefree(xfailed);
        scriptname = xfound;
     }
     return (scriptname ? savepv(scriptname) : Nullch);
@@ -3062,7 +3174,7 @@ Perl_getenv_len(pTHX_ const char *env_elem, unsigned long *len)
 MGVTBL*
 Perl_get_vtbl(pTHX_ int vtbl_id)
 {
-    const MGVTBL* result = Null(MGVTBL*);
+    const MGVTBL* result;
 
     switch(vtbl_id) {
     case want_vtbl_sv:
@@ -3157,6 +3269,9 @@ Perl_get_vtbl(pTHX_ int vtbl_id)
     case want_vtbl_utf8:
        result = &PL_vtbl_utf8;
        break;
+    default:
+       result = Null(MGVTBL*);
+       break;
     }
     return (MGVTBL*)result;
 }
@@ -3214,23 +3329,19 @@ Perl_my_fflush_all(pTHX)
 void
 Perl_report_evil_fh(pTHX_ const GV *gv, const IO *io, I32 op)
 {
-    const char *func =
+    const char * const func =
        op == OP_READLINE   ? "readline"  :     /* "<HANDLE>" not nice */
        op == OP_LEAVEWRITE ? "write" :         /* "write exit" not nice */
        PL_op_desc[op];
-    const char *pars = OP_IS_FILETEST(op) ? "" : "()";
-    const char *type = OP_IS_SOCKET(op)
+    const char * const pars = OP_IS_FILETEST(op) ? "" : "()";
+    const char * const type = OP_IS_SOCKET(op)
            || (gv && io && IoTYPE(io) == IoTYPE_SOCKET)
                ?  "socket" : "filehandle";
-    const char *name = NULL;
-
-    if (gv && isGV(gv)) {
-       name = GvENAME(gv);
-    }
+    const char * const name = gv && isGV(gv) ? GvENAME(gv) : NULL;
 
     if (op == OP_phoney_OUTPUT_ONLY || op == OP_phoney_INPUT_ONLY) {
        if (ckWARN(WARN_IO)) {
-           const char *direction = (op == OP_phoney_INPUT_ONLY) ? "in" : "out";
+           const char * const direction = (op == OP_phoney_INPUT_ONLY) ? "in" : "out";
            if (name && *name)
                Perl_warner(aTHX_ packWARN(WARN_IO),
                            "Filehandle %s opened only for %sput",
@@ -3587,7 +3698,7 @@ Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, in
   } STMT_END;
 #endif
   buflen = 64;
-  New(0, buf, buflen, char);
+  Newx(buf, buflen, char);
   len = strftime(buf, buflen, fmt, &mytm);
   /*
   ** The following is needed to handle to the situation where
@@ -3610,7 +3721,7 @@ Perl_my_strftime(pTHX_ const char *fmt, int sec, int min, int hour, int mday, in
     const int fmtlen = strlen(fmt);
     const int bufsize = fmtlen + buflen;
 
-    New(0, buf, bufsize, char);
+    Newx(buf, bufsize, char);
     while (buf) {
       buflen = strftime(buf, bufsize, fmt, &mytm);
       if (buflen > 0 && buflen < bufsize)
@@ -3675,7 +3786,7 @@ Perl_getcwd_sv(pTHX_ register SV *sv)
         * size from the heap if they are given a NULL buffer pointer.
         * The problem is that this behaviour is not portable. */
        if (getcwd(buf, sizeof(buf) - 1)) {
-           sv_setpvn(sv, buf, strlen(buf));
+           sv_setpv(sv, buf);
            return TRUE;
        }
        else {
@@ -3829,57 +3940,59 @@ it doesn't.
 const char *
 Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv)
 {
-    const char *start = s;
+    const char *start;
     const char *pos;
     const char *last;
     int saw_period = 0;
-    int saw_under = 0;
+    int alpha = 0;
     int width = 3;
-    AV *av = newAV();
-    SV* hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
+    AV * const av = newAV();
+    SV * const hv = newSVrv(rv, "version"); /* create an SV and upgrade the RV */
     (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */
+
 #ifndef NODEFAULT_SHAREKEYS
     HvSHAREKEYS_on(hv);         /* key-sharing on by default */
 #endif
 
+    while (isSPACE(*s)) /* leading whitespace is OK */
+       s++;
+
     if (*s == 'v') {
        s++;  /* get past 'v' */
        qv = 1; /* force quoted version processing */
     }
 
-    last = pos = s;
+    start = last = pos = s;
 
     /* pre-scan the input string to check for decimals/underbars */
     while ( *pos == '.' || *pos == '_' || isDIGIT(*pos) )
     {
        if ( *pos == '.' )
        {
-           if ( saw_under )
+           if ( alpha )
                Perl_croak(aTHX_ "Invalid version format (underscores before decimal)");
            saw_period++ ;
            last = pos;
        }
        else if ( *pos == '_' )
        {
-           if ( saw_under )
+           if ( alpha )
                Perl_croak(aTHX_ "Invalid version format (multiple underscores)");
-           saw_under = 1;
+           alpha = 1;
            width = pos - last - 1; /* natural width of sub-version */
        }
        pos++;
     }
 
-    if ( saw_period > 1 ) {
+    if ( saw_period > 1 )
        qv = 1; /* force quoted version processing */
-    }
 
     pos = s;
 
     if ( qv )
-       hv_store((HV *)hv, "qv", 2, &PL_sv_yes, 0);
-    if ( saw_under ) {
-       hv_store((HV *)hv, "alpha", 5, &PL_sv_yes, 0);
-    }
+       hv_store((HV *)hv, "qv", 2, newSViv(qv), 0);
+    if ( alpha )
+       hv_store((HV *)hv, "alpha", 5, newSViv(alpha), 0);
     if ( !qv && width < 3 )
        hv_store((HV *)hv, "width", 5, newSViv(width), 0);
     
@@ -3900,7 +4013,7 @@ Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv)
                 * point of a version originally created with a bare
                 * floating point number, i.e. not quoted in any way
                 */
-               if ( !qv && s > start+1 && saw_period == 1 ) {
+               if ( !qv && s > start && saw_period == 1 ) {
                    mult *= 100;
                    while ( s < end ) {
                        orev = rev;
@@ -3968,7 +4081,7 @@ Perl_scan_version(pTHX_ const char *s, SV *rv, bool qv)
        av_push(av, newSViv(0));
 
     /* And finally, store the AV in the hash */
-    hv_store((HV *)hv, "version", 7, (SV *)av, 0);
+    hv_store((HV *)hv, "version", 7, newRV_noinc((SV *)av), 0);
     return s;
 }
 
@@ -3988,14 +4101,14 @@ want to upgrade the SV.
 SV *
 Perl_new_version(pTHX_ SV *ver)
 {
-    SV *rv = newSV(0);
+    SV * const rv = newSV(0);
     if ( sv_derived_from(ver,"version") ) /* can just copy directly */
     {
        I32 key;
        AV * const av = newAV();
        AV *sav;
        /* This will get reblessed later if a derived class*/
-       SV const hv = newSVrv(rv, "version"); 
+       SV * const hv = newSVrv(rv, "version"); 
        (void)sv_upgrade(hv, SVt_PVHV); /* needs to be an HV type */
 #ifndef NODEFAULT_SHAREKEYS
        HvSHAREKEYS_on(hv);         /* key-sharing on by default */
@@ -4017,7 +4130,7 @@ Perl_new_version(pTHX_ SV *ver)
            hv_store((HV *)hv, "width", 5, newSViv(width), 0);
        }
 
-       sav = (AV *)*hv_fetch((HV*)ver, "version", 7, FALSE);
+       sav = (AV *)SvRV(*hv_fetch((HV*)ver, "version", 7, FALSE));
        /* This will get reblessed later if a derived class*/
        for ( key = 0; key <= av_len(sav); key++ )
        {
@@ -4025,15 +4138,14 @@ Perl_new_version(pTHX_ SV *ver)
            av_push(av, newSViv(rev));
        }
 
-       hv_store((HV *)hv, "version", 7, (SV *)av, 0);
+       hv_store((HV *)hv, "version", 7, newRV_noinc((SV *)av), 0);
        return rv;
     }
 #ifdef SvVOK
     if ( SvVOK(ver) ) { /* already a v-string */
-       char *version;
-       MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring);
+       const MAGIC* const mg = mg_find(ver,PERL_MAGIC_vstring);
        const STRLEN len = mg->mg_len;
-       version = savepvn( (const char*)mg->mg_ptr, len);
+       char * const version = savepvn( (const char*)mg->mg_ptr, len);
        sv_setpvn(rv,version,len);
        Safefree(version);
     }
@@ -4068,12 +4180,12 @@ Perl_upg_version(pTHX_ SV *ver)
     if ( SvNOK(ver) ) /* may get too much accuracy */ 
     {
        char tbuf[64];
-       sprintf(tbuf,"%.9"NVgf, SvNVX(ver));
-       version = savepv(tbuf);
+       const STRLEN len = my_sprintf(tbuf,"%.9"NVgf, SvNVX(ver));
+       version = savepvn(tbuf, len);
     }
 #ifdef SvVOK
     else if ( SvVOK(ver) ) { /* already a v-string */
-       MAGIC* mg = mg_find(ver,PERL_MAGIC_vstring);
+       const MAGIC* const mg = mg_find(ver,PERL_MAGIC_vstring);
        version = savepvn( (const char*)mg->mg_ptr,mg->mg_len );
        qv = 1;
     }
@@ -4087,6 +4199,45 @@ Perl_upg_version(pTHX_ SV *ver)
     return ver;
 }
 
+/*
+=for apidoc vverify
+
+Validates that the SV contains a valid version object.
+
+    bool vverify(SV *vobj);
+
+Note that it only confirms the bare minimum structure (so as not to get
+confused by derived classes which may contain additional hash entries):
+
+=over 4
+
+=item * The SV contains a [reference to a] hash
+
+=item * The hash contains a "version" key
+
+=item * The "version" key has [a reference to] an AV as its value
+
+=back
+
+=cut
+*/
+
+bool
+Perl_vverify(pTHX_ SV *vs)
+{
+    SV *sv;
+    if ( SvROK(vs) )
+       vs = SvRV(vs);
+
+    /* see if the appropriate elements exist */
+    if ( SvTYPE(vs) == SVt_PVHV
+        && hv_exists((HV*)vs, "version", 7)
+        && (sv = SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE)))
+        && SvTYPE(sv) == SVt_PVAV )
+       return TRUE;
+    else
+       return FALSE;
+}
 
 /*
 =for apidoc vnumify
@@ -4113,6 +4264,9 @@ Perl_vnumify(pTHX_ SV *vs)
     if ( SvROK(vs) )
        vs = SvRV(vs);
 
+    if ( !vverify(vs) )
+       Perl_croak(aTHX_ "Invalid version object");
+
     /* see if various flags exist */
     if ( hv_exists((HV*)vs, "alpha", 5 ) )
        alpha = TRUE;
@@ -4123,7 +4277,7 @@ Perl_vnumify(pTHX_ SV *vs)
 
 
     /* attempt to retrieve the version array */
-    if ( !(av = (AV *)*hv_fetch((HV*)vs, "version", 7, FALSE) ) ) {
+    if ( !(av = (AV *)SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE)) ) ) {
        sv_catpvn(sv,"0",1);
        return sv;
     }
@@ -4136,17 +4290,17 @@ Perl_vnumify(pTHX_ SV *vs)
     }
 
     digit = SvIV(*av_fetch(av, 0, 0));
-    Perl_sv_setpvf(aTHX_ sv,"%d.", (int)PERL_ABS(digit));
+    Perl_sv_setpvf(aTHX_ sv, "%d.", (int)PERL_ABS(digit));
     for ( i = 1 ; i < len ; i++ )
     {
        digit = SvIV(*av_fetch(av, i, 0));
        if ( width < 3 ) {
-           const int denom = (int)pow(10,(3-width));
+           const int denom = (width == 2 ? 10 : 100);
            const div_t term = div((int)PERL_ABS(digit),denom);
-           Perl_sv_catpvf(aTHX_ sv,"%0*d_%d", width, term.quot, term.rem);
+           Perl_sv_catpvf(aTHX_ sv, "%0*d_%d", width, term.quot, term.rem);
        }
        else {
-           Perl_sv_catpvf(aTHX_ sv,"%0*d", width, (int)digit);
+           Perl_sv_catpvf(aTHX_ sv, "%0*d", width, (int)digit);
        }
     }
 
@@ -4154,14 +4308,12 @@ Perl_vnumify(pTHX_ SV *vs)
     {
        digit = SvIV(*av_fetch(av, len, 0));
        if ( alpha && width == 3 ) /* alpha version */
-           Perl_sv_catpv(aTHX_ sv,"_");
-       /* Don't display additional trailing zeros */
-       if ( digit > 0 )
-           Perl_sv_catpvf(aTHX_ sv,"%0*d", width, (int)digit);
+           sv_catpvn(sv,"_",1);
+       Perl_sv_catpvf(aTHX_ sv, "%0*d", width, (int)digit);
     }
-    else /* len == 1 */
+    else /* len == 0 */
     {
-        sv_catpvn(sv,"000",3);
+       sv_catpvn(sv,"000",3);
     }
     return sv;
 }
@@ -4185,28 +4337,33 @@ Perl_vnormal(pTHX_ SV *vs)
 {
     I32 i, len, digit;
     bool alpha = FALSE;
-    SV *sv = newSV(0);
+    SV * const sv = newSV(0);
     AV *av;
     if ( SvROK(vs) )
        vs = SvRV(vs);
 
+    if ( !vverify(vs) )
+       Perl_croak(aTHX_ "Invalid version object");
+
     if ( hv_exists((HV*)vs, "alpha", 5 ) )
        alpha = TRUE;
-    av = (AV *)*hv_fetch((HV*)vs, "version", 7, FALSE);
+    av = (AV *)SvRV(*hv_fetch((HV*)vs, "version", 7, FALSE));
 
     len = av_len(av);
-    if ( len == -1 ) {
+    if ( len == -1 )
+    {
        sv_catpvn(sv,"",0);
        return sv;
     }
     digit = SvIV(*av_fetch(av, 0, 0));
-    Perl_sv_setpvf(aTHX_ sv,"v%"IVdf,(IV)digit);
-    for ( i = 1 ; i <= len-1 ; i++ ) {
+    Perl_sv_setpvf(aTHX_ sv, "v%"IVdf, (IV)digit);
+    for ( i = 1 ; i < len ; i++ ) {
        digit = SvIV(*av_fetch(av, i, 0));
        Perl_sv_catpvf(aTHX_ sv, ".%"IVdf, (IV)digit);
     }
 
-    if ( len > 0 ) {
+    if ( len > 0 )
+    {
        /* handle last digit specially */
        digit = SvIV(*av_fetch(av, len, 0));
        if ( alpha )
@@ -4219,7 +4376,6 @@ Perl_vnormal(pTHX_ SV *vs)
        for ( len = 2 - len; len != 0; len-- )
            sv_catpvn(sv,".0",2);
     }
-
     return sv;
 }
 
@@ -4237,14 +4393,13 @@ the original version contained 1 or more dots, respectively
 SV *
 Perl_vstringify(pTHX_ SV *vs)
 {
-    I32 qv = 0;
     if ( SvROK(vs) )
        vs = SvRV(vs);
     
+    if ( !vverify(vs) )
+       Perl_croak(aTHX_ "Invalid version object");
+
     if ( hv_exists((HV *)vs, "qv", 2) )
-       qv = 1;
-    
-    if ( qv )
        return vnormal(vs);
     else
        return vnumify(vs);
@@ -4273,13 +4428,19 @@ Perl_vcmp(pTHX_ SV *lhv, SV *rhv)
     if ( SvROK(rhv) )
        rhv = SvRV(rhv);
 
+    if ( !vverify(lhv) )
+       Perl_croak(aTHX_ "Invalid version object");
+
+    if ( !vverify(rhv) )
+       Perl_croak(aTHX_ "Invalid version object");
+
     /* get the left hand term */
-    lav = (AV *)*hv_fetch((HV*)lhv, "version", 7, FALSE);
+    lav = (AV *)SvRV(*hv_fetch((HV*)lhv, "version", 7, FALSE));
     if ( hv_exists((HV*)lhv, "alpha", 5 ) )
        lalpha = TRUE;
 
     /* and the right hand term */
-    rav = (AV *)*hv_fetch((HV*)rhv, "version", 7, FALSE);
+    rav = (AV *)SvRV(*hv_fetch((HV*)rhv, "version", 7, FALSE));
     if ( hv_exists((HV*)rhv, "alpha", 5 ) )
        ralpha = TRUE;
 
@@ -4574,7 +4735,7 @@ Perl_my_socketpair (int family, int type, int protocol, int fd[2]) {
 #endif
   tidy_up_and_fail:
     {
-       int save_errno = errno;
+       const int save_errno = errno;
        if (listener != -1)
            PerlLIO_close(listener);
        if (connector != -1)
@@ -4603,8 +4764,9 @@ Perl_my_socketpair (int family, int type, int protocol, int fd[2]) {
 =for apidoc sv_nosharing
 
 Dummy routine which "shares" an SV when there is no sharing module present.
-Exists to avoid test for a NULL function pointer and because it could potentially warn under
-some level of strict-ness.
+Or "locks" it. Or "unlocks" it. In other words, ignores its single SV argument.
+Exists to avoid test for a NULL function pointer and because it could
+potentially warn under some level of strict-ness.
 
 =cut
 */
@@ -4615,39 +4777,6 @@ Perl_sv_nosharing(pTHX_ SV *sv)
     PERL_UNUSED_ARG(sv);
 }
 
-/*
-=for apidoc sv_nolocking
-
-Dummy routine which "locks" an SV when there is no locking module present.
-Exists to avoid test for a NULL function pointer and because it could potentially warn under
-some level of strict-ness.
-
-=cut
-*/
-
-void
-Perl_sv_nolocking(pTHX_ SV *sv)
-{
-    PERL_UNUSED_ARG(sv);
-}
-
-
-/*
-=for apidoc sv_nounlocking
-
-Dummy routine which "unlocks" an SV when there is no locking module present.
-Exists to avoid test for a NULL function pointer and because it could potentially warn under
-some level of strict-ness.
-
-=cut
-*/
-
-void
-Perl_sv_nounlocking(pTHX_ SV *sv)
-{
-    PERL_UNUSED_ARG(sv);
-}
-
 U32
 Perl_parse_unicode_opts(pTHX_ const char **popt)
 {
@@ -4846,8 +4975,8 @@ Perl_init_global_struct(pTHX)
 #ifdef PERL_GLOBAL_STRUCT
 #  define PERL_GLOBAL_STRUCT_INIT
 #  include "opcode.h" /* the ppaddr and check */
-    IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
-    IV ncheck  = sizeof(Gcheck) /sizeof(Perl_check_t);
+    const IV nppaddr = sizeof(Gppaddr)/sizeof(Perl_ppaddr_t);
+    const IV ncheck  = sizeof(Gcheck) /sizeof(Perl_check_t);
 #  ifdef PERL_GLOBAL_STRUCT_PRIVATE
     /* PerlMem_malloc() because can't use even safesysmalloc() this early. */
     plvarsp = (struct perl_vars*)PerlMem_malloc(sizeof(struct perl_vars));
@@ -4911,6 +5040,133 @@ Perl_free_global_struct(pTHX_ struct perl_vars *plvarsp)
 
 #endif /* PERL_GLOBAL_STRUCT */
 
+#ifdef PERL_MEM_LOG
+
+#define PERL_MEM_LOG_SPRINTF_BUF_SIZE 128
+
+Malloc_t
+Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname)
+{
+#ifdef PERL_MEM_LOG_STDERR
+    /* We can't use PerlIO for obvious reasons. */
+    char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
+    const STRLEN len = my_sprintf(buf,
+                                 "alloc: %s:%d:%s: %"IVdf" %"UVuf
+                                 " %s = %"IVdf": %"UVxf"\n",
+                                 filename, linenumber, funcname, n, typesize,
+                                 typename, n * typesize, PTR2UV(newalloc));
+    PerlLIO_write(2,  buf, len));
+#endif
+    return newalloc;
+}
+
+Malloc_t
+Perl_mem_log_realloc(const UV n, const UV typesize, const char *typename, Malloc_t oldalloc, Malloc_t newalloc, const char *filename, const int linenumber, const char *funcname)
+{
+#ifdef PERL_MEM_LOG_STDERR
+    /* We can't use PerlIO for obvious reasons. */
+    char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
+    const STRLEN len = my_sprintf(buf, "realloc: %s:%d:%s: %"IVdf" %"UVuf
+                                 " %s = %"IVdf": %"UVxf" -> %"UVxf"\n",
+                                 filename, linenumber, funcname, n, typesize,
+                                 typename, n * typesize, PTR2UV(oldalloc),
+                                 PTR2UV(newalloc));
+    PerlLIO_write(2,  buf, len);
+#endif
+    return newalloc;
+}
+
+Malloc_t
+Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber, const char *funcname)
+{
+#ifdef PERL_MEM_LOG_STDERR
+    /* We can't use PerlIO for obvious reasons. */
+    char buf[PERL_MEM_LOG_SPRINTF_BUF_SIZE];
+    const STRLEN len = my_sprintf(buf, "free: %s:%d:%s: %"UVxf"\n",
+                                 filename, linenumber, funcname,
+                                 PTR2UV(oldalloc));
+    PerlLIO_write(2,  buf, len);
+#endif
+    return oldalloc;
+}
+
+#endif /* PERL_MEM_LOG */
+
+/*
+=for apidoc my_sprintf
+
+The C library C<sprintf>, wrapped if necessary, to ensure that it will return
+the length of the string written to the buffer. Only rare pre-ANSI systems
+need the wrapper function - usually this is a direct call to C<sprintf>.
+
+=cut
+*/
+#ifndef SPRINTF_RETURNS_STRLEN
+int
+Perl_my_sprintf(char *buffer, const char* pat, ...)
+{
+    va_list args;
+    va_start(args, pat);
+    vsprintf(buffer, pat, args);
+    va_end(args);
+    return strlen(buffer);
+}
+#endif
+
+void
+Perl_my_clearenv(pTHX)
+{
+    dVAR;
+#if ! defined(PERL_MICRO)
+#  if defined(PERL_IMPLICIT_SYS) || defined(WIN32)
+    PerlEnv_clearenv();
+#  else /* ! (PERL_IMPLICIT_SYS || WIN32) */
+#    if defined(USE_ENVIRON_ARRAY)
+#      if defined(USE_ITHREADS)
+    /* only the parent thread can clobber the process environment */
+    if (PL_curinterp == aTHX)
+#      endif /* USE_ITHREADS */
+    {
+#      if ! defined(PERL_USE_SAFE_PUTENV)
+    if ( !PL_use_safe_putenv) {
+      I32 i;
+      if (environ == PL_origenviron)
+        environ = (char**)safesysmalloc(sizeof(char*));
+      else
+        for (i = 0; environ[i]; i++)
+          (void)safesysfree(environ[i]);
+    }
+    environ[0] = NULL;
+#      else /* PERL_USE_SAFE_PUTENV */
+#        if defined(HAS_CLEARENV)
+    (void)clearenv();
+#        elif defined(HAS_UNSETENV)
+    int bsiz = 80; /* Most envvar names will be shorter than this. */
+    char *buf = (char*)safesysmalloc(bsiz * sizeof(char));
+    while (*environ != NULL) {
+      char *e = strchr(*environ, '=');
+      int l = e ? e - *environ : strlen(*environ);
+      if (bsiz < l + 1) {
+        (void)safesysfree(buf);
+        bsiz = l + 1;
+        buf = (char*)safesysmalloc(bsiz * sizeof(char));
+      } 
+      strncpy(buf, *environ, l);
+      *(buf + l) = '\0';
+      (void)unsetenv(buf);
+    }
+    (void)safesysfree(buf);
+#        else /* ! HAS_CLEARENV && ! HAS_UNSETENV */
+    /* Just null environ and accept the leakage. */
+    *environ = NULL;
+#        endif /* HAS_CLEARENV || HAS_UNSETENV */
+#      endif /* ! PERL_USE_SAFE_PUTENV */
+    }
+#    endif /* USE_ENVIRON_ARRAY */
+#  endif /* PERL_IMPLICIT_SYS || WIN32 */
+#endif /* PERL_MICRO */
+}
+
 /*
  * Local variables:
  * c-indentation-style: bsd