aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/acid/print.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/acid/print.c')
-rw-r--r--src/cmd/acid/print.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/src/cmd/acid/print.c b/src/cmd/acid/print.c
new file mode 100644
index 00000000..00d7b737
--- /dev/null
+++ b/src/cmd/acid/print.c
@@ -0,0 +1,446 @@
+#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, '"');
+}