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