xref: /original-bsd/old/make/gram.y (revision a910c8b7)
1 %{#include "defs"
2 static	char *sccsid = "@(#)gram.y	4.1 (Berkeley) 81/02/28";
3 %}
4 
5 %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER
6 %union
7 	{
8 	struct shblock *yshblock;
9 	struct depblock *ydepblock;
10 	struct nameblock *ynameblock;
11 	}
12 
13 %type <yshblock> SHELLINE, shlist, shellist
14 %type <ynameblock> NAME, namelist
15 %type <ydepblock> deplist, dlist
16 
17 
18 %%
19 
20 %{
21 struct depblock *pp;
22 FSTATIC struct shblock *prevshp;
23 
24 FSTATIC struct nameblock *lefts[NLEFTS];
25 struct nameblock *leftp;
26 FSTATIC int nlefts;
27 
28 struct lineblock *lp, *lpp;
29 FSTATIC struct depblock *prevdep;
30 FSTATIC int sepc;
31 %}
32 
33 
34 file:
35 	| file comline
36 	;
37 
38 comline:  START
39 	| MACRODEF
40 	| START namelist deplist shellist = {
41 	    while( --nlefts >= 0)
42 		{
43 		leftp = lefts[nlefts];
44 		if(leftp->septype == 0)
45 			leftp->septype = sepc;
46 		else if(leftp->septype != sepc)
47 			fprintf(stderr, "Inconsistent rules lines for `%s'\n",
48 				leftp->namep);
49 		else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0)
50 			{
51 			for(lp=leftp->linep; lp->nxtlineblock!=0; lp=lp->nxtlineblock)
52 			    if(lp->shp)
53 				fprintf(stderr, "Multiple rules lines for `%s'\n",
54 				    leftp->namep);
55 			}
56 
57 		lp = ALLOC(lineblock);
58 		lp->nxtlineblock = NULL;
59 		lp->depp = $3;
60 		lp->shp = $4;
61 
62 		if(! unequal(leftp->namep, ".SUFFIXES") && $3==0)
63 			leftp->linep = 0;
64 		else if(leftp->linep == 0)
65 			leftp->linep = lp;
66 		else	{
67 			for(lpp = leftp->linep; lpp->nxtlineblock;
68 				lpp = lpp->nxtlineblock) ;
69 				if(sepc==ALLDEPS && leftp->namep[0]=='.')
70 					lpp->shp = 0;
71 			lpp->nxtlineblock = lp;
72 			}
73 		}
74 	}
75 	| error
76 	;
77 
78 namelist: NAME	= { lefts[0] = $1; nlefts = 1; }
79 	| namelist NAME	= { lefts[nlefts++] = $2;
80 	    	if(nlefts>=NLEFTS) fatal("Too many lefts"); }
81 	;
82 
83 deplist:
84 		{
85 		char junk[10];
86 		sprintf(junk, "%d", yylineno);
87 		fatal1("Must be a separator on rules line %s", junk);
88 		}
89 	| dlist
90 	;
91 
92 dlist:  sepchar	= { prevdep = 0;  $$ = 0; }
93 	| dlist NAME	= {
94 			  pp = ALLOC(depblock);
95 			  pp->nxtdepblock = NULL;
96 			  pp->depname = $2;
97 			  if(prevdep == 0) $$ = pp;
98 			  else  prevdep->nxtdepblock = pp;
99 			  prevdep = pp;
100 			  }
101 	;
102 
103 sepchar:  COLON 	= { sepc = ALLDEPS; }
104 	| DOUBLECOLON	= { sepc = SOMEDEPS; }
105 	;
106 
107 shellist:	= {$$ = 0; }
108 	| shlist = { $$ = $1; }
109 	;
110 
111 shlist:	SHELLINE   = { $$ = $1;  prevshp = $1; }
112 	| shlist SHELLINE = { $$ = $1;
113 			prevshp->nxtshblock = $2;
114 			prevshp = $2;
115 			}
116 	;
117 
118 %%
119 
120 char *zznextc;	/* zero if need another line; otherwise points to next char */
121 int yylineno;
122 extern FILE * fin;
123 
124 yylex()
125 {
126 register char *p;
127 register char *q;
128 char word[INMAX];
129 
130 if(zznextc == 0)
131 	return( nextlin() );
132 
133 while( isspace(*zznextc) )
134 	++zznextc;
135 
136 if(*zznextc == '\0')
137 	return( nextlin() );
138 
139 if(*zznextc == ':')
140 	{
141 	if(*++zznextc == ':')
142 		{
143 		++zznextc;
144 		return(DOUBLECOLON);
145 		}
146 	else	return(COLON);
147 	}
148 
149 if(*zznextc == '>')
150 	{
151 	++zznextc;
152 	return(GREATER);
153 	}
154 
155 if(*zznextc == ';')
156 	return( retsh(zznextc) );
157 
158 p = zznextc;
159 q = word;
160 
161 while( ! ( funny[*p] & TERMINAL) )
162 	*q++ = *p++;
163 
164 if(p != zznextc)
165 	{
166 	*q = '\0';
167 	if((yylval.ynameblock=srchname(word))==0)
168 		yylval.ynameblock = makename(word);
169 	zznextc = p;
170 	return(NAME);
171 	}
172 
173 else	{
174 	fprintf(stderr,"Bad character %c (octal %o), line %d",
175 		*zznextc,*zznextc,yylineno);
176 	fatal( (char *) NULL );
177 	}
178 return(0);	/* never executed */
179 }
180 
181 
182 
183 
184 
185 retsh(q)
186 char *q;
187 {
188 register char *p;
189 struct shblock *sp;
190 char *copys();
191 
192 for(p=q+1 ; *p==' '||*p=='\t' ; ++p)  ;
193 
194 sp = ALLOC(shblock);
195 sp->nxtshblock = NULL;
196 sp->shbp = (fin == NULL ? p : copys(p) );
197 yylval.yshblock = sp;
198 zznextc = 0;
199 return(SHELLINE);
200 }
201 
202 nextlin()
203 {
204 static char yytext[INMAX];
205 static char *yytextl	= yytext+INMAX;
206 char *text, templin[INMAX];
207 register char c;
208 register char *p, *t;
209 char lastch, *lastchp;
210 extern char **linesptr;
211 int incom;
212 int kc;
213 
214 again:
215 
216 	incom = NO;
217 	zznextc = 0;
218 
219 if(fin == NULL)
220 	{
221 	if( (text = *linesptr++) == 0)
222 		return(0);
223 	++yylineno;
224 	}
225 
226 else	{
227 	for(p = text = yytext ; p<yytextl ; *p++ = kc)
228 		switch(kc = getc(fin))
229 			{
230 			case '\t':
231 				if(p != yytext)
232 					break;
233 			case ';':
234 				incom = YES;
235 				break;
236 
237 			case '#':
238 				if(! incom)
239 					kc = '\0';
240 				break;
241 
242 			case '\n':
243 				++yylineno;
244 				if(p==yytext || p[-1]!='\\')
245 					{
246 					*p = '\0';
247 					goto endloop;
248 					}
249 				p[-1] = ' ';
250 				while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n')
251 					if(kc == '\n')
252 						++yylineno;
253 
254 				if(kc != EOF)
255 					break;
256 			case EOF:
257 				*p = '\0';
258 				return(0);
259 			}
260 
261 	fatal("line too long");
262 	}
263 
264 endloop:
265 
266 	if((c = text[0]) == '\t')
267 		return( retsh(text) );
268 
269 	if(isalpha(c) || isdigit(c) || c==' ' || c=='.')
270 		for(p=text+1; *p!='\0'; )
271 			if(*p == ':')
272 				break;
273 			else if(*p++ == '=')
274 				{
275 				eqsign(text);
276 				return(MACRODEF);
277 				}
278 
279 /* substitute for macros on dependency line up to the semicolon if any */
280 
281 for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
282 	;
283 
284 lastchp = t;
285 lastch = *t;
286 *t = '\0';
287 
288 subst(yytext, templin);		/* Substitute for macros on dependency lines */
289 
290 if(lastch)
291 	{
292 	for(t = templin ; *t ; ++t)
293 		;
294 	*t = lastch;
295 	while( *++t = *++lastchp ) ;
296 	}
297 
298 p = templin;
299 t = yytext;
300 while( *t++ = *p++ )
301 	;
302 
303 for(p = zznextc = text ; *p ; ++p )
304 	if(*p!=' ' && *p!='\t')
305 		return(START);
306 goto again;
307 }
308