diff options
Diffstat (limited to 'src/cmd/acid/list.c')
-rw-r--r-- | src/cmd/acid/list.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/cmd/acid/list.c b/src/cmd/acid/list.c new file mode 100644 index 00000000..76214b2d --- /dev/null +++ b/src/cmd/acid/list.c @@ -0,0 +1,270 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ctype.h> +#include <mach.h> +#define Extern extern +#include "acid.h" + +static List **tail; + +List* +construct(Node *l) +{ + List *lh, **save; + + save = tail; + lh = 0; + tail = &lh; + build(l); + tail = save; + + return lh; +} + +int +listlen(List *l) +{ + int len; + + len = 0; + while(l) { + len++; + l = l->next; + } + return len; +} + +void +build(Node *n) +{ + List *l; + Node res; + + if(n == 0) + return; + + switch(n->op) { + case OLIST: + build(n->left); + build(n->right); + return; + default: + expr(n, &res); + l = al(res.type); + l->store = res.store; + *tail = l; + tail = &l->next; + } +} + +List* +addlist(List *l, List *r) +{ + List *f; + + if(l == 0) + return r; + + for(f = l; f->next; f = f->next) + ; + f->next = r; + + return l; +} + +void +append(Node *r, Node *list, Node *val) +{ + List *l, *f; + + l = al(val->type); + l->store = val->store; + l->next = 0; + + r->op = OCONST; + r->type = TLIST; + + if(list->store.u.l == 0) { + list->store.u.l = l; + r->store.u.l = l; + return; + } + for(f = list->store.u.l; f->next; f = f->next) + ; + f->next = l; + r->store.u.l = list->store.u.l; +} + +int +listcmp(List *l, List *r) +{ + if(l == r) + return 1; + + while(l) { + if(r == 0) + return 0; + if(l->type != r->type) + return 0; + switch(l->type) { + case TINT: + if(l->store.u.ival != r->store.u.ival) + return 0; + break; + case TFLOAT: + if(l->store.u.fval != r->store.u.fval) + return 0; + break; + case TSTRING: + if(scmp(l->store.u.string, r->store.u.string) == 0) + return 0; + break; + case TLIST: + if(listcmp(l->store.u.l, r->store.u.l) == 0) + return 0; + break; + } + l = l->next; + r = r->next; + } + if(l != r) + return 0; + return 1; +} + +void +nthelem(List *l, int n, Node *res) +{ + if(n < 0) + error("negative index in []"); + + while(l && n--) + l = l->next; + + res->op = OCONST; + if(l == 0) { + res->type = TLIST; + res->store.u.l = 0; + return; + } + res->type = l->type; + res->store = l->store; +} + +void +delete(List *l, int n, Node *res) +{ + List **tl; + + if(n < 0) + error("negative index in delete"); + + res->op = OCONST; + res->type = TLIST; + res->store.u.l = l; + + for(tl = &res->store.u.l; l && n--; l = l->next) + tl = &l->next; + + if(l == 0) + error("element beyond end of list"); + *tl = l->next; +} + +List* +listvar(char *s, long v) +{ + List *l, *tl; + + tl = al(TLIST); + + l = al(TSTRING); + tl->store.u.l = l; + l->store.fmt = 's'; + l->store.u.string = strnode(s); + l->next = al(TINT); + l = l->next; + l->store.fmt = 'X'; + l->store.u.ival = v; + + return tl; +} + +static List* +listlocals(Map *map, Regs *regs, Symbol *fn, int class) +{ + int i; + u32int val; + Symbol s; + List **tail, *l2; + + l2 = 0; + tail = &l2; + if(fn == nil) + return l2; + for(i = 0; indexlsym(fn, i, &s)>=0; i++) { + if(s.class != class) + continue; + if(class == CAUTO && s.name[0] == '.') + continue; + if(lget4(map, regs, s.loc, &val) < 0) + continue; + *tail = listvar(s.name, val); + tail = &(*tail)->next; + } + return l2; +} + +static List* +listparams(Map *map, Regs *regs, Symbol *fn) +{ + return listlocals(map, regs, fn, CPARAM); +} + +static List* +listautos(Map *map, Regs *regs, Symbol *fn) +{ + return listlocals(map, regs, fn, CAUTO); +} + +int +trlist(Map *map, Regs *regs, ulong pc, ulong callerpc, Symbol *sym, int depth) +{ + List *q, *l; + static List **tail; + + if (tracelist == 0) /* first time */ + tail = &tracelist; + + q = al(TLIST); + *tail = q; + tail = &q->next; + + l = al(TINT); /* Function address */ + q->store.u.l = l; + l->store.u.ival = sym ? sym->loc.addr : pc; + l->store.fmt = 'X'; + + l->next = al(TINT); /* actual pc address */ + l = l->next; + l->store.u.ival = pc; + l->store.fmt = 'X'; + + l->next = al(TINT); /* called from address */ + l = l->next; + l->store.u.ival = callerpc; + l->store.fmt = 'X'; + + l->next = al(TLIST); /* make list of params */ + l = l->next; + if(sym) + l->store.u.l = listparams(map, regs, sym); + + l->next = al(TLIST); /* make list of locals */ + l = l->next; + if(sym) + l->store.u.l = listautos(map, regs, sym); + + return depth<40; +} |