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 123
|
/* 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) {
assert(n > 0);
for (; 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;
}
|