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