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