15500Slinton /* Copyright (c) 1982 Regents of the University of California */
25500Slinton 
3*5649Slinton static char sccsid[] = "@(#)readobj.c 1.3 02/02/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"
14*5649Slinton #include "main.h"
155500Slinton #include "mappings.h"
165500Slinton #include "mappings/filetab.h"
175500Slinton #include "mappings/linetab.h"
185500Slinton 
195500Slinton #define MAXSYMNO 2000
205500Slinton 
215500Slinton char *objname = "obj";
225500Slinton 
235500Slinton LOCAL SYM *sym[MAXSYMNO];
245500Slinton 
255500Slinton readobj(file)
265500Slinton char *file;
275500Slinton {
285500Slinton 	register FILE *fp;
295569Slinton 	struct pxhdr hdr;
305500Slinton 
315500Slinton 	if ((fp = fopen(file, "r")) == NIL) {
325500Slinton 		panic("can't open %s", file);
335500Slinton 	}
345569Slinton 	get(fp, hdr);
35*5649Slinton 	if (hdr.magicnum != MAGICNUM) {
36*5649Slinton 		fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
37*5649Slinton 		get(fp, hdr);
38*5649Slinton 		if (hdr.magicnum != MAGICNUM) {
39*5649Slinton 			fatal("%s is not a Pascal object file", file);
40*5649Slinton 		}
41*5649Slinton 	}
42*5649Slinton 	if (hdr.symtabsize == 0) {
43*5649Slinton 		fatal("%s doesn't have symbolic information", file);
44*5649Slinton 	}
455569Slinton 	objsize = hdr.objsize;
465569Slinton 	fseek(fp, (long) objsize, 1);
475500Slinton 	if (get(fp, nlhdr) != 1) {
48*5649Slinton 		panic("can't read nlhdr");
495500Slinton 	}
50*5649Slinton 	if (option('h')) {
51*5649Slinton 		printf("\nHeader information:\n");
52*5649Slinton 		printf("\tobject size %d\n", objsize);
53*5649Slinton 		printf("\tsymtab size %d\n", hdr.symtabsize);
54*5649Slinton 		printf("\tstringsize  %d\n", nlhdr.stringsize);
55*5649Slinton 		printf("\tnsyms       %d\n", nlhdr.nsyms);
56*5649Slinton 		printf("\tnfiles      %d\n", nlhdr.nfiles);
57*5649Slinton 		printf("\tnlines      %d\n", nlhdr.nlines);
58*5649Slinton 	}
595500Slinton 	stringtab = alloc(nlhdr.stringsize, char);
605500Slinton 	fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
615500Slinton 	readsyms(fp);
625500Slinton 	readfiles(fp);
635500Slinton 	readlines(fp);
645500Slinton 	fclose(fp);
655500Slinton }
665500Slinton 
675500Slinton /*
685500Slinton  * allocate and read in file name information table
695500Slinton  */
705500Slinton 
715500Slinton LOCAL readfiles(fp)
725500Slinton register FILE *fp;
735500Slinton {
745500Slinton 	register int i;
755500Slinton 	register FILETAB *ftp;
765500Slinton 	FILETAB temp;
775500Slinton 	ADDRESS prevaddr;
785500Slinton 
795500Slinton 	filetab = alloc(nlhdr.nfiles, FILETAB);
805500Slinton 	ftp = &filetab[0];
815500Slinton 	prevaddr = 0;
825500Slinton 	for (i = 0; i < nlhdr.nfiles; i++) {
835500Slinton 		fread(&temp, sizeof(FILETAB), 1, fp);
845500Slinton 		if (temp.addr != prevaddr) {
855500Slinton 			ftp++;
865500Slinton 		}
875500Slinton 		*ftp = temp;
885500Slinton 		ftp->filename += (int) stringtab;
895500Slinton 		prevaddr = ftp->addr;
905500Slinton 	}
915500Slinton 	nlhdr.nfiles = (ftp - &filetab[0]) + 1;
925500Slinton 	skimsource(filetab[0].filename);
935500Slinton 	dotpfile = filetab[0].filename;
945500Slinton }
955500Slinton 
965500Slinton /*
975500Slinton  * allocate and read in line number information table
985500Slinton  */
995500Slinton 
1005500Slinton LOCAL readlines(fp)
1015500Slinton FILE *fp;
1025500Slinton {
1035500Slinton 	register LINENO oline;
1045500Slinton 	register ADDRESS oaddr;
1055500Slinton 	register LINETAB *lp;
1065500Slinton 	FILETAB *ftp;
1075500Slinton 	short lineincr;
1085500Slinton 
1095500Slinton 	if (nlhdr.nlines == 0) {
1105500Slinton 		return;
1115500Slinton 	}
1125500Slinton 	linetab = alloc(nlhdr.nlines, LINETAB);
1135500Slinton 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1145500Slinton 		lp->line = 0;
1155500Slinton 	}
1165500Slinton 	for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
1175500Slinton 		linetab[ftp->lineindex].line = ftp->line;
1185500Slinton 	}
1195500Slinton 	oline = 0;
1205500Slinton 	oaddr = 0;
1215500Slinton 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1225500Slinton 		if (lp->line != 0) {
1235500Slinton 			oline = lp->line;
1245500Slinton 		}
1255500Slinton 		lineincr = (unsigned) getc(fp);
1265500Slinton 		if (lineincr > 127) {
1275500Slinton 			lineincr -= 256;
1285500Slinton 		}
1295500Slinton 		oline += lineincr;
1305500Slinton 		oaddr += (unsigned) getc(fp);
1315500Slinton 		lp->line = oline;
1325500Slinton 		lp->addr = oaddr;
1335500Slinton 	}
1345500Slinton }
1355500Slinton 
1365500Slinton /*
1375500Slinton  * read in the symbols
1385500Slinton  */
1395500Slinton 
1405500Slinton readsyms(fp)
1415500Slinton FILE *fp;
1425500Slinton {
1435500Slinton 	register int i;
1445500Slinton 	int symno;
1455500Slinton 
1465500Slinton 	symtab = st_creat(nlhdr.nsyms);
1475500Slinton 	for (i = 0; i < nlhdr.nsyms; i++) {
1485500Slinton 		symno = getw(fp);
1495500Slinton 		if (symno >= MAXSYMNO) {
1505500Slinton 			panic("symbol number too large");
1515500Slinton 		}
1525500Slinton 		sym[symno] = readsym(fp);
1535500Slinton 	}
1545500Slinton 	if (backpatch() != 0) {
1555500Slinton 		panic("patchlist not empty after reading namelist");
1565500Slinton 	}
1575500Slinton 	if (program == NIL) {
1585500Slinton 		panic("no program");
1595500Slinton 	}
1605500Slinton 	maketypes();
1615500Slinton }
1625500Slinton 
1635500Slinton typedef struct patchinfo {
1645500Slinton 	SYM **patchsym;
1655500Slinton 	struct patchinfo *next_patch;
1665500Slinton } PATCH;
1675500Slinton 
1685500Slinton LOCAL PATCH *phead;
1695500Slinton 
1705500Slinton /*
1715500Slinton  * Go through patchlist looking for symbol numbers for which the
1725500Slinton  * sym array now has a non-NIL entry.
1735500Slinton  *
1745500Slinton  * Afterwards, zap the sym array.
1755500Slinton  */
1765500Slinton 
1775500Slinton int backpatch()
1785500Slinton {
1795500Slinton 	register PATCH *p, *last, *next;
1805500Slinton 	register SYM *s, **t;
1815500Slinton 	int count;
1825500Slinton 
1835500Slinton 	last = NIL;
1845500Slinton 	count = 0;
1855500Slinton 	for (p = phead; p != NIL; p = next) {
1865500Slinton 		next = p->next_patch;
1875500Slinton 		t = p->patchsym;
1885500Slinton 		if ((s = sym[(int) *t]) != NIL) {
1895500Slinton 			*t = s;
1905500Slinton 			if (last == NIL) {
1915500Slinton 				phead = next;
1925500Slinton 			} else {
1935500Slinton 				last->next_patch = next;
1945500Slinton 			}
1955500Slinton 			dispose(p);
1965500Slinton 		} else {
1975500Slinton 			last = p;
1985500Slinton 			count++;
1995500Slinton 		}
2005500Slinton 	}
2015500Slinton 	for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
2025500Slinton 		*t = NIL;
2035500Slinton 	}
2045500Slinton 	return(count);
2055500Slinton }
2065500Slinton 
2075500Slinton /*
2085500Slinton  * Check to see if the given pointer (really symbol number) should
2095500Slinton  * be added to the patch list.  The argument is double indirect
2105500Slinton  * to do call by reference passing.
2115500Slinton  */
2125500Slinton 
2135500Slinton chkpatch(p)
2145500Slinton SYM **p;
2155500Slinton {
2165500Slinton 	register SYM *s, *t;
2175500Slinton 	register PATCH *patch;
2185500Slinton 
2195500Slinton 	if ((s = *p) != NIL) {
2205500Slinton 		if ((t = sym[(int) s]) != NIL) {
2215500Slinton 			*p = t;
2225500Slinton 		} else {
2235500Slinton 			patch = alloc(1, PATCH);
2245500Slinton 			patch->patchsym = p;
2255500Slinton 			patch->next_patch = phead;
2265500Slinton 			phead = patch;
2275500Slinton 		}
2285500Slinton 	}
2295500Slinton }
2305500Slinton 
2315500Slinton /*
2325500Slinton  * Free all the object information.
2335500Slinton  */
2345500Slinton 
2355500Slinton objfree()
2365500Slinton {
2375500Slinton 	register int i;
2385500Slinton 
2395500Slinton 	st_destroy(symtab);
2405500Slinton 	dispose(stringtab);
2415500Slinton 	dispose(filetab);
2425500Slinton 	dispose(linetab);
2435500Slinton 	clrfunctab();
2445500Slinton 	for (i = 0; i < MAXSYMNO; i++) {
2455500Slinton 		sym[i] = NIL;
2465500Slinton 	}
2475500Slinton }
248