This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
yet another way of debugging memory allocations
[perl5.git] / handy.h
diff --git a/handy.h b/handy.h
index 81f4745..a89f09e 100644 (file)
--- a/handy.h
+++ b/handy.h
@@ -1,6 +1,7 @@
 /*    handy.h
  *
- *    Copyright (c) 1991-2000, Larry Wall
+ *    Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1999,
+ *    2000, 2001, 2002, 2004, 2005 by Larry Wall and others
  *
  *    You may distribute under the terms of either the GNU General Public
  *    License or the Artistic License, as specified in the README file.
@@ -21,7 +22,9 @@
 #define Null(type) ((type)NULL)
 
 /*
-=for apidoc AmU||Nullch
+=head1 Handy Values
+
+=for apidoc AmU||Nullch 
 Null character pointer.
 
 =for apidoc AmU||Nullsv
@@ -48,10 +51,10 @@ Null SV pointer.
    just figure out all the headers such a test needs.
    Andy Dougherty      August 1996
 */
-/* bool is built-in for g++-2.6.3 and later, which might be used 
+/* bool is built-in for g++-2.6.3 and later, which might be used
    for extensions.  <_G_config.h> defines _G_HAVE_BOOL, but we can't
    be sure _G_config.h will be included before this file.  _G_config.h
-   also defines _G_HAVE_BOOL for both gcc and g++, but only g++ 
+   also defines _G_HAVE_BOOL for both gcc and g++, but only g++
    actually has bool.  Hence, _G_HAVE_BOOL is pretty useless for us.
    g++ can be identified by __GNUG__.
    Andy Dougherty      February 2000
@@ -101,8 +104,8 @@ Null SV pointer.
    Similarly, there is no guarantee that I16 and U16 have exactly 16
    bits.
 
-   For dealing with issues that may arise from various 32/64-bit 
-   systems, we will ask Configure to check out 
+   For dealing with issues that may arise from various 32/64-bit
+   systems, we will ask Configure to check out
 
        SHORTSIZE == sizeof(short)
        INTSIZE == sizeof(int)
@@ -114,6 +117,18 @@ Null SV pointer.
 
 */
 
+#ifdef I_INTTYPES /* e.g. Linux has int64_t without <inttypes.h> */
+#   include <inttypes.h>
+#   ifdef INT32_MIN_BROKEN
+#       undef  INT32_MIN
+#       define INT32_MIN (-2147483647-1)
+#   endif
+#   ifdef INT64_MIN_BROKEN
+#       undef  INT64_MIN
+#       define INT64_MIN (-9223372036854775807LL-1)
+#   endif
+#endif
+
 typedef I8TYPE I8;
 typedef U8TYPE U8;
 typedef I16TYPE I16;
@@ -122,17 +137,33 @@ typedef I32TYPE I32;
 typedef U32TYPE U32;
 #ifdef PERL_CORE
 #   ifdef HAS_QUAD
-#       if QUADKIND == QUAD_IS_INT64_T
-#           include <sys/types.h>
-#           ifdef I_INTTYPES /* e.g. Linux has int64_t without <inttypes.h> */
-#               include <inttypes.h>
-#           endif
-#       endif
 typedef I64TYPE I64;
 typedef U64TYPE U64;
 #   endif
 #endif /* PERL_CORE */
 
+#if defined(HAS_QUAD) && defined(USE_64_BIT_INT)
+#   ifndef UINT64_C /* usually from <inttypes.h> */
+#       if defined(HAS_LONG_LONG) && QUADKIND == QUAD_IS_LONG_LONG
+#           define INT64_C(c)  CAT2(c,LL)
+#           define UINT64_C(c) CAT2(c,ULL)
+#       else
+#           if LONGSIZE == 8 && QUADKIND == QUAD_IS_LONG
+#               define INT64_C(c)      CAT2(c,L)
+#               define UINT64_C(c)     CAT2(c,UL)
+#           else
+#               define INT64_C(c)      ((I64TYPE)(c))
+#               define UINT64_C(c)     ((U64TYPE)(c))
+#           endif
+#       endif
+#   endif
+#endif
+
+/* HMB H.Merijn Brand - a placeholder for preparing Configure patches */
+#if defined(LIBM_LIB_VERSION)
+/* Not (yet) used at top level, but mention them for metaconfig */
+#endif
+
 /* Mention I8SIZE, U8SIZE, I16SIZE, U16SIZE, I32SIZE, U32SIZE,
    I64SIZE, and U64SIZE here so that metaconfig pulls them in. */
 
