1de6c3e6fSdist /*
2be26f981Sbostic * Copyright (c) 1983 The Regents of the University of California.
3be26f981Sbostic * All rights reserved.
4be26f981Sbostic *
5*1808f06cSbostic * %sccs.include.redist.c%
6de6c3e6fSdist */
7ec7c7edbSlinton
8de6c3e6fSdist #ifndef lint
9*1808f06cSbostic static char sccsid[] = "@(#)check.c 5.4 (Berkeley) 06/01/90";
10be26f981Sbostic #endif /* not lint */
11ec7c7edbSlinton
12ec7c7edbSlinton /*
13ec7c7edbSlinton * Check a tree for semantic correctness.
14ec7c7edbSlinton */
15ec7c7edbSlinton
16ec7c7edbSlinton #include "defs.h"
17ec7c7edbSlinton #include "tree.h"
18ec7c7edbSlinton #include "operators.h"
19ec7c7edbSlinton #include "events.h"
20ec7c7edbSlinton #include "symbols.h"
21ec7c7edbSlinton #include "scanner.h"
22ec7c7edbSlinton #include "source.h"
23ec7c7edbSlinton #include "object.h"
24ec7c7edbSlinton #include "mappings.h"
25ec7c7edbSlinton #include "process.h"
2649648a56Slinton #include <signal.h>
27ec7c7edbSlinton
28ec7c7edbSlinton #ifndef public
29ec7c7edbSlinton #endif
30ec7c7edbSlinton
31ec7c7edbSlinton /*
32ec7c7edbSlinton * Check that the nodes in a tree have the correct arguments
33ec7c7edbSlinton * in order to be evaluated. Basically the error checking here
34ec7c7edbSlinton * frees the evaluation routines from worrying about anything
35ec7c7edbSlinton * except dynamic errors, e.g. subscript out of range.
36ec7c7edbSlinton */
37ec7c7edbSlinton
check(p)38ec7c7edbSlinton public check(p)
39ec7c7edbSlinton register Node p;
40ec7c7edbSlinton {
4149648a56Slinton Node p1, p2;
42ec7c7edbSlinton Address addr;
43ec7c7edbSlinton Symbol f;
44ec7c7edbSlinton
45ec7c7edbSlinton checkref(p);
46ec7c7edbSlinton switch (p->op) {
4749648a56Slinton case O_ASSIGN:
4849648a56Slinton p1 = p->value.arg[0];
4949648a56Slinton p2 = p->value.arg[1];
50352cb53aSdonn if (varIsSet("$unsafeassign")) {
51352cb53aSdonn if (size(p1->nodetype) != size(p2->nodetype)) {
52352cb53aSdonn error("incompatible sizes");
53352cb53aSdonn }
54352cb53aSdonn } else if (not compatible(p1->nodetype, p2->nodetype)) {
5549648a56Slinton error("incompatible types");
5649648a56Slinton }
5749648a56Slinton break;
5849648a56Slinton
5949648a56Slinton case O_CATCH:
6049648a56Slinton case O_IGNORE:
6149648a56Slinton if (p->value.lcon < 0 or p->value.lcon > NSIG) {
6249648a56Slinton error("invalid signal number");
6349648a56Slinton }
6449648a56Slinton break;
6549648a56Slinton
6649648a56Slinton case O_CONT:
6749648a56Slinton if (p->value.lcon != DEFSIG and (
6849648a56Slinton p->value.lcon < 0 or p->value.lcon > NSIG)
6949648a56Slinton ) {
7049648a56Slinton error("invalid signal number");
7149648a56Slinton }
7249648a56Slinton break;
7349648a56Slinton
7449648a56Slinton case O_DUMP:
7549648a56Slinton if (p->value.arg[0] != nil) {
7649648a56Slinton if (p->value.arg[0]->op == O_SYM) {
7749648a56Slinton f = p->value.arg[0]->value.sym;
7849648a56Slinton if (not isblock(f)) {
7949648a56Slinton error("\"%s\" is not a block", symname(f));
8049648a56Slinton }
8149648a56Slinton } else {
8249648a56Slinton beginerrmsg();
8349648a56Slinton fprintf(stderr, "expected a symbol, found \"");
8449648a56Slinton prtree(stderr, p->value.arg[0]);
8549648a56Slinton fprintf(stderr, "\"");
8649648a56Slinton enderrmsg();
8749648a56Slinton }
8849648a56Slinton }
8949648a56Slinton break;
9049648a56Slinton
91ec7c7edbSlinton case O_LIST:
92ec7c7edbSlinton if (p->value.arg[0]->op == O_SYM) {
93ec7c7edbSlinton f = p->value.arg[0]->value.sym;
94ec7c7edbSlinton if (not isblock(f) or ismodule(f)) {
95ec7c7edbSlinton error("\"%s\" is not a procedure or function", symname(f));
96ec7c7edbSlinton }
97ec7c7edbSlinton addr = firstline(f);
98ec7c7edbSlinton if (addr == NOADDR) {
99ec7c7edbSlinton error("\"%s\" is empty", symname(f));
100ec7c7edbSlinton }
101ec7c7edbSlinton }
102ec7c7edbSlinton break;
103ec7c7edbSlinton
104ec7c7edbSlinton case O_TRACE:
105ec7c7edbSlinton case O_TRACEI:
106ec7c7edbSlinton chktrace(p);
107ec7c7edbSlinton break;
108ec7c7edbSlinton
109ec7c7edbSlinton case O_STOP:
110ec7c7edbSlinton case O_STOPI:
111ec7c7edbSlinton chkstop(p);
112ec7c7edbSlinton break;
113ec7c7edbSlinton
11449648a56Slinton case O_CALLPROC:
1159b67ad80Ssam case O_CALL:
1169b67ad80Ssam if (not isroutine(p->value.arg[0]->nodetype)) {
1179b67ad80Ssam beginerrmsg();
1189b67ad80Ssam fprintf(stderr, "\"");
1199b67ad80Ssam prtree(stderr, p->value.arg[0]);
1209b67ad80Ssam fprintf(stderr, "\" not call-able");
1219b67ad80Ssam enderrmsg();
1229b67ad80Ssam }
1239b67ad80Ssam break;
1249b67ad80Ssam
12549648a56Slinton case O_WHEREIS:
12649648a56Slinton if (p->value.arg[0]->op == O_SYM and
12749648a56Slinton p->value.arg[0]->value.sym == nil) {
12849648a56Slinton error("symbol not defined");
12949648a56Slinton }
13049648a56Slinton break;
13149648a56Slinton
132ec7c7edbSlinton default:
133ec7c7edbSlinton break;
134ec7c7edbSlinton }
135ec7c7edbSlinton }
136ec7c7edbSlinton
137ec7c7edbSlinton /*
138ec7c7edbSlinton * Check arguments to a trace command.
139ec7c7edbSlinton */
140ec7c7edbSlinton
chktrace(p)141ec7c7edbSlinton private chktrace(p)
142ec7c7edbSlinton Node p;
143ec7c7edbSlinton {
144ec7c7edbSlinton Node exp, place, cond;
145ec7c7edbSlinton
146ec7c7edbSlinton exp = p->value.arg[0];
147ec7c7edbSlinton place = p->value.arg[1];
148ec7c7edbSlinton cond = p->value.arg[2];
149ec7c7edbSlinton if (exp == nil) {
150ec7c7edbSlinton chkblock(place);
151ec7c7edbSlinton } else if (exp->op == O_LCON or exp->op == O_QLINE) {
152ec7c7edbSlinton if (place != nil) {
153ec7c7edbSlinton error("unexpected \"at\" or \"in\"");
154ec7c7edbSlinton }
155ec7c7edbSlinton if (p->op == O_TRACE) {
156ec7c7edbSlinton chkline(exp);
157ec7c7edbSlinton } else {
158ec7c7edbSlinton chkaddr(exp);
159ec7c7edbSlinton }
160ec7c7edbSlinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) {
161ec7c7edbSlinton if (p->op == O_TRACE) {
162ec7c7edbSlinton chkline(place);
163ec7c7edbSlinton } else {
164ec7c7edbSlinton chkaddr(place);
165ec7c7edbSlinton }
166ec7c7edbSlinton } else {
16717bdf32aSlinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) {
168ec7c7edbSlinton error("can't trace expressions");
169ec7c7edbSlinton }
170ec7c7edbSlinton chkblock(place);
171ec7c7edbSlinton }
172ec7c7edbSlinton }
173ec7c7edbSlinton
174ec7c7edbSlinton /*
175ec7c7edbSlinton * Check arguments to a stop command.
176ec7c7edbSlinton */
177ec7c7edbSlinton
chkstop(p)178ec7c7edbSlinton private chkstop(p)
179ec7c7edbSlinton Node p;
180ec7c7edbSlinton {
181ec7c7edbSlinton Node exp, place, cond;
182ec7c7edbSlinton
183ec7c7edbSlinton exp = p->value.arg[0];
184ec7c7edbSlinton place = p->value.arg[1];
185ec7c7edbSlinton cond = p->value.arg[2];
186ec7c7edbSlinton if (exp != nil) {
187861d1525Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) {
188ec7c7edbSlinton beginerrmsg();
189ec7c7edbSlinton fprintf(stderr, "expected variable, found ");
190ec7c7edbSlinton prtree(stderr, exp);
191ec7c7edbSlinton enderrmsg();
192ec7c7edbSlinton }
193ec7c7edbSlinton chkblock(place);
1949b67ad80Ssam } else if (place != nil) {
1959b67ad80Ssam if (place->op == O_SYM) {
196ec7c7edbSlinton chkblock(place);
197ec7c7edbSlinton } else {
198ec7c7edbSlinton if (p->op == O_STOP) {
199ec7c7edbSlinton chkline(place);
200ec7c7edbSlinton } else {
201ec7c7edbSlinton chkaddr(place);
202ec7c7edbSlinton }
203ec7c7edbSlinton }
204ec7c7edbSlinton }
2059b67ad80Ssam }
206ec7c7edbSlinton
207ec7c7edbSlinton /*
208ec7c7edbSlinton * Check to see that the given node specifies some subprogram.
209ec7c7edbSlinton * Nil is ok since that means the entire program.
210ec7c7edbSlinton */
211ec7c7edbSlinton
chkblock(b)212ec7c7edbSlinton private chkblock(b)
213ec7c7edbSlinton Node b;
214ec7c7edbSlinton {
2159b67ad80Ssam Symbol p, outer;
2169b67ad80Ssam
217ec7c7edbSlinton if (b != nil) {
218ec7c7edbSlinton if (b->op != O_SYM) {
219ec7c7edbSlinton beginerrmsg();
220ec7c7edbSlinton fprintf(stderr, "expected subprogram, found ");
221ec7c7edbSlinton prtree(stderr, b);
222ec7c7edbSlinton enderrmsg();
2239b67ad80Ssam } else if (ismodule(b->value.sym)) {
2249b67ad80Ssam outer = b->value.sym;
2259b67ad80Ssam while (outer != nil) {
2269b67ad80Ssam find(p, outer->name) where p->block == outer endfind(p);
2279b67ad80Ssam if (p == nil) {
2289b67ad80Ssam outer = nil;
2299b67ad80Ssam error("\"%s\" is not a subprogram", symname(b->value.sym));
2309b67ad80Ssam } else if (ismodule(p)) {
2319b67ad80Ssam outer = p;
2329b67ad80Ssam } else {
2339b67ad80Ssam outer = nil;
2349b67ad80Ssam b->value.sym = p;
2359b67ad80Ssam }
2369b67ad80Ssam }
23749648a56Slinton } else if (
23849648a56Slinton b->value.sym->class == VAR and
23949648a56Slinton b->value.sym->name == b->value.sym->block->name and
24049648a56Slinton b->value.sym->block->class == FUNC
24149648a56Slinton ) {
24249648a56Slinton b->value.sym = b->value.sym->block;
2439b67ad80Ssam } else if (not isblock(b->value.sym)) {
244ec7c7edbSlinton error("\"%s\" is not a subprogram", symname(b->value.sym));
245ec7c7edbSlinton }
246ec7c7edbSlinton }
247ec7c7edbSlinton }
248ec7c7edbSlinton
249ec7c7edbSlinton /*
250ec7c7edbSlinton * Check to make sure a node corresponds to a source line.
251ec7c7edbSlinton */
252ec7c7edbSlinton
chkline(p)253ec7c7edbSlinton private chkline(p)
254ec7c7edbSlinton Node p;
255ec7c7edbSlinton {
256ec7c7edbSlinton if (p == nil) {
257ec7c7edbSlinton error("missing line");
258ec7c7edbSlinton } else if (p->op != O_QLINE and p->op != O_LCON) {
259ec7c7edbSlinton error("expected source line number, found \"%t\"", p);
260ec7c7edbSlinton }
261ec7c7edbSlinton }
262ec7c7edbSlinton
263ec7c7edbSlinton /*
264ec7c7edbSlinton * Check to make sure a node corresponds to an address.
265ec7c7edbSlinton */
266ec7c7edbSlinton
chkaddr(p)267ec7c7edbSlinton private chkaddr(p)
268ec7c7edbSlinton Node p;
269ec7c7edbSlinton {
270ec7c7edbSlinton if (p == nil) {
271ec7c7edbSlinton error("missing address");
272ec7c7edbSlinton } else if (p->op != O_LCON and p->op != O_QLINE) {
273ec7c7edbSlinton beginerrmsg();
274ec7c7edbSlinton fprintf(stderr, "expected address, found \"");
275ec7c7edbSlinton prtree(stderr, p);
276ec7c7edbSlinton fprintf(stderr, "\"");
277ec7c7edbSlinton enderrmsg();
278ec7c7edbSlinton }
279ec7c7edbSlinton }
280