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