plan9port/src/cmd/acid/print.c
rsc 4f2ac1b76b Working on better handling of multithreading in general
and core dumps in particular.  See notes:

new types: register is something that when dereferenced gives you
	the registers.  the Ureg is no longer mapped at 0.
	refconst is something that gives a constant when dereferenced.

new builtin register("AX") creates register values
new builtin refconst(0x123) creates refconst values

new builtin var("foo") is equivalent to the variable foo
	(it returns foo but can also be used as the lhs of an assignment).

new acid function getregs() returns a list of the current values of registers.
new acid function setregs() sets the current registers to those values.
	note that getregs and setregs operate on register locations, not the
		register values themselves.
new acid function resetregs() sets registers to register("AX"), etc.
new acid function clearregs() sets all registers to constant -1.
the default register settings are as in resetregs(), not small numbers.

new acid variables coretext, pids, systype, corefile, cmdline.

new behavior: local variable lookup, stk, etc., use the acid values of registers
	(*PC, *SP, and so on), so the thread support code can change the context
	completely.

unary + is applicable to more data types and prints more often.
2005-01-23 22:48:19 +00:00

458 lines
7 KiB
C

#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include <mach.h>
#define Extern extern
#include "acid.h"
static char *binop[NUMO];
static void
initbinop(void)
{
binop[OMUL]= "*";
binop[ODIV]= "/";
binop[OMOD]= "%";
binop[OADD]= "+";
binop[OSUB]= "-";
binop[ORSH]= ">>";
binop[OLSH]= "<<";
binop[OLT]= "<";
binop[OGT]= ">";
binop[OLEQ]= "<=";
binop[OGEQ]= ">=";
binop[OEQ]= "==";
binop[ONEQ]= "!=";
binop[OLAND]= "&";
binop[OXOR]= "^";
binop[OLOR]= "|";
binop[OCAND]= "&&";
binop[OCOR]= "||";
binop[OASGN]= " = ";
}
static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
char *typenames[] = {
"integer",
"float",
"string",
"list",
"code",
};
void
initprint(void)
{
initbinop();
}
int
cmp(const void *va, const void *vb)
{
char **a = (char**)va;
char **b = (char**)vb;
return strcmp(*a, *b);
}
void
fundefs(void)
{
Lsym *l;
char **vec;
int i, j, n, max, col, f, g, s;
max = 0;
f = 0;
g = 100;
vec = malloc(sizeof(char*)*g);
if(vec == 0)
fatal("out of memory");
for(i = 0; i < Hashsize; i++) {
for(l = hash[i]; l; l = l->hash) {
if(l->proc == 0 && l->builtin == 0)
continue;
n = strlen(l->name);
if(n > max)
max = n;
if(f >= g) {
g *= 2;
vec = realloc(vec, sizeof(char*)*g);
if(vec == 0)
fatal("out of memory");
}
vec[f++] = l->name;
}
}
qsort(vec, f, sizeof(char*), cmp);
max++;
col = 60/max;
s = (f+col-1)/col;
for(i = 0; i < s; i++) {
for(j = i; j < f; j += s)
Bprint(bout, "%-*s", max, vec[j]);
Bprint(bout, "\n");
}
}
void
whatis(Lsym *l)
{
int t;
int def;
Type *ti;
if(l == 0) {
fundefs();
return;
}
def = 0;
if(l->v->set) {
t = l->v->type;
Bprint(bout, "%s variable", typenames[t]);
if(t == TINT || t == TFLOAT)
Bprint(bout, " format %c", l->v->store.fmt);
if(l->v->store.comt)
Bprint(bout, " complex %s",
l->v->store.comt->base->name);
Bputc(bout, '\n');
def = 1;
}
if(l->lt) {
Bprint(bout, "complex %s {\n", l->name);
for(ti = l->lt; ti; ti = ti->next) {
if(ti->type) {
if(ti->fmt == 'a') {
Bprint(bout, "\t%s %d %s;\n",
ti->type->name, ti->offset,
ti->tag->name);
}
else {
Bprint(bout, "\t'%c' %s %d %s;\n",
ti->fmt, ti->type->name, ti->offset,
ti->tag->name);
}
}
else
Bprint(bout, "\t'%c' %d %s;\n",
ti->fmt, ti->offset, ti->tag->name);
}
Bprint(bout, "};\n");
def = 1;
}
if(l->proc) {
Bprint(bout, "defn %s(", l->name);
pexpr(l->proc->left);
Bprint(bout, ") {\n");
pcode(l->proc->right, 1);
Bprint(bout, "}\n");
def = 1;
}
if(l->builtin) {
Bprint(bout, "builtin function\n");
def = 1;
}
if(def == 0)
Bprint(bout, "%s is undefined\n", l->name);
}
void
slist(Node *n, int d)
{
if(n == 0)
return;
if(n->op == OLIST)
Bprint(bout, "%.*s{\n", d-1, tabs);
pcode(n, d);
if(n->op == OLIST)
Bprint(bout, "%.*s}\n", d-1, tabs);
}
void
pcode(Node *n, int d)
{
Node *r, *l;
if(n == 0)
return;
r = n->right;
l = n->left;
switch(n->op) {
default:
Bprint(bout, "%.*s", d, tabs);
pexpr(n);
Bprint(bout, ";\n");
break;
case OLIST:
pcode(n->left, d);
pcode(n->right, d);
break;
case OLOCAL:
Bprint(bout, "%.*slocal", d, tabs);
while(l) {
Bprint(bout, " %s", l->sym->name);
l = l->left;
if(l == 0)
Bprint(bout, ";\n");
else
Bprint(bout, ",");
}
break;
case OCOMPLEX:
Bprint(bout, "%.*scomplex %s %s;\n", d, tabs, n->sym->name, l->sym->name);
break;
case OIF:
Bprint(bout, "%.*sif ", d, tabs);
pexpr(l);
d++;
Bprint(bout, " then\n");
if(r && r->op == OELSE) {
slist(r->left, d);
Bprint(bout, "%.*selse\n", d-1, tabs);
slist(r->right, d);
}
else
slist(r, d);
break;
case OWHILE:
Bprint(bout, "%.*swhile ", d, tabs);
pexpr(l);
d++;
Bprint(bout, " do\n");
slist(r, d);
break;
case ORET:
Bprint(bout, "%.*sreturn ", d, tabs);
pexpr(l);
Bprint(bout, ";\n");
break;
case ODO:
Bprint(bout, "%.*sloop ", d, tabs);
pexpr(l->left);
Bprint(bout, ", ");
pexpr(l->right);
Bprint(bout, " do\n");
slist(r, d+1);
}
}
void
pexpr(Node *n)
{
Node *r, *l;
if(n == 0)
return;
r = n->right;
l = n->left;
switch(n->op) {
case ONAME:
Bprint(bout, "%s", n->sym->name);
break;
case OCONST:
switch(n->type) {
case TINT:
Bprint(bout, "%d", (int)n->store.u.ival);
break;
case TFLOAT:
Bprint(bout, "%g", n->store.u.fval);
break;
case TSTRING:
pstr(n->store.u.string);
break;
case TLIST:
break;
}
break;
case OMUL:
case ODIV:
case OMOD:
case OADD:
case OSUB:
case ORSH:
case OLSH:
case OLT:
case OGT:
case OLEQ:
case OGEQ:
case OEQ:
case ONEQ:
case OLAND:
case OXOR:
case OLOR:
case OCAND:
case OCOR:
Bputc(bout, '(');
pexpr(l);
Bprint(bout, binop[(uchar)n->op]);
pexpr(r);
Bputc(bout, ')');
break;
case OASGN:
pexpr(l);
Bprint(bout, binop[(uchar)n->op]);
pexpr(r);
break;
case OINDM:
Bprint(bout, "*");
pexpr(l);
break;
case OEDEC:
Bprint(bout, "--");
pexpr(l);
break;
case OEINC:
Bprint(bout, "++");
pexpr(l);
break;
case OPINC:
pexpr(l);
Bprint(bout, "++");
break;
case OPDEC:
pexpr(l);
Bprint(bout, "--");
break;
case ONOT:
Bprint(bout, "!");
pexpr(l);
break;
case OLIST:
pexpr(l);
if(r) {
Bprint(bout, ",");
pexpr(r);
}
break;
case OCALL:
pexpr(l);
Bprint(bout, "(");
pexpr(r);
Bprint(bout, ")");
break;
case OCTRUCT:
Bprint(bout, "{");
pexpr(l);
Bprint(bout, "}");
break;
case OHEAD:
Bprint(bout, "head ");
pexpr(l);
break;
case OTAIL:
Bprint(bout, "tail ");
pexpr(l);
break;
case OAPPEND:
Bprint(bout, "append ");
pexpr(l);
Bprint(bout, ",");
pexpr(r);
break;
case ODELETE:
Bprint(bout, "delete ");
pexpr(l);
Bprint(bout, ",");
pexpr(r);
break;
case ORET:
Bprint(bout, "return ");
pexpr(l);
break;
case OINDEX:
pexpr(l);
Bprint(bout, "[");
pexpr(r);
Bprint(bout, "]");
break;
case OINDC:
Bprint(bout, "@");
pexpr(l);
break;
case ODOT:
pexpr(l);
Bprint(bout, ".%s", n->sym->name);
break;
case OFRAME:
Bprint(bout, "%s:%s", n->sym->name, l->sym->name);
break;
case OCAST:
Bprint(bout, "(%s)", n->sym->name);
pexpr(l);
break;
case OFMT:
pexpr(l);
Bprint(bout, "\\%c", (int)r->store.u.ival);
break;
case OEVAL:
Bprint(bout, "eval ");
pexpr(l);
break;
case OWHAT:
Bprint(bout, "whatis");
if(n->sym)
Bprint(bout, " %s", n->sym->name);
break;
case OUPLUS:
Bprint(bout, "+");
pexpr(l);
break;
}
}
void
pstr(String *s)
{
int i, c;
Bputc(bout, '"');
for(i = 0; i < s->len; i++) {
c = s->string[i];
switch(c) {
case '\0':
c = '0';
break;
case '\n':
c = 'n';
break;
case '\r':
c = 'r';
break;
case '\t':
c = 't';
break;
case '\b':
c = 'b';
break;
case '\f':
c = 'f';
break;
case '\a':
c = 'a';
break;
case '\v':
c = 'v';
break;
case '\\':
c = '\\';
break;
case '"':
c = '"';
break;
default:
Bputc(bout, c);
continue;
}
Bputc(bout, '\\');
Bputc(bout, c);
}
Bputc(bout, '"');
}