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