BSD 4_3_Tahoe release
[unix-history] / usr / src / ucb / dbx / tree.c
CommitLineData
2a24676e
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
b3355c51 6
2a24676e 7#ifndef lint
ca67e7b4 8static char sccsid[] = "@(#)tree.c 5.3 (Berkeley) 1/12/88";
2a24676e 9#endif not lint
0022c355 10
d244f11c 11static char rcsid[] = "$Header: tree.c,v 1.3 87/07/08 21:38:59 donn Exp $";
b3355c51
ML
12
13/*
14 * Parse tree management.
15 */
16
17#include "defs.h"
18#include "tree.h"
19#include "operators.h"
0022c355 20#include "debug.h"
b3355c51
ML
21#include "eval.h"
22#include "events.h"
23#include "symbols.h"
24#include "scanner.h"
25#include "source.h"
26#include "object.h"
27#include "mappings.h"
28#include "process.h"
29#include "machine.h"
30
31#ifndef public
32#include "lists.h"
33
34typedef struct Node *Node;
35typedef Node Command;
36typedef List Cmdlist;
37
38#include "operators.h"
39#include "symbols.h"
40#include "events.h"
41
42#define MAXNARGS 5
43
44struct Node {
45 Operator op;
46 Symbol nodetype;
47 union treevalue {
48 Symbol sym;
49 Name name;
50 long lcon;
51 double fcon;
52 String scon;
53 Node arg[MAXNARGS];
54 struct {
55 Node cond;
56 Cmdlist actions;
57 } event;
58 struct {
59 Boolean inst;
60 Event event;
61 Cmdlist actions;
62 } trace;
63 struct {
64 Boolean source;
65 Boolean skipcalls;
66 } step;
67 struct {
68 String mode;
69 Node beginaddr;
70 Node endaddr;
71 Integer count;
72 } examine;
73 } value;
74};
75
76#define evalcmd(cmd) eval(cmd)
77#define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
78
79#endif
80
81typedef char *Arglist;
82
83#define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
84
85/*
86 * Build a tree.
87 */
88
89/* VARARGS1 */
90public Node build(op, args)
91Operator op;
92{
93 register Node p, q;
94 register Arglist ap;
95 Integer i;
96
97 p = new(Node);
98 p->op = op;
99 p->nodetype = nil;
100 ap = (Arglist) &args;
101 switch (op) {
102 case O_NAME:
103 p->value.name = nextarg(Name);
104 break;
105
106 case O_SYM:
107 case O_PRINTCALL:
108 case O_PRINTRTN:
109 case O_PROCRTN:
110 p->value.sym = nextarg(Symbol);
111 break;
112
9eb865a2 113 case O_DEBUG:
b3355c51 114 case O_LCON:
0022c355 115 case O_CCON:
b3eda022 116 case O_CONT:
0022c355
ML
117 case O_CATCH:
118 case O_IGNORE:
b3355c51
ML
119 case O_TRACEOFF:
120 p->value.lcon = nextarg(long);
121 break;
122
123 case O_FCON:
124 p->value.fcon = nextarg(double);
125 break;
126
127 case O_SCON:
128 case O_CHFILE:
129 case O_EDIT:
130 case O_SOURCE:
131 p->value.scon = nextarg(String);
132 break;
133
134 case O_RVAL:
0022c355
ML
135 case O_INDIR:
136 p->value.arg[0] = nextarg(Node);
b3355c51
ML
137 break;
138
0022c355 139 case O_CALL:
b3355c51 140 q = nextarg(Node);
0022c355
ML
141 if (q->op == O_SYM and
142 (q->value.sym->class == TYPE or q->value.sym->class == TAG)
143 ) {
144 p->op = O_TYPERENAME;
145 p->value.arg[0] = nextarg(Node);
146 p->value.arg[1] = q;
147 q = p->value.arg[0];
148 if (q->value.arg[1] != nil) {
149 error("too many arguments to type rename");
150 }
b3355c51 151 p->value.arg[0] = q->value.arg[0];
b3355c51
ML
152 } else {
153 p->value.arg[0] = q;
0022c355 154 p->value.arg[1] = nextarg(Node);
b3355c51
ML
155 }
156 break;
157
158 case O_ADDEVENT:
159 case O_ONCE:
160 case O_IF:
161 p->value.event.cond = nextarg(Node);
162 p->value.event.actions = nextarg(Cmdlist);
163 break;
164
165 case O_TRACEON:
166 p->value.trace.inst = nextarg(Boolean);
167 p->value.trace.event = nil;
168 p->value.trace.actions = nextarg(Cmdlist);
169 break;
170
171 case O_STEP:
172 p->value.step.source = nextarg(Boolean);
173 p->value.step.skipcalls = nextarg(Boolean);
174 break;
175
176 case O_EXAMINE:
177 p->value.examine.mode = nextarg(String);
178 p->value.examine.beginaddr = nextarg(Node);
179 p->value.examine.endaddr = nextarg(Node);
180 p->value.examine.count = nextarg(Integer);
181 break;
182
183 default:
184 for (i = 0; i < nargs(op); i++) {
185 p->value.arg[i] = nextarg(Node);
186 }
187 break;
188 }
189 check(p);
190 assigntypes(p);
0022c355
ML
191 if (tracetree) {
192 printf("built %s node 0x%x with arg[0] 0x%x arg[1] 0x%x\n",
193 opname(p->op), p, p->value.arg[0], p->value.arg[1]);
194 fflush(stdout);
9eb865a2 195 }
b3355c51
ML
196 return p;
197}
198
199/*
0022c355
ML
200 * Strip away indirection from a node, thus returning a node for
201 * interpreting the expression as an lvalue.
b3355c51
ML
202 */
203
0022c355
ML
204public Node unrval (exp)
205Node exp;
b3355c51 206{
0022c355
ML
207 Node p;
208 Symbol t;
209
210 if (exp->op == O_RVAL) {
211 p = exp->value.arg[0];
212 dispose(exp);
213 } else if (exp->op == O_INDIR) {
214 p = exp->value.arg[0];
215 if (p->op == O_RVAL) {
216 p->op = O_INDIR;
217 p->nodetype = exp->nodetype;
218 }
219 dispose(exp);
220 } else {
221 p = exp;
222 }
223 return p;
224}
b3355c51 225
0022c355
ML
226/*
227 * Create a node for renaming a node to a pointer type.
228 */
229
230public Node renameptr (p, t)
231Node p;
232Node t;
233{
234 t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil);
235 p = build(O_TYPERENAME, p, t);
b3355c51
ML
236}
237
238/*
239 * Return the tree for a unary ampersand operator.
240 */
241
242public Node amper(p)
243Node p;
244{
245 Node r;
246
247 checkref(p);
248 switch (p->op) {
249 case O_RVAL:
0022c355 250 case O_INDIR:
b3355c51 251 r = p->value.arg[0];
0022c355
ML
252 r->nodetype = t_addr;
253 dispose(p);
b3355c51
ML
254 break;
255
0022c355
ML
256 case O_TYPERENAME:
257 r = p;
258 r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil);
d244f11c 259 r->nodetype->language = p->nodetype->language;
b3355c51
ML
260 break;
261
262 case O_SYM:
263 if (isblock(p->value.sym)) {
264 r = build(O_LCON, codeloc(p->value.sym));
265 } else {
266 r = build(O_LCON, address(p->value.sym, nil));
267 }
0022c355
ML
268 r->nodetype = t_addr;
269 dispose(p);
b3355c51
ML
270 break;
271
272 case O_DOT:
273 r = p;
0022c355 274 r->nodetype = t_addr;
b3355c51
ML
275 break;
276
277 default:
278 beginerrmsg();
0022c355 279 fprintf(stderr, "expected variable, found \"");
b3355c51 280 prtree(stderr, p);
0022c355 281 fprintf(stderr, "\"");
b3355c51
ML
282 tfree(p);
283 enderrmsg();
284 /* NOTREACHED */
285 }
b3355c51
ML
286 return r;
287}
288
289/*
290 * Create a "concrete" version of a node.
291 * This is necessary when the type of the node contains
292 * an unresolved type reference.
293 */
294
295public Node concrete(p)
296Node p;
297{
298 findtype(p->nodetype);
299 return build(O_INDIR, p);
300}
301
0022c355
ML
302/*
303 * Create a command list from a single command.
304 */
305
306public Cmdlist buildcmdlist(cmd)
307Command cmd;
308{
309 Cmdlist cmdlist;
310
311 cmdlist = list_alloc();
312 cmdlist_append(cmd, cmdlist);
313 return cmdlist;
314}
315
b3355c51
ML
316/*
317 * Print out a command.
318 */
319
320public printcmd(f, cmd)
321File f;
322Command cmd;
323{
324 register Integer i;
325 register Command c;
326 register Node p;
327
328 switch (cmd->op) {
329 case O_PRINTIFCHANGED:
330 case O_PRINTSRCPOS:
331 case O_STOPIFCHANGED:
332 case O_TRACEON:
333 break;
334
335 case O_STEP:
336 if (cmd->value.step.skipcalls) {
337 fprintf(f, "next");
338 } else {
339 fprintf(f, "step");
340 }
341 if (not cmd->value.step.source) {
342 fprintf(f, "i");
343 }
344 break;
345
346 default:
347 fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
348 if (nargs(cmd->op) != 0) {
349 fprintf(f, " ");
350 }
351 break;
352 }
353 switch (cmd->op) {
354 case O_PRINTCALL:
355 case O_PRINTRTN:
356 case O_PROCRTN:
357 fprintf(f, "%s", symname(cmd->value.sym));
358 break;
359
360 case O_PRINTSRCPOS:
361 p = cmd->value.arg[0];
362 if (p != nil and p->op != O_QLINE) {
363 printf("trace ");
364 prtree(f, p);
365 }
366 break;
367
368 case O_CHFILE:
369 case O_EDIT:
370 case O_SOURCE:
371 fprintf(f, "%s", cmd->value.scon);
372 break;
373
0022c355
ML
374 case O_CATCH:
375 case O_IGNORE:
b3355c51
ML
376 case O_TRACEOFF:
377 fprintf(f, "%d", cmd->value.lcon);
378 break;
379
380 case O_ADDEVENT:
381 case O_ONCE:
382 case O_IF:
383 fprintf(f, " ");
384 prtree(f, cmd->value.event.cond);
385 fprintf(f, " { ");
386 foreach (Command, c, cmd->value.event.actions)
387 printcmd(f, c);
388 if (not list_islast()) {
389 fprintf(f, ";");
390 }
391 endfor
b9ae3d87 392 fprintf(f, "%s }", opinfo[ord(cmd->op)].opstring);
b3355c51
ML
393 break;
394
395 case O_TRACEON:
396 print_tracestop(f, cmd);
397 break;
398
399 case O_EXAMINE:
400 prtree(f, cmd->value.examine.beginaddr);
401 if (cmd->value.examine.endaddr != nil) {
402 fprintf(f, ",");
403 prtree(f, cmd->value.examine.endaddr);
404 }
405 fprintf(f, "/");
406 if (cmd->value.examine.count > 1) {
407 fprintf(f, "%d", cmd->value.examine.count);
408 }
409 fprintf("%s", cmd->value.examine.mode);
410 break;
411
412 default:
413 if (nargs(cmd->op) != 0) {
414 i = 0;
415 for (;;) {
416 prtree(f, cmd->value.arg[i]);
417 ++i;
418 if (i >= nargs(cmd->op)) break;
419 fprintf(f, " ");
420 }
421 }
422 break;
423 }
424}
425
426/*
427 * Print out a trace/stop command name.
428 */
429
12e1c9d1
ML
430#define fprintI(f, b) { if (b) fprintf(f, "i"); }
431
b3355c51
ML
432private print_tracestop(f, cmd)
433File f;
434Command cmd;
435{
436 register Command c, ifcmd, stopcmd;
437 Boolean done;
438
439 done = false;
440 ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
441 checkref(ifcmd);
442 if (ifcmd->op == O_IF) {
443 stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
444 checkref(stopcmd);
445 if (stopcmd->op == O_STOPX) {
12e1c9d1
ML
446 fprintf(f, "stop");
447 fprintI(f, cmd->value.trace.inst);
448 fprintf(f, " if ");
b3355c51
ML
449 prtree(f, ifcmd->value.event.cond);
450 done = true;
451 }
12e1c9d1
ML
452 } else if (ifcmd->op == O_STOPIFCHANGED) {
453 fprintf(f, "stop");
454 fprintI(f, cmd->value.trace.inst);
455 fprintf(f, " ");
456 prtree(f, ifcmd->value.arg[0]);
457 done = true;
b3355c51
ML
458 }
459 if (not done) {
460 fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
461 foreach (Command, c, cmd->value.trace.actions)
462 printcmd(f, c);
463 if (not list_islast()) {
464 fprintf(f, ";");
465 }
466 endfor
467 }
468}
469
470/*
12e1c9d1 471 * Print out a tree.
b3355c51
ML
472 */
473
474public prtree(f, p)
475File f;
476register Node p;
477{
478 register Node q;
479 Operator op;
480
481 if (p != nil) {
482 op = p->op;
483 if (ord(op) > ord(O_LASTOP)) {
484 panic("bad op %d in prtree", p->op);
485 }
486 switch (op) {
487 case O_NAME:
488 fprintf(f, "%s", ident(p->value.name));
489 break;
490
491 case O_SYM:
492 printname(f, p->value.sym);
493 break;
494
495 case O_QLINE:
496 if (nlhdr.nfiles > 1) {
497 prtree(f, p->value.arg[0]);
498 fprintf(f, ":");
499 }
500 prtree(f, p->value.arg[1]);
501 break;
502
503 case O_LCON:
0022c355
ML
504 fprintf(f, "%d", p->value.lcon);
505 break;
506
507 case O_CCON:
508 fprintf(f, "'%c'", p->value.lcon);
b3355c51
ML
509 break;
510
511 case O_FCON:
512 fprintf(f, "%g", p->value.fcon);
513 break;
514
515 case O_SCON:
516 fprintf(f, "\"%s\"", p->value.scon);
517 break;
518
519 case O_INDEX:
520 prtree(f, p->value.arg[0]);
521 fprintf(f, "[");
522 prtree(f, p->value.arg[1]);
523 fprintf(f, "]");
524 break;
525
526 case O_COMMA:
527 prtree(f, p->value.arg[0]);
528 if (p->value.arg[1] != nil) {
529 fprintf(f, ", ");
530 prtree(f, p->value.arg[1]);
531 }
532 break;
533
534 case O_RVAL:
b3355c51
ML
535 case O_ITOF:
536 prtree(f, p->value.arg[0]);
537 break;
538
539 case O_CALL:
540 prtree(f, p->value.arg[0]);
541 if (p->value.arg[1]!= nil) {
542 fprintf(f, "(");
543 prtree(f, p->value.arg[1]);
544 fprintf(f, ")");
545 }
546 break;
547
548 case O_INDIR:
0022c355
ML
549 prtree(f, p->value.arg[0]);
550 fprintf(f, "^");
b3355c51
ML
551 break;
552
553 case O_DOT:
0022c355 554 prtree(f, p->value.arg[0]);
b3355c51
ML
555 fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
556 break;
557
0022c355
ML
558 case O_TYPERENAME:
559 prtree(f, p->value.arg[1]);
560 fprintf(f, "(");
561 prtree(f, p->value.arg[0]);
562 fprintf(f, ")");
563 break;
564
b3355c51
ML
565 default:
566 switch (degree(op)) {
567 case BINARY:
568 prtree(f, p->value.arg[0]);
569 fprintf(f, "%s", opinfo[ord(op)].opstring);
570 prtree(f, p->value.arg[1]);
571 break;
572
573 case UNARY:
574 fprintf(f, "%s", opinfo[ord(op)].opstring);
575 prtree(f, p->value.arg[0]);
576 break;
577
578 default:
0022c355
ML
579 if (opinfo[ord(op)].opstring == nil) {
580 fprintf(f, "[op %d]", ord(op));
581 } else {
582 fprintf(f, "%s", opinfo[ord(op)].opstring);
583 }
584 break;
b3355c51
ML
585 }
586 break;
587 }
588 }
589}
590
591/*
592 * Free storage associated with a tree.
593 */
594
595public tfree(p)
596Node p;
597{
598 Integer i;
599
600 if (p == nil) {
601 return;
602 }
603 switch (p->op) {
604 case O_QLINE:
605 dispose(p->value.arg[0]->value.scon);
606 dispose(p->value.arg[0]);
607 tfree(p->value.arg[1]);
608 break;
609
610 case O_SCON:
611 unmkstring(p->nodetype);
612 dispose(p->nodetype);
613 dispose(p->value.scon);
614 break;
615
616 default:
617 for (i = 0; i < nargs(p->op); i++) {
618 tfree(p->value.arg[i]);
619 }
620 break;
621 }
622 dispose(p);
623}