/*
    Copyright 2001 (c) by Claudio Jeker,
    Swiss Federal Institute of Technology,
    Computer Engineering and Networks Laboratory.
 
    TOPSY -- A Teachable Operating System.
             Implementation of a tiny and simple
             micro kernel for teaching purposes.
 
    For further information, please visit http://www.tik.ee.ethz.ch/~topsy
 
    This software is provided under the terms of the GNU General Public 
    Licence. A full copy of the GNU GPL is provided in the file COPYING 
    found in the development root of Topsy.
*/
/*
	
    File:                  $Source: /home/ruf/cvs_Topsy/cvs/Topsy/Topsy/Attic/simpleq.h,v $
    Affiliation:           ETH Zuerich, TIK
    Version:               $Revision: 2922 $
    Last Date of Change:   $Date: 2007-03-19 17:48:52 +0100 (Mon, 19 Mär 2007) $  by: $Author: baderma $
 
*/

/* simpleq.h: a simple linked list with head and tail pointer based on macros
 
	 Idea comes from OpenBSDs queue(3) and /usr/src/sys/sys/queue.h
 
	 Following MACROS are defined:
 
	 SIMPLEQ_HEAD(NAME, TYPE);
	 * create a new simpleq with name NAME and pointers to structs of type TYPE
	 
	 SIMPLEQ_ENTRY(TYPE);
	 * add next pointer for an element (struct TYPE *sq_next)
	 
	 SIMPLEQ_INIT(HEAD);
	 * initialize the list
	 
	 SIMPLEQ_ADDHEAD(LIST, ELM, FIELD);
	 * add element in front of the tail queue
 
	 SIMPLEQ_ADDTAIL(LIST, ELM, FIELD);
	 * add element at the end of the tail queue
	 
	 SIMPLEQ_ADDAFTER(LIST, LIST_ELM, ELM, FIELD);
	 * add element after LIST_ELM
	 
	 SIMPLEQ_EMPTY(LIST);
	 * true if empty
	 
	 SIMPLEQ_REMOVE(LIST, ELM, FIELD);
	 * remove element from list
	 
	 SIMPLEQ_FIRST(LIST);
	 * return first elmenet
	 
	 SIMPLEQ_NEXT(ELM, FIELD);
	 * return next elmenet
	 
	 SIMPLEQ_LAST(LIST, NAME);
	 * return last element
 
	 SIMPLEQ_FOREACH(LIST, ELM, FIELD)
	 * cycle through the simpleq
	
 */

#define SIMPLEQ_HEAD(name, type)																					\
		struct name {																													\
			struct type *sq_first;																							\
			struct type *sq_last;																								\
		}

#define SIMPLEQ_ENTRY(type)																								\
		struct {																															\
			struct type *sq_next;																								\
		}

#define SIMPLEQ_INIT(headptr)																							\
		do {																																	\
			(headptr)->sq_first = NULL;																					\
			(headptr)->sq_last = NULL;																					\
		} while (0)

#define SIMPLEQ_ADDHEAD(headptr, elm, field)															\
		do {																																	\
			if (( (elm)->field.sq_next = (headptr)->sq_first ) == NULL ) 				\
				(headptr)->sq_last = (elm);																				\
			(headptr)->sq_first = (elm);																				\
		} while (0)

#define SIMPLEQ_ADDTAIL(headptr, elm, field)															\
		do {																																	\
			(elm)->field.sq_next = NULL;																				\
			if ( (headptr)->sq_last != NULL )																		\
				(headptr)->sq_last->field.sq_next = (elm);												\
			else																																\
				(headptr)->sq_first = (elm);																			\
			(headptr)->sq_last = (elm);																					\
		} while (0)

#define SIMPLEQ_ADDAFTER(headptr, listelm, elm, field)										\
		do {	XXX																																\
			if (( (elm)->field.sq_next = (listelm)->field.sq_next ) != NULL )		\
				(elm)->field.sq_next->field.sq_prev = &(elm)->field.sq_next;			\
			else																																\
				(headrptr)->sq_last = &(elm)->field.sq_next;											\
			(listelm)->field.sq_next = (elm);																		\
			(elm)->field.sq_prev = &(listelm)->field.sq_next;										\
		} while (0)

#define SIMPLEQ_EMPTY(headptr)																						\
		(SIMPLEQ_FIRST(headptr) == NULL)

#define SIMPLEQ_REMOVE(headptr, elm, field)																\
		do {	XXX																																\
			if (( *(elm)->field.sq_prev = (elm)->field.sq_next ) != NULL )			\
				(elm)->field.sq_next->field.sq_prev = (elm)->field.sq_prev;				\
			else																																\
				(headptr)->sq_last = (elm)->field.sq_prev;												\
		} while (0)

#define SIMPLEQ_POP(headptr, elm, field)																	\
		do {																																	\
			if ( ((elm) = (headptr)->sq_first) != NULL ) 												\
				if( ((headptr)->sq_first = (elm)->field.sq_next ) == NULL )				\
					(headptr)->sq_last = NULL;																			\
			(elm)->field.sq_next = NULL;																				\
		} while (0)

#define SIMPLEQ_FIRST(headptr)																						\
		((headptr)->sq_first)

#define SIMPLEQ_NEXT(elm, field)																					\
		((elm)->field.sq_next)

#define SIMPLEQ_LAST(headptr, headfield)																	\
		((headptr)->sq_last)

#define SIMPLEQ_FOREACH(headptr, var, field)															\
		for ((var) = SIMPLEQ_FIRST(headptr);																	\
				 (var) != NULL;																										\
				 (var) = SIMPLEQ_NEXT(var, field) )