@@ -150,7 +181,11 @@ typedef U64TYPE U64;
 
 #define I32_MAX INT32_MAX
 #define I32_MIN INT32_MIN
-#define U32_MAX UINT32_MAX
+#ifndef UINT32_MAX_BROKEN /* e.g. HP-UX with gcc messes this up */
+#  define U32_MAX UINT32_MAX
+#else
+#  define U32_MAX 4294967295U
+#endif
 #define U32_MIN UINT32_MIN
 
 #else
@@ -179,6 +214,7 @@ typedef U64TYPE U64;
 
 #endif
 
+/* log(2) is pretty close to  0.30103, just in case anyone is grepping for it */
 #define BIT_DIGITS(N)   (((N)*146)/485 + 1)  /* log2(10) =~ 146/485 */
 #define TYPE_DIGITS(T)  BIT_DIGITS(sizeof(T) * 8)
 #define TYPE_CHARS(T)   (TYPE_DIGITS(T) + 2) /* sign, NUL */
@@ -186,6 +222,8 @@ typedef U64TYPE U64;
 #define Ctl(ch) ((ch) & 037)
 
 /*
+=head1 Miscellaneous Functions
+
 =for apidoc Am|bool|strNE|char* s1|char* s2
 Test two strings to see if they are different.  Returns true or
 false.
@@ -259,9 +297,12 @@ C<strncmp>).
 #endif
 
 /*
+
+=head1 Character classes
+
 =for apidoc Am|bool|isALNUM|char ch
 Returns a boolean indicating whether the C C<char> is an ASCII alphanumeric
-character or digit.
+character (including underscore) or digit.
 
 =for apidoc Am|bool|isALPHA|char ch
 Returns a boolean indicating whether the C C<char> is an ASCII alphabetic
@@ -296,6 +337,8 @@ Converts the specified character to lowercase.
 #define isALPHA(c)     (isUPPER(c) || isLOWER(c))
 #define isSPACE(c) \
        ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) =='\r' || (c) == '\f')
+#define isPSXSPC(c)    (isSPACE(c) || (c) == '\v')
+#define isBLANK(c)     ((c) == ' ' || (c) == '\t')
 #define isDIGIT(c)     ((c) >= '0' && (c) <= '9')
 #ifdef EBCDIC
     /* In EBCDIC we do not do locales: therefore() isupper() is fine. */
@@ -315,11 +358,11 @@ Converts the specified character to lowercase.
 #   define isLOWER(c)  ((c) >= 'a' && (c) <= 'z')
 #   define isALNUMC(c) (isALPHA(c) || isDIGIT(c))
 #   define isASCII(c)  ((c) <= 127)
-#   define isCNTRL(c)  ((c) < ' ')
+#   define isCNTRL(c)  ((c) < ' ' || (c) == 127)
 #   define isGRAPH(c)  (isALNUM(c) || isPUNCT(c))
-#   define isPRINT(c)  (((c) > 32 && (c) < 127) || isSPACE(c))
+#   define isPRINT(c)  (((c) > 32 && (c) < 127) || (c) == ' ')
 #   define isPUNCT(c)  (((c) >= 33 && (c) <= 47) || ((c) >= 58 && (c) <= 64)  || ((c) >= 91 && (c) <= 96) || ((c) >= 123 && (c) <= 126))
-#   define isXDIGIT(c)  (isdigit(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
+#   define isXDIGIT(c)  (isDIGIT(c) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F'))
 #   define toUPPER(c)  (isLOWER(c) ? (c) - ('a' - 'A') : (c))
 #   define toLOWER(c)  (isUPPER(c) ? (c) + ('a' - 'A') : (c))
 #endif
