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