Annotation of 43BSD/ucb/pascal/pdx/tree/tracestop.c, revision 1.1.1.1

1.1       root        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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.