1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)readobj.c 1.2 01/19/82";
4 
5 /*
6  * Read in the namelist from the obj file.
7  */
8 
9 #include "defs.h"
10 #include "sym.h"
11 #include "symtab.h"
12 #include "object.h"
13 #include "objfmt.h"
14 #include "mappings.h"
15 #include "mappings/filetab.h"
16 #include "mappings/linetab.h"
17 
18 #define MAXSYMNO 2000
19 
20 char *objname = "obj";
21 
22 LOCAL SYM *sym[MAXSYMNO];
23 
24 readobj(file)
25 char *file;
26 {
27 	register FILE *fp;
28 	struct pxhdr hdr;
29 
30 	if ((fp = fopen(file, "r")) == NIL) {
31 		panic("can't open %s", file);
32 	}
33 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
34 	get(fp, hdr);
35 	objsize = hdr.objsize;
36 	fseek(fp, (long) objsize, 1);
37 	if (get(fp, nlhdr) != 1) {
38 		panic("readobj:  get failed");
39 	}
40 	stringtab = alloc(nlhdr.stringsize, char);
41 	fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
42 	readsyms(fp);
43 	readfiles(fp);
44 	readlines(fp);
45 	fclose(fp);
46 }
47 
48 /*
49  * allocate and read in file name information table
50  */
51 
52 LOCAL readfiles(fp)
53 register FILE *fp;
54 {
55 	register int i;
56 	register FILETAB *ftp;
57 	FILETAB temp;
58 	ADDRESS prevaddr;
59 
60 	filetab = alloc(nlhdr.nfiles, FILETAB);
61 	ftp = &filetab[0];
62 	prevaddr = 0;
63 	for (i = 0; i < nlhdr.nfiles; i++) {
64 		fread(&temp, sizeof(FILETAB), 1, fp);
65 		if (temp.addr != prevaddr) {
66 			ftp++;
67 		}
68 		*ftp = temp;
69 		ftp->filename += (int) stringtab;
70 		prevaddr = ftp->addr;
71 	}
72 	nlhdr.nfiles = (ftp - &filetab[0]) + 1;
73 	skimsource(filetab[0].filename);
74 	dotpfile = filetab[0].filename;
75 }
76 
77 /*
78  * allocate and read in line number information table
79  */
80 
81 LOCAL readlines(fp)
82 FILE *fp;
83 {
84 	register LINENO oline;
85 	register ADDRESS oaddr;
86 	register LINETAB *lp;
87 	FILETAB *ftp;
88 	short lineincr;
89 
90 	if (nlhdr.nlines == 0) {
91 		return;
92 	}
93 	linetab = alloc(nlhdr.nlines, LINETAB);
94 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
95 		lp->line = 0;
96 	}
97 	for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
98 		linetab[ftp->lineindex].line = ftp->line;
99 	}
100 	oline = 0;
101 	oaddr = 0;
102 	for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
103 		if (lp->line != 0) {
104 			oline = lp->line;
105 		}
106 		lineincr = (unsigned) getc(fp);
107 		if (lineincr > 127) {
108 			lineincr -= 256;
109 		}
110 		oline += lineincr;
111 		oaddr += (unsigned) getc(fp);
112 		lp->line = oline;
113 		lp->addr = oaddr;
114 	}
115 }
116 
117 /*
118  * read in the symbols
119  */
120 
121 readsyms(fp)
122 FILE *fp;
123 {
124 	register int i;
125 	int symno;
126 
127 	symtab = st_creat(nlhdr.nsyms);
128 	for (i = 0; i < nlhdr.nsyms; i++) {
129 		symno = getw(fp);
130 		if (symno >= MAXSYMNO) {
131 			panic("symbol number too large");
132 		}
133 		sym[symno] = readsym(fp);
134 	}
135 	if (backpatch() != 0) {
136 		panic("patchlist not empty after reading namelist");
137 	}
138 	if (program == NIL) {
139 		panic("no program");
140 	}
141 	maketypes();
142 }
143 
144 typedef struct patchinfo {
145 	SYM **patchsym;
146 	struct patchinfo *next_patch;
147 } PATCH;
148 
149 LOCAL PATCH *phead;
150 
151 /*
152  * Go through patchlist looking for symbol numbers for which the
153  * sym array now has a non-NIL entry.
154  *
155  * Afterwards, zap the sym array.
156  */
157 
158 int backpatch()
159 {
160 	register PATCH *p, *last, *next;
161 	register SYM *s, **t;
162 	int count;
163 
164 	last = NIL;
165 	count = 0;
166 	for (p = phead; p != NIL; p = next) {
167 		next = p->next_patch;
168 		t = p->patchsym;
169 		if ((s = sym[(int) *t]) != NIL) {
170 			*t = s;
171 			if (last == NIL) {
172 				phead = next;
173 			} else {
174 				last->next_patch = next;
175 			}
176 			dispose(p);
177 		} else {
178 			last = p;
179 			count++;
180 		}
181 	}
182 	for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
183 		*t = NIL;
184 	}
185 	return(count);
186 }
187 
188 /*
189  * Check to see if the given pointer (really symbol number) should
190  * be added to the patch list.  The argument is double indirect
191  * to do call by reference passing.
192  */
193 
194 chkpatch(p)
195 SYM **p;
196 {
197 	register SYM *s, *t;
198 	register PATCH *patch;
199 
200 	if ((s = *p) != NIL) {
201 		if ((t = sym[(int) s]) != NIL) {
202 			*p = t;
203 		} else {
204 			patch = alloc(1, PATCH);
205 			patch->patchsym = p;
206 			patch->next_patch = phead;
207 			phead = patch;
208 		}
209 	}
210 }
211 
212 /*
213  * Free all the object information.
214  */
215 
216 objfree()
217 {
218 	register int i;
219 
220 	st_destroy(symtab);
221 	dispose(stringtab);
222 	dispose(filetab);
223 	dispose(linetab);
224 	clrfunctab();
225 	for (i = 0; i < MAXSYMNO; i++) {
226 		sym[i] = NIL;
227 	}
228 }
229