|
|
1.1 ! root 1: /* ! 2: * This file writes writes Intel iAPX-86 OMF with csd debugging information. ! 3: * Based on outomf.c, but with MWC CSD-format debug info (as in outrel.c) ! 4: * instead of Intel format. ! 5: * The 'out...' routines write to a temporary file during code assembly. ! 6: * At the end of assembly, 'copycode' uses the 'put...' routines ! 7: * to write the object file. ! 8: * This is necessary: SEGDEF records must be written before ! 9: * LEDATA and FIXUPP records, but each SEGDEF includes the size ! 10: * of the segment in bytes. ! 11: * However, the size of the DEBUG segment is fixed up ex post facto. ! 12: */ ! 13: ! 14: /* ! 15: * Reference: "8086 Relocatable Object Formats," ! 16: * Intel 121748-001 (C) Intel 1981. ! 17: */ ! 18: ! 19: #ifdef vax ! 20: #include "INC$LIB:cc2.h" ! 21: #include "INC$LIB:debug.h" ! 22: #else ! 23: #include "cc2.h" ! 24: #include "debug.h" ! 25: #endif ! 26: ! 27: #define NTXT (512+3) /* Text buffer size */ ! 28: #define NREL 256 /* Relocation buffer size */ ! 29: ! 30: #ifndef __LINE__ ! 31: #define __LINE__ 0 ! 32: #endif ! 33: ! 34: #if !TINY ! 35: #define dbrpt(x,y) _dbrpt(x,y) ! 36: #else ! 37: #define dbrpt(x,y) /* _dbrpt(x,y) */ ! 38: #endif ! 39: ! 40: /* ! 41: * Scratch file opcodes. ! 42: * Flags are or'ed in to TBYTE and TWORD opcodes only. ! 43: */ ! 44: #define TTYPE 0x07 /* Type */ ! 45: #define TPCR 0x08 /* PC rel flag */ ! 46: #define TSYM 0x10 /* Symbol based flag */ ! 47: ! 48: #define TEND 0x00 /* End marker */ ! 49: #define TENTER 0x01 /* Enter new area */ ! 50: #define TBYTE 0x02 /* Byte data */ ! 51: #define TWORD 0x03 /* Word data */ ! 52: #define TCODE 0x04 /* Code segment base */ ! 53: #define TDATA 0x05 /* Data segment base */ ! 54: #define TBASE 0x06 /* External segment base */ ! 55: #define TDLAB 0x07 /* Debug label */ ! 56: #define TDLOC 0x08 /* Debug location */ ! 57: ! 58: #if EMUFIXUPS ! 59: /* ! 60: * If EMUFIXUPS is defined at compile time, the generated output writer ! 61: * targets 8087 instructions with magic "M:..." fixups. ! 62: * The linker can then create objects which use either 8087 hardware ! 63: * or software floating point emulation; in the latter case, the ! 64: * linker changes the 8087 instructions into traps to the emulator. ! 65: */ ! 66: #define T8087 0xE0 /* 8087 flags */ ! 67: #define TWT 0x20 /* M:_WT */ ! 68: #define TWST 0x40 /* M:_WST */ ! 69: #define TWES 0x60 /* M:_WES */ ! 70: #define TWCS 0x80 /* M:_WCS */ ! 71: #define TWSS 0xA0 /* M:_WSS */ ! 72: #define TWDS 0xC0 /* M:_WDS */ ! 73: #endif ! 74: ! 75: /* ! 76: * OMF types. ! 77: */ ! 78: #define THEADR 0x80 /* Translator module header */ ! 79: #define COMENT 0x88 /* Comment */ ! 80: #define MODEND 0x8A /* Module end */ ! 81: #define EXTDEF 0x8C /* External definition (reference) */ ! 82: #define TYPDEF 0x8E /* Type definition */ ! 83: #define PUBDEF 0x90 /* Public definition (definition) */ ! 84: #define LNAMES 0x96 /* List of names */ ! 85: #define SEGDEF 0x98 /* Segment definition */ ! 86: #define GRPDEF 0x9A /* Group definition */ ! 87: #define FIXUPP 0x9C /* Fixups */ ! 88: #define LEDATA 0xA0 /* Enumerated data */ ! 89: #define LIDATA 0xA2 /* Iterated data */ ! 90: ! 91: /* ! 92: * Some OMF fields and flags. ! 93: */ ! 94: #define BYTE (0x01<<5) /* Byte alignment */ ! 95: #define PARA (0x03<<5) /* Paragraph alignment */ ! 96: #define CMEM (0x01<<2) /* C field, memory */ ! 97: #define CCON (0x02<<2) /* C field, concatenate */ ! 98: #define CSTACK (0x05<<2) /* C field, stack */ ! 99: ! 100: #define LOCAT 0x80 /* Locat flag bit */ ! 101: #define M 0x40 /* M bit; 0=self rel, 1=seg rel */ ! 102: #define OFFSET (0x01<<2) /* Locat */ ! 103: #define BASE (0x02<<2) /* Locat */ ! 104: #define POINTER (0x03<<2) /* Locat */ ! 105: ! 106: #define SECWAY 0x04 /* Secondary way */ ! 107: #define FD8087 0x36 /* FIXDAT for 8087 fixup */ ! 108: #define FSI (0<<4) /* Frame: segment index */ ! 109: #define FGI (1<<4) /* Frame: group index */ ! 110: #define FEI (2<<4) /* Frame: external index */ ! 111: #define FTARGET (5<<4) /* Frame: target */ ! 112: #define TSI 0 /* Target: segment index */ ! 113: #define TGI 1 /* Target: group index */ ! 114: #define TEI 2 /* Target: external index */ ! 115: #define TFN 3 /* Target: frame */ ! 116: #define F 0x80 /* Frame thread used */ ! 117: #define FT0 0x00 /* 0 */ ! 118: #define FT1 0x10 /* 1 */ ! 119: ! 120: /* ! 121: * Structure to contain debug items on this pass. ! 122: * Debug items are kept in a linked list rooted at 'dbase', ! 123: * with 'dnext' pointing at the most recent item. ! 124: */ ! 125: typedef struct dbgt { ! 126: struct dbgt *d_dp; /* Link */ ! 127: int d_ref; /* Index number */ ! 128: unsigned char d_class; /* Storage class */ ! 129: unsigned char d_flag; /* Flags */ ! 130: unsigned char d_level; /* Bracket level */ ! 131: unsigned char d_seg; /* Reloc-style segment */ ! 132: unsigned char d_cseg; /* C Segment */ ! 133: ADDRESS d_value; /* Offset in segment */ ! 134: int d_size; /* Size of d_data */ ! 135: char d_data[]; /* Name and type */ ! 136: } DBGT; ! 137: /* Flag bits. */ ! 138: #define D_GBL 1 ! 139: #define D_LCL 2 ! 140: #define D_TAG 4 ! 141: #define D_NAM 8 ! 142: #define D_LAB 16 ! 143: #define D_ENU 32 ! 144: ! 145: /* ! 146: * Globals for output writer. ! 147: */ ! 148: static int islarge; /* True iff isvariant(LARGE) */ ! 149: static int isvcsd; /* True iff -VCSD */ ! 150: static int sx_code; /* Segment index of SCODE */ ! 151: static int sx_data; /* Segment index of SDATA */ ! 152: static int sx_debug; /* Segment index of debug info */ ! 153: static char * segtab; /* Segment index conversion table */ ! 154: static char txt[NTXT]; /* Text buffer */ ! 155: static char rel[NREL]; /* Relocation buffer */ ! 156: static char * txtp = txt; /* Text pointer */ ! 157: static char * relp = rel; /* Relocation pointer */ ! 158: static DBGT * dbase; /* Root debug list item */ ! 159: static DBGT * dnext; /* Last debug list item */ ! 160: static int level = 0; /* Debug brace level */ ! 161: static int dline = 0; /* Most recent line number entry */ ! 162: ! 163: #if EMUFIXUPS ! 164: static int has8087; /* Has 8087 code flag */ ! 165: static SYM * wsp[6]; /* Links to emulator symbols */ ! 166: #endif ! 167: ! 168: #if VAXFMT ! 169: /* ! 170: * The Intel cross software packs the OMF ! 171: * data into 512 byte blocks as 510 byte variable length ! 172: * records, with the last record short. ! 173: */ ! 174: #define NVDATA 510 /* Blocksize - 2 */ ! 175: static char vaxbuf[NVDATA]; /* Buffer */ ! 176: static char * vaxptr = vaxbuf; /* Pointer */ ! 177: #endif ! 178: ! 179: /* ! 180: * Function declarations. ! 181: */ ! 182: extern char * calloc(); ! 183: extern long ftell(); ! 184: extern DBGT * getdbgt(); ! 185: extern char * getmembs(); ! 186: extern char * malloc(); ! 187: extern char * movename(); ! 188: extern DBGT * newdbgt(); ! 189: extern long putsegdef(); ! 190: extern char * setindex(); ! 191: extern char * setsymid(); ! 192: extern char * strcpy(); ! 193: extern char * strncpy(); ! 194: ! 195: /* ! 196: * Logical name indices. ! 197: * These must correspond to the order defined by the LNAMES ! 198: * record written by putlnames(). ! 199: */ ! 200: #define LN_EMPTY 1 /* LARGE or SMALL "" */ ! 201: #define LN_L_M_CODE 2 /* LARGE "module_CODE" */ ! 202: #define LN_L_M_DATA 3 /* LARGE "module_DATA" */ ! 203: #define LN_L_CODE 4 /* LARGE "CODE" */ ! 204: #define LN_L_DATA 5 /* LARGE "DATA" */ ! 205: #define LN_L_DEBUG 6 /* LARGE "DEBUG" */ ! 206: #define LN_L_M_DEBUG 7 /* LARGE "module_DEBUG" */ ! 207: #define LN_S_CODE 2 /* SMALL "CODE" */ ! 208: #define LN_S_DATA 3 /* SMALL "DATA" */ ! 209: #define LN_S_CONST 4 /* SMALL "CONST" */ ! 210: #define LN_S_STACK 5 /* SMALL "STACK" */ ! 211: #define LN_S_MEMORY 6 /* SMALL "MEMORY" */ ! 212: #define LN_S_CGROUP 7 /* SMALL "CGROUP" */ ! 213: #define LN_S_DGROUP 8 /* SMALL "DGROUP" */ ! 214: #define LN_S_DEBUG 9 /* SMALL "DEBUG" */ ! 215: #define LN_S_M_DEBUG 10 /* SMALL "module_DEBUG" */ ! 216: ! 217: /* ! 218: * Segment indices. ! 219: * These must correspond to the order of the SEGDEF records ! 220: * written by copycode(). ! 221: */ ! 222: #define SX_L_M_CODE 1 /* LARGE module_CODE */ ! 223: #define SX_L_M_DATA 2 /* LARGE module_DATA */ ! 224: #define SX_L_M_DEBUG 3 /* LARGE module_DEBUG */ ! 225: #define SX_S_CODE 1 /* SMALL CODE */ ! 226: #define SX_S_CONST 2 /* SMALL CONST */ ! 227: #define SX_S_DATA 3 /* SMALL DATA */ ! 228: #define SX_S_STACK 4 /* SMALL STACK */ ! 229: #define SX_S_MEMORY 5 /* SMALL MEMORY */ ! 230: #define SX_S_M_DEBUG 6 /* SMALL module_DEBUG */ ! 231: ! 232: /* ! 233: * Group indices, SMALL model only. ! 234: * These must correspond to the order of the GRPDEF records ! 235: * written by copycode(). ! 236: */ ! 237: #define GX_CGROUP 1 /* CGROUP */ ! 238: #define GX_DGROUP 2 /* DGROUP */ ! 239: ! 240: /* Type index for NIL type. */ ! 241: #define TYPENIL 1 ! 242: ! 243: /* ! 244: * getsegindex() uses the following tables, ! 245: * indexed by a compiler segment name (SCODE et al.) ! 246: * to get an OMF segment index. ! 247: * These tables understand the way the SSTRN segment moves ! 248: * around when the ROM option is given. ! 249: */ ! 250: static char lnonseg[] = { ! 251: SX_L_M_CODE, /* SCODE => module_CODE */ ! 252: SX_L_M_CODE, /* SLINK => module_CODE */ ! 253: SX_L_M_CODE, /* SPURE => module_CODE */ ! 254: SX_L_M_DATA, /* SSTRN => module_DATA */ ! 255: SX_L_M_DATA, /* SDATA => module_DATA */ ! 256: SX_L_M_DATA /* SBSS => module_DATA */ ! 257: }; ! 258: ! 259: static char lromseg[] = { ! 260: SX_L_M_CODE, /* SCODE => module_CODE */ ! 261: SX_L_M_CODE, /* SLINK => module_CODE */ ! 262: SX_L_M_CODE, /* SPURE => module_CODE */ ! 263: SX_L_M_CODE, /* SSTRN => module_CODE */ ! 264: SX_L_M_DATA, /* SDATA => module_DATA */ ! 265: SX_L_M_DATA /* SBSS => module_DATA */ ! 266: }; ! 267: ! 268: static char lramseg[] = { ! 269: SX_L_M_CODE, /* SCODE => module_CODE */ ! 270: SX_L_M_CODE, /* SLINK => module_CODE */ ! 271: SX_L_M_DATA, /* SPURE => module_DATA */ ! 272: SX_L_M_DATA, /* SSTRN => module_DATA */ ! 273: SX_L_M_DATA, /* SDATA => module_DATA */ ! 274: SX_L_M_DATA /* SBSS => module_DATA */ ! 275: }; ! 276: ! 277: static char snonseg[] = { ! 278: SX_S_CODE, /* SCODE => CODE */ ! 279: SX_S_CODE, /* SLINK => CODE */ ! 280: SX_S_CONST, /* SPURE => CONST */ ! 281: SX_S_DATA, /* SSTRN => DATA */ ! 282: SX_S_DATA, /* SDATA => DATA */ ! 283: SX_S_DATA /* SBSS => DATA */ ! 284: }; ! 285: ! 286: static char sromseg[] = { ! 287: SX_S_CODE, /* SCODE => CODE */ ! 288: SX_S_CODE, /* SLINK => CODE */ ! 289: SX_S_CONST, /* SPURE => CONST */ ! 290: SX_S_CONST, /* SSTRN => CONST */ ! 291: SX_S_DATA, /* SDATA => DATA */ ! 292: SX_S_DATA /* SBSS => DATA */ ! 293: }; ! 294: ! 295: static char sramseg[] = { ! 296: SX_S_CODE, /* SCODE => CODE */ ! 297: SX_S_CODE, /* SLINK => CODE */ ! 298: SX_S_DATA, /* SPURE => DATA */ ! 299: SX_S_DATA, /* SSTRN => DATA */ ! 300: SX_S_DATA, /* SDATA => DATA */ ! 301: SX_S_DATA /* SBSS => DATA */ ! 302: }; ! 303: ! 304: /* ! 305: * Same game, but for group index codes. ! 306: * getgrpindex() uses this, in SMALL model only. ! 307: */ ! 308: static char grpindex[] = { ! 309: GX_CGROUP, /* SCODE => CGROUP */ ! 310: GX_CGROUP, /* SLINK => CGROUP */ ! 311: GX_DGROUP, /* SPURE => DGROUP */ ! 312: GX_DGROUP, /* SSTRN => DGROUP */ ! 313: GX_DGROUP, /* SDATA => DGROUP */ ! 314: GX_DGROUP /* SBSS => DGROUP */ ! 315: }; ! 316: ! 317: /* ! 318: * Some prefabricated OMF items. ! 319: * These are just blasted out via calls to putrecord() in copycode(). ! 320: */ ! 321: static char lthred[] = { ! 322: 0x40, SX_L_M_CODE, /* frame0 -> module_CODE */ ! 323: 0x41, SX_L_M_DATA /* frame1 -> module_DATA */ ! 324: }; ! 325: static char gdef1[] = { ! 326: LN_S_CGROUP, ! 327: 0xFF, SX_S_CODE ! 328: }; ! 329: static char gdef2[] = { ! 330: LN_S_DGROUP, ! 331: 0xFF, SX_S_CONST, ! 332: 0xFF, SX_S_DATA, ! 333: 0xFF, SX_S_STACK, ! 334: 0xFF, SX_S_MEMORY ! 335: }; ! 336: static char sthred[] = { ! 337: 0x44, GX_CGROUP, /* frame0 -> CGROUP */ ! 338: 0x45, GX_DGROUP /* frame1 -> DGROUP */ ! 339: }; ! 340: static char typdef[] = { 0, 0, 0x80 }; /* TYPDEF [1] NIL */ ! 341: static char modend[] = { 0x00 }; ! 342: ! 343: /* ! 344: ** First pass routines. ! 345: ** Output items to the temporary file. ! 346: */ ! 347: /* ! 348: * Initialize the code writer. ! 349: */ ! 350: outinit() ! 351: { ! 352: #if MONOLITHIC ! 353: #if EMUFIXUPS ! 354: register int i; ! 355: ! 356: has8087 = 0; ! 357: for (i=0; i<6; ++i) ! 358: wsp[i] = NULL; ! 359: #endif ! 360: txtp = &txt[0]; ! 361: relp = &rel[0]; ! 362: dbase = dnext = NULL; ! 363: #if VAXFMT ! 364: vaxptr = &vaxbuf[0]; ! 365: #endif ! 366: #endif ! 367: /* Initialize global data which depends on variant. */ ! 368: islarge = isvariant(VLARGE); ! 369: isvcsd = isvariant(VTYPES) || isvariant(VDSYMB); ! 370: if (islarge) { ! 371: sx_code = SX_L_M_CODE; ! 372: sx_data = SX_L_M_DATA; ! 373: sx_debug = SX_L_M_DEBUG; ! 374: segtab = isvariant(VROM) ? lromseg ! 375: : notvariant(VRAM) ? lnonseg ! 376: : lramseg; ! 377: } else { ! 378: sx_code = SX_S_CODE; ! 379: sx_data = SX_S_DATA; ! 380: sx_debug = SX_S_M_DEBUG; ! 381: segtab = isvariant(VROM) ? sromseg ! 382: : notvariant(VRAM) ? snonseg ! 383: : sramseg; ! 384: } ! 385: } ! 386: ! 387: /* ! 388: * Output a segment switch. ! 389: */ ! 390: outseg(s) ! 391: { ! 392: bput(TENTER); ! 393: bput(s); ! 394: } ! 395: ! 396: /* ! 397: * Output an absolute byte. ! 398: */ ! 399: outab(b) ! 400: { ! 401: bput(TBYTE); ! 402: bput(b); ! 403: ++dot; ! 404: } ! 405: ! 406: /* ! 407: * Output an absolute word. ! 408: */ ! 409: outaw(w) ! 410: { ! 411: bput(TWORD); ! 412: iput(w); ! 413: dot += 2; ! 414: } ! 415: ! 416: /* ! 417: * Output a full byte. ! 418: */ ! 419: outxb(sp, b, pcrf) ! 420: register SYM *sp; ! 421: { ! 422: register opcode; ! 423: ! 424: opcode = TBYTE; ! 425: if (sp != NULL) ! 426: opcode |= TSYM; ! 427: if (pcrf) ! 428: opcode |= TPCR; ! 429: bput(opcode); ! 430: bput(b); ! 431: if (sp != NULL) ! 432: pput(sp); ! 433: ++dot; ! 434: } ! 435: ! 436: /* ! 437: * Output a full word. ! 438: */ ! 439: outxw(sp, w, pcrf) ! 440: register SYM *sp; ! 441: { ! 442: register opcode; ! 443: ! 444: opcode = TWORD; ! 445: if (sp != NULL) ! 446: opcode |= TSYM; ! 447: if (pcrf) ! 448: opcode |= TPCR; ! 449: bput(opcode); ! 450: iput(w); ! 451: if (sp != NULL) ! 452: pput(sp); ! 453: dot += 2; ! 454: } ! 455: ! 456: #if EMUFIXUPS ! 457: /* ! 458: * Output a one byte opcode for the 8087. ! 459: */ ! 460: outfb(b) ! 461: { ! 462: has8087 = 1; ! 463: bput(TBYTE|TWT); ! 464: bput(b); ! 465: ++dot; ! 466: } ! 467: ! 468: /* ! 469: * Output a two byte opcode for the 8087. ! 470: */ ! 471: outfw(w, prefix) ! 472: { ! 473: has8087 = 1; ! 474: bput(TWORD|((prefix>>3)+TWST)); ! 475: iput(w); ! 476: dot += 2; ! 477: } ! 478: #endif ! 479: ! 480: /* ! 481: * Output a 1 word object containing ! 482: * the base address of the external symbol pointed to by 'sp'. ! 483: */ ! 484: outsb(sp) ! 485: SYM *sp; ! 486: { ! 487: bput(TBASE); ! 488: pput(sp); ! 489: dot += 2; ! 490: } ! 491: ! 492: /* ! 493: * Copy a dlabel record from ifp to ofp. ! 494: * Flag the symbol table entry if appropriate. ! 495: * Recursive for DX_MEMBS member lists. ! 496: */ ! 497: outdlab(l,class) ! 498: { ! 499: register int val; ! 500: register SYM *sp; ! 501: int n; ! 502: ! 503: if (l == 0) ! 504: bput(TDLAB); ! 505: bput(class); ! 506: ! 507: /* Get line number. */ ! 508: iput(iget()); ! 509: ! 510: /* Get value */ ! 511: if (class < DC_AUTO) ! 512: ; ! 513: else if (class < DC_MOS) ! 514: iput(val = iget()); ! 515: else { ! 516: bput(bget()); ! 517: bput(bget()); ! 518: iput(iget()); ! 519: } ! 520: ! 521: /* Get name */ ! 522: sget(id, NCSYMB); ! 523: ! 524: /* Check for symbol table entry */ ! 525: if (class==DC_GDEF || class==DC_SEX || class==DC_GREF) { ! 526: sp = glookup(id, 0); ! 527: sp->s_flag |= S_PUT; ! 528: } else if (class==DC_SIN) { ! 529: sp = llookup(val, 0); ! 530: sp->s_flag |= S_PUT; ! 531: } ! 532: ! 533: /* Put name */ ! 534: sput(id); ! 535: ! 536: /* Get type */ ! 537: for (;;) { ! 538: switch (bput(bget())) { ! 539: case DT_NONE: ! 540: case DT_CHAR: ! 541: case DT_UCHAR: ! 542: case DT_SHORT: ! 543: case DT_USHORT: ! 544: case DT_INT: ! 545: case DT_UINT: ! 546: case DT_LONG: ! 547: case DT_ULONG: ! 548: case DT_FLOAT: ! 549: case DT_DOUBLE: ! 550: case DT_VOID: ! 551: iput(iget()); ! 552: break; ! 553: case DT_STRUCT: ! 554: case DT_UNION: ! 555: case DT_ENUM: ! 556: case DD_PTR: ! 557: case DD_FUNC: ! 558: case DD_ARRAY: ! 559: iput(iget()); ! 560: continue; ! 561: break; ! 562: case DX_MEMBS: ! 563: bput(n = iget()); ! 564: for ( ; n > 0; n-=1) { ! 565: outdlab(1, bget()); ! 566: } ! 567: break; ! 568: case DX_NAME: ! 569: iget(); ! 570: sget(id, NCSYMB); ! 571: sput(id); ! 572: break; ! 573: default: ! 574: cbotch("outdlab: %d", n); ! 575: } ! 576: break; ! 577: } ! 578: } ! 579: ! 580: /* ! 581: * Output a debug relocation record. ! 582: * This 'n' is an index into the list of debug records written. ! 583: */ ! 584: outdloc(n) ! 585: { ! 586: bput(TDLOC); ! 587: iput(n); ! 588: } ! 589: ! 590: /* ! 591: * Finish up the code. ! 592: */ ! 593: outdone() ! 594: { ! 595: if (isvariant(VASM)) ! 596: return; ! 597: ! 598: #if EMUFIXUPS ! 599: /* ! 600: * Put magic names into the symbol table ! 601: * if any 8087 code was generated. ! 602: */ ! 603: if (has8087) { ! 604: wsp[0] = glookup("M:_WT", 0); ! 605: wsp[1] = glookup("M:_WST", 0); ! 606: wsp[2] = glookup("M:_WES", 0); ! 607: wsp[3] = glookup("M:_WCS", 0); ! 608: wsp[4] = glookup("M:_WSS", 0); ! 609: wsp[5] = glookup("M:_WDS", 0); ! 610: } ! 611: #endif ! 612: bput(TEND); ! 613: } ! 614: ! 615: /* ! 616: ** Second pass routines. ! 617: ** Read the temporary file and write the output. ! 618: */ ! 619: /* ! 620: * Finish up. ! 621: * Figure out the sizes and final values of everything. ! 622: * Copy the code from the scratch file back to the output file. ! 623: */ ! 624: copycode() ! 625: { ! 626: register int op; ! 627: register SYM *sp; ! 628: register int i; ! 629: int fixup; ! 630: int nd; ! 631: int data; ! 632: long debugdef; ! 633: ADDRESS code_size; ! 634: ADDRESS data_size; ! 635: ADDRESS const_size; ! 636: ADDRESS bss_size; ! 637: ! 638: /* ! 639: * Assign base addresses to the compiler's logical segments, based on ! 640: * the compilation model and the settings of the VROM and VRAM flags. ! 641: */ ! 642: dot = 0; ! 643: newseg(SCODE); ! 644: newseg(SLINK); ! 645: if (!islarge || isvariant(VRAM)) { ! 646: code_size = dot; ! 647: dot = 0; ! 648: } ! 649: newseg(SPURE); ! 650: if (notvariant(VROM) && notvariant(VRAM)) { ! 651: if (islarge) ! 652: code_size = dot; ! 653: else ! 654: const_size = dot; ! 655: dot = 0; ! 656: } ! 657: newseg(SSTRN); ! 658: if (isvariant(VROM)) { ! 659: if (islarge) ! 660: code_size = dot; ! 661: else ! 662: const_size = dot; ! 663: dot = 0; ! 664: } ! 665: newseg(SDATA); ! 666: newseg(SBSS); ! 667: bss_size = seg[SBSS].s_dot; ! 668: data_size = dot; ! 669: ! 670: /* ! 671: * Put out the preamble. ! 672: */ ! 673: putrecord(THEADR, txt, movename(txt, module, 0) - txt); /* THEADR */ ! 674: txt[0] = txt[1] = '\0'; ! 675: sprintf(&txt[2], "%s %s %s %s", ! 676: #ifdef vax ! 677: "VAX", ! 678: #else ! 679: #ifdef UDI ! 680: "UDI", ! 681: #else ! 682: #ifdef MSDOS ! 683: "MS-DOS", ! 684: #else ! 685: "COHERENT", ! 686: #endif ! 687: #endif ! 688: #endif ! 689: "MWC86", VERSMWC, ! 690: (islarge) ? "LARGE" : "SMALL"); ! 691: putrecord(COMENT, txt, strlen(&txt[2])+2); /* COMENT */ ! 692: putlnames(); /* LNAMES */ ! 693: /* ! 694: * The order of putsegdef() calls below must correspond to ! 695: * the definitions of SX_... macros above. ! 696: * Debug segment sizes are fixed up ex post facto. ! 697: */ ! 698: if (islarge) { ! 699: /* [1] */ putsegdef(PARA|CCON, code_size, LN_L_M_CODE, LN_L_CODE); ! 700: /* [2] */ putsegdef(PARA|CCON, data_size, LN_L_M_DATA, LN_L_DATA); ! 701: if (isvcsd) ! 702: /* [3] */ debugdef = putsegdef(BYTE|CCON, 0, LN_L_M_DEBUG, LN_L_DEBUG); ! 703: putrecord(FIXUPP, lthred, sizeof(lthred)); /* Threads */ ! 704: } else { ! 705: /* [1] */ putsegdef(BYTE|CCON, code_size, LN_S_CODE, LN_S_CODE); ! 706: /* [2] */ putsegdef(BYTE|CCON, const_size, LN_S_CONST, LN_S_CONST); ! 707: /* [3] */ putsegdef(BYTE|CCON, data_size, LN_S_DATA, LN_S_DATA); ! 708: /* [4] */ putsegdef(PARA|CSTACK, 0, LN_S_STACK, LN_S_STACK); ! 709: /* [5] */ putsegdef(PARA|CMEM, 0, LN_S_MEMORY, LN_S_MEMORY); ! 710: if (isvcsd) ! 711: /* [6] */ debugdef = putsegdef(BYTE|CCON, 0, LN_S_M_DEBUG, LN_S_DEBUG); ! 712: /* ! 713: * The order of putrecord() calls below must correspond to ! 714: * the definitions of GX_... macros above. ! 715: */ ! 716: /* [1] */ putrecord(GRPDEF, gdef1, sizeof(gdef1)); ! 717: /* [2] */ putrecord(GRPDEF, gdef2, sizeof(gdef2)); ! 718: putrecord(FIXUPP, sthred, sizeof(sthred)); /* Threads */ ! 719: } ! 720: putrecord(TYPDEF, typdef, sizeof(typdef)); /* TYPDEF */ ! 721: putsymdef(); /* PUBDEF, EXTDEF */ ! 722: ! 723: /* ! 724: * Copy out code. ! 725: */ ! 726: for (i=0; i<NSEG; ++i) ! 727: seg[i].s_dot = seg[i].s_mseek; ! 728: dotseg = SCODE; ! 729: dot = seg[SCODE].s_dot; ! 730: while ((op = bget()) != TEND) { ! 731: switch (op) { ! 732: ! 733: case TENTER: ! 734: notenuf(); ! 735: enter(bget()); ! 736: continue; ! 737: case TDLAB: ! 738: getdlab(); ! 739: continue; ! 740: case TDLOC: ! 741: getdloc(); ! 742: continue; ! 743: case TBASE: ! 744: if (!islarge) ! 745: cbotch("base"); ! 746: sp = pget(); ! 747: enuf(2, 5); ! 748: fixup = txtp - (txt+3); ! 749: *txtp++ = 0; ! 750: *txtp++ = 0; ! 751: dot += 2; ! 752: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 753: *relp++ = fixup; ! 754: if ((sp->s_flag&S_DEF) != 0) { ! 755: *relp++ = FTARGET|SECWAY|TSI; ! 756: *relp++ = getsegindex(sp->s_seg); ! 757: } else { ! 758: *relp++ = FTARGET|SECWAY|TEI; ! 759: relp = setindex(relp, sp->s_ref); ! 760: } ! 761: continue; ! 762: } ! 763: if ((op&TTYPE) == TBYTE) { ! 764: nd = 1; ! 765: data = bget(); ! 766: } else { ! 767: nd = 2; ! 768: data = iget(); ! 769: } ! 770: /* Assure enough space for text and relocation written below. */ ! 771: #if EMUFIXUPS ! 772: enuf(nd, 7); ! 773: #else ! 774: enuf(nd, 6); ! 775: #endif ! 776: dot += nd; ! 777: fixup = (txtp - (txt+3)) | (LOCAT << 8); ! 778: ! 779: #if EMUFIXUPS ! 780: /* ! 781: * 8087 opcodes. ! 782: * Apply magic relocation for the emulator. ! 783: */ ! 784: if ((op&T8087) != 0) { ! 785: sp = wsp[((op&T8087)-TWT)>>5]; ! 786: *txtp++ = data; ! 787: if (nd != 1) { ! 788: *txtp++ = data >> 8; ! 789: fixup |= OFFSET << 8; /* Locat */ ! 790: } ! 791: fixup |= M << 8; /* Seg rel */ ! 792: *relp++ = fixup>>8; ! 793: *relp++ = fixup; ! 794: *relp++ = FD8087; /* Symbol based */ ! 795: *relp++ = 0; /* Frame # */ ! 796: *relp++ = 0; ! 797: relp = setindex(relp, sp->s_ref); ! 798: continue; ! 799: } ! 800: #endif ! 801: /* ! 802: * Absolute. ! 803: */ ! 804: if ((op&(TSYM|TPCR)) == 0) { ! 805: *txtp++ = data; ! 806: if (nd != 1) ! 807: *txtp++ = data >> 8; ! 808: continue; ! 809: } ! 810: /* ! 811: * Absolute PC rel. ! 812: */ ! 813: if ((op&TSYM) == 0) { ! 814: *txtp++ = 0; ! 815: if (nd != 1) { ! 816: *txtp++ = 0; ! 817: fixup |= OFFSET << 8; ! 818: } ! 819: *relp++ = fixup>>8; ! 820: *relp++ = fixup; ! 821: *relp++ = FTARGET|TFN; /* Absolute frame */ ! 822: *relp++ = 0; /* Frame number */ ! 823: *relp++ = data; /* Disp */ ! 824: *relp++ = data >> 8; ! 825: continue; ! 826: } ! 827: /* ! 828: * Symbol based. ! 829: * I would like to always do this ! 830: * in the primary way. However, LINK-86 ! 831: * doesn't do 3 byte offsets, so I cannot ! 832: * do a negative one. ! 833: */ ! 834: sp = pget(); ! 835: if ((sp->s_flag&S_DEF) != 0) { ! 836: data += sp->s_value; ! 837: /* Absolute */ ! 838: if ((op&TPCR)!=0 && sp->s_seg==dotseg) { ! 839: data -= dot; ! 840: *txtp++ = data; ! 841: if (nd != 1) ! 842: *txtp++ = data >> 8; ! 843: continue; ! 844: } ! 845: /* Segment relative */ ! 846: *txtp++ = 0; ! 847: if (nd != 1) { ! 848: *txtp++ = 0; ! 849: fixup |= OFFSET << 8; /* Loc */ ! 850: } ! 851: if ((op&TPCR) == 0) ! 852: fixup |= M << 8; /* Seg rel */ ! 853: *relp++ = fixup>>8; ! 854: *relp++ = fixup; ! 855: if ((i = getsegindex(sp->s_seg)) == sx_code) ! 856: *relp++ = F|FT0|TSI; /* F code, seg ind */ ! 857: else ! 858: *relp++ = F|FT1|TSI; /* F data */ ! 859: *relp++ = i; ! 860: *relp++ = data; /* Disp */ ! 861: *relp++ = data >> 8; ! 862: continue; ! 863: } ! 864: /* ! 865: * Symbol relative. ! 866: */ ! 867: *txtp++ = data; ! 868: if (nd != 1) { ! 869: *txtp++ = data >> 8; ! 870: fixup |= OFFSET << 8; /* Loc */ ! 871: } ! 872: if ((op&TPCR) == 0) ! 873: fixup |= M << 8; /* Seg rel */ ! 874: *relp++ = fixup>>8; ! 875: *relp++ = fixup; ! 876: *relp++ = FTARGET|SECWAY|TEI; /* Fix dat */ ! 877: relp = setindex(relp, sp->s_ref); ! 878: } ! 879: if (isvariant(VLINES)) ! 880: outbrace('}'); ! 881: if (notvariant(VLIB)) ! 882: dump(); ! 883: if (isvcsd) ! 884: oglobals(); /* Dump globals */ ! 885: enter(SDATA); /* flush */ ! 886: /* ! 887: * If the size of the SBSS segment is nonzero, ! 888: * use an LIDATA item to get it zeroed when the program is run. ! 889: */ ! 890: if (bss_size != 0) { ! 891: txtp = &txt[0]; ! 892: *txtp++ = sx_data; ! 893: *txtp++ = seg[SBSS].s_mseek; /* Offset */ ! 894: *txtp++ = seg[SBSS].s_mseek >> 8; ! 895: *txtp++ = bss_size; /* Repeat count */ ! 896: *txtp++ = bss_size >> 8; ! 897: *txtp++ = 0; /* Block count */ ! 898: *txtp++ = 0; ! 899: *txtp++ = 1; /* Count */ ! 900: *txtp++ = 0; /* Data */ ! 901: putrecord(LIDATA, txt, 9); /* LIDATA */ ! 902: } ! 903: putrecord(MODEND, modend, sizeof(modend)); /* MODEND */ ! 904: #if VAXFMT ! 905: vaxflush(); ! 906: #endif ! 907: if (isvcsd) { ! 908: if (fseek(ofp, debugdef, 0) == -1) ! 909: cbotch("fixsegdef seek failed"); ! 910: if (islarge) ! 911: putsegdef(BYTE|CCON, seg[SDBG].s_dot, LN_L_M_DEBUG, LN_L_DEBUG); ! 912: else ! 913: putsegdef(BYTE|CCON, seg[SDBG].s_dot, LN_S_M_DEBUG, LN_S_DEBUG); ! 914: } ! 915: } ! 916: ! 917: /* ! 918: * Assign a base address to logical segment s. ! 919: * Round up the segment size and bump dot. ! 920: */ ! 921: newseg(s) ! 922: register s; ! 923: { ! 924: register ADDRESS n; ! 925: ! 926: if (((n = seg[s].s_dot)&1) == 1) ! 927: seg[s].s_dot = ++n; /* round up segment size to word */ ! 928: seg[s].s_mseek = dot; ! 929: dot += n; ! 930: } ! 931: ! 932: /* ! 933: ** Header writing routines. ! 934: */ ! 935: /* ! 936: * Write the list of names record. ! 937: * The LN_... macros defined above must correspond to the order defined here. ! 938: * For SMALL model, the names are: ! 939: * [1] "" ! 940: * [2] "CODE" ! 941: * [3] "DATA" ! 942: * [4] "CONST" ! 943: * [5] "STACK" ! 944: * [6] "MEMORY" ! 945: * [7] "CGROUP" ! 946: * [8] "DGROUP" ! 947: * [9] "DEBUG" (if -VCSD) ! 948: * [10] "module_DEBUG" (if -VCSD) ! 949: * For LARGE model, the names are: ! 950: * [1] "" ! 951: * [2] "module_CODE" ! 952: * [3] "module_DATA" ! 953: * [4] "CODE" ! 954: * [5] "DATA" ! 955: * [6] "DEBUG" (if -VCSD) ! 956: * [7] "module_DEBUG" (if -VCSD) ! 957: */ ! 958: putlnames() ! 959: { ! 960: register char *p1; ! 961: ! 962: p1 = &txt[0]; ! 963: *p1++ = 0; /* "" */ ! 964: if (islarge) { ! 965: p1 = movename(p1, "CODE", 1); ! 966: p1 = movename(p1, "DATA", 1); ! 967: p1 = movename(p1, "CODE", 0); ! 968: p1 = movename(p1, "DATA", 0); ! 969: } else { ! 970: p1 = movename(p1, "CODE", 0); ! 971: p1 = movename(p1, "DATA", 0); ! 972: p1 = movename(p1, "CONST", 0); ! 973: p1 = movename(p1, "STACK", 0); ! 974: p1 = movename(p1, "MEMORY", 0); ! 975: p1 = movename(p1, "CGROUP", 0); ! 976: p1 = movename(p1, "DGROUP", 0); ! 977: } ! 978: if (isvcsd) { ! 979: p1 = movename(p1, "DEBUG", 0); ! 980: p1 = movename(p1, "DEBUG", 1); ! 981: } ! 982: putrecord(LNAMES, txt, p1-txt); ! 983: } ! 984: ! 985: /* ! 986: * If flag==0, move p2 to the supplied buffer p1. ! 987: * If flag==1, move module_p2 to p1. ! 988: */ ! 989: char * ! 990: movename(p1, p2, flag) ! 991: register char *p1; ! 992: char *p2; ! 993: { ! 994: register int n, m; ! 995: ! 996: n = strlen(p2); ! 997: if (flag) { ! 998: m = strlen(module); ! 999: *p1++ = m + 1 + n; /* length of "module_p2" */ ! 1000: strcpy(p1, module); /* copy module name */ ! 1001: p1 += m; ! 1002: *p1++ = '_'; /* append '_' */ ! 1003: } else ! 1004: *p1++ = n; /* length of p2 */ ! 1005: strcpy(p1, p2); /* copy p2 */ ! 1006: return(p1 + n); ! 1007: } ! 1008: ! 1009: /* ! 1010: * This routine formats and outputs a SEGDEF item. ! 1011: * There is no checking for BIG segments (segments that are 64k in size). ! 1012: * The overlay index points to a null name. ! 1013: * Return the location of the first byte of the record. ! 1014: */ ! 1015: long ! 1016: putsegdef(flag, size, seg, class) ! 1017: { ! 1018: long l; ! 1019: register char *bp; ! 1020: ! 1021: l = ftell(ofp); ! 1022: bp = &txt[0]; ! 1023: *bp++ = flag; ! 1024: *bp++ = size; ! 1025: *bp++ = size >> 8; ! 1026: *bp++ = seg; ! 1027: *bp++ = class; ! 1028: *bp = LN_EMPTY; ! 1029: putrecord(SEGDEF, txt, 6); ! 1030: return(l); ! 1031: } ! 1032: ! 1033: /* ! 1034: * Sweep through the symbol table: ! 1035: * 1) Make symbols LSEG relative. ! 1036: * 2) Assign reference numbers. ! 1037: * 3) Output EXTDEF or PUBDEF. ! 1038: */ ! 1039: putsymdef() ! 1040: { ! 1041: register SYM *sp; ! 1042: register int refnum; ! 1043: register int i; ! 1044: ! 1045: refnum = 1; ! 1046: for (i=0; i<NSHASH; ++i) { ! 1047: for (sp = hash2[i]; sp != NULL; sp = sp->s_fp ) { ! 1048: if ((sp->s_flag&S_DEF) != 0) ! 1049: sp->s_value += seg[sp->s_seg].s_mseek; ! 1050: if ((sp->s_flag&S_GBL)!=0 || (sp->s_flag&S_DEF)==0) { ! 1051: sp->s_ref = 0; ! 1052: if ((sp->s_flag&S_DEF) != 0) { ! 1053: putpubdef(sp); ! 1054: } else { ! 1055: sp->s_ref = refnum++; ! 1056: putextdef(sp); ! 1057: } ! 1058: } ! 1059: } ! 1060: } ! 1061: } ! 1062: ! 1063: /* ! 1064: * Put out a PUBDEF item for symbol 'sp'. ! 1065: * All defs are tagged with the group ! 1066: * so that a FTARGET,EI fixup can determine the correct frame. ! 1067: */ ! 1068: putpubdef(sp) ! 1069: register SYM *sp; ! 1070: { ! 1071: register char *bp, *cp; ! 1072: ! 1073: cp = bp = &txt[0]; ! 1074: *bp++ = getgrpindex(sp->s_seg); ! 1075: *bp++ = getsegindex(sp->s_seg); ! 1076: bp = setsymid(bp, sp->s_id); ! 1077: *bp++ = sp->s_value; ! 1078: *bp++ = sp->s_value >> 8; ! 1079: *bp++ = TYPENIL; ! 1080: putrecord(PUBDEF, cp, bp-cp); ! 1081: } ! 1082: ! 1083: /* ! 1084: * Put out an EXTDEF item for symbol 'sp'. ! 1085: */ ! 1086: putextdef(sp) ! 1087: SYM *sp; ! 1088: { ! 1089: register char *bp, *cp; ! 1090: ! 1091: cp = &txt[0]; ! 1092: bp = setsymid(cp, sp->s_id); ! 1093: *bp++ = TYPENIL; ! 1094: putrecord(EXTDEF, cp, bp-cp); ! 1095: } ! 1096: ! 1097: /* ! 1098: * Translate compiler segment codes ! 1099: * to OMF segment index value, using tables. ! 1100: * The table is selected by the model and the ! 1101: * setting of the VROM and VRAM variants. ! 1102: */ ! 1103: getsegindex(s) ! 1104: register int s; ! 1105: { ! 1106: if (s > SBSS) { ! 1107: if (s == SDBG) ! 1108: return(sx_debug); ! 1109: else ! 1110: cbotch("getsegindex, seg=%d", s); ! 1111: } ! 1112: return(segtab[s]); ! 1113: } ! 1114: ! 1115: /* ! 1116: * Like getsegindex(), but returns a reloc-type segment name for CSD. ! 1117: */ ! 1118: segindex(s) register int s; ! 1119: { ! 1120: register int seg; ! 1121: ! 1122: if ((seg = getsegindex(s)) == sx_code) ! 1123: return(PURCODE); ! 1124: else if (seg == sx_data || (!islarge && seg == SX_S_CONST)) ! 1125: return(PURDATA); ! 1126: cbotch("segindex, s=%x, seg=%x\n", s, seg); ! 1127: } ! 1128: ! 1129: /* ! 1130: * Translate compiler segment codes ! 1131: * to OMF group index value, using table and model. ! 1132: */ ! 1133: getgrpindex(s) ! 1134: register int s; ! 1135: { ! 1136: return (islarge ? 0 : grpindex[s]); ! 1137: } ! 1138: ! 1139: /* ! 1140: ** Debug information processors. ! 1141: */ ! 1142: /* ! 1143: * Read debug table item(s) into memory. ! 1144: */ ! 1145: getdlab() ! 1146: { ! 1147: register DBGT *dp; ! 1148: static int refnum = 0; ! 1149: ! 1150: dp = getdbgt(); ! 1151: ! 1152: /* This should be done in cc0 */ ! 1153: ! 1154: if (isvariant(VLIB)) { ! 1155: switch (dp->d_class) { ! 1156: case DC_TYPE: ! 1157: case DC_STAG: ! 1158: case DC_UTAG: ! 1159: case DC_ETAG: ! 1160: return; ! 1161: } ! 1162: } ! 1163: if (dp->d_class == DC_LINE || dp->d_class == DC_LAB) ! 1164: dp->d_ref = refnum; ! 1165: ! 1166: refnum += 1; ! 1167: if (dbase == NULL) ! 1168: dbase = dp; ! 1169: if (dnext != NULL) ! 1170: dnext->d_dp = dp; ! 1171: dbrpt("enter", dp); ! 1172: while (dp->d_dp != NULL) { ! 1173: dp = dp->d_dp; ! 1174: dbrpt("enter", dp); ! 1175: } ! 1176: dnext = dp; ! 1177: if (dp->d_class == DC_FILE) ! 1178: outbrace('{'); ! 1179: } ! 1180: ! 1181: /* ! 1182: * Read in debug items translating into loader type syntax. ! 1183: * Member definitions are fetched recursively. ! 1184: * If a tag or type definition, the member definitions are appended to the ! 1185: * node surrounded by "{" and "}" nodes. ! 1186: * If not a tag definition, the member definitions are discarded. ! 1187: * In either case, the member types are appended to the type of the ! 1188: * parent node. ! 1189: */ ! 1190: #define DSZ 512 ! 1191: DBGT * ! 1192: getdbgt() ! 1193: { ! 1194: register int n; ! 1195: register char *dptr; ! 1196: DBGT d; ! 1197: char data[DSZ]; ! 1198: int value, width, offs; ! 1199: int typet, subt, membs; ! 1200: char *sdp; ! 1201: ! 1202: d.d_dp = NULL; ! 1203: d.d_ref = -1; ! 1204: d.d_flag = D_LCL; ! 1205: d.d_level = level; ! 1206: d.d_seg = LASTSEG; ! 1207: d.d_cseg = 0; ! 1208: d.d_value = 0; ! 1209: d.d_size = 0; ! 1210: width = membs = 0; ! 1211: ! 1212: /* ! 1213: * Loop to read entire record: ! 1214: * class, optional value, name, type. ! 1215: */ ! 1216: dptr = data; ! 1217: for (typet = 0; ; typet += 1) { ! 1218: ! 1219: if (dptr >= data+DSZ) { ! 1220: dbrpt("1", &d); ! 1221: cbotch("getdbgt buffer"); ! 1222: } ! 1223: ! 1224: n = bget(); ! 1225: if (n < DX_MEMBS) ! 1226: value = iget() * NBPBYTE; ! 1227: else if (n < DC_SEX) ! 1228: ; ! 1229: else { ! 1230: dline = iget(); ! 1231: if (n < DC_AUTO) ! 1232: ; ! 1233: else if (n < DC_MOS) ! 1234: value = iget(); ! 1235: else { ! 1236: width = bget(); ! 1237: offs = bget(); ! 1238: value = iget(); ! 1239: } ! 1240: } ! 1241: subt = 0; ! 1242: ! 1243: switch (n) { ! 1244: ! 1245: /* ! 1246: * Classes: fetch values and set flags. ! 1247: */ ! 1248: case DC_SEX: ! 1249: d.d_flag |= D_NAM; ! 1250: goto setclass; ! 1251: ! 1252: case DC_GDEF: ! 1253: case DC_GREF: ! 1254: d.d_flag = D_GBL|D_NAM; ! 1255: goto setclass; ! 1256: ! 1257: case DC_ETAG: ! 1258: d.d_flag |= D_ENU; ! 1259: strcpy(dptr, "enum "); ! 1260: dptr += 5; ! 1261: goto tag; ! 1262: case DC_STAG: ! 1263: strcpy(dptr, "struct "); ! 1264: dptr += 7; ! 1265: goto tag; ! 1266: case DC_UTAG: ! 1267: strcpy(dptr, "union "); ! 1268: dptr += 6; ! 1269: case DC_TYPE: ! 1270: tag: ! 1271: d.d_flag = (level == 0) ? D_TAG|D_GBL ! 1272: : D_TAG|D_LCL; ! 1273: d.d_seg = TYPESYM; ! 1274: goto setclass; ! 1275: ! 1276: case DC_FILE: ! 1277: d.d_seg = PURCODE; ! 1278: goto setclass; ! 1279: ! 1280: case DC_AUTO: ! 1281: d.d_seg = L_STACK; ! 1282: d.d_value = value; ! 1283: goto setclass; ! 1284: ! 1285: case DC_SIN: ! 1286: d.d_flag |= D_LAB; ! 1287: goto setclass; ! 1288: ! 1289: case DC_LAB: ! 1290: goto setclass; ! 1291: ! 1292: case DC_REG: ! 1293: d.d_seg = L_REG; ! 1294: d.d_value = value; ! 1295: goto setclass; ! 1296: ! 1297: case DC_PREG: ! 1298: if (level == 0) { ! 1299: level++; ! 1300: outbrace('{'); ! 1301: } ! 1302: d.d_seg = L_REG; ! 1303: d.d_value = value; ! 1304: goto setclass; ! 1305: ! 1306: case DC_MOE: ! 1307: d.d_seg = ABSLUTE; ! 1308: d.d_value = value; ! 1309: goto setclass; ! 1310: ! 1311: case DC_PAUTO: ! 1312: if (level == 0) { ! 1313: level++; ! 1314: outbrace('{'); ! 1315: } ! 1316: d.d_seg = P_STACK; ! 1317: d.d_value = value; ! 1318: goto setclass; ! 1319: ! 1320: case DC_LINE: ! 1321: goto setclass; ! 1322: ! 1323: case DC_MOS: ! 1324: case DC_MOU: ! 1325: d.d_seg = FLD_OFF; ! 1326: d.d_value = value * NBPBYTE + offs; ! 1327: goto setclass; ! 1328: ! 1329: /* ! 1330: * Set the class field, read the name; ! 1331: * Lookup globals and statics. ! 1332: */ ! 1333: setclass: ! 1334: d.d_class = n; ! 1335: while (*dptr++ = bget()) ! 1336: ; ! 1337: if ((d.d_flag&(D_NAM|D_LAB)) != 0) { ! 1338: register SYM *sp; ! 1339: ! 1340: if ((d.d_flag&D_NAM) != 0) ! 1341: sp = glookup(data, 0); ! 1342: else ! 1343: sp = llookup(value, 0); ! 1344: if ((sp->s_flag&S_DEF) != 0) { ! 1345: d.d_cseg = sp->s_seg; ! 1346: d.d_seg = segindex(sp->s_seg); ! 1347: d.d_value = sp->s_value; ! 1348: } ! 1349: #if COMMON ! 1350: else if (sp->s_value != 0) { ! 1351: d.d_seg = BLDATA|Cb; ! 1352: d.d_value = sp->s_value; ! 1353: } ! 1354: #endif ! 1355: if ((d.d_flag&D_GBL) != 0) ! 1356: d.d_ref = sp->s_ref; ! 1357: } ! 1358: continue; ! 1359: ! 1360: /* ! 1361: * Types: write type and prepare for trailing data. ! 1362: * For files and lines, write a phony type. ! 1363: */ ! 1364: case DT_NONE: ! 1365: if (d.d_class == DC_FILE) { ! 1366: register char *p; ! 1367: ! 1368: *dptr++ = STRINGt; ! 1369: p = "source file"; ! 1370: while (*dptr++ = *p++) ! 1371: ; ! 1372: } ! 1373: if (d.d_class == DC_LINE) { ! 1374: *dptr++ = 6; /* Line */ ! 1375: *dptr++ = dline; ! 1376: *dptr++ = dline >> 8; ! 1377: *dptr++ = 0; /* Column */ ! 1378: *dptr++ = 0; /* Flag */ ! 1379: *dptr++ = 0; /* Saved instruction */ ! 1380: *dptr++ = 0; ! 1381: } ! 1382: break; ! 1383: ! 1384: case DT_CHAR: ! 1385: case DT_SHORT: ! 1386: case DT_INT: ! 1387: case DT_LONG: ! 1388: n = Integer; ! 1389: goto getwidth; ! 1390: ! 1391: case DT_UCHAR: ! 1392: case DT_USHORT: ! 1393: case DT_UINT: ! 1394: case DT_ULONG: ! 1395: n = Natural; ! 1396: goto getwidth; ! 1397: ! 1398: case DT_FLOAT: ! 1399: case DT_DOUBLE: ! 1400: n = Rational; ! 1401: goto settype; ! 1402: ! 1403: case DT_VOID: ! 1404: n = Void; ! 1405: goto settype; ! 1406: ! 1407: case DT_STRUCT: ! 1408: membs = n; ! 1409: n = Record; ! 1410: sdp = dptr; ! 1411: goto settype; ! 1412: ! 1413: case DT_UNION: ! 1414: membs = n; ! 1415: n = Union; ! 1416: sdp = dptr; ! 1417: goto settype; ! 1418: ! 1419: case DT_ENUM: ! 1420: d.d_flag |= D_ENU; ! 1421: membs = n; ! 1422: n = Natural; ! 1423: sdp = dptr; ! 1424: goto settype; ! 1425: ! 1426: getwidth: ! 1427: if (width) ! 1428: value = width; ! 1429: ! 1430: settype: ! 1431: *dptr++ = 1; ! 1432: *dptr++ = n; ! 1433: if (n != Void) { ! 1434: if (value == 0) ! 1435: *dptr++ = ANYt; ! 1436: else if (value <= 0377) { ! 1437: *dptr++ = 1; ! 1438: *dptr++ = value; ! 1439: } else { ! 1440: *dptr++ = 2; ! 1441: *dptr++ = value; ! 1442: *dptr++ = value >> 8; ! 1443: } ! 1444: } ! 1445: if (subt) { ! 1446: *dptr++ = TYPEt; ! 1447: continue; ! 1448: } ! 1449: if (membs) { ! 1450: --typet; ! 1451: continue; ! 1452: } ! 1453: break; ! 1454: ! 1455: /* ! 1456: * Dimensions: as for types, but flag for subtypes. ! 1457: */ ! 1458: case DD_PTR: ! 1459: n = Pointer; ! 1460: ++subt; ! 1461: goto settype; ! 1462: ! 1463: case DD_FUNC: ! 1464: n = Proc; ! 1465: ++subt; ! 1466: goto settype; ! 1467: ! 1468: case DD_ARRAY: ! 1469: n = Array; ! 1470: ++subt; ! 1471: goto settype; ! 1472: ! 1473: /* ! 1474: * Trailing struct/union/enum data. ! 1475: */ ! 1476: case DX_NAME: ! 1477: dptr = sdp; ! 1478: *dptr++ = STRINGt; ! 1479: switch (membs) { ! 1480: case DT_STRUCT: ! 1481: strcpy(dptr, "struct "); ! 1482: dptr += 7; ! 1483: break; ! 1484: case DT_UNION: ! 1485: strcpy(dptr, "union "); ! 1486: dptr += 6; ! 1487: break; ! 1488: case DT_ENUM: ! 1489: strcpy(dptr, "enum "); ! 1490: dptr += 5; ! 1491: } ! 1492: while (*dptr++ = bget()) ! 1493: ; ! 1494: membs = 0; ! 1495: break; ! 1496: ! 1497: case DX_MEMBS: ! 1498: level += 1; ! 1499: dptr = getmembs(&d, data, dptr); ! 1500: level -= 1; ! 1501: membs = 0; ! 1502: break; ! 1503: ! 1504: default: ! 1505: cbotch("getdbgt: %d", n); ! 1506: } ! 1507: /* ! 1508: * Terminate types. ! 1509: */ ! 1510: if (dptr + typet >= data + DSZ) { ! 1511: dbrpt("2", &d); ! 1512: cbotch("getdbgt buffer"); ! 1513: } ! 1514: while (--typet >= 0) ! 1515: *dptr++ = 0; ! 1516: break; ! 1517: } ! 1518: ! 1519: /* ! 1520: * Check level change. ! 1521: */ ! 1522: if (data[0] == '{') { ! 1523: if (level++ == 0) { ! 1524: d.d_level = level++; ! 1525: outbrace('{'); ! 1526: } ! 1527: } ! 1528: else if (data[0] == '}') ! 1529: level -= 1; ! 1530: ! 1531: /* ! 1532: * Copy into dynamic storage. ! 1533: */ ! 1534: d.d_size = dptr - data; ! 1535: return (newdbgt(&d, data)); ! 1536: } ! 1537: ! 1538: /* ! 1539: * Enter a new output segment. ! 1540: */ ! 1541: enter(newseg) ! 1542: register int newseg; ! 1543: { ! 1544: if (dotseg == newseg) ! 1545: return; /* already in newseg */ ! 1546: notenuf(); /* flush */ ! 1547: seg[dotseg].s_dot = dot; /* save current dot */ ! 1548: dotseg = newseg; /* reset dotseg */ ! 1549: dot = seg[dotseg].s_dot; /* and dot */ ! 1550: } ! 1551: ! 1552: /* ! 1553: * Read a debug relocation item and patch current 'dot' ! 1554: * into the appropriate debug/symbol table item. ! 1555: * If the debug item is '}' and level 2, then dump the batch of locals. ! 1556: * If the debug item is '}' and level 1, then dump the type definitions. ! 1557: */ ! 1558: getdloc() ! 1559: { ! 1560: register DBGT *dp; ! 1561: register int ref; ! 1562: ! 1563: ref = iget(); ! 1564: for (dp = dbase; ; dp = dp->d_dp) { ! 1565: if (dp == NULL) ! 1566: cbotch("getdloc: %d", ref); ! 1567: if ((dp->d_flag&D_GBL) != 0) ! 1568: continue; ! 1569: if (dp->d_ref == ref) ! 1570: break; ! 1571: } ! 1572: dp->d_cseg = dotseg; ! 1573: dp->d_seg = segindex(dotseg); ! 1574: dp->d_value = dot; ! 1575: ! 1576: dbrpt("reloc", dp); ! 1577: if (dp->d_data[0] == '}' && dp->d_level <= 2) { ! 1578: outbrace('}'); ! 1579: level--; ! 1580: dump(); ! 1581: } ! 1582: } ! 1583: ! 1584: /* ! 1585: * Dump the locals and type definitions. ! 1586: */ ! 1587: dump() ! 1588: { ! 1589: register DBGT *dp, **dpp; ! 1590: int saveseg; ! 1591: ! 1592: saveseg = dotseg; ! 1593: enter(SDBG); ! 1594: dpp = &dbase; ! 1595: dnext = NULL; ! 1596: while ((dp = *dpp) != NULL) { ! 1597: if ((dp->d_flag&D_LCL) != 0) { ! 1598: dbrpt("write", dp); ! 1599: osymbol(dp, -1); ! 1600: dp->d_flag &= ~D_LCL; ! 1601: } ! 1602: if ((dp->d_flag&D_GBL) == 0) { ! 1603: dbrpt("free", dp); ! 1604: *dpp = dp->d_dp; ! 1605: free(dp); ! 1606: } else { ! 1607: dbrpt("save", dp); ! 1608: dnext = dp; ! 1609: dpp = &dp->d_dp; ! 1610: } ! 1611: } ! 1612: enter(saveseg); ! 1613: } ! 1614: ! 1615: /* ! 1616: * Write out global symbol definitions and references. ! 1617: */ ! 1618: oglobals() ! 1619: { ! 1620: register DBGT *dp, *dp1; ! 1621: ! 1622: enter(SDBG); ! 1623: for (dp = dbase; dp != NULL; dp = dp1) { ! 1624: dp1 = dp->d_dp; ! 1625: dbrpt("write", dp); ! 1626: if (dp->d_seg == TYPESYM || dp->d_seg == ABSLUTE) ! 1627: osymbol(dp, 0); ! 1628: else ! 1629: osymbol(dp, dp->d_ref); ! 1630: dbrpt("free", dp); ! 1631: free(dp); ! 1632: } ! 1633: notenuf(); ! 1634: } ! 1635: ! 1636: /* ! 1637: * Write out a symbol to the symbol or debug table. ! 1638: * TYPESYM and ABSLUTE symbols have refnum 0. ! 1639: * Debug table symbols have negative refnums and may require relocation. ! 1640: */ ! 1641: osymbol(dp, refnum) ! 1642: register DBGT *dp; ! 1643: { ! 1644: register char *cp; ! 1645: unsigned char seg; ! 1646: int nd, nr, fixup, fixseg; ! 1647: ! 1648: /* Write scope/refnum or seg/value+relocation expression */ ! 1649: seg = dp->d_seg; ! 1650: nr = 0; ! 1651: #if 0 ! 1652: printf("osymbol(%s, %x) seg=%x cseg=%x d_size=%x\n", ! 1653: dp->d_data, refnum, seg, dp->d_cseg, dp->d_size); ! 1654: #endif ! 1655: if (refnum >= 0) { ! 1656: if (seg == LASTSEG) { ! 1657: for (cp=dp->d_data; *cp++; ) ! 1658: ; /* skip the name */ ! 1659: seg = (*cp++ == 1 && *cp++ == Proc) ? PURCODE : PURDATA; ! 1660: fixseg = -1; /* external fixup */ ! 1661: } else ! 1662: fixseg = getsegindex(dp->d_cseg); ! 1663: if (seg != TYPESYM && seg != ABSLUTE) ! 1664: nr = islarge ? 10 : 6; ! 1665: } else if (refnum < 0) { ! 1666: if (seg < SUMMARY && seg != TYPESYM && seg != ABSLUTE) { ! 1667: nr = islarge ? 10 : 6; ! 1668: fixseg = getsegindex(dp->d_cseg); ! 1669: } ! 1670: else ! 1671: fixseg = sx_code; ! 1672: } ! 1673: enuf(5, nr); ! 1674: dot += 5; /* bump dot */ ! 1675: *txtp++ = seg; /* reloc-style segment */ ! 1676: if (fixseg == -1) { /* extern fixup */ ! 1677: if (islarge) { ! 1678: fixup = txtp - (txt+3); ! 1679: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 1680: *relp++ = fixup; ! 1681: *relp++ = FTARGET|SECWAY|TEI; ! 1682: relp = setindex(relp, refnum); ! 1683: } ! 1684: *txtp++ = 0; ! 1685: *txtp++ = 0; ! 1686: fixup = txtp - (txt+3); ! 1687: *relp++ = LOCAT|M|OFFSET|(fixup>>8); ! 1688: *relp++ = fixup; ! 1689: *relp++ = FTARGET|SECWAY|TEI; ! 1690: relp = setindex(relp, refnum); ! 1691: *txtp++ = 0; ! 1692: *txtp++ = 0; ! 1693: } else { ! 1694: if (nr != 0 && islarge) { /* segment fixup */ ! 1695: fixup = txtp - (txt+3); ! 1696: *relp++ = LOCAT|M|BASE|(fixup>>8); ! 1697: *relp++ = fixup; ! 1698: *relp++ = FTARGET|SECWAY|TSI; ! 1699: *relp++ = fixseg; ! 1700: } ! 1701: *txtp++ = 0; ! 1702: *txtp++ = 0; /* segment text */ ! 1703: if (nr != 0) { /* offset text and fixup */ ! 1704: fixup = txtp - (txt+3); ! 1705: *relp++ = LOCAT|M|OFFSET|(fixup>>8); ! 1706: *relp++ = fixup; ! 1707: if (fixseg == sx_code) ! 1708: *relp++ = F|FT0|TSI; /* fixup F code, seg index */ ! 1709: else ! 1710: *relp++ = F|FT1|TSI; /* fixup F data, seg index */ ! 1711: *relp++ = fixseg; ! 1712: *relp++ = dp->d_value; ! 1713: *relp++ = dp->d_value >> 8; ! 1714: *txtp++ = 0; ! 1715: *txtp++ = 0; ! 1716: } else { ! 1717: *txtp++ = dp->d_value; ! 1718: *txtp++ = dp->d_value >> 8; /* nonrelocated offset */ ! 1719: } ! 1720: } ! 1721: ! 1722: /* Write name */ ! 1723: cp = dp->d_data; ! 1724: nd = dp->d_size; ! 1725: enuf(nd, 0); ! 1726: dot += nd; ! 1727: do { ! 1728: *txtp++ = *cp; ! 1729: --nd; ! 1730: } while (*cp++); ! 1731: ! 1732: /* Type */ ! 1733: while (--nd >= 0) ! 1734: *txtp++ = *cp++; /* type */ ! 1735: } ! 1736: ! 1737: /* ! 1738: * Read a list of members of a union/struct/enum. ! 1739: * If struct/union, append member types to caller's buffer. ! 1740: * If making a debug table: ! 1741: * If struct/union tag definition, bracket member definitions. ! 1742: * If enum tag, make member type into "enum tag". ! 1743: */ ! 1744: char * ! 1745: getmembs(dp0, bb, bp) ! 1746: DBGT *dp0; ! 1747: char *bb; ! 1748: register char *bp; ! 1749: { ! 1750: int nmembs, n, istag, isenu, isgbl; ! 1751: char *sbp; ! 1752: register DBGT *dp; ! 1753: DBGT **dpp; ! 1754: register char *p; ! 1755: static DBGT dbrace = { ! 1756: NULL, /* d_dp */ ! 1757: -1, /* d_ref */ ! 1758: DT_NONE, /* d_class */ ! 1759: D_LCL, /* d_flag */ ! 1760: 0, /* d_level */ ! 1761: TYPESYM, /* d_seg */ ! 1762: 0, /* d_cseg */ ! 1763: 0, /* d_value */ ! 1764: 3 /* d_size */ ! 1765: }; ! 1766: ! 1767: dp = dp0; ! 1768: nmembs = bget(); ! 1769: istag = (dp->d_flag&D_TAG) != 0; ! 1770: isenu = (dp->d_flag&D_ENU) != 0; ! 1771: isgbl = (dp->d_flag&D_GBL) != 0; ! 1772: if (isenu) { ! 1773: sbp = bp; ! 1774: isenu = strlen(bb) + 1 + 1; ! 1775: } ! 1776: if ( ! isenu) { ! 1777: #if DO_STRUCT_TYPE ! 1778: /* Note that this blows up for nmembs > 255 anyway */ ! 1779: *bp++ = 1; ! 1780: *bp++ = nmembs; ! 1781: #else ! 1782: *bp++ = 1; ! 1783: *bp++ = 1; ! 1784: *bp++ = ANYt; ! 1785: #endif ! 1786: dpp = &dp->d_dp; ! 1787: dp = *dpp = newdbgt(&dbrace, "{\0\0"); ! 1788: if (isgbl) ! 1789: dp->d_flag ^= D_GBL|D_LCL; ! 1790: } ! 1791: dpp = &dp->d_dp; ! 1792: while (--nmembs >= 0) { ! 1793: /* Note that dp could be a tagless structure, ie a list */ ! 1794: dp = *dpp = getdbgt(); ! 1795: if (isgbl) ! 1796: dp->d_flag ^= D_GBL|D_LCL; ! 1797: n = dp->d_size; ! 1798: p = dp->d_data; ! 1799: if (isenu && istag && isvcsd) { ! 1800: /* Enumerators eschew member lists */ ! 1801: dp->d_size += isenu; ! 1802: dp = newdbgt(dp, dp->d_data); ! 1803: bp = dp->d_data; ! 1804: while (*bp++) ! 1805: ; ! 1806: *bp++ = STRINGt; ! 1807: p = bb; ! 1808: while (*bp++ = *p++) ! 1809: ; ! 1810: *bp++ = 0; ! 1811: free(*dpp); ! 1812: *dpp = dp; ! 1813: bp = sbp; ! 1814: } ! 1815: #if DO_STRUCT_TYPE ! 1816: if ( ! isenu) { ! 1817: do { ! 1818: --n; ! 1819: } while (*p++); ! 1820: *bp++ = TYPEt; ! 1821: if (bp + n >= bb + DSZ) { ! 1822: dbrpt("3", dp); ! 1823: cbotch("getdbgt buffer"); ! 1824: } ! 1825: do { ! 1826: *bp++ = *p++; ! 1827: } while (--n > 0); ! 1828: } ! 1829: #endif ! 1830: if (istag && isvcsd) ! 1831: dpp = &dp->d_dp; ! 1832: else ! 1833: free(*dpp); ! 1834: } ! 1835: if ( ! isenu) { ! 1836: dp = *dpp = newdbgt(&dbrace, "}\0\0"); ! 1837: dpp = &dp->d_dp; ! 1838: if (isgbl) ! 1839: dp->d_flag ^= D_GBL|D_LCL; ! 1840: } ! 1841: *dpp = NULL; ! 1842: return (bp); ! 1843: } ! 1844: ! 1845: DBGT * ! 1846: newdbgt(dp, cp) ! 1847: DBGT *dp; ! 1848: register char *cp; ! 1849: { ! 1850: register DBGT *ndp; ! 1851: register char *ncp; ! 1852: register int n; ! 1853: ! 1854: n = dp->d_size; ! 1855: if ((ndp = (DBGT *)malloc(sizeof(DBGT) + n)) == NULL) ! 1856: cnomem("newdbgt"); ! 1857: *ndp = *dp; ! 1858: for (ncp = ndp->d_data; --n >= 0; *ncp++ = *cp++) ! 1859: ; ! 1860: return (ndp); ! 1861: } ! 1862: ! 1863: /* ! 1864: * Output a debug brace. ! 1865: */ ! 1866: outbrace(c) ! 1867: int c; ! 1868: { ! 1869: DBGT *dp; ! 1870: ! 1871: if ((dp = (DBGT *)calloc(1, sizeof(DBGT) + 10)) == NULL) ! 1872: cnomem("outbrace"); ! 1873: dp->d_class = DC_LINE; ! 1874: dp->d_flag = D_LCL; ! 1875: dp->d_seg = segindex(SCODE); ! 1876: dp->d_value = ( dotseg == SCODE ? dot : seg[SCODE].s_dot); ! 1877: dp->d_size = 10; ! 1878: dp->d_data[0] = c; ! 1879: *(dp->d_data + 2) = 6; ! 1880: *(dp->d_data + 3) = dline; ! 1881: *(dp->d_data + 4) = dline >> 8; ! 1882: if (dnext != NULL) ! 1883: dnext->d_dp = dp; ! 1884: dnext = dp; ! 1885: } ! 1886: ! 1887: #if !TINY ! 1888: _dbrpt(p, dp) ! 1889: char *p; ! 1890: register DBGT *dp; ! 1891: { ! 1892: if (xflag > 5) ! 1893: printf("%5s: %-10s %2x %2d %2x %2x %2x %2x %04x %2x\n", ! 1894: p, ! 1895: dp->d_data, ! 1896: dp->d_class, ! 1897: dp->d_ref, ! 1898: dp->d_flag, ! 1899: dp->d_level, ! 1900: dp->d_seg, ! 1901: dp->d_cseg, ! 1902: dp->d_value, ! 1903: dp->d_size ! 1904: ); ! 1905: } ! 1906: ! 1907: #endif ! 1908: ! 1909: /* ! 1910: ** Low level record formatting. ! 1911: */ ! 1912: /* ! 1913: * Put OMF index i at cp and return updated cp. ! 1914: */ ! 1915: char * ! 1916: setindex(cp, i) ! 1917: register char *cp; ! 1918: register unsigned i; ! 1919: { ! 1920: if (i >= 128) ! 1921: *cp++ = (i >> 8) | 0x80; ! 1922: *cp++ = i; ! 1923: return (cp); ! 1924: } ! 1925: ! 1926: /* ! 1927: * Move the name pointed to by 'cp' into an OMF record. ! 1928: * The 'bp' argument is the OMF buffer pointer. ! 1929: * Return the updated value of 'bp'. ! 1930: */ ! 1931: char * ! 1932: setsymid(bp, cp) ! 1933: register char *bp; ! 1934: char *cp; ! 1935: { ! 1936: register n; ! 1937: ! 1938: if ((n=strlen(cp)) > 39) { ! 1939: cwarn("symbol \"%s\" truncated to 39 characters", cp); ! 1940: n = 39; ! 1941: } ! 1942: *bp++ = n; ! 1943: strncpy(bp, cp, n); ! 1944: return (bp + n); ! 1945: } ! 1946: ! 1947: #if VAXFMT ! 1948: putbyte(b) ! 1949: register b; ! 1950: { ! 1951: if (vaxptr >= &vaxbuf[NVDATA]) { ! 1952: vaxflush(); ! 1953: vaxptr = vaxbuf; ! 1954: } ! 1955: *vaxptr++ = b; ! 1956: } ! 1957: #else ! 1958: #define putbyte(b) bput(b); ! 1959: #endif ! 1960: ! 1961: /* ! 1962: * Put a record. ! 1963: * The 'type' argument is the record type. ! 1964: * The body of the record starts at 'p' and is 'n' bytes long. ! 1965: * The checksum is appended. ! 1966: */ ! 1967: putrecord(type, p, n) ! 1968: char *p; ! 1969: int type, n; ! 1970: { ! 1971: register int i, checksum; ! 1972: ! 1973: ++n; /* +1 for the checksum */ ! 1974: checksum = type + n + (n>>8); /* sum of first three bytes */ ! 1975: putbyte(type); ! 1976: putbyte(n); ! 1977: putbyte(n>>8); ! 1978: --n; /* restore actual byte count */ ! 1979: while (n--) { ! 1980: putbyte(i = *p++); ! 1981: checksum += i; ! 1982: } ! 1983: putbyte(-checksum); ! 1984: } ! 1985: ! 1986: /* ! 1987: ** Output buffering. ! 1988: */ ! 1989: /* ! 1990: * Check to see if there is enough room in the text and relocation buffers ! 1991: * to hold 'nt' bytes of text and 'nr' bytes of relocation. ! 1992: * notenuf() flushes the buffers if necessary. ! 1993: */ ! 1994: enuf(nt, nr) ! 1995: { ! 1996: if (txtp+nt>&txt[NTXT] || relp+nr>&rel[NREL]) { ! 1997: notenuf(); ! 1998: if (nt > NTXT-3 || nr > NREL) ! 1999: cbotch("enuf(%d, %d)", nt, nr); ! 2000: } ! 2001: if (txtp == txt) { ! 2002: *txtp++ = getsegindex(dotseg); ! 2003: *txtp++ = dot; ! 2004: *txtp++ = dot >> 8; ! 2005: } ! 2006: } ! 2007: ! 2008: /* ! 2009: * Flush the buffer. ! 2010: */ ! 2011: notenuf() ! 2012: { ! 2013: register n; ! 2014: ! 2015: if ((n = txtp-txt) > 3) { ! 2016: putrecord(LEDATA, txt, n); ! 2017: if ((n = relp-rel) != 0) { ! 2018: putrecord(FIXUPP, rel, n); ! 2019: relp = rel; ! 2020: } ! 2021: } ! 2022: txtp = txt; ! 2023: } ! 2024: ! 2025: #if VAXFMT ! 2026: /* ! 2027: * Flush out a record on the VAX. The record is a standard, ! 2028: * RMS variable length record. This routine checks for no bytes ! 2029: * in the buffer, so it can be unconditionally called at the ! 2030: * end to flush the buffer out. ! 2031: * The record is padded out to NVDATA bytes with zeros. This ! 2032: * only happens on the last block; the data beyond the end ! 2033: * is zeroed. ! 2034: */ ! 2035: vaxflush() ! 2036: { ! 2037: register int n; ! 2038: ! 2039: if ((n = vaxptr-vaxbuf) != 0) { ! 2040: if (fwrite(vaxbuf, n, 1, ofp) != 1 ! 2041: || fflush(ofp) == EOF) ! 2042: cfatal("output write error"); ! 2043: } ! 2044: } ! 2045: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.