jcs ratpoison hax
1/* This file was taken from the Linux kernel and is
2 * Copyright (C) 2003 Linus Torvalds
3 *
4 * Modified by Shawn Betts. Portions created by Shawn Betts are
5 * Copyright (C) 2003, 2004 Shawn Betts
6 *
7 * This file is part of ratpoison.
8 *
9 * ratpoison is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
12 * any later version.
13 *
14 * ratpoison is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this software; see the file COPYING. If not, write to
21 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
22 * Boston, MA 02111-1307 USA
23 */
24
25#include "linkedlist.h"
26
27/*
28 * Insert a new entry between two known consecutive entries.
29 *
30 * This is only for internal list manipulation where we know
31 * the prev/next entries already!
32 */
33void
34__list_add(struct list_head *new,
35 struct list_head *prev,
36 struct list_head *next)
37{
38 next->prev = new;
39 new->next = next;
40 new->prev = prev;
41 prev->next = new;
42}
43
44/**
45 * list_add - add a new entry
46 * @new: new entry to be added
47 * @head: list head to add it after
48 *
49 * Insert a new entry after the specified head.
50 * This is good for implementing stacks.
51 */
52void
53list_add(struct list_head *new, struct list_head *head)
54{
55 __list_add(new, head, head->next);
56}
57
58/**
59 * list_add_tail - add a new entry
60 * @new: new entry to be added
61 * @head: list head to add it before
62 *
63 * Insert a new entry before the specified head.
64 * This is useful for implementing queues.
65 */
66void
67list_add_tail(struct list_head *new, struct list_head *head)
68{
69 __list_add(new, head->prev, head);
70}
71
72/*
73 * Delete a list entry by making the prev/next entries
74 * point to each other.
75 *
76 * This is only for internal list manipulation where we know
77 * the prev/next entries already!
78 */
79void
80__list_del(struct list_head * prev, struct list_head * next)
81{
82 next->prev = prev;
83 prev->next = next;
84}
85
86/**
87 * list_del - deletes entry from list.
88 * @entry: the element to delete from the list.
89 * Note: list_empty on entry does not return true after this, the entry is
90 * in an undefined state.
91 */
92void
93list_del(struct list_head *entry)
94{
95 __list_del(entry->prev, entry->next);
96}
97
98/**
99 * list_del_init - deletes entry from list and reinitialize it.
100 * @entry: the element to delete from the list.
101 */
102void
103list_del_init(struct list_head *entry)
104{
105 __list_del(entry->prev, entry->next);
106 INIT_LIST_HEAD(entry);
107}
108
109/**
110 * list_move - delete from one list and add as another's head
111 * @list: the entry to move
112 * @head: the head that will precede our entry
113 */
114void
115list_move(struct list_head *list, struct list_head *head)
116{
117 __list_del(list->prev, list->next);
118 list_add(list, head);
119}
120
121/**
122 * list_move_tail - delete from one list and add as another's tail
123 * @list: the entry to move
124 * @head: the head that will follow our entry
125 */
126void
127list_move_tail(struct list_head *list,
128 struct list_head *head)
129{
130 __list_del(list->prev, list->next);
131 list_add_tail(list, head);
132}
133
134/**
135 * list_empty - tests whether a list is empty
136 * @head: the list to test.
137 */
138int
139list_empty(struct list_head *head)
140{
141 return head->next == head;
142}
143
144void
145__list_splice(struct list_head *list,
146 struct list_head *head)
147{
148 struct list_head *first = list->next;
149 struct list_head *last = list->prev;
150 struct list_head *at = head->next;
151
152 first->prev = head;
153 head->next = first;
154
155 last->next = at;
156 at->prev = last;
157}
158
159/**
160 * list_splice - join two lists
161 * @list: the new list to add.
162 * @head: the place to add it in the first list.
163 */
164void
165list_splice(struct list_head *list, struct list_head *head)
166{
167 if (!list_empty(list))
168 __list_splice(list, head);
169}
170
171/**
172 * list_splice_init - join two lists and reinitialise the emptied list.
173 * @list: the new list to add.
174 * @head: the place to add it in the first list.
175 *
176 * The list at @list is reinitialised
177 */
178void
179list_splice_init(struct list_head *list,
180 struct list_head *head)
181{
182 if (!list_empty(list)) {
183 __list_splice(list, head);
184 INIT_LIST_HEAD(list);
185 }
186}
187
188int
189list_size (struct list_head *list)
190{
191 struct list_head *cur;
192
193 int i = 0;
194 list_for_each (cur, list)
195 i++;
196
197 return i;
198}
199
200#define MAX_LIST_LENGTH_BITS 20
201#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
202
203/*
204 * Returns a list organized in an intermediate format suited
205 * to chaining of merge() calls: null-terminated, no reserved or
206 * sentinel head node, "prev" links not maintained.
207 */
208static struct list_head *
209merge(void *priv,
210 int (*cmp)(void *priv, struct list_head *a,
211 struct list_head *b),
212 struct list_head *a, struct list_head *b)
213{
214 struct list_head head, *tail = &head;
215
216 while (a && b) {
217 /* if equal, take 'a' -- important for sort stability */
218 if ((*cmp) (priv, a, b) <= 0) {
219 tail->next = a;
220 a = a->next;
221 } else {
222 tail->next = b;
223 b = b->next;
224 }
225 tail = tail->next;
226 }
227 tail->next = a?:b;
228 return head.next;
229}
230
231/*
232 * Combine final list merge with restoration of standard doubly-linked
233 * list structure. This approach duplicates code from merge(), but
234 * runs faster than the tidier alternatives of either a separate final
235 * prev-link restoration pass, or maintaining the prev links
236 * throughout.
237 */
238static void
239merge_and_restore_back_links(void *priv,
240 int (*cmp)(void *priv, struct list_head *a,
241 struct list_head *b),
242 struct list_head *head,
243 struct list_head *a, struct list_head *b)
244{
245 struct list_head *tail = head;
246 unsigned int count = 0;
247
248 while (a && b) {
249 /* if equal, take 'a' -- important for sort stability */
250 if ((*cmp) (priv, a, b) <= 0) {
251 tail->next = a;
252 a->prev = tail;
253 a = a->next;
254 } else {
255 tail->next = b;
256 b->prev = tail;
257 b = b->next;
258 }
259 tail = tail->next;
260 }
261 tail->next = a ? : b;
262
263 do {
264 /*
265 * In worst cases this loop may run many iterations.
266 * Continue callbacks to the client even though no
267 * element comparison is needed, so the client's cmp()
268 * routine can invoke cond_resched() periodically.
269 */
270 if (!(++count))
271 (*cmp) (priv, tail->next, tail->next);
272
273 tail->next->prev = tail;
274 tail = tail->next;
275 } while (tail->next);
276
277 tail->next = head;
278 head->prev = tail;
279}
280
281/**
282 * list_sort - sort a list
283 * @priv: private data, opaque to list_sort(), passed to @cmp
284 * @head: the list to sort
285 * @cmp: the elements comparison function
286 *
287 * This function implements "merge sort", which has O(nlog(n))
288 * complexity.
289 *
290 * The comparison function @cmp must return a negative value if @a
291 * should sort before @b, and a positive value if @a should sort after
292 * @b. If @a and @b are equivalent, and their original relative
293 * ordering is to be preserved, @cmp must return 0.
294 */
295void
296list_sort(void *priv, struct list_head *head,
297 int (*cmp)(void *priv, struct list_head *a,
298 struct list_head *b))
299{
300 struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists
301 -- last slot is a sentinel */
302 int lev; /* index into part[] */
303 int max_lev = 0;
304 struct list_head *list;
305
306 if (list_empty (head))
307 return;
308
309 memset(part, 0, sizeof(part));
310
311 head->prev->next = NULL;
312 list = head->next;
313
314 while (list) {
315 struct list_head *cur = list;
316 list = list->next;
317 cur->next = NULL;
318
319 for (lev = 0; part[lev]; lev++) {
320 cur = merge (priv, cmp, part[lev], cur);
321 part[lev] = NULL;
322 }
323 if (lev > max_lev) {
324 if (lev >= ARRAY_SIZE(part)-1) {
325 lev--;
326 }
327 max_lev = lev;
328 }
329 part[lev] = cur;
330 }
331
332 for (lev = 0; lev < max_lev; lev++)
333 if (part[lev])
334 list = merge (priv, cmp, part[lev], list);
335
336 merge_and_restore_back_links (priv, cmp, head, part[max_lev], list);
337}