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