cleanup, add manual page
[unix-history] / usr / src / old / make / gram.y
CommitLineData
23cd6ce0 1%{#include "defs"
6521d648 2static char *sccsid = "@(#)gram.y 4.2 (Berkeley) 87/10/22";
23cd6ce0
BJ
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%{
21struct depblock *pp;
22FSTATIC struct shblock *prevshp;
23
24FSTATIC struct nameblock *lefts[NLEFTS];
25struct nameblock *leftp;
26FSTATIC int nlefts;
27
28struct lineblock *lp, *lpp;
29FSTATIC struct depblock *prevdep;
30FSTATIC int sepc;
31%}
32
33
34file:
35 | file comline
36 ;
37
38comline: 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
78namelist: NAME = { lefts[0] = $1; nlefts = 1; }
79 | namelist NAME = { lefts[nlefts++] = $2;
80 if(nlefts>=NLEFTS) fatal("Too many lefts"); }
81 ;
82
83deplist:
84 {
85 char junk[10];
6521d648 86 (void)sprintf(junk, "%d", yylineno);
23cd6ce0
BJ
87 fatal1("Must be a separator on rules line %s", junk);
88 }
89 | dlist
90 ;
91
92dlist: 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
103sepchar: COLON = { sepc = ALLDEPS; }
104 | DOUBLECOLON = { sepc = SOMEDEPS; }
105 ;
106
107shellist: = {$$ = 0; }
108 | shlist = { $$ = $1; }
109 ;
110
111shlist: SHELLINE = { $$ = $1; prevshp = $1; }
112 | shlist SHELLINE = { $$ = $1;
113 prevshp->nxtshblock = $2;
114 prevshp = $2;
115 }
116 ;
117
118%%
119\f
120char *zznextc; /* zero if need another line; otherwise points to next char */
121int yylineno;
122extern FILE * fin;
123
124yylex()
125{
126register char *p;
127register char *q;
128char word[INMAX];
129
130if(zznextc == 0)
131 return( nextlin() );
132
133while( isspace(*zznextc) )
134 ++zznextc;
135
136if(*zznextc == '\0')
137 return( nextlin() );
138
139if(*zznextc == ':')
140 {
141 if(*++zznextc == ':')
142 {
143 ++zznextc;
144 return(DOUBLECOLON);
145 }
146 else return(COLON);
147 }
148
149if(*zznextc == '>')
150 {
151 ++zznextc;
152 return(GREATER);
153 }
154
155if(*zznextc == ';')
156 return( retsh(zznextc) );
157
158p = zznextc;
159q = word;
160
161while( ! ( funny[*p] & TERMINAL) )
162 *q++ = *p++;
163
164if(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
173else {
174 fprintf(stderr,"Bad character %c (octal %o), line %d",
175 *zznextc,*zznextc,yylineno);
176 fatal( (char *) NULL );
177 }
178return(0); /* never executed */
179}
180
181
182
183
184
185retsh(q)
186char *q;
187{
188register char *p;
189struct shblock *sp;
190char *copys();
191
192for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ;
193
194sp = ALLOC(shblock);
195sp->nxtshblock = NULL;
196sp->shbp = (fin == NULL ? p : copys(p) );
197yylval.yshblock = sp;
198zznextc = 0;
199return(SHELLINE);
200}
201\f
202nextlin()
203{
204static char yytext[INMAX];
205static char *yytextl = yytext+INMAX;
206char *text, templin[INMAX];
207register char c;
208register char *p, *t;
209char lastch, *lastchp;
210extern char **linesptr;
211int incom;
212int kc;
213
214again:
215
216 incom = NO;
217 zznextc = 0;
218
219if(fin == NULL)
220 {
221 if( (text = *linesptr++) == 0)
222 return(0);
223 ++yylineno;
224 }
225
226else {
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
264endloop:
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
281for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
282 ;
283
284lastchp = t;
285lastch = *t;
286*t = '\0';
287
288subst(yytext, templin); /* Substitute for macros on dependency lines */
289
290if(lastch)
291 {
292 for(t = templin ; *t ; ++t)
293 ;
294 *t = lastch;
295 while( *++t = *++lastchp ) ;
296 }
297
298p = templin;
299t = yytext;
300while( *t++ = *p++ )
301 ;
302
303for(p = zznextc = text ; *p ; ++p )
304 if(*p!=' ' && *p!='\t')
305 return(START);
306goto again;
307}