Annotation of 43BSDReno/pgrm/dbx/eval.c, revision 1.1

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[] = "@(#)eval.c     5.7 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: /*
        !            25:  * Tree evaluation.
        !            26:  */
        !            27: 
        !            28: #include "defs.h"
        !            29: #include "tree.h"
        !            30: #include "operators.h"
        !            31: #include "debug.h"
        !            32: #include "eval.h"
        !            33: #include "events.h"
        !            34: #include "symbols.h"
        !            35: #include "scanner.h"
        !            36: #include "source.h"
        !            37: #include "object.h"
        !            38: #include "mappings.h"
        !            39: #include "process.h"
        !            40: #include "runtime.h"
        !            41: #include "machine.h"
        !            42: #include <signal.h>
        !            43: 
        !            44: #ifndef public
        !            45: 
        !            46: #include "machine.h"
        !            47: 
        !            48: #define STACKSIZE 20000
        !            49: 
        !            50: typedef Char Stack;
        !            51: 
        !            52: #define push(type, value) { \
        !            53:     ((type *) (sp += sizeof(type)))[-1] = (value); \
        !            54: }
        !            55: 
        !            56: #define pop(type) ( \
        !            57:     (*((type *) (sp -= sizeof(type)))) \
        !            58: )
        !            59: 
        !            60: #define popn(n, dest) { \
        !            61:     sp -= n; \
        !            62:     bcopy(sp, dest, n); \
        !            63: }
        !            64: 
        !            65: #define alignstack() { \
        !            66:     sp = (Stack *) (( ((int) sp) + sizeof(int) - 1)&~(sizeof(int) - 1)); \
        !            67: }
        !            68: 
        !            69: #endif
        !            70: 
        !            71: public Stack stack[STACKSIZE];
        !            72: public Stack *sp = &stack[0];
        !            73: public Boolean useInstLoc = false;
        !            74: 
        !            75: #define chksp() \
        !            76: { \
        !            77:     if (sp < &stack[0]) { \
        !            78:        panic("stack underflow"); \
        !            79:     } \
        !            80: }
        !            81: 
        !            82: #define poparg(n, r, fr) { \
        !            83:     eval(p->value.arg[n]); \
        !            84:     if (isreal(p->op)) { \
        !            85:        if (size(p->value.arg[n]->nodetype) == sizeof(float)) { \
        !            86:            fr = pop(float); \
        !            87:        } else { \
        !            88:            fr = pop(double); \
        !            89:        } \
        !            90:     } else if (isint(p->op)) { \
        !            91:        r = popsmall(p->value.arg[n]->nodetype); \
        !            92:     } \
        !            93: }
        !            94: 
        !            95: #define Boolrep char   /* underlying representation type for booleans */
        !            96: 
        !            97: /*
        !            98:  * Command-level evaluation.
        !            99:  */
        !           100: 
        !           101: public Node topnode;
        !           102: 
        !           103: public topeval (p)
        !           104: Node p;
        !           105: {
        !           106:     if (traceeval) {
        !           107:        fprintf(stderr, "topeval(");
        !           108:        prtree(stderr, p);
        !           109:        fprintf(stderr, ")\n");
        !           110:        fflush(stderr);
        !           111:     }
        !           112:     topnode = p;
        !           113:     eval(p);
        !           114: }
        !           115: 
        !           116: /*
        !           117:  * Evaluate a parse tree leaving the value on the top of the stack.
        !           118:  */
        !           119: 
        !           120: public eval(p)
        !           121: register Node p;
        !           122: {
        !           123:     long r0, r1;
        !           124:     double fr0, fr1;
        !           125:     Address addr;
        !           126:     long i, n;
        !           127:     int len;
        !           128:     Symbol s;
        !           129:     Node n1, n2;
        !           130:     boolean b;
        !           131:     File file;
        !           132:     String str;
        !           133: 
        !           134:     checkref(p);
        !           135:     if (traceeval) {
        !           136:        fprintf(stderr, "begin eval %s\n", opname(p->op));
        !           137:     }
        !           138:     switch (degree(p->op)) {
        !           139:        case BINARY:
        !           140:            poparg(1, r1, fr1);
        !           141:            poparg(0, r0, fr0);
        !           142:            break;
        !           143: 
        !           144:        case UNARY:
        !           145:            poparg(0, r0, fr0);
        !           146:            break;
        !           147: 
        !           148:        default:
        !           149:            /* do nothing */;
        !           150:     }
        !           151:     switch (p->op) {
        !           152:        case O_SYM:
        !           153:            s = p->value.sym;
        !           154:            if (s == retaddrsym) {
        !           155:                push(long, return_addr());
        !           156:            } else if (isvariable(s)) {
        !           157:                if (s != program and not isactive(container(s))) {
        !           158:                    error("\"%s\" is not active", symname(s));
        !           159:                }
        !           160:                if (isvarparam(s) and not isopenarray(s)) {
        !           161:                    rpush(address(s, nil), sizeof(Address));
        !           162:                } else {
        !           163:                    push(Address, address(s, nil));
        !           164:                }
        !           165:            } else if (isblock(s)) {
        !           166:                push(Symbol, s);
        !           167:            } else if (isconst(s)) {
        !           168:                eval(constval(s));
        !           169:            } else {
        !           170:                error("can't evaluate a %s", classname(s));
        !           171:            }
        !           172:            break;
        !           173: 
        !           174:        case O_LCON:
        !           175:        case O_CCON:
        !           176:            r0 = p->value.lcon;
        !           177:            pushsmall(p->nodetype, r0);
        !           178:            break;
        !           179: 
        !           180:        case O_FCON:
        !           181:            push(double, p->value.fcon);
        !           182:            break;
        !           183: 
        !           184:        case O_SCON:
        !           185:            len = size(p->nodetype);
        !           186:            mov(p->value.scon, sp, len);
        !           187:            sp += len;
        !           188:            break;
        !           189: 
        !           190:        case O_INDEX:
        !           191:            s = p->value.arg[0]->nodetype;
        !           192:            p->value.arg[0]->nodetype = t_addr;
        !           193:            eval(p->value.arg[0]);
        !           194:            p->value.arg[0]->nodetype = s;
        !           195:            n = pop(Address);
        !           196:            eval(p->value.arg[1]);
        !           197:            evalindex(s, n, popsmall(p->value.arg[1]->nodetype));
        !           198:            break;
        !           199: 
        !           200:        case O_DOT:
        !           201:            s = p->value.arg[1]->value.sym;
        !           202:            eval(p->value.arg[0]);
        !           203:            n = pop(long);
        !           204:            push(long, n + (s->symvalue.field.offset div 8));
        !           205:            break;
        !           206: 
        !           207:        /*
        !           208:         * Get the value of the expression addressed by the top of the stack.
        !           209:         * Push the result back on the stack.
        !           210:         */
        !           211: 
        !           212:        case O_INDIR:
        !           213:        case O_RVAL:
        !           214:            addr = pop(long);
        !           215:            if (addr == 0) {
        !           216:                error("reference through nil pointer");
        !           217:            }
        !           218:            len = size(p->nodetype);
        !           219:            rpush(addr, len);
        !           220:            break;
        !           221: 
        !           222:        case O_TYPERENAME:
        !           223:            loophole(size(p->value.arg[0]->nodetype), size(p->nodetype));
        !           224:            break;
        !           225: 
        !           226:        case O_COMMA:
        !           227:            eval(p->value.arg[0]);
        !           228:            if (p->value.arg[1] != nil) {
        !           229:                eval(p->value.arg[1]);
        !           230:            }
        !           231:            break;
        !           232: 
        !           233:        case O_ITOF:
        !           234:            push(double, (double) r0);
        !           235:            break;
        !           236: 
        !           237:        case O_ADD:
        !           238:            push(long, r0+r1);
        !           239:            break;
        !           240: 
        !           241:        case O_ADDF:
        !           242:            push(double, fr0+fr1);
        !           243:            break;
        !           244: 
        !           245:        case O_SUB:
        !           246:            push(long, r0-r1);
        !           247:            break;
        !           248: 
        !           249:        case O_SUBF:
        !           250:            push(double, fr0-fr1);
        !           251:            break;
        !           252: 
        !           253:        case O_NEG:
        !           254:            push(long, -r0);
        !           255:            break;
        !           256: 
        !           257:        case O_NEGF:
        !           258:            push(double, -fr0);
        !           259:            break;
        !           260: 
        !           261:        case O_MUL:
        !           262:            push(long, r0*r1);
        !           263:            break;
        !           264: 
        !           265:        case O_MULF:
        !           266:            push(double, fr0*fr1);
        !           267:            break;
        !           268: 
        !           269:        case O_DIVF:
        !           270:            if (fr1 == 0) {
        !           271:                error("error: division by 0");
        !           272:            }
        !           273:            push(double, fr0 / fr1);
        !           274:            break;
        !           275: 
        !           276:        case O_DIV:
        !           277:            if (r1 == 0) {
        !           278:                error("error: div by 0");
        !           279:            }
        !           280:            push(long, r0 div r1);
        !           281:            break;
        !           282: 
        !           283:        case O_MOD:
        !           284:            if (r1 == 0) {
        !           285:                error("error: mod by 0");
        !           286:            }
        !           287:            push(long, r0 mod r1);
        !           288:            break;
        !           289: 
        !           290:        case O_LT:
        !           291:            push(Boolrep, r0 < r1);
        !           292:            break;
        !           293: 
        !           294:        case O_LTF:
        !           295:            push(Boolrep, fr0 < fr1);
        !           296:            break;
        !           297: 
        !           298:        case O_LE:
        !           299:            push(Boolrep, r0 <= r1);
        !           300:            break;
        !           301: 
        !           302:        case O_LEF:
        !           303:            push(Boolrep, fr0 <= fr1);
        !           304:            break;
        !           305: 
        !           306:        case O_GT:
        !           307:            push(Boolrep, r0 > r1);
        !           308:            break;
        !           309: 
        !           310:        case O_GTF:
        !           311:            push(Boolrep, fr0 > fr1);
        !           312:            break;
        !           313: 
        !           314:        case O_EQ:
        !           315:            push(Boolrep, r0 == r1);
        !           316:            break;
        !           317: 
        !           318:        case O_EQF:
        !           319:            push(Boolrep, fr0 == fr1);
        !           320:            break;
        !           321: 
        !           322:        case O_NE:
        !           323:            push(Boolrep, r0 != r1);
        !           324:            break;
        !           325: 
        !           326:        case O_NEF:
        !           327:            push(Boolrep, fr0 != fr1);
        !           328:            break;
        !           329: 
        !           330:        case O_AND:
        !           331:            push(Boolrep, r0 and r1);
        !           332:            break;
        !           333: 
        !           334:        case O_OR:
        !           335:            push(Boolrep, r0 or r1);
        !           336:            break;
        !           337: 
        !           338:        case O_ASSIGN:
        !           339:            assign(p->value.arg[0], p->value.arg[1]);
        !           340:            break;
        !           341: 
        !           342:        case O_CHFILE:
        !           343:            if (p->value.scon == nil) {
        !           344:                printf("%s\n", cursource);
        !           345:            } else {
        !           346:                file = opensource(p->value.scon);
        !           347:                if (file == nil) {
        !           348:                    error("can't read \"%s\"", p->value.scon);
        !           349:                } else {
        !           350:                    fclose(file);
        !           351:                    setsource(p->value.scon);
        !           352:                }
        !           353:            }
        !           354:            break;
        !           355: 
        !           356:        case O_CONT:
        !           357:            cont(p->value.lcon);
        !           358:            printnews();
        !           359:            break;
        !           360: 
        !           361:        case O_LIST:
        !           362:            list(p);
        !           363:            break;
        !           364: 
        !           365:        case O_FUNC:
        !           366:            func(p->value.arg[0]);
        !           367:            break;
        !           368: 
        !           369:        case O_EXAMINE:
        !           370:            eval(p->value.examine.beginaddr);
        !           371:            r0 = pop(long);
        !           372:            if (p->value.examine.endaddr == nil) {
        !           373:                n = p->value.examine.count;
        !           374:                if (n == 0) {
        !           375:                    printvalue(r0, p->value.examine.mode);
        !           376:                } else if (streq(p->value.examine.mode, "i")) {
        !           377:                    printninst(n, (Address) r0);
        !           378:                } else {
        !           379:                    printndata(n, (Address) r0, p->value.examine.mode);
        !           380:                }
        !           381:            } else {
        !           382:                eval(p->value.examine.endaddr);
        !           383:                r1 = pop(long);
        !           384:                if (streq(p->value.examine.mode, "i")) {
        !           385:                    printinst((Address)r0, (Address)r1);
        !           386:                } else {
        !           387:                    printdata((Address)r0, (Address)r1, p->value.examine.mode);
        !           388:                }
        !           389:            }
        !           390:            break;
        !           391: 
        !           392:        case O_PRINT:
        !           393:            for (n1 = p->value.arg[0]; n1 != nil; n1 = n1->value.arg[1]) {
        !           394:                eval(n1->value.arg[0]);
        !           395:                printval(n1->value.arg[0]->nodetype);
        !           396:                putchar(' ');
        !           397:            }
        !           398:            putchar('\n');
        !           399:            break;
        !           400: 
        !           401:        case O_PSYM:
        !           402:            if (p->value.arg[0]->op == O_SYM) {
        !           403:                psym(p->value.arg[0]->value.sym);
        !           404:            } else {
        !           405:                psym(p->value.arg[0]->nodetype);
        !           406:            }
        !           407:            break;
        !           408: 
        !           409:        case O_QLINE:
        !           410:            eval(p->value.arg[1]);
        !           411:            break;
        !           412: 
        !           413:        case O_STEP:
        !           414:            b = inst_tracing;
        !           415:            inst_tracing = (Boolean) (not p->value.step.source);
        !           416:            if (p->value.step.skipcalls) {
        !           417:                next();
        !           418:            } else {
        !           419:                stepc();
        !           420:            }
        !           421:            inst_tracing = b;
        !           422:            useInstLoc = (Boolean) (not p->value.step.source);
        !           423:            printnews();
        !           424:            break;
        !           425: 
        !           426:        case O_WHATIS:
        !           427:            if (p->value.arg[0]->op == O_SYM) {
        !           428:                printdecl(p->value.arg[0]->value.sym);
        !           429:            } else {
        !           430:                printdecl(p->value.arg[0]->nodetype);
        !           431:            }
        !           432:            break;
        !           433: 
        !           434:        case O_WHERE:
        !           435:            wherecmd();
        !           436:            break;
        !           437: 
        !           438:        case O_WHEREIS:
        !           439:            if (p->value.arg[0]->op == O_SYM) {
        !           440:                printwhereis(stdout, p->value.arg[0]->value.sym);
        !           441:            } else {
        !           442:                printwhereis(stdout, p->value.arg[0]->nodetype);
        !           443:            }
        !           444:            break;
        !           445: 
        !           446:        case O_WHICH:
        !           447:            if (p->value.arg[0]->op == O_SYM) {
        !           448:                printwhich(stdout, p->value.arg[0]->value.sym);
        !           449:            } else {
        !           450:                printwhich(stdout, p->value.arg[0]->nodetype);
        !           451:            }
        !           452:            putchar('\n');
        !           453:            break;
        !           454: 
        !           455:        case O_ALIAS:
        !           456:            n1 = p->value.arg[0];
        !           457:            n2 = p->value.arg[1];
        !           458:            if (n2 == nil) {
        !           459:                if (n1 == nil) {
        !           460:                    alias(nil, nil, nil);
        !           461:                } else {
        !           462:                    alias(n1->value.name, nil, nil);
        !           463:                }
        !           464:            } else if (n2->op == O_NAME) {
        !           465:                str = ident(n2->value.name);
        !           466:                alias(n1->value.name, nil, strdup(str));
        !           467:            } else {
        !           468:                if (n1->op == O_COMMA) {
        !           469:                    alias(
        !           470:                        n1->value.arg[0]->value.name,
        !           471:                        (List) n1->value.arg[1],
        !           472:                        n2->value.scon
        !           473:                    );
        !           474:                } else {
        !           475:                    alias(n1->value.name, nil, n2->value.scon);
        !           476:                }
        !           477:            }
        !           478:            break;
        !           479: 
        !           480:        case O_UNALIAS:
        !           481:            unalias(p->value.arg[0]->value.name);
        !           482:            break;
        !           483: 
        !           484:        case O_CALLPROC:
        !           485:            callproc(p, false);
        !           486:            break;
        !           487: 
        !           488:        case O_CALL:
        !           489:            callproc(p, true);
        !           490:            break;
        !           491: 
        !           492:        case O_CATCH:
        !           493:            if (p->value.lcon == 0) {
        !           494:                printsigscaught(process);
        !           495:            } else {
        !           496:                psigtrace(process, p->value.lcon, true);
        !           497:            }
        !           498:            break;
        !           499: 
        !           500:        case O_EDIT:
        !           501:            edit(p->value.scon);
        !           502:            break;
        !           503: 
        !           504:         case O_DEBUG:
        !           505:             debug(p);
        !           506:            break;
        !           507: 
        !           508:        case O_DOWN:
        !           509:            checkref(p->value.arg[0]);
        !           510:            assert(p->value.arg[0]->op == O_LCON);
        !           511:            down(p->value.arg[0]->value.lcon);
        !           512:            break;
        !           513: 
        !           514:        case O_DUMP:
        !           515:            if (p->value.arg[0] == nil) {
        !           516:                dumpall();
        !           517:            } else {
        !           518:                s = p->value.arg[0]->value.sym;
        !           519:                if (s == curfunc) {
        !           520:                    dump(nil);
        !           521:                } else {
        !           522:                    dump(s);
        !           523:                }
        !           524:            }
        !           525:            break;
        !           526: 
        !           527:        case O_GRIPE:
        !           528:            gripe();
        !           529:            break;
        !           530: 
        !           531:        case O_HELP:
        !           532:            help();
        !           533:            break;
        !           534: 
        !           535:        case O_IGNORE:
        !           536:            if (p->value.lcon == 0) {
        !           537:                printsigsignored(process);
        !           538:            } else {
        !           539:                psigtrace(process, p->value.lcon, false);
        !           540:            }
        !           541:            break;
        !           542: 
        !           543:        case O_RETURN:
        !           544:            if (p->value.arg[0] == nil) {
        !           545:                rtnfunc(nil);
        !           546:            } else {
        !           547:                assert(p->value.arg[0]->op == O_SYM);
        !           548:                rtnfunc(p->value.arg[0]->value.sym);
        !           549:            }
        !           550:            break;
        !           551: 
        !           552:        case O_RUN:
        !           553:            run();
        !           554:            break;
        !           555: 
        !           556:        case O_SET:
        !           557:            set(p->value.arg[0], p->value.arg[1]);
        !           558:            break;
        !           559: 
        !           560:        case O_SEARCH:
        !           561:            search(p->value.arg[0]->value.lcon, p->value.arg[1]->value.scon);
        !           562:            break;
        !           563: 
        !           564:        case O_SOURCE:
        !           565:            setinput(p->value.scon);
        !           566:            break;
        !           567: 
        !           568:        case O_STATUS:
        !           569:            status();
        !           570:            break;
        !           571: 
        !           572:        case O_TRACE:
        !           573:        case O_TRACEI:
        !           574:            trace(p);
        !           575:            break;
        !           576: 
        !           577:        case O_STOP:
        !           578:        case O_STOPI:
        !           579:            stop(p);
        !           580:            break;
        !           581: 
        !           582:        case O_UNSET:
        !           583:            undefvar(p->value.arg[0]->value.name);
        !           584:            break;
        !           585: 
        !           586:        case O_UP:
        !           587:            checkref(p->value.arg[0]);
        !           588:            assert(p->value.arg[0]->op == O_LCON);
        !           589:            up(p->value.arg[0]->value.lcon);
        !           590:            break;
        !           591: 
        !           592:        case O_ADDEVENT:
        !           593:            addevent(p->value.event.cond, p->value.event.actions);
        !           594:            break;
        !           595: 
        !           596:        case O_DELETE:
        !           597:            n1 = p->value.arg[0];
        !           598:            while (n1->op == O_COMMA) {
        !           599:                n2 = n1->value.arg[0];
        !           600:                assert(n2->op == O_LCON);
        !           601:                if (not delevent((unsigned int) n2->value.lcon)) {
        !           602:                    error("unknown event %ld", n2->value.lcon);
        !           603:                }
        !           604:                n1 = n1->value.arg[1];
        !           605:            }
        !           606:            assert(n1->op == O_LCON);
        !           607:            if (not delevent((unsigned int) n1->value.lcon)) {
        !           608:                error("unknown event %ld", n1->value.lcon);
        !           609:            }
        !           610:            break;
        !           611: 
        !           612:        case O_ENDX:
        !           613:            endprogram();
        !           614:            break;
        !           615: 
        !           616:        case O_IF:
        !           617:            if (cond(p->value.event.cond)) {
        !           618:                evalcmdlist(p->value.event.actions);
        !           619:            }
        !           620:            break;
        !           621: 
        !           622:        case O_ONCE:
        !           623:            event_once(p->value.event.cond, p->value.event.actions);
        !           624:            break;
        !           625: 
        !           626:        case O_PRINTCALL:
        !           627:            printcall(p->value.sym, whatblock(return_addr()));
        !           628:            break;
        !           629: 
        !           630:        case O_PRINTIFCHANGED:
        !           631:            printifchanged(p->value.arg[0]);
        !           632:            break;
        !           633: 
        !           634:        case O_PRINTRTN:
        !           635:            printrtn(p->value.sym);
        !           636:            break;
        !           637: 
        !           638:        case O_PRINTSRCPOS:
        !           639:            getsrcpos();
        !           640:            if (p->value.arg[0] == nil) {
        !           641:                printsrcpos();
        !           642:                putchar('\n');
        !           643:                printlines(curline, curline);
        !           644:            } else if (p->value.arg[0]->op == O_QLINE) {
        !           645:                if (p->value.arg[0]->value.arg[1]->value.lcon == 0) {
        !           646:                    printf("tracei: ");
        !           647:                    printinst(pc, pc);
        !           648:                } else {
        !           649:                    if (canReadSource()) {
        !           650:                        printf("trace:  ");
        !           651:                        printlines(curline, curline);
        !           652:                    }
        !           653:                }
        !           654:            } else {
        !           655:                printsrcpos();
        !           656:                printf(": ");
        !           657:                eval(p->value.arg[0]);
        !           658:                prtree(stdout, p->value.arg[0]);
        !           659:                printf(" = ");
        !           660:                printval(p->value.arg[0]->nodetype);
        !           661:                putchar('\n');
        !           662:            }
        !           663:            break;
        !           664: 
        !           665:        case O_PROCRTN:
        !           666:            procreturn(p->value.sym);
        !           667:            break;
        !           668: 
        !           669:        case O_STOPIFCHANGED:
        !           670:            stopifchanged(p->value.arg[0]);
        !           671:            break;
        !           672: 
        !           673:        case O_STOPX:
        !           674:            isstopped = true;
        !           675:            break;
        !           676: 
        !           677:        case O_TRACEON:
        !           678:            traceon(p->value.trace.inst, p->value.trace.event,
        !           679:                p->value.trace.actions);
        !           680:            break;
        !           681: 
        !           682:        case O_TRACEOFF:
        !           683:            traceoff(p->value.lcon);
        !           684:            break;
        !           685: 
        !           686:        default:
        !           687:            panic("eval: bad op %d", p->op);
        !           688:     }
        !           689:     if (traceeval) { 
        !           690:        fprintf(stderr, "end eval %s\n", opname(p->op));
        !           691:     }
        !           692: }
        !           693: 
        !           694: /*
        !           695:  * Evaluate a list of commands.
        !           696:  */
        !           697: 
        !           698: public evalcmdlist(cl)
        !           699: Cmdlist cl;
        !           700: {
        !           701:     Command c;
        !           702: 
        !           703:     foreach (Command, c, cl)
        !           704:        evalcmd(c);
        !           705:     endfor
        !           706: }
        !           707: 
        !           708: /*
        !           709:  * Push "len" bytes onto the expression stack from address "addr"
        !           710:  * in the process.  If there isn't room on the stack, print an error message.
        !           711:  */
        !           712: 
        !           713: public rpush(addr, len)
        !           714: Address addr;
        !           715: int len;
        !           716: {
        !           717:     if (not canpush(len)) {
        !           718:        error("expression too large to evaluate");
        !           719:     } else {
        !           720:        chksp();
        !           721:        dread(sp, addr, len);
        !           722:        sp += len;
        !           723:     }
        !           724: }
        !           725: 
        !           726: /*
        !           727:  * Check if the stack has n bytes available.
        !           728:  */
        !           729: 
        !           730: public Boolean canpush(n)
        !           731: Integer n;
        !           732: {
        !           733:     return (Boolean) (sp + n < &stack[STACKSIZE]);
        !           734: }
        !           735: 
        !           736: /*
        !           737:  * Push a small scalar of the given type onto the stack.
        !           738:  */
        !           739: 
        !           740: public pushsmall(t, v)
        !           741: Symbol t;
        !           742: long v;
        !           743: {
        !           744:     register Integer s;
        !           745: 
        !           746:     s = size(t);
        !           747:     switch (s) {
        !           748:        case sizeof(char):
        !           749:            push(char, v);
        !           750:            break;
        !           751: 
        !           752:        case sizeof(short):
        !           753:            push(short, v);
        !           754:            break;
        !           755: 
        !           756:        case sizeof(long):
        !           757:            push(long, v);
        !           758:            break;
        !           759: 
        !           760:        default:
        !           761:            panic("bad size %d in popsmall", s);
        !           762:     }
        !           763: }
        !           764: 
        !           765: /*
        !           766:  * Pop an item of the given type which is assumed to be no larger
        !           767:  * than a long and return it expanded into a long.
        !           768:  */
        !           769: 
        !           770: public long popsmall(t)
        !           771: Symbol t;
        !           772: {
        !           773:     register integer n;
        !           774:     long r;
        !           775: 
        !           776:     n = size(t);
        !           777:     if (n == sizeof(char)) {
        !           778:        if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
        !           779:            r = (long) pop(unsigned char);
        !           780:        } else {
        !           781:            r = (long) pop(char);
        !           782:        }
        !           783:     } else if (n == sizeof(short)) {
        !           784:        if (t->class == RANGE and t->symvalue.rangev.lower >= 0) {
        !           785:            r = (long) pop(unsigned short);
        !           786:        } else {
        !           787:            r = (long) pop(short);
        !           788:        }
        !           789:     } else if (n == sizeof(long)) {
        !           790:        r = pop(long);
        !           791:     } else {
        !           792:        error("[internal error: size %d in popsmall]", n);
        !           793:     }
        !           794:     return r;
        !           795: }
        !           796: 
        !           797: /*
        !           798:  * Evaluate a conditional expression.
        !           799:  */
        !           800: 
        !           801: public Boolean cond(p)
        !           802: Node p;
        !           803: {
        !           804:     Boolean b;
        !           805:     int i;
        !           806: 
        !           807:     if (p == nil) {
        !           808:        b = true;
        !           809:     } else {
        !           810:        eval(p);
        !           811:        i = pop(Boolrep);
        !           812:        b = (Boolean) i;
        !           813:     }
        !           814:     return b;
        !           815: }
        !           816: 
        !           817: /*
        !           818:  * Return the address corresponding to a given tree.
        !           819:  */
        !           820: 
        !           821: public Address lval(p)
        !           822: Node p;
        !           823: {
        !           824:     if (p->op == O_RVAL) {
        !           825:        eval(p->value.arg[0]);
        !           826:     } else {
        !           827:        eval(p);
        !           828:     }
        !           829:     return (Address) (pop(long));
        !           830: }
        !           831: 
        !           832: /*
        !           833:  * Process a trace command, translating into the appropriate events
        !           834:  * and associated actions.
        !           835:  */
        !           836: 
        !           837: public trace(p)
        !           838: Node p;
        !           839: {
        !           840:     Node exp, place, cond;
        !           841:     Node left;
        !           842: 
        !           843:     exp = p->value.arg[0];
        !           844:     place = p->value.arg[1];
        !           845:     cond = p->value.arg[2];
        !           846:     if (exp == nil) {
        !           847:        traceall(p->op, place, cond);
        !           848:     } else if (exp->op == O_QLINE or exp->op == O_LCON) {
        !           849:        traceinst(p->op, exp, cond);
        !           850:     } else if (place != nil and place->op == O_QLINE) {
        !           851:        traceat(p->op, exp, place, cond);
        !           852:     } else {
        !           853:        left = exp;
        !           854:        if (left->op == O_RVAL or left->op == O_CALL) {
        !           855:            left = left->value.arg[0];
        !           856:        }
        !           857:        if (left->op == O_SYM and isblock(left->value.sym)) {
        !           858:            traceproc(p->op, left->value.sym, place, cond);
        !           859:        } else {
        !           860:            tracedata(p->op, exp, place, cond);
        !           861:        }
        !           862:     }
        !           863: }
        !           864: 
        !           865: /*
        !           866:  * Set a breakpoint that will turn on tracing.
        !           867:  */
        !           868: 
        !           869: private traceall(op, place, cond)
        !           870: Operator op;
        !           871: Node place;
        !           872: Node cond;
        !           873: {
        !           874:     Symbol s;
        !           875:     Node event;
        !           876:     Command action;
        !           877: 
        !           878:     if (place == nil) {
        !           879:        s = program;
        !           880:     } else {
        !           881:        s = place->value.sym;
        !           882:     }
        !           883:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
        !           884:     action = build(O_PRINTSRCPOS,
        !           885:        build(O_QLINE, nil, build(O_LCON, (op == O_TRACE) ? 1 : 0)));
        !           886:     if (cond != nil) {
        !           887:        action = build(O_IF, cond, buildcmdlist(action));
        !           888:     }
        !           889:     action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
        !           890:     action->value.trace.event = addevent(event, buildcmdlist(action));
        !           891:     if (isstdin()) {
        !           892:        printevent(action->value.trace.event);
        !           893:     }
        !           894: }
        !           895: 
        !           896: /*
        !           897:  * Set up the appropriate breakpoint for tracing an instruction.
        !           898:  */
        !           899: 
        !           900: private traceinst(op, exp, cond)
        !           901: Operator op;
        !           902: Node exp;
        !           903: Node cond;
        !           904: {
        !           905:     Node event, wh;
        !           906:     Command action;
        !           907:     Event e;
        !           908: 
        !           909:     if (exp->op == O_LCON) {
        !           910:        wh = build(O_QLINE, build(O_SCON, strdup(cursource)), exp);
        !           911:     } else {
        !           912:        wh = exp;
        !           913:     }
        !           914:     if (op == O_TRACEI) {
        !           915:        event = build(O_EQ, build(O_SYM, pcsym), wh);
        !           916:     } else {
        !           917:        event = build(O_EQ, build(O_SYM, linesym), wh);
        !           918:     }
        !           919:     action = build(O_PRINTSRCPOS, wh);
        !           920:     if (cond) {
        !           921:        action = build(O_IF, cond, buildcmdlist(action));
        !           922:     }
        !           923:     e = addevent(event, buildcmdlist(action));
        !           924:     if (isstdin()) {
        !           925:        printevent(e);
        !           926:     }
        !           927: }
        !           928: 
        !           929: /*
        !           930:  * Set a breakpoint to print an expression at a given line or address.
        !           931:  */
        !           932: 
        !           933: private traceat(op, exp, place, cond)
        !           934: Operator op;
        !           935: Node exp;
        !           936: Node place;
        !           937: Node cond;
        !           938: {
        !           939:     Node event;
        !           940:     Command action;
        !           941:     Event e;
        !           942: 
        !           943:     if (op == O_TRACEI) {
        !           944:        event = build(O_EQ, build(O_SYM, pcsym), place);
        !           945:     } else {
        !           946:        event = build(O_EQ, build(O_SYM, linesym), place);
        !           947:     }
        !           948:     action = build(O_PRINTSRCPOS, exp);
        !           949:     if (cond != nil) {
        !           950:        action = build(O_IF, cond, buildcmdlist(action));
        !           951:     }
        !           952:     e = addevent(event, buildcmdlist(action));
        !           953:     if (isstdin()) {
        !           954:        printevent(e);
        !           955:     }
        !           956: }
        !           957: 
        !           958: /*
        !           959:  * Construct event for tracing a procedure.
        !           960:  *
        !           961:  * What we want here is
        !           962:  *
        !           963:  *     when $proc = p do
        !           964:  *         if <condition> then
        !           965:  *             printcall;
        !           966:  *             once $pc = $retaddr do
        !           967:  *                 printrtn;
        !           968:  *             end;
        !           969:  *         end if;
        !           970:  *     end;
        !           971:  *
        !           972:  * Note that "once" is like "when" except that the event
        !           973:  * deletes itself as part of its associated action.
        !           974:  */
        !           975: 
        !           976: private traceproc(op, p, place, cond)
        !           977: Operator op;
        !           978: Symbol p;
        !           979: Node place;
        !           980: Node cond;
        !           981: {
        !           982:     Node event;
        !           983:     Command action;
        !           984:     Cmdlist actionlist;
        !           985:     Event e;
        !           986: 
        !           987:     action = build(O_PRINTCALL, p);
        !           988:     actionlist = list_alloc();
        !           989:     cmdlist_append(action, actionlist);
        !           990:     event = build(O_EQ, build(O_SYM, pcsym), build(O_SYM, retaddrsym));
        !           991:     action = build(O_ONCE, event, buildcmdlist(build(O_PRINTRTN, p)));
        !           992:     cmdlist_append(action, actionlist);
        !           993:     if (cond != nil) {
        !           994:        actionlist = buildcmdlist(build(O_IF, cond, actionlist));
        !           995:     }
        !           996:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
        !           997:     e = addevent(event, actionlist);
        !           998:     if (isstdin()) {
        !           999:        printevent(e);
        !          1000:     }
        !          1001: }
        !          1002: 
        !          1003: /*
        !          1004:  * Set up breakpoint for tracing data.
        !          1005:  */
        !          1006: 
        !          1007: private tracedata(op, exp, place, cond)
        !          1008: Operator op;
        !          1009: Node exp;
        !          1010: Node place;
        !          1011: Node cond;
        !          1012: {
        !          1013:     Symbol p;
        !          1014:     Node event;
        !          1015:     Command action;
        !          1016: 
        !          1017:     if (size(exp->nodetype) > MAXTRSIZE) {
        !          1018:        error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
        !          1019:     }
        !          1020:     p = (place == nil) ? tcontainer(exp) : place->value.sym;
        !          1021:     if (p == nil) {
        !          1022:        p = program;
        !          1023:     }
        !          1024:     action = build(O_PRINTIFCHANGED, exp);
        !          1025:     if (cond != nil) {
        !          1026:        action = build(O_IF, cond, buildcmdlist(action));
        !          1027:     }
        !          1028:     action = build(O_TRACEON, (op == O_TRACEI), buildcmdlist(action));
        !          1029:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
        !          1030:     action->value.trace.event = addevent(event, buildcmdlist(action));
        !          1031:     if (isstdin()) {
        !          1032:        printevent(action->value.trace.event);
        !          1033:     }
        !          1034: }
        !          1035: 
        !          1036: /*
        !          1037:  * Setting and unsetting of stops.
        !          1038:  */
        !          1039: 
        !          1040: public stop(p)
        !          1041: Node p;
        !          1042: {
        !          1043:     Node exp, place, cond, t;
        !          1044:     Symbol s;
        !          1045:     Command action;
        !          1046:     Event e;
        !          1047: 
        !          1048:     exp = p->value.arg[0];
        !          1049:     place = p->value.arg[1];
        !          1050:     cond = p->value.arg[2];
        !          1051:     if (exp != nil) {
        !          1052:        stopvar(p->op, exp, place, cond);
        !          1053:     } else {
        !          1054:        action = build(O_STOPX);
        !          1055:        if (cond != nil) {
        !          1056:            action = build(O_IF, cond, buildcmdlist(action));
        !          1057:        }
        !          1058:        if (place == nil or place->op == O_SYM) {
        !          1059:            if (place == nil) {
        !          1060:                s = program;
        !          1061:            } else {
        !          1062:                s = place->value.sym;
        !          1063:            }
        !          1064:            t = build(O_EQ, build(O_SYM, procsym), build(O_SYM, s));
        !          1065:            if (cond != nil) {
        !          1066:                action = build(O_TRACEON, (p->op == O_STOPI),
        !          1067:                    buildcmdlist(action));
        !          1068:                e = addevent(t, buildcmdlist(action));
        !          1069:                action->value.trace.event = e;
        !          1070:            } else {
        !          1071:                e = addevent(t, buildcmdlist(action));
        !          1072:            }
        !          1073:            if (isstdin()) {
        !          1074:                printevent(e);
        !          1075:            }
        !          1076:        } else {
        !          1077:            stopinst(p->op, place, cond, action);
        !          1078:        }
        !          1079:     }
        !          1080: }
        !          1081: 
        !          1082: private stopinst(op, place, cond, action)
        !          1083: Operator op;
        !          1084: Node place;
        !          1085: Node cond;
        !          1086: Command action;
        !          1087: {
        !          1088:     Node event;
        !          1089:     Event e;
        !          1090: 
        !          1091:     if (op == O_STOP) {
        !          1092:        event = build(O_EQ, build(O_SYM, linesym), place);
        !          1093:     } else {
        !          1094:        event = build(O_EQ, build(O_SYM, pcsym), place);
        !          1095:     }
        !          1096:     e = addevent(event, buildcmdlist(action));
        !          1097:     if (isstdin()) {
        !          1098:        printevent(e);
        !          1099:     }
        !          1100: }
        !          1101: 
        !          1102: /*
        !          1103:  * Implement stopping on assignment to a variable by adding it to
        !          1104:  * the variable list.
        !          1105:  */
        !          1106: 
        !          1107: private stopvar(op, exp, place, cond)
        !          1108: Operator op;
        !          1109: Node exp;
        !          1110: Node place;
        !          1111: Node cond;
        !          1112: {
        !          1113:     Symbol p;
        !          1114:     Node event;
        !          1115:     Command action;
        !          1116: 
        !          1117:     if (size(exp->nodetype) > MAXTRSIZE) {
        !          1118:        error("expression too large to trace (limit is %d bytes)", MAXTRSIZE);
        !          1119:     }
        !          1120:     if (place == nil) {
        !          1121:        if (exp->op == O_LCON) {
        !          1122:            p = program;
        !          1123:        } else {
        !          1124:            p = tcontainer(exp);
        !          1125:            if (p == nil) {
        !          1126:                p = program;
        !          1127:            }
        !          1128:        }
        !          1129:     } else {
        !          1130:        p = place->value.sym;
        !          1131:     }
        !          1132:     action = build(O_STOPIFCHANGED, exp);
        !          1133:     if (cond != nil) {
        !          1134:        action = build(O_IF, cond, buildcmdlist(action));
        !          1135:     }
        !          1136:     action = build(O_TRACEON, (op == O_STOPI), buildcmdlist(action));
        !          1137:     event = build(O_EQ, build(O_SYM, procsym), build(O_SYM, p));
        !          1138:     action->value.trace.event = addevent(event, buildcmdlist(action));
        !          1139:     if (isstdin()) {
        !          1140:        printevent(action->value.trace.event);
        !          1141:     }
        !          1142: }
        !          1143: 
        !          1144: /*
        !          1145:  * Assign the value of an expression to a variable (or term).
        !          1146:  */
        !          1147: 
        !          1148: public assign(var, exp)
        !          1149: Node var;
        !          1150: Node exp;
        !          1151: {
        !          1152:     Address addr;
        !          1153:     integer varsize, expsize;
        !          1154:     char cvalue;
        !          1155:     short svalue;
        !          1156:     long lvalue;
        !          1157:     float fvalue;
        !          1158: 
        !          1159:     if (var->op == O_SYM and regnum(var->value.sym) != -1) {
        !          1160:        eval(exp);
        !          1161:        setreg(regnum(var->value.sym), pop(Address));
        !          1162:     } else {
        !          1163:        addr = lval(var);
        !          1164:        varsize = size(var->nodetype);
        !          1165:        expsize = size(exp->nodetype);
        !          1166:        eval(exp);
        !          1167:        if (varsize == sizeof(float) and expsize == sizeof(double)) {
        !          1168:            fvalue = (float) pop(double);
        !          1169:            dwrite(&fvalue, addr, sizeof(fvalue));
        !          1170:        } else {
        !          1171:            if (varsize < sizeof(long)) {
        !          1172:                lvalue = 0;
        !          1173:                popn(expsize, &lvalue);
        !          1174:                if (varsize == sizeof(char)) {
        !          1175:                    cvalue = lvalue;
        !          1176:                    dwrite(&cvalue, addr, sizeof(cvalue));
        !          1177:                } else if (varsize == sizeof(short)) {
        !          1178:                    svalue = lvalue;
        !          1179:                    dwrite(&svalue, addr, sizeof(svalue));
        !          1180:                } else {
        !          1181:                    error("[internal error: bad size %d in assign]", varsize);
        !          1182:                }
        !          1183:            } else {
        !          1184:                if (expsize <= varsize) {
        !          1185:                    sp -= expsize;
        !          1186:                    dwrite(sp, addr, expsize);
        !          1187:                } else {
        !          1188:                    sp -= expsize;
        !          1189:                    dwrite(sp, addr, varsize);
        !          1190:                }
        !          1191:            }
        !          1192:        }
        !          1193:     }
        !          1194: }
        !          1195: 
        !          1196: /*
        !          1197:  * Set a debugger variable.
        !          1198:  */
        !          1199: 
        !          1200: private set (var, exp)
        !          1201: Node var, exp;
        !          1202: {
        !          1203:     Symbol t;
        !          1204: 
        !          1205:     if (var == nil) {
        !          1206:        defvar(nil, nil);
        !          1207:     } else if (exp == nil) {
        !          1208:        defvar(var->value.name, nil);
        !          1209:     } else if (var->value.name == identname("$frame", true)) {
        !          1210:        t = exp->nodetype;
        !          1211:        if (not compatible(t, t_int) and not compatible(t, t_addr)) {
        !          1212:            error("$frame must be an address");
        !          1213:        }
        !          1214:        eval(exp);
        !          1215:        getnewregs(pop(Address));
        !          1216:     } else {
        !          1217:        defvar(var->value.name, unrval(exp));
        !          1218:     }
        !          1219: }
        !          1220: 
        !          1221: /*
        !          1222:  * Execute a list command.
        !          1223:  */
        !          1224: 
        !          1225: private list (p)
        !          1226: Node p;
        !          1227: {
        !          1228:     Symbol f;
        !          1229:     Address addr;
        !          1230:     Lineno line, l1, l2;
        !          1231: 
        !          1232:     if (p->value.arg[0]->op == O_SYM) {
        !          1233:        f = p->value.arg[0]->value.sym;
        !          1234:        addr = firstline(f);
        !          1235:        if (addr == NOADDR) {
        !          1236:            error("no source lines for \"%s\"", symname(f));
        !          1237:        }
        !          1238:        setsource(srcfilename(addr));
        !          1239:        line = srcline(addr);
        !          1240:        getsrcwindow(line, &l1, &l2);
        !          1241:     } else {
        !          1242:        eval(p->value.arg[0]);
        !          1243:        l1 = (Lineno) (pop(long));
        !          1244:        eval(p->value.arg[1]);
        !          1245:        l2 = (Lineno) (pop(long));
        !          1246:     }
        !          1247:     printlines(l1, l2);
        !          1248: }
        !          1249: 
        !          1250: /*
        !          1251:  * Execute a func command.
        !          1252:  */
        !          1253: 
        !          1254: private func (p)
        !          1255: Node p;
        !          1256: {
        !          1257:     Symbol s, f;
        !          1258:     Address addr;
        !          1259: 
        !          1260:     if (p == nil) {
        !          1261:        printname(stdout, curfunc);
        !          1262:        putchar('\n');
        !          1263:     } else {
        !          1264:        s = p->value.sym;
        !          1265:        if (isroutine(s)) {
        !          1266:            setcurfunc(s);
        !          1267:        } else {
        !          1268:            find(f, s->name) where isroutine(f) endfind(f);
        !          1269:            if (f == nil) {
        !          1270:                error("%s is not a procedure or function", symname(s));
        !          1271:            }
        !          1272:            setcurfunc(f);
        !          1273:        }
        !          1274:        addr = codeloc(curfunc);
        !          1275:        if (addr != NOADDR) {
        !          1276:            setsource(srcfilename(addr));
        !          1277:            cursrcline = srcline(addr);
        !          1278:        }
        !          1279:     }
        !          1280: }
        !          1281: 
        !          1282: /*
        !          1283:  * Send a message to the current support person.
        !          1284:  */
        !          1285: 
        !          1286: public gripe()
        !          1287: {
        !          1288:     typedef Operation();
        !          1289:     Operation *old;
        !          1290:     int pid, status;
        !          1291:     extern int versionNumber;
        !          1292:     char subject[100];
        !          1293: 
        !          1294: #   ifdef MAINTAINER
        !          1295:        puts("Type control-D to end your message.  Be sure to include");
        !          1296:        puts("your name and the name of the file you are debugging.");
        !          1297:        putchar('\n');
        !          1298:        old = signal(SIGINT, SIG_DFL);
        !          1299:        sprintf(subject, "dbx (version 3.%d) gripe", versionNumber);
        !          1300:        pid = back("Mail", stdin, stdout, "-s", subject, MAINTAINER, nil);
        !          1301:        signal(SIGINT, SIG_IGN);
        !          1302:        pwait(pid, &status);
        !          1303:        signal(SIGINT, old);
        !          1304:        if (status == 0) {
        !          1305:            puts("Thank you.");
        !          1306:        } else {
        !          1307:            puts("\nMail not sent.");
        !          1308:        }
        !          1309: #   else
        !          1310:        puts("Sorry, no dbx maintainer available to gripe to.");
        !          1311:        puts("Try contacting your system manager.");
        !          1312: #   endif
        !          1313: }
        !          1314: 
        !          1315: /*
        !          1316:  * Give the user some help.
        !          1317:  */
        !          1318: 
        !          1319: public help()
        !          1320: {
        !          1321:     puts("run                    - begin execution of the program");
        !          1322:     puts("print <exp>            - print the value of the expression");
        !          1323:     puts("where                  - print currently active procedures");
        !          1324:     puts("stop at <line>         - suspend execution at the line");
        !          1325:     puts("stop in <proc>         - suspend execution when <proc> is called");
        !          1326:     puts("cont                   - continue execution");
        !          1327:     puts("step                   - single step one line");
        !          1328:     puts("next                   - step to next line (skip over calls)");
        !          1329:     puts("trace <line#>          - trace execution of the line");
        !          1330:     puts("trace <proc>           - trace calls to the procedure");
        !          1331:     puts("trace <var>            - trace changes to the variable");
        !          1332:     puts("trace <exp> at <line#> - print <exp> when <line> is reached");
        !          1333:     puts("status                 - print trace/stop's in effect");
        !          1334:     puts("delete <number>        - remove trace or stop of given number");
        !          1335:     puts("call <proc>            - call a procedure in program");
        !          1336:     puts("whatis <name>          - print the declaration of the name");
        !          1337:     puts("list <line>, <line>    - list source lines");
        !          1338:     puts("gripe                  - send mail to the person in charge of dbx");
        !          1339:     puts("quit                   - exit dbx");
        !          1340: }
        !          1341: 
        !          1342: /*
        !          1343:  * Divert output to the given file name.
        !          1344:  * Cannot redirect to an existing file.
        !          1345:  */
        !          1346: 
        !          1347: private int so_fd;
        !          1348: private Boolean notstdout;
        !          1349: 
        !          1350: public setout(filename)
        !          1351: String filename;
        !          1352: {
        !          1353:     File f;
        !          1354: 
        !          1355:     f = fopen(filename, "r");
        !          1356:     if (f != nil) {
        !          1357:        fclose(f);
        !          1358:        error("%s: file already exists", filename);
        !          1359:     } else {
        !          1360:        so_fd = dup(1);
        !          1361:        close(1);
        !          1362:        if (creat(filename, 0666) == nil) {
        !          1363:            unsetout();
        !          1364:            error("can't create %s", filename);
        !          1365:        }
        !          1366:        notstdout = true;
        !          1367:     }
        !          1368: }
        !          1369: 
        !          1370: /*
        !          1371:  * Revert output to standard output.
        !          1372:  */
        !          1373: 
        !          1374: public unsetout()
        !          1375: {
        !          1376:     fflush(stdout);
        !          1377:     close(1);
        !          1378:     if (dup(so_fd) != 1) {
        !          1379:        panic("standard out dup failed");
        !          1380:     }
        !          1381:     close(so_fd);
        !          1382:     notstdout = false;
        !          1383: }
        !          1384: 
        !          1385: /*
        !          1386:  * Determine is standard output is currently being redirected
        !          1387:  * to a file (as far as we know).
        !          1388:  */
        !          1389: 
        !          1390: public Boolean isredirected()
        !          1391: {
        !          1392:     return notstdout;
        !          1393: }

unix.superglobalmegacorp.com

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