15500Slinton /* Copyright (c) 1982 Regents of the University of California */
25500Slinton 
3*5569Slinton static char sccsid[] = "@(#)readobj.c 1.2 01/19/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"
13*5569Slinton #include "objfmt.h"
145500Slinton #include "mappings.h"
155500Slinton #include "mappings/filetab.h"
165500Slinton #include "mappings/linetab.h"
175500Slinton 
185500Slinton #define MAXSYMNO 2000
195500Slinton 
205500Slinton char *objname = "obj";
215500Slinton 
225500Slinton LOCAL SYM *sym[MAXSYMNO];
235500Slinton 
245500Slinton readobj(file)
255500Slinton char *file;
265500Slinton {
275500Slinton 	register FILE *fp;
28*5569Slinton 	struct pxhdr hdr;
295500Slinton 
305500Slinton 	if ((fp = fopen(file, "r")) == NIL) {
315500Slinton 		panic("can't open %s", file);
325500Slinton 	}
33*5569Slinton 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
34*5569Slinton 	get(fp, hdr);
35*5569Slinton 	objsize = hdr.objsize;
36*5569Slinton 	fseek(fp, (long) objsize, 1);
375500Slinton 	if (get(fp, nlhdr) != 1) {
385500Slinton 		panic("readobj:  get failed");
395500Slinton 	}
405500Slinton 	stringtab = alloc(nlhdr.stringsize, char);
415500Slinton 	fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
425500Slinton 	readsyms(fp);
435500Slinton 	readfiles(fp);
445500Slinton 	readlines(fp);
455500Slinton 	fclose(fp);
465500Slinton }
475500Slinton 
485500Slinton /*
495500Slinton  * allocate and read in file name information table
505500Slinton  */
515500Slinton 
525500Slinton LOCAL readfiles(fp)
535500Slinton register FILE *fp;
545500Slinton {
555500Slinton 	register int i;
565500Slinton 	register FILETAB *ftp;
575500Slinton 	FILETAB temp;
585500Slinton 	ADDRESS prevaddr;
595500Slinton 
605500Slinton 	filetab = alloc(nlhdr.nfiles, FILETAB);
615500Slinton 	ftp = &filetab[0];
625500Slinton 	prevaddr = 0;
635500Slinton 	for (i = 0; i < nlhdr.nfiles; i++) {
645500Slinton 		fread(&temp, sizeof(FILETAB), 1, fp);
655500Slinton 		if (temp.addr != prevaddr) {
665500Slinton 			ftp++;
675500Slinton 		}
685500Slinton 		*ftp = temp;
695500Slinton 		ftp->filename += (int) stringtab;
705500Slinton 		prevaddr = ftp->addr;
715500Slinton 	}
725500Slinton 	nlhdr.nfiles = (ftp - &filetab[0]) + 1;
735500Slinton 	skimsource(filetab[0].filename);
745500Slinton 	dotpfile = filetab[0].filename;
755500Slinton }
765500Slinton 
775500Slinton /*
785500Slinton  * allocate and read in line number information table
795500Slinton  */
805500Slinton 
815500Slinton LOCAL readlines(fp)
825500Slinton FILE *fp;
835500Slinton {
845500Slinton 	register LINENO oline;
855500Slinton 	register ADDRESS oaddr;
865500Slinton 	register LINETAB *lp;
875500Slinton 	FILETAB *ftp;
885500Slinton 	short lineincr;
895500Slinton 
905500Slinton 	if (nlhdr.nlines == 0) {
915500Slinton 		return;
925500Slinton 	}
935500Slinton 	linetab = alloc(nlhdr.nlines, LINETAB);
945500Slinton 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
955500Slinton 		lp->line = 0;
965500Slinton 	}
975500Slinton 	for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
985500Slinton 		linetab[ftp->lineindex].line = ftp->line;
995500Slinton 	}
1005500Slinton 	oline = 0;
1015500Slinton 	oaddr = 0;
1025500Slinton 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1035500Slinton 		if (lp->line != 0) {
1045500Slinton 			oline = lp->line;
1055500Slinton 		}
1065500Slinton 		lineincr = (unsigned) getc(fp);
1075500Slinton 		if (lineincr > 127) {
1085500Slinton 			lineincr -= 256;
1095500Slinton 		}
1105500Slinton 		oline += lineincr;
1115500Slinton 		oaddr += (unsigned) getc(fp);
1125500Slinton 		lp->line = oline;
1135500Slinton 		lp->addr = oaddr;
1145500Slinton 	}
1155500Slinton }
1165500Slinton 
1175500Slinton /*
1185500Slinton  * read in the symbols
1195500Slinton  */
1205500Slinton 
1215500Slinton readsyms(fp)
1225500Slinton FILE *fp;
1235500Slinton {
1245500Slinton 	register int i;
1255500Slinton 	int symno;
1265500Slinton 
1275500Slinton 	symtab = st_creat(nlhdr.nsyms);
1285500Slinton 	for (i = 0; i < nlhdr.nsyms; i++) {
1295500Slinton 		symno = getw(fp);
1305500Slinton 		if (symno >= MAXSYMNO) {
1315500Slinton 			panic("symbol number too large");
1325500Slinton 		}
1335500Slinton 		sym[symno] = readsym(fp);
1345500Slinton 	}
1355500Slinton 	if (backpatch() != 0) {
1365500Slinton 		panic("patchlist not empty after reading namelist");
1375500Slinton 	}
1385500Slinton 	if (program == NIL) {
1395500Slinton 		panic("no program");
1405500Slinton 	}
1415500Slinton 	maketypes();
1425500Slinton }
1435500Slinton 
1445500Slinton typedef struct patchinfo {
1455500Slinton 	SYM **patchsym;
1465500Slinton 	struct patchinfo *next_patch;
1475500Slinton } PATCH;
1485500Slinton 
1495500Slinton LOCAL PATCH *phead;
1505500Slinton 
1515500Slinton /*
1525500Slinton  * Go through patchlist looking for symbol numbers for which the
1535500Slinton  * sym array now has a non-NIL entry.
1545500Slinton  *
1555500Slinton  * Afterwards, zap the sym array.
1565500Slinton  */
1575500Slinton 
1585500Slinton int backpatch()
1595500Slinton {
1605500Slinton 	register PATCH *p, *last, *next;
1615500Slinton 	register SYM *s, **t;
1625500Slinton 	int count;
1635500Slinton 
1645500Slinton 	last = NIL;
1655500Slinton 	count = 0;
1665500Slinton 	for (p = phead; p != NIL; p = next) {
1675500Slinton 		next = p->next_patch;
1685500Slinton 		t = p->patchsym;
1695500Slinton 		if ((s = sym[(int) *t]) != NIL) {
1705500Slinton 			*t = s;
1715500Slinton 			if (last == NIL) {
1725500Slinton 				phead = next;
1735500Slinton 			} else {
1745500Slinton 				last->next_patch = next;
1755500Slinton 			}
1765500Slinton 			dispose(p);
1775500Slinton 		} else {
1785500Slinton 			last = p;
1795500Slinton 			count++;
1805500Slinton 		}
1815500Slinton 	}
1825500Slinton 	for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
1835500Slinton 		*t = NIL;
1845500Slinton 	}
1855500Slinton 	return(count);
1865500Slinton }
1875500Slinton 
1885500Slinton /*
1895500Slinton  * Check to see if the given pointer (really symbol number) should
1905500Slinton  * be added to the patch list.  The argument is double indirect
1915500Slinton  * to do call by reference passing.
1925500Slinton  */
1935500Slinton 
1945500Slinton chkpatch(p)
1955500Slinton SYM **p;
1965500Slinton {
1975500Slinton 	register SYM *s, *t;
1985500Slinton 	register PATCH *patch;
1995500Slinton 
2005500Slinton 	if ((s = *p) != NIL) {
2015500Slinton 		if ((t = sym[(int) s]) != NIL) {
2025500Slinton 			*p = t;
2035500Slinton 		} else {
2045500Slinton 			patch = alloc(1, PATCH);
2055500Slinton 			patch->patchsym = p;
2065500Slinton 			patch->next_patch = phead;
2075500Slinton 			phead = patch;
2085500Slinton 		}
2095500Slinton 	}
2105500Slinton }
2115500Slinton 
2125500Slinton /*
2135500Slinton  * Free all the object information.
2145500Slinton  */
2155500Slinton 
2165500Slinton objfree()
2175500Slinton {
2185500Slinton 	register int i;
2195500Slinton 
2205500Slinton 	st_destroy(symtab);
2215500Slinton 	dispose(stringtab);
2225500Slinton 	dispose(filetab);
2235500Slinton 	dispose(linetab);
2245500Slinton 	clrfunctab();
2255500Slinton 	for (i = 0; i < MAXSYMNO; i++) {
2265500Slinton 		sym[i] = NIL;
2275500Slinton 	}
2285500Slinton }
229