First stab at rationalizing the PyMem_ API.  Mixing PyObject_xyz with
PyMem_{Del, DEL} doesn't work yet (compilation problems).

pyport.h:  _PyMem_EXTRA is gone.

pmem.h:  Repaired comments.  PyMem_{Malloc, MALLOC} and
PyMem_{Realloc, REALLOC} now make the same x-platform guarantees when
asking for 0 bytes, and when passing a NULL pointer to the latter.

object.c:  PyMem_{Malloc, Realloc} just call their macro versions
now, since the latter take care of the x-platform 0 and NULL stuff
by themselves now.

pypcre.c, grow_stack():  So sue me.  On two lines, this called
PyMem_RESIZE to grow a "const" area.  It's not legit to realloc a
const area, so the compiler warned given the new expansion of
PyMem_RESIZE.  It would have gotten the same warning before if it
had used PyMem_Resize() instead; the older macro version, but not the
function version, silently cast away the constness.  IMO that was a wrong
thing to do, and the docs say the macro versions of PyMem_xyz are
deprecated anyway.  If somebody else is resizing const areas with the
macro spelling, they'll get a warning when they recompile now too.
diff --git a/Include/pymem.h b/Include/pymem.h
index b9c5d2c..3b9c0e2 100644
--- a/Include/pymem.h
+++ b/Include/pymem.h
@@ -18,30 +18,32 @@
    Python runtime switches to its own malloc (different from standard
    malloc), no recompilation is required for the extensions.
 
-   The macro versions trade compatibility for speed. They can be used
-   whenever there is a performance problem, but their use implies
-   recompilation of the code for each new Python release. The Python
-   core uses the macros because it *is* compiled on every upgrade.
-   This might not be the case with 3rd party extensions in a custom
-   setup (for example, a customer does not always have access to the
-   source of 3rd party deliverables). You have been warned! */
+   The macro versions are free to trade compatibility for speed, although
+   there's no guarantee they're ever faster.  Extensions shouldn't use the
+   macro versions, as they don't gurantee binary compatibility across
+   releases.
+
+   Do not mix calls to PyMem_xyz with calls to platform
+   malloc/realloc/calloc/free. */
 
 /*
  * Raw memory interface
  * ====================
  */
 
-/* To make sure the interpreter is user-malloc friendly, all memory
-   APIs are implemented on top of this one. */
-
 /* Functions */
 
-/* Function wrappers around PyMem_MALLOC and friends; useful if you
-   need to be sure that you are using the same memory allocator as
-   Python.  Note that the wrappers make sure that allocating 0 bytes
-   returns a non-NULL pointer, even if the underlying malloc
-   doesn't. Returned pointers must be checked for NULL explicitly.
-   No action is performed on failure. */
+/* Functions supplying platform-independent semantics for malloc/realloc/
+   free; useful if you need to be sure you're using the same memory
+   allocator as Python (this can be especially important on Windows, if
+   you need to make sure you're using the same MS malloc/free, and out of
+   the same heap, as the main Python DLL uses).
+   These functions make sure that allocating 0 bytes returns a distinct
+   non-NULL pointer (whenever possible -- if we're flat out of memory, NULL
+   may be returned), even if the platform malloc and realloc don't.
+   Returned pointers must be checked for NULL explicitly.  No action is
+   performed on failure (no exception is set, no warning is printed, etc).` */
+
 extern DL_IMPORT(void *) PyMem_Malloc(size_t);
 extern DL_IMPORT(void *) PyMem_Realloc(void *, size_t);
 extern DL_IMPORT(void) PyMem_Free(void *);
@@ -49,16 +51,29 @@
 /* Starting from Python 1.6, the wrappers Py_{Malloc,Realloc,Free} are
    no longer supported. They used to call PyErr_NoMemory() on failure. */
 
-/* Macros (override these if you want to a different malloc */
+/* Macros. */
 #ifndef PyMem_MALLOC
-#define PyMem_MALLOC(n)         malloc(n)
-#define PyMem_REALLOC(p, n)     realloc((void *)(p), (n))
-#define PyMem_FREE(p)           free((void *)(p))
+#ifdef MALLOC_ZERO_RETURNS_NULL
+#define PyMem_MALLOC(n)         malloc((n) ? (n) : 1)
+#else
+#define PyMem_MALLOC		malloc
 #endif
 
+/* Caution:  whether MALLOC_ZERO_RETURNS_NULL is #defined has nothing to
+   do with whether platform realloc(non-NULL, 0) normally frees the memory
+   or returns NULL.  Rather than introduce yet another config variation,
+   just make a realloc to 0 bytes act as if to 1 instead. */
+#define PyMem_REALLOC(p, n)     realloc((p), (n) ? (n) : 1)
+
+#define PyMem_FREE           	free
+#endif	/* PyMem_MALLOC */
+
 /*
  * Type-oriented memory interface
  * ==============================
+ *
+ * These are carried along for historical reasons.  There's rarely a good
+ * reason to use them anymore.
  */
 
 /* Functions */
