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