Annotation of 43BSDReno/pgrm/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.2 (Berkeley) 4/6/87";
                      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: #ifdef lint
                    208:        cmd = cmd;
                    209: #endif
                    210:        if (exp->op != O_RVAL && exp->op != O_CALL) {
                    211:                error("can't trace expressions");
                    212:        }
                    213:        if (block == NIL) {
                    214:                t = tcontainer(exp->left);
                    215:        } else if (block->op == O_NAME) {
                    216:                t = block->nameval;
                    217:        } else {
                    218:                trerror("found %t, expected procedure or function", block);
                    219:        }
                    220:        if (exp->left->op == O_NAME) {
                    221:                s = exp->left->nameval;
                    222:                if (isblock(s)) {
                    223:                        addbp(codeloc(t), BLOCK_ON, t, cond, exp->left, 0);
                    224:                        if (t == program) {
                    225:                                addbp(codeloc(s), CALL, s, cond, NIL, 0);
                    226:                        }
                    227:                        return;
                    228:                }
                    229:        }
                    230:        addbp(codeloc(t), TERM_ON, t, cond, exp, 0);
                    231:        if (curfunc == t) {
                    232:                var_tracing++;
                    233:                addvar(TRPRINT, exp, cond);
                    234:                addbp(return_addr(), TERM_OFF, t, cond, exp, 0);
                    235:        }
                    236: }
                    237: 
                    238: /*
                    239:  * Setting and unsetting of stops.
                    240:  */
                    241: 
                    242: stop(cmd, exp, where, cond)
                    243: int cmd;
                    244: NODE *exp;
                    245: NODE *where;
                    246: NODE *cond;
                    247: {
                    248:        SYM *s;
                    249:        LINENO n;
                    250: 
                    251:        if (exp != NIL) {
                    252:                stopvar(cmd, exp, where, cond);
                    253:        } else if (cond != NIL) {
                    254:                if (where == NIL) {
                    255:                        s = program;
                    256:                } else if (where->op == O_NAME) {
                    257:                        s = where->nameval;
                    258:                } else {
                    259:                        error("bad location for stop");
                    260:                }
                    261:                n = codeloc(s);
                    262:                addbp(n, STOP_ON, s, cond, NIL, n);
                    263:                addcond(TRSTOP, cond);
                    264:                var_tracing++;
                    265:        } else if (where->op == O_NAME) {
                    266:                s = where->nameval;
                    267:                if (!isblock(s)) {
                    268:                        error("\"%s\" is not a procedure or function", name(s));
                    269:                }
                    270:                n = codeloc(s);
                    271:                addbp(n, STOP_BP, s, cond, NIL, srcline(firstline(s)));
                    272:        } else {
                    273:                stopinst(cmd, where, cond);
                    274:        }
                    275:        if (where != NIL) {
                    276:                tfree(where);
                    277:        }
                    278: }
                    279: 
                    280: LOCAL stopinst(cmd, where, cond)
                    281: int cmd;
                    282: NODE *where;
                    283: NODE *cond;
                    284: {
                    285:        LINENO line;
                    286:        ADDRESS addr;
                    287: 
                    288:        if (where->op != O_QLINE) {
                    289:                error("expected line number");
                    290:        }
                    291:        if (cmd == O_STOP) {
                    292:                line = (LINENO) where->right->lconval;
                    293:                addr = objaddr(line, where->left->sconval);
                    294:                if (addr == (ADDRESS) -1) {
                    295:                        error("can't stop at that line");
                    296:                }
                    297:        } else {
                    298:                line = -1;
                    299:                addr = (ADDRESS) where->right->lconval;
                    300:        }
                    301:        addbp(addr, STOP_BP, NIL, cond, NIL, line);
                    302: }
                    303: 
                    304: /*
                    305:  * Implement stopping on assignment to a variable by adding it to
                    306:  * the variable list.
                    307:  */
                    308: 
                    309: LOCAL stopvar(cmd, exp, where, cond)
                    310: int cmd;
                    311: NODE *exp;
                    312: NODE *where;
                    313: NODE *cond;
                    314: {
                    315:        SYM *s;
                    316: 
                    317:        if (exp->op != O_RVAL) {
                    318:                trerror("found %t, expected variable", exp);
                    319:        }
                    320:        if (cmd == O_STOPI) {
                    321:                inst_tracing++;
                    322:        }
                    323:        var_tracing++;
                    324:        addvar(TRSTOP, exp, cond);
                    325:        if (where == NIL) {
                    326:                s = program;
                    327:        } else if (where->op == O_NAME) {
                    328:                s = where->nameval;
                    329:        } else {
                    330:                error("bad location for stop");
                    331:        }
                    332:        addbp(codeloc(s), STOP_ON, s, cond, exp, 0);
                    333: }
                    334: 
                    335: /*
                    336:  * Figure out the block that contains the symbols
                    337:  * in the given variable expression.
                    338:  */
                    339: 
                    340: LOCAL SYM *tcontainer(var)
                    341: NODE *var;
                    342: {
                    343:        NODE *p;
                    344: 
                    345:        p = var;
                    346:        while (p->op != O_NAME) {
                    347:                if (isleaf(p->op)) {
                    348:                        panic("unexpected op %d in tcontainer", p->op);
                    349:                        /* NOTREACHED */
                    350:                }
                    351:                p = p->left;
                    352:        }
                    353:        return container(p->nameval);
                    354: }

unix.superglobalmegacorp.com

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