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