fix wrong usage of notify_edge for add_End_keepalive, add_Sync_pred and nodes with...
[libfirm] / ir / adt / plist.c
1 /**
2  * Simple, non circular, double linked pointer list.
3  * Created because the properties of the standard circular list were not
4  * very well suited for the interference graph implementation.
5  * This list uses an obstack and a free-list to efficiently manage its
6  * elements.
7  * @author Kimon Hoffmann
8  * @date   14.07.2005
9  * @cvs-id $Id$
10  * @note Until now the code is entirely untested so it probably contains
11  *              plenty of errors.
12  */
13 #include <stdlib.h>
14
15 #include "plist.h"
16
17 /**
18  * Helper macro that returns a new uninitialized list element by either
19  * fetching one from the free-list or allocating a new one on the lists
20  * obstack.
21  * @param list the list for which to allocate the element.
22  * @return the newly allocated, uninitialized element.
23  */
24 static plist_element_t *allocate_element(plist_t* list) {
25         plist_element_t *new_element;
26
27         if (list->first_free_element != NULL) {
28                 new_element              = list->first_free_element;
29                 list->first_free_element = new_element->next;
30                 new_element->next        = NULL;
31         }
32         else {
33                 new_element = obstack_alloc(list->obst, sizeof(*new_element));
34         }
35
36         return new_element;
37 }
38
39 plist_t *plist_new(void) {
40         plist_t *list = xmalloc(sizeof(*list) + sizeof(*list->obst));
41
42         list->obst               = (struct obstack *)&list[1];
43         list->foreign_obstack    = 0;
44         list->first_element      = NULL;
45         list->last_element       = NULL;
46         list->first_free_element = NULL;
47         list->element_count      = 0;
48
49         obstack_init(list->obst);
50         return list;
51 }
52
53 plist_t *plist_obstack_new(struct obstack *obst) {
54         plist_t *list = obstack_alloc(obst, sizeof(*list));
55
56         list->obst               = obst;
57         list->foreign_obstack    = 1;
58         list->first_element      = NULL;
59         list->last_element       = NULL;
60         list->first_free_element = NULL;
61         list->element_count      = 0;
62
63         return list;
64 }
65
66 void plist_free(plist_t *list) {
67         list->first_element      = NULL;
68         list->last_element       = NULL;
69         list->first_free_element = NULL;
70         list->element_count      = 0;
71
72         if (! list->foreign_obstack) {
73                 obstack_free(list->obst, NULL);
74                 xfree(list);
75         }
76 }
77
78 void plist_insert_back(plist_t *list, void *value) {
79         if (list->last_element != NULL) {
80                 plist_insert_after(list, list->last_element, value);
81         }
82         else {
83                 plist_element_t *newElement = allocate_element(list);
84
85                 newElement->data    = value;
86                 newElement->prev    = NULL;
87                 newElement->next    = NULL;
88                 list->first_element = list->last_element = newElement;
89                 list->element_count = 1;
90         }
91 }
92
93 void plist_insert_front(plist_t *list, void *value) {
94         if (list->first_element != NULL) {
95                 plist_insert_before(list, list->first_element, value);
96         }
97         else {
98                 plist_element_t *newElement = allocate_element(list);
99
100                 newElement->data    = value;
101                 newElement->prev    = NULL;
102                 newElement->next    = NULL;
103                 list->first_element = list->last_element = newElement;
104                 list->element_count = 1;
105         }
106 }
107
108 void plist_insert_before(plist_t *list, plist_element_t *element, void *value) {
109         plist_element_t *prevElement;
110         plist_element_t *newElement = allocate_element(list);
111
112         newElement->data = value;
113         newElement->next = element;
114         prevElement      = element->prev;
115         newElement->prev = prevElement;
116
117         if (prevElement != NULL) {
118                 prevElement->next = newElement;
119         }
120         else {
121                 list->first_element = newElement;
122         }
123
124         element->prev = newElement;
125         ++list->element_count;
126 }
127
128 void plist_insert_after(plist_t* list, plist_element_t* element, void* value) {
129         plist_element_t *nextElement;
130         plist_element_t *newElement = allocate_element(list);
131
132         newElement->data = value;
133         newElement->prev = element;
134         nextElement      = element->next;
135         newElement->next = nextElement;
136
137         if (nextElement != NULL) {
138                 nextElement->prev = newElement;
139         }
140         else {
141                 list->last_element = newElement;
142         }
143
144         element->next = newElement;
145         ++list->element_count;
146 }
147
148 int plist_has_value(plist_t *list, void *value) {
149         plist_element_t *iter;
150
151         for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
152                 if (plist_element_get_value(iter) == value)
153                         return 1;
154         }
155
156         return 0;
157 }
158
159 plist_element_t *plist_find_value(plist_t *list, void *value) {
160         plist_element_t *iter;
161
162         for (iter = plist_first(list); iter; iter = plist_element_get_next(iter)) {
163                 if (plist_element_get_value(iter) == value)
164                         return iter;
165         }
166
167         return NULL;
168 }
169
170 void plist_erase(plist_t *list, plist_element_t *element) {
171         plist_element_t *next_element = element->next;
172         plist_element_t *prev_element = element->prev;
173
174         if (next_element != NULL) {
175                 next_element->prev = prev_element;
176         }
177         else {
178                 list->last_element = prev_element;
179         }
180
181         if (prev_element != NULL) {
182                 prev_element->next = next_element;
183         }
184         else {
185                 list->first_element = next_element;
186         }
187
188         --list->element_count;
189
190         /* Clean the element and prepend it to the free list */
191         element->prev            = NULL; /* The allocation code expects prev to be NULL */
192         element->next            = list->first_free_element;
193         list->first_free_element = element;
194 }
195
196 void plist_clear(plist_t *list) {
197         plist_element_t *curr_element = list->first_element;
198
199         while (curr_element != NULL) {
200                 curr_element->prev = NULL;
201                 curr_element       = curr_element->next;
202         }
203
204         curr_element = list->last_element;
205
206         if (curr_element != NULL) {
207                 curr_element->next = list->first_free_element;
208         }
209
210         list->first_free_element = list->first_element;
211         list->first_element      = 0;
212         list->last_element       = 0;
213         list->element_count      = 0;
214 }