@@ -66,29 +81,29 @@
 	( (type *) PyMem_Malloc((n) * sizeof(type)) )
 #define PyMem_Resize(p, type, n) \
 	( (p) = (type *) PyMem_Realloc((p), (n) * sizeof(type)) )
-#define PyMem_Del(p) PyMem_Free(p)
+
+/* In order to avoid breaking old code mixing PyObject_{New, NEW} with
+   PyMem_{Del, DEL} (there was no choice about this in 1.5.2), the latter
+   have to be redirected to the object allocator. */
+/* XXX The parser module needs rework before this can be enabled. */
+#if 0
+#define PyMem_Del  PyObject_Free
+#else
+#define PyMem_Del  PyMem_Free
+#endif
 
 /* Macros */
 #define PyMem_NEW(type, n) \
-	( (type *) PyMem_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) )
+	( (type *) PyMem_MALLOC((n) * sizeof(type)) )
+#define PyMem_RESIZE(p, type, n) \
+	( (p) = (type *) PyMem_REALLOC((p), (n) * sizeof(type)) )
 
-/* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */
-#define PyMem_RESIZE(p, type, n)			\
-	do {						\
-		size_t _sum = (n) * sizeof(type);	\
-		if (!_sum)				\
-			_sum = 1;			\
-		(p) = (type *)((p) ?			\
-			       PyMem_REALLOC(p, _sum) :	\
-			       PyMem_MALLOC(_sum));	\
-	} while (0)
-
-#define PyMem_DEL(p) PyMem_FREE(p)
-
-/* PyMem_XDEL is deprecated. To avoid the call when p is NULL,
-   it is recommended to write the test explicitly in the code.
-   Note that according to ANSI C, free(NULL) has no effect. */
-
+/* XXX The parser module needs rework before this can be enabled. */
+#if 0
+#define PyMem_DEL PyObject_FREE
+#else
+#define PyMem_DEL  PyMem_FREE
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/Include/pyport.h b/Include/pyport.h
index 86bbab2..790c7af 100644
--- a/Include/pyport.h
+++ b/Include/pyport.h
@@ -384,32 +384,10 @@
 extern double hypot(double, double);
 #endif
 
-
-/************************************
- * MALLOC COMPATIBILITY FOR pymem.h *
- ************************************/
-
 #ifndef DL_IMPORT       /* declarations for DLL import */
 #define DL_IMPORT(RTYPE) RTYPE
 #endif
 
-#ifdef MALLOC_ZERO_RETURNS_NULL
-/* Allocate an extra byte if the platform malloc(0) returns NULL.
-   Caution:  this bears no relation to whether realloc(p, 0) returns NULL
-   when p != NULL.  Even on platforms where malloc(0) does not return NULL,
-   realloc(p, 0) may act like free(p) and return NULL.  Examples include
-   Windows, and Python's own obmalloc.c (as of 2-Mar-2002).  For whatever
-   reason, our docs promise that PyMem_Realloc(p, 0) won't act like
-   free(p) or return NULL, so realloc() calls may have to be hacked
-   too, but MALLOC_ZERO_RETURNS_NULL's state is irrelevant to realloc (it
-   needs a different hack).
-*/
-#define _PyMem_EXTRA 1
-#else
-#define _PyMem_EXTRA 0
-#endif
-
-
 /* If the fd manipulation macros aren't defined,
    here is a set that should do the job */
 
diff --git a/Modules/pypcre.c b/Modules/pypcre.c
index e0aa8d0..5f21005 100644
--- a/Modules/pypcre.c
+++ b/Modules/pypcre.c
@@ -3078,8 +3078,11 @@
       else {md->length = 80;}
     }
   PyMem_RESIZE(md->offset_top, int, md->length);
-  PyMem_RESIZE(md->eptr, const uschar *, md->length);
-  PyMem_RESIZE(md->ecode, const uschar *, md->length);
+  /* Can't realloc a pointer-to-const; cast const away. */
+  md->eptr = (const uschar **)PyMem_Realloc((void *)md->eptr,
+  					    sizeof(uschar *) * md->length);
+  md->ecode = (const uschar **)PyMem_Realloc((void *)md->ecode,
+  					     sizeof(uschar *) * md->length);
   PyMem_RESIZE(md->off_num, int, md->length);
   PyMem_RESIZE(md->r1, int, md->length);
   PyMem_RESIZE(md->r2, int, md->length);
diff --git a/Objects/object.c b/Objects/object.c
index 6090838..e47f80e 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -1897,18 +1897,13 @@
 void *
 PyMem_Malloc(size_t nbytes)
 {
-#if _PyMem_EXTRA > 0
-	if (nbytes == 0)
-		nbytes = _PyMem_EXTRA;
-#endif
 	return PyMem_MALLOC(nbytes);
 }
 
 void *
 PyMem_Realloc(void *p, size_t nbytes)
 {
-	/* See comment near MALLOC_ZERO_RETURNS_NULL in pyport.h. */
-	return PyMem_REALLOC(p, nbytes ? nbytes : 1);
+	return PyMem_REALLOC(p, nbytes);
 }
 
 void