@@ -382,6 +425,9 @@ Converts the specified character to lowercase.
 #  endif
 #endif /* USE_NEXT_CTYPE */
 
+#define isPSXSPC_LC(c)         (isSPACE_LC(c) || (c) == '\v')
+#define isBLANK_LC(c)          isBLANK(c) /* could be wrong */
+
 #define isALNUM_uni(c)         is_uni_alnum(c)
 #define isIDFIRST_uni(c)       is_uni_idfirst(c)
 #define isALPHA_uni(c)         is_uni_alpha(c)
@@ -396,28 +442,35 @@ Converts the specified character to lowercase.
 #define isPRINT_uni(c)         is_uni_print(c)
 #define isPUNCT_uni(c)         is_uni_punct(c)
 #define isXDIGIT_uni(c)                is_uni_xdigit(c)
-#define toUPPER_uni(c)         to_uni_upper(c)
-#define toTITLE_uni(c)         to_uni_title(c)
-#define toLOWER_uni(c)         to_uni_lower(c)
-
-#define isALNUM_LC_uni(c)      (c < 256 ? isALNUM_LC(c) : is_uni_alnum_lc(c))
-#define isIDFIRST_LC_uni(c)    (c < 256 ? isIDFIRST_LC(c) : is_uni_idfirst_lc(c))
-#define isALPHA_LC_uni(c)      (c < 256 ? isALPHA_LC(c) : is_uni_alpha_lc(c))
-#define isSPACE_LC_uni(c)      (c < 256 ? isSPACE_LC(c) : is_uni_space_lc(c))
-#define isDIGIT_LC_uni(c)      (c < 256 ? isDIGIT_LC(c) : is_uni_digit_lc(c))
-#define isUPPER_LC_uni(c)      (c < 256 ? isUPPER_LC(c) : is_uni_upper_lc(c))
-#define isLOWER_LC_uni(c)      (c < 256 ? isLOWER_LC(c) : is_uni_lower_lc(c))
-#define isALNUMC_LC_uni(c)     (c < 256 ? isALNUMC_LC(c) : is_uni_alnumc_lc(c))
-#define isCNTRL_LC_uni(c)      (c < 256 ? isCNTRL_LC(c) : is_uni_cntrl_lc(c))
-#define isGRAPH_LC_uni(c)      (c < 256 ? isGRAPH_LC(c) : is_uni_graph_lc(c))
-#define isPRINT_LC_uni(c)      (c < 256 ? isPRINT_LC(c) : is_uni_print_lc(c))
-#define isPUNCT_LC_uni(c)      (c < 256 ? isPUNCT_LC(c) : is_uni_punct_lc(c))
-#define toUPPER_LC_uni(c)      (c < 256 ? toUPPER_LC(c) : to_uni_upper_lc(c))
-#define toTITLE_LC_uni(c)      (c < 256 ? toUPPER_LC(c) : to_uni_title_lc(c))
-#define toLOWER_LC_uni(c)      (c < 256 ? toLOWER_LC(c) : to_uni_lower_lc(c))
+#define toUPPER_uni(c,s,l)     to_uni_upper(c,s,l)
+#define toTITLE_uni(c,s,l)     to_uni_title(c,s,l)
+#define toLOWER_uni(c,s,l)     to_uni_lower(c,s,l)
+#define toFOLD_uni(c,s,l)      to_uni_fold(c,s,l)
+
+#define isPSXSPC_uni(c)                (isSPACE_uni(c) ||(c) == '\f')
+#define isBLANK_uni(c)         isBLANK(c) /* could be wrong */
+
+#define isALNUM_LC_uvchr(c)    (c < 256 ? isALNUM_LC(c) : is_uni_alnum_lc(c))
+#define isIDFIRST_LC_uvchr(c)  (c < 256 ? isIDFIRST_LC(c) : is_uni_idfirst_lc(c))
+#define isALPHA_LC_uvchr(c)    (c < 256 ? isALPHA_LC(c) : is_uni_alpha_lc(c))
+#define isSPACE_LC_uvchr(c)    (c < 256 ? isSPACE_LC(c) : is_uni_space_lc(c))
+#define isDIGIT_LC_uvchr(c)    (c < 256 ? isDIGIT_LC(c) : is_uni_digit_lc(c))
+#define isUPPER_LC_uvchr(c)    (c < 256 ? isUPPER_LC(c) : is_uni_upper_lc(c))
+#define isLOWER_LC_uvchr(c)    (c < 256 ? isLOWER_LC(c) : is_uni_lower_lc(c))
+#define isALNUMC_LC_uvchr(c)   (c < 256 ? isALNUMC_LC(c) : is_uni_alnumc_lc(c))
+#define isCNTRL_LC_uvchr(c)    (c < 256 ? isCNTRL_LC(c) : is_uni_cntrl_lc(c))
+#define isGRAPH_LC_uvchr(c)    (c < 256 ? isGRAPH_LC(c) : is_uni_graph_lc(c))
+#define isPRINT_LC_uvchr(c)    (c < 256 ? isPRINT_LC(c) : is_uni_print_lc(c))
+#define isPUNCT_LC_uvchr(c)    (c < 256 ? isPUNCT_LC(c) : is_uni_punct_lc(c))
+
+#define isPSXSPC_LC_uni(c)     (isSPACE_LC_uni(c) ||(c) == '\f')
+#define isBLANK_LC_uni(c)      isBLANK(c) /* could be wrong */
 
 #define isALNUM_utf8(p)                is_utf8_alnum(p)
