Annotation of 43BSDReno/pgrm/dbx/vax.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[] = "@(#)vax.c      5.8 (Berkeley) 6/1/90";
        !            22: #endif /* not lint */
        !            23: 
        !            24: /*
        !            25:  * Target machine dependent stuff.
        !            26:  */
        !            27: 
        !            28: #include "defs.h"
        !            29: #include "machine.h"
        !            30: #include "process.h"
        !            31: #include "runtime.h"
        !            32: #include "events.h"
        !            33: #include "main.h"
        !            34: #include "symbols.h"
        !            35: #include "source.h"
        !            36: #include "mappings.h"
        !            37: #include "object.h"
        !            38: #include "tree.h"
        !            39: #include "eval.h"
        !            40: #include "keywords.h"
        !            41: #include "ops.h"
        !            42: 
        !            43: #ifndef public
        !            44: typedef unsigned int Address;
        !            45: typedef unsigned char Byte;
        !            46: typedef unsigned int Word;
        !            47: 
        !            48: #define NREG 16
        !            49: 
        !            50: #define ARGP 12
        !            51: #define FRP 13
        !            52: #define STKP 14
        !            53: #define PROGCTR 15
        !            54: 
        !            55: #define CODESTART 0
        !            56: #define FUNCOFFSET 2
        !            57: 
        !            58: #define nargspassed(frame) argn(0, frame)
        !            59: 
        !            60: #define BITSPERBYTE 8
        !            61: #define BITSPERWORD (BITSPERBYTE * sizeof(Word))
        !            62: 
        !            63: /*
        !            64:  * This magic macro enables us to look at the process' registers
        !            65:  * in its user structure.
        !            66:  */
        !            67: 
        !            68: #define regloc(reg)    (ctob(UPAGES) + (sizeof(Word) * (reg)))
        !            69: 
        !            70: #include "source.h"
        !            71: #include "symbols.h"
        !            72: #include <signal.h>
        !            73: #include <sys/param.h>
        !            74: #include <machine/psl.h>
        !            75: #include <machine/pte.h>
        !            76: #include <sys/user.h>
        !            77: #undef DELETE /* XXX */
        !            78: #include <sys/vm.h>
        !            79: #include <machine/reg.h>
        !            80: 
        !            81: Address pc;
        !            82: Address prtaddr;
        !            83: 
        !            84: #endif
        !            85: 
        !            86: /*
        !            87:  * Indices into u. for use in collecting registers values.
        !            88:  */
        !            89: public int rloc[] ={
        !            90:     R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC
        !            91: };
        !            92: 
        !            93: private Address printop();
        !            94: 
        !            95: private Optab *ioptab[256];    /* index by opcode to optab */
        !            96: private Optab *esctab[256];    /* for extended opcodes */
        !            97: 
        !            98: /*
        !            99:  * Initialize the opcode lookup table.
        !           100:  */
        !           101: public optab_init()
        !           102: {
        !           103:     register Optab *p;
        !           104: 
        !           105:     for (p = optab; p->iname; p++) {
        !           106:        if (p->format == O_ESCD) {
        !           107:            esctab[p->val] = p;
        !           108:        } else if (p->format != O_ESCD && p->format != O_ESCE) {
        !           109:            ioptab[p->val] = p;
        !           110:        }
        !           111:     }
        !           112: }
        !           113: 
        !           114: /*
        !           115:  * Decode and print the instructions within the given address range.
        !           116:  */
        !           117: 
        !           118: public printinst(lowaddr, highaddr)
        !           119: Address lowaddr;
        !           120: Address highaddr;
        !           121: {
        !           122:     register Address addr;
        !           123: 
        !           124:     for (addr = lowaddr; addr <= highaddr; ) {
        !           125:        addr = printop(addr);
        !           126:     }
        !           127:     prtaddr = addr;
        !           128: }
        !           129: 
        !           130: /*
        !           131:  * Another approach:  print n instructions starting at the given address.
        !           132:  */
        !           133: 
        !           134: public printninst(count, addr)
        !           135: int count;
        !           136: Address addr;
        !           137: {
        !           138:     register Integer i;
        !           139:     register Address newaddr;
        !           140: 
        !           141:     if (count <= 0) {
        !           142:        error("non-positive repetition count");
        !           143:     } else {
        !           144:        newaddr = addr;
        !           145:        for (i = 0; i < count; i++) {
        !           146:            newaddr = printop(newaddr);
        !           147:        }
        !           148:        prtaddr = newaddr;
        !           149:     }
        !           150: }
        !           151: 
        !           152: /*
        !           153:  * Print the contents of the addresses within the given range
        !           154:  * according to the given format.
        !           155:  */
        !           156: 
        !           157: typedef struct {
        !           158:     String name;
        !           159:     String printfstring;
        !           160:     int length;
        !           161: } Format;
        !           162: 
        !           163: private Format fmt[] = {
        !           164:     { "d", " %d", sizeof(short) },
        !           165:     { "D", " %ld", sizeof(long) },
        !           166:     { "o", " %o", sizeof(short) },
        !           167:     { "O", " %lo", sizeof(long) },
        !           168:     { "x", " %04x", sizeof(short) },
        !           169:     { "X", " %08x", sizeof(long) },
        !           170:     { "b", " \\%o", sizeof(char) },
        !           171:     { "c", " '%c'", sizeof(char) },
        !           172:     { "s", "%c", sizeof(char) },
        !           173:     { "f", " %f", sizeof(float) },
        !           174:     { "g", " %g", sizeof(double) },
        !           175:     { nil, nil, 0 }
        !           176: };
        !           177: 
        !           178: private Format *findformat(s)
        !           179: String s;
        !           180: {
        !           181:     register Format *f;
        !           182: 
        !           183:     f = &fmt[0];
        !           184:     while (f->name != nil and not streq(f->name, s)) {
        !           185:        ++f;
        !           186:     }
        !           187:     if (f->name == nil) {
        !           188:        error("bad print format \"%s\"", s);
        !           189:     }
        !           190:     return f;
        !           191: }
        !           192: 
        !           193: /*
        !           194:  * Retrieve and print out the appropriate data in the given format.
        !           195:  * Floats have to be handled specially to allow the compiler to
        !           196:  * convert them to doubles when passing to printf.
        !           197:  */
        !           198: 
        !           199: private printformat (f, addr)
        !           200: Format *f;
        !           201: Address addr;
        !           202: {
        !           203:     union {
        !           204:        char charv;
        !           205:        short shortv;
        !           206:        int intv;
        !           207:        float floatv;
        !           208:        double doublev;
        !           209:     } value;
        !           210: 
        !           211:     value.intv = 0;
        !           212:     dread(&value, addr, f->length);
        !           213:     if (streq(f->name, "f")) {
        !           214:        printf(f->printfstring, value.floatv);
        !           215:     } else {
        !           216:        printf(f->printfstring, value);
        !           217:     }
        !           218: }
        !           219: 
        !           220: public Address printdata(lowaddr, highaddr, format)
        !           221: Address lowaddr;
        !           222: Address highaddr;
        !           223: String format;
        !           224: {
        !           225:     int n;
        !           226:     register Address addr;
        !           227:     Format *f;
        !           228: 
        !           229:     if (lowaddr > highaddr) {
        !           230:        error("first address larger than second");
        !           231:     }
        !           232:     f = findformat(format);
        !           233:     n = 0;
        !           234:     for (addr = lowaddr; addr <= highaddr; addr += f->length) {
        !           235:        if (n == 0) {
        !           236:            printf("%08x: ", addr);
        !           237:        }
        !           238:        printformat(f, addr);
        !           239:        ++n;
        !           240:        if (n >= (16 div f->length)) {
        !           241:            printf("\n");
        !           242:            n = 0;
        !           243:        }
        !           244:     }
        !           245:     if (n != 0) {
        !           246:        printf("\n");
        !           247:     }
        !           248:     prtaddr = addr;
        !           249:     return addr;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * The other approach is to print n items starting with a given address.
        !           254:  */
        !           255: 
        !           256: public printndata(count, startaddr, format)
        !           257: int count;
        !           258: Address startaddr;
        !           259: String format;
        !           260: {
        !           261:     int i, n;
        !           262:     Address addr;
        !           263:     Format *f;
        !           264:     Boolean isstring;
        !           265:     char c;
        !           266: 
        !           267:     if (count <= 0) {
        !           268:        error("non-positive repetition count");
        !           269:     }
        !           270:     f = findformat(format);
        !           271:     isstring = (Boolean) streq(f->name, "s");
        !           272:     n = 0;
        !           273:     addr = startaddr;
        !           274:     for (i = 0; i < count; i++) {
        !           275:        if (n == 0) {
        !           276:            printf("%08x: ", addr);
        !           277:        }
        !           278:        if (isstring) {
        !           279:            printf("\"");
        !           280:            dread(&c, addr, sizeof(char));
        !           281:            while (c != '\0') {
        !           282:                printchar(c);
        !           283:                ++addr;
        !           284:                dread(&c, addr, sizeof(char));
        !           285:            }
        !           286:            printf("\"\n");
        !           287:            n = 0;
        !           288:            addr += sizeof(String);
        !           289:        } else {
        !           290:            printformat(f, addr);
        !           291:            ++n;
        !           292:            if (n >= (16 div f->length)) {
        !           293:                printf("\n");
        !           294:                n = 0;
        !           295:            }
        !           296:            addr += f->length;
        !           297:        }
        !           298:     }
        !           299:     if (n != 0) {
        !           300:        printf("\n");
        !           301:     }
        !           302:     prtaddr = addr;
        !           303: }
        !           304: 
        !           305: /*
        !           306:  * Print out a value according to the given format.
        !           307:  */
        !           308: 
        !           309: public printvalue(v, format)
        !           310: long v;
        !           311: String format;
        !           312: {
        !           313:     Format *f;
        !           314:     char *p, *q;
        !           315: 
        !           316:     f = findformat(format);
        !           317:     if (streq(f->name, "s")) {
        !           318:        putchar('"');
        !           319:        p = (char *) &v;
        !           320:        q = p + sizeof(v);
        !           321:        while (p < q) {
        !           322:            printchar(*p);
        !           323:            ++p;
        !           324:        }
        !           325:        putchar('"');
        !           326:     } else {
        !           327:        printf(f->printfstring, v);
        !           328:     }
        !           329:     putchar('\n');
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * Print out an execution time error.
        !           334:  * Assumes the source position of the error has been calculated.
        !           335:  *
        !           336:  * Have to check if the -r option was specified; if so then
        !           337:  * the object file information hasn't been read in yet.
        !           338:  */
        !           339: 
        !           340: public printerror()
        !           341: {
        !           342:     extern Integer sys_nsig;
        !           343:     extern String sys_siglist[];
        !           344:     integer err;
        !           345: 
        !           346:     if (isfinished(process)) {
        !           347:        err = exitcode(process);
        !           348:        if (err == 0) {
        !           349:            printf("\"%s\" terminated normally\n", objname);
        !           350:        } else {
        !           351:            printf("\"%s\" terminated abnormally (exit code %d)\n",
        !           352:                objname, err
        !           353:            );
        !           354:        }
        !           355:        erecover();
        !           356:     }
        !           357:     err = errnum(process);
        !           358:     putchar('\n');
        !           359:     printsig(err);
        !           360:     putchar(' ');
        !           361:     printloc();
        !           362:     putchar('\n');
        !           363:     if (curline > 0) {
        !           364:        printlines(curline, curline);
        !           365:     } else {
        !           366:        printinst(pc, pc);
        !           367:     }
        !           368:     erecover();
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Print out a signal.
        !           373:  */
        !           374: 
        !           375: private String illinames[] = {
        !           376:     "reserved addressing fault",
        !           377:     "privileged instruction fault",
        !           378:     "reserved operand fault"
        !           379: };
        !           380: 
        !           381: private String fpenames[] = {
        !           382:     nil,
        !           383:     "integer overflow trap",
        !           384:     "integer divide by zero trap",
        !           385:     "floating overflow trap",
        !           386:     "floating/decimal divide by zero trap",
        !           387:     "floating underflow trap",
        !           388:     "decimal overflow trap",
        !           389:     "subscript out of range trap",
        !           390:     "floating overflow fault",
        !           391:     "floating divide by zero fault",
        !           392:     "floating underflow fault"
        !           393: };
        !           394: 
        !           395: public printsig (signo)
        !           396: integer signo;
        !           397: {
        !           398:     integer code;
        !           399: 
        !           400:     if (signo < 0 or signo > sys_nsig) {
        !           401:        printf("[signal %d]", signo);
        !           402:     } else {
        !           403:        printf("%s", sys_siglist[signo]);
        !           404:     }
        !           405:     code = errcode(process);
        !           406:     if (signo == SIGILL) {
        !           407:        if (code >= 0 and code < sizeof(illinames) / sizeof(illinames[0])) {
        !           408:            printf(" (%s)", illinames[code]);
        !           409:        }
        !           410:     } else if (signo == SIGFPE) {
        !           411:        if (code > 0 and code < sizeof(fpenames) / sizeof(fpenames[0])) {
        !           412:            printf(" (%s)", fpenames[code]);
        !           413:        }
        !           414:     }
        !           415: }
        !           416: 
        !           417: /*
        !           418:  * Note the termination of the program.  We do this so as to avoid
        !           419:  * having the process exit, which would make the values of variables
        !           420:  * inaccessible.  We do want to flush all output buffers here,
        !           421:  * otherwise it'll never get done.
        !           422:  */
        !           423: 
        !           424: public endprogram()
        !           425: {
        !           426:     Integer exitcode;
        !           427: 
        !           428:     stepto(nextaddr(pc, true));
        !           429:     printnews();
        !           430:     exitcode = argn(1, nil);
        !           431:     if (exitcode != 0) {
        !           432:        printf("\nexecution completed (exit code %d)\n", exitcode);
        !           433:     } else {
        !           434:        printf("\nexecution completed\n");
        !           435:     }
        !           436:     getsrcpos();
        !           437:     erecover();
        !           438: }
        !           439: 
        !           440: /*
        !           441:  * Single step the machine a source line (or instruction if "inst_tracing"
        !           442:  * is true).  If "isnext" is true, skip over procedure calls.
        !           443:  */
        !           444: 
        !           445: private Address getcall();
        !           446: 
        !           447: public dostep(isnext)
        !           448: Boolean isnext;
        !           449: {
        !           450:     register Address addr;
        !           451:     register Lineno line;
        !           452:     String filename;
        !           453:     Address startaddr;
        !           454: 
        !           455:     startaddr = pc;
        !           456:     addr = nextaddr(pc, isnext);
        !           457:     if (not inst_tracing and nlhdr.nlines != 0) {
        !           458:        line = linelookup(addr);
        !           459:        while (line == 0) {
        !           460:            addr = nextaddr(addr, isnext);
        !           461:            line = linelookup(addr);
        !           462:        }
        !           463:        curline = line;
        !           464:     } else {
        !           465:        curline = 0;
        !           466:     }
        !           467:     stepto(addr);
        !           468:     filename = srcfilename(addr);
        !           469:     setsource(filename);
        !           470: }
        !           471: 
        !           472: typedef char Bpinst;
        !           473: 
        !           474: #define BP_OP       O_BPT       /* breakpoint trap */
        !           475: 
        !           476: #define BP_ERRNO    SIGTRAP     /* signal received at a breakpoint */
        !           477: 
        !           478: /*
        !           479:  * Setting a breakpoint at a location consists of saving
        !           480:  * the word at the location and poking a BP_OP there.
        !           481:  *
        !           482:  * We save the locations and words on a list for use in unsetting.
        !           483:  */
        !           484: 
        !           485: typedef struct Savelist *Savelist;
        !           486: 
        !           487: struct Savelist {
        !           488:     Address location;
        !           489:     Bpinst save;
        !           490:     short refcount;
        !           491:     Savelist link;
        !           492: };
        !           493: 
        !           494: private Savelist savelist;
        !           495: 
        !           496: /*
        !           497:  * Set a breakpoint at the given address.  Only save the word there
        !           498:  * if it's not already a breakpoint.
        !           499:  */
        !           500: 
        !           501: public setbp(addr)
        !           502: Address addr;
        !           503: {
        !           504:     Bpinst w, save;
        !           505:     register Savelist newsave, s;
        !           506: 
        !           507:     for (s = savelist; s != nil; s = s->link) {
        !           508:        if (s->location == addr) {
        !           509:            s->refcount++;
        !           510:            return;
        !           511:        }
        !           512:     }
        !           513:     iread(&save, addr, sizeof(save));
        !           514:     newsave = new(Savelist);
        !           515:     newsave->location = addr;
        !           516:     newsave->save = save;
        !           517:     newsave->refcount = 1;
        !           518:     newsave->link = savelist;
        !           519:     savelist = newsave;
        !           520:     w = BP_OP;
        !           521:     iwrite(&w, addr, sizeof(w));
        !           522: }
        !           523: 
        !           524: /*
        !           525:  * Unset a breakpoint; unfortunately we have to search the SAVELIST
        !           526:  * to find the saved value.  The assumption is that the SAVELIST will
        !           527:  * usually be quite small.
        !           528:  */
        !           529: 
        !           530: public unsetbp(addr)
        !           531: Address addr;
        !           532: {
        !           533:     register Savelist s, prev;
        !           534: 
        !           535:     prev = nil;
        !           536:     for (s = savelist; s != nil; s = s->link) {
        !           537:        if (s->location == addr) {
        !           538:            iwrite(&s->save, addr, sizeof(s->save));
        !           539:            s->refcount--;
        !           540:            if (s->refcount == 0) {
        !           541:                if (prev == nil) {
        !           542:                    savelist = s->link;
        !           543:                } else {
        !           544:                    prev->link = s->link;
        !           545:                }
        !           546:                dispose(s);
        !           547:            }
        !           548:            return;
        !           549:        }
        !           550:        prev = s;
        !           551:     }
        !           552:     panic("unsetbp: couldn't find address %d", addr);
        !           553: }
        !           554: 
        !           555: /*
        !           556:  * VAX instruction decoder, derived from adb.
        !           557:  */
        !           558: 
        !           559: private Address printop(addr)
        !           560: Address addr;
        !           561: {
        !           562:     register Optab *op;
        !           563:     VaxOpcode ins;
        !           564:     unsigned char mode;
        !           565:     int argtype, amode, argno, argval;
        !           566:     String reg;
        !           567:     Boolean indexf;
        !           568:     short offset;
        !           569: 
        !           570:     argval = 0;
        !           571:     indexf = false;
        !           572:     printf("%08x  ", addr);
        !           573:     iread(&ins, addr, sizeof(ins));
        !           574:     addr += 1;
        !           575:     if (ins == O_ESCF) {
        !           576:        iread(&ins, addr, sizeof(ins));
        !           577:        addr += 1;
        !           578:        op = ioptab[ins];
        !           579:     } else if (ins == O_ESCD) {
        !           580:        iread(&ins, addr, sizeof(ins));
        !           581:        addr += 1;
        !           582:        op = esctab[ins];
        !           583:     } else {
        !           584:        op = ioptab[ins];
        !           585:     }
        !           586:     if (op == nil) {
        !           587:        printf("[unrecognized opcode %#0x]\n", ins);
        !           588:        return addr;
        !           589:     }
        !           590:     printf("%s", op->iname);
        !           591:     for (argno = 0; argno < op->numargs; argno++) {
        !           592:        if (indexf == true) {
        !           593:            indexf = false;
        !           594:        } else if (argno == 0) {
        !           595:            printf("\t");
        !           596:        } else {
        !           597:            printf(",");
        !           598:        }
        !           599:        argtype = op->argtype[argno];
        !           600:        if (is_branch_disp(argtype)) {
        !           601:            mode = 0xAF + (typelen(argtype) << 5);
        !           602:        } else {
        !           603:            iread(&mode, addr, sizeof(mode));
        !           604:            addr += 1;
        !           605:        }
        !           606:        reg = regname[regnm(mode)];
        !           607:        amode = addrmode(mode);
        !           608:        switch (amode) {
        !           609:            case LITSHORT:
        !           610:            case LITUPTO31:
        !           611:            case LITUPTO47:
        !           612:            case LITUPTO63:
        !           613:                if (typelen(argtype) == TYPF || typelen(argtype) == TYPD ||
        !           614:                    typelen(argtype) == TYPG || typelen(argtype) == TYPH)
        !           615:                    printf("$%s", fltimm[mode]);
        !           616:                else
        !           617:                    printf("$%x", mode);
        !           618:                argval = mode;
        !           619:                break;
        !           620: 
        !           621:            case INDEX:
        !           622:                printf("[%s]", reg);
        !           623:                indexf = true;
        !           624:                argno--;
        !           625:                break;
        !           626: 
        !           627:            case REG:
        !           628:                printf("%s", reg);
        !           629:                break;
        !           630: 
        !           631:            case REGDEF:
        !           632:                printf("(%s)", reg);
        !           633:                break;
        !           634: 
        !           635:            case AUTODEC:
        !           636:                printf("-(%s)", reg);
        !           637:                break;
        !           638: 
        !           639:            case AUTOINC:
        !           640:                if (reg != regname[PROGCTR]) {
        !           641:                    printf("(%s)+", reg);
        !           642:                } else {
        !           643:                    printf("$");
        !           644:                    switch (typelen(argtype)) {
        !           645:                        case TYPB:
        !           646:                            argval = printdisp(addr, 1, reg, amode);
        !           647:                            addr += 1;
        !           648:                            break;
        !           649: 
        !           650:                        case TYPW:
        !           651:                            argval = printdisp(addr, 2, reg, amode);
        !           652:                            addr += 2;
        !           653:                            break;
        !           654: 
        !           655:                        case TYPL:
        !           656:                            argval = printdisp(addr, 4, reg, amode);
        !           657:                            addr += 4;
        !           658:                            break;
        !           659: 
        !           660:                        case TYPF:
        !           661:                            iread(&argval, addr, sizeof(argval));
        !           662:                            if ((argval & 0xffff007f) == 0x8000) {
        !           663:                                printf("[reserved operand]");
        !           664:                            } else {
        !           665:                                printf("%g", *(float *)&argval);
        !           666:                            }
        !           667:                            addr += 4;
        !           668:                            break;
        !           669: 
        !           670:                        case TYPD:
        !           671:                            /* XXX this bags the low order bits */
        !           672:                            iread(&argval, addr, sizeof(argval));
        !           673:                            if ((argval & 0xffff007f) == 0x8000) {
        !           674:                                printf("[reserved operand]");
        !           675:                            } else {
        !           676:                                printf("%g", *(float *)&argval);
        !           677:                            }
        !           678:                            addr += 8;
        !           679:                            break;
        !           680: 
        !           681:                        case TYPG:
        !           682:                        case TYPQ:
        !           683:                            iread(&argval, addr+4, sizeof(argval));
        !           684:                            printf("%08x", argval);
        !           685:                            iread(&argval, addr, sizeof(argval));
        !           686:                            printf("%08x", argval);
        !           687:                            addr += 8;
        !           688:                            break;
        !           689: 
        !           690:                        case TYPH:
        !           691:                        case TYPO:
        !           692:                            iread(&argval, addr+12, sizeof(argval));
        !           693:                            printf("%08x", argval);
        !           694:                            iread(&argval, addr+8, sizeof(argval));
        !           695:                            printf("%08x", argval);
        !           696:                            iread(&argval, addr+4, sizeof(argval));
        !           697:                            printf("%08x", argval);
        !           698:                            iread(&argval, addr, sizeof(argval));
        !           699:                            printf("%08x", argval);
        !           700:                            addr += 16;
        !           701:                            break;
        !           702:                    }
        !           703:                }
        !           704:                break;
        !           705: 
        !           706:            case AUTOINCDEF:
        !           707:                if (reg == regname[PROGCTR]) {
        !           708:                    printf("*$");
        !           709:                    argval = printdisp(addr, 4, reg, amode);
        !           710:                    addr += 4;
        !           711:                } else {
        !           712:                    printf("*(%s)+", reg);
        !           713:                }
        !           714:                break;
        !           715: 
        !           716:            case BYTEDISP:
        !           717:                argval = printdisp(addr, 1, reg, amode);
        !           718:                addr += 1;
        !           719:                break;
        !           720: 
        !           721:            case BYTEDISPDEF:
        !           722:                printf("*");
        !           723:                argval = printdisp(addr, 1, reg, amode);
        !           724:                addr += 1;
        !           725:                break;
        !           726: 
        !           727:            case WORDDISP:
        !           728:                argval = printdisp(addr, 2, reg, amode);
        !           729:                addr += 2;
        !           730:                break;
        !           731: 
        !           732:            case WORDDISPDEF:
        !           733:                printf("*");
        !           734:                argval = printdisp(addr, 2, reg, amode);
        !           735:                addr += 2;
        !           736:                break;
        !           737: 
        !           738:            case LONGDISP:
        !           739:                argval = printdisp(addr, 4, reg, amode);
        !           740:                addr += 4;
        !           741:                break;
        !           742: 
        !           743:            case LONGDISPDEF:
        !           744:                printf("*");
        !           745:                argval = printdisp(addr, 4, reg, amode);
        !           746:                addr += 4;
        !           747:                break;
        !           748:        }
        !           749:     }
        !           750:     if (ins == O_CASEB || ins == O_CASEW || ins == O_CASEL) {
        !           751:        for (argno = 0; argno <= argval; argno++) {
        !           752:            iread(&offset, addr, sizeof(offset));
        !           753:            printf("\n\t\t%d", offset);
        !           754:            addr += 2;
        !           755:        }
        !           756:     }
        !           757:     printf("\n");
        !           758:     return addr;
        !           759: }
        !           760: 
        !           761: /*
        !           762:  * Print the displacement of an instruction that uses displacement
        !           763:  * addressing.
        !           764:  */
        !           765: 
        !           766: private int printdisp(addr, nbytes, reg, mode)
        !           767: Address addr;
        !           768: int nbytes;
        !           769: char *reg;
        !           770: int mode;
        !           771: {
        !           772:     char byte;
        !           773:     short hword;
        !           774:     int argval;
        !           775:     Symbol f;
        !           776: 
        !           777:     switch (nbytes) {
        !           778:        case 1:
        !           779:            iread(&byte, addr, sizeof(byte));
        !           780:            argval = byte;
        !           781:            break;
        !           782: 
        !           783:        case 2:
        !           784:            iread(&hword, addr, sizeof(hword));
        !           785:            argval = hword;
        !           786:            break;
        !           787: 
        !           788:        case 4:
        !           789:            iread(&argval, addr, sizeof(argval));
        !           790:            break;
        !           791:     }
        !           792:     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
        !           793:        argval += addr + nbytes;
        !           794:     }
        !           795:     if (reg == regname[PROGCTR]) {
        !           796:        f = whatblock((Address) argval + 2);
        !           797:        if (codeloc(f) == argval + 2) {
        !           798:            printf("%s", symname(f));
        !           799:        } else {
        !           800:            printf("%x", argval);
        !           801:        }
        !           802:     } else {
        !           803:        if (varIsSet("$hexoffsets")) {
        !           804:            if (argval < 0) {
        !           805:                printf("-%x(%s)", -(argval), reg);
        !           806:            } else {
        !           807:                printf("%x(%s)", argval, reg);
        !           808:            }
        !           809:        } else {
        !           810:            printf("%d(%s)", argval, reg);
        !           811:        }
        !           812:     }
        !           813:     return argval;
        !           814: }
        !           815: 
        !           816: /*
        !           817:  * Compute the next address that will be executed from the given one.
        !           818:  * If "isnext" is true then consider a procedure call as straight line code.
        !           819:  *
        !           820:  * We must unfortunately do much of the same work that is necessary
        !           821:  * to print instructions.  In addition we have to deal with branches.
        !           822:  * Unconditional branches we just follow, for conditional branches
        !           823:  * we continue execution to the current location and then single step
        !           824:  * the machine.  We assume that the last argument in an instruction
        !           825:  * that branches is the branch address (or relative offset).
        !           826:  */
        !           827: 
        !           828: private Address findnextaddr();
        !           829: 
        !           830: public Address nextaddr(startaddr, isnext)
        !           831: Address startaddr;
        !           832: boolean isnext;
        !           833: {
        !           834:     Address addr;
        !           835: 
        !           836:     addr = usignal(process);
        !           837:     if (addr == 0 or addr == 1) {
        !           838:        addr = findnextaddr(startaddr, isnext);
        !           839:     }
        !           840:     return addr;
        !           841: }
        !           842: 
        !           843: /*
        !           844:  * Determine if it's ok to skip function f entered by instruction ins.
        !           845:  * If so, we're going to compute the return address and step to it.
        !           846:  * Therefore we cannot skip over a function entered by a jsb or bsb,
        !           847:  * since the return address is not easily computed for them.
        !           848:  */
        !           849: 
        !           850: private boolean skipfunc (ins, f)
        !           851: VaxOpcode ins;
        !           852: Symbol f;
        !           853: {
        !           854:     boolean b;
        !           855: 
        !           856:     b = (boolean) (
        !           857:        ins != O_JSB and ins != O_BSBB and ins != O_BSBW and
        !           858:        not inst_tracing and nlhdr.nlines != 0 and
        !           859:        nosource(curfunc) and canskip(curfunc)
        !           860:     );
        !           861:     return b;
        !           862: }
        !           863: 
        !           864: private Address findnextaddr(startaddr, isnext)
        !           865: Address startaddr;
        !           866: Boolean isnext;
        !           867: {
        !           868:     register Address addr;
        !           869:     register Optab *op;
        !           870:     VaxOpcode ins, ins2;
        !           871:     unsigned char mode;
        !           872:     int argtype, amode, argno, argval;
        !           873:     String r;
        !           874:     Boolean indexf;
        !           875:     enum { KNOWN, SEQUENTIAL, BRANCH } addrstatus;
        !           876: 
        !           877:     argval = 0;
        !           878:     indexf = false;
        !           879:     addr = startaddr;
        !           880:     iread(&ins, addr, sizeof(ins));
        !           881:     switch (ins) {
        !           882:        /*
        !           883:         * It used to be that unconditional jumps and branches were handled
        !           884:         * by taking their destination address as the next address.  While
        !           885:         * saving the cost of starting up the process, this approach
        !           886:         * doesn't work when jumping indirect (since the value in the
        !           887:         * register might not yet have been set).
        !           888:         *
        !           889:         * So unconditional jumps and branches are now handled the same way
        !           890:         * as conditional jumps and branches.
        !           891:         *
        !           892:        case O_BRB:
        !           893:        case O_BRW:
        !           894:            addrstatus = BRANCH;
        !           895:            break;
        !           896:         *
        !           897:         */
        !           898:            
        !           899:        case O_BSBB:
        !           900:        case O_BSBW:
        !           901:        case O_JSB:
        !           902:        case O_CALLG:
        !           903:        case O_CALLS:
        !           904:            addrstatus = KNOWN;
        !           905:            stepto(addr);
        !           906:            pstep(process, DEFSIG);
        !           907:            addr = reg(PROGCTR);
        !           908:            pc = addr;
        !           909:            setcurfunc(whatblock(pc));
        !           910:            if (not isbperr()) {
        !           911:                printstatus();
        !           912:                /* NOTREACHED */
        !           913:            }
        !           914:            bpact();
        !           915:            if (isnext or skipfunc(ins, curfunc)) {
        !           916:                addrstatus = KNOWN;
        !           917:                addr = return_addr();
        !           918:                stepto(addr);
        !           919:                bpact();
        !           920:            } else {
        !           921:                callnews(/* iscall = */ true);
        !           922:            }
        !           923:            break;
        !           924: 
        !           925:        case O_RSB:
        !           926:        case O_RET:
        !           927:            addrstatus = KNOWN;
        !           928:            stepto(addr);
        !           929:            callnews(/* iscall = */ false);
        !           930:            pstep(process, DEFSIG);
        !           931:            addr = reg(PROGCTR);
        !           932:            pc = addr;
        !           933:            if (not isbperr()) {
        !           934:                printstatus();
        !           935:            }
        !           936:            bpact();
        !           937:            break;
        !           938: 
        !           939:        case O_BRB: case O_BRW:
        !           940:        case O_JMP: /* because it may be jmp (r1) */
        !           941:        case O_BNEQ: case O_BEQL: case O_BGTR:
        !           942:        case O_BLEQ: case O_BGEQ: case O_BLSS:
        !           943:        case O_BGTRU: case O_BLEQU: case O_BVC:
        !           944:        case O_BVS: case O_BCC: case O_BCS:
        !           945:        case O_CASEB: case O_CASEW: case O_CASEL:
        !           946:        case O_BBS: case O_BBC: case O_BBSS: case O_BBCS:
        !           947:        case O_BBSC: case O_BBCC: case O_BBSSI:
        !           948:        case O_BBCCI: case O_BLBS: case O_BLBC:
        !           949:        case O_ACBL: case O_AOBLSS: case O_AOBLEQ:
        !           950:        case O_SOBGEQ: case O_SOBGTR:
        !           951:        case O_ESCF: /* bugchecks */
        !           952:        branches:
        !           953:            addrstatus = KNOWN;
        !           954:            stepto(addr);
        !           955:            pstep(process, DEFSIG);
        !           956:            addr = reg(PROGCTR);
        !           957:            pc = addr;
        !           958:            if (not isbperr()) {
        !           959:                printstatus();
        !           960:            }
        !           961:            break;
        !           962: 
        !           963:        case O_ESCD:
        !           964:            iread(&ins2, addr+1, sizeof(ins2));
        !           965:            if (ins2 == O_ACBF || ins2 == O_ACBD)
        !           966:                /* actually ACBG and ACBH */
        !           967:                goto branches;
        !           968:            /* fall through */
        !           969: 
        !           970:        default:
        !           971:            addrstatus = SEQUENTIAL;
        !           972:            break;
        !           973:     }
        !           974:     if (addrstatus != KNOWN) {
        !           975:        addr += 1;
        !           976:        if (ins == O_ESCD) {
        !           977:            ins = ins2;
        !           978:            addr += 1;
        !           979:            op = esctab[ins];
        !           980:            if (op == nil) {
        !           981:                printf("[bad extended opcode %#x in findnextaddr]\n", ins);
        !           982:                return addr;
        !           983:            }
        !           984:        } else {
        !           985:            op = ioptab[ins];
        !           986:            if (op == nil) {
        !           987:                printf("[bad opcode %#x in findnextaddr]\n", ins);
        !           988:                return addr;
        !           989:            }
        !           990:        }
        !           991:        for (argno = 0; argno < op->numargs; argno++) {
        !           992:            if (indexf == true) {
        !           993:                indexf = false;
        !           994:            }
        !           995:            argtype = op->argtype[argno];
        !           996:            if (is_branch_disp(argtype)) {
        !           997:                mode = 0xAF + (typelen(argtype) << 5);
        !           998:            } else {
        !           999:                iread(&mode, addr, sizeof(mode));
        !          1000:                addr += 1;
        !          1001:            }
        !          1002:            r = regname[regnm(mode)];
        !          1003:            amode = addrmode(mode);
        !          1004:            switch (amode) {
        !          1005:                case LITSHORT:
        !          1006:                case LITUPTO31:
        !          1007:                case LITUPTO47:
        !          1008:                case LITUPTO63:
        !          1009:                    argval = mode;
        !          1010:                    break;
        !          1011: 
        !          1012:                case INDEX:
        !          1013:                    indexf = true;
        !          1014:                    --argno;
        !          1015:                    break;
        !          1016: 
        !          1017:                case REG:
        !          1018:                case REGDEF:
        !          1019:                case AUTODEC:
        !          1020:                    break;
        !          1021: 
        !          1022:                case AUTOINC:
        !          1023:                    if (r == regname[PROGCTR]) {
        !          1024:                        switch (typelen(argtype)) {
        !          1025:                            case TYPB:
        !          1026:                                argval = getdisp(addr, 1, r, amode);
        !          1027:                                addr += 1;
        !          1028:                                break;
        !          1029: 
        !          1030:                            case TYPW:
        !          1031:                                argval = getdisp(addr, 2, r, amode);
        !          1032:                                addr += 2;
        !          1033:                                break;
        !          1034: 
        !          1035:                            case TYPL:
        !          1036:                                argval = getdisp(addr, 4, r, amode);
        !          1037:                                addr += 4;
        !          1038:                                break;
        !          1039: 
        !          1040:                            case TYPF:
        !          1041:                                iread(&argval, addr, sizeof(argval));
        !          1042:                                addr += 4;
        !          1043:                                break;
        !          1044: 
        !          1045:                            case TYPQ:
        !          1046:                            case TYPD:
        !          1047:                            case TYPG:
        !          1048:                                iread(&argval, addr+4, sizeof(argval));
        !          1049:                                addr += 8;
        !          1050:                                break;
        !          1051: 
        !          1052:                            case TYPO:
        !          1053:                            case TYPH:
        !          1054:                                iread(&argval, addr+12, sizeof(argval));
        !          1055:                                addr += 16;
        !          1056:                                break;
        !          1057:                        }
        !          1058:                    }
        !          1059:                    break;
        !          1060: 
        !          1061:                case AUTOINCDEF:
        !          1062:                    if (r == regname[PROGCTR]) {
        !          1063:                        argval = getdisp(addr, 4, r, amode);
        !          1064:                        addr += 4;
        !          1065:                    }
        !          1066:                    break;
        !          1067: 
        !          1068:                case BYTEDISP:
        !          1069:                case BYTEDISPDEF:
        !          1070:                    argval = getdisp(addr, 1, r, amode);
        !          1071:                    addr += 1;
        !          1072:                    break;
        !          1073: 
        !          1074:                case WORDDISP:
        !          1075:                case WORDDISPDEF:
        !          1076:                    argval = getdisp(addr, 2, r, amode);
        !          1077:                    addr += 2;
        !          1078:                    break;
        !          1079: 
        !          1080:                case LONGDISP:
        !          1081:                case LONGDISPDEF:
        !          1082:                    argval = getdisp(addr, 4, r, amode);
        !          1083:                    addr += 4;
        !          1084:                    break;
        !          1085:            }
        !          1086:        }
        !          1087:        if (ins == O_CALLS or ins == O_CALLG) {
        !          1088:            argval += 2;
        !          1089:        }
        !          1090:        if (addrstatus == BRANCH) {
        !          1091:            addr = argval;
        !          1092:        }
        !          1093:     }
        !          1094:     return addr;
        !          1095: }
        !          1096: 
        !          1097: /*
        !          1098:  * Get the displacement of an instruction that uses displacement addressing.
        !          1099:  */
        !          1100: 
        !          1101: private int getdisp(addr, nbytes, reg, mode)
        !          1102: Address addr;
        !          1103: int nbytes;
        !          1104: String reg;
        !          1105: int mode;
        !          1106: {
        !          1107:     char byte;
        !          1108:     short hword;
        !          1109:     int argval;
        !          1110: 
        !          1111:     switch (nbytes) {
        !          1112:        case 1:
        !          1113:            iread(&byte, addr, sizeof(byte));
        !          1114:            argval = byte;
        !          1115:            break;
        !          1116: 
        !          1117:        case 2:
        !          1118:            iread(&hword, addr, sizeof(hword));
        !          1119:            argval = hword;
        !          1120:            break;
        !          1121: 
        !          1122:        case 4:
        !          1123:            iread(&argval, addr, sizeof(argval));
        !          1124:            break;
        !          1125:     }
        !          1126:     if (reg == regname[PROGCTR] && mode >= BYTEDISP) {
        !          1127:        argval += addr + nbytes;
        !          1128:     }
        !          1129:     return argval;
        !          1130: }
        !          1131: 
        !          1132: /*
        !          1133:  * Enter a procedure by creating and executing a call instruction.
        !          1134:  */
        !          1135: 
        !          1136: #define CALLSIZE 7     /* size of call instruction */
        !          1137: 
        !          1138: public beginproc(p, argc)
        !          1139: Symbol p;
        !          1140: Integer argc;
        !          1141: {
        !          1142:     char save[CALLSIZE];
        !          1143:     struct {
        !          1144:        VaxOpcode op;
        !          1145:        unsigned char numargs;
        !          1146:        unsigned char mode;
        !          1147:        char addr[sizeof(long)];        /* unaligned long */
        !          1148:     } call;
        !          1149:     long dest;
        !          1150: 
        !          1151:     pc = 2;
        !          1152:     iread(save, pc, sizeof(save));
        !          1153:     call.op = O_CALLS;
        !          1154:     call.numargs = argc;
        !          1155:     call.mode = 0xef;
        !          1156:     dest = codeloc(p) - 2 - (pc + 7);
        !          1157:     mov(&dest, call.addr, sizeof(call.addr));
        !          1158:     iwrite(&call, pc, sizeof(call));
        !          1159:     setreg(PROGCTR, pc);
        !          1160:     pstep(process, DEFSIG);
        !          1161:     iwrite(save, pc, sizeof(save));
        !          1162:     pc = reg(PROGCTR);
        !          1163:     if (not isbperr()) {
        !          1164:        printstatus();
        !          1165:     }
        !          1166: }
        !          1167: 
        !          1168: /*
        !          1169:  * Special variables for debugging the kernel.
        !          1170:  */
        !          1171: 
        !          1172: public integer masterpcbb;
        !          1173: public integer slr;
        !          1174: public struct pte *sbr;
        !          1175: private struct pcb pcb;
        !          1176: 
        !          1177: public getpcb ()
        !          1178: {
        !          1179:     integer i;
        !          1180: 
        !          1181:     fseek(corefile, masterpcbb & ~0x80000000, 0);
        !          1182:     get(corefile, pcb);
        !          1183:     pcb.pcb_p0lr &= ~AST_CLR;
        !          1184:     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
        !          1185:        pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
        !          1186:     );
        !          1187:     setreg(0, pcb.pcb_r0);
        !          1188:     setreg(1, pcb.pcb_r1);
        !          1189:     setreg(2, pcb.pcb_r2);
        !          1190:     setreg(3, pcb.pcb_r3);
        !          1191:     setreg(4, pcb.pcb_r4);
        !          1192:     setreg(5, pcb.pcb_r5);
        !          1193:     setreg(6, pcb.pcb_r6);
        !          1194:     setreg(7, pcb.pcb_r7);
        !          1195:     setreg(8, pcb.pcb_r8);
        !          1196:     setreg(9, pcb.pcb_r9);
        !          1197:     setreg(10, pcb.pcb_r10);
        !          1198:     setreg(11, pcb.pcb_r11);
        !          1199:     setreg(ARGP, pcb.pcb_ap);
        !          1200:     setreg(FRP, pcb.pcb_fp);
        !          1201:     setreg(STKP, pcb.pcb_ksp);
        !          1202:     setreg(PROGCTR, pcb.pcb_pc);
        !          1203: }
        !          1204: 
        !          1205: public copyregs (savreg, reg)
        !          1206: Word savreg[], reg[];
        !          1207: {
        !          1208:     reg[0] = savreg[R0];
        !          1209:     reg[1] = savreg[R1];
        !          1210:     reg[2] = savreg[R2];
        !          1211:     reg[3] = savreg[R3];
        !          1212:     reg[4] = savreg[R4];
        !          1213:     reg[5] = savreg[R5];
        !          1214:     reg[6] = savreg[R6];
        !          1215:     reg[7] = savreg[R7];
        !          1216:     reg[8] = savreg[R8];
        !          1217:     reg[9] = savreg[R9];
        !          1218:     reg[10] = savreg[R10];
        !          1219:     reg[11] = savreg[R11];
        !          1220:     reg[ARGP] = savreg[AP];
        !          1221:     reg[FRP] = savreg[FP];
        !          1222:     reg[STKP] = savreg[SP];
        !          1223:     reg[PROGCTR] = savreg[PC];
        !          1224: }
        !          1225: 
        !          1226: /*
        !          1227:  * Map a virtual address to a physical address.
        !          1228:  */
        !          1229: 
        !          1230: public Address vmap (addr)
        !          1231: Address addr;
        !          1232: {
        !          1233:     Address r;
        !          1234:     integer v, n;
        !          1235:     struct pte pte;
        !          1236: 
        !          1237:     r = addr & ~0xc0000000;
        !          1238:     v = btop(r);
        !          1239:     switch (addr&0xc0000000) {
        !          1240:        case 0xc0000000:
        !          1241:        case 0x80000000:
        !          1242:            /*
        !          1243:             * In system space, so get system pte.
        !          1244:             * If it is valid or reclaimable then the physical address
        !          1245:             * is the combination of its page number and the page offset
        !          1246:             * of the original address.
        !          1247:             */
        !          1248:            if (v >= slr) {
        !          1249:                error("address %x out of segment", addr);
        !          1250:            }
        !          1251:            r = ((long) (sbr + v)) & ~0x80000000;
        !          1252:            goto simple;
        !          1253: 
        !          1254:        case 0x40000000:
        !          1255:            /*
        !          1256:             * In p1 space, must not be in shadow region.
        !          1257:             */
        !          1258:            if (v < pcb.pcb_p1lr) {
        !          1259:                error("address %x out of segment", addr);
        !          1260:            }
        !          1261:            r = (Address) (pcb.pcb_p1br + v);
        !          1262:            break;
        !          1263: 
        !          1264:        case 0x00000000:
        !          1265:            /*
        !          1266:             * In p0 space, must not be off end of region.
        !          1267:             */
        !          1268:            if (v >= pcb.pcb_p0lr) {
        !          1269:                error("address %x out of segment", addr);
        !          1270:            }
        !          1271:            r = (Address) (pcb.pcb_p0br + v);
        !          1272:            break;
        !          1273: 
        !          1274:        default:
        !          1275:            /* do nothing */
        !          1276:            break;
        !          1277:     }
        !          1278:     /*
        !          1279:      * For p0/p1 address, user-level page table should be in
        !          1280:      * kernel virtual memory.  Do second-level indirect by recursing.
        !          1281:      */
        !          1282:     if ((r & 0x80000000) == 0) {
        !          1283:        error("bad p0br or p1br in pcb");
        !          1284:     }
        !          1285:     r = vmap(r);
        !          1286: simple:
        !          1287:     /*
        !          1288:      * "r" is now the address of the pte of the page
        !          1289:      * we are interested in; get the pte and paste up the physical address.
        !          1290:      */
        !          1291:     fseek(corefile, r, 0);
        !          1292:     n = fread(&pte, sizeof(pte), 1, corefile);
        !          1293:     if (n != 1) {
        !          1294:        error("page table botch (fread at %x returns %d)", r, n);
        !          1295:     }
        !          1296:     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
        !          1297:        error("page no valid or reclamable");
        !          1298:     }
        !          1299:     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
        !          1300: }
        !          1301: 
        !          1302: /*
        !          1303:  * Extract a bit field from an integer.
        !          1304:  */
        !          1305: 
        !          1306: public integer extractField (s)
        !          1307: Symbol s;
        !          1308: {
        !          1309:     integer n, nbytes, r;
        !          1310: 
        !          1311:     n = 0;
        !          1312:     nbytes = size(s);
        !          1313:     if (nbytes > sizeof(n)) {
        !          1314:        printf("[bad size in extractField -- word assumed]\n");
        !          1315:        nbytes = sizeof(n);
        !          1316:     }
        !          1317:     popn(nbytes, &n);
        !          1318:     r = n >> (s->symvalue.field.offset mod BITSPERBYTE);
        !          1319:     r &= ((1 << s->symvalue.field.length) - 1);
        !          1320:     return r;
        !          1321: }
        !          1322: 
        !          1323: /*
        !          1324:  * Change the length of a value in memory according to a given difference
        !          1325:  * in the lengths of its new and old types.
        !          1326:  */
        !          1327: 
        !          1328: public loophole (oldlen, newlen)
        !          1329: integer oldlen, newlen;
        !          1330: {
        !          1331:     integer n, i;
        !          1332: 
        !          1333:     n = newlen - oldlen;
        !          1334:     if (n > 0) {
        !          1335:        for (i = 0; i < n; i++) {
        !          1336:            sp[i] = '\0';
        !          1337:        }
        !          1338:     }
        !          1339:     sp += n;
        !          1340: }

unix.superglobalmegacorp.com

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