1*21600Sdist /* 2*21600Sdist * Copyright (c) 1983 Regents of the University of California. 3*21600Sdist * All rights reserved. The Berkeley software License Agreement 4*21600Sdist * specifies the terms and conditions for redistribution. 5*21600Sdist */ 69660Slinton 7*21600Sdist #ifndef lint 8*21600Sdist static char sccsid[] = "@(#)check.c 5.1 (Berkeley) 05/31/85"; 9*21600Sdist #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]; 5118214Slinton if (not compatible(p1->nodetype, p2->nodetype)) { 5218214Slinton error("incompatible types"); 5318214Slinton } 5418214Slinton break; 5518214Slinton 5618214Slinton case O_CATCH: 5718214Slinton case O_IGNORE: 5818214Slinton if (p->value.lcon < 0 or p->value.lcon > NSIG) { 5918214Slinton error("invalid signal number"); 6018214Slinton } 6118214Slinton break; 6218214Slinton 6318214Slinton case O_CONT: 6418214Slinton if (p->value.lcon != DEFSIG and ( 6518214Slinton p->value.lcon < 0 or p->value.lcon > NSIG) 6618214Slinton ) { 6718214Slinton error("invalid signal number"); 6818214Slinton } 6918214Slinton break; 7018214Slinton 7118214Slinton case O_DUMP: 7218214Slinton if (p->value.arg[0] != nil) { 7318214Slinton if (p->value.arg[0]->op == O_SYM) { 7418214Slinton f = p->value.arg[0]->value.sym; 7518214Slinton if (not isblock(f)) { 7618214Slinton error("\"%s\" is not a block", symname(f)); 7718214Slinton } 7818214Slinton } else { 7918214Slinton beginerrmsg(); 8018214Slinton fprintf(stderr, "expected a symbol, found \""); 8118214Slinton prtree(stderr, p->value.arg[0]); 8218214Slinton fprintf(stderr, "\""); 8318214Slinton enderrmsg(); 8418214Slinton } 8518214Slinton } 8618214Slinton break; 8718214Slinton 889660Slinton case O_LIST: 899660Slinton if (p->value.arg[0]->op == O_SYM) { 909660Slinton f = p->value.arg[0]->value.sym; 919660Slinton if (not isblock(f) or ismodule(f)) { 929660Slinton error("\"%s\" is not a procedure or function", symname(f)); 939660Slinton } 949660Slinton addr = firstline(f); 959660Slinton if (addr == NOADDR) { 969660Slinton error("\"%s\" is empty", symname(f)); 979660Slinton } 989660Slinton } 999660Slinton break; 1009660Slinton 1019660Slinton case O_TRACE: 1029660Slinton case O_TRACEI: 1039660Slinton chktrace(p); 1049660Slinton break; 1059660Slinton 1069660Slinton case O_STOP: 1079660Slinton case O_STOPI: 1089660Slinton chkstop(p); 1099660Slinton break; 1109660Slinton 11118214Slinton case O_CALLPROC: 11216607Ssam case O_CALL: 11316607Ssam if (not isroutine(p->value.arg[0]->nodetype)) { 11416607Ssam beginerrmsg(); 11516607Ssam fprintf(stderr, "\""); 11616607Ssam prtree(stderr, p->value.arg[0]); 11716607Ssam fprintf(stderr, "\" not call-able"); 11816607Ssam enderrmsg(); 11916607Ssam } 12016607Ssam break; 12116607Ssam 12218214Slinton case O_WHEREIS: 12318214Slinton if (p->value.arg[0]->op == O_SYM and 12418214Slinton p->value.arg[0]->value.sym == nil) { 12518214Slinton error("symbol not defined"); 12618214Slinton } 12718214Slinton break; 12818214Slinton 1299660Slinton default: 1309660Slinton break; 1319660Slinton } 1329660Slinton } 1339660Slinton 1349660Slinton /* 1359660Slinton * Check arguments to a trace command. 1369660Slinton */ 1379660Slinton 1389660Slinton private chktrace(p) 1399660Slinton Node p; 1409660Slinton { 1419660Slinton Node exp, place, cond; 1429660Slinton 1439660Slinton exp = p->value.arg[0]; 1449660Slinton place = p->value.arg[1]; 1459660Slinton cond = p->value.arg[2]; 1469660Slinton if (exp == nil) { 1479660Slinton chkblock(place); 1489660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 1499660Slinton if (place != nil) { 1509660Slinton error("unexpected \"at\" or \"in\""); 1519660Slinton } 1529660Slinton if (p->op == O_TRACE) { 1539660Slinton chkline(exp); 1549660Slinton } else { 1559660Slinton chkaddr(exp); 1569660Slinton } 1579660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 1589660Slinton if (p->op == O_TRACE) { 1599660Slinton chkline(place); 1609660Slinton } else { 1619660Slinton chkaddr(place); 1629660Slinton } 1639660Slinton } else { 1649861Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { 1659660Slinton error("can't trace expressions"); 1669660Slinton } 1679660Slinton chkblock(place); 1689660Slinton } 1699660Slinton } 1709660Slinton 1719660Slinton /* 1729660Slinton * Check arguments to a stop command. 1739660Slinton */ 1749660Slinton 1759660Slinton private chkstop(p) 1769660Slinton Node p; 1779660Slinton { 1789660Slinton Node exp, place, cond; 1799660Slinton 1809660Slinton exp = p->value.arg[0]; 1819660Slinton place = p->value.arg[1]; 1829660Slinton cond = p->value.arg[2]; 1839660Slinton if (exp != nil) { 18414444Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { 1859660Slinton beginerrmsg(); 1869660Slinton fprintf(stderr, "expected variable, found "); 1879660Slinton prtree(stderr, exp); 1889660Slinton enderrmsg(); 1899660Slinton } 1909660Slinton chkblock(place); 19116607Ssam } else if (place != nil) { 19216607Ssam if (place->op == O_SYM) { 19316607Ssam chkblock(place); 1949660Slinton } else { 19516607Ssam if (p->op == O_STOP) { 19616607Ssam chkline(place); 19716607Ssam } else { 19816607Ssam chkaddr(place); 19916607Ssam } 2009660Slinton } 2019660Slinton } 2029660Slinton } 2039660Slinton 2049660Slinton /* 2059660Slinton * Check to see that the given node specifies some subprogram. 2069660Slinton * Nil is ok since that means the entire program. 2079660Slinton */ 2089660Slinton 2099660Slinton private chkblock(b) 2109660Slinton Node b; 2119660Slinton { 21216607Ssam Symbol p, outer; 21316607Ssam 2149660Slinton if (b != nil) { 2159660Slinton if (b->op != O_SYM) { 2169660Slinton beginerrmsg(); 2179660Slinton fprintf(stderr, "expected subprogram, found "); 2189660Slinton prtree(stderr, b); 2199660Slinton enderrmsg(); 22016607Ssam } else if (ismodule(b->value.sym)) { 22116607Ssam outer = b->value.sym; 22216607Ssam while (outer != nil) { 22316607Ssam find(p, outer->name) where p->block == outer endfind(p); 22416607Ssam if (p == nil) { 22516607Ssam outer = nil; 22616607Ssam error("\"%s\" is not a subprogram", symname(b->value.sym)); 22716607Ssam } else if (ismodule(p)) { 22816607Ssam outer = p; 22916607Ssam } else { 23016607Ssam outer = nil; 23116607Ssam b->value.sym = p; 23216607Ssam } 23316607Ssam } 23418214Slinton } else if ( 23518214Slinton b->value.sym->class == VAR and 23618214Slinton b->value.sym->name == b->value.sym->block->name and 23718214Slinton b->value.sym->block->class == FUNC 23818214Slinton ) { 23918214Slinton b->value.sym = b->value.sym->block; 24016607Ssam } else if (not isblock(b->value.sym)) { 2419660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 2429660Slinton } 2439660Slinton } 2449660Slinton } 2459660Slinton 2469660Slinton /* 2479660Slinton * Check to make sure a node corresponds to a source line. 2489660Slinton */ 2499660Slinton 2509660Slinton private chkline(p) 2519660Slinton Node p; 2529660Slinton { 2539660Slinton if (p == nil) { 2549660Slinton error("missing line"); 2559660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 2569660Slinton error("expected source line number, found \"%t\"", p); 2579660Slinton } 2589660Slinton } 2599660Slinton 2609660Slinton /* 2619660Slinton * Check to make sure a node corresponds to an address. 2629660Slinton */ 2639660Slinton 2649660Slinton private chkaddr(p) 2659660Slinton Node p; 2669660Slinton { 2679660Slinton if (p == nil) { 2689660Slinton error("missing address"); 2699660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 2709660Slinton beginerrmsg(); 2719660Slinton fprintf(stderr, "expected address, found \""); 2729660Slinton prtree(stderr, p); 2739660Slinton fprintf(stderr, "\""); 2749660Slinton enderrmsg(); 2759660Slinton } 2769660Slinton } 277