xref: /plan9/sys/src/cmd/acid/print.c (revision 4de34a7edde43207e841ec91ecd12e6cf5f5ebe7)
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