-#define isIDFIRST_utf8(p)      is_utf8_idfirst(p)
+/* The ID_Start of Unicode is quite limiting: it assumes a L-class
+ * character (meaning that you cannot have, say, a CJK character).
+ * Instead, let's allow ID_Continue but not digits. */
+#define isIDFIRST_utf8(p)      (is_utf8_idcont(p) && !is_utf8_digit(p))
 #define isALPHA_utf8(p)                is_utf8_alpha(p)
 #define isSPACE_utf8(p)                is_utf8_space(p)
 #define isDIGIT_utf8(p)                is_utf8_digit(p)
@@ -430,74 +483,73 @@ Converts the specified character to lowercase.
 #define isPRINT_utf8(p)                is_utf8_print(p)
 #define isPUNCT_utf8(p)                is_utf8_punct(p)
 #define isXDIGIT_utf8(p)       is_utf8_xdigit(p)
-#define toUPPER_utf8(p)                to_utf8_upper(p)
-#define toTITLE_utf8(p)                to_utf8_title(p)
-#define toLOWER_utf8(p)                to_utf8_lower(p)
-
-#define isALNUM_LC_utf8(p)     isALNUM_LC_uni(utf8_to_uv(p, 0))
-#define isIDFIRST_LC_utf8(p)   isIDFIRST_LC_uni(utf8_to_uv(p, 0))
-#define isALPHA_LC_utf8(p)     isALPHA_LC_uni(utf8_to_uv(p, 0))
-#define isSPACE_LC_utf8(p)     isSPACE_LC_uni(utf8_to_uv(p, 0))
-#define isDIGIT_LC_utf8(p)     isDIGIT_LC_uni(utf8_to_uv(p, 0))
-#define isUPPER_LC_utf8(p)     isUPPER_LC_uni(utf8_to_uv(p, 0))
-#define isLOWER_LC_utf8(p)     isLOWER_LC_uni(utf8_to_uv(p, 0))
-#define isALNUMC_LC_utf8(p)    isALNUMC_LC_uni(utf8_to_uv(p, 0))
-#define isCNTRL_LC_utf8(p)     isCNTRL_LC_uni(utf8_to_uv(p, 0))
-#define isGRAPH_LC_utf8(p)     isGRAPH_LC_uni(utf8_to_uv(p, 0))
-#define isPRINT_LC_utf8(p)     isPRINT_LC_uni(utf8_to_uv(p, 0))
-#define isPUNCT_LC_utf8(p)     isPUNCT_LC_uni(utf8_to_uv(p, 0))
-#define toUPPER_LC_utf8(p)     toUPPER_LC_uni(utf8_to_uv(p, 0))
-#define toTITLE_LC_utf8(p)     toTITLE_LC_uni(utf8_to_uv(p, 0))
-#define toLOWER_LC_utf8(p)     toLOWER_LC_uni(utf8_to_uv(p, 0))
+#define toUPPER_utf8(p,s,l)    to_utf8_upper(p,s,l)
+#define toTITLE_utf8(p,s,l)    to_utf8_title(p,s,l)
+#define toLOWER_utf8(p,s,l)    to_utf8_lower(p,s,l)
+
+#define isPSXSPC_utf8(c)       (isSPACE_utf8(c) ||(c) == '\f')
+#define isBLANK_utf8(c)                isBLANK(c) /* could be wrong */
+
+#define isALNUM_LC_utf8(p)     isALNUM_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isIDFIRST_LC_utf8(p)   isIDFIRST_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isALPHA_LC_utf8(p)     isALPHA_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isSPACE_LC_utf8(p)     isSPACE_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isDIGIT_LC_utf8(p)     isDIGIT_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isUPPER_LC_utf8(p)     isUPPER_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isLOWER_LC_utf8(p)     isLOWER_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isALNUMC_LC_utf8(p)    isALNUMC_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isCNTRL_LC_utf8(p)     isCNTRL_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isGRAPH_LC_utf8(p)     isGRAPH_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isPRINT_LC_utf8(p)     isPRINT_LC_uvchr(utf8_to_uvchr(p,  0))
+#define isPUNCT_LC_utf8(p)     isPUNCT_LC_uvchr(utf8_to_uvchr(p,  0))
+
+#define isPSXSPC_LC_utf8(c)    (isSPACE_LC_utf8(c) ||(c) == '\f')
+#define isBLANK_LC_utf8(c)     isBLANK(c) /* could be wrong */
 
 #ifdef EBCDIC
