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