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