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