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