]> git.ipfire.org Git - thirdparty/bash.git/blobdiff - lib/malloc/gmalloc.c
Imported from ../bash-2.02.tar.gz.
[thirdparty/bash.git] / lib / malloc / gmalloc.c
index 8690b1260a33feca128d4cd14b51018131da939d..dd24146de1781e7123c66795d1c072f4a06221d9 100644 (file)
@@ -1,7 +1,3 @@
-/* DO NOT EDIT THIS FILE -- it is automagically generated.  -*- C -*- */
-
-#define _MALLOC_INTERNAL
-
 /* The malloc headers and source files from the C library follow here.  */
 
 /* Declarations for `malloc' and friends.
@@ -20,118 +16,173 @@ Library General Public License for more details.
 
 You should have received a copy of the GNU Library General Public
 License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+ot, write to the Free Software Foundation, Inc., 59 Temple Place -
+Suite 330, Boston, MA 02111-1307, USA.
 
    The author may be reached (Email) at the address mike@ai.mit.edu,
    or (US mail) as Mike Haertel c/o Free Software Foundation.  */
 
-#ifndef _MALLOC_H
-
-#define _MALLOC_H      1
+/* XXX NOTES:
+    1. Augment the mstats struct so we can see how many blocks for fragments
+       and how many blocks for large requests were allocated.
+*/
 
-#ifdef _MALLOC_INTERNAL
+/* CHANGES:
+    1. Reorganized the source for my benefit.
+    2. Integrated the range-checking code by default.
+    3.  free(0) no longer dumps core.
+    4.  Extended the statistics.
+    5.  Fixed a couple of places where the stats were not kept correctly.
+*/
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
-#if    defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
-#include <string.h>
+#if defined (HAVE_STRING_H)
+#  include <string.h>
 #else
-#ifndef memset
-#define        memset(s, zero, n)      bzero ((s), (n))
-#endif
-#ifndef memcpy
-#define        memcpy(d, s, n)         bcopy ((s), (d), (n))
-#endif
+#  include <strings.h>
 #endif
 
-#if    defined (__GNU_LIBRARY__) || (defined (__STDC__) && __STDC__)
-#include <limits.h>
-#else
-#ifndef CHAR_BIT
-#define        CHAR_BIT        8
+#if defined (HAVE_LIMITS_H)
+#  include <limits.h>
 #endif
+
+#if defined (HAVE_UNISTD_H)
+#  ifdef _MINIX
+#    include <sys/types.h>
+#  endif
+#  include <unistd.h>
 #endif
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
+#if defined (HAVE_STDDEF_H)
+#  include <stddef.h>
 #endif
+#include <errno.h>
 
-#endif /* _MALLOC_INTERNAL.  */
+#if defined (RCHECK) && !defined (botch)
+#  include <stdio.h>
+#  define STDIO_H_INCLUDED
+#endif
 
+#include "stdc.h"
 
