xref: /original-bsd/usr.bin/pascal/src/yyget.c (revision 552e81d8)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 static	char sccsid[] = "@(#)yyget.c 1.1 08/27/80";
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  *	left over from before stdio
231  *
232  *	cp = malloc(518);
233  *	if (cp == -1) {
234  *		error("Ran out of memory (include)");
235  *		pexit(DIED);
236  *	}
237  *
238  */
239 	ip->ibp = ibp;
240 	if ( ( ibp = fopen(filename, "r" ) ) == NULL ) {
241 		perror(filename);
242 		pexit(DIED);
243 	}
244 	if (inpflist(filename)) {
245 #ifdef PI
246 		opush('l');
247 #endif
248 #ifdef PXP
249 		opush('z');
250 #endif
251 	}
252 	ip->Printed = printed;
253 	printed = 0;
254 	ip->yyline = yyline;
255 	yyline = 0;
256 	ip->yyLinpt = yyLinpt;
257 	yyLinpt = 0;
258 /*
259  *	left over from before stdio
260  *
261  *	ip->ibp = ibp;
262  *	ibp = cp;
263  *
264  */
265 #	ifdef PC
266 	    stabinclude( filename );
267 #	endif PC
268 	return (1);
269 }
270 
271 skipbl(ocp)
272 	char *ocp;
273 {
274 	register char *cp;
275 
276 	cp = ocp;
277 	while (*cp == ' ' || *cp == '\t')
278 		cp++;
279 	return (cp);
280 }
281 
282 
283 /*
284  * At the end of an include,
285  * close the file, free the input buffer,
286  * and restore the environment before
287  * the "push", including the value of
288  * the z option for pxp and the l option for pi.
289  */
290 uninclud()
291 {
292 	register struct inc *ip;
293 
294 	if (inclev < 0)
295 		return (0);
296 /*
297  *	left over from before stdio: becomes fclose ( ibp )
298  *
299  *	close(ibp[0]);
300  *	free(ibp);
301  *
302  */
303 	fclose ( ibp );
304 	ip = &incs[inclev];
305 	ibp = ip->ibp;
306 	yyline = ip->yyline;
307 	if (inpflist(filename)) {
308 #ifdef PI
309 		opop('l');
310 #endif
311 #ifdef PXP
312 		opop('z');
313 #endif
314 	}
315 	filename = ip->filename;
316 	yyLinpt = ip->yyLinpt;
317 	/*
318 	 * If we printed out the nested name,
319 	 * then we should print all covered names again.
320 	 * If we didn't print out the nested name
321 	 * we print the uncovered name only if it
322 	 * has not been printed before (unstack).
323 	 */
324 	if (printed) {
325 		printed = 0;
326 		while (ip >= incs) {
327 			ip->Printed = 0;
328 			ip--;
329 		}
330 	} else
331 		printed = ip->Printed;
332 #	ifdef PC
333 	    if ( inclev == 0 ) {
334 		stabsource( filename );
335 	    } else {
336 		stabinclude( filename );
337 	    }
338 #	endif PC
339 	inclev--;
340 	return (1);
341 }
342