|
|
1.1 root 1: /* Copyright (c) 1982 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)lists.c 1.2 12/15/82";
4:
5: /*
6: * General list definitions.
7: *
8: * The assumption is that the elements in a list are words,
9: * usually pointers to the actual information.
10: */
11:
12: #include "defs.h"
13: #include "lists.h"
14:
15: #ifndef public
16:
17: typedef struct List *List;
18: typedef struct ListItem *ListItem;
19: typedef char *ListElement;
20:
21: #define list_item(element) generic_list_item((ListElement) (element))
22: #define list_element(type, item) ((type) (item == nil ? nil : (item)->element))
23: #define list_head(list) ((list == nil) ? nil : (list)->head)
24: #define list_tail(list) ((list == nil) ? nil : (list)->tail)
25: #define list_next(item) ((item == nil) ? nil : (item)->next)
26: #define list_prev(item) ((item == nil) ? nil : (item)->prev)
27: #define list_size(list) (((list) == nil) ? 0 : (list)->nitems)
28:
29: #define foreach(type, i, list) \
30: { \
31: register ListItem _item; \
32: \
33: _item = list_head(list); \
34: while (_item != nil) { \
35: i = list_element(type, _item); \
36: _item = list_next(_item);
37:
38: #define endfor \
39: } \
40: }
41:
42: /*
43: * Iterate through two equal-sized lists.
44: */
45:
46: #define foreach2(type1, i, list1, type2, j, list2) \
47: { \
48: register ListItem _item1, _item2; \
49: \
50: _item1 = list_head(list1); \
51: _item2 = list_head(list2); \
52: while (_item1 != nil) { \
53: i = list_element(type1, _item1); \
54: j = list_element(type2, _item2); \
55: _item1 = list_next(_item1); \
56: _item2 = list_next(_item2);
57:
58: #define list_islast() (_item == nil)
59: #define list_curitem(list) (_item == nil ? list_tail(list) : list_prev(_item))
60:
61: /*
62: * Representation should not be used outside except through macros.
63: */
64:
65: struct List {
66: Integer nitems;
67: ListItem head;
68: ListItem tail;
69: };
70:
71: struct ListItem {
72: ListElement element;
73: ListItem next;
74: ListItem prev;
75: };
76:
77: #endif
78:
79: /*
80: * Allocate and initialize a list.
81: */
82:
83: public List list_alloc()
84: {
85: List list;
86:
87: list = new(List);
88: list->nitems = 0;
89: list->head = nil;
90: list->tail = nil;
91: return list;
92: }
93:
94: /*
95: * Create a list item from an object (represented as pointer or integer).
96: */
97:
98: public ListItem generic_list_item(element)
99: ListElement element;
100: {
101: ListItem i;
102:
103: i = new(ListItem);
104: i->element = element;
105: i->next = nil;
106: i->prev = nil;
107: return i;
108: }
109:
110: /*
111: * Insert an item before the item in a list.
112: */
113:
114: public list_insert(item, after, list)
115: ListItem item;
116: ListItem after;
117: List list;
118: {
119: ListItem a;
120:
121: checkref(list);
122: list->nitems = list->nitems + 1;
123: if (list->head == nil) {
124: list->head = item;
125: list->tail = item;
126: } else {
127: if (after == nil) {
128: a = list->head;
129: } else {
130: a = after;
131: }
132: item->next = a;
133: item->prev = a->prev;
134: if (a->prev != nil) {
135: a->prev->next = item;
136: } else {
137: list->head = item;
138: }
139: a->prev = item;
140: }
141: }
142:
143: /*
144: * Append an item after the given item in a list.
145: */
146:
147: public list_append(item, before, list)
148: ListItem item;
149: ListItem before;
150: List list;
151: {
152: ListItem b;
153:
154: checkref(list);
155: list->nitems = list->nitems + 1;
156: if (list->head == nil) {
157: list->head = item;
158: list->tail = item;
159: } else {
160: if (before == nil) {
161: b = list->tail;
162: } else {
163: b = before;
164: }
165: item->next = b->next;
166: item->prev = b;
167: if (b->next != nil) {
168: b->next->prev = item;
169: } else {
170: list->tail = item;
171: }
172: b->next = item;
173: }
174: }
175:
176: /*
177: * Delete an item from a list.
178: */
179:
180: public list_delete(item, list)
181: ListItem item;
182: List list;
183: {
184: checkref(item);
185: checkref(list);
186: assert(list->nitems > 0);
187: if (item->next == nil) {
188: list->tail = item->prev;
189: } else {
190: item->next->prev = item->prev;
191: }
192: if (item->prev == nil) {
193: list->head = item->next;
194: } else {
195: item->prev->next = item->next;
196: }
197: list->nitems = list->nitems - 1;
198: }
199:
200: /*
201: * Concatenate one list onto the end of another.
202: */
203:
204: public List list_concat(first, second)
205: List first, second;
206: {
207: List r;
208:
209: if (first == nil) {
210: r = second;
211: } else if (second == nil) {
212: r = first;
213: } else {
214: second->head->prev = first->tail;
215: first->tail->next = second->head;
216: first->tail = second->tail;
217: first->nitems = first->nitems + second->nitems;
218: r = first;
219: }
220: return r;
221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.