xref: /plan9/sys/src/ape/cmd/make/gram.y (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
1219b2ee8SDavid du Colombier %{#include "defs.h"
2219b2ee8SDavid du Colombier %}
3219b2ee8SDavid du Colombier 
4219b2ee8SDavid du Colombier %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER AMPER AMPERAMPER
5219b2ee8SDavid du Colombier %union
6219b2ee8SDavid du Colombier 	{
7219b2ee8SDavid du Colombier 	struct shblock *yshblock;
8219b2ee8SDavid du Colombier 	depblkp ydepblock;
9219b2ee8SDavid du Colombier 	nameblkp ynameblock;
10219b2ee8SDavid du Colombier 	}
11219b2ee8SDavid du Colombier 
12219b2ee8SDavid du Colombier %type <yshblock> SHELLINE, shlist, shellist
13219b2ee8SDavid du Colombier %type <ynameblock> NAME, namelist
14219b2ee8SDavid du Colombier %type <ydepblock> deplist, dlist
15219b2ee8SDavid du Colombier 
16219b2ee8SDavid du Colombier 
17219b2ee8SDavid du Colombier %%
18219b2ee8SDavid du Colombier 
19219b2ee8SDavid du Colombier %{
20219b2ee8SDavid du Colombier struct depblock *pp;
21219b2ee8SDavid du Colombier static struct shblock *prevshp;
22219b2ee8SDavid du Colombier 
23219b2ee8SDavid du Colombier static struct nameblock *lefts[NLEFTS];
24219b2ee8SDavid du Colombier struct nameblock *leftp;
25219b2ee8SDavid du Colombier static int nlefts;
26219b2ee8SDavid du Colombier 
27219b2ee8SDavid du Colombier struct lineblock *lp, *lpp;
28219b2ee8SDavid du Colombier static struct depblock *prevdep;
29219b2ee8SDavid du Colombier static int sepc;
30219b2ee8SDavid du Colombier static int allnowait;
31219b2ee8SDavid du Colombier 
32219b2ee8SDavid du Colombier static struct fstack
33219b2ee8SDavid du Colombier 	{
34219b2ee8SDavid du Colombier 	FILE *fin;
35219b2ee8SDavid du Colombier 	char *fname;
36219b2ee8SDavid du Colombier 	int lineno;
37219b2ee8SDavid du Colombier 	} filestack[MAXINCLUDE];
38219b2ee8SDavid du Colombier static int ninclude = 0;
39219b2ee8SDavid du Colombier %}
40219b2ee8SDavid du Colombier 
41219b2ee8SDavid du Colombier 
42219b2ee8SDavid du Colombier file:
43219b2ee8SDavid du Colombier 	| file comline
44219b2ee8SDavid du Colombier 	;
45219b2ee8SDavid du Colombier 
46219b2ee8SDavid du Colombier comline:  START
47219b2ee8SDavid du Colombier 	| MACRODEF
48219b2ee8SDavid du Colombier 	| START namelist deplist shellist = {
49219b2ee8SDavid du Colombier 	    while( --nlefts >= 0)
50219b2ee8SDavid du Colombier 		{
51219b2ee8SDavid du Colombier 		wildp wp;
52219b2ee8SDavid du Colombier 
53219b2ee8SDavid du Colombier 		leftp = lefts[nlefts];
54219b2ee8SDavid du Colombier 		if(wp = iswild(leftp->namep))
55219b2ee8SDavid du Colombier 			{
56219b2ee8SDavid du Colombier 			leftp->septype = SOMEDEPS;
57219b2ee8SDavid du Colombier 			if(lastwild)
58219b2ee8SDavid du Colombier 				lastwild->next = wp;
59219b2ee8SDavid du Colombier 			else
60219b2ee8SDavid du Colombier 				firstwild = wp;
61219b2ee8SDavid du Colombier 			lastwild = wp;
62219b2ee8SDavid du Colombier 			}
63219b2ee8SDavid du Colombier 
64219b2ee8SDavid du Colombier 		if(leftp->septype == 0)
65219b2ee8SDavid du Colombier 			leftp->septype = sepc;
66219b2ee8SDavid du Colombier 		else if(leftp->septype != sepc)
67219b2ee8SDavid du Colombier 			{
68219b2ee8SDavid du Colombier 			if(! wp)
69219b2ee8SDavid du Colombier 				fprintf(stderr,
70219b2ee8SDavid du Colombier 					"Inconsistent rules lines for `%s'\n",
71219b2ee8SDavid du Colombier 					leftp->namep);
72219b2ee8SDavid du Colombier 			}
73219b2ee8SDavid du Colombier 		else if(sepc==ALLDEPS && leftp->namep[0]!='.' && $4!=0)
74219b2ee8SDavid du Colombier 			{
75219b2ee8SDavid du Colombier 			for(lp=leftp->linep; lp->nxtlineblock; lp=lp->nxtlineblock)
76219b2ee8SDavid du Colombier 			if(lp->shp)
77219b2ee8SDavid du Colombier 				fprintf(stderr,
78219b2ee8SDavid du Colombier 					"Multiple rules lines for `%s'\n",
79219b2ee8SDavid du Colombier 					leftp->namep);
80219b2ee8SDavid du Colombier 			}
81219b2ee8SDavid du Colombier 
82219b2ee8SDavid du Colombier 		lp = ALLOC(lineblock);
83219b2ee8SDavid du Colombier 		lp->nxtlineblock = NULL;
84219b2ee8SDavid du Colombier 		lp->depp = $3;
85219b2ee8SDavid du Colombier 		lp->shp = $4;
86219b2ee8SDavid du Colombier 		if(wp)
87219b2ee8SDavid du Colombier 			wp->linep = lp;
88219b2ee8SDavid du Colombier 
89219b2ee8SDavid du Colombier 		if(equal(leftp->namep, ".SUFFIXES") && $3==0)
90219b2ee8SDavid du Colombier 			leftp->linep = 0;
91219b2ee8SDavid du Colombier 		else if(leftp->linep == 0)
92219b2ee8SDavid du Colombier 			leftp->linep = lp;
93219b2ee8SDavid du Colombier 		else	{
94219b2ee8SDavid du Colombier 			for(lpp = leftp->linep; lpp->nxtlineblock;
95219b2ee8SDavid du Colombier 				lpp = lpp->nxtlineblock) ;
96219b2ee8SDavid du Colombier 				if(sepc==ALLDEPS && leftp->namep[0]=='.')
97219b2ee8SDavid du Colombier 					lpp->shp = 0;
98219b2ee8SDavid du Colombier 			lpp->nxtlineblock = lp;
99219b2ee8SDavid du Colombier 			}
100219b2ee8SDavid du Colombier 		}
101219b2ee8SDavid du Colombier 	}
102219b2ee8SDavid du Colombier 	| error
103219b2ee8SDavid du Colombier 	;
104219b2ee8SDavid du Colombier 
105219b2ee8SDavid du Colombier namelist: NAME	= { lefts[0] = $1; nlefts = 1; }
106219b2ee8SDavid du Colombier 	| namelist NAME	= { lefts[nlefts++] = $2;
107219b2ee8SDavid du Colombier 	    	if(nlefts>=NLEFTS) fatal("Too many lefts"); }
108219b2ee8SDavid du Colombier 	;
109219b2ee8SDavid du Colombier 
110219b2ee8SDavid du Colombier deplist:
111219b2ee8SDavid du Colombier 		{
1127dd7cddfSDavid du Colombier 		char junk[100];
1137dd7cddfSDavid du Colombier 		sprintf(junk, "%s:%d", filestack[ninclude-1].fname, yylineno);
114219b2ee8SDavid du Colombier 		fatal1("Must be a separator on rules line %s", junk);
115219b2ee8SDavid du Colombier 		}
116219b2ee8SDavid du Colombier 	| dlist
117219b2ee8SDavid du Colombier 	;
118219b2ee8SDavid du Colombier 
119219b2ee8SDavid du Colombier dlist:  sepchar	= { prevdep = 0;  $$ = 0; allnowait = NO; }
120219b2ee8SDavid du Colombier 	| sepchar AMPER	= { prevdep = 0; $$ = 0; allnowait = YES; }
121219b2ee8SDavid du Colombier 	| dlist NAME	= {
122219b2ee8SDavid du Colombier 			  pp = ALLOC(depblock);
123219b2ee8SDavid du Colombier 			  pp->nxtdepblock = NULL;
124219b2ee8SDavid du Colombier 			  pp->depname = $2;
125219b2ee8SDavid du Colombier 			  pp->nowait = allnowait;
126219b2ee8SDavid du Colombier 			  if(prevdep == 0) $$ = pp;
127219b2ee8SDavid du Colombier 			  else  prevdep->nxtdepblock = pp;
128219b2ee8SDavid du Colombier 			  prevdep = pp;
129219b2ee8SDavid du Colombier 			  }
130219b2ee8SDavid du Colombier 	| dlist AMPER	= { if(prevdep) prevdep->nowait = YES; }
131219b2ee8SDavid du Colombier 	| dlist AMPERAMPER
132219b2ee8SDavid du Colombier 	;
133219b2ee8SDavid du Colombier 
134219b2ee8SDavid du Colombier sepchar:  COLON 	= { sepc = ALLDEPS; }
135219b2ee8SDavid du Colombier 	| DOUBLECOLON	= { sepc = SOMEDEPS; }
136219b2ee8SDavid du Colombier 	;
137219b2ee8SDavid du Colombier 
138219b2ee8SDavid du Colombier shellist:	= {$$ = 0; }
139219b2ee8SDavid du Colombier 	| shlist = { $$ = $1; }
140219b2ee8SDavid du Colombier 	;
141219b2ee8SDavid du Colombier 
142219b2ee8SDavid du Colombier shlist:	SHELLINE   = { $$ = $1;  prevshp = $1; }
143219b2ee8SDavid du Colombier 	| shlist SHELLINE = { $$ = $1;
144219b2ee8SDavid du Colombier 			prevshp->nxtshblock = $2;
145219b2ee8SDavid du Colombier 			prevshp = $2;
146219b2ee8SDavid du Colombier 			}
147219b2ee8SDavid du Colombier 	;
148219b2ee8SDavid du Colombier 
149219b2ee8SDavid du Colombier %%
150219b2ee8SDavid du Colombier 
151219b2ee8SDavid du Colombier static char *zznextc;	/* null if need another line;
152219b2ee8SDavid du Colombier 			   otherwise points to next char */
153219b2ee8SDavid du Colombier static int yylineno;
154219b2ee8SDavid du Colombier static FILE * fin;
155219b2ee8SDavid du Colombier static int retsh(char *);
156219b2ee8SDavid du Colombier static int nextlin(void);
157219b2ee8SDavid du Colombier static int isinclude(char *);
158219b2ee8SDavid du Colombier 
159219b2ee8SDavid du Colombier int yyparse(void);
160219b2ee8SDavid du Colombier 
161219b2ee8SDavid du Colombier int
parse(char * name)162219b2ee8SDavid du Colombier parse(char *name)
163219b2ee8SDavid du Colombier {
164219b2ee8SDavid du Colombier FILE *stream;
165219b2ee8SDavid du Colombier 
166219b2ee8SDavid du Colombier if(name == CHNULL)
167219b2ee8SDavid du Colombier 	{
168219b2ee8SDavid du Colombier 	stream = NULL;
169219b2ee8SDavid du Colombier 	name = "(builtin-rules)";
170219b2ee8SDavid du Colombier 	}
171219b2ee8SDavid du Colombier else if(equal(name, "-"))
172219b2ee8SDavid du Colombier 	{
173219b2ee8SDavid du Colombier 	stream = stdin;
174219b2ee8SDavid du Colombier 	name = "(stdin)";
175219b2ee8SDavid du Colombier 	}
176219b2ee8SDavid du Colombier else if( (stream = fopen(name, "r")) == NULL)
177219b2ee8SDavid du Colombier 	return NO;
178219b2ee8SDavid du Colombier filestack[0].fname = copys(name);
179219b2ee8SDavid du Colombier ninclude = 1;
180219b2ee8SDavid du Colombier fin = stream;
181219b2ee8SDavid du Colombier yylineno = 0;
182219b2ee8SDavid du Colombier zznextc = 0;
183219b2ee8SDavid du Colombier 
184219b2ee8SDavid du Colombier if( yyparse() )
185219b2ee8SDavid du Colombier 	fatal("Description file error");
186219b2ee8SDavid du Colombier 
187219b2ee8SDavid du Colombier if(fin)
188219b2ee8SDavid du Colombier 	fclose(fin);
189219b2ee8SDavid du Colombier return YES;
190219b2ee8SDavid du Colombier }
191219b2ee8SDavid du Colombier 
192219b2ee8SDavid du Colombier int
yylex(void)193219b2ee8SDavid du Colombier yylex(void)
194219b2ee8SDavid du Colombier {
195219b2ee8SDavid du Colombier char *p;
196219b2ee8SDavid du Colombier char *q;
197219b2ee8SDavid du Colombier char word[INMAX];
198219b2ee8SDavid du Colombier 
199219b2ee8SDavid du Colombier if(! zznextc )
200219b2ee8SDavid du Colombier 	return nextlin() ;
201219b2ee8SDavid du Colombier 
202219b2ee8SDavid du Colombier while( isspace(*zznextc) )
203219b2ee8SDavid du Colombier 	++zznextc;
204219b2ee8SDavid du Colombier switch(*zznextc)
205219b2ee8SDavid du Colombier 	{
206219b2ee8SDavid du Colombier 	case '\0':
207219b2ee8SDavid du Colombier 		return nextlin() ;
208219b2ee8SDavid du Colombier 
209219b2ee8SDavid du Colombier 	case '|':
210219b2ee8SDavid du Colombier 		if(zznextc[1]==':')
211219b2ee8SDavid du Colombier 			{
212219b2ee8SDavid du Colombier 			zznextc += 2;
213219b2ee8SDavid du Colombier 			return DOUBLECOLON;
214219b2ee8SDavid du Colombier 			}
215219b2ee8SDavid du Colombier 		break;
216219b2ee8SDavid du Colombier 	case ':':
217219b2ee8SDavid du Colombier 		if(*++zznextc == ':')
218219b2ee8SDavid du Colombier 			{
219219b2ee8SDavid du Colombier 			++zznextc;
220219b2ee8SDavid du Colombier 			return DOUBLECOLON;
221219b2ee8SDavid du Colombier 			}
222219b2ee8SDavid du Colombier 		return COLON;
223219b2ee8SDavid du Colombier 	case '>':
224219b2ee8SDavid du Colombier 		++zznextc;
225219b2ee8SDavid du Colombier 		return GREATER;
226219b2ee8SDavid du Colombier 	case '&':
227219b2ee8SDavid du Colombier 		if(*++zznextc == '&')
228219b2ee8SDavid du Colombier 			{
229219b2ee8SDavid du Colombier 			++zznextc;
230219b2ee8SDavid du Colombier 			return AMPERAMPER;
231219b2ee8SDavid du Colombier 			}
232219b2ee8SDavid du Colombier 		return AMPER;
233219b2ee8SDavid du Colombier 	case ';':
234219b2ee8SDavid du Colombier 		return retsh(zznextc) ;
235219b2ee8SDavid du Colombier 	}
236219b2ee8SDavid du Colombier 
237219b2ee8SDavid du Colombier p = zznextc;
238219b2ee8SDavid du Colombier q = word;
239219b2ee8SDavid du Colombier 
240219b2ee8SDavid du Colombier while( ! ( funny[*p] & TERMINAL) )
241219b2ee8SDavid du Colombier 	*q++ = *p++;
242219b2ee8SDavid du Colombier 
243219b2ee8SDavid du Colombier if(p != zznextc)
244219b2ee8SDavid du Colombier 	{
245219b2ee8SDavid du Colombier 	*q = '\0';
246219b2ee8SDavid du Colombier 	if((yylval.ynameblock=srchname(word))==0)
247219b2ee8SDavid du Colombier 		yylval.ynameblock = makename(word);
248219b2ee8SDavid du Colombier 	zznextc = p;
249219b2ee8SDavid du Colombier 	return NAME;
250219b2ee8SDavid du Colombier 	}
251219b2ee8SDavid du Colombier 
252219b2ee8SDavid du Colombier else	{
253219b2ee8SDavid du Colombier 	char junk[100];
254219b2ee8SDavid du Colombier 	sprintf(junk, "Bad character %c (octal %o), line %d of file %s",
255219b2ee8SDavid du Colombier 		*zznextc, *zznextc, yylineno, filestack[ninclude-1].fname);
256219b2ee8SDavid du Colombier 	fatal(junk);
257219b2ee8SDavid du Colombier 	}
258219b2ee8SDavid du Colombier return 0;	/* never executed */
259219b2ee8SDavid du Colombier }
260219b2ee8SDavid du Colombier 
261219b2ee8SDavid du Colombier 
262219b2ee8SDavid du Colombier 
263219b2ee8SDavid du Colombier 
264219b2ee8SDavid du Colombier static int
retsh(char * q)265219b2ee8SDavid du Colombier retsh(char *q)
266219b2ee8SDavid du Colombier {
267219b2ee8SDavid du Colombier register char *p;
268219b2ee8SDavid du Colombier struct shblock *sp;
269219b2ee8SDavid du Colombier 
270219b2ee8SDavid du Colombier for(p=q+1 ; *p==' '||*p=='\t' ; ++p)  ;
271219b2ee8SDavid du Colombier 
272219b2ee8SDavid du Colombier sp = ALLOC(shblock);
273219b2ee8SDavid du Colombier sp->nxtshblock = NULL;
274219b2ee8SDavid du Colombier sp->shbp = (fin ? copys(p) : p );
275219b2ee8SDavid du Colombier yylval.yshblock = sp;
276219b2ee8SDavid du Colombier zznextc = 0;
277219b2ee8SDavid du Colombier return SHELLINE;
278219b2ee8SDavid du Colombier }
279219b2ee8SDavid du Colombier 
280219b2ee8SDavid du Colombier static int
nextlin(void)281219b2ee8SDavid du Colombier nextlin(void)
282219b2ee8SDavid du Colombier {
283219b2ee8SDavid du Colombier static char yytext[INMAX];
284219b2ee8SDavid du Colombier static char *yytextl	= yytext+INMAX;
285219b2ee8SDavid du Colombier char *text, templin[INMAX];
286219b2ee8SDavid du Colombier char c;
287219b2ee8SDavid du Colombier char *p, *t;
288219b2ee8SDavid du Colombier char lastch, *lastchp;
289219b2ee8SDavid du Colombier extern char **linesptr;
290219b2ee8SDavid du Colombier int incom;
291219b2ee8SDavid du Colombier int kc;
292219b2ee8SDavid du Colombier 
293219b2ee8SDavid du Colombier again:
294219b2ee8SDavid du Colombier 
295219b2ee8SDavid du Colombier 	incom = NO;
296219b2ee8SDavid du Colombier 	zznextc = 0;
297219b2ee8SDavid du Colombier 
298219b2ee8SDavid du Colombier if(fin == NULL)
299219b2ee8SDavid du Colombier 	{
300219b2ee8SDavid du Colombier 	if( (text = *linesptr++) == 0)
301219b2ee8SDavid du Colombier 		return 0;
302219b2ee8SDavid du Colombier 	++yylineno;
303219b2ee8SDavid du Colombier 	}
304219b2ee8SDavid du Colombier 
305219b2ee8SDavid du Colombier else	{
306219b2ee8SDavid du Colombier 	for(p = text = yytext ; p<yytextl ; *p++ = kc)
307219b2ee8SDavid du Colombier 		switch(kc = getc(fin))
308219b2ee8SDavid du Colombier 			{
309219b2ee8SDavid du Colombier 			case '\t':
310219b2ee8SDavid du Colombier 				if(p == yytext)
311219b2ee8SDavid du Colombier 					incom = YES;
312219b2ee8SDavid du Colombier 				break;
313219b2ee8SDavid du Colombier 
314219b2ee8SDavid du Colombier 			case ';':
315219b2ee8SDavid du Colombier 				incom = YES;
316219b2ee8SDavid du Colombier 				break;
317219b2ee8SDavid du Colombier 
318219b2ee8SDavid du Colombier 			case '#':
319219b2ee8SDavid du Colombier 				if(! incom)
320219b2ee8SDavid du Colombier 					kc = '\0';
321219b2ee8SDavid du Colombier 				break;
322219b2ee8SDavid du Colombier 
323219b2ee8SDavid du Colombier 			case '\n':
324219b2ee8SDavid du Colombier 				++yylineno;
325219b2ee8SDavid du Colombier 				if(p==yytext || p[-1]!='\\')
326219b2ee8SDavid du Colombier 					{
327219b2ee8SDavid du Colombier 					*p = '\0';
328219b2ee8SDavid du Colombier 					goto endloop;
329219b2ee8SDavid du Colombier 					}
330219b2ee8SDavid du Colombier 				p[-1] = ' ';
331219b2ee8SDavid du Colombier 				while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n')
332219b2ee8SDavid du Colombier 					if(kc == '\n')
333219b2ee8SDavid du Colombier 						++yylineno;
334219b2ee8SDavid du Colombier 
335219b2ee8SDavid du Colombier 				if(kc != EOF)
336219b2ee8SDavid du Colombier 					break;
337219b2ee8SDavid du Colombier 			case EOF:
338219b2ee8SDavid du Colombier 				*p = '\0';
339219b2ee8SDavid du Colombier 				if(ninclude > 1)
340219b2ee8SDavid du Colombier 					{
341219b2ee8SDavid du Colombier 					register struct fstack *stp;
342219b2ee8SDavid du Colombier 					fclose(fin);
343219b2ee8SDavid du Colombier 					--ninclude;
344219b2ee8SDavid du Colombier 					stp = filestack + ninclude;
345219b2ee8SDavid du Colombier 					fin = stp->fin;
346219b2ee8SDavid du Colombier 					yylineno = stp->lineno;
347219b2ee8SDavid du Colombier 					free(stp->fname);
348219b2ee8SDavid du Colombier 					goto again;
349219b2ee8SDavid du Colombier 					}
350219b2ee8SDavid du Colombier 				return 0;
351219b2ee8SDavid du Colombier 			}
352219b2ee8SDavid du Colombier 
353219b2ee8SDavid du Colombier 	fatal("line too long");
354219b2ee8SDavid du Colombier 	}
355219b2ee8SDavid du Colombier 
356219b2ee8SDavid du Colombier endloop:
357219b2ee8SDavid du Colombier 
358219b2ee8SDavid du Colombier 	if((c = text[0]) == '\t')
359219b2ee8SDavid du Colombier 		return retsh(text) ;
360219b2ee8SDavid du Colombier 
3617dd7cddfSDavid du Colombier 	if(isalpha(c) || isdigit(c) || c==' ' || c=='.'|| c=='_')
362219b2ee8SDavid du Colombier 		for(p=text+1; *p!='\0'; )
363219b2ee8SDavid du Colombier 			if(*p == ':')
364219b2ee8SDavid du Colombier 				break;
365219b2ee8SDavid du Colombier 			else if(*p++ == '=')
366219b2ee8SDavid du Colombier 				{
367219b2ee8SDavid du Colombier 				eqsign(text);
368219b2ee8SDavid du Colombier 				return MACRODEF;
369219b2ee8SDavid du Colombier 				}
370219b2ee8SDavid du Colombier 
371219b2ee8SDavid du Colombier /* substitute for macros on dependency line up to the semicolon if any */
372219b2ee8SDavid du Colombier 
373219b2ee8SDavid du Colombier for(t = yytext ; *t!='\0' && *t!=';' ; ++t)
374219b2ee8SDavid du Colombier 	;
375219b2ee8SDavid du Colombier 
376219b2ee8SDavid du Colombier lastchp = t;
377219b2ee8SDavid du Colombier lastch = *t;
378219b2ee8SDavid du Colombier *t = '\0';	/* replace the semi with a null so subst will stop */
379219b2ee8SDavid du Colombier 
380*9b7bf7dfSDavid du Colombier /* Substitute for macros on dependency lines */
381*9b7bf7dfSDavid du Colombier subst(yytext, templin, &templin[sizeof templin - 1]);
382219b2ee8SDavid du Colombier 
383219b2ee8SDavid du Colombier if(lastch)	/* copy the stuff after the semicolon */
384219b2ee8SDavid du Colombier 	{
385219b2ee8SDavid du Colombier 	*lastchp = lastch;
386219b2ee8SDavid du Colombier 	strcat(templin, lastchp);
387219b2ee8SDavid du Colombier 	}
388219b2ee8SDavid du Colombier 
389219b2ee8SDavid du Colombier strcpy(yytext, templin);
390219b2ee8SDavid du Colombier 
39180ee5cbfSDavid du Colombier /* process include files after macro substitution */
39280ee5cbfSDavid du Colombier if(strncmp(text, "include", 7) == 0) {
39380ee5cbfSDavid du Colombier  	if (isinclude(text+7))
39480ee5cbfSDavid du Colombier 		goto again;
39580ee5cbfSDavid du Colombier }
39680ee5cbfSDavid du Colombier 
397219b2ee8SDavid du Colombier for(p = zznextc = text ; *p ; ++p )
398219b2ee8SDavid du Colombier 	if(*p!=' ' && *p!='\t')
399219b2ee8SDavid du Colombier 		return START;
400219b2ee8SDavid du Colombier goto again;
401219b2ee8SDavid du Colombier }
402219b2ee8SDavid du Colombier 
403219b2ee8SDavid du Colombier 
404219b2ee8SDavid du Colombier static int
isinclude(char * s)405219b2ee8SDavid du Colombier isinclude(char *s)
406219b2ee8SDavid du Colombier {
407219b2ee8SDavid du Colombier char *t;
408219b2ee8SDavid du Colombier struct fstack *p;
409219b2ee8SDavid du Colombier 
410219b2ee8SDavid du Colombier for(t=s; *t==' ' || *t=='\t' ; ++t)
411219b2ee8SDavid du Colombier 	;
412219b2ee8SDavid du Colombier if(t == s)
413219b2ee8SDavid du Colombier 	return NO;
414219b2ee8SDavid du Colombier 
415219b2ee8SDavid du Colombier for(s = t; *s!='\n' && *s!='#' && *s!='\0' ; ++s)
416219b2ee8SDavid du Colombier 	if(*s == ':')
417219b2ee8SDavid du Colombier 		return NO;
418219b2ee8SDavid du Colombier *s = '\0';
419219b2ee8SDavid du Colombier 
420219b2ee8SDavid du Colombier if(ninclude >= MAXINCLUDE)
421219b2ee8SDavid du Colombier 	fatal("include depth exceeded");
422219b2ee8SDavid du Colombier p = filestack + ninclude;
423219b2ee8SDavid du Colombier p->fin = fin;
424219b2ee8SDavid du Colombier p->lineno = yylineno;
425219b2ee8SDavid du Colombier p->fname = copys(t);
426219b2ee8SDavid du Colombier if( (fin = fopen(t, "r")) == NULL)
427219b2ee8SDavid du Colombier 	fatal1("Cannot open include file %s", t);
428219b2ee8SDavid du Colombier yylineno = 0;
429219b2ee8SDavid du Colombier ++ninclude;
430219b2ee8SDavid du Colombier return YES;
431219b2ee8SDavid du Colombier }
432219b2ee8SDavid du Colombier 
433219b2ee8SDavid du Colombier 
434219b2ee8SDavid du Colombier int
yyerror(char * s,...)435219b2ee8SDavid du Colombier yyerror(char *s, ...)
436219b2ee8SDavid du Colombier {
437219b2ee8SDavid du Colombier char buf[100];
438219b2ee8SDavid du Colombier 
439219b2ee8SDavid du Colombier sprintf(buf, "line %d of file %s: %s",
440219b2ee8SDavid du Colombier 		yylineno, filestack[ninclude-1].fname, s);
441219b2ee8SDavid du Colombier fatal(buf);
442027288c8SDavid du Colombier return 0;
443219b2ee8SDavid du Colombier }
444