|
|
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[] = "@(#)check.c 5.4 (Berkeley) 6/1/90";
22: #endif /* not lint */
23:
24: /*
25: * Check a tree for semantic correctness.
26: */
27:
28: #include "defs.h"
29: #include "tree.h"
30: #include "operators.h"
31: #include "events.h"
32: #include "symbols.h"
33: #include "scanner.h"
34: #include "source.h"
35: #include "object.h"
36: #include "mappings.h"
37: #include "process.h"
38: #include <signal.h>
39:
40: #ifndef public
41: #endif
42:
43: /*
44: * Check that the nodes in a tree have the correct arguments
45: * in order to be evaluated. Basically the error checking here
46: * frees the evaluation routines from worrying about anything
47: * except dynamic errors, e.g. subscript out of range.
48: */
49:
50: public check(p)
51: register Node p;
52: {
53: Node p1, p2;
54: Address addr;
55: Symbol f;
56:
57: checkref(p);
58: switch (p->op) {
59: case O_ASSIGN:
60: p1 = p->value.arg[0];
61: p2 = p->value.arg[1];
62: if (varIsSet("$unsafeassign")) {
63: if (size(p1->nodetype) != size(p2->nodetype)) {
64: error("incompatible sizes");
65: }
66: } else if (not compatible(p1->nodetype, p2->nodetype)) {
67: error("incompatible types");
68: }
69: break;
70:
71: case O_CATCH:
72: case O_IGNORE:
73: if (p->value.lcon < 0 or p->value.lcon > NSIG) {
74: error("invalid signal number");
75: }
76: break;
77:
78: case O_CONT:
79: if (p->value.lcon != DEFSIG and (
80: p->value.lcon < 0 or p->value.lcon > NSIG)
81: ) {
82: error("invalid signal number");
83: }
84: break;
85:
86: case O_DUMP:
87: if (p->value.arg[0] != nil) {
88: if (p->value.arg[0]->op == O_SYM) {
89: f = p->value.arg[0]->value.sym;
90: if (not isblock(f)) {
91: error("\"%s\" is not a block", symname(f));
92: }
93: } else {
94: beginerrmsg();
95: fprintf(stderr, "expected a symbol, found \"");
96: prtree(stderr, p->value.arg[0]);
97: fprintf(stderr, "\"");
98: enderrmsg();
99: }
100: }
101: break;
102:
103: case O_LIST:
104: if (p->value.arg[0]->op == O_SYM) {
105: f = p->value.arg[0]->value.sym;
106: if (not isblock(f) or ismodule(f)) {
107: error("\"%s\" is not a procedure or function", symname(f));
108: }
109: addr = firstline(f);
110: if (addr == NOADDR) {
111: error("\"%s\" is empty", symname(f));
112: }
113: }
114: break;
115:
116: case O_TRACE:
117: case O_TRACEI:
118: chktrace(p);
119: break;
120:
121: case O_STOP:
122: case O_STOPI:
123: chkstop(p);
124: break;
125:
126: case O_CALLPROC:
127: case O_CALL:
128: if (not isroutine(p->value.arg[0]->nodetype)) {
129: beginerrmsg();
130: fprintf(stderr, "\"");
131: prtree(stderr, p->value.arg[0]);
132: fprintf(stderr, "\" not call-able");
133: enderrmsg();
134: }
135: break;
136:
137: case O_WHEREIS:
138: if (p->value.arg[0]->op == O_SYM and
139: p->value.arg[0]->value.sym == nil) {
140: error("symbol not defined");
141: }
142: break;
143:
144: default:
145: break;
146: }
147: }
148:
149: /*
150: * Check arguments to a trace command.
151: */
152:
153: private chktrace(p)
154: Node p;
155: {
156: Node exp, place, cond;
157:
158: exp = p->value.arg[0];
159: place = p->value.arg[1];
160: cond = p->value.arg[2];
161: if (exp == nil) {
162: chkblock(place);
163: } else if (exp->op == O_LCON or exp->op == O_QLINE) {
164: if (place != nil) {
165: error("unexpected \"at\" or \"in\"");
166: }
167: if (p->op == O_TRACE) {
168: chkline(exp);
169: } else {
170: chkaddr(exp);
171: }
172: } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) {
173: if (p->op == O_TRACE) {
174: chkline(place);
175: } else {
176: chkaddr(place);
177: }
178: } else {
179: if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) {
180: error("can't trace expressions");
181: }
182: chkblock(place);
183: }
184: }
185:
186: /*
187: * Check arguments to a stop command.
188: */
189:
190: private chkstop(p)
191: Node p;
192: {
193: Node exp, place, cond;
194:
195: exp = p->value.arg[0];
196: place = p->value.arg[1];
197: cond = p->value.arg[2];
198: if (exp != nil) {
199: if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) {
200: beginerrmsg();
201: fprintf(stderr, "expected variable, found ");
202: prtree(stderr, exp);
203: enderrmsg();
204: }
205: chkblock(place);
206: } else if (place != nil) {
207: if (place->op == O_SYM) {
208: chkblock(place);
209: } else {
210: if (p->op == O_STOP) {
211: chkline(place);
212: } else {
213: chkaddr(place);
214: }
215: }
216: }
217: }
218:
219: /*
220: * Check to see that the given node specifies some subprogram.
221: * Nil is ok since that means the entire program.
222: */
223:
224: private chkblock(b)
225: Node b;
226: {
227: Symbol p, outer;
228:
229: if (b != nil) {
230: if (b->op != O_SYM) {
231: beginerrmsg();
232: fprintf(stderr, "expected subprogram, found ");
233: prtree(stderr, b);
234: enderrmsg();
235: } else if (ismodule(b->value.sym)) {
236: outer = b->value.sym;
237: while (outer != nil) {
238: find(p, outer->name) where p->block == outer endfind(p);
239: if (p == nil) {
240: outer = nil;
241: error("\"%s\" is not a subprogram", symname(b->value.sym));
242: } else if (ismodule(p)) {
243: outer = p;
244: } else {
245: outer = nil;
246: b->value.sym = p;
247: }
248: }
249: } else if (
250: b->value.sym->class == VAR and
251: b->value.sym->name == b->value.sym->block->name and
252: b->value.sym->block->class == FUNC
253: ) {
254: b->value.sym = b->value.sym->block;
255: } else if (not isblock(b->value.sym)) {
256: error("\"%s\" is not a subprogram", symname(b->value.sym));
257: }
258: }
259: }
260:
261: /*
262: * Check to make sure a node corresponds to a source line.
263: */
264:
265: private chkline(p)
266: Node p;
267: {
268: if (p == nil) {
269: error("missing line");
270: } else if (p->op != O_QLINE and p->op != O_LCON) {
271: error("expected source line number, found \"%t\"", p);
272: }
273: }
274:
275: /*
276: * Check to make sure a node corresponds to an address.
277: */
278:
279: private chkaddr(p)
280: Node p;
281: {
282: if (p == nil) {
283: error("missing address");
284: } else if (p->op != O_LCON and p->op != O_QLINE) {
285: beginerrmsg();
286: fprintf(stderr, "expected address, found \"");
287: prtree(stderr, p);
288: fprintf(stderr, "\"");
289: enderrmsg();
290: }
291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.