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