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