-#ifdef __cplusplus
-extern "C"
-{
+#ifndef errno
+extern int errno;
 #endif
 
-#if defined (__cplusplus) || (defined (__STDC__) && __STDC__)
-#undef __P
-#define        __P(args)       args
-#undef __ptr_t
-#define        __ptr_t         void *
-#else /* Not C++ or ANSI C.  */
-#undef __P
-#define        __P(args)       ()
-#undef const
-#define        const
-#undef __ptr_t
-#define        __ptr_t         char *
-#endif /* C++ or ANSI C.  */
-
-#if defined (__STDC__) && __STDC__
-#include <stddef.h>
-#define        __malloc_size_t         size_t
-#define        __malloc_ptrdiff_t      ptrdiff_t
+/* Need an autoconf test for this. */
+#if __STDC__
+#  undef  genptr_t
+#  define genptr_t     void *
 #else
-#define        __malloc_size_t         unsigned int
-#define        __malloc_ptrdiff_t      int
+#  undef  genptr_t
+#  define genptr_t     char *
+#endif /* !__STDC__ */
+
+#if !defined (HAVE_MEMSET)
+#  define      memset(s, zero, n)      bzero ((s), (n))
+#endif
+#if !defined (HAVE_MEMCPY)
+#  define      memcpy(d, s, n)         bcopy ((s), (d), (n))
+#endif
+
+/* Cope with systems lacking `memmove'.    */
+#if !defined (HAVE_MEMMOVE) && !defined (memmove)
+static void malloc_safe_bcopy __P ((genptr_t, genptr_t, size_t));
+#  define memmove(to, from, size)      malloc_safe_bcopy ((from), (to), (size))
 #endif
 
 #ifndef        NULL
 #define        NULL    0
 #endif
 
+#ifndef min
+#define min(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+/* Return values for `mprobe': these are the kinds of inconsistencies that
+   `mcheck' enables detection of.  */
+enum mcheck_status
+  {
+    MCHECK_DISABLED = -1,      /* Consistency checking is not turned on.  */
+    MCHECK_OK,                 /* Block is fine.  */
+    MCHECK_FREE,               /* Block freed twice.  */
+    MCHECK_HEAD,               /* Memory before the block was clobbered.  */
+    MCHECK_TAIL                        /* Memory after the block was clobbered.  */
+  };
+
+/* Statistics available to the user.  */
+struct mstats
+  {
+    size_t bytes_total; /* Total size of the heap. */
+    size_t chunks_used; /* Chunks allocated by the user. */
+    size_t bytes_used; /* Byte total of user-allocated chunks. */
+    size_t chunks_free; /* Chunks in the free list. */
+    size_t bytes_free; /* Byte total of chunks in the free list. */
+    int nmalloc;       /* Total number of calls to malloc. */
+    int nfree;         /* Total number of calls to free. */
+    int nrealloc;      /* Total number of calls to realloc. */
+    int nsbrk;         /* Total number of calls to sbrk. */
+    size_t tsbrk;      /* Total number of bytes allocated via sbrk. */
+    int negsbrk;       /* Total number of calls to sbrk with a negative arg */
+    size_t tnegsbrk;   /* Total number of bytes returned to the kernel. */
+  };
+
+#ifdef RCHECK
+/* Arbitrary magical numbers.  */
+#define MAGICWORD      0xfedabeeb
+#define MAGICFREE      0xd8675309
+#define MAGICBYTE      ((char) 0xd7)
+#define MALLOCFLOOD    ((char) 0x93)
+#define FREEFLOOD      ((char) 0x95)
 
+struct hdr
+  {
+    size_t size;               /* Exact size requested by user.  */
+    u_int32_t magic;           /* Magic number to check header integrity.  */
+  };
+#endif /* RCHECK */
+
+/* Functions exported by this library. */
 /* Allocate SIZE bytes of memory.  */
-extern __ptr_t malloc __P ((__malloc_size_t __size));
+extern genptr_t malloc __P ((size_t __size));
+
 /* Re-allocate the previously allocated block
-   in __ptr_t, making the new block SIZE bytes long.  */
-extern __ptr_t realloc __P ((__ptr_t __ptr, __malloc_size_t __size));
+   in genptr_t, making the new block SIZE bytes long.  */
+extern genptr_t realloc __P ((genptr_t __ptr, size_t __size));
+
 /* Allocate NMEMB elements of SIZE bytes each, all initialized to 0.  */
-extern __ptr_t calloc __P ((__malloc_size_t __nmemb, __malloc_size_t __size));
+extern genptr_t calloc __P ((size_t __nmemb, size_t __size));
+
 /* Free a block allocated by `malloc', `realloc' or `calloc'.  */
-extern void free __P ((__ptr_t __ptr));
+extern void free __P ((genptr_t __ptr));
 
 /* Allocate SIZE bytes allocated to ALIGNMENT bytes.  */
-#if ! (defined (_MALLOC_INTERNAL) && __DJGPP__ - 0 == 1) /* Avoid conflict.  */
-extern __ptr_t memalign __P ((__malloc_size_t __alignment,
-                             __malloc_size_t __size));
-#endif
+extern genptr_t memalign __P ((size_t __alignment, size_t __size));
 
-/* Allocate SIZE bytes on a page boundary.  */
-#if ! (defined (_MALLOC_INTERNAL) && defined (emacs)) /* Avoid conflict.  */
-extern __ptr_t valloc __P ((__malloc_size_t __size));
-#endif
+/* Pick up the current statistics. */
+extern struct mstats mstats __P ((void));
 
+#ifdef RCHECK
+extern enum mcheck_status mprobe __P((genptr_t ptr));
+#endif
 
-#ifdef _MALLOC_INTERNAL
+/* End of exported functions. */
 
 /* The allocator divides the heap into blocks of fixed size; large
    requests receive one or more whole blocks, and small requests
    receive a fragment of a block.  Fragment sizes are powers of two,
    and all fragments of a block are the same size.  When all the
    fragments in a block have been freed, the block itself is freed.  */
-#define INT_BIT                (CHAR_BIT * sizeof(int))
-#define BLOCKLOG       (INT_BIT > 16 ? 12 : 9)
-#define BLOCKSIZE      (1 << BLOCKLOG)
+#define BLOCKLOG       12
+#define BLOCKSIZE      4096            /* 1 << BLOCKLOG */
 #define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
 
 /* Determine the amount of memory spanned by the initial heap table
    (not an absolute limit).  */
-#define HEAP           (INT_BIT > 16 ? 4194304 : 65536)
+#define HEAP           4194304         /* 1 << 22 */
 
 /* Number of contiguous free blocks allowed to build up at the end of
    memory before they will be returned to the system.  */
@@ -150,40 +201,43 @@ typedef union
          {
            struct
              {
-               __malloc_size_t nfree; /* Free frags in a fragmented block.  */
-               __malloc_size_t first; /* First free fragment of the block.  */
+               size_t nfree; /* Free frags in a fragmented block.  */
+               size_t first; /* First free fragment of the block.  */
              } frag;
            /* For a large object, in its first block, this has the number
               of blocks in the object.  In the other blocks, this has a
               negative number which says how far back the first block is.  */
-           __malloc_ptrdiff_t size;
+           ptrdiff_t size;
          } info;
       } busy;
-    /* Heap information for a free block
-       (that may be the first of a free cluster).  */
+    /* Heap information for a free block (that may be the first of a
+       free cluster).  */
     struct
       {
-       __malloc_size_t size;   /* Size (in blocks) of a free cluster.  */
-       __malloc_size_t next;   /* Index of next free cluster.  */
-       __malloc_size_t prev;   /* Index of previous free cluster.  */
+       size_t size;    /* Size (in blocks) of a free cluster.  */
+       size_t next;    /* Index of next free cluster.  */
+       size_t prev;    /* Index of previous free cluster.  */
       } free;
   } malloc_info;
 
 /* Pointer to first block of the heap.  */
-extern char *_heapbase;
+static char *_heapbase;
 
 /* Table indexed by block number giving per-block information.  */
-extern malloc_info *_heapinfo;
+static malloc_info *_heapinfo;
 
 /* Address to block number and vice versa.  */
 #define BLOCK(A)       (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
-#define ADDRESS(B)     ((__ptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+#define ADDRESS(B)     ((genptr_t) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Number of info entries.  */
+static size_t heapsize;
 
 /* Current search index for the heap table.  */
-extern __malloc_size_t _heapindex;
+static size_t _heapindex;
 
 /* Limit of valid info table indices.  */
-extern __malloc_size_t _heaplimit;
+static size_t _heaplimit;
 
 /* Doubly linked lists of free fragments.  */
 struct list
@@ -193,270 +247,127 @@ struct list
   };
 
 /* Free list headers for each fragment size.  */
-extern struct list _fraghead[];
+static struct list _fraghead[BLOCKLOG];
 
-/* List of blocks allocated with `memalign' (or `valloc').  */
+/* List of blocks allocated with `memalign'.  */
 struct alignlist
   {
     struct alignlist *next;
-    __ptr_t aligned;           /* The address that memaligned returned.  */
-    __ptr_t exact;             /* The address that malloc returned.  */
+    genptr_t aligned;          /* The address that memaligned returned.  */
+    genptr_t exact;            /* The address that malloc returned.  */
   };
-extern struct alignlist *_aligned_blocks;
 
-/* Instrumentation.  */
-extern __malloc_size_t _chunks_used;
-extern __malloc_size_t _bytes_used;
-extern __malloc_size_t _chunks_free;
-extern __malloc_size_t _bytes_free;
+/* List of blocks allocated by memalign.  */
+static struct alignlist *_aligned_blocks = NULL;
 
 /* Internal versions of `malloc', `realloc', and `free'
-   used when these functions need to call each other.
-   They are the same but don't call the hooks.  */
-extern __ptr_t _malloc_internal __P ((__malloc_size_t __size));
-extern __ptr_t _realloc_internal __P ((__ptr_t __ptr, __malloc_size_t __size));
-extern void _free_internal __P ((__ptr_t __ptr));
-
-#endif /* _MALLOC_INTERNAL.  */
+   used when these functions need to call each other. */
+static genptr_t imalloc __P ((size_t __size));
+static genptr_t irealloc __P ((genptr_t __ptr, size_t __size));
+static void ifree __P ((genptr_t __ptr));
 
 /* Given an address in the middle of a malloc'd object,
    return the address of the beginning of the object.  */
-extern __ptr_t malloc_find_object_address __P ((__ptr_t __ptr));
+static genptr_t malloc_find_object_address __P ((genptr_t __ptr));
 
 /* Underlying allocation function; successive calls should
    return contiguous pieces of memory.  */
-extern __ptr_t (*__morecore) __P ((__malloc_ptrdiff_t __size));
-
-/* Default value of `__morecore'.  */
-extern __ptr_t __default_morecore __P ((__malloc_ptrdiff_t __size));
-
-/* If not NULL, this function is called after each time
-   `__morecore' is called to increase the data size.  */
-extern void (*__after_morecore_hook) __P ((void));
+static genptr_t default_morecore __P ((ptrdiff_t __size));
 
 /* Number of extra blocks to get each time we ask for more core.
-   This reduces the frequency of calling `(*__morecore)'.  */
-extern __malloc_size_t __malloc_extra_blocks;
+   This reduces the frequency of calling `default_morecore'.  */
+static size_t malloc_extra_blocks;
 
 /* Nonzero if `malloc' has been called and done its initialization.  */
-extern int __malloc_initialized;
+static int malloc_initialized;
 /* Function called to initialize malloc data structures.  */
-extern int __malloc_initialize __P ((void));
+static int malloc_initialize __P ((void));
 
