1 /* Copyright (c) 1982 Regents of the University of California */
2 
3 static char sccsid[] = "@(#)readobj.c 1.4 02/10/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 #include "objsym.rep"
19 
20 #define MAXSYMNO 2000
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 	linetab[ftp->lineindex].line = ftp->line;
119     }
120     oline = 0;
121     oaddr = 0;
122     for (lp = &linetab[0]; lp < &linetab[nlhdr.nlines]; lp++) {
123 	if (lp->line != 0) {
124 	    oline = lp->line;
125 	}
126 	info.together = getw(fp);
127 	oline += info.separate.lineincr;
128 	oaddr += info.separate.addrincr;
129 	lp->line = oline;
130 	lp->addr = oaddr;
131     }
132 }
133 
134 /*
135  * read in the symbols
136  */
137 
138 readsyms(fp)
139 FILE *fp;
140 {
141     register int i;
142     int symno;
143 
144     symtab = st_creat(nlhdr.nsyms);
145     for (i = 0; i < nlhdr.nsyms; i++) {
146 	symno = getw(fp);
147 	if (symno >= MAXSYMNO) {
148 	    panic("symbol number too large");
149 	}
150 	sym[symno] = readsym(fp);
151     }
152     if (backpatch() != 0) {
153 	panic("patchlist not empty after reading namelist");
154     }
155     if (program == NIL) {
156 	panic("no program");
157     }
158     maketypes();
159 }
160 
161 typedef struct patchinfo {
162     SYM **patchsym;
163     struct patchinfo *next_patch;
164 } PATCH;
165 
166 LOCAL PATCH *phead;
167 
168 /*
169  * Go through patchlist looking for symbol numbers for which the
170  * sym array now has a non-NIL entry.
171  *
172  * Afterwards, zap the sym array.
173  */
174 
175 int backpatch()
176 {
177     register PATCH *p, *last, *next;
178     register SYM *s, **t;
179     int count;
180 
181     last = NIL;
182     count = 0;
183     for (p = phead; p != NIL; p = next) {
184 	next = p->next_patch;
185 	t = p->patchsym;
186 	if ((s = sym[(int) *t]) != NIL) {
187 	    *t = s;
188 	    if (last == NIL) {
189 		phead = next;
190 	    } else {
191 		last->next_patch = next;
192 	    }
193 	    dispose(p);
194 	} else {
195 	    last = p;
196 	    count++;
197 	}
198     }
199     for (t = &sym[0]; t < &sym[MAXSYMNO]; t++) {
200 	*t = NIL;
201     }
202     return(count);
203 }
204 
205 /*
206  * Check to see if the given pointer (really symbol number) should
207  * be added to the patch list.  The argument is double indirect
208  * to do call by reference passing.
209  */
210 
211 chkpatch(p)
212 SYM **p;
213 {
214     register SYM *s, *t;
215     register PATCH *patch;
216 
217     if ((s = *p) != NIL) {
218 	if ((t = sym[(int) s]) != NIL) {
219 	    *p = t;
220 	} else {
221 	    patch = alloc(1, PATCH);
222 	    patch->patchsym = p;
223 	    patch->next_patch = phead;
224 	    phead = patch;
225 	}
226     }
227 }
228 
229 /*
230  * Free all the object information.
231  */
232 
233 objfree()
234 {
235     register int i;
236 
237     st_destroy(symtab);
238     dispose(stringtab);
239     dispose(filetab);
240     dispose(linetab);
241     clrfunctab();
242     for (i = 0; i < MAXSYMNO; i++) {
243 	sym[i] = NIL;
244     }
245 }
246