|  | #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* | 
|  | listregisters(Map *map, Regs *regs) | 
|  | { | 
|  | List **tail, *l2, *l; | 
|  | Regdesc *rp; | 
|  | u64int v; | 
|  |  | 
|  | l2 = 0; | 
|  | tail = &l2; | 
|  | for(rp=mach->reglist; rp->name; rp++){ | 
|  | if(rget(regs, rp->name, &v) < 0) | 
|  | continue; | 
|  | l = al(TSTRING); | 
|  | l->store.fmt = 's'; | 
|  | l->store.u.string = strnode(rp->name); | 
|  | *tail = l; | 
|  | tail = &l->next; | 
|  | l = al(TINT); | 
|  | l->store.fmt = 'X'; | 
|  | l->store.u.ival = v; | 
|  | *tail = l; | 
|  | tail = &l->next; | 
|  | } | 
|  | return l2; | 
|  | } | 
|  |  | 
|  | 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 || 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, u64int pc, u64int 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); | 
|  |  | 
|  | l->next = al(TLIST);		/* make list of registers */ | 
|  | l = l->next; | 
|  | l->store.u.l = listregisters(map, regs); | 
|  |  | 
|  | return depth<40; | 
|  | } |