-/* Hooks for debugging versions.  */
-extern void (*__malloc_initialize_hook) __P ((void));
-extern void (*__free_hook) __P ((__ptr_t __ptr));
-extern __ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
-extern __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
-extern __ptr_t (*__memalign_hook) __P ((__malloc_size_t __size,
-                                       __malloc_size_t __alignment));
-
-/* Return values for `mprobe': these are the kinds of inconsistencies that
-   `mcheck' enables detection of.  */
-enum mcheck_status
-  {
-    MCHECK_DISABLED = -1,      /* Consistency checking is not turned on.  */
-    MCHECK_OK,                 /* Block is fine.  */
-    MCHECK_FREE,               /* Block freed twice.  */
-    MCHECK_HEAD,               /* Memory before the block was clobbered.  */
-    MCHECK_TAIL                        /* Memory after the block was clobbered.  */
-  };
-
-/* Activate a standard collection of debugging hooks.  This must be called
-   before `malloc' is ever called.  ABORTFUNC is called with an error code
-   (see enum above) when an inconsistency is detected.  If ABORTFUNC is
-   null, the standard function prints on stderr and then calls `abort'.  */
-extern int mcheck __P ((void (*__abortfunc) __P ((enum mcheck_status))));
-
-/* Check for aberrations in a particular malloc'd block.  You must have
-   called `mcheck' already.  These are the same checks that `mcheck' does
-   when you free or reallocate a block.  */
-extern enum mcheck_status mprobe __P ((__ptr_t __ptr));
-
-/* Activate a standard collection of tracing hooks.  */
-extern void mtrace __P ((void));
-extern void muntrace __P ((void));
-
-/* Statistics available to the user.  */
-struct mstats
-  {
-    __malloc_size_t bytes_total; /* Total size of the heap. */
-    __malloc_size_t chunks_used; /* Chunks allocated by the user. */
-    __malloc_size_t bytes_used;        /* Byte total of user-allocated chunks. */
-    __malloc_size_t chunks_free; /* Chunks in the free list. */
-    __malloc_size_t bytes_free;        /* Byte total of chunks in the free list. */
-  };
-
-/* Pick up the current statistics. */
-extern struct mstats mstats __P ((void));
-
-/* Call WARNFUN with a warning message when memory usage is high.  */
-extern void memory_warnings __P ((__ptr_t __start,
-                                 void (*__warnfun) __P ((const char *))));
-
-
-/* Relocating allocator.  */
-
-/* Allocate SIZE bytes, and store the address in *HANDLEPTR.  */
-extern __ptr_t r_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
-
-/* Free the storage allocated in HANDLEPTR.  */
-extern void r_alloc_free __P ((__ptr_t *__handleptr));
-
-/* Adjust the block at HANDLEPTR to be SIZE bytes long.  */
-extern __ptr_t r_re_alloc __P ((__ptr_t *__handleptr, __malloc_size_t __size));
-
-
-#ifdef __cplusplus
-}
+#ifdef RCHECK
+static void zmemset __P((genptr_t, int, size_t));
+static enum mcheck_status checkhdr __P((const struct hdr *));
+static void mabort __P((enum mcheck_status));
 #endif
 
-#endif /* malloc.h  */
-/* Memory allocator `malloc'.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-                 Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
-   The author may be reached (Email) at the address mike@ai.mit.edu,
-   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
-
-#ifndef        _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-#include <errno.h>
-
-/* How to really get more memory.  */
-__ptr_t (*__morecore) __P ((ptrdiff_t __size)) = __default_morecore;
-
-/* Debugging hook for `malloc'.  */
-__ptr_t (*__malloc_hook) __P ((__malloc_size_t __size));
-
-/* Pointer to the base of the first block.  */
-char *_heapbase;
-
-/* Block information table.  Allocated with align/__free (not malloc/free).  */
-malloc_info *_heapinfo;
-
-/* Number of info entries.  */
-static __malloc_size_t heapsize;
-
-/* Search index in the info table.  */
-__malloc_size_t _heapindex;
-
-/* Limit of valid info table indices.  */
-__malloc_size_t _heaplimit;
-
-/* Free lists for each fragment size.  */
-struct list _fraghead[BLOCKLOG];
-
 /* Instrumentation.  */
-__malloc_size_t _chunks_used;
-__malloc_size_t _bytes_used;
-__malloc_size_t _chunks_free;
-__malloc_size_t _bytes_free;
-
-/* Are you experienced?  */
-int __malloc_initialized;
-
-__malloc_size_t __malloc_extra_blocks;
-
-void (*__malloc_initialize_hook) __P ((void));
-void (*__after_morecore_hook) __P ((void));
-
+static size_t chunks_used;
+static size_t bytes_used;
+static size_t chunks_free;
+static size_t bytes_free;
+static int nmalloc, nfree, nrealloc;
+static int nsbrk;
+static size_t tsbrk;
+static int negsbrk;
+static size_t tnegsbrk;
 
 /* Aligned allocation.  */
-static __ptr_t align __P ((__malloc_size_t));
-static __ptr_t
+static genptr_t
 align (size)
-     __malloc_size_t size;
+     size_t size;
 {
-  __ptr_t result;
+  genptr_t result;
   unsigned long int adj;
 
-  result = (*__morecore) (size);
+  result = default_morecore (size);
   adj = (unsigned long int) ((unsigned long int) ((char *) result -
                                                  (char *) NULL)) % BLOCKSIZE;
   if (adj != 0)
     {
-      __ptr_t new;
+      genptr_t new;
       adj = BLOCKSIZE - adj;
-      new = (*__morecore) (adj);
+      new = default_morecore (adj);
       result = (char *) result + adj;
     }
 
-  if (__after_morecore_hook)
-    (*__after_morecore_hook) ();
-
   return result;
 }
 
 /* Get SIZE bytes, if we can get them starting at END.
    Return the address of the space we got.
    If we cannot get space at END, fail and return -1.  */
-static __ptr_t get_contiguous_space __P ((__malloc_ptrdiff_t, __ptr_t));
-static __ptr_t
+static genptr_t
 get_contiguous_space (size, position)
-     __malloc_ptrdiff_t size;
-     __ptr_t position;
+     ptrdiff_t size;
+     genptr_t position;
 {
-  __ptr_t before;
-  __ptr_t after;
+  genptr_t before;
+  genptr_t after;
 
-  before = (*__morecore) (0);
+  before = default_morecore (0);
   /* If we can tell in advance that the break is at the wrong place,
      fail now.  */
   if (before != position)
     return 0;
 
   /* Allocate SIZE bytes and get the address of them.  */
-  after = (*__morecore) (size);
+  after = default_morecore (size);
   if (!after)
     return 0;
 
   /* It was not contiguous--reject it.  */
   if (after != position)
     {
-      (*__morecore) (- size);
+      default_morecore (- size);
       return 0;
     }
 
   return after;
 }
 
-
 /* This is called when `_heapinfo' and `heapsize' have just
    been set to describe a new info table.  Set up the table
    to describe itself and account for it in the statistics.  */
-static void register_heapinfo __P ((void));
-#ifdef __GNUC__
-__inline__
-#endif
-static void
+inline static void
 register_heapinfo ()
 {
-  __malloc_size_t block, blocks;
+  size_t block, blocks;
 
   block = BLOCK (_heapinfo);
   blocks = BLOCKIFY (heapsize * sizeof (malloc_info));
 
   /* Account for the _heapinfo block itself in the statistics.  */
-  _bytes_used += blocks * BLOCKSIZE;
-  ++_chunks_used;
+  bytes_used += blocks * BLOCKSIZE;
+  ++chunks_used;
 
   /* Describe the heapinfo block itself in the heapinfo.  */
   _heapinfo[block].busy.type = 0;
@@ -467,15 +378,12 @@ register_heapinfo ()
 }
 
 /* Set everything up and remember that we have.  */
