1: /*
   2:  * Copyright (c) 1980 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[] = "@(#)tracestop.c	5.1 (Berkeley) 6/6/85";
   9: #endif not lint
  10: 
  11: /*
  12:  * Handle trace and stop commands.
  13:  */
  14: 
  15: #include "defs.h"
  16: #include "breakpoint.h"
  17: #include "sym.h"
  18: #include "tree.h"
  19: #include "runtime.h"
  20: #include "source.h"
  21: #include "object.h"
  22: #include "mappings.h"
  23: #include "machine.h"
  24: #include "tree.rep"
  25: 
  26: LOCAL SYM *tcontainer();
  27: 
  28: /*
  29:  * Process a trace/untrace command, basically checking arguments
  30:  * and translate to a call of the appropriate routine.
  31:  */
  32: 
  33: trace(cmd, exp, where, cond)
  34: int cmd;
  35: NODE *exp;
  36: NODE *where;
  37: NODE *cond;
  38: {
  39:     if (exp == NIL) {
  40:         traceall(cmd, where, cond);
  41:     } else if (exp->op == O_LCON || exp->op == O_QLINE) {
  42:         traceinst(cmd, exp, where, cond);
  43:     } else if (where!=NIL && (where->op==O_QLINE || where->op==O_LCON)) {
  44:         traceat(cmd, exp, where, cond);
  45:     } else {
  46:         tracedata(cmd, exp, where, cond);
  47:     }
  48:     if (where != NIL) {
  49:         tfree(where);
  50:     }
  51: }
  52: 
  53: /*
  54:  * Set a breakpoint that will turn on tracing.
  55:  *
  56:  * A line number of 0 in the breakpoint information structure
  57:  * means it's a normal trace.
  58:  *
  59:  * A line number of -1 indicates that we want to trace at the instruction
  60:  * rather than source line level.
  61:  *
  62:  * If location is NIL, turn on tracing because if the user
  63:  * has the program stopped somewhere and says "trace",
  64:  * he/she wants to see tracing after continuing execution.
  65:  */
  66: 
  67: LOCAL traceall(cmd, where, cond)
  68: int cmd;
  69: NODE *where;
  70: NODE *cond;
  71: {
  72:     SYM *s;
  73:     LINENO line;
  74: 
  75:     if (where != NIL && where->op != O_NAME) {
  76:         error("bad location for trace");
  77:     }
  78:     if (cmd == O_TRACE) {
  79:         line = 0;
  80:     } else {
  81:         line = -1;
  82:     }
  83:     if (where == NIL) {
  84:         switch (cmd) {
  85:             case O_TRACE:
  86:                 if (tracing != 0) {
  87:                     error("already tracing lines");
  88:                 }
  89:                 tracing++;
  90:                 addcond(TRPRINT, cond);
  91:                 break;
  92: 
  93:             case O_TRACEI:
  94:                 if (inst_tracing != 0) {
  95:                     error("already tracing instructions");
  96:                 }
  97:                 inst_tracing++;
  98:                 addcond(TRPRINT, cond);
  99:                 break;
 100: 
 101:             default:
 102:                 panic("bad cmd in traceall");
 103:                 break;
 104:         }
 105:         s = program;
 106:     } else if (where->op != O_NAME) {
 107:         trerror("found %t, expected procedure or function", where);
 108:     } else {
 109:         s = where->nameval;
 110:         if (!isblock(s)) {
 111:             error("\"%s\" is not a procedure or function", name(s));
 112:         }
 113:     }
 114:     addbp(codeloc(s), ALL_ON, s, cond, NIL, line);
 115: }
 116: 
 117: /*
 118:  * Set up the appropriate breakpoint for tracing an instruction.
 119:  */
 120: 
 121: LOCAL traceinst(cmd, exp, where, cond)
 122: int cmd;
 123: NODE *exp;
 124: NODE *where;
 125: NODE *cond;
 126: {
 127:     LINENO line;
 128:     ADDRESS addr;
 129: 
 130:     if (where != NIL) {
 131:         error("unexpected \"at\" or \"in\"");
 132:     }
 133:     if (cmd == O_TRACEI) {
 134:         if (exp->op == O_QLINE) {
 135:             addr = (ADDRESS) exp->right->lconval;
 136:         } else if (exp->op == O_LCON) {
 137:             addr = (ADDRESS) exp->lconval;
 138:         } else {
 139:             trerror("expected integer constant, found %t", exp);
 140:         }
 141:         line = -1;
 142:     } else {
 143:         if (exp->op == O_QLINE) {
 144:             line = (LINENO) exp->right->lconval;
 145:             addr = objaddr(line, exp->left->sconval);
 146:         } else {
 147:             line = (LINENO) exp->lconval;
 148:             addr = objaddr(line, cursource);
 149:         }
 150:         if (addr == (ADDRESS) -1) {
 151:             error("can't trace line %d", line);
 152:         }
 153:     }
 154:     tfree(exp);
 155:     addbp(addr, INST, NIL, cond, NIL, line);
 156: }
 157: 
 158: /*
 159:  * set a breakpoint to print an expression at a given line or address
 160:  */
 161: 
 162: LOCAL traceat(cmd, exp, where, cond)
 163: int cmd;
 164: NODE *exp;
 165: NODE *where;
 166: NODE *cond;
 167: {
 168:     LINENO line;
 169:     ADDRESS addr;
 170: 
 171:     if (cmd == O_TRACEI) {
 172:         if (where->op != O_LCON) {
 173:             trerror("expected integer constant, found %t", where);
 174:         }
 175:         line = -1;
 176:         addr = (ADDRESS) where->lconval;
 177:     } else {
 178:         line = (LINENO) where->right->lconval;
 179:         addr = objaddr(line, where->left->sconval);
 180:         if (addr == (ADDRESS) -1) {
 181:             error("can't trace at line %d", line);
 182:         }
 183:     }
 184:     addbp(addr, AT_BP, NIL, cond, exp, line);
 185: }
 186: 
 187: /*
 188:  * Set up breakpoint for tracing data.
 189:  *
 190:  * The tracing of blocks lies somewhere between instruction and data;
 191:  * it's here since a block cannot be distinguished from other terms.
 192:  *
 193:  * As in "traceall", if the "block" is the main program then the
 194:  * user didn't actually specify a block.  This means we want to
 195:  * turn tracing on ourselves because if the program is stopped
 196:  * we want to be on regardless of whether they say "cont" or "run".
 197:  */
 198: 
 199: LOCAL tracedata(cmd, exp, block, cond)
 200: int cmd;
 201: NODE *exp;
 202: NODE *block;
 203: NODE *cond;
 204: {
 205:     SYM *s, *t;
 206: 
 207:     if (exp->op != O_RVAL && exp->op != O_CALL) {
 208:         error("can't trace expressions");
 209:     }
 210:     if (block == NIL) {
 211:         t = tcontainer(exp->left);
 212:     } else if (block->op == O_NAME) {
 213:         t = block->nameval;
 214:     } else {
 215:         trerror("found %t, expected procedure or function", block);
 216:     }
 217:     if (exp->left->op == O_NAME) {
 218:         s = exp->left->nameval;
 219:         if (isblock(s)) {
 220:             addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
 221:             if (t == program) {
 222:                 addbp(codeloc(s), CALL, s, cond, NIL, 0);
 223:             }
 224:             return;
 225:         }
 226:     }
 227:     addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
 228:     if (curfunc == t) {
 229:         var_tracing++;
 230:         addvar(TRPRINT, exp, cond);
 231:         addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
 232:     }
 233: }
 234: 
 235: /*
 236:  * Setting and unsetting of stops.
 237:  */
 238: 
 239: stop(cmd, exp, where, cond)
 240: int cmd;
 241: NODE *exp;
 242: NODE *where;
 243: NODE *cond;
 244: {
 245:     SYM *s;
 246:     LINENO n;
 247: 
 248:     if (exp != NIL) {
 249:         stopvar(cmd, exp, where, cond);
 250:     } else if (cond != NIL) {
 251:         if (where == NIL) {
 252:             s = program;
 253:         } else if (where->op == O_NAME) {
 254:             s = where->nameval;
 255:         } else {
 256:             error("bad location for stop");
 257:         }
 258:         n = codeloc(s);
 259:         addbp(n, STOP_ON, s, cond, NIL, n);
 260:         addcond(TRSTOP, cond);
 261:         var_tracing++;
 262:     } else if (where->op == O_NAME) {
 263:         s = where->nameval;
 264:         if (!isblock(s)) {
 265:             error("\"%s\" is not a procedure or function", name(s));
 266:         }
 267:         n = codeloc(s);
 268:         addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
 269:     } else {
 270:         stopinst(cmd, where, cond);
 271:     }
 272:     if (where != NIL) {
 273:         tfree(where);
 274:     }
 275: }
 276: 
 277: LOCAL stopinst(cmd, where, cond)
 278: int cmd;
 279: NODE *where;
 280: NODE *cond;
 281: {
 282:     LINENO line;
 283:     ADDRESS addr;
 284: 
 285:     if (where->op != O_QLINE) {
 286:         error("expected line number");
 287:     }
 288:     if (cmd == O_STOP) {
 289:         line = (LINENO) where->right->lconval;
 290:         addr = objaddr(line, where->left->sconval);
 291:         if (addr == (ADDRESS) -1) {
 292:             error("can't stop at that line");
 293:         }
 294:     } else {
 295:         line = -1;
 296:         addr = (ADDRESS) where->right->lconval;
 297:     }
 298:     addbp(addr, STOP_BP, NIL, cond, NIL, line);
 299: }
 300: 
 301: /*
 302:  * Implement stopping on assignment to a variable by adding it to
 303:  * the variable list.
 304:  */
 305: 
 306: LOCAL stopvar(cmd, exp, where, cond)
 307: int cmd;
 308: NODE *exp;
 309: NODE *where;
 310: NODE *cond;
 311: {
 312:     SYM *s;
 313: 
 314:     if (exp->op != O_RVAL) {
 315:         trerror("found %t, expected variable", exp);
 316:     }
 317:     if (cmd == O_STOPI) {
 318:         inst_tracing++;
 319:     }
 320:     var_tracing++;
 321:     addvar(TRSTOP, exp, cond);
 322:     if (where == NIL) {
 323:         s = program;
 324:     } else if (where->op == O_NAME) {
 325:         s = where->nameval;
 326:     } else {
 327:         error("bad location for stop");
 328:     }
 329:     addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
 330: }
 331: 
 332: /*
 333:  * Figure out the block that contains the symbols
 334:  * in the given variable expression.
 335:  */
 336: 
 337: LOCAL SYM *tcontainer(var)
 338: NODE *var;
 339: {
 340:     NODE *p;
 341: 
 342:     p = var;
 343:     while (p->op != O_NAME) {
 344:         if (isleaf(p->op)) {
 345:             panic("unexpected op %d in tcontainer", p->op);
 346:             /* NOTREACHED */
 347:         }
 348:         p = p->left;
 349:     }
 350:     return container(p->nameval);
 351: }

Defined functions

stop defined in line 239; used 1 times
stopinst defined in line 277; used 1 times
stopvar defined in line 306; used 1 times
tcontainer defined in line 337; used 2 times
trace defined in line 33; used 1 times
traceall defined in line 67; used 1 times
  • in line 40
traceat defined in line 162; used 1 times
  • in line 44
tracedata defined in line 199; used 1 times
  • in line 46
traceinst defined in line 121; used 1 times
  • in line 42

Defined variables

sccsid defined in line 8; never used
Last modified: 1985-06-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2587
Valid CSS Valid XHTML 1.0 Strict