xref: /original-bsd/old/dbx/check.c (revision 1808f06c)
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