1 /* Copyright (c) 1982 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)check.c 1.2 12/15/82"; 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) { 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 (cond != nil) { 124 chkblock(place); 125 } else if (place->op == O_SYM) { 126 chkblock(place); 127 } else { 128 if (p->op == O_STOP) { 129 chkline(place); 130 } else { 131 chkaddr(place); 132 } 133 } 134 } 135 136 /* 137 * Check to see that the given node specifies some subprogram. 138 * Nil is ok since that means the entire program. 139 */ 140 141 private chkblock(b) 142 Node b; 143 { 144 if (b != nil) { 145 if (b->op != O_SYM) { 146 beginerrmsg(); 147 fprintf(stderr, "expected subprogram, found "); 148 prtree(stderr, b); 149 enderrmsg(); 150 } else if (not isblock(b->value.sym) or ismodule(b->value.sym)) { 151 error("\"%s\" is not a subprogram", symname(b->value.sym)); 152 } 153 } 154 } 155 156 /* 157 * Check to make sure a node corresponds to a source line. 158 */ 159 160 private chkline(p) 161 Node p; 162 { 163 if (p == nil) { 164 error("missing line"); 165 } else if (p->op != O_QLINE and p->op != O_LCON) { 166 error("expected source line number, found \"%t\"", p); 167 } 168 } 169 170 /* 171 * Check to make sure a node corresponds to an address. 172 */ 173 174 private chkaddr(p) 175 Node p; 176 { 177 if (p == nil) { 178 error("missing address"); 179 } else if (p->op != O_LCON and p->op != O_QLINE) { 180 beginerrmsg(); 181 fprintf(stderr, "expected address, found \""); 182 prtree(stderr, p); 183 fprintf(stderr, "\""); 184 enderrmsg(); 185 } 186 } 187