19660Slinton /* Copyright (c) 1982 Regents of the University of California */ 29660Slinton 3*16607Ssam static char sccsid[] = "@(#)check.c 1.5 8/10/83"; 49660Slinton 5*16607Ssam static char rcsid[] = "$Header: check.c,v 1.3 84/03/27 10:19:54 linton Exp $"; 6*16607Ssam 79660Slinton /* 89660Slinton * Check a tree for semantic correctness. 99660Slinton */ 109660Slinton 119660Slinton #include "defs.h" 129660Slinton #include "tree.h" 139660Slinton #include "operators.h" 149660Slinton #include "events.h" 159660Slinton #include "symbols.h" 169660Slinton #include "scanner.h" 179660Slinton #include "source.h" 189660Slinton #include "object.h" 199660Slinton #include "mappings.h" 209660Slinton #include "process.h" 219660Slinton 229660Slinton #ifndef public 239660Slinton #endif 249660Slinton 259660Slinton /* 269660Slinton * Check that the nodes in a tree have the correct arguments 279660Slinton * in order to be evaluated. Basically the error checking here 289660Slinton * frees the evaluation routines from worrying about anything 299660Slinton * except dynamic errors, e.g. subscript out of range. 309660Slinton */ 319660Slinton 329660Slinton public check(p) 339660Slinton register Node p; 349660Slinton { 359660Slinton Address addr; 369660Slinton Symbol f; 379660Slinton 389660Slinton checkref(p); 399660Slinton switch (p->op) { 409660Slinton case O_LIST: 419660Slinton if (p->value.arg[0]->op == O_SYM) { 429660Slinton f = p->value.arg[0]->value.sym; 439660Slinton if (not isblock(f) or ismodule(f)) { 449660Slinton error("\"%s\" is not a procedure or function", symname(f)); 459660Slinton } 469660Slinton addr = firstline(f); 479660Slinton if (addr == NOADDR) { 489660Slinton error("\"%s\" is empty", symname(f)); 499660Slinton } 509660Slinton } 519660Slinton break; 529660Slinton 539660Slinton case O_TRACE: 549660Slinton case O_TRACEI: 559660Slinton chktrace(p); 569660Slinton break; 579660Slinton 589660Slinton case O_STOP: 599660Slinton case O_STOPI: 609660Slinton chkstop(p); 619660Slinton break; 629660Slinton 63*16607Ssam case O_CALL: 64*16607Ssam if (not isroutine(p->value.arg[0]->nodetype)) { 65*16607Ssam beginerrmsg(); 66*16607Ssam fprintf(stderr, "\""); 67*16607Ssam prtree(stderr, p->value.arg[0]); 68*16607Ssam fprintf(stderr, "\" not call-able"); 69*16607Ssam enderrmsg(); 70*16607Ssam } 71*16607Ssam break; 72*16607Ssam 739660Slinton default: 749660Slinton break; 759660Slinton } 769660Slinton } 779660Slinton 789660Slinton /* 799660Slinton * Check arguments to a trace command. 809660Slinton */ 819660Slinton 829660Slinton private chktrace(p) 839660Slinton Node p; 849660Slinton { 859660Slinton Node exp, place, cond; 869660Slinton 879660Slinton exp = p->value.arg[0]; 889660Slinton place = p->value.arg[1]; 899660Slinton cond = p->value.arg[2]; 909660Slinton if (exp == nil) { 919660Slinton chkblock(place); 929660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 939660Slinton if (place != nil) { 949660Slinton error("unexpected \"at\" or \"in\""); 959660Slinton } 969660Slinton if (p->op == O_TRACE) { 979660Slinton chkline(exp); 989660Slinton } else { 999660Slinton chkaddr(exp); 1009660Slinton } 1019660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 1029660Slinton if (p->op == O_TRACE) { 1039660Slinton chkline(place); 1049660Slinton } else { 1059660Slinton chkaddr(place); 1069660Slinton } 1079660Slinton } else { 1089861Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { 1099660Slinton error("can't trace expressions"); 1109660Slinton } 1119660Slinton chkblock(place); 1129660Slinton } 1139660Slinton } 1149660Slinton 1159660Slinton /* 1169660Slinton * Check arguments to a stop command. 1179660Slinton */ 1189660Slinton 1199660Slinton private chkstop(p) 1209660Slinton Node p; 1219660Slinton { 1229660Slinton Node exp, place, cond; 1239660Slinton 1249660Slinton exp = p->value.arg[0]; 1259660Slinton place = p->value.arg[1]; 1269660Slinton cond = p->value.arg[2]; 1279660Slinton if (exp != nil) { 12814444Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { 1299660Slinton beginerrmsg(); 1309660Slinton fprintf(stderr, "expected variable, found "); 1319660Slinton prtree(stderr, exp); 1329660Slinton enderrmsg(); 1339660Slinton } 1349660Slinton chkblock(place); 135*16607Ssam } else if (place != nil) { 136*16607Ssam if (place->op == O_SYM) { 137*16607Ssam chkblock(place); 1389660Slinton } else { 139*16607Ssam if (p->op == O_STOP) { 140*16607Ssam chkline(place); 141*16607Ssam } else { 142*16607Ssam chkaddr(place); 143*16607Ssam } 1449660Slinton } 1459660Slinton } 1469660Slinton } 1479660Slinton 1489660Slinton /* 1499660Slinton * Check to see that the given node specifies some subprogram. 1509660Slinton * Nil is ok since that means the entire program. 1519660Slinton */ 1529660Slinton 1539660Slinton private chkblock(b) 1549660Slinton Node b; 1559660Slinton { 156*16607Ssam Symbol p, outer; 157*16607Ssam 1589660Slinton if (b != nil) { 1599660Slinton if (b->op != O_SYM) { 1609660Slinton beginerrmsg(); 1619660Slinton fprintf(stderr, "expected subprogram, found "); 1629660Slinton prtree(stderr, b); 1639660Slinton enderrmsg(); 164*16607Ssam } else if (ismodule(b->value.sym)) { 165*16607Ssam outer = b->value.sym; 166*16607Ssam while (outer != nil) { 167*16607Ssam find(p, outer->name) where p->block == outer endfind(p); 168*16607Ssam if (p == nil) { 169*16607Ssam outer = nil; 170*16607Ssam error("\"%s\" is not a subprogram", symname(b->value.sym)); 171*16607Ssam } else if (ismodule(p)) { 172*16607Ssam outer = p; 173*16607Ssam } else { 174*16607Ssam outer = nil; 175*16607Ssam b->value.sym = p; 176*16607Ssam } 177*16607Ssam } 178*16607Ssam } else if (not isblock(b->value.sym)) { 1799660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 1809660Slinton } 1819660Slinton } 1829660Slinton } 1839660Slinton 1849660Slinton /* 1859660Slinton * Check to make sure a node corresponds to a source line. 1869660Slinton */ 1879660Slinton 1889660Slinton private chkline(p) 1899660Slinton Node p; 1909660Slinton { 1919660Slinton if (p == nil) { 1929660Slinton error("missing line"); 1939660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 1949660Slinton error("expected source line number, found \"%t\"", p); 1959660Slinton } 1969660Slinton } 1979660Slinton 1989660Slinton /* 1999660Slinton * Check to make sure a node corresponds to an address. 2009660Slinton */ 2019660Slinton 2029660Slinton private chkaddr(p) 2039660Slinton Node p; 2049660Slinton { 2059660Slinton if (p == nil) { 2069660Slinton error("missing address"); 2079660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 2089660Slinton beginerrmsg(); 2099660Slinton fprintf(stderr, "expected address, found \""); 2109660Slinton prtree(stderr, p); 2119660Slinton fprintf(stderr, "\""); 2129660Slinton enderrmsg(); 2139660Slinton } 2149660Slinton } 215