-int
-__malloc_initialize ()
+static int
+malloc_initialize ()
 {
-  if (__malloc_initialized)
+  if (malloc_initialized)
     return 0;
 
-  if (__malloc_initialize_hook)
-    (*__malloc_initialize_hook) ();
-
   heapsize = HEAP / BLOCKSIZE;
   _heapinfo = (malloc_info *) align (heapsize * sizeof (malloc_info));
   if (_heapinfo == NULL)
@@ -489,22 +397,43 @@ __malloc_initialize ()
 
   register_heapinfo ();
 
-  __malloc_initialized = 1;
+  malloc_initialized = 1;
   return 1;
 }
 
+/* Allocate INCREMENT more bytes of data space,
+   and return the start of data space, or NULL on errors.
+   If INCREMENT is negative, shrink data space.  */
+static genptr_t
+default_morecore (increment)
+     ptrdiff_t increment;
+{
+  genptr_t result;
+
+  nsbrk++;
+  tsbrk += increment;
+  if (increment < 0)
+    {
+      negsbrk++;
+      tnegsbrk += -increment;
+    }
+  result = (genptr_t) sbrk (increment);
+  if ((long)result == -1L)
+    return NULL;
+  return result;
+}
+
 static int morecore_recursing;
 
 /* Get neatly aligned memory, initializing or
    growing the heap info table as necessary. */
-static __ptr_t morecore __P ((__malloc_size_t));
-static __ptr_t
+static genptr_t
 morecore (size)
-     __malloc_size_t size;
+     size_t size;
 {
-  __ptr_t result;
+  genptr_t result;
   malloc_info *newinfo, *oldinfo;
-  __malloc_size_t newsize;
+  size_t newsize;
 
   if (morecore_recursing)
     /* Avoid recursion.  The caller will know how to handle a null return.  */
@@ -515,7 +444,7 @@ morecore (size)
     return NULL;
 
   /* Check if we need to grow the info table.  */
-  if ((__malloc_size_t) BLOCK ((char *) result + size) > heapsize)
+  if ((size_t) BLOCK ((char *) result + size) > heapsize)
     {
       /* Calculate the new _heapinfo table size.  We do not account for the
         added blocks in the table itself, as we hope to place them in
@@ -523,8 +452,8 @@ morecore (size)
         existing table.  */
       newsize = heapsize;
       do
-       newsize *= 2;
-      while ((__malloc_size_t) BLOCK ((char *) result + size) > newsize);
+       newsize <<= 1;
+      while ((size_t) BLOCK ((char *) result + size) > newsize);
 
       /* We must not reuse existing core for the new info table when called
         from realloc in the case of growing a large block, because the
@@ -540,8 +469,7 @@ morecore (size)
             `morecore_recursing' flag and return null.  */
          int save = errno;     /* Don't want to clobber errno with ENOMEM.  */
          morecore_recursing = 1;
-         newinfo = (malloc_info *) _realloc_internal
-           (_heapinfo, newsize * sizeof (malloc_info));
+         newinfo = (malloc_info *) irealloc (_heapinfo, newsize * sizeof (malloc_info));
          morecore_recursing = 0;
          if (newinfo == NULL)
            errno = save;
@@ -550,8 +478,7 @@ morecore (size)
              /* We found some space in core, and realloc has put the old
                 table's blocks on the free list.  Now zero the new part
                 of the table and install the new table location.  */
-             memset (&newinfo[heapsize], 0,
-                     (newsize - heapsize) * sizeof (malloc_info));
+             memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info));
              _heapinfo = newinfo;
              heapsize = newsize;
              goto got_heap;
@@ -566,37 +493,34 @@ morecore (size)
          /* Did it fail?  */
          if (newinfo == NULL)
            {
-             (*__morecore) (-size);
+             default_morecore (-size);
              return NULL;
            }
 
          /* Is it big enough to record status for its own space?
             If so, we win.  */
-         if ((__malloc_size_t) BLOCK ((char *) newinfo
-                                      + newsize * sizeof (malloc_info))
-             < newsize)
+         if ((size_t) BLOCK ((char *) newinfo + newsize * sizeof (malloc_info)) < newsize)
            break;
 
          /* Must try again.  First give back most of what we just got.  */
-         (*__morecore) (- newsize * sizeof (malloc_info));
+         default_morecore (- newsize * sizeof (malloc_info));
          newsize *= 2;
        }
 
       /* Copy the old table to the beginning of the new,
         and zero the rest of the new table.  */
       memcpy (newinfo, _heapinfo, heapsize * sizeof (malloc_info));
-      memset (&newinfo[heapsize], 0,
-             (newsize - heapsize) * sizeof (malloc_info));
+      memset (&newinfo[heapsize], 0, (newsize - heapsize) * sizeof (malloc_info));
       oldinfo = _heapinfo;
       _heapinfo = newinfo;
       heapsize = newsize;
 
       register_heapinfo ();
 
-      /* Reset _heaplimit so _free_internal never decides
+      /* Reset _heaplimit so ifree never decides
         it can relocate or resize the info table.  */
       _heaplimit = 0;
-      _free_internal (oldinfo);
+      ifree (oldinfo);
 
       /* The new heap limit includes the new table just allocated.  */
       _heaplimit = BLOCK ((char *) newinfo + heapsize * sizeof (malloc_info));
@@ -609,13 +533,13 @@ morecore (size)
 }
 
 /* Allocate memory from the heap.  */
-__ptr_t
-_malloc_internal (size)
-     __malloc_size_t size;
+static genptr_t
+imalloc (size)
+     size_t size;
 {
-  __ptr_t result;
-  __malloc_size_t block, blocks, lastblocks, start;
-  register __malloc_size_t i;
+  genptr_t result;
+  size_t block, blocks, lastblocks, start;
+  register size_t i;
   struct list *next;
 
   /* ANSI C allows `malloc (0)' to either return NULL, or to return a
@@ -625,7 +549,7 @@ _malloc_internal (size)
      expects `malloc (0)' to return non-NULL and breaks otherwise.
      Be compatible.  */
 
-#if    0
+#if 0
   if (size == 0)
     return NULL;
 #endif
@@ -643,7 +567,7 @@ _malloc_internal (size)
     {
       /* Small allocation to receive a fragment of a block.
         Determine the logarithm to base two of the fragment size. */
-      register __malloc_size_t log = 1;
+      register size_t log = 1;
       --size;
       while ((size /= 2) != 0)
        ++log;
@@ -656,7 +580,7 @@ _malloc_internal (size)
          /* There are free fragments of this size.
             Pop a fragment out of the fragment list and return it.
             Update the block's nfree and first counters. */
-         result = (__ptr_t) next;
+         result = (genptr_t) next;
          next->prev->next = next->next;
          if (next->next != NULL)
            next->next->prev = next->prev;
@@ -667,16 +591,16 @@ _malloc_internal (size)
               % BLOCKSIZE) >> log;
 
          /* Update the statistics.  */
-         ++_chunks_used;
-         _bytes_used += 1 << log;
-         --_chunks_free;
-         _bytes_free -= 1 << log;
+         ++chunks_used;
+         bytes_used += 1 << log;
+         --chunks_free;
+         bytes_free -= 1 << log;
        }
       else
        {
          /* No free fragments of the desired size, so get a new block
             and break it into fragments, returning the first.  */
-         result = malloc (BLOCKSIZE);
+         result = imalloc (BLOCKSIZE);
          if (result == NULL)
            return NULL;
 
@@ -686,7 +610,7 @@ _malloc_internal (size)
          next->prev = &_fraghead[log];
          _fraghead[log].next = next;
 
-         for (i = 2; i < (__malloc_size_t) (BLOCKSIZE >> log); ++i)
+         for (i = 2; i < (size_t) (BLOCKSIZE >> log); ++i)
            {
              next = (struct list *) ((char *) result + (i << log));
              next->next = _fraghead[log].next;
@@ -701,9 +625,9 @@ _malloc_internal (size)
          _heapinfo[block].busy.info.frag.nfree = i - 1;
          _heapinfo[block].busy.info.frag.first = i - 1;
 
-         _chunks_free += (BLOCKSIZE >> log) - 1;
-         _bytes_free += BLOCKSIZE - (1 << log);
-         _bytes_used -= BLOCKSIZE - (1 << log);
+         chunks_free += (BLOCKSIZE >> log) - 1;
+         bytes_free += BLOCKSIZE - (1 << log);
+         bytes_used -= BLOCKSIZE - (1 << log);
        }
     }
   else
