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