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