@@ -720,7 +644,7 @@ _malloc_internal (size)
          if (block == start)
            {
              /* Need to get more from the system.  Get a little extra.  */
-             __malloc_size_t wantblocks = blocks + __malloc_extra_blocks;
+             size_t wantblocks = blocks + malloc_extra_blocks;
              block = _heapinfo[0].free.prev;
              lastblocks = _heapinfo[block].free.size;
              /* Check to see if the new core will be contiguous with the
@@ -737,7 +661,7 @@ _malloc_internal (size)
                     changed, if it got combined with a freed info table.  */
                  block = _heapinfo[0].free.prev;
                  _heapinfo[block].free.size += (wantblocks - lastblocks);
-                 _bytes_free += (wantblocks - lastblocks) * BLOCKSIZE;
+                 bytes_free += (wantblocks - lastblocks) * BLOCKSIZE;
                  _heaplimit += wantblocks - lastblocks;
                  continue;
                }
@@ -751,7 +675,8 @@ _malloc_internal (size)
              _heapinfo[block].free.next = 0;
              _heapinfo[0].free.prev = block;
              _heapinfo[_heapinfo[block].free.prev].free.next = block;
-             ++_chunks_free;
+             ++chunks_free;
+             bytes_free += wantblocks * BLOCKSIZE;
              /* Now loop to use some of that block for this allocation.  */
            }
        }
@@ -781,14 +706,14 @@ _malloc_internal (size)
            = _heapinfo[block].free.prev;
          _heapinfo[_heapinfo[block].free.prev].free.next
            = _heapindex = _heapinfo[block].free.next;
-         --_chunks_free;
+         --chunks_free;
        }
 
       _heapinfo[block].busy.type = 0;
       _heapinfo[block].busy.info.size = blocks;
-      ++_chunks_used;
-      _bytes_used += blocks * BLOCKSIZE;
-      _bytes_free -= blocks * BLOCKSIZE;
+      ++chunks_used;
+      bytes_used += blocks * BLOCKSIZE;
+      bytes_free -= blocks * BLOCKSIZE;
 
       /* Mark all the blocks of the object just allocated except for the
         first with a negative number so you can find the first block by
@@ -800,113 +725,55 @@ _malloc_internal (size)
   return result;
 }
 
-__ptr_t
+genptr_t
 malloc (size)
-     __malloc_size_t size;
-{
-  if (!__malloc_initialized && !__malloc_initialize ())
-    return NULL;
-
-  return (__malloc_hook != NULL ? *__malloc_hook : _malloc_internal) (size);
-}
-\f
-#ifndef _LIBC
-
-/* On some ANSI C systems, some libc functions call _malloc, _free
-   and _realloc.  Make them use the GNU functions.  */
-
-__ptr_t
-_malloc (size)
-     __malloc_size_t size;
+     size_t size;
 {
-  return malloc (size);
-}
-
-void
-_free (ptr)
-     __ptr_t ptr;
-{
-  free (ptr);
-}
-
-__ptr_t
-_realloc (ptr, size)
-     __ptr_t ptr;
-     __malloc_size_t size;
-{
-  return realloc (ptr, size);
-}
-
+#ifdef RCHECK
+  struct hdr *hdr;
 #endif
-/* Free a block of memory allocated by `malloc'.
-   Copyright 1990, 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
-                 Written May 1989 by Mike Haertel.
 
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+  nmalloc++;
 
-   The author may be reached (Email) at the address mike@ai.mit.edu,
-   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
-
-#ifndef        _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
+  if (malloc_initialized == 0 && malloc_initialize () == 0)
+    return NULL;
 
+#ifdef RCHECK
+  hdr = (struct hdr *) imalloc (sizeof (struct hdr) + size + 1);
+  if (hdr == NULL)
+    return NULL;
 
-/* Cope with systems lacking `memmove'.    */
-#ifndef memmove
-#if  (defined (MEMMOVE_MISSING) || \
-      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
-#ifdef emacs
-#undef __malloc_safe_bcopy
-#define __malloc_safe_bcopy safe_bcopy
-#endif
-/* This function is defined in realloc.c.  */
-extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t));
-#define memmove(to, from, size)        __malloc_safe_bcopy ((from), (to), (size))
-#endif
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  zmemset ((genptr_t) (hdr + 1), MALLOCFLOOD, size);
+  return (genptr_t) (hdr + 1);
+#else
+  return (imalloc (size));
 #endif
+}
 
+/* Free a block of memory allocated by `malloc'. */
 
