15500Slinton /* Copyright (c) 1982 Regents of the University of California */
25500Slinton 
3*6871Slinton static char sccsid[] = "@(#)readobj.c 1.5 05/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"
135569Slinton #include "objfmt.h"
145649Slinton #include "main.h"
155500Slinton #include "mappings.h"
165500Slinton #include "mappings/filetab.h"
175500Slinton #include "mappings/linetab.h"
185741Slinton #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 {
295741Slinton     register FILE *fp;
305741Slinton     struct pxhdr hdr;
315500Slinton 
325741Slinton     if ((fp = fopen(file, "r")) == NIL) {
335741Slinton 	panic("can't open %s", file);
345741Slinton     }
355741Slinton     get(fp, hdr);
365741Slinton     if (hdr.magicnum != MAGICNUM) {
375741Slinton 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
385569Slinton 	get(fp, hdr);
395649Slinton 	if (hdr.magicnum != MAGICNUM) {
405741Slinton 	    fatal("%s is not a Pascal object file", file);
415649Slinton 	}
425741Slinton     }
435741Slinton     if (hdr.symtabsize == 0) {
445741Slinton 	fatal("%s doesn't have symbolic information", file);
455741Slinton     }
465741Slinton     objsize = hdr.objsize;
475741Slinton     fseek(fp, (long) objsize, 1);
485741Slinton     if (get(fp, nlhdr) != 1) {
495741Slinton 	panic("can't read nlhdr");
505741Slinton     }
515741Slinton     if (option('h')) {
525741Slinton 	printf("\nHeader information:\n");
535741Slinton 	printf("\tobject size %d\n", objsize);
545741Slinton 	printf("\tsymtab size %d\n", hdr.symtabsize);
555741Slinton 	printf("\tstringsize  %d\n", nlhdr.stringsize);
565741Slinton 	printf("\tnsyms       %d\n", nlhdr.nsyms);
575741Slinton 	printf("\tnfiles      %d\n", nlhdr.nfiles);
585741Slinton 	printf("\tnlines      %d\n", nlhdr.nlines);
595741Slinton     }
605741Slinton     stringtab = alloc(nlhdr.stringsize, char);
615741Slinton     fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
625741Slinton     readsyms(fp);
635741Slinton     readfiles(fp);
645741Slinton     readlines(fp);
655741Slinton     fclose(fp);
665500Slinton }
675500Slinton 
685500Slinton /*
69*6871Slinton  * Allocate and read in file name information table.
705500Slinton  */
715500Slinton 
725500Slinton LOCAL readfiles(fp)
735500Slinton register FILE *fp;
745500Slinton {
755741Slinton     register int i;
765741Slinton     register FILETAB *ftp;
775741Slinton     FILETAB temp;
785741Slinton     ADDRESS prevaddr;
795500Slinton 
805741Slinton     filetab = alloc(nlhdr.nfiles, FILETAB);
815741Slinton     ftp = &filetab[0];
825741Slinton     prevaddr = 0;
835741Slinton     for (i = 0; i < nlhdr.nfiles; i++) {
845741Slinton 	fread(&temp, sizeof(FILETAB), 1, fp);
855741Slinton 	if (temp.addr != prevaddr) {
865741Slinton 	    ftp++;
875500Slinton 	}
885741Slinton 	*ftp = temp;
895741Slinton 	ftp->filename += (int) stringtab;
905741Slinton 	prevaddr = ftp->addr;
915741Slinton     }
925741Slinton     nlhdr.nfiles = (ftp - &filetab[0]) + 1;
935741Slinton     skimsource(filetab[0].filename);
945741Slinton     dotpfile = filetab[0].filename;
955500Slinton }
965500Slinton 
975500Slinton /*
98*6871Slinton  * Allocate and read in line number information table.
995500Slinton  */
1005500Slinton 
1015500Slinton LOCAL readlines(fp)
1025500Slinton FILE *fp;
1035500Slinton {
1045741Slinton     register LINENO oline;
1055741Slinton     register ADDRESS oaddr;
1065741Slinton     register LINETAB *lp;
1075741Slinton     FILETAB *ftp;
1085741Slinton     OBJLINE info;
1095500Slinton 
1105741Slinton     if (nlhdr.nlines == 0) {
1115741Slinton 	return;
1125741Slinton     }
1135741Slinton     linetab = alloc(nlhdr.nlines, LINETAB);
1145741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1155741Slinton 	lp->line = 0;
1165741Slinton     }
1175741Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
118*6871Slinton 	if (ftp->lineindex < nlhdr.nlines) {
119*6871Slinton 	    linetab[ftp->lineindex].line = ftp->line;
120*6871Slinton 	}
1215741Slinton     }
1225741Slinton     oline = 0;
1235741Slinton     oaddr = 0;
1245741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1255741Slinton 	if (lp->line != 0) {
1265741Slinton 	    oline = lp->line;
1275500Slinton 	}
1285741Slinton 	info.together = getw(fp);
1295741Slinton 	oline += info.separate.lineincr;
1305741Slinton 	oaddr += info.separate.addrincr;
1315741Slinton 	lp->line = oline;
1325741Slinton 	lp->addr = oaddr;
1335741Slinton     }
1345500Slinton }
1355500Slinton 
1365500Slinton /*
137*6871Slinton  * Read in the symbols.
1385500Slinton  */
1395500Slinton 
1405500Slinton readsyms(fp)
1415500Slinton FILE *fp;
1425500Slinton {
1435741Slinton     register int i;
1445741Slinton     int symno;
1455500Slinton 
1465741Slinton     symtab = st_creat(nlhdr.nsyms);
1475741Slinton     for (i = 0; i < nlhdr.nsyms; i++) {
1485741Slinton 	symno = getw(fp);
1495741Slinton 	if (symno >= MAXSYMNO) {
1505741Slinton 	    panic("symbol number too large");
1515500Slinton 	}
1525741Slinton 	sym[symno] = readsym(fp);
1535741Slinton     }
1545741Slinton     if (backpatch() != 0) {
1555741Slinton 	panic("patchlist not empty after reading namelist");
1565741Slinton     }
1575741Slinton     if (program == NIL) {
1585741Slinton 	panic("no program");
1595741Slinton     }
1605741Slinton     maketypes();
1615500Slinton }
1625500Slinton 
1635500Slinton typedef struct patchinfo {
1645741Slinton     SYM **patchsym;
1655741Slinton     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 {
1795741Slinton     register PATCH *p, *last, *next;
1805741Slinton     register SYM *s, **t;
1815741Slinton     int count;
1825500Slinton 
1835741Slinton     last = NIL;
1845741Slinton     count = 0;
1855741Slinton     for (p = phead; p != NIL; p = next) {
1865741Slinton 	next = p->next_patch;
1875741Slinton 	t = p->patchsym;
1885741Slinton 	if ((s = sym[(int) *t]) != NIL) {
1895741Slinton 	    *t = s;
1905741Slinton 	    if (last == NIL) {
1915741Slinton 		phead = next;
1925741Slinton 	    } else {
1935741Slinton 		last->next_patch = next;
1945741Slinton 	    }
1955741Slinton 	    dispose(p);
1965741Slinton 	} else {
1975741Slinton 	    last = p;
1985741Slinton 	    count++;
1995500Slinton 	}
2005741Slinton     }
2015741Slinton     for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
2025741Slinton 	*t = NIL;
2035741Slinton     }
2045741Slinton     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 {
2165741Slinton     register SYM *s, *t;
2175741Slinton     register PATCH *patch;
2185500Slinton 
2195741Slinton     if ((s = *p) != NIL) {
2205741Slinton 	if ((t = sym[(int) s]) != NIL) {
2215741Slinton 	    *p = t;
2225741Slinton 	} else {
2235741Slinton 	    patch = alloc(1, PATCH);
2245741Slinton 	    patch->patchsym = p;
2255741Slinton 	    patch->next_patch = phead;
2265741Slinton 	    phead = patch;
2275500Slinton 	}
2285741Slinton     }
2295500Slinton }
2305500Slinton 
2315500Slinton /*
2325500Slinton  * Free all the object information.
2335500Slinton  */
2345500Slinton 
2355500Slinton objfree()
2365500Slinton {
2375741Slinton     register int i;
2385500Slinton 
2395741Slinton     st_destroy(symtab);
2405741Slinton     dispose(stringtab);
2415741Slinton     dispose(filetab);
2425741Slinton     dispose(linetab);
2435741Slinton     clrfunctab();
2445741Slinton     for (i = 0; i < MAXSYMNO; i++) {
2455741Slinton 	sym[i] = NIL;
2465741Slinton     }
2475500Slinton }
248