#ifndef _LINK_H_
#define _LINK_H_

/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1991 by John E. Lloyd.				    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

/*---------------------------------------------------------------------------
 *
 * 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 LINK_AFTER_H(h,n,x)		\
	if ((n) == NULL)		\
	 { LINK_H((h),(x));		\
	 }				\
	else				\
	 { (x)->prev = (n);		\
	   (x)->next = (n)->next;	\
	   if ((n)->next)		\
	    { (n)->next->prev = (x);	\
	    }				\
	   (n)->next = (x);		\
	 }

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

#define LINK_T(t,x)			\
	if (t)				\
	 { (t)->next = (x);		\
	   (x)->prev = (t);		\
	 }				\
	else				\
	 { (x)->prev = NULL;		\
	 }				\
	(x)->next = NULL;		\
	(t) = (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
