1 /*-
2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)savenl.c 8.2 (Berkeley) 05/24/94";
10 #endif /* not lint */
11
12 /*
13 * savenl - routines for saving namelist and line number information
14 *
15 * This module contains the routines that make pi dump a namelist
16 * at the end of the object file. We do this by first creating
17 * four temporary files in "startnlfile". One temp file contains
18 * the string table, one the symbol table, one the file name
19 * information and one the line number information.
20 *
21 * Prior to generation of the code for a statement the "lineno"
22 * routine is called to dump the line number and current object
23 * address. At the end of each block "savenl" is called to dump
24 * the strings and symbol structures.
25 *
26 * At the end of execution "copynlfile" is called and it copies
27 * the temp files onto the end of the obj file.
28 *
29 * In case of error, "removenlfile" is called to destroy the temp files.
30 *
31 * The only other changes to pi are in calling these routines from
32 *
33 * "main" (main.c)
34 * "yymain" (yymain.c)
35 * "funcend" (fend.c)
36 * "yyget" (yyget.c)
37 * "putline" (stat.c)
38 */
39
40 #include "whoami.h"
41 #ifdef OBJ
42 /*
43 * and the rest of the file
44 */
45 #include "0.h"
46 #include "objfmt.h"
47
48 #undef NIL
49
50 /*
51 * pdx header files
52 */
53
54 #include "../pdx/defs.h"
55 #include "../pdx/object.h"
56 #include "../pdx/object/objsym.rep"
57 #include "../pdx/mappings.h"
58 #include "../pdx/mappings/filetab.h"
59
60 LOCAL char symname[] = "/tmp/obj.symXXXXXX";
61 LOCAL char strname[] = "/tmp/obj.strXXXXXX";
62 LOCAL char filesname[] = "/tmp/obj.filesXXXXXX";
63 LOCAL char linesname[] = "/tmp/obj.linesXXXXXX";
64
65 LOCAL FILE *symfp;
66 LOCAL FILE *strfp;
67 LOCAL FILE *filesfp;
68 LOCAL FILE *linesfp;
69
70 LOCAL long nlsize;
71
72 extern FILE *fopen();
73
74 LOCAL putblock();
75 LOCAL putstring();
76
77 /*
78 * create temporary files for the namelist info
79 */
80
startnlfile()81 startnlfile()
82 {
83 nlsize = 0;
84 (void) mktemp(symname);
85 (void) mktemp(strname);
86 (void) mktemp(filesname);
87 (void) mktemp(linesname);
88 symfp = fopen(symname, "w");
89 strfp = fopen(strname, "w");
90 filesfp = fopen(filesname, "w");
91 linesfp = fopen(linesname, "w");
92 if (symfp==NULL || strfp==NULL || filesfp==NULL || linesfp==NULL) {
93 fprintf(stderr, "can't create /tmp/obj");
94 pexit(NOSTART);
95 }
96 newfile(filename, 1);
97 }
98
99 /*
100 * now copy the temp files back to obj; strings, symbols, file names, and lines
101 *
102 * There's some efficiency garbage here that uses straight system
103 * calls rather than standard I/O library calls.
104 */
105
copynlfile()106 copynlfile()
107 {
108 register int n;
109 int symfd, strfd, filesfd, linesfd;
110 char buff[BUFSIZ];
111
112 (void) fclose((FILE *) symfp);
113 (void) fclose((FILE *) strfp);
114 (void) fclose((FILE *) filesfp);
115 (void) fclose((FILE *) linesfp);
116 if (!opt('g')) {
117 removenlfile();
118 return;
119 }
120 symfd = open(symname, 0);
121 strfd = open(strname, 0);
122 filesfd = open(filesname, 0);
123 linesfd = open(linesname, 0);
124 if (symfd < 0 || strfd < 0 || filesfd < 0 || linesfd < 0) {
125 fprintf(stderr, "sync error on /tmp/obj");
126 pexit(ERRS);
127 }
128 if (lseek(ofil, (off_t)0, 2) == -1)
129 perror("copynlfile: lseek"), panic("copynlfile");
130 write(ofil, (char *) (&nlhdr), sizeof(nlhdr));
131 n = read(strfd, buff, BUFSIZ - sizeof(nlhdr));
132 write(ofil, buff, n);
133 cat(strfd);
134 cat(symfd);
135 cat(filesfd);
136 cat(linesfd);
137 removenlfile();
138 }
139
cat(fd)140 cat(fd)
141 int fd;
142 {
143 register int n;
144 char buff[BUFSIZ];
145
146 while ((n = read(fd, buff, BUFSIZ)) > 0) {
147 write(ofil, buff, n);
148 }
149 (void) close(fd);
150 }
151
removenlfile()152 removenlfile()
153 {
154 unlink(symname);
155 unlink(strname);
156 unlink(filesname);
157 unlink(linesname);
158 }
159
nlhdrsize()160 nlhdrsize()
161 {
162 int r;
163
164 if (!opt('g')) {
165 r = 0;
166 } else {
167 r = nlsize + sizeof(nlhdr);
168 }
169 return r;
170 }
171
172 #define isblock(s) (s->class == FUNC || s->class == PROC)
173 #define isbuiltin(s) ((s->nl_block&037) == 0 && isblock(s))
174 #define symno(p) (p==NULL ? 0 : nloff(p))
175
176 struct nls {
177 struct nl *nls_low;
178 struct nl *nls_high;
179 };
180
181 struct nl nl[], *nlp, ntab[], *nlact;
182
183 /*VARARGS*/
184 savenl(to, rout)
185 struct nl *to;
186 {
187 register struct nl *p;
188 register OBJSYM *s;
189 OBJSYM tmpsym;
190 struct nls *nlsp;
191
192 if (to != NIL) {
193 putblock((char *) rout);
194 } else {
195 putblock("main program");
196 }
197 nlsp = (struct nls *) nlact;
198 s = &tmpsym;
199 for (p = nlp; p != to;) {
200 if (p == nlsp->nls_low) {
201 if (nlsp == ((struct nls *) &ntab[0]))
202 break;
203 nlsp--;
204 p = nlsp->nls_high;
205 }
206 p--;
207 if (isbuiltin(p) || symno(p) == 0) {
208 continue;
209 }
210 nlhdr.nsyms++;
211 nlsize += sizeof(OBJSYM) + sizeof(int);
212 (void) putw(symno(p), symfp);
213 if (p->symbol != NULL) {
214 s->strindex = nlhdr.stringsize;
215 putstring(p->symbol);
216 } else {
217 s->strindex = 0;
218 }
219 s->oclass = p->class;
220 s->oblkno = (p->nl_block&037);
221 s->typno = symno(p->type);
222 s->chno = symno(p->chain);
223 s->osymvalue.orangev.lower = p->range[0];
224 s->osymvalue.orangev.upper = p->range[1];
225 if (isblock(p)) {
226 s->osymvalue.ofuncv.codeloc = p->value[NL_ENTLOC];
227 } else if (p->class == RECORD || p->class == VARNT) {
228 s->osymvalue.ovarnt.vtorecno = symno(p->ptr[2]);
229 s->osymvalue.ovarnt.vtagno = symno(p->ptr[3]);
230 }
231 fwrite((char *) s, sizeof(*s), 1, symfp);
232 }
233 }
234
235 /*
236 * Dump a line number and the current object location counter.
237 *
238 * To save space the difference from the previous line number and offset
239 * (one byte each) is dumped.
240 */
241
242 LOCAL int oline = 0;
243 LOCAL int olc = HEADER_BYTES;
244
lineno(line)245 lineno(line)
246 int line;
247 {
248 OBJLINE info;
249
250 if (line != oline) {
251 nlhdr.nlines++;
252 nlsize += sizeof(OBJLINE);
253 info.separate.lineincr = line - oline;
254 info.separate.addrincr = ((unsigned short) (lc - olc));
255 (void) putw((int) info.together, linesfp);
256 oline = line;
257 olc = (int) lc;
258 }
259 }
260
261 /*
262 * put out a file name entry, including:
263 *
264 * the current line number for the new file
265 * the current location counter
266 * the string table address of the file name
267 * an index into the current line number information
268 */
269
newfile(s,line)270 newfile(s, line)
271 char *s;
272 int line;
273 {
274 FILETAB ft;
275
276 nlhdr.nfiles++;
277 nlsize += sizeof(FILETAB);
278 ft.line = line;
279 oline = line;
280 if (lc == 0) {
281 ft.addr = 0;
282 } else {
283 ft.addr = ((LINENO) lc - HEADER_BYTES );
284 }
285 ft.filename = (char *) nlhdr.stringsize;
286 putstring(s);
287 ft.lineindex = nlhdr.nlines;
288 fwrite((char *) (&ft), sizeof(ft), 1, filesfp);
289 }
290
291 /*
292 * put out a dummy symbol at the beginning of a block
293 */
294
putblock(s)295 LOCAL putblock(s)
296 char *s;
297 {
298 static OBJSYM zerosym;
299
300 nlhdr.nsyms++;
301 nlsize += sizeof(OBJSYM) + sizeof(int);
302 (void) putw(0, symfp);
303 zerosym.strindex = nlhdr.stringsize;
304 putstring(s);
305 fwrite((char *) (&zerosym), sizeof(zerosym), 1, symfp);
306 }
307
308 /*
309 * put out a string to the string table file
310 */
311
putstring(s)312 LOCAL putstring(s)
313 char *s;
314 {
315 register char *p;
316
317 for (p = s; *p != '\0'; p++) {
318 putc(*p, strfp);
319 }
320 nlhdr.stringsize += (p - s + 1);
321 nlsize += (p - s + 1);
322 putc('\0', strfp);
323 }
324 #endif OBJ
325