ldmud-3.2.9/doc/
ldmud-3.2.9/doc/efun/
ldmud-3.2.9/mud/
ldmud-3.2.9/mud/heaven7/
ldmud-3.2.9/mud/heaven7/lib/
ldmud-3.2.9/mud/lp-245/
ldmud-3.2.9/mud/lp-245/banish/
ldmud-3.2.9/mud/lp-245/doc/
ldmud-3.2.9/mud/lp-245/doc/examples/
ldmud-3.2.9/mud/lp-245/doc/sefun/
ldmud-3.2.9/mud/lp-245/log/
ldmud-3.2.9/mud/lp-245/obj/Go/
ldmud-3.2.9/mud/lp-245/players/lars/
ldmud-3.2.9/mud/lp-245/room/death/
ldmud-3.2.9/mud/lp-245/room/maze1/
ldmud-3.2.9/mud/lp-245/room/sub/
ldmud-3.2.9/mud/lp-245/secure/
ldmud-3.2.9/mud/morgengrauen/
ldmud-3.2.9/mud/morgengrauen/lib/
ldmud-3.2.9/mud/sticklib/
ldmud-3.2.9/mud/sticklib/src/
ldmud-3.2.9/mudlib/uni-crasher/
ldmud-3.2.9/pkg/
ldmud-3.2.9/pkg/debugger/
ldmud-3.2.9/pkg/diff/
ldmud-3.2.9/pkg/misc/
ldmud-3.2.9/src/autoconf/
ldmud-3.2.9/src/bugs/
ldmud-3.2.9/src/bugs/MudCompress/
ldmud-3.2.9/src/bugs/b-020916-files/
ldmud-3.2.9/src/bugs/doomdark/
ldmud-3.2.9/src/bugs/ferrycode/ferry/
ldmud-3.2.9/src/bugs/ferrycode/obj/
ldmud-3.2.9/src/bugs/psql/
ldmud-3.2.9/src/done/
ldmud-3.2.9/src/done/order_alist/
ldmud-3.2.9/src/done/order_alist/obj/
ldmud-3.2.9/src/done/order_alist/room/
ldmud-3.2.9/src/gcc/
ldmud-3.2.9/src/gcc/2.7.0/
ldmud-3.2.9/src/gcc/2.7.1/
ldmud-3.2.9/src/hosts/
ldmud-3.2.9/src/hosts/GnuWin32/
ldmud-3.2.9/src/hosts/amiga/NetIncl/
ldmud-3.2.9/src/hosts/amiga/NetIncl/netinet/
ldmud-3.2.9/src/hosts/amiga/NetIncl/sys/
ldmud-3.2.9/src/hosts/i386/
ldmud-3.2.9/src/hosts/msdos/byacc/
ldmud-3.2.9/src/hosts/msdos/doc/
ldmud-3.2.9/src/hosts/os2/
ldmud-3.2.9/src/hosts/win32/
ldmud-3.2.9/src/util/
ldmud-3.2.9/src/util/erq/
ldmud-3.2.9/src/util/indent/hosts/next/
ldmud-3.2.9/src/util/xerq/
ldmud-3.2.9/src/util/xerq/lpc/
ldmud-3.2.9/src/util/xerq/lpc/www/
/*---------------------------------------------------------------------------
 * Gamedriver alloca -- a portable alloca() implementation
 * Based on the public-domain version by D.A. Gwyn.
 *
 *---------------------------------------------------------------------------
 * This implementation of the PWB library alloca() function,
 * which is used to allocate space off the run-time stack so
 * that it is automatically reclaimed upon procedure exit,
 * was inspired by discussions with J. Q. Johnson of Cornell
 * and later extended by Lars Duening.
 *
 * It should work under any C implementation that uses an
 * actual procedure stack (as opposed to a linked list of
 * frames).  There are some preprocessor constants that can
 * be defined when compiling for your specific system, for
 * improved efficiency; however, the defaults should be okay.
 *
 * The general concept of this implementation is to keep
 * track of all alloca()-allocated blocks, and reclaim any
 * that are found to be deeper in the stack than the current
 * invocation.  This heuristic does not reclaim storage as
 * soon as it becomes invalid, but it will do so eventually.
 *
 * As a special case, alloca(0) reclaims storage without
 * allocating any, including storage 'cached' by the implementation
 * for fast reuse. It is a good idea to use alloca(0) in
 * your main control loop, etc. to force garbage collection.
 *
 * As opposed to the original implementaion using malloc()/free(),
 * this version utilizes the 'mempools' module to allocate the memory.
 *---------------------------------------------------------------------------
 */

#include <stdlib.h>
#include <stdio.h>

#include "mempools.h"

typedef void *pointer;  /* generic pointer type */

