/* Header file for the list abstraction.
 * 
 * Author: Bob Baldwin
 */

#ifndef LIST_DEFINED
#define LIST_DEFINED

/* 
 * This is a doubly linked list.
 * It currently only supports the stack operations.
 */


/* LITERALS */
/* These would be useful if C had stronger type checking. */
#ifndef Obj
#define Obj	void *
#endif
#ifndef List
#define List	void *
#endif
#define List_NULLP     ((List) 0)
#ifndef bool
#define bool	int
#endif
#ifndef True
#define True	1
#define False	0
#endif
#ifndef NULL
#define NULL	0
#endif


/* OPERATIONS */

/* Allocate and initialize an empty list.
 */
List list_new (/* void */);


/* Push an element onto the list.
 * It both modifies and returns the list.
 */
List list_push (/* List l, Obj o */);


/* Pop an element off of the list and return it.
 * If the list is empty return Obj_NULLP.
 */
Obj list_pop (/* List l */);


/* Deallocate a list and all its storage.  This operation
 * returns List_NULLP, which should be assigned to the list
 * variable that was passed to it in order to avoid a dangling
 * reference.
 * The elem_func function is invoked for each element in the list
 * passing the element and the state object.
 * If l is List_NULLP, then don't complain, just return List_NULLP.
 */
List list_free (/* List l,
		   bool (*elem_free) (Obj element, Obj state),
		   Obj state */);


/* Remove and free a subset of the items from a list.
 * Return True if anything removed.
 * The elem_free routine is called with each element,
 * and if it returns true, the element is removed from
 * the list.
 */
bool list_free_subset (/* List l,
			  bool (*elem_free) (Obj element, Obj state),
			  Obj state */);


/* Create a duplicate of the list.
 * This is a shallow copy in the sense that the new list
 * just contains pointers to the object that were pointed
 * to by the old list.  The objects on the old list are
 * not copied.
 */
List list_dup (/* List l */);


/* Push an element onto the list.
 * It both modifies and returns the list.
 * The arguments are reverse from the list_push operation in order
 * to simplify passing this function to set and list traversing operations.
 */
void list_pushr (/* Obj o, List l */);


/* Traverse the list starting with the first element pushed.
 */
void list_traverse_fifo (/* List l,
			    void (*elem_func) (Obj element, Obj state),
			    Obj state */);


/* Traverse the list starting with the element just pushed.
 */
void list_traverse_lifo (/* List l,
			    void (*elem_func) (Obj element, Obj state),
			    Obj state */);


/* Search for an element within a list.
 * Return the first element for which elem_func returns TRUE,
 * or return NULL.
 */
Obj list_search (/* List l,
		     bool (*elem_equal) (Obj element, Obj state),
		     Obj state */);


/* Search for an element within a list, and if found remove it
 * from the list and return it.
 * If not found, return NULL.
 */
Obj list_remove (/* List l,
		     bool (*elem_equal) (Obj element, Obj state),
		     Obj state */);


/* Callback routine for list_remove and list_search to
 * locate an object with a particular address in memory.
 */
bool element_eq(/* Obj element, Obj desired_element */);


#endif
