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