|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.