]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/cmd/make/gram.y
libc: use Runemax instead of hardcoded 0x65536 for fmtchar check (thanks qrstuv)
[plan9front.git] / sys / src / ape / cmd / make / gram.y
1 %{#include "defs.h"
2 %}
3
4 %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER AMPER AMPERAMPER
5 %union
6         {
7         struct shblock *yshblock;
8         depblkp ydepblock;
9         nameblkp ynameblock;
10         }
11
12 %type <yshblock> SHELLINE, shlist, shellist
13 %type <ynameblock> NAME, namelist
14 %type <ydepblock> deplist, dlist
15
16
17 %%
18
19 %{
20 struct depblock *pp;
21 static struct shblock *prevshp;
22
23 static struct nameblock *lefts[NLEFTS];
24 struct nameblock *leftp;
25 static int nlefts;
26
27 struct lineblock *lp, *lpp;
28 static struct depblock *prevdep;
29 static int sepc;
30 static int allnowait;
31
32 static struct fstack
33         {
34         FILE *fin;
35         char *fname;
36         int lineno;
37         } filestack[MAXINCLUDE];
38 static int ninclude = 0;
39 %}
40
41
42 file:
43         | file comline
44         ;
45
46 comline:  START
47         | MACRODEF
48         | START namelist deplist shellist = {
49             while( --nlefts >= 0)
50                 {
51                 wildp wp;
52
53                 leftp = lefts[nlefts];
54                 if(wp = iswild(leftp->namep))
55                         {
56                         leftp->septype = SOMEDEPS;
57                         if(lastwild)
58                                 lastwild->next = wp;
59                         else
60                                 firstwild = wp;
61                         lastwild = wp;
62                         }
63
64                 if(leftp->septype == 0)
65                         leftp->septype = sepc;
66                 else if(leftp->septype != sepc)
67                         {
68                         if(! wp)
69                                 fprintf(stderr,
70                                         "Inconsistent rules lines for `%s'\n",
71                                         leftp->namep);
72                         }
73                 else if(sepc==ALLDEPS && leftp->namep[0]!='.' && $4!=0)
74                         {
75                         for(lp=leftp->linep; lp->nxtlineblock; lp=lp->nxtlineblock)
76                         if(lp->shp)
77                                 fprintf(stderr,
78                                         "Multiple rules lines for `%s'\n",
79                                         leftp->namep);
80                         }
81
82                 lp = ALLOC(lineblock);
83                 lp->nxtlineblock = NULL;
84                 lp->depp = $3;
85                 lp->shp = $4;
86                 if(wp)
87                         wp->linep = lp;
88
89                 if(equal(leftp->namep, ".SUFFIXES") && $3==0)
90                         leftp->linep = 0;
91                 else if(leftp->linep == 0)
92                         leftp->linep = lp;
93                 else    {
94                         for(lpp = leftp->linep; lpp->nxtlineblock;
95                                 lpp = lpp->nxtlineblock) ;
96                                 if(sepc==ALLDEPS && leftp->namep[0]=='.')
97                                         lpp->shp = 0;
98                         lpp->nxtlineblock = lp;
99                         }
100                 }
101         }
102         | error
103         ;
104
105 namelist: NAME  = { lefts[0] = $1; nlefts = 1; }
106         | namelist NAME = { lefts[nlefts++] = $2;
107                 if(nlefts>=NLEFTS) fatal("Too many lefts"); }
108         ;
109
110 deplist:
111                 {
112                 char junk[100];
113                 sprintf(junk, "%s:%d", filestack[ninclude-1].fname, yylineno);
114                 fatal1("Must be a separator on rules line %s", junk);
115                 }
116         | dlist
117         ;
118
119 dlist:  sepchar = { prevdep = 0;  $$ = 0; allnowait = NO; }
120         | sepchar AMPER = { prevdep = 0; $$ = 0; allnowait = YES; }
121         | dlist NAME    = {
122                           pp = ALLOC(depblock);
123                           pp->nxtdepblock = NULL;
124                           pp->depname = $2;
125                           pp->nowait = allnowait;
126                           if(prevdep == 0) $$ = pp;
127                           else  prevdep->nxtdepblock = pp;
128                           prevdep = pp;
129                           }
130         | dlist AMPER   = { if(prevdep) prevdep->nowait = YES; }
131         | dlist AMPERAMPER
132         ;
133
134 sepchar:  COLON         = { sepc = ALLDEPS; }
135         | DOUBLECOLON   = { sepc = SOMEDEPS; }
136         ;
137
138 shellist:       = {$$ = 0; }
139         | shlist = { $$ = $1; }
140         ;
141
142 shlist: SHELLINE   = { $$ = $1;  prevshp = $1; }
143         | shlist SHELLINE = { $$ = $1;
144                         prevshp->nxtshblock = $2;
145                         prevshp = $2;
146                         }
147         ;
148
149 %%
150 \f
151 static char *zznextc;   /* null if need another line;
152                            otherwise points to next char */
153 static int yylineno;
154 static FILE * fin;
155 static int retsh(char *);
156 static int nextlin(void);
157 static int isinclude(char *);
158
159 int yyparse(void);
160
161 int
162 parse(char *name)
163 {
164 FILE *stream;
165
166 if(name == CHNULL)
167         {
168         stream = NULL;
169         name = "(builtin-rules)";
170         }
171 else if(equal(name, "-"))
172         {
173         stream = stdin;
174         name = "(stdin)";
175         }
176 else if( (stream = fopen(name, "r")) == NULL)
177         return NO;
178 filestack[0].fname = copys(name);
179 ninclude = 1;
180 fin = stream;
181 yylineno = 0;
182 zznextc = 0;
183
184 if( yyparse() )
185         fatal("Description file error");
186
187 if(fin)
188         fclose(fin);
189 return YES;
190 }
191
192 int
193 yylex(void)
194 {
195 char *p;
196 char *q;
197 char word[INMAX];
198
199 if(! zznextc )
200         return nextlin() ;
201
202 while( isspace(*zznextc) )
203         ++zznextc;
204 switch(*zznextc)
205         {
206         case '\0':
207                 return nextlin() ;
208
209         case '|':
210                 if(zznextc[1]==':')
211                         {
212                         zznextc += 2;
213                         return DOUBLECOLON;
214                         }
215                 break;
216         case ':':
217                 if(*++zznextc == ':')
218                         {
219                         ++zznextc;
220                         return DOUBLECOLON;
221                         }
222                 return COLON;
223         case '>':
224                 ++zznextc;
225                 return GREATER;
226         case '&':
227                 if(*++zznextc == '&')
228                         {
229                         ++zznextc;
230                         return AMPERAMPER;
231                         }
232                 return AMPER;
233         case ';':
234                 return retsh(zznextc) ;
235         }
236
237 p = zznextc;
238 q = word;
239
240 while( ! ( funny[*p] & TERMINAL) )
241         *q++ = *p++;
242
243 if(p != zznextc)
244         {
245         *q = '\0';
246         if((yylval.ynameblock=srchname(word))==0)
247                 yylval.ynameblock = makename(word);
248         zznextc = p;
249         return NAME;
250         }
251
252 else    {
253         char junk[100];
254         sprintf(junk, "Bad character %c (octal %o), line %d of file %s",
255                 *zznextc, *zznextc, yylineno, filestack[ninclude-1].fname);
256         fatal(junk);
257         }
258 return 0;       /* never executed */
259 }
260
261
262
263
264 static int
265 retsh(char *q)
266 {
267 register char *p;
268 struct shblock *sp;
269
270 for(p=q+1 ; *p==' '||*p=='\t' ; ++p)  ;
271
272 sp = ALLOC(shblock);
273 sp->nxtshblock = NULL;
274 sp->shbp = (fin ? copys(p) : p );
275 yylval.yshblock = sp;
276 zznextc = 0;
277 return SHELLINE;
278 }
279
280 static int
281 nextlin(void)
282 {
283 static char yytext[INMAX];
284 static char *yytextl    = yytext+INMAX;
285 char *text, templin[INMAX];
286 char c;
287 char *p, *t;
288 char lastch, *lastchp;
289 extern char **linesptr;
290 int incom;
291 int kc;
292
293 again:
294
295         incom = NO;
296         zznextc = 0;
297
298 if(fin == NULL)
299         {
300         if( (text = *linesptr++) == 0)
301                 return 0;
302         ++yylineno;
303         }
304
305 else    {
306         for(p = text = yytext ; p<yytextl ; *p++ = kc)
307                 switch(kc = getc(fin))
308                         {
309                         case '\t':
310                                 if(p == yytext)
311                                         incom = YES;
312                                 break;
313
314                         case ';':
315                                 incom = YES;
316                                 break;
317
318                         case '#':
319                                 if(! incom)
320                                         kc = '\0';
321                                 break;
322
323                         case '\n':
324                                 ++yylineno;
325                                 if(p==yytext || p[-1]!='\\')
326                                         {
327                                         *p = '\0';
328                                         goto endloop;
329                                         }
330                                 p[-1] = ' ';
331                                 while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n')
332                                         if(kc == '\n')
333                                                 ++yylineno;
334         
335                                 if(kc != EOF)
336                                         break;
337                         case EOF:
338                                 *p = '\0';
339                                 if(ninclude > 1)
340                                         {
341                                         register struct fstack *stp;
342                                         fclose(fin);
343                                         --ninclude;
344                                         stp = filestack + ninclude;
345                                         fin = stp->fin;
346                                         yylineno = stp->lineno;
347                                         free(stp->fname);
348                                         goto again;
349                                         }
350                                 return 0;
351                         }
352
353         fatal("line too long");
354         }
355
356 endloop:
357
358         if((c = text[0]) == '\t')
359                 return retsh(text) ;
360         
361         if(isalpha(c) || isdigit(c) || c==' ' || c=='.'|| c=='_')
362                 for(p=text+1; *p!='\0'; )
363                         if(*p == ':')
364                                 break;
365                         else if(*p++ == '=')
366                                 {
367                                 eqsign(text);
368                                 return MACRODEF;
369                                 }
370
371 /* substitute for macros on dependency line up to the semicolon if any */
372
373 for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
374         ;
375
376 lastchp = t;
377 lastch = *t;
378 *t = '\0';      /* replace the semi with a null so subst will stop */
379
380 subst(yytext, templin);         /* Substitute for macros on dependency lines */
381
382 if(lastch)      /* copy the stuff after the semicolon */
383         {
384         *lastchp = lastch;
385         strcat(templin, lastchp);
386         }
387
388 strcpy(yytext, templin);
389
390 /* process include files after macro substitution */
391 if(strncmp(text, "include", 7) == 0) {
392         if (isinclude(text+7))
393                 goto again;
394 }
395
396 for(p = zznextc = text ; *p ; ++p )
397         if(*p!=' ' && *p!='\t')
398                 return START;
399 goto again;
400 }
401
402
403 static int
404 isinclude(char *s)
405 {
406 char *t;
407 struct fstack *p;
408
409 for(t=s; *t==' ' || *t=='\t' ; ++t)
410         ;
411 if(t == s)
412         return NO;
413
414 for(s = t; *s!='\n' && *s!='#' && *s!='\0' ; ++s)
415         if(*s == ':')
416                 return NO;
417 *s = '\0';
418
419 if(ninclude >= MAXINCLUDE)
420         fatal("include depth exceeded");
421 p = filestack + ninclude;
422 p->fin = fin;
423 p->lineno = yylineno;
424 p->fname = copys(t);
425 if( (fin = fopen(t, "r")) == NULL)
426         fatal1("Cannot open include file %s", t);
427 yylineno = 0;
428 ++ninclude;
429 return YES;
430 }
431
432
433 int
434 yyerror(char *s, ...)
435 {
436 char buf[100];
437
438 sprintf(buf, "line %d of file %s: %s",
439                 yylineno, filestack[ninclude-1].fname, s);
440 fatal(buf);
441 return -1;
442 }