-
Notifications
You must be signed in to change notification settings - Fork 26
/
list.c
122 lines (105 loc) · 2.29 KB
/
list.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* list.c -- operations on lists ($Revision: 1.1.1.1 $) */
#include "es.h"
#include "gc.h"
/*
* allocation and garbage collector support
*/
DefineTag(List, static);
extern List *mklist(Term *term, List *next) {
gcdisable();
assert(term != NULL);
Ref(List *, list, gcnew(List));
list->term = term;
list->next = next;
gcenable();
RefReturn(list);
}
static void *ListCopy(void *op) {
void *np = gcnew(List);
memcpy(np, op, sizeof (List));
return np;
}
static size_t ListScan(void *p) {
List *list = p;
list->term = forward(list->term);
list->next = forward(list->next);
return sizeof (List);
}
/*
* basic list manipulations
*/
/* reverse -- destructively reverse a list */
extern List *reverse(List *list) {
List *prev, *next;
if (list == NULL)
return NULL;
prev = NULL;
do {
next = list->next;
list->next = prev;
prev = list;
} while ((list = next) != NULL);
return prev;
}
/* append -- merge two lists, non-destructively */
extern List *append(List *head, List *tail) {
List *lp, **prevp;
Ref(List *, hp, head);
Ref(List *, tp, tail);
gcreserve(40 * sizeof (List));
gcdisable();
head = hp;
tail = tp;
RefEnd2(tp, hp);
for (prevp = &lp; head != NULL; head = head->next) {
List *np = mklist(head->term, NULL);
*prevp = np;
prevp = &np->next;
}
*prevp = tail;
Ref(List *, result, lp);
gcenable();
RefReturn(result);
}
/* listcopy -- make a copy of a list */
extern List *listcopy(List *list) {
return append(list, NULL);
}
/* length -- lenth of a list */
extern int length(List *list) {
int len = 0;
for (; list != NULL; list = list->next)
++len;
return len;
}
/* listify -- turn an argc/argv vector into a list */
extern List *listify(int argc, char **argv) {
Ref(List *, list, NULL);
while (argc > 0) {
Term *term = mkstr(argv[--argc]);
list = mklist(term, list);
}
RefReturn(list);
}
/* nth -- return nth element of a list, indexed from 1 */
extern Term *nth(List *list, int n) {
for (; n > 0 && list != NULL; list = list->next) {
assert(list->term != NULL);
if (--n == 0)
return list->term;
}
return NULL;
}
/* sortlist */
extern List *sortlist(List *list) {
if (length(list) > 1) {
Vector *v = vectorize(list);
sortvector(v);
gcdisable();
Ref(List *, lp, listify(v->count, v->vector));
gcenable();
list = lp;
RefEnd(lp);
}
return list;
}