Annotation of coherent/b/bin/c/n2/i8086/out286.c, revision 1.1.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.