1*9660Slinton /* Copyright (c) 1982 Regents of the University of California */ 2*9660Slinton 3*9660Slinton static char sccsid[] = "@(#)@(#)check.c 1.1 12/15/82"; 4*9660Slinton 5*9660Slinton /* 6*9660Slinton * Check a tree for semantic correctness. 7*9660Slinton */ 8*9660Slinton 9*9660Slinton #include "defs.h" 10*9660Slinton #include "tree.h" 11*9660Slinton #include "operators.h" 12*9660Slinton #include "events.h" 13*9660Slinton #include "symbols.h" 14*9660Slinton #include "scanner.h" 15*9660Slinton #include "source.h" 16*9660Slinton #include "object.h" 17*9660Slinton #include "mappings.h" 18*9660Slinton #include "process.h" 19*9660Slinton 20*9660Slinton #ifndef public 21*9660Slinton #endif 22*9660Slinton 23*9660Slinton /* 24*9660Slinton * Check that the nodes in a tree have the correct arguments 25*9660Slinton * in order to be evaluated. Basically the error checking here 26*9660Slinton * frees the evaluation routines from worrying about anything 27*9660Slinton * except dynamic errors, e.g. subscript out of range. 28*9660Slinton */ 29*9660Slinton 30*9660Slinton public check(p) 31*9660Slinton register Node p; 32*9660Slinton { 33*9660Slinton Address addr; 34*9660Slinton Symbol f; 35*9660Slinton 36*9660Slinton checkref(p); 37*9660Slinton switch (p->op) { 38*9660Slinton case O_LIST: 39*9660Slinton if (p->value.arg[0]->op == O_SYM) { 40*9660Slinton f = p->value.arg[0]->value.sym; 41*9660Slinton if (not isblock(f) or ismodule(f)) { 42*9660Slinton error("\"%s\" is not a procedure or function", symname(f)); 43*9660Slinton } 44*9660Slinton addr = firstline(f); 45*9660Slinton if (addr == NOADDR) { 46*9660Slinton error("\"%s\" is empty", symname(f)); 47*9660Slinton } 48*9660Slinton } 49*9660Slinton break; 50*9660Slinton 51*9660Slinton case O_TRACE: 52*9660Slinton case O_TRACEI: 53*9660Slinton chktrace(p); 54*9660Slinton break; 55*9660Slinton 56*9660Slinton case O_STOP: 57*9660Slinton case O_STOPI: 58*9660Slinton chkstop(p); 59*9660Slinton break; 60*9660Slinton 61*9660Slinton default: 62*9660Slinton break; 63*9660Slinton } 64*9660Slinton } 65*9660Slinton 66*9660Slinton /* 67*9660Slinton * Check arguments to a trace command. 68*9660Slinton */ 69*9660Slinton 70*9660Slinton private chktrace(p) 71*9660Slinton Node p; 72*9660Slinton { 73*9660Slinton Node exp, place, cond; 74*9660Slinton 75*9660Slinton exp = p->value.arg[0]; 76*9660Slinton place = p->value.arg[1]; 77*9660Slinton cond = p->value.arg[2]; 78*9660Slinton if (exp == nil) { 79*9660Slinton chkblock(place); 80*9660Slinton } else if (exp->op == O_LCON or exp->op == O_QLINE) { 81*9660Slinton if (place != nil) { 82*9660Slinton error("unexpected \"at\" or \"in\""); 83*9660Slinton } 84*9660Slinton if (p->op == O_TRACE) { 85*9660Slinton chkline(exp); 86*9660Slinton } else { 87*9660Slinton chkaddr(exp); 88*9660Slinton } 89*9660Slinton } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { 90*9660Slinton if (p->op == O_TRACE) { 91*9660Slinton chkline(place); 92*9660Slinton } else { 93*9660Slinton chkaddr(place); 94*9660Slinton } 95*9660Slinton } else { 96*9660Slinton if (exp->op != O_RVAL and exp->op != O_SYM) { 97*9660Slinton error("can't trace expressions"); 98*9660Slinton } 99*9660Slinton chkblock(place); 100*9660Slinton } 101*9660Slinton } 102*9660Slinton 103*9660Slinton /* 104*9660Slinton * Check arguments to a stop command. 105*9660Slinton */ 106*9660Slinton 107*9660Slinton private chkstop(p) 108*9660Slinton Node p; 109*9660Slinton { 110*9660Slinton Node exp, place, cond; 111*9660Slinton 112*9660Slinton exp = p->value.arg[0]; 113*9660Slinton place = p->value.arg[1]; 114*9660Slinton cond = p->value.arg[2]; 115*9660Slinton if (exp != nil) { 116*9660Slinton if (exp->op != O_RVAL and exp->op != O_SYM) { 117*9660Slinton beginerrmsg(); 118*9660Slinton fprintf(stderr, "expected variable, found "); 119*9660Slinton prtree(stderr, exp); 120*9660Slinton enderrmsg(); 121*9660Slinton } 122*9660Slinton chkblock(place); 123*9660Slinton } else if (cond != nil) { 124*9660Slinton chkblock(place); 125*9660Slinton } else if (place->op == O_SYM) { 126*9660Slinton chkblock(place); 127*9660Slinton } else { 128*9660Slinton if (p->op == O_STOP) { 129*9660Slinton chkline(place); 130*9660Slinton } else { 131*9660Slinton chkaddr(place); 132*9660Slinton } 133*9660Slinton } 134*9660Slinton } 135*9660Slinton 136*9660Slinton /* 137*9660Slinton * Check to see that the given node specifies some subprogram. 138*9660Slinton * Nil is ok since that means the entire program. 139*9660Slinton */ 140*9660Slinton 141*9660Slinton private chkblock(b) 142*9660Slinton Node b; 143*9660Slinton { 144*9660Slinton if (b != nil) { 145*9660Slinton if (b->op != O_SYM) { 146*9660Slinton beginerrmsg(); 147*9660Slinton fprintf(stderr, "expected subprogram, found "); 148*9660Slinton prtree(stderr, b); 149*9660Slinton enderrmsg(); 150*9660Slinton } else if (not isblock(b->value.sym) or ismodule(b->value.sym)) { 151*9660Slinton error("\"%s\" is not a subprogram", symname(b->value.sym)); 152*9660Slinton } 153*9660Slinton } 154*9660Slinton } 155*9660Slinton 156*9660Slinton /* 157*9660Slinton * Check to make sure a node corresponds to a source line. 158*9660Slinton */ 159*9660Slinton 160*9660Slinton private chkline(p) 161*9660Slinton Node p; 162*9660Slinton { 163*9660Slinton if (p == nil) { 164*9660Slinton error("missing line"); 165*9660Slinton } else if (p->op != O_QLINE and p->op != O_LCON) { 166*9660Slinton error("expected source line number, found \"%t\"", p); 167*9660Slinton } 168*9660Slinton } 169*9660Slinton 170*9660Slinton /* 171*9660Slinton * Check to make sure a node corresponds to an address. 172*9660Slinton */ 173*9660Slinton 174*9660Slinton private chkaddr(p) 175*9660Slinton Node p; 176*9660Slinton { 177*9660Slinton if (p == nil) { 178*9660Slinton error("missing address"); 179*9660Slinton } else if (p->op != O_LCON and p->op != O_QLINE) { 180*9660Slinton beginerrmsg(); 181*9660Slinton fprintf(stderr, "expected address, found \""); 182*9660Slinton prtree(stderr, p); 183*9660Slinton fprintf(stderr, "\""); 184*9660Slinton enderrmsg(); 185*9660Slinton } 186*9660Slinton } 187