2004-04-19 19:32:07 +00:00
|
|
|
#include <u.h>
|
|
|
|
#include <libc.h>
|
|
|
|
#include <bio.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <mach.h>
|
|
|
|
#define Extern extern
|
|
|
|
#include "acid.h"
|
|
|
|
|
2004-04-20 01:42:20 +00:00
|
|
|
static char *binop[NUMO];
|
|
|
|
|
|
|
|
static void
|
|
|
|
initbinop(void)
|
2004-04-19 19:32:07 +00:00
|
|
|
{
|
2004-04-20 01:42:20 +00:00
|
|
|
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]= " = ";
|
2004-04-19 19:32:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
2004-04-20 01:42:20 +00:00
|
|
|
char *typenames[] = {
|
|
|
|
"integer",
|
|
|
|
"float",
|
|
|
|
"string",
|
|
|
|
"list",
|
|
|
|
"code",
|
2004-04-19 19:32:07 +00:00
|
|
|
};
|
|
|
|
|
2004-04-20 01:42:20 +00:00
|
|
|
void
|
|
|
|
initprint(void)
|
|
|
|
{
|
|
|
|
initbinop();
|
|
|
|
}
|
|
|
|
|
2004-04-19 19:32:07 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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, '"');
|
|
|
|
}
|