148116Sbostic /*-
2*62223Sbostic * Copyright (c) 1980, 1993
3*62223Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622205Sdist */
7785Speter
815943Smckusick #ifndef lint
9*62223Sbostic static char sccsid[] = "@(#)yyget.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11785Speter
12785Speter #include "whoami.h"
1344620Sbostic #include <0.h>
1415943Smckusick #include "tree_ty.h" /* must be included for yy.h */
15785Speter #include "yy.h"
16785Speter
17785Speter #ifdef PXP
18785Speter int yytokcnt;
19785Speter #endif
20785Speter
21785Speter /*
22785Speter * Readch returns the next
23785Speter * character from the current
24785Speter * input line or -1 on end-of-file.
25785Speter * It also maintains yycol for use in
26785Speter * printing error messages.
27785Speter */
readch()28785Speter readch()
29785Speter {
3015943Smckusick register c;
31785Speter
32785Speter if (*bufp == '\n' && bufp >= charbuf) {
33785Speter #ifdef PXP
34785Speter yytokcnt = 0;
35785Speter #endif
36785Speter if (getline() < 0)
37785Speter return (-1);
38785Speter }
39785Speter c = *++bufp;
40785Speter if (c == '\t')
41785Speter yycol = ((yycol + 8) & ~7);
42785Speter else
43785Speter yycol++;
44785Speter return (c);
45785Speter }
46785Speter
47785Speter /*
48785Speter * Definitions of the structures used for the
49785Speter * include facility. The variable "ibp" points
50785Speter * to the getc buffer of the current input file.
51785Speter * There are "inclev + 1" current include files,
52785Speter * and information in saved in the incs stack
53785Speter * whenever a new level of include nesting occurs.
54785Speter *
55785Speter * Ibp in the incs structure saves the pointer
56785Speter * to the previous levels input buffer;
57785Speter * filename saves the previous file name;
58785Speter * Printed saves whether the previous file name
59785Speter * had been printed before this nesting occurred;
60785Speter * and yyline is the line we were on on the previous file.
61785Speter */
62785Speter
63785Speter #define MAXINC 10
64785Speter
65785Speter struct inc {
66785Speter FILE *ibp;
67785Speter char *filename;
68785Speter int Printed;
69785Speter int yyline;
70785Speter int yyLinpt;
71785Speter } incs[MAXINC];
72785Speter
7312394Speter extern char printed;
74785Speter
75785Speter int inclev = -1;
76785Speter
77785Speter #ifdef PXP
78785Speter /*
79785Speter * These initializations survive only if
80785Speter * pxp is asked to pretty print one file.
81785Speter * Otherwise they are destroyed by the initial
82785Speter * call to getline.
83785Speter */
84785Speter char charbuf[CBSIZE] = " program x(output);\n";
85785Speter int yycol = 8;
86785Speter char *bufp = charbuf;
87785Speter
88785Speter #endif
89785Speter /*
90785Speter * YyLinpt is the seek pointer to the beginning of the
91785Speter * next line in the file.
92785Speter */
93785Speter int yyLinpt;
94785Speter
95785Speter /*
96785Speter * Getline places the next line
97785Speter * from the input stream in the
98785Speter * line buffer, returning -1 at YEOF.
99785Speter */
getline()100785Speter getline()
101785Speter {
102785Speter register char *cp;
103785Speter register CHAR c;
104785Speter #ifdef PXP
105785Speter static char ateof;
106785Speter #endif
107785Speter register FILE *ib;
108785Speter int i;
109785Speter
110785Speter if (opt('l') && yyprtd == 0)
111785Speter yyoutline();
112785Speter yyprtd = 0;
113785Speter top:
114785Speter yylinpt = yyLinpt;
115785Speter yyline++;
116785Speter yyseqid++;
117785Speter cp = charbuf;
118785Speter ib = ibp;
119785Speter i = sizeof charbuf - 1;
120785Speter for (;;) {
121785Speter c = getc(ib);
122785Speter if (c == EOF) {
123785Speter if (uninclud())
124785Speter goto top;
125785Speter #ifdef PXP
126785Speter if (ateof == 0 && bracket) {
12715943Smckusick (void) pstrcpy(charbuf, "begin end.\n");
128785Speter ateof = 1;
129785Speter goto out;
130785Speter }
131785Speter #endif
132785Speter bufp = "\n";
133785Speter yyline--;
134785Speter yyseqid--;
135785Speter yyprtd = 1;
136785Speter return (-1);
137785Speter }
138785Speter *cp++ = c;
139785Speter if (c == '\n')
140785Speter break;
141785Speter if (--i == 0) {
142785Speter line = yyline;
143785Speter error("Input line too long - QUIT");
144785Speter pexit(DIED);
145785Speter }
146785Speter }
147785Speter *cp = 0;
148785Speter yyLinpt = yylinpt + cp - charbuf;
149785Speter if (includ())
150785Speter goto top;
151785Speter #ifdef PXP
152785Speter if (cp == &charbuf[1])
153785Speter commnl();
154785Speter else if (cp == &charbuf[2])
155785Speter switch (charbuf[0]) {
156785Speter case ' ':
157785Speter commnlbl();
158785Speter break;
159785Speter case '\f':
160785Speter commform();
161785Speter }
162785Speter #endif
163785Speter if (opt('u'))
164785Speter setuflg();
16515943Smckusick #ifdef PXP
166785Speter out:
16715943Smckusick #endif
168785Speter bufp = charbuf - 1;
169785Speter yycol = 8;
170785Speter return (1);
171785Speter }
172785Speter
173785Speter /*
174785Speter * Check an input line to see if it is a "#include" pseudo-statement.
175785Speter * We allow arbitrary blanks in the line and the file name
176785Speter * may be delimited by either 's or "s. A single semicolon
177785Speter * may be placed after the name, but nothing else is allowed
178785Speter */
includ()179785Speter includ()
180785Speter {
181785Speter register char *cp, *dp;
182785Speter char ch;
183785Speter register struct inc *ip;
184785Speter
185785Speter cp = charbuf;
186785Speter if (*cp++ != '#')
187785Speter return (0);
188785Speter cp = skipbl(cp);
189785Speter for (dp = "include"; *dp; dp++)
190785Speter if (*dp != *cp++)
191785Speter return (0);
192785Speter line = yyline;
193785Speter cp = skipbl(cp);
194785Speter ch = *cp++;
195785Speter if (ch != '\'' && ch != '"') {
196785Speter /*
197785Speter * This should be a yerror flagging the place
198785Speter * but its not worth figuring out the column.
199785Speter */
200785Speter line = yyline;
201785Speter error("Include syntax error - expected ' or \" not found - QUIT");
202785Speter pexit(DIED);
203785Speter }
204785Speter for (dp = cp; *dp != ch; dp++)
205785Speter if (*dp == 0) {
206785Speter line = yyline;
20715943Smckusick error("Missing closing %c for include file name - QUIT", (char *) ch);
208785Speter pexit(DIED);
209785Speter }
210785Speter *dp++ = 0;
211785Speter /*
212785Speter * if (*dp == ';')
213785Speter * dp++;
214785Speter * dp = skipbl(dp);
215785Speter * if (*dp != '\n') {
216785Speter * line = yyline;
217785Speter * error("Garbage after filename in include");
218785Speter * pexit(DIED);
219785Speter * }
220785Speter */
22112394Speter if (!dotted(cp, 'i') && !dotted(cp, 'h')) {
222785Speter line = yyline;
223785Speter error("Include filename must end in .i or .h");
224785Speter }
225785Speter #ifdef PXP
226785Speter commincl(cp, ch);
227785Speter if (noinclude)
228785Speter return (1);
229785Speter #endif
230785Speter inclev++;
231785Speter if (inclev > MAXINC) {
232785Speter line = yyline;
233785Speter error("Absurdly deep include nesting - QUIT");
234785Speter pexit(DIED);
235785Speter }
236785Speter ip = &incs[inclev];
237785Speter ip->filename = filename;
238785Speter filename = savestr(cp);
2395654Slinton
2405654Slinton #ifdef OBJ
241785Speter /*
2425654Slinton * For the debugger pdx, we need to note that we've changed files.
2435654Slinton */
2445654Slinton newfile(filename, 1);
2455654Slinton #endif
2465654Slinton
2475654Slinton /*
248785Speter * left over from before stdio
249785Speter *
250785Speter * cp = malloc(518);
251785Speter * if (cp == -1) {
252785Speter * error("Ran out of memory (include)");
253785Speter * pexit(DIED);
254785Speter * }
255785Speter *
256785Speter */
257785Speter ip->ibp = ibp;
258785Speter if ( ( ibp = fopen(filename, "r" ) ) == NULL ) {
259785Speter perror(filename);
260785Speter pexit(DIED);
261785Speter }
262785Speter if (inpflist(filename)) {
263785Speter #ifdef PI
264785Speter opush('l');
265785Speter #endif
266785Speter #ifdef PXP
267785Speter opush('z');
268785Speter #endif
269785Speter }
270785Speter ip->Printed = printed;
271785Speter printed = 0;
272785Speter ip->yyline = yyline;
273785Speter yyline = 0;
274785Speter ip->yyLinpt = yyLinpt;
275785Speter yyLinpt = 0;
276785Speter /*
277785Speter * left over from before stdio
278785Speter *
279785Speter * ip->ibp = ibp;
280785Speter * ibp = cp;
281785Speter *
282785Speter */
283785Speter # ifdef PC
28415944Smckusick stabinclude( filename , TRUE );
285785Speter # endif PC
286785Speter return (1);
287785Speter }
288785Speter
28915943Smckusick char *
skipbl(ocp)290785Speter skipbl(ocp)
291785Speter char *ocp;
292785Speter {
293785Speter register char *cp;
294785Speter
295785Speter cp = ocp;
296785Speter while (*cp == ' ' || *cp == '\t')
297785Speter cp++;
298785Speter return (cp);
299785Speter }
300785Speter
301785Speter
302785Speter /*
303785Speter * At the end of an include,
304785Speter * close the file, free the input buffer,
305785Speter * and restore the environment before
306785Speter * the "push", including the value of
307785Speter * the z option for pxp and the l option for pi.
308785Speter */
uninclud()309785Speter uninclud()
310785Speter {
311785Speter register struct inc *ip;
312785Speter
313785Speter if (inclev < 0)
314785Speter return (0);
315785Speter /*
316785Speter * left over from before stdio: becomes fclose ( ibp )
317785Speter *
31815943Smckusick * (void) close(ibp[0]);
319785Speter * free(ibp);
320785Speter *
321785Speter */
32215943Smckusick (void) fclose ( ibp );
323785Speter ip = &incs[inclev];
324785Speter ibp = ip->ibp;
325785Speter yyline = ip->yyline;
326785Speter if (inpflist(filename)) {
327785Speter #ifdef PI
328785Speter opop('l');
329785Speter #endif
330785Speter #ifdef PXP
331785Speter opop('z');
332785Speter #endif
333785Speter }
334785Speter filename = ip->filename;
3355654Slinton
336785Speter yyLinpt = ip->yyLinpt;
337785Speter /*
338785Speter * If we printed out the nested name,
339785Speter * then we should print all covered names again.
340785Speter * If we didn't print out the nested name
341785Speter * we print the uncovered name only if it
342785Speter * has not been printed before (unstack).
343785Speter */
344785Speter if (printed) {
345785Speter printed = 0;
346785Speter while (ip >= incs) {
347785Speter ip->Printed = 0;
348785Speter ip--;
349785Speter }
350785Speter } else
351785Speter printed = ip->Printed;
3525757Slinton # ifdef OBJ
3535757Slinton /*
3545757Slinton * For the debugger pdx, we need to note that we've changed files.
3555757Slinton */
3565757Slinton newfile(filename, yyline);
3575757Slinton #endif
358785Speter # ifdef PC
359785Speter if ( inclev == 0 ) {
360785Speter stabsource( filename );
361785Speter } else {
36215944Smckusick stabinclude( filename , FALSE );
363785Speter }
364785Speter # endif PC
365785Speter inclev--;
366785Speter return (1);
367785Speter }
368