|
|
1.1 root 1:
2: /* @(#)gram.y 3.6 */
3: %{#include "defs"
4: %}
5:
6: %term NAME SHELLINE START COLON DOUBLECOLON EQUAL A_STRING VERSION
7:
8: %union
9: {
10: SHBLOCK yshblock;
11: DEPBLOCK ydepblock;
12: NAMEBLOCK ynameblock;
13: CHARSTAR ycharstring;
14: }
15:
16: %type <yshblock> SHELLINE, shlist, shellist
17: %type <ynameblock> NAME, namelist, name
18: %type <ydepblock> deplist, dlist
19: %type <ycharstring> A_STRING
20:
21:
22: %%
23:
24: %{
25: DEPBLOCK pp;
26: FSTATIC SHBLOCK prevshp;
27:
28: FSTATIC NAMEBLOCK lefts[NLEFTS];
29: NAMEBLOCK leftp;
30: FSTATIC int nlefts;
31:
32: LINEBLOCK lp, lpp;
33: FSTATIC DEPBLOCK prevdep;
34: FSTATIC int sepc;
35: %}
36:
37:
38: file:
39: | file comline
40: ;
41:
42: comline: START
43: | START macrodef
44: | START namelist deplist shellist = {
45: if(mainname == NULL && IS_OFF(INTRULE))
46: if(lefts[0]->namep[0] != DOT || any(lefts[0]->namep, SLASH) )
47: mainname = lefts[0];
48: while( --nlefts >= 0)
49: {
50: leftp = lefts[nlefts];
51: if(leftp->septype == 0)
52: leftp->septype = sepc;
53: else if(leftp->septype != sepc)
54: fprintf(stderr, "Inconsistent rules lines for `%s'\n",
55: leftp->namep);
56: else if(sepc==ALLDEPS && *(leftp->namep)!=DOT && $4!=0)
57: {
58: for(lp=leftp->linep; lp->nextline!=0; lp=lp->nextline)
59: if(lp->shp)
60: fprintf(stderr, "Multiple rules lines for `%s'\n",
61: leftp->namep);
62: }
63:
64: lp = ALLOC(lineblock);
65: lp->nextline = 0;
66: lp->depp = $3;
67: lp->shp = $4;
68:
69: if(equal(leftp->namep, ".SUFFIXES") && $3==0)
70: leftp->linep = 0;
71: else if(leftp->linep == 0)
72: leftp->linep = lp;
73: else
74: {
75: for(lpp = leftp->linep; lpp->nextline!=0;
76: lpp = lpp->nextline) ;
77: if(sepc==ALLDEPS && leftp->namep[0]==DOT)
78: lpp->shp = 0;
79: lpp->nextline = lp;
80: }
81: }
82: }
83: | error
84: ;
85:
86: macrodef: NAME EQUAL A_STRING =
87: {
88: setvar($1, $3);
89: }
90: ;
91:
92: namelist: name = { lefts[0] = $1; nlefts = 1; }
93: | namelist name = { lefts[nlefts++] = $2;
94: if(nlefts>NLEFTS) fatal("Too many lefts"); }
95: ;
96:
97: name: NAME =
98: {
99: if(($$ = srchname($1)) == 0)
100: $$ = makename($1);
101: }
102: | NAME VERSION =
103: {
104: if(($$ = srchname($1)) == 0)
105: $$ = makename($1);
106: }
107: ;
108:
109: deplist: = { fatal1("Must be a separator on rules line %d", yylineno); }
110: | dlist
111: ;
112:
113: dlist: sepchar = { prevdep = 0; $$ = 0; }
114: | dlist name = {
115: pp = ALLOC(depblock);
116: pp->nextdep = 0;
117: pp->depname = $2;
118: if(prevdep == 0) $$ = pp;
119: else prevdep->nextdep = pp;
120: prevdep = pp;
121: }
122: ;
123:
124: sepchar: COLON = { sepc = ALLDEPS; }
125: | DOUBLECOLON = { sepc = SOMEDEPS; }
126: ;
127:
128: shellist: = {$$ = 0; }
129: | shlist = { $$ = $1; }
130: ;
131:
132: shlist: SHELLINE = { $$ = $1; prevshp = $1; }
133: | shlist SHELLINE = { $$ = $1;
134: prevshp->nextsh = $2;
135: prevshp = $2;
136: }
137: ;
138:
139:
140: %%
141:
142: /* @(#)lex.c 3.1 */
143:
144: #include "ctype.h"
145: CHARSTAR zznextc; /* zero if need another line; otherwise points to next char */
146: int yylineno;
147: static char inmacro = NO;
148:
149: yylex()
150: {
151: register CHARSTAR p;
152: register CHARSTAR q;
153: static char word[128];
154: CHARSTAR pword;
155:
156: pword = word;
157: if(zznextc == 0)
158: return( nextlin() );
159:
160: while( isspace(*zznextc) )
161: ++zznextc;
162:
163: if(inmacro == YES)
164: {
165: inmacro = NO;
166: yylval.ycharstring = copys(zznextc);
167: zznextc = 0;
168: return(A_STRING);
169: }
170:
171: if(*zznextc == CNULL)
172: return( nextlin() );
173:
174: if(*zznextc == KOLON)
175: {
176: if(*++zznextc == KOLON)
177: {
178: ++zznextc;
179: return(DOUBLECOLON);
180: }
181: else
182: return(COLON);
183: }
184:
185: if(*zznextc == EQUALS)
186: {
187: inmacro = YES;
188: ++zznextc;
189: return(EQUAL);
190: }
191:
192: if(*zznextc == SKOLON)
193: return( retsh(zznextc) );
194:
195: p = zznextc;
196: q = word;
197:
198: while( ! ( funny[*p] & TERMINAL) )
199: *q++ = *p++;
200:
201: if(p != zznextc)
202: {
203: *q = CNULL;
204: yylval.ycharstring = copys(pword);
205: if(*p == RCURLY)
206: {
207: zznextc = p+1;
208: return(VERSION);
209: }
210: if(*p == LCURLY)
211: p++;
212: zznextc = p;
213: return(NAME);
214: }
215:
216: else
217: {
218: fprintf(stderr,"Bad character %c (octal %o), line %d",
219: *zznextc,*zznextc,yylineno);
220: fatal(Nullstr);
221: }
222: return(0); /* never executed */
223: }
224:
225:
226: retsh(q)
227: register CHARSTAR q;
228: {
229: register CHARSTAR p;
230: register int c;
231: extern CHARSTAR *linesptr;
232: SHBLOCK sp;
233:
234: for(p=q+1 ; *p==BLANK||*p==TAB ; ++p) ;
235:
236: sp = ALLOC(shblock);
237: sp->nextsh = 0;
238: sp->shbp = (fin == NULL ? p : copys(p) );
239: yylval.yshblock = sp;
240: zznextc = 0;
241: /*
242: * The following if-else "thing" eats up newlines within
243: * shell blocks.
244: */
245: if(fin == NULL)
246: {
247: if(linesptr[0])
248: while(linesptr[1] && equal(linesptr[1], "\n"))
249: {
250: yylineno++;
251: linesptr++;
252: }
253: }
254: else
255: {
256: while((c = GETC()) == NEWLINE)
257: yylineno++;
258: if(c != EOF)
259: ungetc(c, fin);
260: }
261: return(SHELLINE);
262: }
263:
264: nextlin()
265: {
266: register char c;
267: register CHARSTAR p, t;
268: static char yytext[INMAX];
269: static CHARSTAR yytextl = yytext+INMAX;
270: CHARSTAR text;
271: char templin[INMAX];
272: char lastch;
273: CHARSTAR lastchp;
274: extern CHARSTAR *linesptr;
275: int incom;
276: int kc;
277: int nflg;
278: int poundflg;
279:
280: again:
281: incom = 0;
282: zznextc = 0;
283: poundflg = 0;
284:
285: if(fin == NULL)
286: {
287: if( (text = *linesptr++) == 0)
288: return(0);
289: ++yylineno;
290: copstr(yytext, text);
291: }
292:
293: else
294: {
295: yytext[0] = CNULL;
296: for(p=yytext ; ; ++p)
297: {
298: if(p > yytextl)
299: fatal("line too long");
300: kc = GETC();
301: if(kc == EOF)
302: {
303: *p = CNULL;
304: return(0);
305: }
306: else if(kc == SKOLON)
307: ++incom;
308: else if (kc == TAB && p == yytext)
309: ++incom;
310: else if (kc==POUND && !incom && yytext[0] != TAB)
311: {
312: poundflg++;
313: kc = CNULL;
314: }
315: else if (kc == NEWLINE)
316: {
317: ++yylineno;
318: if(p==yytext || p[-1]!=BACKSLASH)
319: break;
320: if(incom || yytext[0] == TAB)
321: *p++ = NEWLINE;
322: else
323: p[-1] = BLANK;
324: nflg = YES;
325: while( kc = GETC())
326: {
327: if(kc != TAB && kc != BLANK && kc != NEWLINE)
328: break;
329: if(incom || yytext[0] == TAB)
330: {
331: if(nflg == YES && kc == TAB)
332: {
333: nflg = NO;
334: continue;
335: }
336: if(kc == NEWLINE)
337: {
338: nflg = YES;
339: }
340:
341: *p++ = kc;
342: }
343: if(kc == NEWLINE)
344: ++yylineno;
345: }
346:
347: if(kc == EOF)
348: {
349: *p = CNULL;
350: return(0);
351: }
352: }
353: *p = kc;
354: }
355: *p = CNULL;
356: text = yytext;
357: }
358:
359: c = text[0];
360:
361: if(c == TAB)
362: return( retsh(text) );
363:
364: /*
365: * DO include FILES HERE.
366: */
367: if(sindex(text, "include") == 0 && (text[7] == BLANK || text[7] == TAB))
368: {
369: CHARSTAR pfile;
370:
371: for(p = &text[8]; *p != CNULL; p++)
372: if(*p != TAB ||
373: *p != BLANK)
374: break;
375: pfile = p;
376: for(; *p != CNULL &&
377: *p != NEWLINE &&
378: *p != TAB &&
379: *p != BLANK; p++);
380: if(*p != CNULL)
381: *p = CNULL;
382:
383: /*
384: * Start using new file.
385: */
386: fstack(pfile, &fin, &yylineno);
387: goto again;
388: }
389: if(isalpha(c) || isdigit(c) || c==BLANK || c==DOT)
390: for(p=text+1; *p!=CNULL; p++)
391: if(*p == KOLON || *p == EQUALS)
392: break;
393:
394: /* substtitute for macros on dependency line up to the semicolon if any */
395: if(*p != EQUALS)
396: {
397: for(t = yytext ; *t!=CNULL && *t!=SKOLON ; ++t);
398:
399: lastchp = t;
400: lastch = *t;
401: *t = CNULL;
402:
403: subst(yytext, templin); /* Substitute for macros on dep lines */
404:
405: if(lastch)
406: {
407: for(t = templin ; *t ; ++t);
408: *t = lastch;
409: while( *++t = *++lastchp ) ;
410: }
411:
412: p = templin;
413: t = yytext;
414: while( *t++ = *p++ );
415: }
416:
417: if(poundflg == 0 || yytext[0] != CNULL)
418: {
419: zznextc = text;
420: return(START);
421: }
422: else
423: goto again;
424: }
425:
426: #include "stdio.h"
427:
428: /*
429: * GETC automatically unravels stacked include files. That is,
430: * during include file processing, when a new file is encountered
431: * fstack will stack the FILE pointer argument. Subsequent
432: * calls to GETC with the new FILE pointer will get characters
433: * from the new file. When an EOF is encountered, GETC will
434: * check to see if the file pointer has been stacked. If so,
435: * a character from the previous file will be returned.
436: * The external references are "GETC()" and "fstack(fname,stream,lno)".
437: * "Fstack(stfname,ream,lno)" is used to stack an old file pointer before
438: * the new file is assigned to the same variable. Also stacked are the
439: * file name and the old current lineno, generally, yylineno.
440: */
441:
442:
443:
444: static int morefiles;
445: static struct sfiles
446: {
447: char sfname[64];
448: FILE *sfilep;
449: int syylno;
450: } sfiles[20];
451:
452: GETC()
453: {
454: register int c;
455:
456: c = getc(fin);
457: while(c == EOF && morefiles)
458: {
459: fclose(fin);
460: yylineno = sfiles[--morefiles].syylno;
461: fin = sfiles[morefiles].sfilep;
462: c = getc(fin);
463: }
464: return(c);
465: }
466: fstack(newname, oldfp, oldlno)
467: register char *newname;
468: register FILE **oldfp;
469: register int *oldlno;
470: {
471: if(access(newname, 4) != 0)
472: /*
473: * This get line can be removed if used elsewhere than make.
474: */
475: if(get(newname, CD, Nullstr) == NO)
476: fatal1("Cannot read or get %s", newname);
477: if(IS_ON(DBUG))
478: printf("Include file: \"%s\"\n", newname);
479: /*
480: * Stack the new file name, the old file pointer and the
481: * old yylineno;
482: */
483: strcat(sfiles[morefiles].sfname, newname);
484: sfiles[morefiles].sfilep = *oldfp;
485: sfiles[morefiles++].syylno = *oldlno;
486: yylineno = 0;
487: if((*oldfp=fopen(newname, "r")) == NULL)
488: fatal1("Cannot open %s", newname);
489: }
490:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.