-/* Debugging hook for free.  */
-void (*__free_hook) __P ((__ptr_t __ptr));
-
-/* List of blocks allocated by memalign.  */
-struct alignlist *_aligned_blocks = NULL;
-
-/* Return memory to the heap.
-   Like `free' but don't call a __free_hook if there is one.  */
-void
-_free_internal (ptr)
-     __ptr_t ptr;
+/* Return memory to the heap. */
+static void
+ifree (ptr)
+     genptr_t ptr;
 {
   int type;
-  __malloc_size_t block, blocks;
-  register __malloc_size_t i;
+  size_t block, blocks;
+  register size_t i;
   struct list *prev, *next;
-  __ptr_t curbrk;
-  const __malloc_size_t lesscore_threshold
-    /* Threshold of free space at which we will return some to the system.  */
-    = FINAL_FREE_BLOCKS + 2 * __malloc_extra_blocks;
-
+  genptr_t curbrk;
+  size_t lesscore_threshold;
   register struct alignlist *l;
 
   if (ptr == NULL)
     return;
 
+  /* Threshold of free space at which we will return some to the system.  */
+  lesscore_threshold = FINAL_FREE_BLOCKS + 2 * malloc_extra_blocks;
+
   for (l = _aligned_blocks; l != NULL; l = l->next)
     if (l->aligned == ptr)
       {
@@ -922,9 +789,9 @@ _free_internal (ptr)
     {
     case 0:
       /* Get as many statistics as early as we can.  */
-      --_chunks_used;
-      _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
-      _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+      --chunks_used;
+      bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+      bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
 
       /* Find the free cluster previous to this one in the free list.
         Start searching at the last block referenced; this may benefit
@@ -956,7 +823,7 @@ _free_internal (ptr)
          _heapinfo[block].free.prev = i;
          _heapinfo[i].free.next = block;
          _heapinfo[_heapinfo[block].free.next].free.prev = block;
-         ++_chunks_free;
+         ++chunks_free;
        }
 
       /* Now that the block is linked in, see if we can coalesce it
@@ -969,14 +836,14 @@ _free_internal (ptr)
          _heapinfo[block].free.next
            = _heapinfo[_heapinfo[block].free.next].free.next;
          _heapinfo[_heapinfo[block].free.next].free.prev = block;
-         --_chunks_free;
+         --chunks_free;
        }
 
       /* How many trailing free blocks are there now?  */
       blocks = _heapinfo[block].free.size;
 
       /* Where is the current end of accessible core?  */
-      curbrk = (*__morecore) (0);
+      curbrk = default_morecore (0);
 
       if (_heaplimit != 0 && curbrk == ADDRESS (_heaplimit))
        {
@@ -984,12 +851,12 @@ _free_internal (ptr)
             It's possible that moving _heapinfo will allow us to
             return some space to the system.  */
 
-         __malloc_size_t info_block = BLOCK (_heapinfo);
-         __malloc_size_t info_blocks = _heapinfo[info_block].busy.info.size;
-         __malloc_size_t prev_block = _heapinfo[block].free.prev;
-         __malloc_size_t prev_blocks = _heapinfo[prev_block].free.size;
-         __malloc_size_t next_block = _heapinfo[block].free.next;
-         __malloc_size_t next_blocks = _heapinfo[next_block].free.size;
+         size_t info_block = BLOCK (_heapinfo);
+         size_t info_blocks = _heapinfo[info_block].busy.info.size;
+         size_t prev_block = _heapinfo[block].free.prev;
+         size_t prev_blocks = _heapinfo[prev_block].free.size;
+         size_t next_block = _heapinfo[block].free.next;
+         size_t next_blocks = _heapinfo[next_block].free.size;
 
          if (/* Win if this block being freed is last in core, the info table
                 is just before it, the previous free block is just before the
@@ -1012,14 +879,14 @@ _free_internal (ptr)
              )
            {
              malloc_info *newinfo;
-             __malloc_size_t oldlimit = _heaplimit;
+             size_t oldlimit = _heaplimit;
 
              /* Free the old info table, clearing _heaplimit to avoid
                 recursion into this code.  We don't want to return the
                 table's blocks to the system before we have copied them to
                 the new location.  */
              _heaplimit = 0;
-             _free_internal (_heapinfo);
+             ifree (_heapinfo);
              _heaplimit = oldlimit;
 
              /* Tell malloc to search from the beginning of the heap for
@@ -1027,7 +894,7 @@ _free_internal (ptr)
              _heapindex = 0;
 
              /* Allocate new space for the info table and move its data.  */
-             newinfo = (malloc_info *) _malloc_internal (info_blocks
+             newinfo = (malloc_info *) imalloc (info_blocks
                                                          * BLOCKSIZE);
              memmove (newinfo, _heapinfo, info_blocks * BLOCKSIZE);
              _heapinfo = newinfo;
@@ -1043,16 +910,16 @@ _free_internal (ptr)
          /* Now see if we can return stuff to the system.  */
          if (block + blocks == _heaplimit && blocks >= lesscore_threshold)
            {
-             register __malloc_size_t bytes = blocks * BLOCKSIZE;
+             register size_t bytes = blocks * BLOCKSIZE;
              _heaplimit -= blocks;
-             (*__morecore) (-bytes);
+             default_morecore (-bytes);
              _heapinfo[_heapinfo[block].free.prev].free.next
                = _heapinfo[block].free.next;
              _heapinfo[_heapinfo[block].free.next].free.prev
                = _heapinfo[block].free.prev;
              block = _heapinfo[block].free.prev;
-             --_chunks_free;
-             _bytes_free -= bytes;
+             --chunks_free;
+             bytes_free -= bytes;
            }
        }
 
@@ -1062,10 +929,10 @@ _free_internal (ptr)
 
     default:
       /* Do some of the statistics.  */
-      --_chunks_used;
-      _bytes_used -= 1 << type;
-      ++_chunks_free;
-      _bytes_free += 1 << type;
+      --chunks_used;
+      bytes_used -= 1 << type;
+      ++chunks_free;
+      bytes_free += 1 << type;
 
       /* Get the address of the first free fragment in this block.  */
       prev = (struct list *) ((char *) ADDRESS (block) +
@@ -1076,7 +943,7 @@ _free_internal (ptr)
          /* If all fragments of this block are free, remove them
             from the fragment list and free the whole block.  */
          next = prev;
-         for (i = 1; i < (__malloc_size_t) (BLOCKSIZE >> type); ++i)
+         for (i = 1; i < (size_t) (BLOCKSIZE >> type); ++i)
            next = next->next;
          prev->prev->next = next;
          if (next != NULL)
@@ -1085,12 +952,12 @@ _free_internal (ptr)
          _heapinfo[block].busy.info.size = 1;
 
          /* Keep the statistics accurate.  */
-         ++_chunks_used;
-         _bytes_used += BLOCKSIZE;
-         _chunks_free -= BLOCKSIZE >> type;
-         _bytes_free -= BLOCKSIZE;
+         ++chunks_used;
+         bytes_used += BLOCKSIZE;
+         chunks_free -= BLOCKSIZE >> type;
+         bytes_free -= BLOCKSIZE;
 
-         free (ADDRESS (block));
+         ifree (ADDRESS (block));
        }
       else if (_heapinfo[block].busy.info.frag.nfree != 0)
        {
@@ -1128,76 +995,46 @@ _free_internal (ptr)
 /* Return memory to the heap.  */
 void
 free (ptr)
-     __ptr_t ptr;
+     genptr_t ptr;
 {
-  if (__free_hook != NULL)
-    (*__free_hook) (ptr);
-  else
-    _free_internal (ptr);
-}
-
-/* Define the `cfree' alias for `free'.  */
-#ifdef weak_alias
-weak_alias (free, cfree)
-#else
-void
-cfree (ptr)
-     __ptr_t ptr;
-{
-  free (ptr);
-}
+#ifdef RCHECK
+  struct hdr *hdr;
 #endif
-/* Change the size of a block allocated by `malloc'.
-   Copyright 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-                    Written May 1989 by Mike Haertel.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
+  nfree++;
 
-   The author may be reached (Email) at the address mike@ai.mit.edu,
-   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+  if (ptr == 0)
+    return;
 
-#ifndef        _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
+#ifdef RCHECK
+  hdr = ((struct hdr *) ptr) - 1;
+  checkhdr (hdr);
+  hdr->magic = MAGICFREE;
+  zmemset (ptr, FREEFLOOD, hdr->size);
+  ifree (hdr);
+#else
+  ifree (ptr);
 #endif
+}
 
+/* Change the size of a block allocated by `malloc'. */
 
-
-/* Cope with systems lacking `memmove'.    */
-#if  (defined (MEMMOVE_MISSING) || \
-      !defined(_LIBC) && !defined(STDC_HEADERS) && !defined(USG))
-
-#ifdef emacs
-#undef __malloc_safe_bcopy
-#define __malloc_safe_bcopy safe_bcopy
-#else
-
+#ifndef HAVE_MEMMOVE
 /* Snarfed directly from Emacs src/dispnew.c:
    XXX Should use system bcopy if it handles overlap.  */
 
 /* Like bcopy except never gets confused by overlap.  */
 
-void
-__malloc_safe_bcopy (afrom, ato, size)
-     __ptr_t afrom;
-     __ptr_t ato;
-     __malloc_size_t size;
+static void
+malloc_safe_bcopy (afrom, ato, size)
+     genptr_t afrom;
+     genptr_t ato;
+     size_t size;
 {
-  char *from = afrom, *to = ato;
+  char *from, *to;
 
+  from = afrom;
+  to = ato;
   if (size <= 0 || from == to)
     return;
 
@@ -1245,20 +1082,7 @@ __malloc_safe_bcopy (afrom, ato, size)
        }
     }
 }
-#endif /* emacs */
-
-#ifndef memmove
-extern void __malloc_safe_bcopy __P ((__ptr_t, __ptr_t, __malloc_size_t));
-#define memmove(to, from, size) __malloc_safe_bcopy ((from), (to), (size))
-#endif
-
-#endif
-
-
-#define min(A, B) ((A) < (B) ? (A) : (B))
-
-/* Debugging hook for realloc.  */
-__ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
+#endif /* !HAVE_MEMMOVE */
 
 /* Resize the given region to the new size, returning a pointer
    to the (possibly moved) region.  This is optimized for speed;
@@ -1266,22 +1090,22 @@ __ptr_t (*__realloc_hook) __P ((__ptr_t __ptr, __malloc_size_t __size));
    achieved by unconditionally allocating and copying to a
    new region.  This module has incestuous knowledge of the
    internals of both free and malloc. */
-__ptr_t
-_realloc_internal (ptr, size)
-     __ptr_t ptr;
-     __malloc_size_t size;
+static genptr_t
+irealloc (ptr, size)
+     genptr_t ptr;
+     size_t size;
 {
-  __ptr_t result;
+  genptr_t result;
   int type;
-  __malloc_size_t block, blocks, oldlimit;
+  size_t block, blocks, oldlimit;
 
   if (size == 0)
     {
-      _free_internal (ptr);
-      return _malloc_internal (0);
+      ifree (ptr);
+      return imalloc (0);
     }
   else if (ptr == NULL)
-    return _malloc_internal (size);
+    return imalloc (size);
 
   block = BLOCK (ptr);
 
@@ -1292,11 +1116,11 @@ _realloc_internal (ptr, size)
       /* Maybe reallocate a large block to a small fragment.  */
       if (size <= BLOCKSIZE / 2)
        {
-         result = _malloc_internal (size);
+         result = imalloc (size);
          if (result != NULL)
            {
              memcpy (result, ptr, size);
-             _free_internal (ptr);
+             ifree (ptr);
              return result;
            }
        }
@@ -1314,9 +1138,9 @@ _realloc_internal (ptr, size)
          _heapinfo[block].busy.info.size = blocks;
          /* We have just created a new chunk by splitting a chunk in two.
             Now we will free this chunk; increment the statistics counter
-            so it doesn't become wrong when _free_internal decrements it.  */
-         ++_chunks_used;
-         _free_internal (ADDRESS (block + blocks));
+            so it doesn't become wrong when ifree decrements it.  */
+         ++chunks_used;
+         ifree (ADDRESS (block + blocks));
          result = ptr;
        }
       else if (blocks == _heapinfo[block].busy.info.size)
@@ -1331,8 +1155,8 @@ _realloc_internal (ptr, size)
          /* Prevent free from actually returning memory to the system.  */
          oldlimit = _heaplimit;
          _heaplimit = 0;
-         _free_internal (ptr);
-         result = _malloc_internal (size);
+         ifree (ptr);
+         result = imalloc (size);
          if (_heaplimit == 0)
            _heaplimit = oldlimit;
          if (result == NULL)
@@ -1341,13 +1165,13 @@ _realloc_internal (ptr, size)
                 the thing we just freed.  Unfortunately it might
                 have been coalesced with its neighbors.  */
              if (_heapindex == block)
-               (void) _malloc_internal (blocks * BLOCKSIZE);
+               (void) imalloc (blocks * BLOCKSIZE);
              else
                {
-                 __ptr_t previous
-                   = _malloc_internal ((block - _heapindex) * BLOCKSIZE);
-                 (void) _malloc_internal (blocks * BLOCKSIZE);
-                 _free_internal (previous);
+                 genptr_t previous;
+                 previous  = imalloc ((block - _heapindex) * BLOCKSIZE);
+                 (void) imalloc (blocks * BLOCKSIZE);
+                 ifree (previous);
                }
              return NULL;
            }
@@ -1359,19 +1183,19 @@ _realloc_internal (ptr, size)
     default:
       /* Old size is a fragment; type is logarithm
         to base two of the fragment size.  */
-      if (size > (__malloc_size_t) (1 << (type - 1)) &&
-         size <= (__malloc_size_t) (1 << type))
+      if (size > (size_t) (1 << (type - 1)) &&
+         size <= (size_t) (1 << type))
        /* The new size is the same kind of fragment.  */
        result = ptr;
       else
        {
          /* The new size is different; allocate a new space,
             and copy the lesser of the new size and the old. */
-         result = _malloc_internal (size);
+         result = imalloc (size);
          if (result == NULL)
            return NULL;
-         memcpy (result, ptr, min (size, (__malloc_size_t) 1 << type));
-         _free_internal (ptr);
+         memcpy (result, ptr, min (size, (size_t) 1 << type));
+         ifree (ptr);
        }
       break;
     }
@@ -1379,148 +1203,75 @@ _realloc_internal (ptr, size)
   return result;
 }
 
