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