Annotation of 42BSD/ucb/dbx/tree.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1982 Regents of the University of California */
                      2: 
                      3: static char sccsid[] = "@(#)tree.c 1.5 8/10/83";
                      4: 
                      5: /*
                      6:  * Parse tree management.
                      7:  */
                      8: 
                      9: #include "defs.h"
                     10: #include "tree.h"
                     11: #include "operators.h"
                     12: #include "eval.h"
                     13: #include "events.h"
                     14: #include "symbols.h"
                     15: #include "scanner.h"
                     16: #include "source.h"
                     17: #include "object.h"
                     18: #include "mappings.h"
                     19: #include "process.h"
                     20: #include "machine.h"
                     21: 
                     22: #ifndef public
                     23: #include "lists.h"
                     24: 
                     25: typedef struct Node *Node;
                     26: typedef Node Command;
                     27: typedef List Cmdlist;
                     28: 
                     29: #include "operators.h"
                     30: #include "symbols.h"
                     31: #include "events.h"
                     32: 
                     33: #define MAXNARGS 5
                     34: 
                     35: struct Node {
                     36:     Operator op;
                     37:     Symbol nodetype;
                     38:     union treevalue {
                     39:        Symbol sym;
                     40:        Name name;
                     41:        long lcon;
                     42:        double fcon;
                     43:        String scon;
                     44:        Node arg[MAXNARGS];
                     45:        struct {
                     46:            Node cond;
                     47:            Cmdlist actions;
                     48:        } event;
                     49:        struct {
                     50:            Boolean inst;
                     51:            Event event;
                     52:            Cmdlist actions;
                     53:        } trace;
                     54:        struct {
                     55:            Boolean source;
                     56:            Boolean skipcalls;
                     57:        } step;
                     58:        struct {
                     59:            String mode;
                     60:            Node beginaddr;
                     61:            Node endaddr;
                     62:            Integer count;
                     63:        } examine;
                     64:     } value;
                     65: };
                     66: 
                     67: #define evalcmd(cmd) eval(cmd)
                     68: #define cmdlist_append(cmd, cl) list_append(list_item(cmd), nil, cl)
                     69: 
                     70: #endif
                     71: 
                     72: typedef char *Arglist;
                     73: 
                     74: #define nextarg(type)  ((type *) (ap += sizeof(type)))[-1]
                     75: 
                     76: /*
                     77:  * Build a tree.
                     78:  */
                     79: 
                     80: /* VARARGS1 */
                     81: public Node build(op, args)
                     82: Operator op;
                     83: {
                     84:     register Node p, q;
                     85:     register Arglist ap;
                     86:     Integer i;
                     87: 
                     88:     p = new(Node);
                     89:     p->op = op;
                     90:     p->nodetype = nil;
                     91:     ap = (Arglist) &args;
                     92:     switch (op) {
                     93:        case O_NAME:
                     94:            p->value.name = nextarg(Name);
                     95:            break;
                     96: 
                     97:        case O_SYM:
                     98:        case O_PRINTCALL:
                     99:        case O_PRINTRTN:
                    100:        case O_PROCRTN:
                    101:            p->value.sym = nextarg(Symbol);
                    102:            break;
                    103: 
                    104:        case O_DEBUG:
                    105:        case O_LCON:
                    106:        case O_CONT:
                    107:        case O_DELETE:
                    108:        case O_CATCH:
                    109:        case O_IGNORE:
                    110:        case O_TRACEOFF:
                    111:            p->value.lcon = nextarg(long);
                    112:            break;
                    113: 
                    114:        case O_FCON:
                    115:            p->value.fcon = nextarg(double);
                    116:            break;
                    117: 
                    118:        case O_SCON:
                    119:        case O_CHFILE:
                    120:        case O_EDIT:
                    121:        case O_SOURCE:
                    122:            p->value.scon = nextarg(String);
                    123:            break;
                    124: 
                    125:        case O_RVAL:
                    126:            q = nextarg(Node);
                    127:            if (q->op == O_CALL) {
                    128:                *p = *q;
                    129:                dispose(q);
                    130:            } else {
                    131:                p->value.arg[0] = q;
                    132:            }
                    133:            break;
                    134: 
                    135:        case O_INDIR:
                    136:            q = nextarg(Node);
                    137:            if (q != nil and q->op == O_RVAL) {
                    138:                p->value.arg[0] = q->value.arg[0];
                    139:                dispose(q);
                    140:            } else {
                    141:                p->value.arg[0] = q;
                    142:            }
                    143:            break;
                    144: 
                    145:        case O_ADDEVENT:
                    146:        case O_ONCE:
                    147:        case O_IF:
                    148:            p->value.event.cond = nextarg(Node);
                    149:            p->value.event.actions = nextarg(Cmdlist);
                    150:            break;
                    151: 
                    152:        case O_TRACEON:
                    153:            p->value.trace.inst = nextarg(Boolean);
                    154:            p->value.trace.event = nil;
                    155:            p->value.trace.actions = nextarg(Cmdlist);
                    156:            break;
                    157: 
                    158:        case O_STEP:
                    159:            p->value.step.source = nextarg(Boolean);
                    160:            p->value.step.skipcalls = nextarg(Boolean);
                    161:            break;
                    162: 
                    163:        case O_EXAMINE:
                    164:            p->value.examine.mode = nextarg(String);
                    165:            p->value.examine.beginaddr = nextarg(Node);
                    166:            p->value.examine.endaddr = nextarg(Node);
                    167:            p->value.examine.count = nextarg(Integer);
                    168:            break;
                    169: 
                    170:        default:
                    171:            for (i = 0; i < nargs(op); i++) {
                    172:                p->value.arg[i] = nextarg(Node);
                    173:            }
                    174:            break;
                    175:     }
                    176:     check(p);
                    177:     assigntypes(p);
                    178:     if(debug_flag[5]) {     
                    179:        fprintf(stderr," built %s node %d with arg0 %d arg1 %d \n",
                    180:                showoperator(p->op), p, p->value.arg[0],p->value.arg[1]);
                    181:     }
                    182:     return p;
                    183: }
                    184: 
                    185: /*
                    186:  * Create a command list from a single command.
                    187:  */
                    188: 
                    189: public Cmdlist buildcmdlist(cmd)
                    190: Command cmd;
                    191: {
                    192:     Cmdlist cmdlist;
                    193: 
                    194:     cmdlist = list_alloc();
                    195:     cmdlist_append(cmd, cmdlist);
                    196:     return cmdlist;
                    197: }
                    198: 
                    199: /*
                    200:  * Return the tree for a unary ampersand operator.
                    201:  */
                    202: 
                    203: public Node amper(p)
                    204: Node p;
                    205: {
                    206:     Node r;
                    207: 
                    208:     checkref(p);
                    209:     switch (p->op) {
                    210:        case O_RVAL:
                    211:            r = p->value.arg[0];
                    212:            break;
                    213: 
                    214:        case O_CALL:
                    215:            r = build(O_LCON, codeloc(p->value.arg[0]->value.sym));
                    216:            tfree(p);
                    217:            break;
                    218: 
                    219:        case O_SYM:
                    220:            if (isblock(p->value.sym)) {
                    221:                r = build(O_LCON, codeloc(p->value.sym));
                    222:            } else {
                    223:                r = build(O_LCON, address(p->value.sym, nil));
                    224:            }
                    225:            tfree(p);
                    226:            break;
                    227: 
                    228:        case O_DOT:
                    229:            r = p;
                    230:            break;
                    231: 
                    232:        case O_INDIR:
                    233:            r = p->value.arg[0];
                    234:            dispose(p);
                    235:            break;
                    236: 
                    237:        default:
                    238:            beginerrmsg();
                    239:            fprintf(stderr, "expected variable, found ");
                    240:            prtree(stderr, p);
                    241:            tfree(p);
                    242:            enderrmsg();
                    243:            /* NOTREACHED */
                    244:     }
                    245:     r->nodetype = t_int;
                    246:     return r;
                    247: }
                    248: 
                    249: /*
                    250:  * Create a "concrete" version of a node.
                    251:  * This is necessary when the type of the node contains
                    252:  * an unresolved type reference.
                    253:  */
                    254: 
                    255: public Node concrete(p)
                    256: Node p;
                    257: {
                    258:     findtype(p->nodetype);
                    259:     return build(O_INDIR, p);
                    260: }
                    261: 
                    262: /*
                    263:  * Print out a command.
                    264:  */
                    265: 
                    266: public printcmd(f, cmd)
                    267: File f;
                    268: Command cmd;
                    269: {
                    270:     register Integer i;
                    271:     register Command c;
                    272:     register Node p;
                    273: 
                    274:     switch (cmd->op) {
                    275:        case O_PRINTIFCHANGED:
                    276:        case O_PRINTSRCPOS:
                    277:        case O_STOPIFCHANGED:
                    278:        case O_TRACEON:
                    279:            break;
                    280: 
                    281:        case O_STEP:
                    282:            if (cmd->value.step.skipcalls) {
                    283:                fprintf(f, "next");
                    284:            } else {
                    285:                fprintf(f, "step");
                    286:            }
                    287:            if (not cmd->value.step.source) {
                    288:                fprintf(f, "i");
                    289:            }
                    290:            break;
                    291: 
                    292:        default:
                    293:            fprintf(f, "%s", opinfo[ord(cmd->op)].opstring);
                    294:            if (nargs(cmd->op) != 0) {
                    295:                fprintf(f, " ");
                    296:            }
                    297:            break;
                    298:     }
                    299:     switch (cmd->op) {
                    300:        case O_PRINTCALL:
                    301:        case O_PRINTRTN:
                    302:        case O_PROCRTN:
                    303:            fprintf(f, "%s", symname(cmd->value.sym));
                    304:            break;
                    305: 
                    306:        case O_PRINTSRCPOS:
                    307:            p = cmd->value.arg[0];
                    308:            if (p != nil and p->op != O_QLINE) {
                    309:                printf("trace ");
                    310:                prtree(f, p);
                    311:            }
                    312:            break;
                    313: 
                    314:        case O_CHFILE:
                    315:        case O_EDIT:
                    316:        case O_SOURCE:
                    317:            fprintf(f, "%s", cmd->value.scon);
                    318:            break;
                    319: 
                    320:        case O_DELETE:
                    321:        case O_CATCH:
                    322:        case O_IGNORE:
                    323:        case O_TRACEOFF:
                    324:            fprintf(f, "%d", cmd->value.lcon);
                    325:            break;
                    326: 
                    327:        case O_ADDEVENT:
                    328:        case O_ONCE:
                    329:        case O_IF:
                    330:            fprintf(f, " ");
                    331:            prtree(f, cmd->value.event.cond);
                    332:            fprintf(f, " { ");
                    333:            foreach (Command, c, cmd->value.event.actions)
                    334:                printcmd(f, c);
                    335:                if (not list_islast()) {
                    336:                    fprintf(f, ";");
                    337:                }
                    338:            endfor
                    339:            fprintf(f, " }", opinfo[ord(cmd->op)].opstring);
                    340:            break;
                    341: 
                    342:        case O_TRACEON:
                    343:            print_tracestop(f, cmd);
                    344:            break;
                    345: 
                    346:        case O_EXAMINE:
                    347:            prtree(f, cmd->value.examine.beginaddr);
                    348:            if (cmd->value.examine.endaddr != nil) {
                    349:                fprintf(f, ",");
                    350:                prtree(f, cmd->value.examine.endaddr);
                    351:            }
                    352:            fprintf(f, "/");
                    353:            if (cmd->value.examine.count > 1) {
                    354:                fprintf(f, "%d", cmd->value.examine.count);
                    355:            }
                    356:            fprintf("%s", cmd->value.examine.mode);
                    357:            break;
                    358: 
                    359:        default:
                    360:            if (nargs(cmd->op) != 0) {
                    361:                i = 0;
                    362:                for (;;) {
                    363:                    prtree(f, cmd->value.arg[i]);
                    364:                    ++i;
                    365:                if (i >= nargs(cmd->op)) break;
                    366:                    fprintf(f, " ");
                    367:                }
                    368:            }
                    369:            break;
                    370:     }
                    371: }
                    372: 
                    373: /*
                    374:  * Print out a trace/stop command name.
                    375:  */
                    376: 
                    377: #define fprintI(f, b) { if (b) fprintf(f, "i"); }
                    378: 
                    379: private print_tracestop(f, cmd)
                    380: File f;
                    381: Command cmd;
                    382: {
                    383:     register Command c, ifcmd, stopcmd;
                    384:     Boolean done;
                    385: 
                    386:     done = false;
                    387:     ifcmd = list_element(Command, list_head(cmd->value.trace.actions));
                    388:     checkref(ifcmd);
                    389:     if (ifcmd->op == O_IF) {
                    390:        stopcmd = list_element(Command, list_head(ifcmd->value.event.actions));
                    391:        checkref(stopcmd);
                    392:        if (stopcmd->op == O_STOPX) {
                    393:            fprintf(f, "stop");
                    394:            fprintI(f, cmd->value.trace.inst);
                    395:            fprintf(f, " if ");
                    396:            prtree(f, ifcmd->value.event.cond);
                    397:            done = true;
                    398:        }
                    399:     } else if (ifcmd->op == O_STOPIFCHANGED) {
                    400:        fprintf(f, "stop");
                    401:        fprintI(f, cmd->value.trace.inst);
                    402:        fprintf(f, " ");
                    403:        prtree(f, ifcmd->value.arg[0]);
                    404:        done = true;
                    405:     }
                    406:     if (not done) {
                    407:        fprintf(f, "%s ", cmd->value.trace.inst ? "tracei" : "trace");
                    408:        foreach (Command, c, cmd->value.trace.actions)
                    409:            printcmd(f, c);
                    410:            if (not list_islast()) {
                    411:                fprintf(f, ";");
                    412:            }
                    413:        endfor
                    414:     }
                    415: }
                    416: 
                    417: /*
                    418:  * Print out a tree.
                    419:  */
                    420: 
                    421: public prtree(f, p)
                    422: File f;
                    423: register Node p;
                    424: {
                    425:     register Node q;
                    426:     Operator op;
                    427: 
                    428:     if (p != nil) {
                    429:        op = p->op;
                    430:        if (ord(op) > ord(O_LASTOP)) {
                    431:            panic("bad op %d in prtree", p->op);
                    432:        }
                    433:        switch (op) {
                    434:            case O_NAME:
                    435:                fprintf(f, "%s", ident(p->value.name));
                    436:                break;
                    437: 
                    438:            case O_SYM:
                    439:                printname(f, p->value.sym);
                    440:                break;
                    441: 
                    442:            case O_QLINE:
                    443:                if (nlhdr.nfiles > 1) {
                    444:                    prtree(f, p->value.arg[0]);
                    445:                    fprintf(f, ":");
                    446:                }
                    447:                prtree(f, p->value.arg[1]);
                    448:                break;
                    449: 
                    450:            case O_LCON:
                    451:                if (compatible(p->nodetype, t_char)) {
                    452:                    fprintf(f, "'%c'", p->value.lcon);
                    453:                } else {
                    454:                    fprintf(f, "%d", p->value.lcon);
                    455:                }
                    456:                break;
                    457: 
                    458:            case O_FCON:
                    459:                fprintf(f, "%g", p->value.fcon);
                    460:                break;
                    461: 
                    462:            case O_SCON:
                    463:                fprintf(f, "\"%s\"", p->value.scon);
                    464:                break;
                    465: 
                    466:            case O_INDEX:
                    467:                prtree(f, p->value.arg[0]);
                    468:                fprintf(f, "[");
                    469:                prtree(f, p->value.arg[1]);
                    470:                fprintf(f, "]");
                    471:                break;
                    472: 
                    473:            case O_COMMA:
                    474:                prtree(f, p->value.arg[0]);
                    475:                if (p->value.arg[1] != nil) {
                    476:                    fprintf(f, ", ");
                    477:                    prtree(f, p->value.arg[1]);
                    478:                }
                    479:                break;
                    480: 
                    481:            case O_RVAL:
                    482:                if (p->value.arg[0]->op == O_SYM) {
                    483:                    printname(f, p->value.arg[0]->value.sym);
                    484:                } else {
                    485:                    prtree(f, p->value.arg[0]);
                    486:                }
                    487:                break;
                    488: 
                    489:            case O_ITOF:
                    490:                prtree(f, p->value.arg[0]);
                    491:                break;
                    492: 
                    493:            case O_CALL:
                    494:                prtree(f, p->value.arg[0]);
                    495:                if (p->value.arg[1]!= nil) {
                    496:                    fprintf(f, "(");
                    497:                    prtree(f, p->value.arg[1]);
                    498:                    fprintf(f, ")");
                    499:                }
                    500:                break;
                    501: 
                    502:            case O_INDIR:
                    503:                q = p->value.arg[0];
                    504:                if (isvarparam(q->nodetype)) {
                    505:                    prtree(f, q);
                    506:                } else {
                    507:                    if (q->op == O_SYM or q->op == O_LCON or q->op == O_DOT) {
                    508:                        prtree(f, q);
                    509:                        fprintf(f, "^");
                    510:                    } else {
                    511:                        fprintf(f, "*(");
                    512:                        prtree(f, q);
                    513:                        fprintf(f, ")");
                    514:                    }
                    515:                }
                    516:                break;
                    517: 
                    518:            case O_DOT:
                    519:                q = p->value.arg[0];
                    520:                if (q->op == O_INDIR) {
                    521:                    prtree(f, q->value.arg[0]);
                    522:                } else {
                    523:                    prtree(f, q);
                    524:                }
                    525:                fprintf(f, ".%s", symname(p->value.arg[1]->value.sym));
                    526:                break;
                    527: 
                    528:            default:
                    529:                switch (degree(op)) {
                    530:                    case BINARY:
                    531:                        prtree(f, p->value.arg[0]);
                    532:                        fprintf(f, "%s", opinfo[ord(op)].opstring);
                    533:                        prtree(f, p->value.arg[1]);
                    534:                        break;
                    535: 
                    536:                    case UNARY:
                    537:                        fprintf(f, "%s", opinfo[ord(op)].opstring);
                    538:                        prtree(f, p->value.arg[0]);
                    539:                        break;
                    540: 
                    541:                    default:
                    542:                        error("internal error: bad op %d in prtree", op);
                    543:                }
                    544:                break;
                    545:        }
                    546:     }
                    547: }
                    548: 
                    549: /*
                    550:  * Free storage associated with a tree.
                    551:  */
                    552: 
                    553: public tfree(p)
                    554: Node p;
                    555: {
                    556:     Integer i;
                    557: 
                    558:     if (p == nil) {
                    559:        return;
                    560:     }
                    561:     switch (p->op) {
                    562:        case O_QLINE:
                    563:            dispose(p->value.arg[0]->value.scon);
                    564:            dispose(p->value.arg[0]);
                    565:            tfree(p->value.arg[1]);
                    566:            break;
                    567: 
                    568:        case O_SCON:
                    569:            unmkstring(p->nodetype);
                    570:            dispose(p->nodetype);
                    571:            dispose(p->value.scon);
                    572:            break;
                    573: 
                    574:        default:
                    575:            for (i = 0; i < nargs(p->op); i++) {
                    576:                tfree(p->value.arg[i]);
                    577:            }
                    578:            break;
                    579:     }
                    580:     dispose(p);
                    581: }
                    582: 
                    583: /*
                    584:  * A recursive tree search routine to test if two trees * are equivalent.
                    585:  */
                    586: 
                    587: public Boolean tr_equal(t1, t2)
                    588: register Node t1;
                    589: register Node t2;
                    590: {
                    591:     register Boolean b;
                    592: 
                    593:     if (t1 == nil and t2 == nil) {
                    594:        b = true;
                    595:     } else if (t1 == nil or t2 == nil) {
                    596:        b = false;
                    597:     } else if (t1->op != t2->op or degree(t1->op) != degree(t2->op)) {
                    598:        b = false;
                    599:     } else {
                    600:        switch (degree(t1->op)) {
                    601:            case LEAF:
                    602:                switch (t1->op) {
                    603:                    case O_NAME:
                    604:                        b = (Boolean) (t1->value.name == t2->value.name);
                    605:                        break;
                    606: 
                    607:                    case O_SYM:
                    608:                        b = (Boolean) (t1->value.sym == t2->value.sym);
                    609:                        break;
                    610: 
                    611:                    case O_LCON:
                    612:                        b = (Boolean) (t1->value.lcon == t2->value.lcon);
                    613:                        break;
                    614: 
                    615:                    case O_FCON:
                    616:                        b = (Boolean) (t1->value.fcon == t2->value.fcon);
                    617:                        break;
                    618: 
                    619:                    case O_SCON:
                    620:                        b = (Boolean) (t1->value.scon == t2->value.scon);
                    621:                        break;
                    622: 
                    623:                    default:
                    624:                        panic("tr_equal: leaf %d\n", t1->op);
                    625:                }
                    626:                /*NOTREACHED*/
                    627: 
                    628:            case BINARY:
                    629:                if (not tr_equal(t1->value.arg[0], t2->value.arg[0])) {
                    630:                    b = false;
                    631:                } else {
                    632:                    b = tr_equal(t1->value.arg[1], t2->value.arg[1]);
                    633:                }
                    634:                break;
                    635: 
                    636:            case UNARY:
                    637:                b = tr_equal(t1->value.arg[0], t2->value.arg[0]);
                    638:                break;
                    639: 
                    640:            default:
                    641:                panic("tr_equal: bad degree for op %d\n", t1->op);
                    642:        }
                    643:     }
                    644:     return b;
                    645: }

unix.superglobalmegacorp.com

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