121600Sdist /* 2*38105Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*38105Sbostic * All rights reserved. 4*38105Sbostic * 5*38105Sbostic * Redistribution and use in source and binary forms are permitted 6*38105Sbostic * provided that the above copyright notice and this paragraph are 7*38105Sbostic * duplicated in all such forms and that any documentation, 8*38105Sbostic * advertising materials, and other materials related to such 9*38105Sbostic * distribution and use acknowledge that the software was developed 10*38105Sbostic * by the University of California, Berkeley. The name of the 11*38105Sbostic * University may not be used to endorse or promote products derived 12*38105Sbostic * from this software without specific prior written permission. 13*38105Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*38105Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*38105Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621600Sdist */ 179660Slinton 1821600Sdist #ifndef lint 19*38105Sbostic static char sccsid[] = "@(#)check.c 5.3 (Berkeley) 05/23/89"; 20*38105Sbostic #endif /* not lint */ 219660Slinton 229660Slinton /* 239660Slinton * Check a tree for semantic correctness. 249660Slinton */ 259660Slinton 269660Slinton #include "defs.h" 279660Slinton #include "tree.h" 289660Slinton #include "operators.h" 299660Slinton #include "events.h" 309660Slinton #include "symbols.h" 319660Slinton #include "scanner.h" 329660Slinton #include "source.h" 339660Slinton #include "object.h" 349660Slinton #include "mappings.h" 359660Slinton #include "process.h" 3618214Slinton #include <signal.h> 379660Slinton 389660Slinton #ifndef public 399660Slinton #endif 409660Slinton 419660Slinton /* 429660Slinton * Check that the nodes in a tree have the correct arguments 439660Slinton * in order to be evaluated. Basically the error checking here 449660Slinton * frees the evaluation routines from worrying about anything 459660Slinton * except dynamic errors, e.g. subscript out of range. 469660Slinton */ 479660Slinton 489660Slinton public check(p) 499660Slinton register Node p; 509660Slinton { 5118214Slinton Node p1, p2; 529660Slinton Address addr; 539660Slinton Symbol f; 549660Slinton 559660Slinton checkref(p); 569660Slinton switch (p->op) { 5718214Slinton case O_ASSIGN: 5818214Slinton p1 = p->value.arg[0]; 5918214Slinton p2 = p->value.arg[1]; 6025811Sdonn if (varIsSet("$unsafeassign")) { 6125811Sdonn if (size(p1->nodetype) != size(p2->nodetype)) { 6225811Sdonn error("incompatible sizes"); 6325811Sdonn } 6425811Sdonn } else if (not compatible(p1->nodetype, p2->nodetype)) { 6518214Slinton error("incompatible types"); 6618214Slinton } 6718214Slinton break; 6818214Slinton 6918214Slinton case O_CATCH: 7018214Slinton case O_IGNORE: 7118214Slinton if (p->value.lcon < 0 or p->value.lcon > NSIG) { 7218214Slinton error("invalid signal number"); 7318214Slinton } 7418214Slinton break; 7518214Slinton 7618214Slinton case O_CONT: 7718214Slinton if (p->value.lcon != DEFSIG and ( 7818214Slinton p->value.lcon < 0 or p->value.lcon > NSIG) 7918214Slinton ) { 8018214Slinton error("invalid signal number"); 8118214Slinton } 8218214Slinton break; 8318214Slinton 8418214Slinton case O_DUMP: 8518214Slinton if (p->value.arg[0] != nil) { 8618214Slinton if (p->value.arg[0]->op == O_SYM) { 8718214Slinton f = p->value.arg[0]->value.sym; 8818214Slinton if (not isblock(f)) { 8918214Slinton error("\"%s\" is not a block", symname(f)); 9018214Slinton } 9118214Slinton } else { 9218214Slinton beginerrmsg(); 9318214Slinton fprintf(stderr, "expected a symbol, found \""); 9418214Slinton prtree(stderr, p->value.arg[0]); 9518214Slinton fprintf(stderr, "\""); 9618214Slinton enderrmsg(); 9718214Slinton } 9818214Slinton } 9918214Slinton break; 10018214Slinton 1019660Slinton case O_LIST: 1029660Slinton if (p->value.arg[0]->op == O_SYM) { 1039660Slinton f = p->value.arg[0]->value.sym; 1049660Slinton if (not isblock(f) or ismodule(f)) { 1059660Slinton error("\"%s\" is not a procedure or function", symname(f)); 1069660Slinton } 1079660Slinton addr = firstline(f); 1089660Slinton if (addr == NOADDR) { 1099660Slinton error("\"%s\" is empty", symname(f)); 1109660Slinton } 1119660Slinton } 1129660Slinton break; 1139660Slinton 1149660Slinton case O_TRACE: 1159660Slinton case O_TRACEI: 1169660Slinton chktrace(p); 1179660Slinton break; 1189660Slinton 1199660Slinton case O_STOP: 1209660Slinton case O_STOPI: 1219660Slinton chkstop(p); 1229660Slinton break; 1239660Slinton 12418214Slinton case O_CALLPROC: 12516607Ssam case O_CALL: 12616607Ssam if (not isroutine(p->value.arg[0]->nodetype)) { 12716607Ssam beginerrmsg(); 12816607Ssam fprintf(stderr, "\""); 12916607Ssam prtree(stderr, p->value.arg[0]); 13016607Ssam fprintf(stderr, "\" not call-able"); 13116607Ssam enderrmsg(); 13216607Ssam } 13316607Ssam break; 13416607Ssam 13518214Slinton case O_WHEREIS: 13618214Slinton if (p->value.arg[0]->op == O_SYM and 13718214Slinton p->value.arg[0]->value.sym == nil) { 13818214Slinton error("symbol not defined"); 13918214Slinton } 14018214Slinton break; 14118214Slinton 1429660Slinton default: 1439660Slinton break; 1449660Slinton } 1459660Slinton } 1469660Slinton 1479660Slinton /* 1489660Slinton * Check arguments to a trace command. 1499660Slinton */ 1509660Slinton 1519660Slinton private chktrace(p) 1529660Slinton Node p; 1539660Slinton { 1549660Slinton Node exp, place, cond; 1559660Slinton 1569660Slinton exp = p->value.arg[0]; 1579660Slinton place = p->value.arg[1]; 1589660Slinton cond = p->value.arg[2]; 1599660Slinton if (exp == nil) { 1609660Slinton chkblock(place); 1619660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 1629660Slinton if (place != nil) { 1639660Slinton error("unexpected \"at\" or \"in\""); 1649660Slinton } 1659660Slinton if (p->op == O_TRACE) { 1669660Slinton chkline(exp); 1679660Slinton } else { 1689660Slinton chkaddr(exp); 1699660Slinton } 1709660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 1719660Slinton if (p->op == O_TRACE) { 1729660Slinton chkline(place); 1739660Slinton } else { 1749660Slinton chkaddr(place); 1759660Slinton } 1769660Slinton } else { 1779861Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { 1789660Slinton error("can't trace expressions"); 1799660Slinton } 1809660Slinton chkblock(place); 1819660Slinton } 1829660Slinton } 1839660Slinton 1849660Slinton /* 1859660Slinton * Check arguments to a stop command. 1869660Slinton */ 1879660Slinton 1889660Slinton private chkstop(p) 1899660Slinton Node p; 1909660Slinton { 1919660Slinton Node exp, place, cond; 1929660Slinton 1939660Slinton exp = p->value.arg[0]; 1949660Slinton place = p->value.arg[1]; 1959660Slinton cond = p->value.arg[2]; 1969660Slinton if (exp != nil) { 19714444Slinton if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { 1989660Slinton beginerrmsg(); 1999660Slinton fprintf(stderr, "expected variable, found "); 2009660Slinton prtree(stderr, exp); 2019660Slinton enderrmsg(); 2029660Slinton } 2039660Slinton chkblock(place); 20416607Ssam } else if (place != nil) { 20516607Ssam if (place->op == O_SYM) { 20616607Ssam chkblock(place); 2079660Slinton } else { 20816607Ssam if (p->op == O_STOP) { 20916607Ssam chkline(place); 21016607Ssam } else { 21116607Ssam chkaddr(place); 21216607Ssam } 2139660Slinton } 2149660Slinton } 2159660Slinton } 2169660Slinton 2179660Slinton /* 2189660Slinton * Check to see that the given node specifies some subprogram. 2199660Slinton * Nil is ok since that means the entire program. 2209660Slinton */ 2219660Slinton 2229660Slinton private chkblock(b) 2239660Slinton Node b; 2249660Slinton { 22516607Ssam Symbol p, outer; 22616607Ssam 2279660Slinton if (b != nil) { 2289660Slinton if (b->op != O_SYM) { 2299660Slinton beginerrmsg(); 2309660Slinton fprintf(stderr, "expected subprogram, found "); 2319660Slinton prtree(stderr, b); 2329660Slinton enderrmsg(); 23316607Ssam } else if (ismodule(b->value.sym)) { 23416607Ssam outer = b->value.sym; 23516607Ssam while (outer != nil) { 23616607Ssam find(p, outer->name) where p->block == outer endfind(p); 23716607Ssam if (p == nil) { 23816607Ssam outer = nil; 23916607Ssam error("\"%s\" is not a subprogram", symname(b->value.sym)); 24016607Ssam } else if (ismodule(p)) { 24116607Ssam outer = p; 24216607Ssam } else { 24316607Ssam outer = nil; 24416607Ssam b->value.sym = p; 24516607Ssam } 24616607Ssam } 24718214Slinton } else if ( 24818214Slinton b->value.sym->class == VAR and 24918214Slinton b->value.sym->name == b->value.sym->block->name and 25018214Slinton b->value.sym->block->class == FUNC 25118214Slinton ) { 25218214Slinton b->value.sym = b->value.sym->block; 25316607Ssam } else if (not isblock(b->value.sym)) { 2549660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 2559660Slinton } 2569660Slinton } 2579660Slinton } 2589660Slinton 2599660Slinton /* 2609660Slinton * Check to make sure a node corresponds to a source line. 2619660Slinton */ 2629660Slinton 2639660Slinton private chkline(p) 2649660Slinton Node p; 2659660Slinton { 2669660Slinton if (p == nil) { 2679660Slinton error("missing line"); 2689660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 2699660Slinton error("expected source line number, found \"%t\"", p); 2709660Slinton } 2719660Slinton } 2729660Slinton 2739660Slinton /* 2749660Slinton * Check to make sure a node corresponds to an address. 2759660Slinton */ 2769660Slinton 2779660Slinton private chkaddr(p) 2789660Slinton Node p; 2799660Slinton { 2809660Slinton if (p == nil) { 2819660Slinton error("missing address"); 2829660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 2839660Slinton beginerrmsg(); 2849660Slinton fprintf(stderr, "expected address, found \""); 2859660Slinton prtree(stderr, p); 2869660Slinton fprintf(stderr, "\""); 2879660Slinton enderrmsg(); 2889660Slinton } 2899660Slinton } 290