untermud/DOC/
untermud/DOC/U/
untermud/DOC/U/U-examples/
untermud/DOC/internals/
untermud/DOC/wizard/
untermud/MISC/
untermud/MISC/dbchk/
untermud/RWHO/
untermud/RWHO/rwhod/
/*
    Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

/* configure all options BEFORE including system stuff. */
#include    "config.h"
#include    "mud.h"

/*
routines that handle copying stuff in memory, and other main
memory allocation shenanigans.
*/


/*
#define ALLOC_DEBUG
*/


/*
temporary data is managed by keeping a list of allocated stuff, which
can be traversed and freed. this is not too terribly efficient, but
is not a load-bearing section of code.
*/
struct tmplist {
  struct tmplist *next;
  mall_t dat;
};


/* list of currently active temporaries */
static struct tmplist *tmpl;

/* list of temp list structures that have been freed and stacked */
static struct tmplist *freetmpl;



/* just like malloc() but keep track of the storage */
mall_t tmpalloc (size_t siz)
{
  struct tmplist *lp;

  if (freetmpl != (struct tmplist *) 0) {
    lp = freetmpl;
#ifdef  ALLOC_DEBUG
    printf ("take holder %d from tmp holder list\n", lp);
#endif
    freetmpl = freetmpl->next;
  } else {
    if ((lp = (struct tmplist *) malloc (sizeof (struct tmplist))) == 0)
      return ((mall_t) 0);
  }
  lp->dat = malloc ((unsigned) siz);

  /* add to the chain */
  lp->next = tmpl;
  tmpl = lp;

#ifdef  ALLOC_DEBUG
  printf ("tmpalloc %d bytes at %d (holder is %d)\n", siz, lp->dat, lp);
#endif
  return (lp->dat);
}




/*
put something on the temp list to free later.
this results in what is basically a deferred free() - executed
at the end of each machine run.
*/
void deferfree (mall_t p)
{
  struct tmplist *lp;

  if (freetmpl != (struct tmplist *) 0) {
    lp = freetmpl;
#ifdef  ALLOC_DEBUG
    printf ("take holder %d from tmp holder list\n", lp);
#endif
    freetmpl = freetmpl->next;
  } else {
    if ((lp = (struct tmplist *) malloc (sizeof (struct tmplist))) == 0) {
#ifdef  ALLOC_DEBUG
      printf ("deferfree can't allocate holder, leaks memory\n");
#endif
      return;
    }
  }
  lp->dat = p;
  lp->next = tmpl;
  tmpl = lp;

#ifdef  ALLOC_DEBUG
  printf ("tmpputonfree ? bytes at %d (holder is %d)\n", lp->dat, lp);
#endif
}




/* free all the temporaries */
void tmp_sync ()
{
  register struct tmplist *lp = tmpl;
  register struct tmplist *np;

  if (tmpl == (struct tmplist *) 0)
    return;

  while (lp != (struct tmplist *) 0) {
    if (lp->dat != 0)
      (void) free (lp->dat);
#ifdef  ALLOC_DEBUG
    printf ("tmpsync at %d (holder is %d)\n", lp->dat, lp);
#endif
    np = lp->next;
    lp->next = freetmpl;
    freetmpl = lp;
#ifdef  ALLOC_DEBUG
    printf ("stack holder %d on tmp holder list\n", lp);
#endif
    lp = np;
  }
  tmpl = (struct tmplist *) 0;
}


char *tmpstr (char *s)
{
  char *ret;
  size_t l;

  ret = (char *) tmpalloc (l = (strlen (s) + 1));
  if (ret != (char *) 0)
    bcopy (s, ret, l);
  else
    fatal ("cannot allocate string space!\n", (char *) 0);
  return (ret);
}