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