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