/*
	Copyright (C) 1991, Marcus J. Ranum. All rights reserved.
*/

#ifdef WANT_ANSI
#ifdef __STDC__
#include	<stdlib.h>
#endif
#endif
#include	"udb_defs.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(siz)
int	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(0);
	}
	lp->dat = (mall_t) 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(p)
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;
}