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