-__ptr_t
+genptr_t
 realloc (ptr, size)
-     __ptr_t ptr;
-     __malloc_size_t size;
+     genptr_t ptr;
+     size_t size;
 {
-  if (!__malloc_initialized && !__malloc_initialize ())
+#ifdef RCHECK
+  struct hdr *hdr;
+  size_t osize;
+#endif
+
+  if (malloc_initialized == 0 && malloc_initialize () == 0)
     return NULL;
 
-  return (__realloc_hook != NULL ? *__realloc_hook : _realloc_internal)
-    (ptr, size);
-}
-/* Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
+  nrealloc++;
 
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+#ifdef RCHECK
+  hdr = ((struct hdr *) ptr) - 1;
+  osize = hdr->size;
 
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.
-
-   The author may be reached (Email) at the address mike@ai.mit.edu,
-   or (US mail) as Mike Haertel c/o Free Software Foundation.  */
+  checkhdr (hdr);
+  if (size < osize)
+    zmemset ((char *) ptr + size, FREEFLOOD, osize - size);
+  hdr = (struct hdr *) irealloc ((genptr_t) hdr, sizeof (struct hdr) + size + 1);
+  if (hdr == NULL)
+    return NULL;
 
-#ifndef        _MALLOC_INTERNAL
-#define        _MALLOC_INTERNAL
-#include <malloc.h>
+  hdr->size = size;
+  hdr->magic = MAGICWORD;
+  ((char *) &hdr[1])[size] = MAGICBYTE;
+  if (size > osize)
+    zmemset ((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
+  return (genptr_t) (hdr + 1);
+#else
+  return (irealloc (ptr, size));
 #endif
+}
 
 /* Allocate an array of NMEMB elements each SIZE bytes long.
    The entire array is initialized to zeros.  */
-__ptr_t
+genptr_t
 calloc (nmemb, size)
-     register __malloc_size_t nmemb;
-     register __malloc_size_t size;
+     register size_t nmemb;
+     register size_t size;
 {
-  register __ptr_t result = malloc (nmemb * size);
+  register genptr_t result;
 
+  result = malloc (nmemb * size);
   if (result != NULL)
     (void) memset (result, 0, nmemb * size);
 
   return result;
 }
-/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
 
-The GNU C Library is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with the GNU C Library; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-#ifndef        _MALLOC_INTERNAL
-#define        _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#ifndef        __GNU_LIBRARY__
-#define        __sbrk  sbrk
-#endif
-
-#ifdef __GNU_LIBRARY__
-/* It is best not to declare this and cast its result on foreign operating
-   systems with potentially hostile include files.  */
-
-#include <stddef.h>
-extern __ptr_t __sbrk __P ((ptrdiff_t increment));
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/* Allocate INCREMENT more bytes of data space,
-   and return the start of data space, or NULL on errors.
-   If INCREMENT is negative, shrink data space.  */
-__ptr_t
-__default_morecore (increment)
-     __malloc_ptrdiff_t increment;
+/* Define the `cfree' alias for `free'.  */
+void
+cfree (ptr)
+     genptr_t ptr;
 {
-  __ptr_t result = (__ptr_t) __sbrk (increment);
-  if (result == (__ptr_t) -1)
-    return NULL;
-  return result;
+  free (ptr);
 }
-/* Copyright (C) 1991, 92, 93, 94, 95, 96 Free Software Foundation, Inc.
 
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with this library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
-
-#ifndef        _MALLOC_INTERNAL
-#define _MALLOC_INTERNAL
-#include <malloc.h>
-#endif
-
-#if __DJGPP__ - 0 == 1
-
-/* There is some problem with memalign in DJGPP v1 and we are supposed
-   to omit it.  Noone told me why, they just told me to do it.  */
-
-#else
-
-__ptr_t (*__memalign_hook) __P ((size_t __size, size_t __alignment));
-
-__ptr_t
+genptr_t
 memalign (alignment, size)
-     __malloc_size_t alignment;
-     __malloc_size_t size;
+     size_t alignment;
+     size_t size;
 {
-  __ptr_t result;
+  genptr_t result;
   unsigned long int adj, lastadj;
 
-  if (__memalign_hook)
-    return (*__memalign_hook) (alignment, size);
-
   /* Allocate a block with enough extra space to pad the block with up to
      (ALIGNMENT - 1) bytes if necessary.  */
   result = malloc (size + alignment - 1);
@@ -1560,7 +1311,7 @@ memalign (alignment, size)
          break;
       if (l == NULL)
        {
-         l = (struct alignlist *) malloc (sizeof (struct alignlist));
+         l = (struct alignlist *) imalloc (sizeof (struct alignlist));
          if (l == NULL)
            {
              free (result);
@@ -1576,4 +1327,160 @@ memalign (alignment, size)
   return result;
 }
 
-#endif /* Not DJGPP v1 */
+/* On some ANSI C systems, some libc functions call _malloc, _free
+   and _realloc.  Make them use the GNU functions.  */
+
+genptr_t
+_malloc (size)
+     size_t size;
+{
+  return malloc (size);
+}
+
+void
+_free (ptr)
+     genptr_t ptr;
+{
+  free (ptr);
+}
+
+genptr_t
+_realloc (ptr, size)
+     genptr_t ptr;
+     size_t size;
+{
+  return realloc (ptr, size);
+}
+
+struct mstats
+mstats ()
+{
+  struct mstats result;
+         
+  result.bytes_total = (char *) default_morecore (0) - _heapbase;
+  result.chunks_used = chunks_used;
+  result.bytes_used = bytes_used;
+  result.chunks_free = chunks_free;
+  result.bytes_free = bytes_free;
+  result.nmalloc = nmalloc;
+  result.nrealloc = nrealloc;
+  result.nfree = nfree;
+  result.nsbrk = nsbrk;
+  result.tsbrk = tsbrk;
+  result.negsbrk = negsbrk;
+  result.tnegsbrk = tnegsbrk;
+
+  return result;
+}
+
+#ifdef RCHECK
+/* Standard debugging hooks for `malloc'. */
+
+static void
+zmemset (ptr, val, size)
+     genptr_t ptr;
+     int val;
+     size_t size;
+{
+  char *cp = ptr;
+
+  while (size--)
+    *cp++ = val;
+}
+
+static enum mcheck_status
+checkhdr (hdr)
+     const struct hdr *hdr;
+{
+  enum mcheck_status status;
+
+  switch (hdr->magic)
+    {
+    default:
+      status = MCHECK_HEAD;
+      break;
+    case MAGICFREE:
+      status = MCHECK_FREE;
+      break;
+    case MAGICWORD:
+      if (((char *) &hdr[1])[hdr->size] != MAGICBYTE)
+       status = MCHECK_TAIL;
+      else
+       status = MCHECK_OK;
+      break;
+    }
+  if (status != MCHECK_OK)
+    mabort (status);
+  return status;
+}
+
+#ifndef botch
+botch (msg)
+     char *msg;
+{
+  fprintf (stderr, "mcheck: %s\n", msg);
+  fflush (stderr);
+  abort ();
+}
+#endif
+
+static void
+mabort (status)
+     enum mcheck_status status;
+{
+  const char *msg;
+
+  switch (status)
+    {
+    case MCHECK_OK:
+      msg = "memory is consistent, library is buggy";
+      break;
+    case MCHECK_HEAD:
+      msg = "memory clobbered before allocated block";
+      break;
+    case MCHECK_TAIL:
+      msg = "memory clobbered past end of allocated block";
+      break;
+    case MCHECK_FREE:
+      msg = "block freed twice";
+      break;
+    default:
+      msg = "bogus mcheck_status, library is buggy";
+      break;
+    }
+
+  botch (msg);
+}
+
+enum mcheck_status
+mprobe (ptr)
+     genptr_t ptr;
+{
+  return checkhdr ((struct hdr *)ptr);
+}
+
+#ifndef STDIO_H_INCLUDED
+#  include <stdio.h>
+#endif
+
+void
+print_malloc_stats (s)
+     char *s;
+{
+  struct mstats ms;
+
+  ms = mstats ();
+  fprintf (stderr, "Memory allocation statistics: %s\n", s ? s : "");
+  fprintf (stderr, "\nTotal chunks in use: %d, total chunks free: %d\n",
+          ms.chunks_used, ms.chunks_free);
+  fprintf (stderr, "Total bytes in use: %u, total bytes free: %u\n",
+          ms.bytes_used, ms.bytes_free);
+  fprintf (stderr, "Total bytes (from heapbase): %d\n", ms.bytes_total);
+  fprintf (stderr, "Total mallocs: %d, total frees: %d, total reallocs: %d\n",
+          ms.nmalloc, ms.nfree, ms.nrealloc);
+  fprintf (stderr, "Total sbrks: %d, total bytes via sbrk: %d\n",
+          ms.nsbrk, ms.tsbrk);
+  fprintf (stderr, "Total negative sbrks: %d, total bytes returned to kernel: %d\n",
+          ms.negsbrk, ms.tnegsbrk);
+}
+#endif /* RCHECK */