-EXT int ebcdic_control (int);
-#  define toCTRL(c)    ebcdic_control(c)
+#  ifdef PERL_IMPLICIT_CONTEXT
+#    define toCTRL(c)     Perl_ebcdic_control(aTHX_ c)
+#  else
+#    define toCTRL        Perl_ebcdic_control
+#  endif
 #else
   /* This conversion works both ways, strangely enough. */
 #  define toCTRL(c)    (toUPPER(c) ^ 64)
 #endif
 
-/* Line numbers are unsigned, 16 bits. */
-typedef U16 line_t;
-#ifdef lint
-#define NOLINE ((line_t)0)
-#else
-#define NOLINE ((line_t) 65535)
-#endif
-
+/* Line numbers are unsigned, 32 bits. */
+typedef U32 line_t;
+#define NOLINE ((line_t) 4294967295UL)
 
-/* 
-   XXX LEAKTEST doesn't really work in perl5.  There are direct calls to
-   safemalloc() in the source, so LEAKTEST won't pick them up.
-   (The main "offenders" are extensions.)
-   Further, if you try LEAKTEST, you'll also end up calling
-   Safefree, which might call safexfree() on some things that weren't
-   malloced with safexmalloc.  The correct "fix" to this, if anyone
-   is interested, is to ensure that all calls go through the New and
-   Renew macros.
-       --Andy Dougherty                August 1996
-*/
 
 /*
+=head1 SV Manipulation Functions
+
 =for apidoc Am|SV*|NEWSV|int id|STRLEN len
 Creates a new SV.  A non-zero C<len> parameter indicates the number of
 bytes of preallocated string space the SV should have.  An extra byte for a
 tailing NUL is also reserved.  (SvPOK is not set for the SV even if string
-space is allocated.)  The reference count for the new SV is set to 1. 
+space is allocated.)  The reference count for the new SV is set to 1.
 C<id> is an integer id between 0 and 1299 (used to identify leaks).
 
-=for apidoc Am|void|New|int id|void* ptr|int nitems|type
+=head1 Memory Management
+
+=for apidoc Am|void|Newx|void* ptr|int nitems|type
 The XSUB-writer's interface to the C C<malloc> function.
 
-=for apidoc Am|void|Newc|int id|void* ptr|int nitems|type|cast
+=for apidoc Am|void|Newxc|void* ptr|int nitems|type|cast
 The XSUB-writer's interface to the C C<malloc> function, with
 cast.
 
-=for apidoc Am|void|Newz|int id|void* ptr|int nitems|type
+=for apidoc Am|void|Newxz|void* ptr|int nitems|type
 The XSUB-writer's interface to the C C<malloc> function.  The allocated
 memory is zeroed with C<memzero>.
 
+In 5.9.3, we removed the 1st parameter, a debug aid, from the api.  It
+was used to uniquely identify each usage of these allocation
+functions, but was deemed unnecessary with the availability of better
+memory tracking tools, valgrind for example.
+
 =for apidoc Am|void|Renew|void* ptr|int nitems|type
 The XSUB-writer's interface to the C C<realloc> function.
 
@@ -505,7 +557,7 @@ The XSUB-writer's interface to the C C<realloc> function.
 The XSUB-writer's interface to the C C<realloc> function, with
 cast.
 
-=for apidoc Am|void|Safefree|void* src|void* dest|int nitems|type
+=for apidoc Am|void|Safefree|void* ptr
 The XSUB-writer's interface to the C C<free> function.
 
 =for apidoc Am|void|Move|void* src|void* dest|int nitems|type
@@ -513,79 +565,155 @@ The XSUB-writer's interface to the C C<memmove> function.  The C<src> is the
 source, C<dest> is the destination, C<nitems> is the number of items, and C<type> is
 the type.  Can do overlapping moves.  See also C<Copy>.
 
+=for apidoc Am|void *|MoveD|void* src|void* dest|int nitems|type
+Like C<Move> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|Copy|void* src|void* dest|int nitems|type
 The XSUB-writer's interface to the C C<memcpy> function.  The C<src> is the
 source, C<dest> is the destination, C<nitems> is the number of items, and C<type> is
 the type.  May fail on overlapping copies.  See also C<Move>.
 
+=for apidoc Am|void *|CopyD|void* src|void* dest|int nitems|type
+
+Like C<Copy> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|Zero|void* dest|int nitems|type
 
 The XSUB-writer's interface to the C C<memzero> function.  The C<dest> is the
 destination, C<nitems> is the number of items, and C<type> is the type.
 
+=for apidoc Am|void *|ZeroD|void* dest|int nitems|type
+
+Like C<Zero> but returns dest. Useful for encouraging compilers to tail-call
+optimise.
+
 =for apidoc Am|void|StructCopy|type src|type dest|type
 This is an architecture-independent macro to copy one structure to another.
 
-=cut
-*/
+=for apidoc Am|void|Poison|void* dest|int nitems|type
+
+Fill up memory with a pattern (byte 0xAB over and over again) that
+hopefully catches attempts to access uninitialized memory.
 
