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