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