1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <ctype.h>
5 #include <mach.h>
6 #define Extern extern
7 #include "acid.h"
8
9 static char *binop[] =
10 {
11 [OMUL] "*",
12 [ODIV] "/",
13 [OMOD] "%",
14 [OADD] "+",
15 [OSUB] "-",
16 [ORSH] ">>",
17 [OLSH] "<<",
18 [OLT] "<",
19 [OGT] ">",
20 [OLEQ] "<=",
21 [OGEQ] ">=",
22 [OEQ] "==",
23 [ONEQ] "!=",
24 [OLAND] "&",
25 [OXOR] "^",
26 [OLOR] "|",
27 [OCAND] "&&",
28 [OCOR] "||",
29 [OASGN] " = ",
30 };
31
32 static char *tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
33 char *typenames[] =
34 {
35 [TINT] "integer",
36 [TFLOAT] "float",
37 [TSTRING] "string",
38 [TLIST] "list",
39 [TCODE] "code",
40 };
41
42 int
cmp(void * va,void * vb)43 cmp(void *va, void *vb)
44 {
45 char **a = va;
46 char **b = vb;
47
48 return strcmp(*a, *b);
49 }
50
51 void
fundefs(void)52 fundefs(void)
53 {
54 Lsym *l;
55 char **vec;
56 int i, j, n, max, col, f, g, s;
57
58 max = 0;
59 f = 0;
60 g = 100;
61 vec = malloc(sizeof(char*)*g);
62 if(vec == 0)
63 fatal("out of memory");
64
65 for(i = 0; i < Hashsize; i++) {
66 for(l = hash[i]; l; l = l->hash) {
67 if(l->proc == 0 && l->builtin == 0)
68 continue;
69 n = strlen(l->name);
70 if(n > max)
71 max = n;
72 if(f >= g) {
73 g *= 2;
74 vec = realloc(vec, sizeof(char*)*g);
75 if(vec == 0)
76 fatal("out of memory");
77 }
78 vec[f++] = l->name;
79 }
80 }
81 qsort(vec, f, sizeof(char*), cmp);
82 max++;
83 col = 60/max;
84 s = (f+col-1)/col;
85
86 for(i = 0; i < s; i++) {
87 for(j = i; j < f; j += s)
88 Bprint(bout, "%-*s", max, vec[j]);
89 Bprint(bout, "\n");
90 }
91 }
92
93 void
whatis(Lsym * l)94 whatis(Lsym *l)
95 {
96 int t;
97 int def;
98 Type *ti;
99
100 if(l == 0) {
101 fundefs();
102 return;
103 }
104
105 def = 0;
106 if(l->v->set) {
107 t = l->v->type;
108 Bprint(bout, "%s variable", typenames[t]);
109 if(t == TINT || t == TFLOAT)
110 Bprint(bout, " format %c", l->v->fmt);
111 if(l->v->comt)
112 Bprint(bout, " complex %s", l->v->comt->base->name);
113 Bputc(bout, '\n');
114 def = 1;
115 }
116 if(l->lt) {
117 Bprint(bout, "complex %s {\n", l->name);
118 for(ti = l->lt; ti; ti = ti->next) {
119 if(ti->type) {
120 if(ti->fmt == 'a') {
121 Bprint(bout, "\t%s %d %s;\n",
122 ti->type->name, ti->offset,
123 ti->tag->name);
124 }
125 else {
126 Bprint(bout, "\t'%c' %s %d %s;\n",
127 ti->fmt, ti->type->name, ti->offset,
128 ti->tag->name);
129 }
130 }
131 else
132 Bprint(bout, "\t'%c' %d %s;\n",
133 ti->fmt, ti->offset, ti->tag->name);
134 }
135 Bprint(bout, "};\n");
136 def = 1;
137 }
138 if(l->proc) {
139 Bprint(bout, "defn %s(", l->name);
140 pexpr(l->proc->left);
141 Bprint(bout, ") {\n");
142 pcode(l->proc->right, 1);
143 Bprint(bout, "}\n");
144 def = 1;
145 }
146 if(l->builtin) {
147 Bprint(bout, "builtin function\n");
148 def = 1;
149 }
150 if(def == 0)
151 Bprint(bout, "%s is undefined\n", l->name);
152 }
153
154 void
slist(Node * n,int d)155 slist(Node *n, int d)
156 {
157 if(n == 0)
158 return;
159 if(n->op == OLIST)
160 Bprint(bout, "%.*s{\n", d-1, tabs);
161 pcode(n, d);
162 if(n->op == OLIST)
163 Bprint(bout, "%.*s}\n", d-1, tabs);
164 }
165
166 void
pcode(Node * n,int d)167 pcode(Node *n, int d)
168 {
169 Node *r, *l;
170
171 if(n == 0)
172 return;
173
174 r = n->right;
175 l = n->left;
176
177 switch(n->op) {
178 default:
179 Bprint(bout, "%.*s", d, tabs);
180 pexpr(n);
181 Bprint(bout, ";\n");
182 break;
183 case OLIST:
184 pcode(n->left, d);
185 pcode(n->right, d);
186 break;
187 case OLOCAL:
188 Bprint(bout, "%.*slocal", d, tabs);
189 while(l) {
190 Bprint(bout, " %s", l->sym->name);
191 l = l->left;
192 if(l == 0)
193 Bprint(bout, ";\n");
194 else
195 Bprint(bout, ",");
196 }
197 break;
198 case OCOMPLEX:
199 Bprint(bout, "%.*scomplex %s %s;\n", d, tabs, n->sym->name, l->sym->name);
200 break;
201 case OIF:
202 Bprint(bout, "%.*sif ", d, tabs);
203 pexpr(l);
204 d++;
205 Bprint(bout, " then\n");
206 if(r && r->op == OELSE) {
207 slist(r->left, d);
208 Bprint(bout, "%.*selse\n", d-1, tabs);
209 slist(r->right, d);
210 }
211 else
212 slist(r, d);
213 break;
214 case OWHILE:
215 Bprint(bout, "%.*swhile ", d, tabs);
216 pexpr(l);
217 d++;
218 Bprint(bout, " do\n");
219 slist(r, d);
220 break;
221 case ORET:
222 Bprint(bout, "%.*sreturn ", d, tabs);
223 pexpr(l);
224 Bprint(bout, ";\n");
225 break;
226 case ODO:
227 Bprint(bout, "%.*sloop ", d, tabs);
228 pexpr(l->left);
229 Bprint(bout, ", ");
230 pexpr(l->right);
231 Bprint(bout, " do\n");
232 slist(r, d+1);
233 }
234 }
235
236 void
pexpr(Node * n)237 pexpr(Node *n)
238 {
239 Node *r, *l;
240
241 if(n == 0)
242 return;
243
244 r = n->right;
245 l = n->left;
246
247 switch(n->op) {
248 case ONAME:
249 Bprint(bout, "%s", n->sym->name);
250 break;
251 case OCONST:
252 switch(n->type) {
253 case TINT:
254 Bprint(bout, "%lld", n->ival);
255 break;
256 case TFLOAT:
257 Bprint(bout, "%g", n->fval);
258 break;
259 case TSTRING:
260 pstr(n->string);
261 break;
262 case TLIST:
263 break;
264 }
265 break;
266 case OMUL:
267 case ODIV:
268 case OMOD:
269 case OADD:
270 case OSUB:
271 case ORSH:
272 case OLSH:
273 case OLT:
274 case OGT:
275 case OLEQ:
276 case OGEQ:
277 case OEQ:
278 case ONEQ:
279 case OLAND:
280 case OXOR:
281 case OLOR:
282 case OCAND:
283 case OCOR:
284 Bputc(bout, '(');
285 pexpr(l);
286 Bprint(bout, binop[n->op]);
287 pexpr(r);
288 Bputc(bout, ')');
289 break;
290 case OASGN:
291 pexpr(l);
292 Bprint(bout, binop[n->op]);
293 pexpr(r);
294 break;
295 case OINDM:
296 Bprint(bout, "*");
297 pexpr(l);
298 break;
299 case OEDEC:
300 Bprint(bout, "--");
301 pexpr(l);
302 break;
303 case OEINC:
304 Bprint(bout, "++");
305 pexpr(l);
306 break;
307 case OPINC:
308 pexpr(l);
309 Bprint(bout, "++");
310 break;
311 case OPDEC:
312 pexpr(l);
313 Bprint(bout, "--");
314 break;
315 case ONOT:
316 Bprint(bout, "!");
317 pexpr(l);
318 break;
319 case OLIST:
320 pexpr(l);
321 if(r) {
322 Bprint(bout, ",");
323 pexpr(r);
324 }
325 break;
326 case OCALL:
327 pexpr(l);
328 Bprint(bout, "(");
329 pexpr(r);
330 Bprint(bout, ")");
331 break;
332 case OCTRUCT:
333 Bprint(bout, "{");
334 pexpr(l);
335 Bprint(bout, "}");
336 break;
337 case OHEAD:
338 Bprint(bout, "head ");
339 pexpr(l);
340 break;
341 case OTAIL:
342 Bprint(bout, "tail ");
343 pexpr(l);
344 break;
345 case OAPPEND:
346 Bprint(bout, "append ");
347 pexpr(l);
348 Bprint(bout, ",");
349 pexpr(r);
350 break;
351 case ODELETE:
352 Bprint(bout, "delete ");
353 pexpr(l);
354 Bprint(bout, ",");
355 pexpr(r);
356 break;
357 case ORET:
358 Bprint(bout, "return ");
359 pexpr(l);
360 break;
361 case OINDEX:
362 pexpr(l);
363 Bprint(bout, "[");
364 pexpr(r);
365 Bprint(bout, "]");
366 break;
367 case OINDC:
368 Bprint(bout, "@");
369 pexpr(l);
370 break;
371 case ODOT:
372 pexpr(l);
373 Bprint(bout, ".%s", n->sym->name);
374 break;
375 case OFRAME:
376 Bprint(bout, "%s:%s", n->sym->name, l->sym->name);
377 break;
378 case OCAST:
379 Bprint(bout, "(%s)", n->sym->name);
380 pexpr(l);
381 break;
382 case OFMT:
383 pexpr(l);
384 Bprint(bout, "\\%c", (int)r->ival);
385 break;
386 case OEVAL:
387 Bprint(bout, "eval ");
388 pexpr(l);
389 break;
390 case OWHAT:
391 Bprint(bout, "whatis");
392 if(n->sym)
393 Bprint(bout, " %s", n->sym->name);
394 break;
395 }
396 }
397
398 void
pstr(String * s)399 pstr(String *s)
400 {
401 int i, c;
402
403 Bputc(bout, '"');
404 for(i = 0; i < s->len; i++) {
405 c = s->string[i];
406 switch(c) {
407 case '\0':
408 c = '0';
409 break;
410 case '\n':
411 c = 'n';
412 break;
413 case '\r':
414 c = 'r';
415 break;
416 case '\t':
417 c = 't';
418 break;
419 case '\b':
420 c = 'b';
421 break;
422 case '\f':
423 c = 'f';
424 break;
425 case '\a':
426 c = 'a';
427 break;
428 case '\v':
429 c = 'v';
430 break;
431 case '\\':
432 c = '\\';
433 break;
434 case '"':
435 c = '"';
436 break;
437 default:
438 Bputc(bout, c);
439 continue;
440 }
441 Bputc(bout, '\\');
442 Bputc(bout, c);
443 }
444 Bputc(bout, '"');
445 }
446