1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)readobj.c 1.6 03/24/83";
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 #include "objsym.rep"
19 
20 #define MAXSYMNO 6000
21 
22 char *objname = "obj";
23 
24 LOCAL SYM *sym[MAXSYMNO];
25 
26 readobj(file)
27 char *file;
28 {
29     register FILE *fp;
30     struct pxhdr hdr;
31 
32     if ((fp = fopen(file, "r")) == NIL) {
33 	panic("can't open %s", file);
34     }
35     get(fp, hdr);
36     if (hdr.magicnum != MAGICNUM) {
37 	fseek(fp, (long) (HEADER_BYTES - sizeof(struct pxhdr)), 0);
38 	get(fp, hdr);
39 	if (hdr.magicnum != MAGICNUM) {
40 	    fatal("%s is not a Pascal object file", file);
41 	}
42     }
43     if (hdr.symtabsize == 0) {
44 	fatal("%s doesn't have symbolic information", file);
45     }
46     objsize = hdr.objsize;
47     fseek(fp, (long) objsize, 1);
48     if (get(fp, nlhdr) != 1) {
49 	panic("can't read nlhdr");
50     }
51     if (option('h')) {
52 	printf("\nHeader information:\n");
53 	printf("\tobject size %d\n", objsize);
54 	printf("\tsymtab size %d\n", hdr.symtabsize);
55 	printf("\tstringsize  %d\n", nlhdr.stringsize);
56 	printf("\tnsyms       %d\n", nlhdr.nsyms);
57 	printf("\tnfiles      %d\n", nlhdr.nfiles);
58 	printf("\tnlines      %d\n", nlhdr.nlines);
59     }
60     stringtab = alloc(nlhdr.stringsize, char);
61     fread(stringtab, sizeof(char), nlhdr.stringsize, fp);
62     readsyms(fp);
63     readfiles(fp);
64     readlines(fp);
65     fclose(fp);
66 }
67 
68 /*
69  * Allocate and read in file name information table.
70  */
71 
72 LOCAL readfiles(fp)
73 register FILE *fp;
74 {
75     register int i;
76     register FILETAB *ftp;
77     FILETAB temp;
78     ADDRESS prevaddr;
79 
80     filetab = alloc(nlhdr.nfiles, FILETAB);
81     ftp = &filetab[0];
82     prevaddr = 0;
83     for (i = 0; i < nlhdr.nfiles; i++) {
84 	fread(&temp, sizeof(FILETAB), 1, fp);
85 	if (temp.addr != prevaddr) {
86 	    ftp++;
87 	}
88 	*ftp = temp;
89 	ftp->filename += (int) stringtab;
90 	prevaddr = ftp->addr;
91     }
92     nlhdr.nfiles = (ftp - &filetab[0]) + 1;
93     skimsource(filetab[0].filename);
94     dotpfile = filetab[0].filename;
95 }
96 
97 /*
98  * Allocate and read in line number information table.
99  */
100 
101 LOCAL readlines(fp)
102 FILE *fp;
103 {
104     register LINENO oline;
105     register ADDRESS oaddr;
106     register LINETAB *lp;
107     FILETAB *ftp;
108     OBJLINE info;
109 
110     if (nlhdr.nlines == 0) {
111 	return;
112     }
113     linetab = alloc(nlhdr.nlines, LINETAB);
114     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
115 	lp->line = 0;
116     }
117     for (ftp = &filetab[0]; ftp < &filetab[nlhdr.nfiles]; ftp++) {
118 	if (ftp->lineindex < nlhdr.nlines) {
119 	    linetab[ftp->lineindex].line = ftp->line;
120 	}
121     }
122     oline = 0;
123     oaddr = 0;
124     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
125 	if (lp->line != 0) {
126 	    oline = lp->line;
127 	}
128 	info.together = getw(fp);
129 	oline += info.separate.lineincr;
130 	oaddr += info.separate.addrincr;
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 (%d)", symno);
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