-#ifndef lint
+=cut */
 
 #define NEWSV(x,len)   newSV(len)
 
-#ifndef LEAKTEST
+#ifdef PERL_MALLOC_WRAP
+#define MEM_WRAP_CHECK(n,t) \
+       (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(PL_memory_wrap),0):0)
+#define MEM_WRAP_CHECK_1(n,t,a) \
+       (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a),0):0)
+#define MEM_WRAP_CHECK_2(n,t,a,b) \
+       (void)((sizeof(t)>1?(n):1)>((MEM_SIZE)~0)/sizeof(t)?(Perl_croak_nocontext(a,b),0):0)
+#define MEM_WRAP_CHECK_(n,t) MEM_WRAP_CHECK(n,t),
 
-#define New(x,v,n,t)   (v = (t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))
-#define Newc(x,v,n,t,c)        (v = (c*)safemalloc((MEM_SIZE)((n)*sizeof(t))))
-#define Newz(x,v,n,t)  (v = (t*)safemalloc((MEM_SIZE)((n)*sizeof(t)))), \
-                       memzero((char*)(v), (n)*sizeof(t))
-#define Renew(v,n,t) \
-         (v = (t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))
-#define Renewc(v,n,t,c) \
-         (v = (c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))
-#define Safefree(d)    safefree((Malloc_t)(d))
+#define PERL_STRLEN_ROUNDUP(n) ((void)(((n) > (MEM_SIZE)~0 - 2 * PERL_STRLEN_ROUNDUP_QUANTUM) ? (Perl_croak_nocontext(PL_memory_wrap),0):0),((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1)))
 
