Annotation of coherent/b/bin/c/n2/i8086/out286.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * This file contains an output writer for Intel iAPX-80286 OMF.
        !             3:  * Some of this code is from the i8086 OMF output writer.
        !             4:  *
        !             5:  * References:  "The Concrete Representation of 80286
        !             6:  * Object Module Formats," Rev. 1.91 (c) Intel 1983.
        !             7:  * "Type Definition Records for High Level Languages,"
        !             8:  * Version 2.0, 6/25/84, #114834 (Intel proprietary).
        !             9:  *
        !            10:  * During code assembly, the 'out...' routines write to a temporary file.
        !            11:  * At the end of assembly, 'copycode' writes the object file
        !            12:  * using the 'write...' routines.
        !            13:  * The 'put...' routines copy bits to the object file.
        !            14:  * The object file contains a single linkable module
        !            15:  * which in turn contains a single partition.
        !            16:  * It may include SEGDEF, TYPDEF, PUBDEF, EXTDEF and TXTFIX sections.
        !            17:  * The section lengths and locations in the table of contents
        !            18:  * and the segment attributes and lengths in the SEGDEF section
        !            19:  * are initially 0; 'fixoutput' seeks back in the output file
        !            20:  * (or copies it back, in the case of the VAX version)
        !            21:  * and patches them with the correct values.
        !            22:  */
        !            23: 
        !            24: #ifdef   vax
        !            25: #include "INC$LIB:cc2.h"
        !            26: #include <time.h>
        !            27: #else
        !            28: #include "cc2.h"
        !            29: #endif
        !            30: #ifdef COHERENT
        !            31: #include <time.h>
        !            32: #include <sys/timeb.h>
        !            33: #endif
        !            34: #ifdef UDI
        !            35: #include <udi.h>
        !            36: #endif
        !            37: #ifndef __LINE__
        !            38: #define        __LINE__        0
        !            39: #endif
        !            40: #if !TINY
        !            41: #define dbrpt(x,y)     _dbrpt(x,y)
        !            42: #else
        !            43: #define dbrpt(x,y)     /* _dbrpt(x,y) */
        !            44: #endif
        !            45: 
        !            46: /*
        !            47:  * As of 4/29/85, PSCOPE does not support unnamed blocks correctly.
        !            48:  * The output writer therefore suppresses unnamed blocks #ifdef NOABLOCKS.
        !            49:  */
        !            50: #if INTEL
        !            51: #define        NOABLOCKS 1
        !            52: int    blkcount;
        !            53: #endif
        !            54: 
        !            55: #define        NTXT    256                     /* Text buffer size */
        !            56: #define        NFIX    256                     /* Fixup buffer size */
        !            57: 
        !            58: /*
        !            59:  * Scratch file opcodes.
        !            60:  */
        !            61: #define        TTYPE   0x0F                    /* Type */
        !            62: #define        TPCR    0x10                    /* PC rel flag, ored in */
        !            63: #define        TSYM    0x20                    /* Symbol based flag, ored in */
        !            64: #define        TEND    0                       /* End marker */
        !            65: #define        TENTER  1                       /* Enter new area */
        !            66: #define        TBYTE   2                       /* Byte data */
        !            67: #define        TWORD   3                       /* Word data */
        !            68: #define        TCODE   4                       /* Code segment base */
        !            69: #define        TDATA   5                       /* Data segment base */
        !            70: #define        TBASE   6                       /* External segment base */
        !            71: #define        TDLAB   7                       /* Debug label */
        !            72: #define TDLOC  8                       /* Debug location */
        !            73: 
        !            74: /*
        !            75:  * Sections, in the order of the table of contents.
        !            76:  */
        !            77: #define        NSECS   6                       /* Number of sections */
        !            78: #define        SEGSEC  0                       /* SEGDEF section */
        !            79: #define        GATSEC  1                       /* GATDEF section */
        !            80: #define        TYPSEC  2                       /* TYPDEF section */
        !            81: #define        PUBSEC  3                       /* PUBDEF section */
        !            82: #define        EXTSEC  4                       /* EXTDEF section */
        !            83: #define        TXTSEC  5                       /* TXTFIX section */
        !            84: 
        !            85: /*
        !            86:  * Segment indices, in the order of 'writesegdef'.
        !            87:  */
        !            88: #define        NSEGS   6                       /* Number of segments if DEBUG */
        !            89: #define        CODESEG 1                       /* CODE */
        !            90: #define        DATASEG 2                       /* DATA */
        !            91: #define        STKSEG  3                       /* STACK */
        !            92: #define        MODSEG  4                       /* MODULES: */
        !            93: #define        SYMSEG  5                       /* SYMBOLS: */
        !            94: #define        LINESEG 6                       /* LINES: */
        !            95: 
        !            96: /*
        !            97:  * 80286 OMF bits.
        !            98:  */
        !            99: #define        TID     6                       /* C-286 translator id */
        !           100: #define        SEGIN   (1<<13)                 /* Segment internal name field */
        !           101: #define        EXTIN   (3<<13)                 /* External symbol int name field */
        !           102: #define        BTEXT   0                       /* TXTFIX text block */
        !           103: #define        BFIXUP  1                       /* TXTFIX fixup block */
        !           104: #define        BITEXT  2                       /* TXTFIX iterated text block */
        !           105: #define        FORMSEL (0<<2)                  /* Fixup format selector only */
        !           106: #define        FORMOFF (1<<2)                  /* Fixup format offset only */
        !           107: #define        FORMSRO (2<<2)                  /* Fixup format self-relative offset */
        !           108: #define        FORMFVA (3<<2)                  /* Fixup format full virtual addr */
        !           109: #define        FIXGEN  0                       /* Fixup type general */
        !           110: #define        FIXISEG 1                       /* Fixup type intrasegment */
        !           111: #define        FIXCALL 2                       /* Fixup type call */
        !           112: #define        SYMBBEG 0                       /* SYMBOLS block start */
        !           113: #define        SYMPBEG 1                       /* SYMBOLS procedure start */
        !           114: #define        SYMBEND 2                       /* SYMBOLS block end */
        !           115: #define        SYMBASE 3                       /* SYMBOLS base */
        !           116: #define        SYMBPRB 4                       /* SYMBOLS BP-relative base */
        !           117: #define        SYMSYMB 5                       /* SYMBOLS symbol */
        !           118: #define        SEGARO  (0<<13)                 /* SEGDEF access readonly */
        !           119: #define        SEGARW  (1<<13)                 /* SEGDEF access read-write */
        !           120: #define        SEGAXR  (3<<13)                 /* SEGDEF access execute-read */
        !           121: #define        SEGDPL  (3<<11)                 /* SEGDEF DPL */
        !           122: #define        SEGEXT  (1<<6)                  /* SEGDEF external */
        !           123: #define        SEGNOC  0                       /* SEGDEF combine type no-combine */
        !           124: #define        SEGCOM  1                       /* SEGDEF combine type normal */
        !           125: #define        SEGSTK  2                       /* SEGDEF combine type stack */
        !           126: #define        SEGDEB  6                       /* SEGDEF combine type debug */
        !           127: 
        !           128: /*
        !           129:  * Type representation constants for i80286 TYPDEF records.
        !           130:  * Some differ from the corresponding i8086 OMF constants.
        !           131:  */
        !           132: #if INTEL
        !           133: /* Intel proprietary. */
        !           134: #define OTSFUNC        0x63                    /* SHORT$NOPOP */
        !           135: #define OTLFUNC        0x64                    /* LONG$NOPOP */
        !           136: #define OTUPACK        0x69                    /* UNPACKED */
        !           137: #define OTLABEL        0x72                    /* LABEL */
        !           138: #define OTLONG 0x73                    /* LONG */
        !           139: #define OTSHORT        0x74                    /* SHORT */
        !           140: #define OTPROC 0x75                    /* PROCEDURE */
        !           141: #define OTPARA 0x76                    /* PARAMETER */
        !           142: #define OTARRAY        0x78                    /* ARRAY */
        !           143: #define OTSTRUC        0x79                    /* STRUCTURE */
        !           144: #define OTPOINT        0x7A                    /* POINTER */
        !           145: #define OTSCAL 0x7B                    /* SCALAR */
        !           146: #define OTUINT 0x7C                    /* UNSINT */
        !           147: #define OTSINT 0x7D                    /* SGNINT */
        !           148: #define OTREAL 0x7E                    /* REAL */
        !           149: #define OTLIST 0x7F                    /* LIST */
        !           150: #endif
        !           151: #define OTNIL  0x80                    /* NIL */
        !           152: #define OTNAME 0x82                    /* Name leaf */
        !           153: #define OTINDEX        0x83                    /* Index leaf */
        !           154: #define OTUNUM2        0x85                    /* Unsigned numeric 2 byte leaf */
        !           155: #define OTUNUM4        0x86                    /* Unsigned numeric 4 byte leaf */
        !           156: 
        !           157: /*
        !           158:  * Length and OMF type of scalar C types.
        !           159:  * The order corresponds to the order of DT_ types in ops.h.
        !           160:  */
        !           161: #if INTEL
        !           162: static char ntypes [DT_DOUBLE+1][2] = {
        !           163:        { 0x00, OTNIL },                /* DT_NONE */
        !           164:        { 0x08, OTSINT },               /* DT_CHAR */
        !           165:        { 0x08, OTUINT },               /* DT_UCHAR */
        !           166:        { 0x10, OTSINT },               /* DT_SHORT */
        !           167:        { 0x10, OTUINT },               /* DT_USHORT */
        !           168:        { 0x10, OTSINT },               /* DT_INT */
        !           169:        { 0x10, OTUINT },               /* DT_UINT */
        !           170:        { 0x20, OTSINT },               /* DT_LONG */
        !           171:        { 0x20, OTUINT },               /* DT_ULONG */
        !           172:        { 0x20, OTREAL },               /* DT_FLOAT */
        !           173:        { 0x40, OTREAL }                /* DT_DOUBLE */
        !           174: };
        !           175: #endif
        !           176: 
        !           177: /*
        !           178:  * The compiler generates a linked list of TINFO records
        !           179:  * containing OMF type definitions while reading DLABEL records.
        !           180:  * The type index corresponds to the position in the TINFO list.
        !           181:  * The tflag keeps track of whether a forward reference
        !           182:  * tagname type ever gets resolved.
        !           183:  */
        !           184: typedef        struct  typeinfo {
        !           185:        struct  typeinfo *t_tp;         /* link */
        !           186:        char    t_tflag;                /* tag name flag */
        !           187:        int     t_length;               /* length */
        !           188:        char    t_info[];               /* info */
        !           189: } TINFO;
        !           190: 
        !           191: /*
        !           192:  * To generate correct references to tagged types, the compiler
        !           193:  * enters the tag name as a type and refers to the type by tag name.
        !           194:  * When the compiler dumps the types, it consults the patch list
        !           195:  * and substitutes the tag definition for the tag name.
        !           196:  */
        !           197: typedef struct typefix {
        !           198:        struct  typefix *t_tp;          /* Link */
        !           199:        int     t_ttype;                /* Dummy definition */
        !           200:        int     t_type;                 /* Fixed definition */
        !           201: } TYFIX;
        !           202: 
        !           203: /*
        !           204:  * Structure to contain debug items on this pass.
        !           205:  */
        !           206: struct dbgt {
        !           207:        struct dbgt *d_dp;              /* Link */
        !           208:        int d_ref;                      /* Index number */
        !           209:        unsigned char d_class;          /* Storage class */
        !           210:        unsigned char d_flag;           /* Flags */
        !           211:        unsigned char d_level;          /* Bracket level */
        !           212:        unsigned char d_seg;            /* Segment */
        !           213:        ADDRESS d_value;                /* Offset in segment */
        !           214:        int d_type;                     /* Type index */
        !           215:        int d_line;                     /* Line number */
        !           216:        char d_id[];                    /* Name */
        !           217: };
        !           218: 
        !           219: /*
        !           220:  * Globals.
        !           221:  */
        !           222: static int     checksum;               /* For putbyte */
        !           223: static int     lastline;               /* Last line number */
        !           224: static long    lastsize;               /* Last number size */
        !           225: static int     txtseg;                 /* Current text segment */
        !           226: static unsigned char   txt[NTXT];      /* Text buffer */
        !           227: static unsigned char   *txtp = txt;    /* Text pointer */
        !           228: static int     fixseg;                 /* Current fixup segment */
        !           229: static unsigned char   fix[NFIX];      /* Fixup buffer */
        !           230: static unsigned char   *fixp = fix;    /* Fixup pointer */
        !           231: static unsigned char   *ofixp = NULL;  /* Previous fixup pointer for fva kludge */
        !           232: static int     symbase;                /* Symbol base, -1 for BP-rel */
        !           233: static ADDRESS seg_size;               /* Size of segment thus far */
        !           234: static ADDRESS bss_size;               /* Size of BSS */
        !           235: static ADDRESS seglen[NSEGS+1];        /* Segment text length */
        !           236: static long    secloc[NSECS];          /* Section locations */
        !           237: static long    seclen[NSECS];          /* Section lengths */
        !           238: static long    oflength;               /* Output file length */
        !           239: static int     nsegs;                  /* Number of SEGDEFs */
        !           240: static int     npubs;                  /* Number of PUBDEFs */
        !           241: static int     nexts;                  /* Number of EXTDEFs */
        !           242: static TINFO   *typelistp;             /* Typdef list */
        !           243: static TYFIX   *typefixp;              /* Type fix list */
        !           244: static SYM     *curfsp;                /* Current function sp */
        !           245: static int     curfna;                 /* Current function nargs */
        !           246: static int     curfar[NARGS];          /* Current function arg types */
        !           247: static struct dbgt     *dbase;         /* First debug table entry */
        !           248: static struct dbgt     *dnext;         /* Last debug table entry */
        !           249: 
        !           250: /*
        !           251:  * Object file offsets.
        !           252:  * Used by fixoutput() to fix information in output file.
        !           253:  */
        !           254: static long    mhdseek;                /* Module header offset */
        !           255: static long    tocseek;                /* Table of contents offset */
        !           256: static long    segseek[NSEGS+1];       /* SEGDEF attribute byte offsets */
        !           257: static long    lenseek;                /* SYMBOLS module length offset */
        !           258: 
        !           259: /*
        !           260:  * Functions.
        !           261:  */
        !           262: extern struct dbgt     *getdbgt();
        !           263: extern TINFO   *gettype();
        !           264: extern long    putsegdef();
        !           265: extern char    *setindex();
        !           266: extern char    *setname();
        !           267: extern char    *setnumb();
        !           268: extern char    *setsize();
        !           269: extern char    *setsymid();
        !           270: 
        !           271: #if VAXFMT
        !           272: /*
        !           273:  * The Intel cross software packs the OMF data into 512 byte blocks
        !           274:  * as 510 byte variable length records, with the last record short.
        !           275:  */
        !           276: #define        NVDATA  510                     /* Blocksize - 2 */
        !           277: static char    vaxbuf[NVDATA];         /* Buffer */
        !           278: static char    *vaxptr = vaxbuf;       /* Pointer */
        !           279: extern int     filo;
        !           280: extern char    *wfn[];
        !           281: extern char    ofn[];
        !           282: extern int     trace();
        !           283: #endif
        !           284: 
        !           285: /*
        !           286:  * Routine 'segindex' uses the following tables
        !           287:  * to find the OMF segment index corresponding
        !           288:  * to a given compiler internal segment name.
        !           289:  * The tables understand the ROM and RAM options.
        !           290:  * SMALL model always uses ramseg[] (because the compiler assumes
        !           291:  * SMALL model SPURE, SSTRN, SDATA and SBSS references to be DS-relative).
        !           292:  */
        !           293: static char    nonseg[] = {
        !           294:        CODESEG,                        /* SCODE => CODE */
        !           295:        CODESEG,                        /* SLINK => CODE */
        !           296:        CODESEG,                        /* SPURE => CODE */
        !           297:        DATASEG,                        /* SSTRN => DATA */
        !           298:        DATASEG,                        /* SDATA => DATA */
        !           299:        DATASEG                         /* SBSS  => DATA */
        !           300: };
        !           301: static char    romseg[] = {
        !           302:        CODESEG,                        /* SCODE => CODE */
        !           303:        CODESEG,                        /* SLINK => CODE */
        !           304:        CODESEG,                        /* SPURE => CODE */
        !           305:        CODESEG,                        /* SSTRN => CODE */
        !           306:        DATASEG,                        /* SDATA => DATA */
        !           307:        DATASEG                         /* SDATA => DATA */
        !           308: };
        !           309: static char    ramseg[] = {
        !           310:        CODESEG,                        /* SCODE => CODE */
        !           311:        CODESEG,                        /* SLINK => CODE */
        !           312:        DATASEG,                        /* SPURE => DATA */
        !           313:        DATASEG,                        /* SSTRN => DATA */
        !           314:        DATASEG,                        /* SDATA => DATA */
        !           315:        DATASEG                         /* SDATA => DATA */
        !           316: };
        !           317: 
        !           318: /*
        !           319: ** First pass routines.
        !           320: ** Output items to the temporary file.
        !           321:  */
        !           322: 
        !           323: /*
        !           324:  * Output a segment switch.
        !           325:  */
        !           326: outseg(s)
        !           327: {
        !           328:        bput(TENTER);
        !           329:        bput(s);
        !           330: }
        !           331: 
        !           332: /*
        !           333:  * Output an absolute byte.
        !           334:  */
        !           335: outab(b)
        !           336: {
        !           337:        bput(TBYTE);
        !           338:        bput(b);
        !           339:        ++dot;
        !           340: }
        !           341: 
        !           342: /*
        !           343:  * Output an absolute word.
        !           344:  */
        !           345: outaw(w)
        !           346: {
        !           347:        bput(TWORD);
        !           348:        iput(w);
        !           349:        dot += 2;
        !           350: }
        !           351: 
        !           352: /*
        !           353:  * Output a full byte.
        !           354:  */
        !           355: outxb(sp, b, pcrf)
        !           356: register SYM *sp;
        !           357: {
        !           358:        register opcode;
        !           359:        opcode = TBYTE;
        !           360:        if (sp != NULL)
        !           361:                opcode |= TSYM;
        !           362:        if (pcrf)
        !           363:                opcode |= TPCR;
        !           364:        bput(opcode);
        !           365:        bput(b);
        !           366:        if (sp != NULL)
        !           367:                pput(sp);
        !           368:        ++dot;
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * Output a full word.
        !           373:  */
        !           374: outxw(sp, w, pcrf)
        !           375: register SYM *sp;
        !           376: {
        !           377:        register opcode;
        !           378:        opcode = TWORD;
        !           379:        if (sp != NULL)
        !           380:                opcode |= TSYM;
        !           381:        if (pcrf)
        !           382:                opcode |= TPCR;
        !           383:        bput(opcode);
        !           384:        iput(w);
        !           385:        if (sp != NULL)
        !           386:                pput(sp);
        !           387:        dot += 2;
        !           388: }
        !           389: 
        !           390: #if    0
        !           391: /*
        !           392:  * Because the compiler now generates LARGE model code with links,
        !           393:  * the following routines are currently unused.
        !           394:  * They are retained for future reference.
        !           395:  */
        !           396: /*
        !           397:  * Output a 1 word object containing
        !           398:  * the base address of the current code segment.
        !           399:  */
        !           400: outcb()
        !           401: {
        !           402:        bput(TCODE);
        !           403:        dot += 2;
        !           404: }
        !           405: 
        !           406: /*
        !           407:  * Output a 1 word object containing
        !           408:  * the base address of the current data segment.
        !           409:  */
        !           410: outdb()
        !           411: {
        !           412:        bput(TDATA);
        !           413:        dot += 2;
        !           414: }
        !           415: #endif
        !           416: 
        !           417: /*
        !           418:  * Output a 1 word object containing
        !           419:  * the base address of the external symbol pointed to by 'sp'.
        !           420:  */
        !           421: outsb(sp)
        !           422: SYM *sp;
        !           423: {
        !           424:        bput(TBASE);
        !           425:        pput(sp);
        !           426:        dot += 2;
        !           427: }
        !           428: 
        !           429: /*
        !           430:  * Initialize the code writer.
        !           431:  */
        !           432: outinit()
        !           433: {
        !           434:        register TINFO *tp;
        !           435: #if MONOLITHIC
        !           436:        /* UNDONE:  initialize all globals here */
        !           437:        txtp = &txt[0];
        !           438:        fixp = &fix[0];
        !           439: #if VAXFMT
        !           440:        vaxptr = &vaxbuf[0];
        !           441: #endif
        !           442: #endif
        !           443:        /* Initialize type list to contain NIL type as type 1. */
        !           444:        typelistp = tp = (TINFO *)malloc(sizeof(TINFO)+1);
        !           445:        typefixp = tp->t_tp = NULL;
        !           446:        tp->t_tflag = 0;
        !           447:        tp->t_length = 1;
        !           448:        tp->t_info[0] = OTNIL;
        !           449: }
        !           450: 
        !           451: /*
        !           452:  * Finish up the code.
        !           453:  * If writing binary code, put out a TEND item
        !           454:  * to tell 'copycode' when to stop.
        !           455:  */
        !           456: outdone()
        !           457: {
        !           458:        if (notvariant(VASM))
        !           459:                bput(TEND);
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Read a dlabel record from ifp.
        !           464:  * If l(evel) == 0, then only the DLABEL and class bytes have been read.
        !           465:  * For GDEF's and SEX's in SCODE, save the symbol pointer, accumulate the
        !           466:  * argument list types, and back patch the type appropriately.
        !           467:  * For everything else at level zero, translate the compiler type
        !           468:  * to OMF type and write a truncated record to the scratch file.
        !           469:  */
        !           470: outdlab(l, class)
        !           471: {
        !           472:        register int value;
        !           473:        register int nline;
        !           474:        register SYM *sp;
        !           475:        register int type;
        !           476:        register int seg;
        !           477:        register int ttype;
        !           478: 
        !           479:        /* Get line number */
        !           480:        nline = iget();
        !           481: 
        !           482:        if (l != 0)
        !           483:                dbfatal(__LINE__);
        !           484:        value = 0;
        !           485:        seg = dotseg;
        !           486:        /* Get value */
        !           487:        if (class < DC_AUTO)
        !           488:                ;
        !           489:        else if (class < DC_MOS)
        !           490:                value = iget();
        !           491:        else
        !           492:                dbfatal(__LINE__);
        !           493: 
        !           494:        /* Get name */
        !           495:        sget(id, NCSYMB);
        !           496: 
        !           497:        /* Check for symbol table entry */
        !           498:        sp = NULL;
        !           499:        if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) {
        !           500:                sp = glookup(id, 0);
        !           501:        } else {
        !           502:                /* Make all c names the same, hopefully */
        !           503:        }
        !           504:        if (sp != NULL) {
        !           505:                seg = sp->s_seg;
        !           506:                value = sp->s_value;
        !           507:        }
        !           508:        /* Check for tag definition */
        !           509:        if (class==DC_ETAG
        !           510:         || class==DC_STAG
        !           511:         || class==DC_UTAG)
        !           512:                ttype = tlookup(id, strlen(id)+1);
        !           513:        else
        !           514:                ttype = 0;
        !           515: 
        !           516:        /* Write part of truncated record */
        !           517:        bput(TDLAB);
        !           518:        bput(class);
        !           519:        iput(nline);
        !           520:        iput(value);
        !           521:        bput(seg);
        !           522:        sput(id);
        !           523: 
        !           524:        /* Get type and enter into table */
        !           525:        /* This will possibly overwrite id[], so it must come after glookup */
        !           526:        type = dbtmap(ttype);
        !           527: 
        !           528:        /* Write out truncated record */
        !           529:        iput(type);
        !           530: 
        !           531:        /* Store the type for pubdef and extdef records */
        !           532:        if (sp != NULL) {
        !           533:                sp->s_type = type;
        !           534:                /* Begin collecting parameter types */
        !           535:                if ((class == DC_GDEF || class == DC_SEX)
        !           536:                 && sp->s_seg == SCODE) {
        !           537:                        curfsp = sp;
        !           538:                        curfna = 0;
        !           539:                }
        !           540:        }
        !           541:        /* Collect parameter types */
        !           542:        if (class == DC_PAUTO || class == DC_PREG)
        !           543:                curfar[curfna++] = type;
        !           544:        /* Dump the parameter list, tricky stuff. */
        !           545:        if (class == DC_LINE && id[0] == '{' && curfna >= 0) {
        !           546:                arglisttype();
        !           547:                curfna = -1;
        !           548:        }
        !           549:        /* Back patch tag definition */
        !           550:        if (ttype != 0)
        !           551:                tpatch(ttype, type);
        !           552: }
        !           553: 
        !           554: /*
        !           555:  * Enter a patch into the typefix list.
        !           556:  */
        !           557: tpatch(ttype, type)
        !           558: {
        !           559:        register TYFIX *tp;
        !           560:        tp = (TYFIX *) malloc(sizeof(*tp));
        !           561:        if (tp == NULL) dbmemory(__LINE__);
        !           562:        tp->t_ttype = ttype;
        !           563:        tp->t_type = type;
        !           564:        tp->t_tp = typefixp;
        !           565:        typefixp = tp;
        !           566: }
        !           567: 
        !           568: /*
        !           569:  * Return type index associated with type definition
        !           570:  * at infop of length len.
        !           571:  * Define a new TINFO item if necessary.
        !           572:  */
        !           573: tlookup(infop, len)
        !           574: register char *infop;
        !           575: int len;
        !           576: {
        !           577: #if INTEL
        !           578:        register TINFO *tp, *lasttp;
        !           579:        register int i, index;
        !           580:        register char *cp1, *cp2;
        !           581:        tp = typelistp;
        !           582:        index = 1;
        !           583:        /* Search the TINFO list for the type. */
        !           584:        while (tp != NULL) {
        !           585:                if (tp->t_length == len) {
        !           586:                        cp1 = infop;
        !           587:                        cp2 = tp->t_info;
        !           588:                        i = len;
        !           589:                        while ((*cp1++ == *cp2++) && (--i > 0))
        !           590:                                ;
        !           591:                        if (i == 0)
        !           592:                                return (index);
        !           593:                }
        !           594:                index++;
        !           595:                lasttp = tp;
        !           596:                tp = tp->t_tp;
        !           597:        }
        !           598:        /* Not found, add new type to TINFO list. */
        !           599:        if ((tp=(TINFO *)malloc(sizeof(TINFO)+len)) == NULL)
        !           600:                cnomem("tlookup");
        !           601:        tp->t_tp = NULL;
        !           602:        tp->t_tflag = 0;
        !           603:        tp->t_length = len;
        !           604:        cp1 = tp->t_info;
        !           605:        while (len--)
        !           606:                *cp1++ = *infop++;
        !           607:        /* outinit puts NIL type on the list, so it's never empty. */
        !           608:        lasttp->t_tp = tp;
        !           609:        return (index);
        !           610: #else
        !           611:        return (1);
        !           612: #endif
        !           613: }
        !           614: 
        !           615: /*
        !           616:  * Read the dimension/type/info list from input and return the type index.
        !           617:  * Store the size back through the pointer supplied.
        !           618:  * This routine is reentrant so it can map the types of structure members
        !           619:  * while mapping the structure definition.
        !           620:  */
        !           621: dbtmap(ttype)
        !           622: {
        !           623:        int             type;
        !           624:        unsigned        size;
        !           625:        register char   *bp;
        !           626:        char            bb[10];
        !           627: 
        !           628:        bp = bb;
        !           629:        type = bget();
        !           630:        size = iget();
        !           631:        switch (type) {
        !           632:        case DT_NONE:
        !           633: #if INTEL
        !           634:                /* NIL */
        !           635:                *bp++ = OTNIL;
        !           636: #endif
        !           637:                break;
        !           638:        case DT_CHAR:
        !           639:        case DT_UCHAR:
        !           640:        case DT_SHORT:
        !           641:        case DT_USHORT:
        !           642:        case DT_INT:
        !           643:        case DT_UINT:
        !           644:        case DT_LONG:
        !           645:        case DT_ULONG:
        !           646:        case DT_FLOAT:
        !           647:        case DT_DOUBLE:
        !           648: #if INTEL
        !           649:                /* SCALAR length type */
        !           650:                *bp++ = OTSCAL;
        !           651:                bp = setsize(bp, (long)(ntypes[type][0]));
        !           652:                *bp++ = ntypes[type][1];
        !           653: #endif
        !           654:                break;
        !           655:        case DT_VOID:
        !           656: #if INTEL
        !           657:                *bp++ = OTNIL;                  /* undone */
        !           658: #endif
        !           659:                break;
        !           660:        case DT_STRUCT:
        !           661:        case DT_UNION:
        !           662:        case DT_ENUM:
        !           663:                if (bget() == DX_NAME) {
        !           664:                        lastsize = ((long)size) * NBPBYTE;
        !           665:                        return (dbxname(ttype));
        !           666:                }
        !           667:                else if (type == DT_STRUCT)
        !           668:                        return (dbxstruct(size, ttype));
        !           669:                else if (type == DT_UNION)
        !           670:                        return (dbxunion(size, ttype));
        !           671:                else
        !           672:                        return (dbxenum(size, ttype));
        !           673:        case DD_PTR:
        !           674: #if INTEL
        !           675:                /* SCALAR length @pointer */
        !           676:                /* POINTER @type */
        !           677:                *bp++ = OTPOINT;
        !           678: #endif
        !           679:                type = dbtmap(ttype);
        !           680: #if INTEL
        !           681:                bp = setindex(bp, type);
        !           682:                type = tlookup(bb, bp-bb);
        !           683:                bp = bb;
        !           684:                *bp++ = OTSCAL;
        !           685:                bp = setsize(bp, isvariant(VLARGE) ? 0x20L : 0x10L);
        !           686:                bp = setindex(bp, type);
        !           687: #endif
        !           688:                break;
        !           689:        case DD_FUNC:
        !           690: #if INTEL
        !           691:                /* PROCEDURE NIL @type calltype count @plist */
        !           692:                /* arglisttype will fix the count and @plist later. */
        !           693:                *bp++ = OTPROC;
        !           694:                *bp++ = OTNIL;
        !           695: #endif
        !           696:                type = dbtmap(ttype);
        !           697: #if INTEL
        !           698:                bp = setindex(bp, type);
        !           699:                *bp++ = (isvariant(VLARGE)) ? OTLFUNC : OTSFUNC;
        !           700:                *bp++ = 0;      /* Zero args, possibly corrected later */
        !           701: #endif
        !           702:                break;
        !           703:        case DD_ARRAY:
        !           704:                type = dbtmap(ttype);
        !           705: #if INTEL
        !           706:                /* ARRAY length @type */
        !           707:                *bp++ = OTARRAY;
        !           708:                bp = setsize(bp, ((long)size)*NBPBYTE);
        !           709:                bp = setindex(bp, type);
        !           710: #endif
        !           711:                break;
        !           712:        default:
        !           713:                dbfatal(__LINE__);
        !           714:        }
        !           715:        return (tlookup(bb, bp-bb));
        !           716: }
        !           717: 
        !           718: /*
        !           719:  * Construct typdef for enum, struct, or union.
        !           720:  * DX_NAME records supply tag name of type which will be defined later.
        !           721:  * Tag references point to type consisting of the tag name;
        !           722:  * the type will be backpatched into a struct/union/enum typdef.
        !           723:  */
        !           724: dbxname(ttype)
        !           725: {
        !           726:        register char   *bp;
        !           727:        register TINFO  *tp;
        !           728:        register int i;
        !           729:        iget();         /* Dummy size */
        !           730:        bp = &id[0];
        !           731:        while (*bp++ = bget())
        !           732:                ;
        !           733:        i = tlookup(id, bp-id);
        !           734:        tp = gettype(i);
        !           735:        tp->t_tflag = 1;
        !           736:        return(i);
        !           737: }
        !           738: 
        !           739: dbxstruct(s, ttype)
        !           740: unsigned       s;              /* Size of structure in bytes */
        !           741: {
        !           742:        int     nmemb;  /* Number of members */
        !           743:        int     i;      /* Member counter */
        !           744:        unsigned        bwid;   /* Bit width of current field */
        !           745:        unsigned        boff;   /* Bit offset of current field */
        !           746:        unsigned        valu;   /* Byte offset of current member */
        !           747:        int     type;   /* Type index of current member */
        !           748: #if INTEL
        !           749:        int     size;   /* Size of name field */
        !           750:        long    offs;   /* Bit offset computed from valu and boff */
        !           751:        long    loffs;  /* Bit offset computed from previous member */
        !           752:        int     nname;  /* Number of bytes required for name list */
        !           753:        int     tlist;  /* Type list index */
        !           754:        int     nlist;  /* Name list index */
        !           755:        struct  slist {
        !           756:                struct slist *sl_sp;
        !           757:                int     sl_type;
        !           758:                char    sl_id[];
        !           759:        };
        !           760:        struct slist *sp1;
        !           761:        register struct slist *sp2;
        !           762:        char *lp;
        !           763:        register char *bp;
        !           764:        char bb[64];
        !           765: #endif
        !           766: 
        !           767:        /* Struct member list */
        !           768: #if INTEL
        !           769:        /* STRUCT length count @tlist @nlist name */
        !           770:        /* tLIST @type1 ... @typen */
        !           771:        /* nLIST name1 ... namen */
        !           772:        sp1 = NULL;
        !           773:        offs = loffs = 0;
        !           774:        nname = 0;
        !           775: #endif
        !           776:        nmemb = iget();         /* Number of members */
        !           777:                                /* Does not include filler fields */
        !           778:        /* Read in member descriptions */
        !           779:        for (i = nmemb; i > 0; i--) {
        !           780:                if (bget() != DC_MOS)
        !           781:                        dbfatal(__LINE__);
        !           782:                iget();         /* forget line */
        !           783:                bwid = bget();  /* bit width */
        !           784:                boff = bget();  /* bit offset */
        !           785:                valu = iget();  /* byte offset */
        !           786:                sget(id, NCSYMB);
        !           787: #if INTEL
        !           788:                /* Enter into list, possibly prefixing nil filler field */
        !           789:                offs = (long)valu * (long)NBPBYTE + boff;
        !           790:                if (offs != loffs) {
        !           791:                        /* Add filler field with name "" so PSCOPE */
        !           792:                        /* does not lose its place in the structure. */
        !           793:                        nmemb++;        /* Add a member */
        !           794:                        nname += 2;     /* Bytes required for nlist */
        !           795:                        sp2 = (struct slist *)malloc(sizeof(*sp2)+1);
        !           796:                        if (sp2 == NULL) dbmemory(__LINE__);
        !           797:                        sp2->sl_type = dbfmap((int)(offs-loffs), DT_UINT);
        !           798:                        sp2->sl_id[0] = 0;
        !           799:                        sp2->sl_sp = sp1;
        !           800:                        sp1 = sp2;
        !           801:                }
        !           802:                size = strlen(id)+2;    /* OTNAME+count+length */
        !           803:                nname += size;
        !           804:                sp2 = (struct slist *)malloc(sizeof(*sp2)+size);
        !           805:                if (sp2 == NULL) dbmemory(__LINE__);
        !           806:                strcpy(sp2->sl_id, id);
        !           807: #endif
        !           808:                /* Now get the type with its possible id field */
        !           809:                if (bwid != 0) {
        !           810:                        /* Only fields have non-zero widths and offsets */
        !           811:                        type = dbfmap(bwid, bget());
        !           812:                        iget(); /* Subtype size */
        !           813:                        lastsize = bwid;
        !           814:                } else {
        !           815:                        /* Non field member, must lookup its width */
        !           816:                        type = dbtmap(0);
        !           817:                }
        !           818: #if INTEL
        !           819:                sp2->sl_type = type;
        !           820:                sp2->sl_sp = sp1;
        !           821:                sp1 = sp2;
        !           822:                loffs = offs + lastsize;
        !           823: #endif
        !           824:        }
        !           825: #if INTEL
        !           826:        /* Reverse member list */
        !           827:        sp2 = sp1;
        !           828:        sp1 = NULL;
        !           829:        while (sp2 != NULL) {
        !           830:                struct slist *tsp;
        !           831: 
        !           832:                tsp = sp2->sl_sp;
        !           833:                sp2->sl_sp = sp1;
        !           834:                sp1 = sp2;
        !           835:                sp2 = tsp;
        !           836:        }
        !           837:        /* Construct type list */
        !           838:        lp = bp = malloc(nmemb*3+1);
        !           839:        if (bp == NULL) dbmemory(__LINE__);
        !           840:        *bp++ = OTLIST;
        !           841:        sp2 = sp1;
        !           842:        for (i = 0; i < nmemb; i++) {
        !           843:                bp = setindex(bp, sp2->sl_type);
        !           844:                sp2 = sp2->sl_sp;
        !           845:        }
        !           846:        tlist = tlookup(lp, bp-lp);
        !           847:        free(lp);
        !           848:        /* Construct name list */
        !           849:        lp = bp = malloc(nname+1);
        !           850:        if (bp == NULL) dbmemory(__LINE__);
        !           851:        *bp++ = OTLIST;
        !           852:        sp2 = sp1;
        !           853:        for (i = 0; i < nmemb; i++) {
        !           854:                if (sp2==NULL) dbfatal(__LINE__);
        !           855:                bp = setname(bp, sp2->sl_id);
        !           856:                sp2 = sp2->sl_sp;
        !           857:                free(sp1);
        !           858:                sp1 = sp2;
        !           859:        }
        !           860:        nlist = tlookup(lp, bp-lp);
        !           861:        free(lp);
        !           862:        /* Construct the true type record */
        !           863:        bp = &bb[0];
        !           864:        *bp++ = OTSTRUC;                        /* STRUCT */
        !           865:        bp = setsize(bp, ((long)s)*NBPBYTE);    /* length */
        !           866:        bp = setnumb(bp, (long)nmemb);          /* count */
        !           867:        bp = setindex(bp, tlist);               /* @tlist */
        !           868:        bp = setindex(bp, nlist);               /* @nlist */
        !           869:        bp = setname(bp, (ttype)?gettype(ttype)->t_info:"");    /* name */
        !           870:        return (tlookup(bb, bp-bb));
        !           871: #else
        !           872:        return (1);
        !           873: #endif
        !           874: }
        !           875: 
        !           876: /*
        !           877:  * Map a bitfield type.
        !           878:  * Should only have CHAR, UCHAR, sort of type.
        !           879:  */
        !           880: dbfmap(bw, bt)
        !           881: int bw;                /* Bit width */
        !           882: int bt;                /* Base type */
        !           883: {
        !           884: #if INTEL
        !           885:        /* SCALAR length type */
        !           886:        char bb[4];
        !           887:        bb[0] = OTSCAL;
        !           888:        bb[1] = bw;
        !           889:        switch (bt) {
        !           890:        case DT_CHAR:   case DT_SHORT:  case DT_INT:    case DT_LONG:
        !           891:                bb[2] = OTSINT;
        !           892:                break;
        !           893:        case DT_UCHAR:  case DT_USHORT: case DT_UINT:   case DT_ULONG:
        !           894:                bb[2] = OTUINT;
        !           895:                break;
        !           896:        default:
        !           897:                dbfatal(__LINE__);
        !           898:        }
        !           899:        return (tlookup(bb, 3));
        !           900: #else
        !           901:        return (1);
        !           902: #endif
        !           903: }
        !           904: 
        !           905: dbxunion(s, ttype)
        !           906: unsigned       s;                      /* Size of union in bytes */
        !           907: {
        !           908:        int     nmemb;
        !           909:        int     i;
        !           910: #if INTEL
        !           911:        char    *lp;
        !           912:        register char *bp;
        !           913:        int namelen;
        !           914: #endif
        !           915:        /* Union member list */
        !           916:        nmemb = iget();                 /* Number of members in union */
        !           917: #if INTEL
        !           918:        /* STRUCT length 0 NIL NIL name UNPACKED count NIL NIL
        !           919:                1 @tlist1 @nlist1 ... 1 @tlistn @nlistn */
        !           920:        namelen = (ttype) ? strlen(gettype(ttype)->t_info) : 0;
        !           921:        lp = bp = malloc(17+7*nmemb+namelen);
        !           922:        if (bp == NULL) dbmemory(__LINE__);
        !           923:        *bp++ = OTSTRUC;                /* STRUCT */
        !           924:        bp = setsize(bp, ((long)s)*NBPBYTE);    /* length */
        !           925:        *bp++ = 0;                      /* Invariant records */
        !           926:        *bp++ = OTNIL;                  /* Invariant type list */
        !           927:        *bp++ = OTNIL;                  /* Invariant name list */
        !           928:        bp = setname(bp, (ttype)?gettype(ttype)->t_info:"");    /* name */
        !           929:        *bp++ = OTUPACK;                /* UNPACKED */
        !           930:        bp = setnumb(bp, (long)nmemb);  /* count */
        !           931:        *bp++ = OTNIL;                  /* Selector field type */
        !           932:        *bp++ = OTNIL;                  /* Selector field name */
        !           933: #endif
        !           934:        i = 1;
        !           935:        while (--nmemb >= 0) {
        !           936:                int     type;
        !           937: #if INTEL
        !           938:                int     tlist;
        !           939:                int     nlist;
        !           940:                char    bb[50];
        !           941:                register char *tbp;
        !           942: #endif
        !           943: 
        !           944:                if (bget() != DC_MOU) dbfatal(__LINE__);
        !           945:                iget();         /* forget line */
        !           946:                bget();         /* forget bit width */
        !           947:                bget();         /* forget bit offset */
        !           948:                iget();         /* forget byte offset */
        !           949:                sget(id, NCSYMB);
        !           950: #if INTEL
        !           951:                /* Make name list item */
        !           952:                tbp = bb;
        !           953:                *tbp++ = OTLIST;
        !           954:                tbp = setname(tbp, id);
        !           955:                nlist = tlookup(bb, tbp-bb);
        !           956: #endif
        !           957:                type = dbtmap(0);
        !           958: #if INTEL
        !           959:                /* Make type list item */
        !           960:                tbp = bb;
        !           961:                *tbp++ = OTLIST;
        !           962:                tbp = setindex(tbp, type);
        !           963:                tlist = tlookup(bb, tbp-bb);
        !           964:                /* Append member items to typdef */
        !           965:                *bp++ = 1;
        !           966:                bp = setindex(bp, tlist);
        !           967:                bp = setindex(bp, nlist);
        !           968: #endif
        !           969:        }
        !           970: #if INTEL
        !           971:        lastsize = ((long)s) * NBPBYTE;
        !           972:        i = tlookup(lp, bp-lp);
        !           973:        free(lp);
        !           974:        return (i);
        !           975: #else
        !           976:        return (1);
        !           977: #endif
        !           978: }
        !           979: 
        !           980: dbxenum(s, ttype)
        !           981: unsigned       s;                      /* Size of enum type in bytes */
        !           982: {
        !           983:        int     nmemb;
        !           984:        int     i;
        !           985:        int     valu;
        !           986:        int     nname;
        !           987: #if INTEL
        !           988:        int     minvalu;
        !           989:        int     maxvalu;
        !           990:        int     range;
        !           991:        int     nlist;
        !           992:        struct el {
        !           993:                struct el *el_ep;
        !           994:                int     el_valu;
        !           995:                char    el_id[];
        !           996:        };
        !           997:        struct el **epp;
        !           998:        register char *bp;
        !           999:        char *lp;
        !          1000:        char bb[16];
        !          1001: #endif
        !          1002:        /* Enum member list */
        !          1003:        nname = 0;
        !          1004:        nmemb = iget();         /* Number of members in enum */
        !          1005: #if INTEL
        !          1006:        /* SCALAR size type @list lbound ubound */
        !          1007:        /* LIST name1 ... namen */
        !          1008:        epp = (struct el **)malloc(nmemb * sizeof(*epp));
        !          1009:        if (epp == NULL) dbmemory(__LINE__);
        !          1010:        maxvalu = -MAXIV-1;
        !          1011:        minvalu = MAXIV;
        !          1012: #endif
        !          1013:        for (i = 0; i < nmemb; i++) {
        !          1014: #if INTEL
        !          1015:                int size;
        !          1016:                register struct el *ep;
        !          1017: #endif
        !          1018: 
        !          1019: 
        !          1020:                if (bget() != DC_MOE) dbfatal(__LINE__);
        !          1021:                iget();         /* forget line */
        !          1022:                valu = iget();  /* value */
        !          1023:                sget(id, NCSYMB);
        !          1024: #if INTEL
        !          1025:                size = strlen(id)+2;
        !          1026:                nname += size;
        !          1027: #endif
        !          1028:                dbtmap(0);
        !          1029: #if INTEL
        !          1030:                ep = malloc(sizeof(*ep)+size);
        !          1031:                if (ep == NULL) dbmemory(__LINE__);
        !          1032:                ep->el_valu = valu;
        !          1033:                strcpy(ep->el_id, id);
        !          1034:                if (valu < minvalu)
        !          1035:                        minvalu = valu;
        !          1036:                else if (valu > maxvalu)
        !          1037:                        maxvalu = valu;
        !          1038:                epp[i] = ep;
        !          1039: #endif
        !          1040:        }
        !          1041: #if INTEL
        !          1042:        /* Construct name list */
        !          1043:        range = maxvalu - minvalu + 1;
        !          1044:        if (range > nmemb)
        !          1045:                nname += (range-nmemb)*2;
        !          1046:        nname += range/8 + 3;
        !          1047:        lp = bp = malloc(nname);
        !          1048:        if (bp == NULL) dbmemory(__LINE__);
        !          1049:        *bp++ = OTLIST;
        !          1050:        for (valu = minvalu; valu <= maxvalu; valu++) {
        !          1051:                *bp++ = OTNAME;
        !          1052:                for (i = 0; i < nmemb; i++)
        !          1053:                        if (epp[i]->el_valu == valu)
        !          1054:                                break;
        !          1055:                if (i < nmemb) {
        !          1056:                        bp = setsymid(bp, epp[i]->el_id);
        !          1057:                        free(epp[i]);
        !          1058:                } else
        !          1059:                        *bp++ = 0;
        !          1060:                if (bp > lp + nname) cbotch("enum overrun");
        !          1061:        }
        !          1062:        free(epp);
        !          1063:        nlist = tlookup(lp, bp-lp);
        !          1064:        free(lp);
        !          1065:        /* Construct type record */
        !          1066:        bp = &bb[0];
        !          1067:        *bp++ = OTSCAL;
        !          1068:        bp = setsize(bp, ((long)s)*NBPBYTE);
        !          1069:        *bp++ = OTSINT;
        !          1070:        bp = setname(bp, (ttype)?gettype(ttype)->t_info:"");
        !          1071:        bp = setindex(bp, nlist);
        !          1072:        bp = setnumb(bp, (long)minvalu);
        !          1073:        bp = setnumb(bp, (long)maxvalu);
        !          1074:        return (tlookup(bb, bp-bb));
        !          1075: #else
        !          1076:        return (1);
        !          1077: #endif
        !          1078: }
        !          1079: 
        !          1080: /*
        !          1081:  * Construct list of arg types and return its type.
        !          1082:  * The function's type with zero args has already been computed.
        !          1083:  * Expand the type and append nargs and arglist type.
        !          1084:  */
        !          1085: arglisttype()
        !          1086: {
        !          1087: #if INTEL
        !          1088:        /* LIST @param1 ... @paramn */
        !          1089:        /* PARAM @type1 */
        !          1090:        /* ... */
        !          1091:        /* PARAM @typen */
        !          1092:        int type;
        !          1093:        int oldtypesize;
        !          1094:        char *oldtype;
        !          1095:        register char *bp;
        !          1096:        register int i;
        !          1097:        register char *sbp;
        !          1098:        char b[3*NARGS+3];
        !          1099:        register TINFO *tp;
        !          1100:        char b2[16];
        !          1101: 
        !          1102:        if (curfna == 0)
        !          1103:                return;
        !          1104:        /* Compute argument list type */
        !          1105:        bp = &b[0];
        !          1106:        *bp++ = OTLIST;
        !          1107:        for (i=0; i<curfna; ++i) {
        !          1108:                *bp++ = OTINDEX;
        !          1109:                sbp = bp;
        !          1110:                *bp++ = OTPARA;
        !          1111:                bp = setindex(bp, curfar[i]);
        !          1112:                bp = setindex(sbp-1, tlookup(sbp, bp-sbp));
        !          1113:        }
        !          1114:        type = tlookup(b, bp-b);
        !          1115: 
        !          1116:        /* Find old type */
        !          1117:        tp = gettype(curfsp->s_type);
        !          1118:        oldtype = tp->t_info;
        !          1119:        oldtypesize = tp->t_length;
        !          1120: 
        !          1121:        /* Expand and compute new type */
        !          1122:        bp = b2;
        !          1123:        while (--oldtypesize > 0)       /* Last byte should be zero */
        !          1124:                *bp++ = *oldtype++;
        !          1125:        bp = setnumb(bp, (long)curfna); /* Number of args */
        !          1126:        bp = setindex(bp, type);        /* Arg types */
        !          1127:        curfsp->s_type = tlookup(b2, bp-b2);
        !          1128: #else
        !          1129:        return;
        !          1130: #endif
        !          1131: }
        !          1132: 
        !          1133: /*
        !          1134:  * Output a debug line record.
        !          1135:  */
        !          1136: outdlin(op)
        !          1137: {
        !          1138:        bput(TDLAB);
        !          1139:        bput(DC_LINE);
        !          1140:        iput(line);
        !          1141:        bput(op);
        !          1142:        bput(0);
        !          1143:        bput(1);        /* Nil type */
        !          1144: }
        !          1145: 
        !          1146: /*
        !          1147:  * Output a debug relocation record.
        !          1148:  * This 'n' is an index into the list of debug records written.
        !          1149:  */
        !          1150: outdloc(n)
        !          1151: {
        !          1152:        bput(TDLOC);
        !          1153:        iput(n);
        !          1154: }
        !          1155: 
        !          1156: /*
        !          1157:  * Finish up.
        !          1158:  * Figure out the sizes and final values of everything.
        !          1159:  * Write the output file.
        !          1160:  */
        !          1161: copycode()
        !          1162: {
        !          1163:        register SYM *sp;
        !          1164:        register i;
        !          1165: 
        !          1166:        /*
        !          1167:         * Assign base addresses to the compiler's logical segments
        !          1168:         * based on the settings of the VROM and VRAM flags.
        !          1169:         */
        !          1170:        seg_size = 0;
        !          1171:        bss_size = seg[SBSS].s_dot;
        !          1172:        lseg(SCODE);
        !          1173:        lseg(SLINK);
        !          1174:        if (isvariant(VSMALL) || isvariant(VRAM))
        !          1175:                seg_size = 0;
        !          1176:        lseg(SPURE);
        !          1177:        if (notvariant(VSMALL) && notvariant(VROM) && notvariant(VRAM))
        !          1178:                seg_size = 0;
        !          1179:        lseg(SSTRN);
        !          1180:        if (notvariant(VSMALL) && isvariant(VROM))
        !          1181:                seg_size = 0;
        !          1182:        lseg(SDATA);
        !          1183:        lseg(SBSS);
        !          1184: 
        !          1185:        /*
        !          1186:         * Adjust symbol base addresses to make them LSEG relative
        !          1187:         * instead of compiler segment relative.
        !          1188:         */
        !          1189:        for (i=0; i<NSHASH; ++i) {
        !          1190:                sp = hash2[i];
        !          1191:                while (sp != NULL) {
        !          1192:                        if ((sp->s_flag&S_DEF) != 0)
        !          1193:                                sp->s_value += seg[sp->s_seg].s_mseek;
        !          1194:                        sp = sp->s_fp;
        !          1195:                }
        !          1196:        }
        !          1197: 
        !          1198:        /*
        !          1199:         * Write the object file.
        !          1200:         * Information in header and SEGDEF section is fixed ex post facto.
        !          1201:         */
        !          1202:        putbyte(0xA0);                  /* file type = linkable module */
        !          1203:        checksum = 0;                   /* file type byte not in checksum */
        !          1204:        writeheader();                  /* file header */
        !          1205:        writesegdef();                  /* SEGDEF section */
        !          1206:        writetypdef();                  /* TYPDEF section */
        !          1207:        writesymdef(PUBSEC);            /* PUBDEF section */
        !          1208:        writesymdef(EXTSEC);            /* EXTDEF section */
        !          1209:        writetxtfix();                  /* TXTFIX section */
        !          1210:        fixoutput();                    /* fix output file */
        !          1211:        putbyte(-checksum);             /* and write checksum */
        !          1212: #if VAXFMT
        !          1213:        vaxflush();
        !          1214: #endif
        !          1215: }
        !          1216: 
        !          1217: /*
        !          1218:  * Write linkable module header and table of contents.
        !          1219:  * Some of this gets fixed up after writing the object.
        !          1220:  */
        !          1221: writeheader()
        !          1222: {
        !          1223:        register int n;
        !          1224:        mhdseek = oflength;             /* save header location */
        !          1225:        putrept (0, 13);                /* 13 bytes of 0, fixed later */
        !          1226:        putdate();                      /* date and time */
        !          1227:        n = strlen(module);
        !          1228:        putbyte(n);
        !          1229:        putupper(module, n);            /* module name */
        !          1230:        putrept(' ', 40 - n);           /* padded with spaces */
        !          1231:        putcreator();                   /* module creator */
        !          1232:        tocseek = oflength;             /* save toc location */
        !          1233:        putrept(0, 64);                 /* table of contents, fixed later */
        !          1234: }
        !          1235: 
        !          1236: /*
        !          1237:  * Write SEGDEF section.
        !          1238:  */
        !          1239: writesegdef()
        !          1240: {
        !          1241:        char b[NMNAME+5];
        !          1242:        secloc[SEGSEC] = oflength;
        !          1243:        if (isvariant(VSMALL)) {
        !          1244:                segseek[CODESEG] = putsegdef(0, "CODE");
        !          1245:                segseek[DATASEG] = putsegdef(0, "DATA");
        !          1246:                putsegdef(SEGDPL|SEGARW|SEGSTK|SEGEXT, "DATA");
        !          1247:        }
        !          1248:        else {
        !          1249:                strcpy(b, module);
        !          1250:                strcat(b, "_CODE");
        !          1251:                segseek[CODESEG] = putsegdef(0, b);
        !          1252:                strcpy(b, module);
        !          1253:                strcat(b, "_DATA");
        !          1254:                segseek[DATASEG] = putsegdef(0, b);
        !          1255:                putsegdef(SEGDPL|SEGARW|SEGSTK|SEGEXT, "STACK");
        !          1256:        }
        !          1257:        if (isvariant(VDEBUG)) {
        !          1258:                segseek[MODSEG] = putsegdef(0, "MODULES:");
        !          1259:                segseek[SYMSEG] = putsegdef(0, "SYMBOLS:");
        !          1260:                segseek[LINESEG] = putsegdef(0, "LINES:");
        !          1261:        }
        !          1262:        endsec(SEGSEC);
        !          1263: }
        !          1264: 
        !          1265: /*
        !          1266:  * Write TYPDEF section.
        !          1267:  */
        !          1268: writetypdef()
        !          1269: {
        !          1270:        register TINFO *tp;
        !          1271:        register int length;
        !          1272:        register TINFO *ttp;
        !          1273:        secloc[TYPSEC] = oflength;
        !          1274:        fixpatch();
        !          1275:        tp = typelistp;
        !          1276:        while (tp != NULL) {
        !          1277:                putbyte(0xFF);          /* linkage = TRUE */
        !          1278:                if (tp->t_tflag) {
        !          1279:                        length = 1;
        !          1280:                        tp->t_info[0] = OTNIL;
        !          1281:                }
        !          1282:                else
        !          1283:                        length = tp->t_length;
        !          1284:                putword(length);        /* length */
        !          1285:                putblock(tp->t_info, length);   /* type string */
        !          1286:                ttp = tp;
        !          1287:                tp = tp->t_tp;
        !          1288:                free(ttp);
        !          1289:        }
        !          1290:        endsec(TYPSEC);
        !          1291: }
        !          1292: 
        !          1293: /*
        !          1294:  * Write PUBDEF or EXTDEF section.
        !          1295:  */
        !          1296: writesymdef(n)
        !          1297: int n;
        !          1298: {
        !          1299:        register int isdefined;
        !          1300:        register SYM *sp;
        !          1301:        int flag, i, type, ispubsec;
        !          1302:        secloc[n] = oflength;
        !          1303:        ispubsec = (n == PUBSEC);
        !          1304:        for (i=0; i<NSHASH; i++) {
        !          1305:                sp = hash2[i];
        !          1306:                while (sp != NULL) {
        !          1307:                        flag = sp->s_flag;
        !          1308:                        isdefined = ((flag&S_DEF)!=0);
        !          1309:                        if ((flag&S_GBL)!=0 || !isdefined) {
        !          1310:                                type = sp->s_type;
        !          1311:                                if (type == 0)
        !          1312:                                        ++type;
        !          1313:                                if (isdefined && ispubsec) {
        !          1314:                                        /* Public symbol. */
        !          1315:                                        putword(sp->s_value);
        !          1316:                                        putword(segindex(sp->s_seg));
        !          1317:                                        putword(type);
        !          1318:                                        putbyte(0);     /* wordcount */
        !          1319:                                        putname(sp->s_id);
        !          1320:                                        sp->s_ref = 0;
        !          1321:                                        ++npubs;
        !          1322:                                }
        !          1323:                                else if (!isdefined && !ispubsec) {
        !          1324:                                        /* External symbol. */
        !          1325:                                        putword(0);     /* segment unknown */
        !          1326:                                        putword(type);
        !          1327:                                        putbyte(0);
        !          1328:                                        putname(sp->s_id);
        !          1329:                                        sp->s_ref = ++nexts;
        !          1330:                                }
        !          1331:                        }
        !          1332:                        sp = sp->s_fp;
        !          1333:                }
        !          1334:        }
        !          1335:        endsec(n);
        !          1336: }
        !          1337: 
        !          1338: /*
        !          1339:  * Write TXTFIX section.
        !          1340:  */
        !          1341: writetxtfix()
        !          1342: {
        !          1343:        register int op, data, nd, i;
        !          1344:        register char *cp;
        !          1345:        register SYM *sp;
        !          1346: 
        !          1347:        secloc[TXTSEC] = oflength;
        !          1348:        if (isvariant(VDEBUG)) {
        !          1349:                need(SYMSEG, 5+strlen(module)+1);
        !          1350:                lenseek = oflength+10;          /* length fixed later */
        !          1351:                *txtp++ = SYMBBEG;              /* block begin */
        !          1352:                fixsym(FORMOFF, CODESEG, 0);    /* offset fixup */
        !          1353:                text2(0);                       /* offset */
        !          1354:                text2(0);                       /* length */
        !          1355:                txtp = setsymid(txtp, module);  /* name */
        !          1356:        }
        !          1357:        dotseg = SCODE;
        !          1358:        dot = seg[SCODE].s_dot;
        !          1359:        while ((op=bget()) != TEND) {
        !          1360:                switch(op) {
        !          1361:                case TENTER:
        !          1362:                        flush();
        !          1363:                        dotseg = bget();
        !          1364:                        dot = seg[dotseg].s_dot;
        !          1365:                        continue;
        !          1366:                case TDLAB:
        !          1367:                        getdlab();
        !          1368:                        continue;
        !          1369:                case TDLOC:
        !          1370:                        getdloc();
        !          1371:                        continue;
        !          1372: #if    0
        !          1373: /* See comment on outcb()/outdb() above. */
        !          1374:                case TCODE:
        !          1375:                case TDATA:
        !          1376:                        if (isvariant(VSMALL))
        !          1377:                                cbotch("code:data");
        !          1378:                        need(segindex(dotseg), 2);
        !          1379:                        text2(0);
        !          1380:                        fixdot(FORMSEL, SEGIN | ((op == TCODE) ? CODESEG : DATASEG), 0);
        !          1381:                        dot += 2;
        !          1382:                        continue;
        !          1383: #endif
        !          1384:                case TBASE:
        !          1385:                        if (isvariant(VSMALL))
        !          1386:                                cbotch("base");
        !          1387:                        sp = pget();
        !          1388:                        need(segindex(dotseg), 2);
        !          1389:                        text2(0);
        !          1390:                        fixdot(FORMSEL, ((sp->s_flag&S_DEF)!=0) ? segindex(sp->s_seg) : EXTIN|(sp->s_ref), 0);
        !          1391:                        dot += 2;
        !          1392:                        continue;
        !          1393:                }
        !          1394:                if ((op&TTYPE) == TBYTE) {
        !          1395:                        nd = 1;
        !          1396:                        data = bget();
        !          1397:                } else {
        !          1398:                        nd = 2;
        !          1399:                        data = iget();
        !          1400:                }
        !          1401:                need(segindex(dotseg), nd);
        !          1402:                /*
        !          1403:                 * Absolute.
        !          1404:                 */
        !          1405:                if ((op&(TSYM|TPCR)) == 0) {
        !          1406:                        text(data, nd);
        !          1407:                        dot += nd;
        !          1408:                        continue;
        !          1409:                }
        !          1410:                /*
        !          1411:                 * Absolute PC rel.
        !          1412:                 */
        !          1413:                if ((op&TSYM) == 0) {
        !          1414:                        text(dot+data, nd);
        !          1415:                        fixdot(FORMOFF, txtseg, dot+data);
        !          1416:                        dot += nd;
        !          1417:                        continue;
        !          1418:                }
        !          1419:                /*
        !          1420:                 * Symbol based.
        !          1421:                 */
        !          1422:                sp = pget();
        !          1423:                if ((sp->s_flag&S_DEF) != 0) {
        !          1424:                        data += sp->s_value;
        !          1425:                        /* Absolute */
        !          1426:                        if ((op&TPCR)!=0 && sp->s_seg==dotseg) {
        !          1427:                                text(data-(dot+nd), nd);
        !          1428:                                dot += nd;
        !          1429:                                continue;
        !          1430:                        }
        !          1431:                        /* Segment relative */
        !          1432:                        text(data, nd);
        !          1433:                        fixdot((op&TPCR)?FORMSRO:FORMOFF, segindex(sp->s_seg), data);
        !          1434:                        dot += nd;
        !          1435:                        continue;
        !          1436:                }
        !          1437:                /*
        !          1438:                 * Symbol relative.
        !          1439:                 */
        !          1440:                text(data, nd);
        !          1441:                fixdot((op&TPCR)?FORMSRO:FORMOFF, EXTIN|(sp->s_ref), data);
        !          1442:                dot += nd;
        !          1443:        }
        !          1444: 
        !          1445:        /*
        !          1446:         * Write SYMBOLS: and MODULES: text and fixups if DEBUG.
        !          1447:         */
        !          1448:        if (isvariant(VDEBUG)) {
        !          1449:                dbdump();                       /* dump debug symbols */
        !          1450:                putbend();                      /* block end */
        !          1451:                need(MODSEG, 33+1+strlen(module));
        !          1452:                for (i=1; i<=26; i++)
        !          1453:                        *txtp++ = 0;
        !          1454:                text2(1);                       /* first line number = 1 */
        !          1455:                *txtp++ = TID;                  /* translator ID */
        !          1456: #if INTEL
        !          1457:                cp = VERSINT;
        !          1458: #else
        !          1459:                cp = VERSMWC;
        !          1460: #endif
        !          1461:                for (i=1; i<=4; i++)
        !          1462:                        *txtp++ = *cp++;        /* version */
        !          1463:                txtp = setsymid(txtp, module);
        !          1464:                fixup(FORMFVA, MODSEG, 0x02, CODESEG|SEGIN, 0);
        !          1465:                fixup(FORMFVA, MODSEG, 0x0A, SYMSEG|SEGIN, 0);
        !          1466:                fixup(FORMFVA, MODSEG, 0x0E, LINESEG|SEGIN, 0);
        !          1467:        }
        !          1468:        flush();
        !          1469: 
        !          1470:        /*
        !          1471:         * Write an ITEXT block to initialize BSS if nonempty.
        !          1472:         */
        !          1473:        if (bss_size != 0) {
        !          1474:                putbyte(BITEXT);                /* iterated text block */
        !          1475:                putword(seg[SBSS].s_mseek);     /* offset */
        !          1476:                putword(segindex(SDATA));       /* segment */
        !          1477:                putword(bss_size);              /* iteration count */
        !          1478:                putword(1);                     /* template length */
        !          1479:                putbyte(0);                     /* template */
        !          1480:        }
        !          1481:        endsec(TXTSEC);
        !          1482: }
        !          1483: 
        !          1484: /*
        !          1485:  * Fix the output file.
        !          1486:  */
        !          1487: fixoutput()
        !          1488: {
        !          1489:        register int i;
        !          1490:        long len;
        !          1491: 
        !          1492: #ifdef vax
        !          1493:        /* On the VAX, copy the temp file to the output file. */
        !          1494:        /* This is because of problems with seeking in the output file. */
        !          1495: #if VAXFMT
        !          1496:        vaxflush();
        !          1497: #endif
        !          1498:        setin();
        !          1499:        outopen(1);
        !          1500:        trace("repacking");
        !          1501: #endif
        !          1502: 
        !          1503:        /* Fix the module header. */
        !          1504:        len = oflength;                 /* save module length */
        !          1505:        fakeseek(mhdseek, 12);          /* seek to module header */
        !          1506:        putlong(len);                   /* fix total module length */
        !          1507:        putword(nsegs);                 /* fix SEGDEFs */
        !          1508:        putword(0);                     /* GATDEFs */ 
        !          1509:        putword(npubs);                 /* fix PUBDEFs */
        !          1510:        putword(nexts);                 /* fix EXTDEFs */
        !          1511:        /* Fix the table of contents. */
        !          1512:        fakeseek(tocseek, 8*NSECS);     /* seek to table of contents */
        !          1513:        for (i=0; i<NSECS; i++) {
        !          1514:                if (secloc[i] != 0L)
        !          1515:                        --secloc[i];    /* location without file type byte */
        !          1516:                putlong(secloc[i]);     /* fix location */
        !          1517:                putlong(seclen[i]);     /* fix length */
        !          1518:        }
        !          1519:        /* Fix the SEGDEF section. */
        !          1520:        seglen[DATASEG] += bss_size;    /* DATA includes text and BSS */
        !          1521:        fixsegdef(SEGDPL|SEGAXR|SEGCOM, CODESEG);
        !          1522:        fixsegdef(SEGDPL|SEGARW|SEGCOM, DATASEG);
        !          1523:        if (isvariant(VDEBUG)) {
        !          1524:                fixsegdef(SEGDPL|SEGARO|SEGDEB, MODSEG);
        !          1525:                fixsegdef(SEGDPL|SEGARO|SEGDEB, SYMSEG);
        !          1526:                fixsegdef(SEGDPL|SEGARO|SEGDEB, LINESEG);
        !          1527:                /* Fix the SYMSEG text. */
        !          1528:                fakeseek(lenseek, 2);
        !          1529:                putword(seglen[CODESEG]);
        !          1530:        }
        !          1531:        /* Seek to end. */
        !          1532:        fakeseek(len, 0);
        !          1533: }
        !          1534: 
        !          1535: /*
        !          1536:  * Seek to 'where' and disregard next 'ignore' bytes.
        !          1537:  * Should just be lseek(), but complicated for VAX.
        !          1538:  */
        !          1539: fakeseek(where, ignore)
        !          1540: long where;
        !          1541: int ignore;
        !          1542: {
        !          1543: #ifdef vax
        !          1544:        register int i;
        !          1545:        static long pos = 0L;
        !          1546: 
        !          1547:        for (; pos < where; pos++)
        !          1548:                putbyte(bget());        /* copy bytes */
        !          1549:        for (i=0; i<ignore; i++)
        !          1550:                bget();                 /* skip old bytes */
        !          1551:        pos += (long) ignore;           /* and update position */
        !          1552:        if (where == mhdseek)
        !          1553:                checksum = 0;           /* reset checksum */
        !          1554: #else
        !          1555:        if (fseek(ofp, where, 0) != 0)  /* seek to location */
        !          1556:                cfatal("seek error");
        !          1557: #endif
        !          1558: }
        !          1559: 
        !          1560: /*
        !          1561:  * Fix the attribute and length words of a segment definition.
        !          1562:  */
        !          1563: fixsegdef(attrib, seginx)
        !          1564: int attrib, seginx;
        !          1565: {
        !          1566:        register ADDRESS size;
        !          1567: 
        !          1568:        size = seglen[seginx];
        !          1569:        if (size == 0)
        !          1570:                attrib |= SEGEXT;       /* external if empty */
        !          1571:        else
        !          1572:                --size;                 /* length-1 gives length */
        !          1573:        fakeseek(segseek[seginx], 4);   /* seek to attribute byte */    
        !          1574:        putword(attrib);                /* attributes */
        !          1575:        putword(size);                  /* length */
        !          1576: }
        !          1577: 
        !          1578: /*
        !          1579:  * Write LINES text for line number.
        !          1580:  * 'lastline' is the last line for which LINES text was written.
        !          1581:  * Watch for the case where 'line' is much larger than 'lastline'.
        !          1582:  */
        !          1583: putline(dp)
        !          1584: struct dbgt *dp;
        !          1585: {
        !          1586:        register int i, value, line;
        !          1587:        line = dp->d_line;
        !          1588:        value = dp->d_value;
        !          1589:        while (line > lastline) {               /* need to write LINES text */
        !          1590:                i = 2 * (line - lastline);      /* bytes of LINES text needed */
        !          1591:                if (i > NTXT)
        !          1592:                        i = NTXT;               /* cannot buffer more than NTXT */
        !          1593:                need(LINESEG, i);
        !          1594:                while (i > 0) {
        !          1595:                        text2(value);
        !          1596:                        i -= 2;
        !          1597:                        lastline++;
        !          1598:                }
        !          1599:        }
        !          1600: }
        !          1601: 
        !          1602: /*
        !          1603:  * Write SYMBOLS text for a block or procedure begin.
        !          1604:  */
        !          1605: putbbeg(dp)
        !          1606: register struct dbgt *dp;
        !          1607: {
        !          1608:        if (dp->d_id[0] != '{') {               /* procedure block */
        !          1609:                need(SYMSEG, 10+1+strlen(dp->d_id));
        !          1610:                *txtp++ = SYMPBEG;              /* procedure begin */
        !          1611:                fixsym(FORMOFF, CODESEG, dp->d_value);  /* offset fixup */
        !          1612:                text2(dp->d_value);             /* offset */
        !          1613:                text2(dp->d_type);              /* type */
        !          1614:                *txtp++ = (isvariant(VSMALL)?0:1);      /* near or far */
        !          1615:                text2(6);                       /* r. a. offset */
        !          1616:                text2(blklength(dp,1));         /* length */
        !          1617:                txtp = setsymid(txtp, dp->d_id);        /* name */
        !          1618:        }
        !          1619:        else {                                  /* non-procedure block */
        !          1620: #ifdef NOABLOCKS
        !          1621:                blkcount++;
        !          1622: #else
        !          1623:                need(SYMSEG, 6);
        !          1624:                *txtp++ = SYMBBEG;              /* block begin */
        !          1625:                fixsym(FORMOFF, CODESEG, dp->d_value);  /* offset fixup */
        !          1626:                text2(dp->d_value);             /* offset */
        !          1627:                text2(blklength(dp, 0));        /* length */
        !          1628:                *txtp++ = 0;                    /* name */
        !          1629: #endif
        !          1630:        }
        !          1631: }
        !          1632: 
        !          1633: /*
        !          1634:  * Return the blocklength of block dp.
        !          1635:  * Add the epilog size if epiflag.
        !          1636:  */
        !          1637: blklength(dp, epiflag)
        !          1638: register struct dbgt *dp;
        !          1639: int epiflag;
        !          1640: {
        !          1641:        register int level;
        !          1642:        register ADDRESS length;
        !          1643:        register int episize;
        !          1644: 
        !          1645:        /* Set episize to epilog length (8086: without autos) if epiflag. */
        !          1646:        episize = (epiflag) ? 4 : 0;
        !          1647:        level = dp->d_level + 1;
        !          1648:        length = dp->d_value;
        !          1649:        while ((dp = dp->d_dp) != NULL) {
        !          1650:                if (epiflag && dp->d_class == DC_AUTO && notvariant(V80186))
        !          1651:                        episize = 6;    /* epilog length with autos, 8086 */
        !          1652:                else if (dp->d_class == DC_LINE
        !          1653:                 && dp->d_id[0] == '}'
        !          1654:                 && dp->d_level == level)
        !          1655:                        return ((int) (dp->d_value - length + episize));
        !          1656:        }
        !          1657:        cbotch("missing blkend");
        !          1658: }
        !          1659: 
        !          1660: /*
        !          1661:  * Write SYMBOLS text for block end.
        !          1662:  */
        !          1663: putbend()
        !          1664: {
        !          1665: #ifdef NOABLOCKS
        !          1666:        if (blkcount > 0) {
        !          1667:                blkcount--;
        !          1668:                return;
        !          1669:        }
        !          1670: #endif
        !          1671:        need(SYMSEG, 1);
        !          1672:        *txtp++ = SYMBEND;
        !          1673:        if (symbase == -1)
        !          1674:                symbase = 0;
        !          1675: }
        !          1676: 
        !          1677: /*
        !          1678:  * Write SYMBOLS text for debug symbol.
        !          1679:  */
        !          1680: putsym(dp)
        !          1681: register struct dbgt *dp;
        !          1682: {
        !          1683:        register char *cp;
        !          1684:        register int n;
        !          1685:        int class = dp->d_class;
        !          1686:        if ((class == DC_AUTO) || (class == DC_PAUTO)) {
        !          1687:                /* BP-relative symbol */
        !          1688:                if (symbase != -1) {
        !          1689:                        need(SYMSEG, 1);
        !          1690:                        *txtp++ = SYMBPRB;      /* BP-relative base */
        !          1691:                        symbase = -1;
        !          1692:                }
        !          1693:        }
        !          1694:        else if (segindex(dp->d_seg) != symbase) {
        !          1695:                /* Need to change symbol segments */
        !          1696:                symbase = segindex(dp->d_seg);
        !          1697:                need(SYMSEG, 5);
        !          1698:                *txtp++ = SYMBASE;              /* base */
        !          1699:                fixsym(FORMFVA, symbase, 0);    /* full virt addr fixup */
        !          1700:                text2(0);                       /* offset */
        !          1701:                text2(symbase);                 /* segment */
        !          1702:        }
        !          1703:        cp = dp->d_id;
        !          1704:        n = strlen(cp);
        !          1705:        need(SYMSEG, 5+1+n);
        !          1706:        *txtp++ = SYMSYMB;
        !          1707:        text2(dp->d_value);                     /* offset */
        !          1708:        text2(dp->d_type);                      /* type */
        !          1709:        txtp = setsymid(txtp, cp);              /* name */
        !          1710: }
        !          1711: 
        !          1712: /*
        !          1713:  * Put out a byte, updating checksum.
        !          1714:  */
        !          1715: putbyte(b)
        !          1716: register b;
        !          1717: {
        !          1718:        ++oflength;
        !          1719:        checksum += b;
        !          1720: #if    VAXFMT
        !          1721: #if    TEMPBUF
        !          1722:        if (ofp == NULL) {
        !          1723:                bput(b);
        !          1724:                return;
        !          1725:        }
        !          1726: #endif
        !          1727:        if (vaxptr >= &vaxbuf[NVDATA])
        !          1728:                vaxflush();
        !          1729:        *vaxptr++ = b;
        !          1730: #else
        !          1731:        bput(b);
        !          1732: #endif
        !          1733: }
        !          1734: 
        !          1735: /*
        !          1736:  * Put out a word.
        !          1737:  */
        !          1738: putword(n)
        !          1739: register int n;
        !          1740: {
        !          1741:        putbyte(n);
        !          1742:        putbyte(n>>8);
        !          1743: }
        !          1744: 
        !          1745: /*
        !          1746:  * Put out a long.
        !          1747:  */
        !          1748: putlong(n)
        !          1749: long n;
        !          1750: {
        !          1751:        putword((int)n);
        !          1752:        putword((int)(n>>16));
        !          1753: }
        !          1754: 
        !          1755: /*
        !          1756:  * Put out a block of n bytes from cp.
        !          1757:  */
        !          1758: putblock(cp, n)
        !          1759: register unsigned char *cp;
        !          1760: register int n;
        !          1761: {
        !          1762:        while (n--)
        !          1763:                putbyte(*cp++);
        !          1764: }
        !          1765: 
        !          1766: /*
        !          1767:  * Put out a block of n bytes from cp,
        !          1768:  * mapping lower case to upper case.
        !          1769:  */
        !          1770: putupper(cp, n)
        !          1771: register char *cp;
        !          1772: register int n;
        !          1773: {
        !          1774:        while (n--)
        !          1775:                putbyte(uppercase(*cp++));
        !          1776: }
        !          1777: 
        !          1778: /*
        !          1779:  * Put out n bytes of character c.
        !          1780:  */
        !          1781: putrept(c, n)
        !          1782: register int c;
        !          1783: register int n;
        !          1784: {
        !          1785:        while (n--)
        !          1786:                putbyte(c);
        !          1787: }
        !          1788: 
        !          1789: /*
        !          1790:  * Put out a PL/M-format name.
        !          1791:  * Warn and truncate if the name is longer than 39 characters.
        !          1792:  */
        !          1793: putname(cp)
        !          1794: register char *cp;
        !          1795: {
        !          1796:        register int len;
        !          1797:        if ((len = strlen(cp)) > 39) {
        !          1798:                cwarn("symbol \"%s\" truncated to 39 characters", cp);
        !          1799:                len = 39;
        !          1800:        }
        !          1801:        putbyte(len);
        !          1802:        putupper(cp, len);
        !          1803: }
        !          1804: 
        !          1805: /*
        !          1806:  * Put out date and time.
        !          1807:  */
        !          1808: putdate()
        !          1809: {
        !          1810: #ifdef UDI
        !          1811:        extern struct gt udigtime;
        !          1812:        putblock(udigtime.gt_date, 8);
        !          1813:        putblock(udigtime.gt_time, 8);
        !          1814: #else                                  /* COHERENT or VAX */
        !          1815: #ifdef COHERENT
        !          1816:        time_t now;
        !          1817: #else                                  /* VAX */
        !          1818:        struct tm *localtime();
        !          1819:        long time();
        !          1820:        long now;
        !          1821: #endif
        !          1822:        char b[17];
        !          1823:        register struct tm *tmp;
        !          1824:        time(&now);
        !          1825:        tmp = localtime(&now);
        !          1826:        sprintf (b, "%02d/%02d/%02d%02d:%02d:%02d",
        !          1827:                tmp->tm_mon+1,
        !          1828:                tmp->tm_mday,
        !          1829:                tmp->tm_year,
        !          1830:                tmp->tm_hour,
        !          1831:                tmp->tm_min,
        !          1832:                tmp->tm_sec);
        !          1833:        putblock(b, 16);
        !          1834: #endif
        !          1835: }
        !          1836: 
        !          1837: /*
        !          1838:  * Put out module creator.
        !          1839:  */
        !          1840: putcreator()
        !          1841: {
        !          1842:        register int n;
        !          1843:        char b[40];
        !          1844: #ifdef UDI
        !          1845:        extern char udisysid[];
        !          1846:        cstr(b, &udisysid[0]);
        !          1847: #endif
        !          1848: #ifdef COHERENT
        !          1849:        strcpy(b, "COHERENT");
        !          1850: #endif
        !          1851: #ifdef vax
        !          1852:        strcpy(b, "VAX");
        !          1853: #endif
        !          1854: #if INTEL
        !          1855:        strcat (b, " iC286 ");
        !          1856:        strcat (b, VERSINT);
        !          1857: #else
        !          1858:        strcat (b, " MWC286 ");
        !          1859:        strcat (b, VERSMWC);
        !          1860: #endif
        !          1861:        n = strlen(b);
        !          1862:        putbyte(n);
        !          1863:        putblock(b, n);
        !          1864:        putrept(' ', 40 - n);
        !          1865: }
        !          1866: 
        !          1867: /*
        !          1868:  * Put out a segment definition.
        !          1869:  * The attribute and length may be fixed later.
        !          1870:  * Return the location of the attribute byte.
        !          1871:  */
        !          1872: long
        !          1873: putsegdef(attrib, namep)
        !          1874: int attrib;
        !          1875: char *namep;
        !          1876: {
        !          1877:        long l;
        !          1878: 
        !          1879:        l = oflength;
        !          1880:        ++nsegs;
        !          1881:        putword(attrib);                /* attributes, may be fixed later */
        !          1882:        putrept(0, 6);                  /* length, dlength, LDT position */
        !          1883:        putname(namep);                 /* combine name */
        !          1884:        return(l);
        !          1885: }
        !          1886: 
        !          1887: /*
        !          1888:  * End a section.
        !          1889:  * Compute section length;
        !          1890:  * reset section location to 0 if empty.
        !          1891:  */
        !          1892: endsec(n)
        !          1893: register int n;
        !          1894: {
        !          1895:        seclen[n] = oflength - secloc[n];
        !          1896:        if (seclen[n] == 0L)
        !          1897:                secloc[n] = 0L;
        !          1898: }
        !          1899: 
        !          1900: /*
        !          1901:  * Return OMF segment index internal name corresponding to
        !          1902:  * compiler logical segment code.
        !          1903:  */
        !          1904: segindex(n)
        !          1905: register int n;
        !          1906: {
        !          1907:        return(SEGIN |  ((isvariant(VSMALL)||isvariant(VRAM))?ramseg[n]
        !          1908:                        : ((isvariant(VROM))?romseg[n]
        !          1909:                        : nonseg[n])));
        !          1910: }
        !          1911: 
        !          1912: /*
        !          1913:  * Convert character to upper case.
        !          1914:  */
        !          1915: uppercase(c)
        !          1916: register c;
        !          1917: {
        !          1918:        if (c < 'a' || c > 'z')
        !          1919:                return(c);
        !          1920:        return(c - 'a' + 'A');
        !          1921: }
        !          1922: 
        !          1923: /*
        !          1924:  * Assign a base address to a compiler logical segment.
        !          1925:  * Bump seg_size and reset segment location counter to base.
        !          1926:  * Round sizes up to even boundaries because of 80287 word alignment bug.
        !          1927:  */
        !          1928: lseg(n)
        !          1929: register int n;
        !          1930: {
        !          1931:        seg[n].s_mseek = seg_size;
        !          1932:        if (((seg[n].s_dot)&1) == 1) {
        !          1933:                ++seg[n].s_dot;         /* round dot up to even boundary */
        !          1934:                ++seglen[segindex(n)&~SEGIN];   /* and bump segment length */
        !          1935:        }
        !          1936:        seg_size += seg[n].s_dot;
        !          1937:        seg[n].s_dot = seg[n].s_mseek;
        !          1938: }
        !          1939: 
        !          1940: /*
        !          1941:  * Flush the text and fixup buffers.
        !          1942:  */
        !          1943: flush()
        !          1944: {
        !          1945:        register int n, sindex;
        !          1946:        if (txtp != txt) {
        !          1947:                n = txtp - txt;
        !          1948:                sindex = txtseg&~SEGIN;         /* mask off segment IN */
        !          1949:                putbyte(BTEXT);                 /* text block */
        !          1950:                if (sindex == CODESEG || sindex == DATASEG) {
        !          1951:                        putword(seg[dotseg].s_dot);
        !          1952:                        seg[dotseg].s_dot += n;
        !          1953:                }
        !          1954:                else putword(seglen[sindex]);   /* offset */
        !          1955:                putword(txtseg);                /* segment IN */
        !          1956:                seglen[sindex] += n;            /* bump seg length */
        !          1957:                putword(n);                     /* length */
        !          1958:                txtp = txt;
        !          1959:                while (n--)
        !          1960:                        putbyte(*txtp++);       /* text */
        !          1961:                txtp = txt;                     /* reset pointer */
        !          1962:        }
        !          1963:        if (fixp != fix) {
        !          1964:                putbyte(BFIXUP);                /* fixup block */
        !          1965:                putword(fixseg);                /* where-IN */
        !          1966:                n = fixp - fix;
        !          1967:                putword(n);                     /* length */
        !          1968:                fixp = fix;
        !          1969:                while (n--)
        !          1970:                        putbyte(*fixp++);       /* fixup */
        !          1971:                fixp = fix;                     /* reset pointer */
        !          1972:                ofixp = NULL;                   /* and reset ofixp */
        !          1973:        }
        !          1974: }
        !          1975: 
        !          1976: /*
        !          1977:  * Leave n bytes of space for text in given seg.
        !          1978:  * Flush if buffer is too full or contains text from a different segment.
        !          1979:  */
        !          1980: need(seg, n)
        !          1981: register int seg, n;
        !          1982: {
        !          1983:        if (n == 0)
        !          1984:                return;
        !          1985:        if (n > NTXT)
        !          1986:                cbotch("need");
        !          1987:        seg |= SEGIN;
        !          1988:        if ((txtp+n > &txt[NTXT]) || ((seg != txtseg) && (txtp != txt)))
        !          1989:                flush();
        !          1990:        txtseg = seg;
        !          1991: }
        !          1992: 
        !          1993: /*
        !          1994:  * Write n (1 or 2) bytes of data as text.
        !          1995:  */
        !          1996: text(data, n)
        !          1997: register int data, n;
        !          1998: {
        !          1999:        *txtp++ = data;
        !          2000:        if (n == 2)
        !          2001:                *txtp++ = data >> 8;
        !          2002: }
        !          2003: 
        !          2004: /*
        !          2005:  * Write 2 bytes of data as text.
        !          2006:  */
        !          2007: text2(data)
        !          2008: register int data;
        !          2009: {
        !          2010:        *txtp++ = data;
        !          2011:        *txtp++ = data >> 8;
        !          2012: }
        !          2013: 
        !          2014: /*
        !          2015:  * Write a fixup.
        !          2016:  * Flush if buffer is too full or contains fixups on a different segment.
        !          2017:  * An offset fixup followed by a selector fixup can get kludged into
        !          2018:  * a full virtual address fixup.
        !          2019:  */
        !          2020: fixup(format, wherein, whereoffs, whatin, whatoffs)
        !          2021: int format;
        !          2022: ADDRESS wherein, whereoffs, whatin, whatoffs;
        !          2023: {
        !          2024:        register int type;
        !          2025:        static ADDRESS owhereoffs, owhatin;
        !          2026:        wherein |= SEGIN;
        !          2027:        /* Flush if necessary. */
        !          2028:        if ((fixp+7 > &fix[NFIX]) || ((wherein != fixseg) && (fixp != fix)))
        !          2029:                flush();
        !          2030:        fixseg = wherein;
        !          2031:        /* Patch offset/selector fixup pairs to full virtual address fixups. */
        !          2032:        if (format == FORMOFF) {
        !          2033:                ofixp = fixp;
        !          2034:                owhereoffs = whereoffs;
        !          2035:                owhatin = whatin;
        !          2036:        }
        !          2037:        else if ((ofixp != NULL) && (format == FORMSEL) && (whatin == owhatin)
        !          2038:                && (whereoffs == owhereoffs + 2)) {
        !          2039:                *ofixp |= FORMFVA;
        !          2040:                ofixp = NULL;
        !          2041:                return;
        !          2042:        }
        !          2043:        else ofixp == NULL;
        !          2044:        /* Determine the fixup type. */
        !          2045:        if (whatin == wherein)
        !          2046:                type = FIXISEG;         /* intrasegment */
        !          2047:        else if (whatoffs == 0)
        !          2048:                type = FIXCALL;         /* call */
        !          2049:        else type = FIXGEN;             /* general */
        !          2050:        /* Write the fixup. */
        !          2051:        *fixp++ = format | type;        /* kind */
        !          2052:        *fixp++ = whereoffs;
        !          2053:        *fixp++ = whereoffs >> 8;       /* where-offset */
        !          2054:        if (type != FIXCALL) {
        !          2055:                *fixp++ = whatoffs;
        !          2056:                *fixp++ = whatoffs >> 8;        /* what-offset */
        !          2057:        }
        !          2058:        if (type != FIXISEG) {
        !          2059:                *fixp++ = whatin;
        !          2060:                *fixp++ = whatin >> 8;  /* what-IN */
        !          2061:        }
        !          2062: }
        !          2063: 
        !          2064: /*
        !          2065:  * Write a symbol fixup at the current text location in SYMSEG.
        !          2066:  */
        !          2067: fixsym(format, whatin, whatoffs)
        !          2068: int format;
        !          2069: ADDRESS whatin, whatoffs;
        !          2070: {
        !          2071:        fixup(format, SYMSEG, seglen[SYMSEG]+txtp-txt, SEGIN|whatin, whatoffs);
        !          2072: }
        !          2073: 
        !          2074: /*
        !          2075:  * Perform fixup at current location.
        !          2076:  */
        !          2077: fixdot(format, whatin, whatoffs)
        !          2078: int format;
        !          2079: ADDRESS whatin, whatoffs;
        !          2080: {
        !          2081:        fixup(format, segindex(dotseg), dot, whatin, whatoffs);
        !          2082: }
        !          2083: 
        !          2084: #if VAXFMT
        !          2085: /*
        !          2086:  * Flush out a record on the VAX. The record is a standard,
        !          2087:  * RMS variable length record. This routine checks for no bytes
        !          2088:  * in the buffer, so it can be unconditionally called at the
        !          2089:  * end to flush the buffer out.
        !          2090:  * The record is padded out to NVDATA bytes with zeros. This
        !          2091:  * only happens on the last block; the data beyond the end
        !          2092:  * is zeroed.
        !          2093:  */
        !          2094: vaxflush()
        !          2095: {
        !          2096:        register int    n;
        !          2097: 
        !          2098: #if    TEMPBUF
        !          2099:        if (ofp == NULL)
        !          2100:                return;
        !          2101: #endif
        !          2102:        if ((n = vaxptr-vaxbuf) != 0) {
        !          2103:                if (fwrite(vaxbuf, n, 1, ofp) != 1
        !          2104:                ||  fflush(ofp) == EOF)
        !          2105:                        cfatal("output write error");
        !          2106:                vaxptr = vaxbuf;
        !          2107:        }
        !          2108: }
        !          2109: #endif
        !          2110: 
        !          2111: /*
        !          2112: ** Debug information processors.
        !          2113: */
        !          2114: 
        !          2115: fixpatch()
        !          2116: {
        !          2117:        register TYFIX *fp;
        !          2118: #if INTEL
        !          2119:        register TINFO *ttp, *pttp, *tp, *ptp;
        !          2120: #endif
        !          2121: 
        !          2122:        while ((fp = typefixp) != NULL) {
        !          2123: #if INTEL
        !          2124:                if (fp->t_ttype >= fp->t_type) dbfatal(__LINE__);
        !          2125:                /*
        !          2126:                 * This depends on NIL being at type index 1.
        !          2127:                 * Excise the dummy type def.
        !          2128:                 */
        !          2129:                pttp = gettype(fp->t_ttype-1);
        !          2130:                ttp = pttp->t_tp;
        !          2131:                pttp->t_tp = ttp->t_tp;
        !          2132:                /*
        !          2133:                 * Excise the real type def.
        !          2134:                 */
        !          2135:                ptp = gettype(fp->t_type-2);
        !          2136:                tp = ptp->t_tp;
        !          2137:                ptp->t_tp = tp->t_tp;
        !          2138:                /*
        !          2139:                 * Insert the dummy and blank it.
        !          2140:                 */
        !          2141:                ttp->t_tp = ptp->t_tp;
        !          2142:                ptp->t_tp = ttp;
        !          2143:                ttp->t_tflag = 0;
        !          2144:                ttp->t_length = 1;
        !          2145:                ttp->t_info[0] = OTNIL;
        !          2146:                /*
        !          2147:                 * Insert the real definition.
        !          2148:                 */
        !          2149:                tp->t_tp = pttp->t_tp;
        !          2150:                pttp->t_tp = tp;
        !          2151: #endif
        !          2152:                /*
        !          2153:                 * Release the memory.
        !          2154:                 */
        !          2155:                typefixp = fp->t_tp;
        !          2156:                free(fp);
        !          2157:        }
        !          2158: }
        !          2159: 
        !          2160: static TINFO *
        !          2161: gettype(index)
        !          2162: {
        !          2163:        register TINFO *tp;
        !          2164: 
        !          2165:        tp = typelistp;
        !          2166:        while (--index != 0)
        !          2167:                if ((tp = tp->t_tp) == NULL)
        !          2168:                        dbfatal(__LINE__);
        !          2169:        return (tp);
        !          2170: }
        !          2171: 
        !          2172: /*
        !          2173:  * Read debug table item(s) into memory.
        !          2174:  * These are buffered until appropriate moments.
        !          2175:  */
        !          2176: getdlab()
        !          2177: {
        !          2178:        register struct dbgt *dp;
        !          2179:        static int refnum = 0;
        !          2180: 
        !          2181:        dp = getdbgt();
        !          2182:        if (dp->d_class == DC_LINE || dp->d_class == DC_LAB)
        !          2183:                dp->d_ref = refnum;
        !          2184:        refnum += 1;
        !          2185:        if (dbase == NULL)
        !          2186:                dbase = dp;
        !          2187:        if (dnext != NULL)
        !          2188:                dnext->d_dp = dp;
        !          2189:        dbrpt("enter", dp);
        !          2190:        while (dp->d_dp != NULL) {
        !          2191:                dp = dp->d_dp;
        !          2192:                dbrpt("enter", dp);
        !          2193:        }
        !          2194:        dnext = dp;
        !          2195: }
        !          2196: 
        !          2197: /*
        !          2198:  * Read in debug item in form abbreviated by outdlab().
        !          2199:  */
        !          2200: struct dbgt *
        !          2201: getdbgt()
        !          2202: {
        !          2203:        register char *cp;
        !          2204:        register struct dbgt *dp;
        !          2205:        static int level = 0;
        !          2206:        struct dbgt d;
        !          2207:        SYM *sp;
        !          2208: 
        !          2209:        d.d_level = level;
        !          2210: 
        !          2211:        /*
        !          2212:         * Read the values in.
        !          2213:         */
        !          2214:        d.d_class = bget();
        !          2215:        d.d_line = iget();
        !          2216:        d.d_value = iget();
        !          2217:        d.d_seg = bget();
        !          2218: 
        !          2219:        /*
        !          2220:         * Read name.
        !          2221:         */
        !          2222:        for (cp = id; *cp = bget(); cp += 1);
        !          2223: 
        !          2224:        /*
        !          2225:         * Read type.
        !          2226:         */
        !          2227:        d.d_type = iget();
        !          2228: 
        !          2229:        /*
        !          2230:         * Check level change.
        !          2231:         */
        !          2232:        if (d.d_class == DC_LINE) {
        !          2233:                switch (id[0]) {
        !          2234:                case '{': level += 1; break;
        !          2235:                case '}': level -= 1; break;
        !          2236:                }
        !          2237:        }
        !          2238: 
        !          2239:        /*
        !          2240:         * Find location of static internal items.
        !          2241:         */
        !          2242:        if (d.d_class == DC_SIN) {
        !          2243:                sp = llookup(d.d_value, 0);
        !          2244:                d.d_value = sp->s_value;
        !          2245:                d.d_seg = sp->s_seg;
        !          2246:        }
        !          2247: 
        !          2248:        /*
        !          2249:         * Copy into dynamic storage.
        !          2250:         */
        !          2251:        dp = (struct dbgt *)malloc(sizeof(struct dbgt) + cp - id + 1);
        !          2252:        if (dp == NULL)
        !          2253:                cnomem("getdbgt");
        !          2254:        dp->d_level = d.d_level;
        !          2255:        dp->d_class = d.d_class;
        !          2256:        dp->d_line = d.d_line;
        !          2257:        dp->d_seg = d.d_seg;
        !          2258:        if (d.d_seg < SANY)
        !          2259:                d.d_value += seg[d.d_seg].s_mseek;
        !          2260:        dp->d_value = d.d_value;
        !          2261:        dp->d_type = d.d_type;
        !          2262:        dp->d_dp = NULL;
        !          2263:        dp->d_ref = -1;
        !          2264:        while (cp >= id) {
        !          2265:                dp->d_id[cp-id] = *cp;
        !          2266:                cp -= 1;
        !          2267:        }
        !          2268:        return (dp);
        !          2269: }
        !          2270: 
        !          2271: /*
        !          2272:  * Read a debug relocation item and patch current 'dot'
        !          2273:  * into the appropriate debug/symbol table item.
        !          2274:  * If the debug item is '}' and level 1, then dump everything in the list.
        !          2275:  */
        !          2276: getdloc()
        !          2277: {
        !          2278:        register struct dbgt *dp;
        !          2279:        register int ref;
        !          2280: 
        !          2281:        ref = iget();
        !          2282:        for (dp = dbase; ; dp = dp->d_dp) {
        !          2283:                if (dp == NULL)
        !          2284:                        cbotch("getdloc: %d", ref);
        !          2285:                if (dp->d_ref == ref)
        !          2286:                        break;
        !          2287:        }
        !          2288:        dp->d_seg = dotseg;
        !          2289:        dp->d_value = dot;
        !          2290: 
        !          2291:        dbrpt("reloc", dp);
        !          2292:        if (dp->d_id[0] == '}' && dp->d_level == 1)
        !          2293:                dbdump();
        !          2294: }
        !          2295: 
        !          2296: /*
        !          2297:  * Dump all the debug symbols.
        !          2298:  */
        !          2299: dbdump()
        !          2300: {
        !          2301:        register struct dbgt *dp, **dpp;
        !          2302:        extern char *regnames[];
        !          2303: 
        !          2304:        dpp = &dbase;
        !          2305:        dnext = NULL;
        !          2306:        while ((dp = *dpp) != NULL) {
        !          2307:                switch (dp->d_class) {
        !          2308:                case DC_GDEF:           /* Global def. */
        !          2309:                case DC_SEX:            /* Static external */
        !          2310:                        /* Function definitions replace initial { */
        !          2311:                        if (dp->d_seg == SCODE) {
        !          2312:                                /* The initial BLKDEF occurs before PROLOG
        !          2313:                                 * at the function entry point.  Could be
        !          2314:                                 * moved after PROLOG if desired.
        !          2315:                                 * The last BLKEND occurs just
        !          2316:                                 * before the EPILOG, and can also be moved.
        !          2317:                                 */
        !          2318:                                SYM *sp;
        !          2319: 
        !          2320:                                sp = glookup(dp->d_id, 0);
        !          2321:                                dp->d_type = sp->s_type;
        !          2322:                                putline(dp);
        !          2323:                                putbbeg(dp);
        !          2324:                        } else
        !          2325:                                putsym(dp);
        !          2326:                        break;
        !          2327:                case DC_GREF:           /* Global ref. */
        !          2328:                        break;
        !          2329:                case DC_TYPE:           /* Typedef name */
        !          2330:                case DC_STAG:           /* Structure tag */
        !          2331:                case DC_UTAG:           /* Union tag */
        !          2332:                case DC_ETAG:           /* Enumeration tag */
        !          2333:                case DC_FILE:           /* Source file name */
        !          2334:                        break;
        !          2335:                case DC_AUTO:           /* Auto */
        !          2336:                case DC_PAUTO:          /* Parametric auto */
        !          2337:                        putsym(dp);
        !          2338:                        break;
        !          2339:                case DC_SIN:            /* Static internal */
        !          2340:                case DC_LAB:            /* Label */
        !          2341:                        putsym(dp);
        !          2342:                        break;
        !          2343:                case DC_REG:            /* Register */
        !          2344:                case DC_PREG:           /* Parametric register */
        !          2345: #if INTEL
        !          2346:                        line = dp->d_line;
        !          2347:                        cwarn("variable \"%s\" is in register %s",
        !          2348:                                dp->d_id, regnames[dp->d_value]);
        !          2349: #endif
        !          2350:                        break;
        !          2351:                case DC_MOE:            /* Member of enumeration */
        !          2352:                        break;
        !          2353:                case DC_LINE:           /* Line number */
        !          2354:                        switch (dp->d_id[0]) {
        !          2355:                        case '{':       /* Block begins */
        !          2356:                                /* GDEF or SEX takes first blkdef */
        !          2357:                                if (dp->d_level != 0) {
        !          2358:                                        putline(dp);
        !          2359:                                        putbbeg(dp);
        !          2360:                                }
        !          2361:                                break;
        !          2362:                        case ';':       /* Line number */
        !          2363:                                putline(dp);
        !          2364:                                break;
        !          2365:                        case '}':       /* Block ends */
        !          2366:                                putbend();
        !          2367:                                break;
        !          2368:                        default:
        !          2369:                                cbotch("bad line record (dbdump)");
        !          2370:                        }
        !          2371:                        break;
        !          2372:                case DC_MOS:            /* Member of structure */
        !          2373:                case DC_MOU:            /* Member of union */
        !          2374:                case DC_CALL:           /* Function call */
        !          2375:                        break;
        !          2376:                default:
        !          2377:                        cbotch("bad class (dbdump)");
        !          2378:                }
        !          2379:                *dpp = dp->d_dp;
        !          2380:                free(dp);
        !          2381:        }
        !          2382: }
        !          2383: 
        !          2384: #if !TINY
        !          2385: _dbrpt(p, dp)
        !          2386: char *p;
        !          2387: register struct dbgt *dp;
        !          2388: {
        !          2389:        if (xflag > 5)
        !          2390:                printf("%s:     %d %s %d %d %o %d\n",
        !          2391:                        p,
        !          2392:                        dp->d_class,
        !          2393:                        dp->d_id,
        !          2394:                        dp->d_ref,
        !          2395:                        dp->d_level,
        !          2396:                        dp->d_flag,
        !          2397:                        dp->d_type,
        !          2398:                        0);
        !          2399: }
        !          2400: 
        !          2401: #endif
        !          2402: 
        !          2403: /*
        !          2404:  * Splat an index leaf.
        !          2405:  */
        !          2406: char *
        !          2407: setindex(cp, i)
        !          2408: register char *cp;
        !          2409: register unsigned i;
        !          2410: {
        !          2411:        *cp++ = OTINDEX;
        !          2412:        *cp++ = i;
        !          2413:        *cp++ = (i >> 8);
        !          2414:        return (cp);
        !          2415: }
        !          2416: 
        !          2417: /*
        !          2418:  * Splat a name leaf.
        !          2419:  */
        !          2420: char *
        !          2421: setname(bp, cp)
        !          2422: register char *bp;
        !          2423: register char *cp;
        !          2424: {
        !          2425:        *bp++ = OTNAME;
        !          2426:        return(setsymid(bp, cp));
        !          2427: }
        !          2428: 
        !          2429: /*
        !          2430:  * Splat an unsigned numeric leaf.
        !          2431:  * This assumes that the leaf always fits in 4 bytes,
        !          2432:  * since any object the compiler knows about must fit in
        !          2433:  * 64K bytes or 64K * NBPBYTE = 512K bits.
        !          2434:  */
        !          2435: char *
        !          2436: setnumb(bp, numb)
        !          2437: char *bp;
        !          2438: unsigned long numb;
        !          2439: {
        !          2440:        if (numb < 128)
        !          2441:                *bp++ = numb;
        !          2442:        else if (numb < 0x10000L) {
        !          2443:                *bp++ = OTUNUM2;
        !          2444:                *bp++ = numb;
        !          2445:                *bp++ = numb >> 8;
        !          2446:        }
        !          2447:        else {
        !          2448:                *bp++ = OTUNUM4;
        !          2449:                *bp++ = numb;
        !          2450:                *bp++ = numb >> 8;
        !          2451:                *bp++ = numb >> 16;
        !          2452:                *bp++ = numb >> 24;
        !          2453:        }
        !          2454:        return (bp);
        !          2455: }
        !          2456: 
        !          2457: /*
        !          2458:  * Splat a bit size.
        !          2459:  */
        !          2460: char *
        !          2461: setsize(bp, size)
        !          2462: char *bp;
        !          2463: long size;
        !          2464: {
        !          2465:        lastsize = size;
        !          2466:        return (setnumb(bp, size));
        !          2467: }
        !          2468: 
        !          2469: /*
        !          2470:  * Copy name through bp and return updated bp.
        !          2471:  */
        !          2472: char *
        !          2473: setsymid(bp, cp)
        !          2474: register char *bp;
        !          2475: register char *cp;
        !          2476: {
        !          2477:        register len;
        !          2478:        if ((len=strlen(cp)) > 39) {
        !          2479:                cwarn("symbol \"%s\" truncated to 39 characters", cp);
        !          2480:                len = 39;
        !          2481:        }
        !          2482:        *bp++ = len;
        !          2483:        while (len--)
        !          2484:                *bp++ = uppercase(*cp++);
        !          2485:        return (bp);
        !          2486: }
        !          2487: 
        !          2488: dbfatal(lineno)
        !          2489: {
        !          2490:        cbotch("debug label format in %d", lineno);
        !          2491: }
        !          2492: 
        !          2493: dbmemory(lineno)
        !          2494: {
        !          2495:        cnomem("dbmemory %d", lineno);
        !          2496: }

unix.superglobalmegacorp.com

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