1 /* this is the brisby fancy list */
2 #ifndef __list_h
3 #define __list_h
4 
5 #include "mem.h"
6 #include "error.h"
7 
8 #include <stdlib.h>
9 
10 struct list_s {
11 	char *str;
12 	struct list_s *next;
13 };
14 
15 typedef struct list_s *list_t;
16 
list_length(list_t x)17 static int inline list_length(list_t x) {
18 	int i;
19 	for (i = 0; x; x = x->next, i++);
20 	return i;
21 }
list_push(list_t * x,char * str)22 static void inline list_push(list_t *x, char *str) {
23 	list_t p;
24 
25 	/* never push empty stuff on */
26 	if (str == 0)
27 		return;
28 
29 	p = mem_alloc(sizeof(list_t));
30 	if (!p)
31 		cfatal("mem_alloc: %s");
32 	p->next = (*x);
33 	p->str = str;
34 	*x = p;
35 }
list_pop(list_t * x)36 static char inline *list_pop(list_t *x) {
37 	list_t p;
38 	char *q;
39 
40 	p = (*x);
41 	if (p) {
42 		*x = p->next;
43 		q = p->str;
44 		mem_free(p);
45 	} else
46 		q = 0;
47 	return q;
48 }
list_reverse(list_t * p)49 static void inline list_reverse(list_t *p) {
50 	list_t x = 0;
51 	char *q;
52 
53 	if (!p || !*p)
54 		return;
55 	while ((q = list_pop(p))) {
56 		list_push(&x, q);
57 	}
58 	*p = x;
59 }
__list_randomize_helper(list_t * x)60 static char inline *__list_randomize_helper(list_t *x)
61 {
62 	char *q;
63 	list_t p;
64 	if (!x || !*x || !(*x)->next) return 0;
65 	q = (*x)->next->str;
66 	p = (*x)->next;
67 	(*x)->next = (*x)->next->next;
68 	mem_free(p);
69 	return q;
70 }
list_randomize(list_t * p)71 static void inline list_randomize(list_t *p) {
72 	list_t x = 0, y;
73 	int i, j, k, q, z;
74 	char *s;
75 
76 	/* no need */
77 	if (!p || !*p || !(*p)->next)
78 		return;
79 	if (!(*p)->next->next) {
80 		/* shortcut */
81 		if (rand() % 2 == 0) {
82 			list_reverse(p);
83 		}
84 		return;
85 	}
86 	/* count list elements */
87 	for (i = 0, x = *p; x; i++, x = x->next);
88 
89 	/* x is 0 again */
90 	j = i;
91 	for (z = j*j; z > 0; z--) {
92 		i = j; while (i > 2 && *p) {
93 			k = rand() % (i+1);
94 			for (y = *p, q = 0; q < k; q++, y = y->next);
95 			if (!y) {
96 				i--;
97 				list_push(&x, list_pop(p));
98 				continue;
99 			}
100 			s = __list_randomize_helper(&y);
101 			if (!s) continue;
102 			list_push(&x, s);
103 			i--;
104 		}
105 		while (*p) {
106 			list_push(&x, list_pop(p));
107 		}
108 	}
109 	*p = x;
110 }
111 
112 #endif
113