-#else /* LEAKTEST */
+#else
 
-#define New(x,v,n,t)   (v = (t*)safexmalloc((x),(MEM_SIZE)((n)*sizeof(t))))
-#define Newc(x,v,n,t,c)        (v = (c*)safexmalloc((x),(MEM_SIZE)((n)*sizeof(t))))
-#define Newz(x,v,n,t)  (v = (t*)safexmalloc((x),(MEM_SIZE)((n)*sizeof(t)))), \
-                        memzero((char*)(v), (n)*sizeof(t))
-#define Renew(v,n,t) \
-         (v = (t*)safexrealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))
-#define Renewc(v,n,t,c) \
-         (v = (c*)safexrealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))
-#define Safefree(d)    safexfree((Malloc_t)(d))
+#define MEM_WRAP_CHECK(n,t)
+#define MEM_WRAP_CHECK_1(n,t,a)
+#define MEM_WRAP_CHECK_2(n,t,a,b)
+#define MEM_WRAP_CHECK_(n,t)
+
+#define PERL_STRLEN_ROUNDUP(n) (((n-1+PERL_STRLEN_ROUNDUP_QUANTUM)&~((MEM_SIZE)PERL_STRLEN_ROUNDUP_QUANTUM-1)))
 
-#define MAXXCOUNT 1400
-#define MAXY_SIZE 80
-#define MAXYCOUNT 16                   /* (MAXY_SIZE/4 + 1) */
-extern long xcount[MAXXCOUNT];
-extern long lastxcount[MAXXCOUNT];
-extern long xycount[MAXXCOUNT][MAXYCOUNT];
-extern long lastxycount[MAXXCOUNT][MAXYCOUNT];
+#endif
 
-#endif /* LEAKTEST */
+#ifdef PERL_MEM_LOG
+Malloc_t Perl_mem_log_alloc(const UV n, const UV typesize, const char *typename, Malloc_t newalloc, const char *filename, const int linenumber);
+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);
+Malloc_t Perl_mem_log_free(Malloc_t oldalloc, const char *filename, const int linenumber);
+#endif
 
-#define Move(s,d,n,t)  (void)memmove((char*)(d),(char*)(s), (n) * sizeof(t))
-#define Copy(s,d,n,t)  (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))
-#define Zero(d,n,t)    (void)memzero((char*)(d), (n) * sizeof(t))
+#ifdef PERL_MEM_LOG
+#define MEM_LOG_ALLOC(n,t,a)     Perl_mem_log_alloc(n,sizeof(t),STRINGIFY(t),a,__FILE__,__LINE__)
+#define MEM_LOG_REALLOC(n,t,v,a) Perl_mem_log_realloc(n,sizeof(t),STRINGIFY(t),v,a,__FILE__,__LINE__)
+#define MEM_LOG_FREE(a)           Perl_mem_log_free(a,__FILE__,__LINE__)
+#endif
 
-#else /* lint */
+#ifndef MEM_LOG_ALLOC
+#define MEM_LOG_ALLOC(n,t,a)     (a)
+#endif
+#ifndef MEM_LOG_REALLOC
+#define MEM_LOG_REALLOC(n,t,v,a) (a)
+#endif
+#ifndef MEM_LOG_FREE
+#define MEM_LOG_FREE(a)          (a)
+#endif
 
