19660Slinton /* Copyright (c) 1982 Regents of the University of California */ 29660Slinton 3*14444Slinton static char sccsid[] = "@(#)check.c 1.5 08/10/83"; 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 { 969861Slinton 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) { 116*14444Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { 1179660Slinton beginerrmsg(); 1189660Slinton fprintf(stderr, "expected variable, found "); 1199660Slinton prtree(stderr, exp); 1209660Slinton enderrmsg(); 1219660Slinton } 1229660Slinton chkblock(place); 1239660Slinton } else if (place->op == O_SYM) { 1249660Slinton chkblock(place); 1259660Slinton } else { 1269660Slinton if (p->op == O_STOP) { 1279660Slinton chkline(place); 1289660Slinton } else { 1299660Slinton chkaddr(place); 1309660Slinton } 1319660Slinton } 1329660Slinton } 1339660Slinton 1349660Slinton /* 1359660Slinton * Check to see that the given node specifies some subprogram. 1369660Slinton * Nil is ok since that means the entire program. 1379660Slinton */ 1389660Slinton 1399660Slinton private chkblock(b) 1409660Slinton Node b; 1419660Slinton { 1429660Slinton if (b != nil) { 1439660Slinton if (b->op != O_SYM) { 1449660Slinton beginerrmsg(); 1459660Slinton fprintf(stderr, "expected subprogram, found "); 1469660Slinton prtree(stderr, b); 1479660Slinton enderrmsg(); 1489660Slinton } else if (not isblock(b->value.sym) or ismodule(b->value.sym)) { 1499660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 1509660Slinton } 1519660Slinton } 1529660Slinton } 1539660Slinton 1549660Slinton /* 1559660Slinton * Check to make sure a node corresponds to a source line. 1569660Slinton */ 1579660Slinton 1589660Slinton private chkline(p) 1599660Slinton Node p; 1609660Slinton { 1619660Slinton if (p == nil) { 1629660Slinton error("missing line"); 1639660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 1649660Slinton error("expected source line number, found \"%t\"", p); 1659660Slinton } 1669660Slinton } 1679660Slinton 1689660Slinton /* 1699660Slinton * Check to make sure a node corresponds to an address. 1709660Slinton */ 1719660Slinton 1729660Slinton private chkaddr(p) 1739660Slinton Node p; 1749660Slinton { 1759660Slinton if (p == nil) { 1769660Slinton error("missing address"); 1779660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 1789660Slinton beginerrmsg(); 1799660Slinton fprintf(stderr, "expected address, found \""); 1809660Slinton prtree(stderr, p); 1819660Slinton fprintf(stderr, "\""); 1829660Slinton enderrmsg(); 1839660Slinton } 1849660Slinton } 185