btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * Standard debugging hooks for `malloc'.
 * * Copyright 1990, 1991, 1992, 1993, 1994 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 <stdio.h>
#endif

#include "copyright.h"
#include "config.h"
#include "externs.h"

/*
 * Old hook values.  
 */
static void (*old_free_hook) __P((__ptr_t ptr));
static __ptr_t(*old_malloc_hook) __P((__malloc_size_t size));
static __ptr_t(*old_realloc_hook) __P((__ptr_t ptr, __malloc_size_t size));

/*
 * Function to call when something awful happens.  
 */
static void (*abortfunc) __P((enum mcheck_status));

/*
 * Arbitrary magical numbers.  
 */
#define MAGICWORD	0xfedabeeb
#define MAGICFREE	0xd8675309
#define MAGICBYTE	((char) 0xd7)
#define MALLOCFLOOD	((char) 0x93)
#define FREEFLOOD	((char) 0x95)

struct hdr {
    __malloc_size_t size;	/*
				 * Exact size requested by user.  
				 */
    unsigned long int magic;	/*
				 * Magic number to check header * *
				 * integrity.  
				 */
};

#if	defined(_LIBC) || defined(STDC_HEADERS) || defined(USG)
#define flood memset
#else
static void flood __P((__ptr_t, int, __malloc_size_t));
static void flood(ptr, val, size)
__ptr_t ptr;
int val;
__malloc_size_t size;
{
    char *cp = ptr;

    while (size--)
	*cp++ = val;
}
#endif

static enum mcheck_status checkhdr __P((const struct hdr *));
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)
	(*abortfunc) (status);
    return status;
}

static void freehook __P((__ptr_t));
static void freehook(ptr)
__ptr_t ptr;
{
    struct hdr *hdr = ((struct hdr *) ptr) - 1;

    checkhdr(hdr);
    hdr->magic = MAGICFREE;
    flood(ptr, FREEFLOOD, hdr->size);
    __free_hook = old_free_hook;
    free(hdr);
    __free_hook = freehook;
}

static __ptr_t mallochook __P((__malloc_size_t));
static __ptr_t mallochook(size)
__malloc_size_t size;
{
    struct hdr *hdr;

    __malloc_hook = old_malloc_hook;
    hdr = (struct hdr *) malloc(sizeof(struct hdr) + size + 1);

    __malloc_hook = mallochook;
    if (hdr == NULL)
	return NULL;

    hdr->size = size;
    hdr->magic = MAGICWORD;
    ((char *) &hdr[1])[size] = MAGICBYTE;
    flood((__ptr_t) (hdr + 1), MALLOCFLOOD, size);
    return (__ptr_t) (hdr + 1);
}

static __ptr_t reallochook __P((__ptr_t, __malloc_size_t));
static __ptr_t reallochook(ptr, size)
__ptr_t ptr;
__malloc_size_t size;
{
    struct hdr *hdr = ((struct hdr *) ptr) - 1;
    __malloc_size_t osize = hdr->size;

    checkhdr(hdr);
    if (size < osize)
	flood((char *) ptr + size, FREEFLOOD, osize - size);
    __free_hook = old_free_hook;
    __malloc_hook = old_malloc_hook;
    __realloc_hook = old_realloc_hook;
    hdr =
	(struct hdr *) realloc((__ptr_t) hdr,
	sizeof(struct hdr) + size + 1);

    __free_hook = freehook;
    __malloc_hook = mallochook;
    __realloc_hook = reallochook;
    if (hdr == NULL)
	return NULL;

    hdr->size = size;
    hdr->magic = MAGICWORD;
    ((char *) &hdr[1])[size] = MAGICBYTE;
    if (size > osize)
	flood((char *) (hdr + 1) + osize, MALLOCFLOOD, size - osize);
    return (__ptr_t) (hdr + 1);
}

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;
    }

    STARTLOG(LOG_ALWAYS, "BUG", "MLLOC") {
	log_text(tprintf("mcheck: %s\n", msg));
	ENDLOG;
    }
}

static int mcheck_used = 0;

int mcheck(void)
{
    abortfunc = &mabort;

    /*
     * These hooks may not be safely inserted if malloc is already in * * 
     * use.  
     */
    if (!__malloc_initialized && !mcheck_used) {
	old_free_hook = __free_hook;
	__free_hook = freehook;
	old_malloc_hook = __malloc_hook;
	__malloc_hook = mallochook;
	old_realloc_hook = __realloc_hook;
	__realloc_hook = reallochook;
	mcheck_used = 1;
    }
    return mcheck_used ? 0 : -1;
}

enum mcheck_status mprobe(__ptr_t ptr)
{
    return mcheck_used ? checkhdr(ptr) : MCHECK_DISABLED;
}