diff options
author | rsc <devnull@localhost> | 2004-04-19 19:32:07 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-19 19:32:07 +0000 |
commit | 564ca709d0e20d4fc46744bd858f14cff94ab382 (patch) | |
tree | 47bf49710238a6cb7112682e7bd0885f82544759 /src/cmd/acid/builtin.c | |
parent | 22a7368ef24d5c530a275dd0db0bd4f23b1c3ce3 (diff) | |
download | plan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.tar.gz plan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.tar.bz2 plan9port-564ca709d0e20d4fc46744bd858f14cff94ab382.zip |
acid
Diffstat (limited to 'src/cmd/acid/builtin.c')
-rw-r--r-- | src/cmd/acid/builtin.c | 1460 |
1 files changed, 1460 insertions, 0 deletions
diff --git a/src/cmd/acid/builtin.c b/src/cmd/acid/builtin.c new file mode 100644 index 00000000..492fdfb4 --- /dev/null +++ b/src/cmd/acid/builtin.c @@ -0,0 +1,1460 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <ctype.h> +#include <mach.h> +#include <regexp.h> +#define Extern extern +#include "acid.h" +#include "y.tab.h" + +void cvtatof(Node*, Node*); +void cvtatoi(Node*, Node*); +void cvtitoa(Node*, Node*); +void bprint(Node*, Node*); +void funcbound(Node*, Node*); +void printto(Node*, Node*); +void getfile(Node*, Node*); +void fmt(Node*, Node*); +void pcfile(Node*, Node*); +void pcline(Node*, Node*); +void setproc(Node*, Node*); +void strace(Node*, Node*); +void follow(Node*, Node*); +void reason(Node*, Node*); +void newproc(Node*, Node*); +void startstop(Node*, Node*); +void match(Node*, Node*); +void status(Node*, Node*); +void xkill(Node*,Node*); +void waitstop(Node*, Node*); +void sysstop(Node*, Node*); +void stop(Node*, Node*); +void start(Node*, Node*); +void filepc(Node*, Node*); +void doerror(Node*, Node*); +void rc(Node*, Node*); +void doaccess(Node*, Node*); +void map(Node*, Node*); +void readfile(Node*, Node*); +void interpret(Node*, Node*); +void include(Node*, Node*); +void includepipe(Node*, Node*); +void regexp(Node*, Node*); +void textfile(Node*, Node*); +void deltextfile(Node*, Node*); + +typedef struct Btab Btab; +struct Btab +{ + char *name; + void (*fn)(Node*, Node*); +} tab[] = +{ + "atof", cvtatof, + "atoi", cvtatoi, + "deltextfile", deltextfile, + "error", doerror, + "file", getfile, + "readfile", readfile, + "access", doaccess, + "filepc", filepc, + "fnbound", funcbound, + "fmt", fmt, + "follow", follow, + "include", include, + "includepipe", includepipe, + "interpret", interpret, + "itoa", cvtitoa, + "kill", xkill, + "map", map, + "match", match, + "newproc", newproc, + "pcfile", pcfile, + "pcline", pcline, + "print", bprint, + "printto", printto, + "rc", rc, + "reason", reason, + "regexp", regexp, + "setproc", setproc, + "start", start, + "startstop", startstop, + "status", status, + "stop", stop, + "strace", strace, + "sysstop", sysstop, + "textfile", textfile, + "waitstop", waitstop, + 0 +}; + +void +mkprint(Lsym *s) +{ + prnt = malloc(sizeof(Node)); + memset(prnt, 0, sizeof(Node)); + prnt->op = OCALL; + prnt->left = malloc(sizeof(Node)); + memset(prnt->left, 0, sizeof(Node)); + prnt->left->sym = s; +} + +void +installbuiltin(void) +{ + Btab *b; + Lsym *s; + + b = tab; + while(b->name) { + s = look(b->name); + if(s == 0) + s = enter(b->name, Tid); + + s->builtin = b->fn; + if(b->fn == bprint) + mkprint(s); + b++; + } +} + +void +match(Node *r, Node *args) +{ + int i; + List *f; + Node *av[Maxarg]; + Node resi, resl; + + na = 0; + flatten(av, args); + if(na != 2) + error("match(obj, list): arg count"); + + expr(av[1], &resl); + if(resl.type != TLIST) + error("match(obj, list): need list"); + expr(av[0], &resi); + + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; + r->store.u.ival = -1; + + i = 0; + for(f = resl.store.u.l; f; f = f->next) { + if(resi.type == f->type) { + switch(resi.type) { + case TINT: + if(resi.store.u.ival == f->store.u.ival) { + r->store.u.ival = i; + return; + } + break; + case TFLOAT: + if(resi.store.u.fval == f->store.u.fval) { + r->store.u.ival = i; + return; + } + break; + case TSTRING: + if(scmp(resi.store.u.string, f->store.u.string)) { + r->store.u.ival = i; + return; + } + break; + case TLIST: + error("match(obj, list): not defined for list"); + } + } + i++; + } +} + +void +newproc(Node *r, Node *args) +{ + int i; + Node res; + char *p, *e; + char *argv[Maxarg], buf[Strsize]; + + i = 1; + argv[0] = symfil; + + if(args) { + expr(args, &res); + if(res.type != TSTRING) + error("newproc(): arg not string"); + if(res.store.u.string->len >= sizeof(buf)) + error("newproc(): too many arguments"); + memmove(buf, res.store.u.string->string, res.store.u.string->len); + buf[res.store.u.string->len] = '\0'; + p = buf; + e = buf+res.store.u.string->len; + for(;;) { + while(p < e && (*p == '\t' || *p == ' ')) + *p++ = '\0'; + if(p >= e) + break; + argv[i++] = p; + if(i >= Maxarg) + error("newproc: too many arguments"); + while(p < e && *p != '\t' && *p != ' ') + p++; + } + } + argv[i] = 0; + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; + r->store.u.ival = nproc(argv); +} + +void +startstop(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("startstop(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("startstop(pid): arg type"); + + msg(res.store.u.ival, "startstop"); + notes(res.store.u.ival); + dostop(res.store.u.ival); +} + +void +waitstop(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("waitstop(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("waitstop(pid): arg type"); + + Bflush(bout); + msg(res.store.u.ival, "waitstop"); + notes(res.store.u.ival); + dostop(res.store.u.ival); +} + +void +sysstop(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("waitstop(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("waitstop(pid): arg type"); + + Bflush(bout); + msg(res.store.u.ival, "sysstop"); + notes(res.store.u.ival); + dostop(res.store.u.ival); +} + +void +start(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("start(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("start(pid): arg type"); + + msg(res.store.u.ival, "start"); +} + +void +stop(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("stop(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("stop(pid): arg type"); + + Bflush(bout); + msg(res.store.u.ival, "stop"); + notes(res.store.u.ival); + dostop(res.store.u.ival); +} + +void +xkill(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("kill(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("kill(pid): arg type"); + + msg(res.store.u.ival, "kill"); + deinstall(res.store.u.ival); +} + +void +status(Node *r, Node *args) +{ + Node res; + char *p; + + USED(r); + if(args == 0) + error("status(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("status(pid): arg type"); + + p = getstatus(res.store.u.ival); + r->store.u.string = strnode(p); + r->op = OCONST; + r->store.fmt = 's'; + r->type = TSTRING; +} + +void +reason(Node *r, Node *args) +{ + Node res; + + if(args == 0) + error("reason(cause): no cause"); + expr(args, &res); + if(res.type != TINT) + error("reason(cause): arg type"); + + r->op = OCONST; + r->type = TSTRING; + r->store.fmt = 's'; + r->store.u.string = strnode((*mach->exc)(cormap, correg)); +} + +void +follow(Node *r, Node *args) +{ + int n, i; + Node res; + ulong f[10]; + List **tail, *l; + + if(args == 0) + error("follow(addr): no addr"); + expr(args, &res); + if(res.type != TINT) + error("follow(addr): arg type"); + + n = (*mach->foll)(cormap, correg, res.store.u.ival, f); + if (n < 0) + error("follow(addr): %r"); + tail = &r->store.u.l; + for(i = 0; i < n; i++) { + l = al(TINT); + l->store.u.ival = f[i]; + l->store.fmt = 'X'; + *tail = l; + tail = &l->next; + } +} + +void +funcbound(Node *r, Node *args) +{ + int n; + Node res; + ulong bounds[2]; + List *l; + + if(args == 0) + error("fnbound(addr): no addr"); + expr(args, &res); + if(res.type != TINT) + error("fnbound(addr): arg type"); + + n = fnbound(res.store.u.ival, bounds); + if (n != 0) { + r->store.u.l = al(TINT); + l = r->store.u.l; + l->store.u.ival = bounds[0]; + l->store.fmt = 'X'; + l->next = al(TINT); + l = l->next; + l->store.u.ival = bounds[1]; + l->store.fmt = 'X'; + } +} + +void +setproc(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("setproc(pid): no pid"); + expr(args, &res); + if(res.type != TINT) + error("setproc(pid): arg type"); + + sproc(res.store.u.ival); +} + +void +filepc(Node *r, Node *args) +{ + int i; + Node res; + char *p, c; + ulong v; + + if(args == 0) + error("filepc(filename:line): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("filepc(filename:line): arg type"); + + p = strchr(res.store.u.string->string, ':'); + if(p == 0) + error("filepc(filename:line): bad arg format"); + + c = *p; + *p++ = '\0'; + i = file2pc(res.store.u.string->string, atoi(p), &v); + p[-1] = c; + if(i < 0) + error("filepc(filename:line): can't find address"); + + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; + r->store.u.ival = v; +} + +void +interpret(Node *r, Node *args) +{ + Node res; + int isave; + + if(args == 0) + error("interpret(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("interpret(string): arg type"); + + pushstr(&res); + + isave = interactive; + interactive = 0; + r->store.u.ival = yyparse(); + interactive = isave; + popio(); + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; +} + +void +include(Node *r, Node *args) +{ + Node res; + int isave; + + if(args == 0) + error("include(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("include(string): arg type"); + + Bflush(bout); + pushfile(res.store.u.string->string); + + isave = interactive; + interactive = 0; + r->store.u.ival = yyparse(); + interactive = isave; + popio(); + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; +} + +void +includepipe(Node *r, Node *args) +{ + Node res; + int i, isave, pid, pip[2]; + char *argv[4]; + Waitmsg *w; + + USED(r); + if(args == 0) + error("includepipe(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("includepipe(string): arg type"); + + Bflush(bout); + + argv[0] = "rc"; + argv[1] = "-c"; + argv[2] = res.store.u.string->string; + argv[3] = 0; + + if(pipe(pip) < 0) + error("pipe: %r"); + + pid = fork(); + switch(pid) { + case -1: + close(pip[0]); + close(pip[1]); + error("fork: %r"); + case 0: + close(pip[0]); + close(0); + open("/dev/null", OREAD); + dup(pip[1], 1); + if(pip[1] > 1) + close(pip[1]); + for(i=3; i<100; i++) + close(i); + exec("rc", argv); + sysfatal("exec rc: %r"); + } + + close(pip[1]); + pushfd(pip[0]); + + isave = interactive; + interactive = 0; + r->store.u.ival = yyparse(); + interactive = isave; + popio(); + r->op = OCONST; + r->type = TINT; + r->store.fmt = 'D'; + + w = waitfor(pid); + if(w->msg && w->msg[0]) + error("includepipe(\"%s\"): %s", argv[2], w->msg); /* leaks w */ + free(w); +} + +void +rc(Node *r, Node *args) +{ + Node res; + int pid; + char *p, *q, *argv[4]; + Waitmsg *w; + + USED(r); + if(args == 0) + error("rc(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("rc(string): arg type"); + + argv[0] = "rc"; + argv[1] = "-c"; + argv[2] = res.store.u.string->string; + argv[3] = 0; + + pid = fork(); + switch(pid) { + case -1: + error("fork %r"); + case 0: + exec("rc", argv); + exits(0); + default: + w = waitfor(pid); + break; + } + p = w->msg; + q = strrchr(p, ':'); + if (q) + p = q+1; + + r->op = OCONST; + r->type = TSTRING; + r->store.u.string = strnode(p); + free(w); + r->store.fmt = 's'; +} + +void +doerror(Node *r, Node *args) +{ + Node res; + + USED(r); + if(args == 0) + error("error(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("error(string): arg type"); + + error(res.store.u.string->string); +} + +void +doaccess(Node *r, Node *args) +{ + Node res; + + if(args == 0) + error("access(filename): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("access(filename): arg type"); + + r->op = OCONST; + r->type = TINT; + r->store.u.ival = 0; + if(access(res.store.u.string->string, 4) == 0) + r->store.u.ival = 1; +} + +void +readfile(Node *r, Node *args) +{ + Node res; + int n, fd; + char *buf; + Dir *db; + + if(args == 0) + error("readfile(filename): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("readfile(filename): arg type"); + + fd = open(res.store.u.string->string, OREAD); + if(fd < 0) + return; + + db = dirfstat(fd); + if(db == nil || db->length == 0) + n = 8192; + else + n = db->length; + free(db); + + buf = malloc(n); + n = read(fd, buf, n); + + if(n > 0) { + r->op = OCONST; + r->type = TSTRING; + r->store.u.string = strnodlen(buf, n); + r->store.fmt = 's'; + } + free(buf); + close(fd); +} + +void +getfile(Node *r, Node *args) +{ + int n; + char *p; + Node res; + String *s; + Biobuf *bp; + List **l, *new; + + if(args == 0) + error("file(filename): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("file(filename): arg type"); + + r->op = OCONST; + r->type = TLIST; + r->store.u.l = 0; + + p = res.store.u.string->string; + bp = Bopen(p, OREAD); + if(bp == 0) + return; + + l = &r->store.u.l; + for(;;) { + p = Brdline(bp, '\n'); + n = Blinelen(bp); + if(p == 0) { + if(n == 0) + break; + s = strnodlen(0, n); + Bread(bp, s->string, n); + } + else + s = strnodlen(p, n-1); + + new = al(TSTRING); + new->store.u.string = s; + new->store.fmt = 's'; + *l = new; + l = &new->next; + } + Bterm(bp); +} + +void +cvtatof(Node *r, Node *args) +{ + Node res; + + if(args == 0) + error("atof(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("atof(string): arg type"); + + r->op = OCONST; + r->type = TFLOAT; + r->store.u.fval = atof(res.store.u.string->string); + r->store.fmt = 'f'; +} + +void +cvtatoi(Node *r, Node *args) +{ + Node res; + + if(args == 0) + error("atoi(string): arg count"); + expr(args, &res); + if(res.type != TSTRING) + error("atoi(string): arg type"); + + r->op = OCONST; + r->type = TINT; + r->store.u.ival = strtoul(res.store.u.string->string, 0, 0); + r->store.fmt = 'D'; +} + +void +cvtitoa(Node *r, Node *args) +{ + Node res; + Node *av[Maxarg]; + int ival; + char buf[128], *fmt; + + if(args == 0) +err: + error("itoa(number [, printformat]): arg count"); + na = 0; + flatten(av, args); + if(na == 0 || na > 2) + goto err; + expr(av[0], &res); + if(res.type != TINT) + error("itoa(integer): arg type"); + ival = (int)res.store.u.ival; + fmt = "%d"; + if(na == 2){ + expr(av[1], &res); + if(res.type != TSTRING) + error("itoa(integer, string): arg type"); + fmt = res.store.u.string->string; + } + + sprint(buf, fmt, ival); + r->op = OCONST; + r->type = TSTRING; + r->store.u.string = strnode(buf); + r->store.fmt = 's'; +} + +List* +mapent(Map *m) +{ + int i; + List *l, *n, **t, *h; + + h = 0; + t = &h; + for(i = 0; i < m->nseg; i++) { + l = al(TSTRING); + n = al(TLIST); + n->store.u.l = l; + *t = n; + t = &n->next; + l->store.u.string = strnode(m->seg[i].name); + l->store.fmt = 's'; + l->next = al(TSTRING); + l = l->next; + l->store.u.string = strnode(m->seg[i].file ? m->seg[i].file : ""); + l->store.fmt = 's'; + l->next = al(TINT); + l = l->next; + l->store.u.ival = m->seg[i].base; + l->store.fmt = 'X'; + l->next = al(TINT); + l = l->next; + l->store.u.ival = m->seg[i].base + m->seg[i].size; + l->store.fmt = 'X'; + l->next = al(TINT); + l = l->next; + l->store.u.ival = m->seg[i].offset; + l->store.fmt = 'X'; + } + return h; +} + +void +map(Node *r, Node *args) +{ + int i; + Map *m; + List *l; + char *nam, *fil; + Node *av[Maxarg], res; + + na = 0; + flatten(av, args); + + if(na != 0) { + expr(av[0], &res); + if(res.type != TLIST) + error("map(list): map needs a list"); + if(listlen(res.store.u.l) != 5) + error("map(list): list must have 5 entries"); + + l = res.store.u.l; + if(l->type != TSTRING) + error("map name must be a string"); + nam = l->store.u.string->string; + l = l->next; + if(l->type != TSTRING) + error("map file must be a string"); + fil = l->store.u.string->string; + m = symmap; + i = findseg(m, nam, fil); + if(i < 0) { + m = cormap; + i = findseg(m, nam, fil); + } + if(i < 0) + error("%s %s is not a map entry", nam, fil); + l = l->next; + if(l->type != TINT) + error("map entry not int"); + m->seg[i].base = l->store.u.ival; +/* + if (strcmp(ent, "text") == 0) + textseg(l->store.u.ival, &fhdr); +*/ + l = l->next; + if(l->type != TINT) + error("map entry not int"); + m->seg[i].size = l->store.u.ival - m->seg[i].base; + l = l->next; + if(l->type != TINT) + error("map entry not int"); + m->seg[i].offset = l->store.u.ival; + } + + r->type = TLIST; + r->store.u.l = 0; + if(symmap) + r->store.u.l = mapent(symmap); + if(cormap) { + if(r->store.u.l == 0) + r->store.u.l = mapent(cormap); + else { + for(l = r->store.u.l; l->next; l = l->next) + ; + l->next = mapent(cormap); + } + } +} + +void +flatten(Node **av, Node *n) +{ + if(n == 0) + return; + + switch(n->op) { + case OLIST: + flatten(av, n->left); + flatten(av, n->right); + break; + default: + av[na++] = n; + if(na >= Maxarg) + error("too many function arguments"); + break; + } +} + +static struct +{ + char *name; + ulong val; +} sregs[Maxarg/2]; +static int nsregs; + +static int +straceregrw(Regs *regs, char *name, ulong *val, int isr) +{ + int i; + + if(!isr){ + werrstr("saved registers cannot be written"); + return -1; + } + for(i=0; i<nsregs; i++) + if(strcmp(sregs[i].name, name) == 0){ + *val = sregs[i].val; + return 0; + } + return rget(correg, name, val); +} + +void +strace(Node *r, Node *args) +{ + Node *av[Maxarg], res; + List *l; + Regs regs; + + na = 0; + flatten(av, args); + + if(na != 1) + error("strace(list): want one arg"); + + expr(av[0], &res); + if(res.type != TLIST) + error("strace(list): strace needs a list"); + l = res.store.u.l; + if(listlen(l)%2) + error("strace(list): strace needs an even-length list"); + for(nsregs=0; l; nsregs++){ + if(l->type != TSTRING) + error("strace({r,v,r,v,...}): non-string name"); + sregs[nsregs].name = l->store.u.string->string; + if(regdesc(sregs[nsregs].name) == nil) + error("strace: bad register '%s'", sregs[nsregs].name); + l = l->next; + + if(l == nil) + error("cannot happen in strace"); + if(l->type != TINT) + error("strace: non-int value for %s", sregs[nsregs].name); + sregs[nsregs].val = l->store.u.ival; + l = l->next; + } + regs.rw = straceregrw; + + tracelist = 0; + if(stacktrace(cormap, ®s, trlist) <= 0) + error("no stack frame"); + r->type = TLIST; + r->store.u.l = tracelist; +} + +void +regerror(char *msg) +{ + error(msg); +} + +void +regexp(Node *r, Node *args) +{ + Node res; + Reprog *rp; + Node *av[Maxarg]; + + na = 0; + flatten(av, args); + if(na != 2) + error("regexp(pattern, string): arg count"); + expr(av[0], &res); + if(res.type != TSTRING) + error("regexp(pattern, string): pattern must be string"); + rp = regcomp(res.store.u.string->string); + if(rp == 0) + return; + + expr(av[1], &res); + if(res.type != TSTRING) + error("regexp(pattern, string): bad string"); + + r->store.fmt = 'D'; + r->type = TINT; + r->store.u.ival = regexec(rp, res.store.u.string->string, 0, 0); + free(rp); +} + +char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVxXYZ"; + +void +fmt(Node *r, Node *args) +{ + Node res; + Node *av[Maxarg]; + + na = 0; + flatten(av, args); + if(na != 2) + error("fmt(obj, fmt): arg count"); + expr(av[1], &res); + if(res.type != TINT || strchr(vfmt, res.store.u.ival) == 0) + error("fmt(obj, fmt): bad format '%c'", (char)res.store.u.ival); + expr(av[0], r); + r->store.fmt = res.store.u.ival; +} + +void +patom(char type, Store *res) +{ + int i; + char buf[512]; + extern char *typenames[]; + + switch(res->fmt) { + case 'c': + Bprint(bout, "%c", (int)res->u.ival); + break; + case 'C': + if(res->u.ival < ' ' || res->u.ival >= 0x7f) + Bprint(bout, "%3d", (int)res->u.ival&0xff); + else + Bprint(bout, "%3c", (int)res->u.ival); + break; + case 'r': + Bprint(bout, "%C", (int)res->u.ival); + break; + case 'B': + memset(buf, '0', 34); + buf[1] = 'b'; + for(i = 0; i < 32; i++) { + if(res->u.ival & (1<<i)) + buf[33-i] = '1'; + } + buf[35] = '\0'; + Bprint(bout, "%s", buf); + break; + case 'b': + Bprint(bout, "%.2x", (int)res->u.ival&0xff); + break; + case 'X': + Bprint(bout, "%.8lux", (ulong)res->u.ival); + break; + case 'x': + Bprint(bout, "%.4lux", (ulong)res->u.ival&0xffff); + break; + case 'W': + Bprint(bout, "%.16llux", res->u.ival); + break; + case 'D': + Bprint(bout, "%d", (int)res->u.ival); + break; + case 'd': + Bprint(bout, "%d", (ushort)res->u.ival); + break; + case 'u': + Bprint(bout, "%d", (int)res->u.ival&0xffff); + break; + case 'U': + Bprint(bout, "%lud", (ulong)res->u.ival); + break; + case 'Z': + Bprint(bout, "%llud", res->u.ival); + break; + case 'V': + Bprint(bout, "%lld", res->u.ival); + break; + case 'Y': + Bprint(bout, "%.16llux", res->u.ival); + break; + case 'o': + Bprint(bout, "0%.11uo", (int)res->u.ival&0xffff); + break; + case 'O': + Bprint(bout, "0%.6uo", (int)res->u.ival); + break; + case 'q': + Bprint(bout, "0%.11o", (short)(res->u.ival&0xffff)); + break; + case 'Q': + Bprint(bout, "0%.6o", (int)res->u.ival); + break; + case 'f': + case 'F': + if(type != TFLOAT) + Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]); + else + Bprint(bout, "%g", res->u.fval); + break; + case 's': + case 'g': + case 'G': + if(type != TSTRING) + Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]); + else + Bwrite(bout, res->u.string->string, res->u.string->len); + break; + case 'R': + if(type != TSTRING) + Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]); + else + Bprint(bout, "%S", (Rune*)res->u.string->string); + break; + case 'a': + case 'A': + symoff(buf, sizeof(buf), res->u.ival, CANY); + Bprint(bout, "%s", buf); + break; + case 'I': + case 'i': + if(type != TINT) + Bprint(bout, "*%c<%s>*", res->fmt, typenames[(uchar)type]); + else { + if (symmap == nil || (*mach->das)(symmap, res->u.ival, res->fmt, buf, sizeof(buf)) < 0) + Bprint(bout, "no instruction"); + else + Bprint(bout, "%s", buf); + } + break; + } +} + +void +blprint(List *l) +{ + Store *res; + + Bprint(bout, "{"); + while(l) { + switch(l->type) { + case TINT: + res = &l->store; + if(res->fmt == 'c'){ + Bprint(bout, "\'%c\'", (int)res->u.ival); + break; + }else if(res->fmt == 'r'){ + Bprint(bout, "\'%C\'", (int)res->u.ival); + break; + } + /* fall through */ + default: + patom(l->type, &l->store); + break; + case TSTRING: + Bputc(bout, '"'); + patom(l->type, &l->store); + Bputc(bout, '"'); + break; + case TLIST: + blprint(l->store.u.l); + break; + case TCODE: + pcode(l->store.u.cc, 0); + break; + } + l = l->next; + if(l) + Bprint(bout, ", "); + } + Bprint(bout, "}"); +} + +int +comx(Node res) +{ + Lsym *sl; + Node *n, xx; + + if(res.store.fmt != 'a' && res.store.fmt != 'A') + return 0; + + if(res.store.comt == 0 || res.store.comt->base == 0) + return 0; + + sl = res.store.comt->base; + if(sl->proc) { + res.left = ZN; + res.right = ZN; + n = an(ONAME, ZN, ZN); + n->sym = sl; + n = an(OCALL, n, &res); + n->left->sym = sl; + expr(n, &xx); + return 1; + } + print("(%s)", sl->name); + return 0; +} + +void +bprint(Node *r, Node *args) +{ + int i, nas; + Node res, *av[Maxarg]; + + USED(r); + na = 0; + flatten(av, args); + nas = na; + for(i = 0; i < nas; i++) { + expr(av[i], &res); + switch(res.type) { + default: + if(comx(res)) + break; + patom(res.type, &res.store); + break; + case TCODE: + pcode(res.store.u.cc, 0); + break; + case TLIST: + blprint(res.store.u.l); + break; + } + } + if(ret == 0) + Bputc(bout, '\n'); +} + +void +printto(Node *r, Node *args) +{ + int fd; + Biobuf *b; + int i, nas; + Node res, *av[Maxarg]; + + USED(r); + na = 0; + flatten(av, args); + nas = na; + + expr(av[0], &res); + if(res.type != TSTRING) + error("printto(string, ...): need string"); + + fd = create(res.store.u.string->string, OWRITE, 0666); + if(fd < 0) + fd = open(res.store.u.string->string, OWRITE); + if(fd < 0) + error("printto: open %s: %r", res.store.u.string->string); + + b = gmalloc(sizeof(Biobuf)); + Binit(b, fd, OWRITE); + + Bflush(bout); + io[iop++] = bout; + bout = b; + + for(i = 1; i < nas; i++) { + expr(av[i], &res); + switch(res.type) { + default: + if(comx(res)) + break; + patom(res.type, &res.store); + break; + case TLIST: + blprint(res.store.u.l); + break; + } + } + if(ret == 0) + Bputc(bout, '\n'); + + Bterm(b); + close(fd); + free(b); + bout = io[--iop]; +} + +void +pcfile(Node *r, Node *args) +{ + Node res; + char *p, buf[128]; + + if(args == 0) + error("pcfile(addr): arg count"); + expr(args, &res); + if(res.type != TINT) + error("pcfile(addr): arg type"); + + r->type = TSTRING; + r->store.fmt = 's'; + if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) { + r->store.u.string = strnode("?file?"); + return; + } + p = strrchr(buf, ':'); + if(p == 0) + error("pcfile(addr): funny file %s", buf); + *p = '\0'; + r->store.u.string = strnode(buf); +} + +void +pcline(Node *r, Node *args) +{ + Node res; + char *p, buf[128]; + + if(args == 0) + error("pcline(addr): arg count"); + expr(args, &res); + if(res.type != TINT) + error("pcline(addr): arg type"); + + r->type = TINT; + r->store.fmt = 'D'; + if(fileline(res.store.u.ival, buf, sizeof(buf)) < 0) { + r->store.u.ival = 0; + return; + } + + p = strrchr(buf, ':'); + if(p == 0) + error("pcline(addr): funny file %s", buf); + r->store.u.ival = atoi(p+1); +} + +void +textfile(Node *r, Node *args) +{ + char *file; + long base; + Fhdr *fp; + Node res, *av[Maxarg]; + List *l, *l2, **tail, *list, *tl; + + na = 0; + flatten(av, args); + + if(na != 0) { + expr(av[0], &res); + if(res.type != TLIST) + error("textfile(list): textfile needs a list"); + if(listlen(res.store.u.l) != 2) + error("textfile(list): list must have 2 entries"); + + l = res.store.u.l; + if(l->type != TSTRING) + error("textfile name must be a string"); + file = l->store.u.string->string; + + l = l->next; + if(l->type != TINT) + error("textfile base must be an int"); + base = l->store.u.ival; + + if((fp = crackhdr(file, OREAD)) == nil) + error("crackhdr %s: %r", file); + Bflush(bout); + fp->base = base; + fprint(2, "%s: %s %s %s\n", file, fp->aname, fp->mname, fp->fname); + if(mapfile(fp, base, symmap, nil) < 0) + fprint(2, "mapping %s: %r\n", file); + if(corhdr){ + unmapfile(corhdr, cormap); + mapfile(fp, base, cormap, nil); + free(correg); + mapfile(corhdr, 0, cormap, &correg); + } + if(syminit(fp) < 0) + fprint(2, "syminit %s: %r\n", file); + else + addvarsym(fp); + return; + } + + l2 = nil; + tail = &l2; + for(fp=fhdrlist; fp; fp=fp->next){ + if(fp->ftype == FCORE) + continue; + tl = al(TLIST); + *tail = tl; + tail = &tl->next; + + list = al(TSTRING); + tl->store.u.l = list; + list->store.u.string = strnode(fp->filename); + list->store.fmt = 's'; + list->next = al(TINT); + list = list->next; + list->store.fmt = 'X'; + list->store.u.ival = fp->base; + } + + r->type = TLIST; + r->store.u.l = l2; +} + +void +deltextfile(Node *r, Node *args) +{ + int did; + char *file; + Fhdr *fp, *fpnext; + Node res, *av[Maxarg]; + + na = 0; + flatten(av, args); + + if(na != 1) + error("deltextfile(string): arg count"); + + expr(av[0], &res); + if(res.type != TSTRING) + error("deltextfile(string): arg type"); + file = res.store.u.string->string; + + did = 0; + for(fp=fhdrlist; fp; fp=fpnext){ + fpnext = fp->next; + if(fp->ftype == FCORE) + continue; + if(strcmp(file, fp->filename) == 0){ + did = 1; + if(fp == symhdr) + error("cannot remove symbols from main text file"); + unmapfile(fp, symmap); + uncrackhdr(fp); + } + } + + delvarsym(file); + if(!did) + error("symbol file %s not open", file); +} + |