121600Sdist /* 221600Sdist * Copyright (c) 1983 Regents of the University of California. 321600Sdist * All rights reserved. The Berkeley software License Agreement 421600Sdist * specifies the terms and conditions for redistribution. 521600Sdist */ 69660Slinton 721600Sdist #ifndef lint 8*25811Sdonn static char sccsid[] = "@(#)check.c 5.2 (Berkeley) 01/10/86"; 921600Sdist #endif not lint 109660Slinton 1118214Slinton static char rcsid[] = "$Header: check.c,v 1.5 84/12/26 10:38:35 linton Exp $"; 1218214Slinton 139660Slinton /* 149660Slinton * Check a tree for semantic correctness. 159660Slinton */ 169660Slinton 179660Slinton #include "defs.h" 189660Slinton #include "tree.h" 199660Slinton #include "operators.h" 209660Slinton #include "events.h" 219660Slinton #include "symbols.h" 229660Slinton #include "scanner.h" 239660Slinton #include "source.h" 249660Slinton #include "object.h" 259660Slinton #include "mappings.h" 269660Slinton #include "process.h" 2718214Slinton #include <signal.h> 289660Slinton 299660Slinton #ifndef public 309660Slinton #endif 319660Slinton 329660Slinton /* 339660Slinton * Check that the nodes in a tree have the correct arguments 349660Slinton * in order to be evaluated. Basically the error checking here 359660Slinton * frees the evaluation routines from worrying about anything 369660Slinton * except dynamic errors, e.g. subscript out of range. 379660Slinton */ 389660Slinton 399660Slinton public check(p) 409660Slinton register Node p; 419660Slinton { 4218214Slinton Node p1, p2; 439660Slinton Address addr; 449660Slinton Symbol f; 459660Slinton 469660Slinton checkref(p); 479660Slinton switch (p->op) { 4818214Slinton case O_ASSIGN: 4918214Slinton p1 = p->value.arg[0]; 5018214Slinton p2 = p->value.arg[1]; 51*25811Sdonn if (varIsSet("$unsafeassign")) { 52*25811Sdonn if (size(p1->nodetype) != size(p2->nodetype)) { 53*25811Sdonn error("incompatible sizes"); 54*25811Sdonn } 55*25811Sdonn } else if (not compatible(p1->nodetype, p2->nodetype)) { 5618214Slinton error("incompatible types"); 5718214Slinton } 5818214Slinton break; 5918214Slinton 6018214Slinton case O_CATCH: 6118214Slinton case O_IGNORE: 6218214Slinton if (p->value.lcon < 0 or p->value.lcon > NSIG) { 6318214Slinton error("invalid signal number"); 6418214Slinton } 6518214Slinton break; 6618214Slinton 6718214Slinton case O_CONT: 6818214Slinton if (p->value.lcon != DEFSIG and ( 6918214Slinton p->value.lcon < 0 or p->value.lcon > NSIG) 7018214Slinton ) { 7118214Slinton error("invalid signal number"); 7218214Slinton } 7318214Slinton break; 7418214Slinton 7518214Slinton case O_DUMP: 7618214Slinton if (p->value.arg[0] != nil) { 7718214Slinton if (p->value.arg[0]->op == O_SYM) { 7818214Slinton f = p->value.arg[0]->value.sym; 7918214Slinton if (not isblock(f)) { 8018214Slinton error("\"%s\" is not a block", symname(f)); 8118214Slinton } 8218214Slinton } else { 8318214Slinton beginerrmsg(); 8418214Slinton fprintf(stderr, "expected a symbol, found \""); 8518214Slinton prtree(stderr, p->value.arg[0]); 8618214Slinton fprintf(stderr, "\""); 8718214Slinton enderrmsg(); 8818214Slinton } 8918214Slinton } 9018214Slinton break; 9118214Slinton 929660Slinton case O_LIST: 939660Slinton if (p->value.arg[0]->op == O_SYM) { 949660Slinton f = p->value.arg[0]->value.sym; 959660Slinton if (not isblock(f) or ismodule(f)) { 969660Slinton error("\"%s\" is not a procedure or function", symname(f)); 979660Slinton } 989660Slinton addr = firstline(f); 999660Slinton if (addr == NOADDR) { 1009660Slinton error("\"%s\" is empty", symname(f)); 1019660Slinton } 1029660Slinton } 1039660Slinton break; 1049660Slinton 1059660Slinton case O_TRACE: 1069660Slinton case O_TRACEI: 1079660Slinton chktrace(p); 1089660Slinton break; 1099660Slinton 1109660Slinton case O_STOP: 1119660Slinton case O_STOPI: 1129660Slinton chkstop(p); 1139660Slinton break; 1149660Slinton 11518214Slinton case O_CALLPROC: 11616607Ssam case O_CALL: 11716607Ssam if (not isroutine(p->value.arg[0]->nodetype)) { 11816607Ssam beginerrmsg(); 11916607Ssam fprintf(stderr, "\""); 12016607Ssam prtree(stderr, p->value.arg[0]); 12116607Ssam fprintf(stderr, "\" not call-able"); 12216607Ssam enderrmsg(); 12316607Ssam } 12416607Ssam break; 12516607Ssam 12618214Slinton case O_WHEREIS: 12718214Slinton if (p->value.arg[0]->op == O_SYM and 12818214Slinton p->value.arg[0]->value.sym == nil) { 12918214Slinton error("symbol not defined"); 13018214Slinton } 13118214Slinton break; 13218214Slinton 1339660Slinton default: 1349660Slinton break; 1359660Slinton } 1369660Slinton } 1379660Slinton 1389660Slinton /* 1399660Slinton * Check arguments to a trace command. 1409660Slinton */ 1419660Slinton 1429660Slinton private chktrace(p) 1439660Slinton Node p; 1449660Slinton { 1459660Slinton Node exp, place, cond; 1469660Slinton 1479660Slinton exp = p->value.arg[0]; 1489660Slinton place = p->value.arg[1]; 1499660Slinton cond = p->value.arg[2]; 1509660Slinton if (exp == nil) { 1519660Slinton chkblock(place); 1529660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 1539660Slinton if (place != nil) { 1549660Slinton error("unexpected \"at\" or \"in\""); 1559660Slinton } 1569660Slinton if (p->op == O_TRACE) { 1579660Slinton chkline(exp); 1589660Slinton } else { 1599660Slinton chkaddr(exp); 1609660Slinton } 1619660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 1629660Slinton if (p->op == O_TRACE) { 1639660Slinton chkline(place); 1649660Slinton } else { 1659660Slinton chkaddr(place); 1669660Slinton } 1679660Slinton } else { 1689861Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { 1699660Slinton error("can't trace expressions"); 1709660Slinton } 1719660Slinton chkblock(place); 1729660Slinton } 1739660Slinton } 1749660Slinton 1759660Slinton /* 1769660Slinton * Check arguments to a stop command. 1779660Slinton */ 1789660Slinton 1799660Slinton private chkstop(p) 1809660Slinton Node p; 1819660Slinton { 1829660Slinton Node exp, place, cond; 1839660Slinton 1849660Slinton exp = p->value.arg[0]; 1859660Slinton place = p->value.arg[1]; 1869660Slinton cond = p->value.arg[2]; 1879660Slinton if (exp != nil) { 18814444Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { 1899660Slinton beginerrmsg(); 1909660Slinton fprintf(stderr, "expected variable, found "); 1919660Slinton prtree(stderr, exp); 1929660Slinton enderrmsg(); 1939660Slinton } 1949660Slinton chkblock(place); 19516607Ssam } else if (place != nil) { 19616607Ssam if (place->op == O_SYM) { 19716607Ssam chkblock(place); 1989660Slinton } else { 19916607Ssam if (p->op == O_STOP) { 20016607Ssam chkline(place); 20116607Ssam } else { 20216607Ssam chkaddr(place); 20316607Ssam } 2049660Slinton } 2059660Slinton } 2069660Slinton } 2079660Slinton 2089660Slinton /* 2099660Slinton * Check to see that the given node specifies some subprogram. 2109660Slinton * Nil is ok since that means the entire program. 2119660Slinton */ 2129660Slinton 2139660Slinton private chkblock(b) 2149660Slinton Node b; 2159660Slinton { 21616607Ssam Symbol p, outer; 21716607Ssam 2189660Slinton if (b != nil) { 2199660Slinton if (b->op != O_SYM) { 2209660Slinton beginerrmsg(); 2219660Slinton fprintf(stderr, "expected subprogram, found "); 2229660Slinton prtree(stderr, b); 2239660Slinton enderrmsg(); 22416607Ssam } else if (ismodule(b->value.sym)) { 22516607Ssam outer = b->value.sym; 22616607Ssam while (outer != nil) { 22716607Ssam find(p, outer->name) where p->block == outer endfind(p); 22816607Ssam if (p == nil) { 22916607Ssam outer = nil; 23016607Ssam error("\"%s\" is not a subprogram", symname(b->value.sym)); 23116607Ssam } else if (ismodule(p)) { 23216607Ssam outer = p; 23316607Ssam } else { 23416607Ssam outer = nil; 23516607Ssam b->value.sym = p; 23616607Ssam } 23716607Ssam } 23818214Slinton } else if ( 23918214Slinton b->value.sym->class == VAR and 24018214Slinton b->value.sym->name == b->value.sym->block->name and 24118214Slinton b->value.sym->block->class == FUNC 24218214Slinton ) { 24318214Slinton b->value.sym = b->value.sym->block; 24416607Ssam } else if (not isblock(b->value.sym)) { 2459660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 2469660Slinton } 2479660Slinton } 2489660Slinton } 2499660Slinton 2509660Slinton /* 2519660Slinton * Check to make sure a node corresponds to a source line. 2529660Slinton */ 2539660Slinton 2549660Slinton private chkline(p) 2559660Slinton Node p; 2569660Slinton { 2579660Slinton if (p == nil) { 2589660Slinton error("missing line"); 2599660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 2609660Slinton error("expected source line number, found \"%t\"", p); 2619660Slinton } 2629660Slinton } 2639660Slinton 2649660Slinton /* 2659660Slinton * Check to make sure a node corresponds to an address. 2669660Slinton */ 2679660Slinton 2689660Slinton private chkaddr(p) 2699660Slinton Node p; 2709660Slinton { 2719660Slinton if (p == nil) { 2729660Slinton error("missing address"); 2739660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 2749660Slinton beginerrmsg(); 2759660Slinton fprintf(stderr, "expected address, found \""); 2769660Slinton prtree(stderr, p); 2779660Slinton fprintf(stderr, "\""); 2789660Slinton enderrmsg(); 2799660Slinton } 2809660Slinton } 281