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