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