-/* Copyright (c) 1982 Regents of the University of California */
+/*
+ * Copyright (c) 1983 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
-static char sccsid[] = "@(#)check.c 1.2 %G%";
+#ifndef lint
+static char sccsid[] = "@(#)check.c 5.2 (Berkeley) %G%";
+#endif not lint
+
+static char rcsid[] = "$Header: check.c,v 1.5 84/12/26 10:38:35 linton Exp $";
/*
* Check a tree for semantic correctness.
#include "object.h"
#include "mappings.h"
#include "process.h"
+#include <signal.h>
#ifndef public
#endif
public check(p)
register Node p;
{
+ Node p1, p2;
Address addr;
Symbol f;
checkref(p);
switch (p->op) {
+ case O_ASSIGN:
+ p1 = p->value.arg[0];
+ p2 = p->value.arg[1];
+ if (varIsSet("$unsafeassign")) {
+ if (size(p1->nodetype) != size(p2->nodetype)) {
+ error("incompatible sizes");
+ }
+ } else if (not compatible(p1->nodetype, p2->nodetype)) {
+ error("incompatible types");
+ }
+ break;
+
+ case O_CATCH:
+ case O_IGNORE:
+ if (p->value.lcon < 0 or p->value.lcon > NSIG) {
+ error("invalid signal number");
+ }
+ break;
+
+ case O_CONT:
+ if (p->value.lcon != DEFSIG and (
+ p->value.lcon < 0 or p->value.lcon > NSIG)
+ ) {
+ error("invalid signal number");
+ }
+ break;
+
+ case O_DUMP:
+ if (p->value.arg[0] != nil) {
+ if (p->value.arg[0]->op == O_SYM) {
+ f = p->value.arg[0]->value.sym;
+ if (not isblock(f)) {
+ error("\"%s\" is not a block", symname(f));
+ }
+ } else {
+ beginerrmsg();
+ fprintf(stderr, "expected a symbol, found \"");
+ prtree(stderr, p->value.arg[0]);
+ fprintf(stderr, "\"");
+ enderrmsg();
+ }
+ }
+ break;
+
case O_LIST:
if (p->value.arg[0]->op == O_SYM) {
f = p->value.arg[0]->value.sym;
chkstop(p);
break;
+ case O_CALLPROC:
+ case O_CALL:
+ if (not isroutine(p->value.arg[0]->nodetype)) {
+ beginerrmsg();
+ fprintf(stderr, "\"");
+ prtree(stderr, p->value.arg[0]);
+ fprintf(stderr, "\" not call-able");
+ enderrmsg();
+ }
+ break;
+
+ case O_WHEREIS:
+ if (p->value.arg[0]->op == O_SYM and
+ p->value.arg[0]->value.sym == nil) {
+ error("symbol not defined");
+ }
+ break;
+
default:
break;
}
chkaddr(place);
}
} else {
- if (exp->op != O_RVAL and exp->op != O_SYM) {
+ if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) {
error("can't trace expressions");
}
chkblock(place);
place = p->value.arg[1];
cond = p->value.arg[2];
if (exp != nil) {
- if (exp->op != O_RVAL and exp->op != O_SYM) {
+ if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) {
beginerrmsg();
fprintf(stderr, "expected variable, found ");
prtree(stderr, exp);
enderrmsg();
}
chkblock(place);
- } else if (cond != nil) {
- chkblock(place);
- } else if (place->op == O_SYM) {
- chkblock(place);
- } else {
- if (p->op == O_STOP) {
- chkline(place);
+ } else if (place != nil) {
+ if (place->op == O_SYM) {
+ chkblock(place);
} else {
- chkaddr(place);
+ if (p->op == O_STOP) {
+ chkline(place);
+ } else {
+ chkaddr(place);
+ }
}
}
}
private chkblock(b)
Node b;
{
+ Symbol p, outer;
+
if (b != nil) {
if (b->op != O_SYM) {
beginerrmsg();
fprintf(stderr, "expected subprogram, found ");
prtree(stderr, b);
enderrmsg();
- } else if (not isblock(b->value.sym) or ismodule(b->value.sym)) {
+ } else if (ismodule(b->value.sym)) {
+ outer = b->value.sym;
+ while (outer != nil) {
+ find(p, outer->name) where p->block == outer endfind(p);
+ if (p == nil) {
+ outer = nil;
+ error("\"%s\" is not a subprogram", symname(b->value.sym));
+ } else if (ismodule(p)) {
+ outer = p;
+ } else {
+ outer = nil;
+ b->value.sym = p;
+ }
+ }
+ } else if (
+ b->value.sym->class == VAR and
+ b->value.sym->name == b->value.sym->block->name and
+ b->value.sym->block->class == FUNC
+ ) {
+ b->value.sym = b->value.sym->block;
+ } else if (not isblock(b->value.sym)) {
error("\"%s\" is not a subprogram", symname(b->value.sym));
}
}