/* alloc.c for !DiscEx */


#include "main.h"
#include "alloc.h"


#define  BIG_BLOCK_SIZE  4096



/*
 * Allocate n zeroed bytes of space; return error if not possible.
 */

error * check_alloc (void **p, int n)
{
    *p = calloc (1, n);
    if (*p == NULL)
        return error_lookup ("NoMem");

    return NULL;
}


/*
 * Space for small records (eg ForDRec's, FragRec's etc.) is not malloc'd
 *  directly, but is instead allocated from larger chunks that are malloc'd
 *  by this function.
 *
 * These records are never free'd individually, but only en-masse: the
 *  'anchor' identifies the unit for freeing, and should be the address of
 *  a single word.
 */

error * alloc_big_block (BigBlockDefPtr p)
{
    char *newblock = (char *) malloc (BIG_BLOCK_SIZE);

    if (newblock == NULL)
        return error_lookup ("NoMem");

    * ((char **) newblock) = p->anchor;
    p->anchor = newblock;

    p->nextfree = newblock + sizeof (char *);
    p->endfree = p->nextfree + BIG_BLOCK_SIZE - sizeof (char *);

    return NULL;
}


/*
 * All space malloc'd by the previous function for a particular 'anchor' is
 *  free'd.
 */

void free_big_blocks (BigBlockDefPtr p)
{
    char *block = p->anchor;

    while (block != NULL)
    {
        char *next = * ((char **) block);

        free (block);
        block = next;
    }

    return;
}
