148112Sbostic /*-
2*62195Sbostic * Copyright (c) 1980, 1993
3*62195Sbostic * The Regents of the University of California. All rights reserved.
448112Sbostic *
548112Sbostic * %sccs.include.redist.c%
648111Sbostic */
748111Sbostic
848111Sbostic #ifndef lint
9*62195Sbostic static char sccsid[] = "@(#)yyget.c 8.1 (Berkeley) 06/06/93";
1048112Sbostic #endif /* not lint */
1148111Sbostic
1248111Sbostic #include "whoami.h"
1348111Sbostic #include <0.h>
1448111Sbostic #include "tree_ty.h" /* must be included for yy.h */
1548111Sbostic #include "yy.h"
1648111Sbostic
1748111Sbostic #ifdef PXP
1848111Sbostic int yytokcnt;
1948111Sbostic #endif
2048111Sbostic
2148111Sbostic /*
2248111Sbostic * Readch returns the next
2348111Sbostic * character from the current
2448111Sbostic * input line or -1 on end-of-file.
2548111Sbostic * It also maintains yycol for use in
2648111Sbostic * printing error messages.
2748111Sbostic */
readch()2848111Sbostic readch()
2948111Sbostic {
3048111Sbostic register c;
3148111Sbostic
3248111Sbostic if (*bufp == '\n' && bufp >= charbuf) {
3348111Sbostic #ifdef PXP
3448111Sbostic yytokcnt = 0;
3548111Sbostic #endif
3648111Sbostic if (getline() < 0)
3748111Sbostic return (-1);
3848111Sbostic }
3948111Sbostic c = *++bufp;
4048111Sbostic if (c == '\t')
4148111Sbostic yycol = ((yycol + 8) & ~7);
4248111Sbostic else
4348111Sbostic yycol++;
4448111Sbostic return (c);
4548111Sbostic }
4648111Sbostic
4748111Sbostic /*
4848111Sbostic * Definitions of the structures used for the
4948111Sbostic * include facility. The variable "ibp" points
5048111Sbostic * to the getc buffer of the current input file.
5148111Sbostic * There are "inclev + 1" current include files,
5248111Sbostic * and information in saved in the incs stack
5348111Sbostic * whenever a new level of include nesting occurs.
5448111Sbostic *
5548111Sbostic * Ibp in the incs structure saves the pointer
5648111Sbostic * to the previous levels input buffer;
5748111Sbostic * filename saves the previous file name;
5848111Sbostic * Printed saves whether the previous file name
5948111Sbostic * had been printed before this nesting occurred;
6048111Sbostic * and yyline is the line we were on on the previous file.
6148111Sbostic */
6248111Sbostic
6348111Sbostic #define MAXINC 10
6448111Sbostic
6548111Sbostic struct inc {
6648111Sbostic FILE *ibp;
6748111Sbostic char *filename;
6848111Sbostic int Printed;
6948111Sbostic int yyline;
7048111Sbostic int yyLinpt;
7148111Sbostic } incs[MAXINC];
7248111Sbostic
7348111Sbostic extern char printed;
7448111Sbostic
7548111Sbostic int inclev = -1;
7648111Sbostic
7748111Sbostic #ifdef PXP
7848111Sbostic /*
7948111Sbostic * These initializations survive only if
8048111Sbostic * pxp is asked to pretty print one file.
8148111Sbostic * Otherwise they are destroyed by the initial
8248111Sbostic * call to getline.
8348111Sbostic */
8448111Sbostic char charbuf[CBSIZE] = " program x(output);\n";
8548111Sbostic int yycol = 8;
8648111Sbostic char *bufp = charbuf;
8748111Sbostic
8848111Sbostic #endif
8948111Sbostic /*
9048111Sbostic * YyLinpt is the seek pointer to the beginning of the
9148111Sbostic * next line in the file.
9248111Sbostic */
9348111Sbostic int yyLinpt;
9448111Sbostic
9548111Sbostic /*
9648111Sbostic * Getline places the next line
9748111Sbostic * from the input stream in the
9848111Sbostic * line buffer, returning -1 at YEOF.
9948111Sbostic */
getline()10048111Sbostic getline()
10148111Sbostic {
10248111Sbostic register char *cp;
10348111Sbostic register CHAR c;
10448111Sbostic #ifdef PXP
10548111Sbostic static char ateof;
10648111Sbostic #endif
10748111Sbostic register FILE *ib;
10848111Sbostic int i;
10948111Sbostic
11048111Sbostic if (opt('l') && yyprtd == 0)
11148111Sbostic yyoutline();
11248111Sbostic yyprtd = 0;
11348111Sbostic top:
11448111Sbostic yylinpt = yyLinpt;
11548111Sbostic yyline++;
11648111Sbostic yyseqid++;
11748111Sbostic cp = charbuf;
11848111Sbostic ib = ibp;
11948111Sbostic i = sizeof charbuf - 1;
12048111Sbostic for (;;) {
12148111Sbostic c = getc(ib);
12248111Sbostic if (c == EOF) {
12348111Sbostic if (uninclud())
12448111Sbostic goto top;
12548111Sbostic #ifdef PXP
12648111Sbostic if (ateof == 0 && bracket) {
12748111Sbostic (void) pstrcpy(charbuf, "begin end.\n");
12848111Sbostic ateof = 1;
12948111Sbostic goto out;
13048111Sbostic }
13148111Sbostic #endif
13248111Sbostic bufp = "\n";
13348111Sbostic yyline--;
13448111Sbostic yyseqid--;
13548111Sbostic yyprtd = 1;
13648111Sbostic return (-1);
13748111Sbostic }
13848111Sbostic *cp++ = c;
13948111Sbostic if (c == '\n')
14048111Sbostic break;
14148111Sbostic if (--i == 0) {
14248111Sbostic line = yyline;
14348111Sbostic error("Input line too long - QUIT");
14448111Sbostic pexit(DIED);
14548111Sbostic }
14648111Sbostic }
14748111Sbostic *cp = 0;
14848111Sbostic yyLinpt = yylinpt + cp - charbuf;
14948111Sbostic if (includ())
15048111Sbostic goto top;
15148111Sbostic #ifdef PXP
15248111Sbostic if (cp == &charbuf[1])
15348111Sbostic commnl();
15448111Sbostic else if (cp == &charbuf[2])
15548111Sbostic switch (charbuf[0]) {
15648111Sbostic case ' ':
15748111Sbostic commnlbl();
15848111Sbostic break;
15948111Sbostic case '\f':
16048111Sbostic commform();
16148111Sbostic }
16248111Sbostic #endif
16348111Sbostic if (opt('u'))
16448111Sbostic setuflg();
16548111Sbostic #ifdef PXP
16648111Sbostic out:
16748111Sbostic #endif
16848111Sbostic bufp = charbuf - 1;
16948111Sbostic yycol = 8;
17048111Sbostic return (1);
17148111Sbostic }
17248111Sbostic
17348111Sbostic /*
17448111Sbostic * Check an input line to see if it is a "#include" pseudo-statement.
17548111Sbostic * We allow arbitrary blanks in the line and the file name
17648111Sbostic * may be delimited by either 's or "s. A single semicolon
17748111Sbostic * may be placed after the name, but nothing else is allowed
17848111Sbostic */
includ()17948111Sbostic includ()
18048111Sbostic {
18148111Sbostic register char *cp, *dp;
18248111Sbostic char ch;
18348111Sbostic register struct inc *ip;
18448111Sbostic
18548111Sbostic cp = charbuf;
18648111Sbostic if (*cp++ != '#')
18748111Sbostic return (0);
18848111Sbostic cp = skipbl(cp);
18948111Sbostic for (dp = "include"; *dp; dp++)
19048111Sbostic if (*dp != *cp++)
19148111Sbostic return (0);
19248111Sbostic line = yyline;
19348111Sbostic cp = skipbl(cp);
19448111Sbostic ch = *cp++;
19548111Sbostic if (ch != '\'' && ch != '"') {
19648111Sbostic /*
19748111Sbostic * This should be a yerror flagging the place
19848111Sbostic * but its not worth figuring out the column.
19948111Sbostic */
20048111Sbostic line = yyline;
20148111Sbostic error("Include syntax error - expected ' or \" not found - QUIT");
20248111Sbostic pexit(DIED);
20348111Sbostic }
20448111Sbostic for (dp = cp; *dp != ch; dp++)
20548111Sbostic if (*dp == 0) {
20648111Sbostic line = yyline;
20748111Sbostic error("Missing closing %c for include file name - QUIT", (char *) ch);
20848111Sbostic pexit(DIED);
20948111Sbostic }
21048111Sbostic *dp++ = 0;
21148111Sbostic /*
21248111Sbostic * if (*dp == ';')
21348111Sbostic * dp++;
21448111Sbostic * dp = skipbl(dp);
21548111Sbostic * if (*dp != '\n') {
21648111Sbostic * line = yyline;
21748111Sbostic * error("Garbage after filename in include");
21848111Sbostic * pexit(DIED);
21948111Sbostic * }
22048111Sbostic */
22148111Sbostic if (!dotted(cp, 'i') && !dotted(cp, 'h')) {
22248111Sbostic line = yyline;
22348111Sbostic error("Include filename must end in .i or .h");
22448111Sbostic }
22548111Sbostic #ifdef PXP
22648111Sbostic commincl(cp, ch);
22748111Sbostic if (noinclude)
22848111Sbostic return (1);
22948111Sbostic #endif
23048111Sbostic inclev++;
23148111Sbostic if (inclev > MAXINC) {
23248111Sbostic line = yyline;
23348111Sbostic error("Absurdly deep include nesting - QUIT");
23448111Sbostic pexit(DIED);
23548111Sbostic }
23648111Sbostic ip = &incs[inclev];
23748111Sbostic ip->filename = filename;
23848111Sbostic filename = savestr(cp);
23948111Sbostic
24048111Sbostic #ifdef OBJ
24148111Sbostic /*
24248111Sbostic * For the debugger pdx, we need to note that we've changed files.
24348111Sbostic */
24448111Sbostic newfile(filename, 1);
24548111Sbostic #endif
24648111Sbostic
24748111Sbostic /*
24848111Sbostic * left over from before stdio
24948111Sbostic *
25048111Sbostic * cp = malloc(518);
25148111Sbostic * if (cp == -1) {
25248111Sbostic * error("Ran out of memory (include)");
25348111Sbostic * pexit(DIED);
25448111Sbostic * }
25548111Sbostic *
25648111Sbostic */
25748111Sbostic ip->ibp = ibp;
25848111Sbostic if ( ( ibp = fopen(filename, "r" ) ) == NULL ) {
25948111Sbostic perror(filename);
26048111Sbostic pexit(DIED);
26148111Sbostic }
26248111Sbostic if (inpflist(filename)) {
26348111Sbostic #ifdef PI
26448111Sbostic opush('l');
26548111Sbostic #endif
26648111Sbostic #ifdef PXP
26748111Sbostic opush('z');
26848111Sbostic #endif
26948111Sbostic }
27048111Sbostic ip->Printed = printed;
27148111Sbostic printed = 0;
27248111Sbostic ip->yyline = yyline;
27348111Sbostic yyline = 0;
27448111Sbostic ip->yyLinpt = yyLinpt;
27548111Sbostic yyLinpt = 0;
27648111Sbostic /*
27748111Sbostic * left over from before stdio
27848111Sbostic *
27948111Sbostic * ip->ibp = ibp;
28048111Sbostic * ibp = cp;
28148111Sbostic *
28248111Sbostic */
28348111Sbostic # ifdef PC
28448111Sbostic stabinclude( filename , TRUE );
28548111Sbostic # endif PC
28648111Sbostic return (1);
28748111Sbostic }
28848111Sbostic
28948111Sbostic char *
skipbl(ocp)29048111Sbostic skipbl(ocp)
29148111Sbostic char *ocp;
29248111Sbostic {
29348111Sbostic register char *cp;
29448111Sbostic
29548111Sbostic cp = ocp;
29648111Sbostic while (*cp == ' ' || *cp == '\t')
29748111Sbostic cp++;
29848111Sbostic return (cp);
29948111Sbostic }
30048111Sbostic
30148111Sbostic
30248111Sbostic /*
30348111Sbostic * At the end of an include,
30448111Sbostic * close the file, free the input buffer,
30548111Sbostic * and restore the environment before
30648111Sbostic * the "push", including the value of
30748111Sbostic * the z option for pxp and the l option for pi.
30848111Sbostic */
uninclud()30948111Sbostic uninclud()
31048111Sbostic {
31148111Sbostic register struct inc *ip;
31248111Sbostic
31348111Sbostic if (inclev < 0)
31448111Sbostic return (0);
31548111Sbostic /*
31648111Sbostic * left over from before stdio: becomes fclose ( ibp )
31748111Sbostic *
31848111Sbostic * (void) close(ibp[0]);
31948111Sbostic * free(ibp);
32048111Sbostic *
32148111Sbostic */
32248111Sbostic (void) fclose ( ibp );
32348111Sbostic ip = &incs[inclev];
32448111Sbostic ibp = ip->ibp;
32548111Sbostic yyline = ip->yyline;
32648111Sbostic if (inpflist(filename)) {
32748111Sbostic #ifdef PI
32848111Sbostic opop('l');
32948111Sbostic #endif
33048111Sbostic #ifdef PXP
33148111Sbostic opop('z');
33248111Sbostic #endif
33348111Sbostic }
33448111Sbostic filename = ip->filename;
33548111Sbostic
33648111Sbostic yyLinpt = ip->yyLinpt;
33748111Sbostic /*
33848111Sbostic * If we printed out the nested name,
33948111Sbostic * then we should print all covered names again.
34048111Sbostic * If we didn't print out the nested name
34148111Sbostic * we print the uncovered name only if it
34248111Sbostic * has not been printed before (unstack).
34348111Sbostic */
34448111Sbostic if (printed) {
34548111Sbostic printed = 0;
34648111Sbostic while (ip >= incs) {
34748111Sbostic ip->Printed = 0;
34848111Sbostic ip--;
34948111Sbostic }
35048111Sbostic } else
35148111Sbostic printed = ip->Printed;
35248111Sbostic # ifdef OBJ
35348111Sbostic /*
35448111Sbostic * For the debugger pdx, we need to note that we've changed files.
35548111Sbostic */
35648111Sbostic newfile(filename, yyline);
35748111Sbostic #endif
35848111Sbostic # ifdef PC
35948111Sbostic if ( inclev == 0 ) {
36048111Sbostic stabsource( filename );
36148111Sbostic } else {
36248111Sbostic stabinclude( filename , FALSE );
36348111Sbostic }
36448111Sbostic # endif PC
36548111Sbostic inclev--;
36648111Sbostic return (1);
36748111Sbostic }
368