mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-15 11:20:03 +00:00
447 lines
6.8 KiB
C
447 lines
6.8 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[] =
|
||
|
{
|
||
|
[OMUL] "*",
|
||
|
[ODIV] "/",
|
||
|
[OMOD] "%",
|
||
|
[OADD] "+",
|
||
|
[OSUB] "-",
|
||
|
[ORSH] ">>",
|
||
|
[OLSH] "<<",
|
||
|
[OLT] "<",
|
||
|
[OGT] ">",
|
||
|
[OLEQ] "<=",
|
||
|
[OGEQ] ">=",
|
||
|
[OEQ] "==",
|
||
|
[ONEQ] "!=",
|
||
|
[OLAND] "&",
|
||
|
[OXOR] "^",
|
||
|
[OLOR] "|",
|
||
|
[OCAND] "&&",
|
||
|
[OCOR] "||",
|
||
|
[OASGN] " = ",
|
||
|
};
|
||
|
|
||
|
static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
||
|
char *typenames[] =
|
||
|
{
|
||
|
[TINT] "integer",
|
||
|
[TFLOAT] "float",
|
||
|
[TSTRING] "string",
|
||
|
[TLIST] "list",
|
||
|
[TCODE] "code",
|
||
|
};
|
||
|
|
||
|
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, '"');
|
||
|
}
|