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