-#define New(x,v,n,s)   (v = Null(s *))
-#define Newc(x,v,n,s,c)        (v = Null(s *))
-#define Newz(x,v,n,s)  (v = Null(s *))
-#define Renew(v,n,s)   (v = Null(s *))
-#define Move(s,d,n,t)
-#define Copy(s,d,n,t)
-#define Zero(d,n,t)
-#define Safefree(d)    (d) = (d)
+#define Newx(v,n,t)    (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(t*)safemalloc((MEM_SIZE)((n)*sizeof(t))))))
+#define Newxc(v,n,t,c) (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(c*)safemalloc((MEM_SIZE)((n)*sizeof(t))))))
+#define Newxz(v,n,t)   (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(t*)safemalloc((MEM_SIZE)((n)*sizeof(t)))))), \
+                       memzero((char*)(v), (n)*sizeof(t))
+/* pre 5.9.x compatibility */
+#define New(x,v,n,t)   Newx(v,n,t)
+#define Newc(x,v,n,t,c)        Newxc(v,n,t,c)
+#define Newc(x,v,n,t,c)        Newxc(v,n,t,c)
 
-#endif /* lint */
+#define Renew(v,n,t) \
+         (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_REALLOC(n,t,v,(t*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))))
+#define Renewc(v,n,t,c) \
+         (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_REALLOC(n,t,v,(c*)saferealloc((Malloc_t)(v),(MEM_SIZE)((n)*sizeof(t))))))
+
+#ifdef PERL_POISON
+#define Safefree(d) \
+  ((d) ? (void)(safefree(MEM_LOG_FREE((Malloc_t)(d)))), Poison(&(d), 1, Malloc_t)) : (void) 0)
+#else
+#define Safefree(d)    safefree(MEM_LOG_FREE((Malloc_t)(d)))
+#endif
+
+#define Move(s,d,n,t)  (MEM_WRAP_CHECK_(n,t) (void)memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
+#define Copy(s,d,n,t)  (MEM_WRAP_CHECK_(n,t) (void)memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
+#define Zero(d,n,t)    (MEM_WRAP_CHECK_(n,t) (void)memzero((char*)(d), (n) * sizeof(t)))
+
+#define MoveD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memmove((char*)(d),(const char*)(s), (n) * sizeof(t)))
+#define CopyD(s,d,n,t) (MEM_WRAP_CHECK_(n,t) memcpy((char*)(d),(const char*)(s), (n) * sizeof(t)))
+#ifdef HAS_MEMSET
+#define ZeroD(d,n,t)   (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)))
+#else
+/* Using bzero(), which returns void.  */
+#define ZeroD(d,n,t)   (MEM_WRAP_CHECK_(n,t) memzero((char*)(d), (n) * sizeof(t)),d)
+#endif
+
+#define Poison(d,n,t)  (MEM_WRAP_CHECK_(n,t) (void)memset((char*)(d), 0xAB, (n) * sizeof(t)))
 
 #ifdef USE_STRUCT_COPY
 #define StructCopy(s,d,t) (*((t*)(d)) = *((t*)(s)))
 #else
 #define StructCopy(s,d,t) Copy(s,d,1,t)
 #endif
+
+#define C_ARRAY_LENGTH(a)      (sizeof(a)/sizeof((a)[0]))
+
+#ifdef NEED_VA_COPY
+# ifdef va_copy
+#  define Perl_va_copy(s, d) va_copy(d, s)
+# else
+#  if defined(__va_copy)
+#   define Perl_va_copy(s, d) __va_copy(d, s)
+#  else
+#   define Perl_va_copy(s, d) Copy(s, d, 1, va_list)
+#  endif
+# endif
+#endif
+
+/* convenience debug macros */
+#ifdef USE_ITHREADS
+#define pTHX_FORMAT  "Perl interpreter: 0x%p"
+#define pTHX__FORMAT ", Perl interpreter: 0x%p"
+#define pTHX_VALUE_   (void *)my_perl,
+#define pTHX_VALUE    (void *)my_perl
+#define pTHX__VALUE_ ,(void *)my_perl,
+#define pTHX__VALUE  ,(void *)my_perl
+#else
+#define pTHX_FORMAT 
+#define pTHX__FORMAT
+#define pTHX_VALUE_ 
+#define pTHX_VALUE
+#define pTHX__VALUE_ 
+#define pTHX__VALUE
+#endif /* USE_ITHREADS */