15500Slinton /* Copyright (c) 1982 Regents of the University of California */
25500Slinton 
3*5741Slinton static char sccsid[] = "@(#)readobj.c 1.4 02/10/82";
45500Slinton 
55500Slinton /*
65500Slinton  * Read in the namelist from the obj file.
75500Slinton  */
85500Slinton 
95500Slinton #include "defs.h"
105500Slinton #include "sym.h"
115500Slinton #include "symtab.h"
125500Slinton #include "object.h"
135569Slinton #include "objfmt.h"
145649Slinton #include "main.h"
155500Slinton #include "mappings.h"
165500Slinton #include "mappings/filetab.h"
175500Slinton #include "mappings/linetab.h"
18*5741Slinton #include "objsym.rep"
195500Slinton 
205500Slinton #define MAXSYMNO 2000
215500Slinton 
225500Slinton char *objname = "obj";
235500Slinton 
245500Slinton LOCAL SYM *sym[MAXSYMNO];
255500Slinton 
265500Slinton readobj(file)
275500Slinton char *file;
285500Slinton {
29*5741Slinton     register FILE *fp;
30*5741Slinton     struct pxhdr hdr;
315500Slinton 
32*5741Slinton     if ((fp = fopen(file, "r")) == NIL) {
33*5741Slinton 	panic("can't open %s", file);
34*5741Slinton     }
35*5741Slinton     get(fp, hdr);
36*5741Slinton     if (hdr.magicnum != MAGICNUM) {
37*5741Slinton 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
385569Slinton 	get(fp, hdr);
395649Slinton 	if (hdr.magicnum != MAGICNUM) {
40*5741Slinton 	    fatal("%s is not a Pascal object file", file);
415649Slinton 	}
42*5741Slinton     }
43*5741Slinton     if (hdr.symtabsize == 0) {
44*5741Slinton 	fatal("%s doesn't have symbolic information", file);
45*5741Slinton     }
46*5741Slinton     objsize = hdr.objsize;
47*5741Slinton     fseek(fp, (long) objsize, 1);
48*5741Slinton     if (get(fp, nlhdr) != 1) {
49*5741Slinton 	panic("can't read nlhdr");
50*5741Slinton     }
51*5741Slinton     if (option('h')) {
52*5741Slinton 	printf("\nHeader information:\n");
53*5741Slinton 	printf("\tobject size %d\n", objsize);
54*5741Slinton 	printf("\tsymtab size %d\n", hdr.symtabsize);
55*5741Slinton 	printf("\tstringsize  %d\n", nlhdr.stringsize);
56*5741Slinton 	printf("\tnsyms       %d\n", nlhdr.nsyms);
57*5741Slinton 	printf("\tnfiles      %d\n", nlhdr.nfiles);
58*5741Slinton 	printf("\tnlines      %d\n", nlhdr.nlines);
59*5741Slinton     }
60*5741Slinton     stringtab = alloc(nlhdr.stringsize, char);
61*5741Slinton     fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
62*5741Slinton     readsyms(fp);
63*5741Slinton     readfiles(fp);
64*5741Slinton     readlines(fp);
65*5741Slinton     fclose(fp);
665500Slinton }
675500Slinton 
685500Slinton /*
695500Slinton  * allocate and read in file name information table
705500Slinton  */
715500Slinton 
725500Slinton LOCAL readfiles(fp)
735500Slinton register FILE *fp;
745500Slinton {
75*5741Slinton     register int i;
76*5741Slinton     register FILETAB *ftp;
77*5741Slinton     FILETAB temp;
78*5741Slinton     ADDRESS prevaddr;
795500Slinton 
80*5741Slinton     filetab = alloc(nlhdr.nfiles, FILETAB);
81*5741Slinton     ftp = &filetab[0];
82*5741Slinton     prevaddr = 0;
83*5741Slinton     for (i = 0; i < nlhdr.nfiles; i++) {
84*5741Slinton 	fread(&temp, sizeof(FILETAB), 1, fp);
85*5741Slinton 	if (temp.addr != prevaddr) {
86*5741Slinton 	    ftp++;
875500Slinton 	}
88*5741Slinton 	*ftp = temp;
89*5741Slinton 	ftp->filename += (int) stringtab;
90*5741Slinton 	prevaddr = ftp->addr;
91*5741Slinton     }
92*5741Slinton     nlhdr.nfiles = (ftp - &filetab[0]) + 1;
93*5741Slinton     skimsource(filetab[0].filename);
94*5741Slinton     dotpfile = filetab[0].filename;
955500Slinton }
965500Slinton 
975500Slinton /*
985500Slinton  * allocate and read in line number information table
995500Slinton  */
1005500Slinton 
1015500Slinton LOCAL readlines(fp)
1025500Slinton FILE *fp;
1035500Slinton {
104*5741Slinton     register LINENO oline;
105*5741Slinton     register ADDRESS oaddr;
106*5741Slinton     register LINETAB *lp;
107*5741Slinton     FILETAB *ftp;
108*5741Slinton     OBJLINE info;
1095500Slinton 
110*5741Slinton     if (nlhdr.nlines == 0) {
111*5741Slinton 	return;
112*5741Slinton     }
113*5741Slinton     linetab = alloc(nlhdr.nlines, LINETAB);
114*5741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
115*5741Slinton 	lp->line = 0;
116*5741Slinton     }
117*5741Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
118*5741Slinton 	linetab[ftp->lineindex].line = ftp->line;
119*5741Slinton     }
120*5741Slinton     oline = 0;
121*5741Slinton     oaddr = 0;
122*5741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
123*5741Slinton 	if (lp->line != 0) {
124*5741Slinton 	    oline = lp->line;
1255500Slinton 	}
126*5741Slinton 	info.together = getw(fp);
127*5741Slinton 	oline += info.separate.lineincr;
128*5741Slinton 	oaddr += info.separate.addrincr;
129*5741Slinton 	lp->line = oline;
130*5741Slinton 	lp->addr = oaddr;
131*5741Slinton     }
1325500Slinton }
1335500Slinton 
1345500Slinton /*
1355500Slinton  * read in the symbols
1365500Slinton  */
1375500Slinton 
1385500Slinton readsyms(fp)
1395500Slinton FILE *fp;
1405500Slinton {
141*5741Slinton     register int i;
142*5741Slinton     int symno;
1435500Slinton 
144*5741Slinton     symtab = st_creat(nlhdr.nsyms);
145*5741Slinton     for (i = 0; i < nlhdr.nsyms; i++) {
146*5741Slinton 	symno = getw(fp);
147*5741Slinton 	if (symno >= MAXSYMNO) {
148*5741Slinton 	    panic("symbol number too large");
1495500Slinton 	}
150*5741Slinton 	sym[symno] = readsym(fp);
151*5741Slinton     }
152*5741Slinton     if (backpatch() != 0) {
153*5741Slinton 	panic("patchlist not empty after reading namelist");
154*5741Slinton     }
155*5741Slinton     if (program == NIL) {
156*5741Slinton 	panic("no program");
157*5741Slinton     }
158*5741Slinton     maketypes();
1595500Slinton }
1605500Slinton 
1615500Slinton typedef struct patchinfo {
162*5741Slinton     SYM **patchsym;
163*5741Slinton     struct patchinfo *next_patch;
1645500Slinton } PATCH;
1655500Slinton 
1665500Slinton LOCAL PATCH *phead;
1675500Slinton 
1685500Slinton /*
1695500Slinton  * Go through patchlist looking for symbol numbers for which the
1705500Slinton  * sym array now has a non-NIL entry.
1715500Slinton  *
1725500Slinton  * Afterwards, zap the sym array.
1735500Slinton  */
1745500Slinton 
1755500Slinton int backpatch()
1765500Slinton {
177*5741Slinton     register PATCH *p, *last, *next;
178*5741Slinton     register SYM *s, **t;
179*5741Slinton     int count;
1805500Slinton 
181*5741Slinton     last = NIL;
182*5741Slinton     count = 0;
183*5741Slinton     for (p = phead; p != NIL; p = next) {
184*5741Slinton 	next = p->next_patch;
185*5741Slinton 	t = p->patchsym;
186*5741Slinton 	if ((s = sym[(int) *t]) != NIL) {
187*5741Slinton 	    *t = s;
188*5741Slinton 	    if (last == NIL) {
189*5741Slinton 		phead = next;
190*5741Slinton 	    } else {
191*5741Slinton 		last->next_patch = next;
192*5741Slinton 	    }
193*5741Slinton 	    dispose(p);
194*5741Slinton 	} else {
195*5741Slinton 	    last = p;
196*5741Slinton 	    count++;
1975500Slinton 	}
198*5741Slinton     }
199*5741Slinton     for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
200*5741Slinton 	*t = NIL;
201*5741Slinton     }
202*5741Slinton     return(count);
2035500Slinton }
2045500Slinton 
2055500Slinton /*
2065500Slinton  * Check to see if the given pointer (really symbol number) should
2075500Slinton  * be added to the patch list.  The argument is double indirect
2085500Slinton  * to do call by reference passing.
2095500Slinton  */
2105500Slinton 
2115500Slinton chkpatch(p)
2125500Slinton SYM **p;
2135500Slinton {
214*5741Slinton     register SYM *s, *t;
215*5741Slinton     register PATCH *patch;
2165500Slinton 
217*5741Slinton     if ((s = *p) != NIL) {
218*5741Slinton 	if ((t = sym[(int) s]) != NIL) {
219*5741Slinton 	    *p = t;
220*5741Slinton 	} else {
221*5741Slinton 	    patch = alloc(1, PATCH);
222*5741Slinton 	    patch->patchsym = p;
223*5741Slinton 	    patch->next_patch = phead;
224*5741Slinton 	    phead = patch;
2255500Slinton 	}
226*5741Slinton     }
2275500Slinton }
2285500Slinton 
2295500Slinton /*
2305500Slinton  * Free all the object information.
2315500Slinton  */
2325500Slinton 
2335500Slinton objfree()
2345500Slinton {
235*5741Slinton     register int i;
2365500Slinton 
237*5741Slinton     st_destroy(symtab);
238*5741Slinton     dispose(stringtab);
239*5741Slinton     dispose(filetab);
240*5741Slinton     dispose(linetab);
241*5741Slinton     clrfunctab();
242*5741Slinton     for (i = 0; i < MAXSYMNO; i++) {
243*5741Slinton 	sym[i] = NIL;
244*5741Slinton     }
2455500Slinton }
246