1 %{#include "defs"
2 static char *sccsid = "@(#)gram.y 4.2 (Berkeley) 87/10/22";
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 (void)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
yylex()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
retsh(q)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
nextlin()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