| #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, '"'); |
| } |