19660Slinton /* Copyright (c) 1982 Regents of the University of California */ 29660Slinton 3*9861Slinton static char sccsid[] = "@(#)check.c 1.3 12/20/82"; 49660Slinton 59660Slinton /* 69660Slinton * Check a tree for semantic correctness. 79660Slinton */ 89660Slinton 99660Slinton #include "defs.h" 109660Slinton #include "tree.h" 119660Slinton #include "operators.h" 129660Slinton #include "events.h" 139660Slinton #include "symbols.h" 149660Slinton #include "scanner.h" 159660Slinton #include "source.h" 169660Slinton #include "object.h" 179660Slinton #include "mappings.h" 189660Slinton #include "process.h" 199660Slinton 209660Slinton #ifndef public 219660Slinton #endif 229660Slinton 239660Slinton /* 249660Slinton * Check that the nodes in a tree have the correct arguments 259660Slinton * in order to be evaluated. Basically the error checking here 269660Slinton * frees the evaluation routines from worrying about anything 279660Slinton * except dynamic errors, e.g. subscript out of range. 289660Slinton */ 299660Slinton 309660Slinton public check(p) 319660Slinton register Node p; 329660Slinton { 339660Slinton Address addr; 349660Slinton Symbol f; 359660Slinton 369660Slinton checkref(p); 379660Slinton switch (p->op) { 389660Slinton case O_LIST: 399660Slinton if (p->value.arg[0]->op == O_SYM) { 409660Slinton f = p->value.arg[0]->value.sym; 419660Slinton if (not isblock(f) or ismodule(f)) { 429660Slinton error("\"%s\" is not a procedure or function", symname(f)); 439660Slinton } 449660Slinton addr = firstline(f); 459660Slinton if (addr == NOADDR) { 469660Slinton error("\"%s\" is empty", symname(f)); 479660Slinton } 489660Slinton } 499660Slinton break; 509660Slinton 519660Slinton case O_TRACE: 529660Slinton case O_TRACEI: 539660Slinton chktrace(p); 549660Slinton break; 559660Slinton 569660Slinton case O_STOP: 579660Slinton case O_STOPI: 589660Slinton chkstop(p); 599660Slinton break; 609660Slinton 619660Slinton default: 629660Slinton break; 639660Slinton } 649660Slinton } 659660Slinton 669660Slinton /* 679660Slinton * Check arguments to a trace command. 689660Slinton */ 699660Slinton 709660Slinton private chktrace(p) 719660Slinton Node p; 729660Slinton { 739660Slinton Node exp, place, cond; 749660Slinton 759660Slinton exp = p->value.arg[0]; 769660Slinton place = p->value.arg[1]; 779660Slinton cond = p->value.arg[2]; 789660Slinton if (exp == nil) { 799660Slinton chkblock(place); 809660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 819660Slinton if (place != nil) { 829660Slinton error("unexpected \"at\" or \"in\""); 839660Slinton } 849660Slinton if (p->op == O_TRACE) { 859660Slinton chkline(exp); 869660Slinton } else { 879660Slinton chkaddr(exp); 889660Slinton } 899660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 909660Slinton if (p->op == O_TRACE) { 919660Slinton chkline(place); 929660Slinton } else { 939660Slinton chkaddr(place); 949660Slinton } 959660Slinton } else { 96*9861Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { 979660Slinton error("can't trace expressions"); 989660Slinton } 999660Slinton chkblock(place); 1009660Slinton } 1019660Slinton } 1029660Slinton 1039660Slinton /* 1049660Slinton * Check arguments to a stop command. 1059660Slinton */ 1069660Slinton 1079660Slinton private chkstop(p) 1089660Slinton Node p; 1099660Slinton { 1109660Slinton Node exp, place, cond; 1119660Slinton 1129660Slinton exp = p->value.arg[0]; 1139660Slinton place = p->value.arg[1]; 1149660Slinton cond = p->value.arg[2]; 1159660Slinton if (exp != nil) { 1169660Slinton if (exp->op != O_RVAL and exp->op != O_SYM) { 1179660Slinton beginerrmsg(); 1189660Slinton fprintf(stderr, "expected variable, found "); 1199660Slinton prtree(stderr, exp); 1209660Slinton enderrmsg(); 1219660Slinton } 1229660Slinton chkblock(place); 1239660Slinton } else if (cond != nil) { 1249660Slinton chkblock(place); 1259660Slinton } else if (place->op == O_SYM) { 1269660Slinton chkblock(place); 1279660Slinton } else { 1289660Slinton if (p->op == O_STOP) { 1299660Slinton chkline(place); 1309660Slinton } else { 1319660Slinton chkaddr(place); 1329660Slinton } 1339660Slinton } 1349660Slinton } 1359660Slinton 1369660Slinton /* 1379660Slinton * Check to see that the given node specifies some subprogram. 1389660Slinton * Nil is ok since that means the entire program. 1399660Slinton */ 1409660Slinton 1419660Slinton private chkblock(b) 1429660Slinton Node b; 1439660Slinton { 1449660Slinton if (b != nil) { 1459660Slinton if (b->op != O_SYM) { 1469660Slinton beginerrmsg(); 1479660Slinton fprintf(stderr, "expected subprogram, found "); 1489660Slinton prtree(stderr, b); 1499660Slinton enderrmsg(); 1509660Slinton } else if (not isblock(b->value.sym) or ismodule(b->value.sym)) { 1519660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 1529660Slinton } 1539660Slinton } 1549660Slinton } 1559660Slinton 1569660Slinton /* 1579660Slinton * Check to make sure a node corresponds to a source line. 1589660Slinton */ 1599660Slinton 1609660Slinton private chkline(p) 1619660Slinton Node p; 1629660Slinton { 1639660Slinton if (p == nil) { 1649660Slinton error("missing line"); 1659660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 1669660Slinton error("expected source line number, found \"%t\"", p); 1679660Slinton } 1689660Slinton } 1699660Slinton 1709660Slinton /* 1719660Slinton * Check to make sure a node corresponds to an address. 1729660Slinton */ 1739660Slinton 1749660Slinton private chkaddr(p) 1759660Slinton Node p; 1769660Slinton { 1779660Slinton if (p == nil) { 1789660Slinton error("missing address"); 1799660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 1809660Slinton beginerrmsg(); 1819660Slinton fprintf(stderr, "expected address, found \""); 1829660Slinton prtree(stderr, p); 1839660Slinton fprintf(stderr, "\""); 1849660Slinton enderrmsg(); 1859660Slinton } 1869660Slinton } 187