xref: /original-bsd/usr.bin/pascal/src/savenl.c (revision deff14a8)
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 
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 
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 
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 
152 removenlfile()
153 {
154 	unlink(symname);
155 	unlink(strname);
156 	unlink(filesname);
157 	unlink(linesname);
158 }
159 
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 
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 
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 
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 
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