xref: /original-bsd/usr.bin/pascal/pxp/yyget.c (revision c3e32dec)
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[] = "@(#)yyget.c	8.1 (Berkeley) 06/06/93";
10 #endif /* not lint */
11 
12 #include "whoami.h"
13 #include <0.h>
14 #include "tree_ty.h"	/* must be included for yy.h */
15 #include "yy.h"
16 
17 #ifdef PXP
18 int	yytokcnt;
19 #endif
20 
21 /*
22  * Readch returns the next
23  * character from the current
24  * input line or -1 on end-of-file.
25  * It also maintains yycol for use in
26  * printing error messages.
27  */
28 readch()
29 {
30 	register c;
31 
32 	if (*bufp == '\n' && bufp >= charbuf) {
33 #ifdef PXP
34 		yytokcnt = 0;
35 #endif
36 		if (getline() < 0)
37 			return (-1);
38 	}
39 	c = *++bufp;
40 	if (c == '\t')
41 		yycol = ((yycol + 8) & ~7);
42 	else
43 		yycol++;
44 	return (c);
45 }
46 
47 /*
48  * Definitions of the structures used for the
49  * include facility.  The variable "ibp" points
50  * to the getc buffer of the current input file.
51  * There are "inclev + 1" current include files,
52  * and information in saved in the incs stack
53  * whenever a new level of include nesting occurs.
54  *
55  * Ibp in the incs structure saves the pointer
56  * to the previous levels input buffer;
57  * filename saves the previous file name;
58  * Printed saves whether the previous file name
59  * had been printed before this nesting occurred;
60  * and yyline is the line we were on on the previous file.
61  */
62 
63 #define	MAXINC	10
64 
65 struct inc {
66 	FILE	*ibp;
67 	char	*filename;
68 	int	Printed;
69 	int	yyline;
70 	int	yyLinpt;
71 } incs[MAXINC];
72 
73 extern	char printed;
74 
75 int	inclev	= -1;
76 
77 #ifdef PXP
78 /*
79  * These initializations survive only if
80  * pxp is asked to pretty print one file.
81  * Otherwise they are destroyed by the initial
82  * call to getline.
83  */
84 char	charbuf[CBSIZE]	= " program x(output);\n";
85 int	yycol = 8;
86 char	*bufp = charbuf;
87 
88 #endif
89 /*
90  * YyLinpt is the seek pointer to the beginning of the
91  * next line in the file.
92  */
93 int	yyLinpt;
94 
95 /*
96  * Getline places the next line
97  * from the input stream in the
98  * line buffer, returning -1 at YEOF.
99  */
100 getline()
101 {
102 	register char *cp;
103 	register CHAR c;
104 #ifdef PXP
105 	static char ateof;
106 #endif
107 	register FILE *ib;
108 	int i;
109 
110 	if (opt('l') && yyprtd == 0)
111 		yyoutline();
112 	yyprtd = 0;
113 top:
114 	yylinpt = yyLinpt;
115 	yyline++;
116 	yyseqid++;
117 	cp = charbuf;
118 	ib = ibp;
119 	i = sizeof charbuf - 1;
120 	for (;;) {
121 		c = getc(ib);
122 		if (c == EOF) {
123 			if (uninclud())
124 				goto top;
125 #ifdef PXP
126 			if (ateof == 0 && bracket) {
127 				(void) pstrcpy(charbuf, "begin end.\n");
128 				ateof = 1;
129 				goto out;
130 			}
131 #endif
132 			bufp = "\n";
133 			yyline--;
134 			yyseqid--;
135 			yyprtd = 1;
136 			return (-1);
137 		}
138 		*cp++ = c;
139 		if (c == '\n')
140 			break;
141 		if (--i == 0) {
142 			line = yyline;
143 			error("Input line too long - QUIT");
144 			pexit(DIED);
145 		}
146 	}
147 	*cp = 0;
148 	yyLinpt = yylinpt + cp - charbuf;
149 	if (includ())
150 		goto top;
151 #ifdef PXP
152 	if (cp == &charbuf[1])
153 		commnl();
154 	else if (cp == &charbuf[2])
155 		switch (charbuf[0]) {
156 			case ' ':
157 				commnlbl();
158 				break;
159 			case '\f':
160 				commform();
161 		}
162 #endif
163 	if (opt('u'))
164 		setuflg();
165 #ifdef PXP
166 out:
167 #endif
168 	bufp = charbuf - 1;
169 	yycol = 8;
170 	return (1);
171 }
172 
173 /*
174  * Check an input line to see if it is a "#include" pseudo-statement.
175  * We allow arbitrary blanks in the line and the file name
176  * may be delimited by either 's or "s.  A single semicolon
177  * may be placed after the name, but nothing else is allowed
178  */
179 includ()
180 {
181 	register char *cp, *dp;
182 	char ch;
183 	register struct inc *ip;
184 
185 	cp = charbuf;
186 	if (*cp++ != '#')
187 		return (0);
188 	cp = skipbl(cp);
189 	for (dp = "include"; *dp; dp++)
190 		if (*dp != *cp++)
191 			return (0);
192 	line = yyline;
193 	cp = skipbl(cp);
194 	ch = *cp++;
195 	if (ch != '\'' && ch != '"') {
196 		/*
197 		 * This should be a yerror flagging the place
198 		 * but its not worth figuring out the column.
199 		 */
200 		line = yyline;
201 		error("Include syntax error - expected ' or \" not found - QUIT");
202 		pexit(DIED);
203 	}
204 	for (dp = cp; *dp != ch; dp++)
205 		if (*dp == 0) {
206 			line = yyline;
207 			error("Missing closing %c for include file name - QUIT", (char *) ch);
208 			pexit(DIED);
209 		}
210 	*dp++ = 0;
211 /*
212  *	if (*dp == ';')
213  *		dp++;
214  *	dp = skipbl(dp);
215  *	if (*dp != '\n') {
216  *		line = yyline;
217  *		error("Garbage after filename in include");
218  *		pexit(DIED);
219  *	}
220  */
221 	if (!dotted(cp, 'i') && !dotted(cp, 'h')) {
222 		line = yyline;
223 		error("Include filename must end in .i or .h");
224 	}
225 #ifdef PXP
226 	commincl(cp, ch);
227 	if (noinclude)
228 		return (1);
229 #endif
230 	inclev++;
231 	if (inclev > MAXINC) {
232 		line = yyline;
233 		error("Absurdly deep include nesting - QUIT");
234 		pexit(DIED);
235 	}
236 	ip = &incs[inclev];
237 	ip->filename = filename;
238 	filename = savestr(cp);
239 
240 #ifdef OBJ
241 /*
242  * For the debugger pdx, we need to note that we've changed files.
243  */
244 	newfile(filename, 1);
245 #endif
246 
247 /*
248  *	left over from before stdio
249  *
250  *	cp = malloc(518);
251  *	if (cp == -1) {
252  *		error("Ran out of memory (include)");
253  *		pexit(DIED);
254  *	}
255  *
256  */
257 	ip->ibp = ibp;
258 	if ( ( ibp = fopen(filename, "r" ) ) == NULL ) {
259 		perror(filename);
260 		pexit(DIED);
261 	}
262 	if (inpflist(filename)) {
263 #ifdef PI
264 		opush('l');
265 #endif
266 #ifdef PXP
267 		opush('z');
268 #endif
269 	}
270 	ip->Printed = printed;
271 	printed = 0;
272 	ip->yyline = yyline;
273 	yyline = 0;
274 	ip->yyLinpt = yyLinpt;
275 	yyLinpt = 0;
276 /*
277  *	left over from before stdio
278  *
279  *	ip->ibp = ibp;
280  *	ibp = cp;
281  *
282  */
283 #	ifdef PC
284 	    stabinclude( filename , TRUE );
285 #	endif PC
286 	return (1);
287 }
288 
289 char *
290 skipbl(ocp)
291 	char *ocp;
292 {
293 	register char *cp;
294 
295 	cp = ocp;
296 	while (*cp == ' ' || *cp == '\t')
297 		cp++;
298 	return (cp);
299 }
300 
301 
302 /*
303  * At the end of an include,
304  * close the file, free the input buffer,
305  * and restore the environment before
306  * the "push", including the value of
307  * the z option for pxp and the l option for pi.
308  */
309 uninclud()
310 {
311 	register struct inc *ip;
312 
313 	if (inclev < 0)
314 		return (0);
315 /*
316  *	left over from before stdio: becomes fclose ( ibp )
317  *
318  *	(void) close(ibp[0]);
319  *	free(ibp);
320  *
321  */
322 	(void) fclose ( ibp );
323 	ip = &incs[inclev];
324 	ibp = ip->ibp;
325 	yyline = ip->yyline;
326 	if (inpflist(filename)) {
327 #ifdef PI
328 		opop('l');
329 #endif
330 #ifdef PXP
331 		opop('z');
332 #endif
333 	}
334 	filename = ip->filename;
335 
336 	yyLinpt = ip->yyLinpt;
337 	/*
338 	 * If we printed out the nested name,
339 	 * then we should print all covered names again.
340 	 * If we didn't print out the nested name
341 	 * we print the uncovered name only if it
342 	 * has not been printed before (unstack).
343 	 */
344 	if (printed) {
345 		printed = 0;
346 		while (ip >= incs) {
347 			ip->Printed = 0;
348 			ip--;
349 		}
350 	} else
351 		printed = ip->Printed;
352 #	ifdef OBJ
353 	/*
354 	 * For the debugger pdx, we need to note that we've changed files.
355 	 */
356 	newfile(filename, yyline);
357 #endif
358 #	ifdef PC
359 	    if ( inclev == 0 ) {
360 		stabsource( filename );
361 	    } else {
362 		stabinclude( filename , FALSE );
363 	    }
364 #	endif PC
365 	inclev--;
366 	return (1);
367 }
368