|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)check.c 5.2 (Berkeley) 1/10/86"; ! 9: #endif not lint ! 10: ! 11: static char rcsid[] = "$Header: check.c,v 1.5 84/12/26 10:38:35 linton Exp $"; ! 12: ! 13: /* ! 14: * Check a tree for semantic correctness. ! 15: */ ! 16: ! 17: #include "defs.h" ! 18: #include "tree.h" ! 19: #include "operators.h" ! 20: #include "events.h" ! 21: #include "symbols.h" ! 22: #include "scanner.h" ! 23: #include "source.h" ! 24: #include "object.h" ! 25: #include "mappings.h" ! 26: #include "process.h" ! 27: #include <signal.h> ! 28: ! 29: #ifndef public ! 30: #endif ! 31: ! 32: /* ! 33: * Check that the nodes in a tree have the correct arguments ! 34: * in order to be evaluated. Basically the error checking here ! 35: * frees the evaluation routines from worrying about anything ! 36: * except dynamic errors, e.g. subscript out of range. ! 37: */ ! 38: ! 39: public check(p) ! 40: register Node p; ! 41: { ! 42: Node p1, p2; ! 43: Address addr; ! 44: Symbol f; ! 45: ! 46: checkref(p); ! 47: switch (p->op) { ! 48: case O_ASSIGN: ! 49: p1 = p->value.arg[0]; ! 50: p2 = p->value.arg[1]; ! 51: if (varIsSet("$unsafeassign")) { ! 52: if (size(p1->nodetype) != size(p2->nodetype)) { ! 53: error("incompatible sizes"); ! 54: } ! 55: } else if (not compatible(p1->nodetype, p2->nodetype)) { ! 56: error("incompatible types"); ! 57: } ! 58: break; ! 59: ! 60: case O_CATCH: ! 61: case O_IGNORE: ! 62: if (p->value.lcon < 0 or p->value.lcon > NSIG) { ! 63: error("invalid signal number"); ! 64: } ! 65: break; ! 66: ! 67: case O_CONT: ! 68: if (p->value.lcon != DEFSIG and ( ! 69: p->value.lcon < 0 or p->value.lcon > NSIG) ! 70: ) { ! 71: error("invalid signal number"); ! 72: } ! 73: break; ! 74: ! 75: case O_DUMP: ! 76: if (p->value.arg[0] != nil) { ! 77: if (p->value.arg[0]->op == O_SYM) { ! 78: f = p->value.arg[0]->value.sym; ! 79: if (not isblock(f)) { ! 80: error("\"%s\" is not a block", symname(f)); ! 81: } ! 82: } else { ! 83: beginerrmsg(); ! 84: fprintf(stderr, "expected a symbol, found \""); ! 85: prtree(stderr, p->value.arg[0]); ! 86: fprintf(stderr, "\""); ! 87: enderrmsg(); ! 88: } ! 89: } ! 90: break; ! 91: ! 92: case O_LIST: ! 93: if (p->value.arg[0]->op == O_SYM) { ! 94: f = p->value.arg[0]->value.sym; ! 95: if (not isblock(f) or ismodule(f)) { ! 96: error("\"%s\" is not a procedure or function", symname(f)); ! 97: } ! 98: addr = firstline(f); ! 99: if (addr == NOADDR) { ! 100: error("\"%s\" is empty", symname(f)); ! 101: } ! 102: } ! 103: break; ! 104: ! 105: case O_TRACE: ! 106: case O_TRACEI: ! 107: chktrace(p); ! 108: break; ! 109: ! 110: case O_STOP: ! 111: case O_STOPI: ! 112: chkstop(p); ! 113: break; ! 114: ! 115: case O_CALLPROC: ! 116: case O_CALL: ! 117: if (not isroutine(p->value.arg[0]->nodetype)) { ! 118: beginerrmsg(); ! 119: fprintf(stderr, "\""); ! 120: prtree(stderr, p->value.arg[0]); ! 121: fprintf(stderr, "\" not call-able"); ! 122: enderrmsg(); ! 123: } ! 124: break; ! 125: ! 126: case O_WHEREIS: ! 127: if (p->value.arg[0]->op == O_SYM and ! 128: p->value.arg[0]->value.sym == nil) { ! 129: error("symbol not defined"); ! 130: } ! 131: break; ! 132: ! 133: default: ! 134: break; ! 135: } ! 136: } ! 137: ! 138: /* ! 139: * Check arguments to a trace command. ! 140: */ ! 141: ! 142: private chktrace(p) ! 143: Node p; ! 144: { ! 145: Node exp, place, cond; ! 146: ! 147: exp = p->value.arg[0]; ! 148: place = p->value.arg[1]; ! 149: cond = p->value.arg[2]; ! 150: if (exp == nil) { ! 151: chkblock(place); ! 152: } else if (exp->op == O_LCON or exp->op == O_QLINE) { ! 153: if (place != nil) { ! 154: error("unexpected \"at\" or \"in\""); ! 155: } ! 156: if (p->op == O_TRACE) { ! 157: chkline(exp); ! 158: } else { ! 159: chkaddr(exp); ! 160: } ! 161: } else if (place != nil and (place->op == O_QLINE or place->op == O_LCON)) { ! 162: if (p->op == O_TRACE) { ! 163: chkline(place); ! 164: } else { ! 165: chkaddr(place); ! 166: } ! 167: } else { ! 168: if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_CALL) { ! 169: error("can't trace expressions"); ! 170: } ! 171: chkblock(place); ! 172: } ! 173: } ! 174: ! 175: /* ! 176: * Check arguments to a stop command. ! 177: */ ! 178: ! 179: private chkstop(p) ! 180: Node p; ! 181: { ! 182: Node exp, place, cond; ! 183: ! 184: exp = p->value.arg[0]; ! 185: place = p->value.arg[1]; ! 186: cond = p->value.arg[2]; ! 187: if (exp != nil) { ! 188: if (exp->op != O_RVAL and exp->op != O_SYM and exp->op != O_LCON) { ! 189: beginerrmsg(); ! 190: fprintf(stderr, "expected variable, found "); ! 191: prtree(stderr, exp); ! 192: enderrmsg(); ! 193: } ! 194: chkblock(place); ! 195: } else if (place != nil) { ! 196: if (place->op == O_SYM) { ! 197: chkblock(place); ! 198: } else { ! 199: if (p->op == O_STOP) { ! 200: chkline(place); ! 201: } else { ! 202: chkaddr(place); ! 203: } ! 204: } ! 205: } ! 206: } ! 207: ! 208: /* ! 209: * Check to see that the given node specifies some subprogram. ! 210: * Nil is ok since that means the entire program. ! 211: */ ! 212: ! 213: private chkblock(b) ! 214: Node b; ! 215: { ! 216: Symbol p, outer; ! 217: ! 218: if (b != nil) { ! 219: if (b->op != O_SYM) { ! 220: beginerrmsg(); ! 221: fprintf(stderr, "expected subprogram, found "); ! 222: prtree(stderr, b); ! 223: enderrmsg(); ! 224: } else if (ismodule(b->value.sym)) { ! 225: outer = b->value.sym; ! 226: while (outer != nil) { ! 227: find(p, outer->name) where p->block == outer endfind(p); ! 228: if (p == nil) { ! 229: outer = nil; ! 230: error("\"%s\" is not a subprogram", symname(b->value.sym)); ! 231: } else if (ismodule(p)) { ! 232: outer = p; ! 233: } else { ! 234: outer = nil; ! 235: b->value.sym = p; ! 236: } ! 237: } ! 238: } else if ( ! 239: b->value.sym->class == VAR and ! 240: b->value.sym->name == b->value.sym->block->name and ! 241: b->value.sym->block->class == FUNC ! 242: ) { ! 243: b->value.sym = b->value.sym->block; ! 244: } else if (not isblock(b->value.sym)) { ! 245: error("\"%s\" is not a subprogram", symname(b->value.sym)); ! 246: } ! 247: } ! 248: } ! 249: ! 250: /* ! 251: * Check to make sure a node corresponds to a source line. ! 252: */ ! 253: ! 254: private chkline(p) ! 255: Node p; ! 256: { ! 257: if (p == nil) { ! 258: error("missing line"); ! 259: } else if (p->op != O_QLINE and p->op != O_LCON) { ! 260: error("expected source line number, found \"%t\"", p); ! 261: } ! 262: } ! 263: ! 264: /* ! 265: * Check to make sure a node corresponds to an address. ! 266: */ ! 267: ! 268: private chkaddr(p) ! 269: Node p; ! 270: { ! 271: if (p == nil) { ! 272: error("missing address"); ! 273: } else if (p->op != O_LCON and p->op != O_QLINE) { ! 274: beginerrmsg(); ! 275: fprintf(stderr, "expected address, found \""); ! 276: prtree(stderr, p); ! 277: fprintf(stderr, "\""); ! 278: enderrmsg(); ! 279: } ! 280: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.