magic/utils/malloc.c

171 lines
4.9 KiB
C

/*
* malloc.c --
*
* Memory allocator.
* Magic no longer contains its own version of malloc(), as all modern
* operating systems have implementations which are as good or better.
*
* The main thing this file does is to define mallocMagic and friends.
* freeMagic frees the previously requested memory item, not the one
* passed as the argument. This allows efficient coding of loops which
* run through linked lists and process and free them at the same time.
*
* ALWAYS use mallocMagic() with freeMagic() and NEVER mix them with
* malloc() and free().
*
* Malloc trace routines have been removed. There are standard methods
* to trace memory allocation and magic doesn't need its own built-in
* method.
*
* The Tcl/Tk version of magic makes use of Tcl_Alloc() and Tcl_Free()
* which allows the Tcl/Tk version to trace memory using Tcl's methods.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/malloc.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include "tcltk/tclmagic.h"
#include "utils/magic.h"
#include "utils/malloc.h"
/* Normally we're supposed to warn against the use of standard malloc() */
/* and free(), but obviously that doesn't apply to this file. */
#undef malloc
#undef free
/* Imports */
extern void TxError(char *, ...);
extern char *TxGetLine();
/*
* Magic may reference an object after it is free'ed, but only one object.
* This is a change from previous versions of Magic, which needed to reference
* an arbitrary number of objects before the next call to malloc. Only then
* would no further references would be made to free'ed storage.
*/
/* Delay free'ing by one call, to accommodate Magic's needs. */
static char *freeDelayedItem = NULL;
/* Local definitions */
#ifdef MAGIC_WRAPPER
#ifdef TCL_MEM_DEBUG
#define MallocRoutine(a) ckalloc(a)
#define FreeRoutine(a) ckfree(a)
#else
/* DO NOT USE: Tcl_Alloc is defined with argument (unsigned int) NOT
* (size_t) and therefore limits memory allocation to the size of a
* 32-bit integer. Just use the normal malloc() and free(). Left as-is
* with TCL_MEM_DEBUG with the caveat that one should not use this to
* debug a huge design. Valgrind works better anyway.
*/
/* #define MallocRoutine(a) Tcl_Alloc(a) */
/* #define FreeRoutine(a) Tcl_Free(a) */
#define MallocRoutine(a) malloc(a)
#define FreeRoutine(a) free(a)
#endif
#else
#define MallocRoutine(a) malloc(a)
#define FreeRoutine(a) free(a)
#endif
/*
*---------------------------------------------------------------------
* mallocMagic() --
*
* memory allocator with support for one-delayed-item free'ing
*---------------------------------------------------------------------
*/
void *
mallocMagic(nbytes)
size_t nbytes;
{
void *p;
if (freeDelayedItem)
{
/* fprintf(stderr, "freed 0x%x (delayed)\n", freeDelayedItem); fflush(stderr); */
FreeRoutine(freeDelayedItem);
freeDelayedItem=NULL;
}
if ((p = (void *)MallocRoutine(nbytes)) != NULL)
{
/* fprintf(stderr, "alloc'd %u bytes at 0x%x\n", nbytes, p); fflush(stderr); */
return p;
}
else
{
ASSERT(FALSE, "Can't allocate any more memory.\n");
}
return NULL;
}
/*
*---------------------------------------------------------------------
* freeMagic() --
*
* one-delayed-item memory deallocation
*---------------------------------------------------------------------
*/
void
freeMagic(cp)
void *cp;
{
if (cp == NULL)
TxError("freeMagic called with NULL argument.\n");
if (freeDelayedItem)
{
/* fprintf(stderr, "freed 0x%x\n", freeDelayedItem); fflush(stderr); */
FreeRoutine(freeDelayedItem);
}
freeDelayedItem=cp;
}
/*
*---------------------------------------------------------------------
* callocMagic() --
*
* allocate memory and initialize it to all zero bytes.
*---------------------------------------------------------------------
*/
void *
callocMagic(nbytes)
size_t nbytes;
{
void *cp;
cp = mallocMagic(nbytes);
bzero(cp, (size_t) nbytes);
return (cp);
}