xref: /csrg-svn/old/dbx/lists.c (revision 18222)
19667Slinton /* Copyright (c) 1982 Regents of the University of California */
29667Slinton 
3*18222Slinton static	char sccsid[] = "@(#)lists.c	1.4 (Berkeley) 03/01/85";
49667Slinton 
5*18222Slinton static char rcsid[] = "$Header: lists.c,v 1.5 84/12/26 10:40:00 linton Exp $";
6*18222Slinton 
79667Slinton /*
89667Slinton  * General list definitions.
99667Slinton  *
109667Slinton  * The assumption is that the elements in a list are words,
119667Slinton  * usually pointers to the actual information.
129667Slinton  */
139667Slinton 
149667Slinton #include "defs.h"
159667Slinton #include "lists.h"
169667Slinton 
179667Slinton #ifndef public
189667Slinton 
199667Slinton typedef struct List *List;
209667Slinton typedef struct ListItem *ListItem;
219667Slinton typedef char *ListElement;
229667Slinton 
239667Slinton #define list_item(element) generic_list_item((ListElement) (element))
249667Slinton #define list_element(type, item) ((type) (item == nil ? nil : (item)->element))
259667Slinton #define list_head(list) ((list == nil) ? nil : (list)->head)
269667Slinton #define list_tail(list) ((list == nil) ? nil : (list)->tail)
279667Slinton #define list_next(item) ((item == nil) ? nil : (item)->next)
289667Slinton #define list_prev(item) ((item == nil) ? nil : (item)->prev)
299667Slinton #define list_size(list) (((list) == nil) ? 0 : (list)->nitems)
309667Slinton 
319667Slinton #define foreach(type, i, list) \
329667Slinton { \
339667Slinton     register ListItem _item; \
349667Slinton  \
359667Slinton     _item = list_head(list); \
369667Slinton     while (_item != nil) { \
379667Slinton 	i = list_element(type, _item); \
389667Slinton 	_item = list_next(_item);
399667Slinton 
409667Slinton #define endfor \
419667Slinton     } \
429667Slinton }
439667Slinton 
449667Slinton /*
459667Slinton  * Iterate through two equal-sized lists.
469667Slinton  */
479667Slinton 
489667Slinton #define foreach2(type1, i, list1, type2, j, list2) \
499667Slinton { \
509667Slinton     register ListItem _item1, _item2; \
519667Slinton  \
529667Slinton     _item1 = list_head(list1); \
539667Slinton     _item2 = list_head(list2); \
549667Slinton     while (_item1 != nil) { \
559667Slinton 	i = list_element(type1, _item1); \
569667Slinton 	j = list_element(type2, _item2); \
579667Slinton 	_item1 = list_next(_item1); \
589667Slinton 	_item2 = list_next(_item2);
599667Slinton 
609667Slinton #define list_islast() (_item == nil)
619667Slinton #define list_curitem(list) (_item == nil ? list_tail(list) : list_prev(_item))
629667Slinton 
639667Slinton /*
649667Slinton  * Representation should not be used outside except through macros.
659667Slinton  */
669667Slinton 
679667Slinton struct List {
689667Slinton     Integer nitems;
699667Slinton     ListItem head;
709667Slinton     ListItem tail;
719667Slinton };
729667Slinton 
739667Slinton struct ListItem {
749667Slinton     ListElement element;
759667Slinton     ListItem next;
769667Slinton     ListItem prev;
779667Slinton };
789667Slinton 
799667Slinton #endif
809667Slinton 
819667Slinton /*
829667Slinton  * Allocate and initialize a list.
839667Slinton  */
849667Slinton 
859667Slinton public List list_alloc()
869667Slinton {
879667Slinton     List list;
889667Slinton 
899667Slinton     list = new(List);
909667Slinton     list->nitems = 0;
919667Slinton     list->head = nil;
929667Slinton     list->tail = nil;
939667Slinton     return list;
949667Slinton }
959667Slinton 
969667Slinton /*
979667Slinton  * Create a list item from an object (represented as pointer or integer).
989667Slinton  */
999667Slinton 
1009667Slinton public ListItem generic_list_item(element)
1019667Slinton ListElement element;
1029667Slinton {
1039667Slinton     ListItem i;
1049667Slinton 
1059667Slinton     i = new(ListItem);
1069667Slinton     i->element = element;
1079667Slinton     i->next = nil;
1089667Slinton     i->prev = nil;
1099667Slinton     return i;
1109667Slinton }
1119667Slinton 
1129667Slinton /*
1139667Slinton  * Insert an item before the item in a list.
1149667Slinton  */
1159667Slinton 
1169667Slinton public list_insert(item, after, list)
1179667Slinton ListItem item;
1189667Slinton ListItem after;
1199667Slinton List list;
1209667Slinton {
1219667Slinton     ListItem a;
1229667Slinton 
1239667Slinton     checkref(list);
1249667Slinton     list->nitems = list->nitems + 1;
1259667Slinton     if (list->head == nil) {
1269667Slinton 	list->head = item;
1279667Slinton 	list->tail = item;
1289667Slinton     } else {
1299667Slinton 	if (after == nil) {
1309667Slinton 	    a = list->head;
1319667Slinton 	} else {
1329667Slinton 	    a = after;
1339667Slinton 	}
1349667Slinton 	item->next = a;
1359667Slinton 	item->prev = a->prev;
1369667Slinton 	if (a->prev != nil) {
1379667Slinton 	    a->prev->next = item;
1389667Slinton 	} else {
1399667Slinton 	    list->head = item;
1409667Slinton 	}
1419667Slinton 	a->prev = item;
1429667Slinton     }
1439667Slinton }
1449667Slinton 
1459667Slinton /*
1469667Slinton  * Append an item after the given item in a list.
1479667Slinton  */
1489667Slinton 
1499667Slinton public list_append(item, before, list)
1509667Slinton ListItem item;
1519667Slinton ListItem before;
1529667Slinton List list;
1539667Slinton {
1549667Slinton     ListItem b;
1559667Slinton 
1569667Slinton     checkref(list);
1579667Slinton     list->nitems = list->nitems + 1;
1589667Slinton     if (list->head == nil) {
1599667Slinton 	list->head = item;
1609667Slinton 	list->tail = item;
1619667Slinton     } else {
1629667Slinton 	if (before == nil) {
1639667Slinton 	    b = list->tail;
1649667Slinton 	} else {
1659667Slinton 	    b = before;
1669667Slinton 	}
1679667Slinton 	item->next = b->next;
1689667Slinton 	item->prev = b;
1699667Slinton 	if (b->next != nil) {
1709667Slinton 	    b->next->prev = item;
1719667Slinton 	} else {
1729667Slinton 	    list->tail = item;
1739667Slinton 	}
1749667Slinton 	b->next = item;
1759667Slinton     }
1769667Slinton }
1779667Slinton 
1789667Slinton /*
1799667Slinton  * Delete an item from a list.
1809667Slinton  */
1819667Slinton 
1829667Slinton public list_delete(item, list)
1839667Slinton ListItem item;
1849667Slinton List list;
1859667Slinton {
1869667Slinton     checkref(item);
1879667Slinton     checkref(list);
1889667Slinton     assert(list->nitems > 0);
1899667Slinton     if (item->next == nil) {
1909667Slinton 	list->tail = item->prev;
1919667Slinton     } else {
1929667Slinton 	item->next->prev = item->prev;
1939667Slinton     }
1949667Slinton     if (item->prev == nil) {
1959667Slinton 	list->head = item->next;
1969667Slinton     } else {
1979667Slinton 	item->prev->next = item->next;
1989667Slinton     }
1999667Slinton     list->nitems = list->nitems - 1;
2009667Slinton }
2019667Slinton 
2029667Slinton /*
2039667Slinton  * Concatenate one list onto the end of another.
2049667Slinton  */
2059667Slinton 
2069667Slinton public List list_concat(first, second)
2079667Slinton List first, second;
2089667Slinton {
2099667Slinton     List r;
2109667Slinton 
2119667Slinton     if (first == nil) {
2129667Slinton 	r = second;
2139667Slinton     } else if (second == nil) {
2149667Slinton 	r = first;
2159667Slinton     } else {
2169667Slinton 	second->head->prev = first->tail;
2179667Slinton 	first->tail->next = second->head;
2189667Slinton 	first->tail = second->tail;
2199667Slinton 	first->nitems = first->nitems + second->nitems;
2209667Slinton 	r = first;
2219667Slinton     }
2229667Slinton     return r;
2239667Slinton }
224