add vdioctl
[unix-history] / usr / src / old / 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
DF
7#ifndef lint
8static char sccsid[] = "@(#)tree.c 5.1 (Berkeley) %G%";
9#endif not lint
0022c355
ML
10
11static char rcsid[] = "$Header: tree.c,v 1.5 84/12/26 10:42:55 linton 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);
b3355c51
ML
259 break;
260
261 case O_SYM:
262 if (isblock(p->value.sym)) {
263 r = build(O_LCON, codeloc(p->value.sym));
264 } else {
265 r = build(O_LCON, address(p->value.sym, nil));
266 }
0022c355
ML
267 r->nodetype = t_addr;
268 dispose(p);
b3355c51
ML
269 break;
270
271 case O_DOT:
272 r = p;
0022c355 273 r->nodetype = t_addr;
b3355c51
ML
274 break;
275
276 default:
277 beginerrmsg();
0022c355 278 fprintf(stderr, "expected variable, found \"");
b3355c51 279 prtree(stderr, p);
0022c355 280 fprintf(stderr, "\"");
b3355c51
ML
281 tfree(p);
282 enderrmsg();
283 /* NOTREACHED */
284 }
b3355c51
ML
285 return r;
286}
287
288/*
289 * Create a "concrete" version of a node.
290 * This is necessary when the type of the node contains
291 * an unresolved type reference.
292 */
293
294public Node concrete(p)
295Node p;
296{
297 findtype(p->nodetype);
298 return build(O_INDIR, p);
299}
300
0022c355
ML
301/*
302 * Create a command list from a single command.
303 */
304
305public Cmdlist buildcmdlist(cmd)
306Command cmd;
307{
308 Cmdlist cmdlist;
309
310 cmdlist = list_alloc();
311 cmdlist_append(cmd, cmdlist);
312 return cmdlist;
313}
314
b3355c51
ML
315/*
316 * Print out a command.
317 */
318
319public printcmd(f, cmd)
320File f;
321Command cmd;
322{
323 register Integer i;
324 register Command c;
325 register Node p;
326
327 switch (cmd->op) {
328 case O_PRINTIFCHANGED:
329 case O_PRINTSRCPOS:
330 case O_STOPIFCHANGED:
331 case O_TRACEON:
332 break;
333
334 case O_STEP:
335 if (cmd->value.step.skipcalls) {
336 fprintf(f, "next");
337 } else {
338 fprintf(f, "step");
339 }
340 if (not cmd->value.step.source) {
341 fprintf(f, "i");
342 }
343 break;
344
345 default:
346 fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
347 if (nargs(cmd->op) != 0) {
348 fprintf(f, " ");
349 }
350 break;
351 }
352 switch (cmd->op) {
353 case O_PRINTCALL:
354 case O_PRINTRTN:
355 case O_PROCRTN:
356 fprintf(f, "%s", symname(cmd->value.sym));
357 break;
358
359 case O_PRINTSRCPOS:
360 p = cmd->value.arg[0];
361 if (p != nil and p->op != O_QLINE) {
362 printf("trace ");
363 prtree(f, p);
364 }
365 break;
366
367 case O_CHFILE:
368 case O_EDIT:
369 case O_SOURCE:
370 fprintf(f, "%s", cmd->value.scon);
371 break;
372
0022c355
ML
373 case O_CATCH:
374 case O_IGNORE:
b3355c51
ML
375 case O_TRACEOFF:
376 fprintf(f, "%d", cmd->value.lcon);
377 break;
378
379 case O_ADDEVENT:
380 case O_ONCE:
381 case O_IF:
382 fprintf(f, " ");
383 prtree(f, cmd->value.event.cond);
384 fprintf(f, " { ");
385 foreach (Command, c, cmd->value.event.actions)
386 printcmd(f, c);
387 if (not list_islast()) {
388 fprintf(f, ";");
389 }
390 endfor
391 fprintf(f, " }", opinfo[ord(cmd->op)].opstring);
392 break;
393
394 case O_TRACEON:
395 print_tracestop(f, cmd);
396 break;
397
398 case O_EXAMINE:
399 prtree(f, cmd->value.examine.beginaddr);
400 if (cmd->value.examine.endaddr != nil) {
401 fprintf(f, ",");
402 prtree(f, cmd->value.examine.endaddr);
403 }
404 fprintf(f, "/");
405 if (cmd->value.examine.count > 1) {
406 fprintf(f, "%d", cmd->value.examine.count);
407 }
408 fprintf("%s", cmd->value.examine.mode);
409 break;
410
411 default:
412 if (nargs(cmd->op) != 0) {
413 i = 0;
414 for (;;) {
415 prtree(f, cmd->value.arg[i]);
416 ++i;
417 if (i >= nargs(cmd->op)) break;
418 fprintf(f, " ");
419 }
420 }
421 break;
422 }
423}
424
425/*
426 * Print out a trace/stop command name.
427 */
428
12e1c9d1
ML
429#define fprintI(f, b) { if (b) fprintf(f, "i"); }
430
b3355c51
ML
431private print_tracestop(f, cmd)
432File f;
433Command cmd;
434{
435 register Command c, ifcmd, stopcmd;
436 Boolean done;
437
438 done = false;
439 ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
440 checkref(ifcmd);
441 if (ifcmd->op == O_IF) {
442 stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
443 checkref(stopcmd);
444 if (stopcmd->op == O_STOPX) {
12e1c9d1
ML
445 fprintf(f, "stop");
446 fprintI(f, cmd->value.trace.inst);
447 fprintf(f, " if ");
b3355c51
ML
448 prtree(f, ifcmd->value.event.cond);
449 done = true;
450 }
12e1c9d1
ML
451 } else if (ifcmd->op == O_STOPIFCHANGED) {
452 fprintf(f, "stop");
453 fprintI(f, cmd->value.trace.inst);
454 fprintf(f, " ");
455 prtree(f, ifcmd->value.arg[0]);
456 done = true;
b3355c51
ML
457 }
458 if (not done) {
459 fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
460 foreach (Command, c, cmd->value.trace.actions)
461 printcmd(f, c);
462 if (not list_islast()) {
463 fprintf(f, ";");
464 }
465 endfor
466 }
467}
468
469/*
12e1c9d1 470 * Print out a tree.
b3355c51
ML
471 */
472
473public prtree(f, p)
474File f;
475register Node p;
476{
477 register Node q;
478 Operator op;
479
480 if (p != nil) {
481 op = p->op;
482 if (ord(op) > ord(O_LASTOP)) {
483 panic("bad op %d in prtree", p->op);
484 }
485 switch (op) {
486 case O_NAME:
487 fprintf(f, "%s", ident(p->value.name));
488 break;
489
490 case O_SYM:
491 printname(f, p->value.sym);
492 break;
493
494 case O_QLINE:
495 if (nlhdr.nfiles > 1) {
496 prtree(f, p->value.arg[0]);
497 fprintf(f, ":");
498 }
499 prtree(f, p->value.arg[1]);
500 break;
501
502 case O_LCON:
0022c355
ML
503 fprintf(f, "%d", p->value.lcon);
504 break;
505
506 case O_CCON:
507 fprintf(f, "'%c'", p->value.lcon);
b3355c51
ML
508 break;
509
510 case O_FCON:
511 fprintf(f, "%g", p->value.fcon);
512 break;
513
514 case O_SCON:
515 fprintf(f, "\"%s\"", p->value.scon);
516 break;
517
518 case O_INDEX:
519 prtree(f, p->value.arg[0]);
520 fprintf(f, "[");
521 prtree(f, p->value.arg[1]);
522 fprintf(f, "]");
523 break;
524
525 case O_COMMA:
526 prtree(f, p->value.arg[0]);
527 if (p->value.arg[1] != nil) {
528 fprintf(f, ", ");
529 prtree(f, p->value.arg[1]);
530 }
531 break;
532
533 case O_RVAL:
b3355c51
ML
534 case O_ITOF:
535 prtree(f, p->value.arg[0]);
536 break;
537
538 case O_CALL:
539 prtree(f, p->value.arg[0]);
540 if (p->value.arg[1]!= nil) {
541 fprintf(f, "(");
542 prtree(f, p->value.arg[1]);
543 fprintf(f, ")");
544 }
545 break;
546
547 case O_INDIR:
0022c355
ML
548 prtree(f, p->value.arg[0]);
549 fprintf(f, "^");
b3355c51
ML
550 break;
551
552 case O_DOT:
0022c355 553 prtree(f, p->value.arg[0]);
b3355c51
ML
554 fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
555 break;
556
0022c355
ML
557 case O_TYPERENAME:
558 prtree(f, p->value.arg[1]);
559 fprintf(f, "(");
560 prtree(f, p->value.arg[0]);
561 fprintf(f, ")");
562 break;
563
b3355c51
ML
564 default:
565 switch (degree(op)) {
566 case BINARY:
567 prtree(f, p->value.arg[0]);
568 fprintf(f, "%s", opinfo[ord(op)].opstring);
569 prtree(f, p->value.arg[1]);
570 break;
571
572 case UNARY:
573 fprintf(f, "%s", opinfo[ord(op)].opstring);
574 prtree(f, p->value.arg[0]);
575 break;
576
577 default:
0022c355
ML
578 if (opinfo[ord(op)].opstring == nil) {
579 fprintf(f, "[op %d]", ord(op));
580 } else {
581 fprintf(f, "%s", opinfo[ord(op)].opstring);
582 }
583 break;
b3355c51
ML
584 }
585 break;
586 }
587 }
588}
589
590/*
591 * Free storage associated with a tree.
592 */
593
594public tfree(p)
595Node p;
596{
597 Integer i;
598
599 if (p == nil) {
600 return;
601 }
602 switch (p->op) {
603 case O_QLINE:
604 dispose(p->value.arg[0]->value.scon);
605 dispose(p->value.arg[0]);
606 tfree(p->value.arg[1]);
607 break;
608
609 case O_SCON:
610 unmkstring(p->nodetype);
611 dispose(p->nodetype);
612 dispose(p->value.scon);
613 break;
614
615 default:
616 for (i = 0; i < nargs(p->op); i++) {
617 tfree(p->value.arg[i]);
618 }
619 break;
620 }
621 dispose(p);
622}