#ifndef hoc_list_h
#define hoc_list_h

#if HOC_L_LIST
#define stralloc	hoc_l_stralloc
#define newitem		hoc_l_newitem
#define newlist		hoc_l_newlist
#define freelist	hoc_l_freelist
#define next		hoc_l_next
#define prev		hoc_l_prev
#define insertstr	hoc_l_insertstr
#define insertitem	hoc_l_insertitem
#define insertlist	hoc_l_insertlist
#define insertsym	hoc_l_insertsym
#define insertsec	hoc_l_insertsec
#define insertobj	hoc_l_insertobj
#define insertvoid	hoc_l_insertvoid
#define linsertsym	hoc_l_linsertsym
#define linsertstr	hoc_l_linsertstr
#define lappendsym	hoc_l_lappendsym
#define lappendstr	hoc_l_lappendstr
#define lappenditem	hoc_l_lappenditem
#define lappendlst	hoc_l_lappendlst
#define lappendsec	hoc_l_lappendsec
#define lappendobj	hoc_l_lappendobj
#define lappendvoid	hoc_l_lappendvoid
#define delete		hoc_l_delete
#define delitems	hoc_l_delitems
#define move		hoc_l_move
#define movelist	hoc_l_movelist
#define replacstr	hoc_l_replacstr
#define Item		hoc_Item
#define List		hoc_List

typedef struct hoc_Item    hoc_List;		/* list of mixed items */
#else
#define hoc_List struct hoc_Item
#endif

typedef struct hoc_Item {
	union	{
			struct hoc_Item *itm;
			hoc_List *lst;
			char *str;
			struct Symbol *sym;
			struct Section* sec;
			struct Object* obj;
			void* vd;
	}	element;	/* pointer to the actual item */
	struct hoc_Item    *next;
	struct hoc_Item    *prev;
	short           itemtype;
}               hoc_Item;
#define ITEM0	(hoc_Item *)0
#define LIST0	(hoc_List *)0

#define ITERATE(itm,lst) for (itm = (lst)->next; itm != (lst); itm = itm->next)
/*
 * this is convenient way to get the element pointer if you know what type
 * the item is 
 */
#define SYM(q)	((q)->element.sym)
#define STR(q)	((q)->element.str)
#define ITM(q)	((q)->element.itm)
#define LST(q)	((q)->element.lst)
#define hocSEC(q)	((q)->element.sec)
#define OBJ(q)	((q)->element.obj)
#define VOIDITM(q)	((q)->element.vd)

/* types not defined in parser */
#define ITEM	2
#define LIST	3
#define VOIDPOINTER	4
/*
 * An item type, STRING is also used as an item type 
 */

#ifdef __cplusplus
extern "C" {
#endif

extern char* hoc_l_stralloc(const char*, char* release);
extern hoc_List* hoc_l_newlist();
extern hoc_Item* hoc_l_insertstr(hoc_Item*, const char*);
extern hoc_Item* hoc_l_insertsym(hoc_Item*, struct Symbol*);
extern hoc_Item* hoc_l_insertitem(hoc_Item*, hoc_Item*);
extern hoc_Item* hoc_l_insertlist(hoc_Item*, hoc_List*);
extern hoc_Item* hoc_l_insertsec(hoc_Item*, struct Section*);
extern hoc_Item* hoc_l_insertvoid(hoc_Item*, void*);

extern hoc_Item* hoc_l_linsertstr(hoc_List*, const char*);
extern hoc_Item* hoc_l_linsertsym(hoc_List*, struct Symbol*);

extern hoc_Item* hoc_l_lappendstr(hoc_List*, const char*);
extern hoc_Item* hoc_l_lappendsym(hoc_List*, struct Symbol*);
extern hoc_Item* hoc_l_lappenditem(hoc_List*, hoc_Item*);
extern hoc_Item* hoc_l_lappendlst(hoc_List*, hoc_List*);
extern hoc_Item* hoc_l_lappendsec(hoc_List*, struct Section*);
extern hoc_Item* hoc_l_lappendvoid(hoc_List*, void*);
extern hoc_Item* hoc_l_lappendobj(hoc_List*, struct Object*);

extern void hoc_l_freelist(hoc_List**);
extern hoc_Item* hoc_l_next(hoc_Item*);
extern hoc_Item* hoc_l_prev(hoc_Item*);
extern void hoc_l_delete(hoc_Item*);
extern void hoc_l_move(hoc_Item*, hoc_Item*, hoc_Item*);
extern void hoc_l_movelist(hoc_Item*, hoc_Item*, hoc_List*);
extern void hoc_l_replacstr(hoc_Item*, const char*);

#define Insertstr	insertstr
#define Insertsym	insertsym
#define Insertsec	insertsec
#define Linsertsym	linsertsym
#define Linsertstr	linsertstr
#define Lappendsym	lappendsym
#define Lappendstr	lappendstr
#define Lappenditem	lappenditem
#define Lappendlst	lappendlst
#define Lappendsec	lappendsec

#ifdef __cplusplus
}
#endif

#endif
