|
|
1.1 root 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: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)tree.c 5.1 (Berkeley) 5/31/85";
9: #endif not lint
10:
11: static char rcsid[] = "$Header: tree.c,v 1.5 84/12/26 10:42:55 linton Exp $";
12:
13: /*
14: * Parse tree management.
15: */
16:
17: #include "defs.h"
18: #include "tree.h"
19: #include "operators.h"
20: #include "debug.h"
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:
34: typedef struct Node *Node;
35: typedef Node Command;
36: typedef List Cmdlist;
37:
38: #include "operators.h"
39: #include "symbols.h"
40: #include "events.h"
41:
42: #define MAXNARGS 5
43:
44: struct 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:
81: typedef char *Arglist;
82:
83: #define nextarg(type) ((type *) (ap += sizeof(type)))[-1]
84:
85: /*
86: * Build a tree.
87: */
88:
89: /* VARARGS1 */
90: public Node build(op, args)
91: Operator 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:
113: case O_DEBUG:
114: case O_LCON:
115: case O_CCON:
116: case O_CONT:
117: case O_CATCH:
118: case O_IGNORE:
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:
135: case O_INDIR:
136: p->value.arg[0] = nextarg(Node);
137: break;
138:
139: case O_CALL:
140: q = nextarg(Node);
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: }
151: p->value.arg[0] = q->value.arg[0];
152: } else {
153: p->value.arg[0] = q;
154: p->value.arg[1] = nextarg(Node);
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);
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);
195: }
196: return p;
197: }
198:
199: /*
200: * Strip away indirection from a node, thus returning a node for
201: * interpreting the expression as an lvalue.
202: */
203:
204: public Node unrval (exp)
205: Node exp;
206: {
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: }
225:
226: /*
227: * Create a node for renaming a node to a pointer type.
228: */
229:
230: public Node renameptr (p, t)
231: Node p;
232: Node t;
233: {
234: t->nodetype = newSymbol(nil, 0, PTR, t->nodetype, nil);
235: p = build(O_TYPERENAME, p, t);
236: }
237:
238: /*
239: * Return the tree for a unary ampersand operator.
240: */
241:
242: public Node amper(p)
243: Node p;
244: {
245: Node r;
246:
247: checkref(p);
248: switch (p->op) {
249: case O_RVAL:
250: case O_INDIR:
251: r = p->value.arg[0];
252: r->nodetype = t_addr;
253: dispose(p);
254: break;
255:
256: case O_TYPERENAME:
257: r = p;
258: r->nodetype = newSymbol(nil, 0, PTR, r->nodetype, nil);
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: }
267: r->nodetype = t_addr;
268: dispose(p);
269: break;
270:
271: case O_DOT:
272: r = p;
273: r->nodetype = t_addr;
274: break;
275:
276: default:
277: beginerrmsg();
278: fprintf(stderr, "expected variable, found \"");
279: prtree(stderr, p);
280: fprintf(stderr, "\"");
281: tfree(p);
282: enderrmsg();
283: /* NOTREACHED */
284: }
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:
294: public Node concrete(p)
295: Node p;
296: {
297: findtype(p->nodetype);
298: return build(O_INDIR, p);
299: }
300:
301: /*
302: * Create a command list from a single command.
303: */
304:
305: public Cmdlist buildcmdlist(cmd)
306: Command cmd;
307: {
308: Cmdlist cmdlist;
309:
310: cmdlist = list_alloc();
311: cmdlist_append(cmd, cmdlist);
312: return cmdlist;
313: }
314:
315: /*
316: * Print out a command.
317: */
318:
319: public printcmd(f, cmd)
320: File f;
321: Command 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:
373: case O_CATCH:
374: case O_IGNORE:
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:
429: #define fprintI(f, b) { if (b) fprintf(f, "i"); }
430:
431: private print_tracestop(f, cmd)
432: File f;
433: Command 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) {
445: fprintf(f, "stop");
446: fprintI(f, cmd->value.trace.inst);
447: fprintf(f, " if ");
448: prtree(f, ifcmd->value.event.cond);
449: done = true;
450: }
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;
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: /*
470: * Print out a tree.
471: */
472:
473: public prtree(f, p)
474: File f;
475: register 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:
503: fprintf(f, "%d", p->value.lcon);
504: break;
505:
506: case O_CCON:
507: fprintf(f, "'%c'", p->value.lcon);
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:
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:
548: prtree(f, p->value.arg[0]);
549: fprintf(f, "^");
550: break;
551:
552: case O_DOT:
553: prtree(f, p->value.arg[0]);
554: fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
555: break;
556:
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:
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:
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;
584: }
585: break;
586: }
587: }
588: }
589:
590: /*
591: * Free storage associated with a tree.
592: */
593:
594: public tfree(p)
595: Node 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.