#ifndef _LINK_H_
#define _LINK_H_

/*=-=-=-=-=-=-=-=-=-=-=-  RCI/RCCL Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987 by John E. Lloyd. Permission to use, distribute  *
 *	and copy is granted for non-commercial and research purposes only,  *
 *	providing the authors are acknowledged and this copyright notice is *
 *	displayed. The authors provide this software in hope that it will   *
 *	useful, but do not assume responsibility for its use.		    *
 *									    *
 *	This software was developed using the facilities of the McGill 	    *
 *	University Research Center for Intelligent Machines, Montreal,	    *
 *	Canada, for a project undertaken and supported by the RCA Advanced  *
 *	Technology Laboratories, Moorestown, New Jersey.		    *
 *									    *
 *=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
/*---------------------------------------------------------------------------
 *
 * DESCRIPTION:	Macros for inserting and deleting items from doubly linked
 *		lists.
 * 
 * AUTHOR/DATE:	John Lloyd, Fall 1987
 *
 * MODIFICATION HISTORY:
 *
 *		John Lloyd, Fall 1989: Added LINK_H and LINK_HT macros for 
 *			dealing with non-circular linked lists.
 *
 *--------------------------------------------------------------------------*/

/* macros for dealing with double circular linked lists */

/* link (a) into the list after (b) */
#define LINK(a,b)	(a)->next = (b)->next; (a)->prev = (b); \
			(b)->next->prev = (a); (b)->next = (a);

/* unlink (a) from the list */
#define UNLINK(a)	(a)->prev->next = (a)->next; \
			(a)->next->prev = (a)->prev;

/* check to see if the list is empty */
#define EMPTY(a)	(a)->next = (a)

/* macros for linking things into a double linked list with 
   a head pointer (h) */

#define LINK_H(h,x)			\
	if (h)				\
	 { (h)->prev = (x);		\
	   (x)->next = (h);		\
	 }				\
	else				\
	 { (x)->next = NULL;		\
	 }				\
	(x)->prev = NULL;		\
	(h) = (x);

#define UNLINK_H(h,x)			\
	if ((x)->prev)			\
	 { (x)->prev->next = (x)->next;	\
	 }				\
	else				\
	 { (h) = (x)->next;		\
	 }				\
	if ((x)->next)			\
	 { (x)->next->prev = (x)->prev;	\
	 }

/* macros for linking things into a double linked list with 
   a head pointer (h) and a tail pointer (t) */

#define LINK_HT(h,t,x)			\
	if (h)				\
	 { (h)->prev = (x);		\
	   (x)->next = (h);		\
	 }				\
	else				\
	 { (x)->next = NULL;		\
	   (t) = (x);			\
	 }				\
	(x)->prev = NULL;		\
	(h) = (x);

#define LINK_NEXT_HT(h,t,n,x)		\
	if ((n)==NULL)			\
	 { LINK_HT((h),(t),(x));	\
	 }				\
	else				\
	 { if ((n)->next)		\
	    { (n)->next->prev = (x);	\
	      (x)->next = (n)->next;	\
	    }				\
	   else				\
	    { (x)->next = NULL;		\
	      (t) = (x);		\
	    }				\
	   (x)->prev = (n);		\
	   (n)->next = (x);		\
	 }

#define LINK_PREV_HT(h,t,n,x)		\
	if ((n)==NULL)			\
	 { LINK_HT((h),(t),(x));	\
	 }				\
	else				\
	 { if ((n)->prev)		\
	    { (n)->prev->next = (x);	\
	      (x)->prev = (n)->prev;	\
	    }				\
	   else				\
	    { (x)->prev = NULL;		\
	      (h) = (x);		\
	    }				\
	   (x)->next = (n);		\
	   (n)->prev = (x);		\
	 }

#define UNLINK_HT(h,t,x)		\
	if ((x)->prev)			\
	 { (x)->prev->next = (x)->next;	\
	 }				\
	else				\
	 { (h) = (x)->next;		\
	 }				\
	if ((x)->next)			\
	 { (x)->next->prev = (x)->prev;	\
	 }				\
	else				\
	 { (t) = (x)->prev;		\
	 }
	


#endif
