148097Sbostic /*-
2*62142Sbostic  * Copyright (c) 1982, 1993
3*62142Sbostic  *	The Regents of the University of California.  All rights reserved.
448097Sbostic  *
548097Sbostic  * %sccs.include.redist.c%
622767Smckusick  */
75500Slinton 
822767Smckusick #ifndef lint
9*62142Sbostic static char sccsid[] = "@(#)readobj.c	8.1 (Berkeley) 06/06/93";
1048097Sbostic #endif /* not lint */
115500Slinton 
125500Slinton /*
135500Slinton  * Read in the namelist from the obj file.
145500Slinton  */
155500Slinton 
165500Slinton #include "defs.h"
175500Slinton #include "sym.h"
185500Slinton #include "symtab.h"
195500Slinton #include "object.h"
205569Slinton #include "objfmt.h"
215649Slinton #include "main.h"
225500Slinton #include "mappings.h"
235500Slinton #include "mappings/filetab.h"
245500Slinton #include "mappings/linetab.h"
255741Slinton #include "objsym.rep"
265500Slinton 
2711715Slinton #define MAXSYMNO 6000
285500Slinton 
295500Slinton char *objname = "obj";
305500Slinton 
315500Slinton LOCAL SYM *sym[MAXSYMNO];
325500Slinton 
readobj(file)335500Slinton readobj(file)
345500Slinton char *file;
355500Slinton {
365741Slinton     register FILE *fp;
375741Slinton     struct pxhdr hdr;
385500Slinton 
395741Slinton     if ((fp = fopen(file, "r")) == NIL) {
405741Slinton 	panic("can't open %s", file);
415741Slinton     }
425741Slinton     get(fp, hdr);
435741Slinton     if (hdr.magicnum != MAGICNUM) {
445741Slinton 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
455569Slinton 	get(fp, hdr);
465649Slinton 	if (hdr.magicnum != MAGICNUM) {
475741Slinton 	    fatal("%s is not a Pascal object file", file);
485649Slinton 	}
495741Slinton     }
505741Slinton     if (hdr.symtabsize == 0) {
515741Slinton 	fatal("%s doesn't have symbolic information", file);
525741Slinton     }
535741Slinton     objsize = hdr.objsize;
545741Slinton     fseek(fp, (long) objsize, 1);
555741Slinton     if (get(fp, nlhdr) != 1) {
565741Slinton 	panic("can't read nlhdr");
575741Slinton     }
585741Slinton     if (option('h')) {
595741Slinton 	printf("\nHeader information:\n");
605741Slinton 	printf("\tobject size %d\n", objsize);
615741Slinton 	printf("\tsymtab size %d\n", hdr.symtabsize);
625741Slinton 	printf("\tstringsize  %d\n", nlhdr.stringsize);
635741Slinton 	printf("\tnsyms       %d\n", nlhdr.nsyms);
645741Slinton 	printf("\tnfiles      %d\n", nlhdr.nfiles);
655741Slinton 	printf("\tnlines      %d\n", nlhdr.nlines);
665741Slinton     }
675741Slinton     stringtab = alloc(nlhdr.stringsize, char);
685741Slinton     fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
695741Slinton     readsyms(fp);
705741Slinton     readfiles(fp);
715741Slinton     readlines(fp);
725741Slinton     fclose(fp);
735500Slinton }
745500Slinton 
755500Slinton /*
766871Slinton  * Allocate and read in file name information table.
775500Slinton  */
785500Slinton 
readfiles(fp)795500Slinton LOCAL readfiles(fp)
805500Slinton register FILE *fp;
815500Slinton {
825741Slinton     register int i;
835741Slinton     register FILETAB *ftp;
845741Slinton     FILETAB temp;
855741Slinton     ADDRESS prevaddr;
865500Slinton 
875741Slinton     filetab = alloc(nlhdr.nfiles, FILETAB);
885741Slinton     ftp = &filetab[0];
895741Slinton     prevaddr = 0;
905741Slinton     for (i = 0; i < nlhdr.nfiles; i++) {
915741Slinton 	fread(&temp, sizeof(FILETAB), 1, fp);
925741Slinton 	if (temp.addr != prevaddr) {
935741Slinton 	    ftp++;
945500Slinton 	}
955741Slinton 	*ftp = temp;
965741Slinton 	ftp->filename += (int) stringtab;
975741Slinton 	prevaddr = ftp->addr;
985741Slinton     }
995741Slinton     nlhdr.nfiles = (ftp - &filetab[0]) + 1;
1005741Slinton     skimsource(filetab[0].filename);
1015741Slinton     dotpfile = filetab[0].filename;
1025500Slinton }
1035500Slinton 
1045500Slinton /*
1056871Slinton  * Allocate and read in line number information table.
1065500Slinton  */
1075500Slinton 
readlines(fp)1085500Slinton LOCAL readlines(fp)
1095500Slinton FILE *fp;
1105500Slinton {
1115741Slinton     register LINENO oline;
1125741Slinton     register ADDRESS oaddr;
1135741Slinton     register LINETAB *lp;
1145741Slinton     FILETAB *ftp;
1155741Slinton     OBJLINE info;
1165500Slinton 
1175741Slinton     if (nlhdr.nlines == 0) {
1185741Slinton 	return;
1195741Slinton     }
1205741Slinton     linetab = alloc(nlhdr.nlines, LINETAB);
1215741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1225741Slinton 	lp->line = 0;
1235741Slinton     }
1245741Slinton     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
1256871Slinton 	if (ftp->lineindex < nlhdr.nlines) {
1266871Slinton 	    linetab[ftp->lineindex].line = ftp->line;
1276871Slinton 	}
1285741Slinton     }
1295741Slinton     oline = 0;
1305741Slinton     oaddr = 0;
1315741Slinton     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
1325741Slinton 	if (lp->line != 0) {
1335741Slinton 	    oline = lp->line;
1345500Slinton 	}
1355741Slinton 	info.together = getw(fp);
1365741Slinton 	oline += info.separate.lineincr;
1375741Slinton 	oaddr += info.separate.addrincr;
1385741Slinton 	lp->line = oline;
1395741Slinton 	lp->addr = oaddr;
1405741Slinton     }
1415500Slinton }
1425500Slinton 
1435500Slinton /*
1446871Slinton  * Read in the symbols.
1455500Slinton  */
1465500Slinton 
readsyms(fp)1475500Slinton readsyms(fp)
1485500Slinton FILE *fp;
1495500Slinton {
1505741Slinton     register int i;
1515741Slinton     int symno;
1525500Slinton 
1535741Slinton     symtab = st_creat(nlhdr.nsyms);
1545741Slinton     for (i = 0; i < nlhdr.nsyms; i++) {
1555741Slinton 	symno = getw(fp);
1565741Slinton 	if (symno >= MAXSYMNO) {
15711715Slinton 	    panic("symbol number too large (%d)", symno);
1585500Slinton 	}
1595741Slinton 	sym[symno] = readsym(fp);
1605741Slinton     }
1615741Slinton     if (backpatch() != 0) {
1625741Slinton 	panic("patchlist not empty after reading namelist");
1635741Slinton     }
1645741Slinton     if (program == NIL) {
1655741Slinton 	panic("no program");
1665741Slinton     }
1675741Slinton     maketypes();
1685500Slinton }
1695500Slinton 
1705500Slinton typedef struct patchinfo {
1715741Slinton     SYM **patchsym;
1725741Slinton     struct patchinfo *next_patch;
1735500Slinton } PATCH;
1745500Slinton 
1755500Slinton LOCAL PATCH *phead;
1765500Slinton 
1775500Slinton /*
1785500Slinton  * Go through patchlist looking for symbol numbers for which the
1795500Slinton  * sym array now has a non-NIL entry.
1805500Slinton  *
1815500Slinton  * Afterwards, zap the sym array.
1825500Slinton  */
1835500Slinton 
backpatch()1845500Slinton int backpatch()
1855500Slinton {
1865741Slinton     register PATCH *p, *last, *next;
1875741Slinton     register SYM *s, **t;
1885741Slinton     int count;
1895500Slinton 
1905741Slinton     last = NIL;
1915741Slinton     count = 0;
1925741Slinton     for (p = phead; p != NIL; p = next) {
1935741Slinton 	next = p->next_patch;
1945741Slinton 	t = p->patchsym;
1955741Slinton 	if ((s = sym[(int) *t]) != NIL) {
1965741Slinton 	    *t = s;
1975741Slinton 	    if (last == NIL) {
1985741Slinton 		phead = next;
1995741Slinton 	    } else {
2005741Slinton 		last->next_patch = next;
2015741Slinton 	    }
2025741Slinton 	    dispose(p);
2035741Slinton 	} else {
2045741Slinton 	    last = p;
2055741Slinton 	    count++;
2065500Slinton 	}
2075741Slinton     }
2085741Slinton     for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
2095741Slinton 	*t = NIL;
2105741Slinton     }
2115741Slinton     return(count);
2125500Slinton }
2135500Slinton 
2145500Slinton /*
2155500Slinton  * Check to see if the given pointer (really symbol number) should
2165500Slinton  * be added to the patch list.  The argument is double indirect
2175500Slinton  * to do call by reference passing.
2185500Slinton  */
2195500Slinton 
chkpatch(p)2205500Slinton chkpatch(p)
2215500Slinton SYM **p;
2225500Slinton {
2235741Slinton     register SYM *s, *t;
2245741Slinton     register PATCH *patch;
2255500Slinton 
2265741Slinton     if ((s = *p) != NIL) {
2275741Slinton 	if ((t = sym[(int) s]) != NIL) {
2285741Slinton 	    *p = t;
2295741Slinton 	} else {
2305741Slinton 	    patch = alloc(1, PATCH);
2315741Slinton 	    patch->patchsym = p;
2325741Slinton 	    patch->next_patch = phead;
2335741Slinton 	    phead = patch;
2345500Slinton 	}
2355741Slinton     }
2365500Slinton }
2375500Slinton 
2385500Slinton /*
2395500Slinton  * Free all the object information.
2405500Slinton  */
2415500Slinton 
objfree()2425500Slinton objfree()
2435500Slinton {
2445741Slinton     register int i;
2455500Slinton 
2465741Slinton     st_destroy(symtab);
2475741Slinton     dispose(stringtab);
2485741Slinton     dispose(filetab);
2495741Slinton     dispose(linetab);
2505741Slinton     clrfunctab();
2515741Slinton     for (i = 0; i < MAXSYMNO; i++) {
2525741Slinton 	sym[i] = NIL;
2535741Slinton     }
2545500Slinton }
255