#ifndef lint
static char *sccsid = "@(#)list.c	1.1 (Steve Hill) 3/9/90";
#endif

/* LIST.C
 *
 * Primitive functions for manipulating a linked list.
 * These lists can be specialised by writing appropriate wrapper
 * functions or macros.
 */

#include <stdio.h>

#include "basetype.h"
#include "malloc.h"
#include "error.h"
#include "list.h"


/* ListCons
 *
 * Cons element elem onto the front of list.  Returns pointer to
 * the new head of the list.
 */

list_t *
ListCons(elem, list)
address_t	elem;
list_t		*list;
{
	list_t	*l;

	l = (list_t *) malloc(sizeof(list_t));

	if (l == ListNull)
		FatalError(__FILE__, __LINE__, "ListCons: out of memory");

	l->elem  = elem;
	l->ptr   = list;

	return(l);
}


/* ListCopy
 *
 * Make a copy of a list.  The function provided should be a copying
 * function for the elements of the list.
 */

list_t *
ListCopy(list, copy_fn)
list_t		*list;
address_t	(*copy_fn)();
{
	if (list != ListNull)
	{
		address_t	elem;

		if (copy_fn != NULL)
			elem = (*copy_fn)(list->elem);
		else
			elem = list->elem;

		return(ListCons(elem, ListCopy(list->ptr, copy_fn)));
	}
	else
		return(ListNull);
}


/* ListPrint
 *
 * Print a list to a specified file.  The supplied function prints
 * individual elements.
 */

void
ListPrint(file, printfn, list)
FILE		*file;
void		(*printfn)();
list_t		*list;
{
	list_t	*l;

	if (list == ListNull)
	{
		fprintf(file, "Null List\n");
		return;
	}

	l = list;

	while (l != ListNull)
	{
		(*printfn)(file, l->elem);
		l = l->ptr;
	}
}


/* ListFree
 *
 * Free a list.  The supplied function should free each element.
 */

void
ListFree(list, freefn)
list_t	*list;
void	(*freefn)();
{
	list_t	*l, *n;

	l = list;

	while (l != ListNull)
	{
		n = l->ptr;
		if (freefn != NULL)
			(*freefn)(l->elem);
		(void) free((char *) l);
		l = n;
	}
}
