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