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