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