/*-------------------------------------------------------------------------*/
/* Define STACK_DIRECTION if you know the direction of stack
 * growth for your system; otherwise it will be automatically
 * deduced at run-time.
 *
 * STACK_DIRECTION > 0 => grows toward higher addresses
 * STACK_DIRECTION < 0 => grows toward lower addresses
 * STACK_DIRECTION = 0 => direction of growth unknown
 */

#if defined(AMIGA)
#    define STACK_DIRECTION -1
#endif

#ifndef STACK_DIRECTION
#    define STACK_DIRECTION  0  /* direction unknown */
#endif

#if STACK_DIRECTION != 0

#    define STACK_DIR  STACK_DIRECTION  /* known at compile-time */

#else /* STACK_DIRECTION == 0; need run-time code */

static int stack_dir;                   /* 1 or -1 once known */
#    define STACK_DIR stack_dir

#endif /* STACK_DIRECTION == 0 */

/*-------------------------------------------------------------------------*/

/* An "alloca header" is used to:
 * (a) chain together all alloca()ed blocks;
 * (b) keep track of stack depth.
 */

typedef struct hdr
{
    struct hdr * next;  /* for chaining headers */
    char       * deep;  /* for stack depth measure */
    mempool_t  * pool;  /* the memory pool */
} header;

static header *last_alloca_header = NULL; /* -> last alloca header */
static header *free_header = NULL; /* List of unused structures */

/*-------------------------------------------------------------------------*/
#if STACK_DIRECTION == 0

static void
find_stack_direction (void)

/* Find the direction of the stackgrowth and store the result (+1 or -1)
 * into the global stack_dir.
 */

{
    static char *addr = NULL;  /* address of first `dummy', once known */
    char        dummy;         /* to get stack address */

    if (addr == NULL)  /* initial call */
    {
        addr = &dummy;
        find_stack_direction ();  /* recurse once */
    }
    else  /* second entry */
    if (&dummy > addr)
        stack_dir = 1;    /* stack grew upward */
    else
        stack_dir = -1;   /* stack grew downward */
}

#endif  /* STACK_DIRECTION == 0 */

/*-------------------------------------------------------------------------*/
pointer
palloca (size_t size)

/* Allocate at least <size> bytes of memory "on the stack" and return a
 * pointer to the start of the memory block. Return NULL if running out
 * of memory.
 *
 * Allocating "on the stack" means that every allocation is associated with
 * the call depth of the allocator. Allocations of a higher call depth
 * cause the deallocation of any memory allocated on deepter call depths.
 *
 * Originally this memory was meant to be taken from the stack frame of
 * the caller, but some systems and C implementations do not allow this.
 *
 * An allocation of 0 bytes is a special case, causing the deallocation of
 * every memory block allocated so far.
 */

{
    char              probe;         /* probes stack depth: */
    register char   * depth = &probe;
    register header * hp;            /* current header structure */

#if STACK_DIRECTION == 0
    if (STACK_DIR == 0)  /* (yet)unknown growth direction */
        find_stack_direction ();
#endif

    /* Reclaim garbage, defined as all alloca()ed storage that
     * was allocated from deeper in the stack than currently.
     */

    for (hp = last_alloca_header; hp != NULL;)
    {
        if ((STACK_DIR > 0 && hp->deep > depth)
         || (STACK_DIR < 0 && hp->deep < depth))
        {
            register header *np = hp->next;

            mempool_reset(hp->pool);  /* collect garbage */
            hp->next = free_header;
            free_header = hp;
            hp = np;              /* -> next header */
        }
        else
            break; /* rest are not deeper */
    }

    last_alloca_header = hp;  /* -> last valid storage */

    /* From here on, hp is always == last_alloca_header; the
     * use of the local however is a hint for the optimizer.
     */

    if (size == 0)
    {
        while (free_header != NULL)
        {
            header * this = free_header;
            free_header = free_header->next;
            if (this->pool)
            {
                mempool_delete(this->pool);
            }
            free(this);
        }
        return NULL;  /* no allocation required */
    }

    /* Allocate a new header structure if there is non for
     * this particular stack depth. The new structure will
     * be the new bottom of the header list.
     */

    if (hp == NULL || hp->deep != depth)
    {
        if (free_header == NULL)
        {
            hp = malloc (sizeof (*hp));
            if (!hp) { fprintf(stderr, "alloca: failed!\n"); return NULL; }
            hp->pool = new_mempool(1024);
            if (!hp->pool)
            {
                free(hp);
                fprintf(stderr, "alloca: failed!\n");
                return NULL;
            }
        }
        else
        {
            hp = free_header;
            free_header = hp->next;
        }

        hp->next = last_alloca_header;
        hp->deep = depth;
        last_alloca_header = hp;
    }

    /* The actual allocation is easy: */
    return mempool_alloc(hp->pool, size);
}

/***************************************************************************/