443 lines · 7.2 KB · Text
RawDownload
%{#include "defs.h"%} %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER AMPER AMPERAMPER%union	{	struct shblock *yshblock;	depblkp ydepblock;	nameblkp ynameblock;	} %type <yshblock> SHELLINE, shlist, shellist%type <ynameblock> NAME, namelist%type <ydepblock> deplist, dlist  %% %{struct depblock *pp;static struct shblock *prevshp; static struct nameblock *lefts[NLEFTS];struct nameblock *leftp;static int nlefts; struct lineblock *lp, *lpp;static struct depblock *prevdep;static int sepc;static int allnowait; static struct fstack	{	FILE *fin;	char *fname;	int lineno;	} filestack[MAXINCLUDE];static int ninclude = 0;%}  file:	| file comline	; comline:  START	| MACRODEF	| START namelist deplist shellist = {	    while( --nlefts >= 0)		{		wildp wp; 		leftp = lefts[nlefts];		if(wp = iswild(leftp->namep))			{			leftp->septype = SOMEDEPS;			if(lastwild)				lastwild->next = wp;			else				firstwild = wp;			lastwild = wp;			} 		if(leftp->septype == 0)			leftp->septype = sepc;		else if(leftp->septype != sepc)			{			if(! wp)				fprintf(stderr,					"Inconsistent rules lines for `%s'\n",					leftp->namep);			}		else if(sepc==ALLDEPS && leftp->namep[0]!='.' && $4!=0)			{			for(lp=leftp->linep; lp->nxtlineblock; lp=lp->nxtlineblock)			if(lp->shp)				fprintf(stderr,					"Multiple rules lines for `%s'\n",					leftp->namep);			} 		lp = ALLOC(lineblock);		lp->nxtlineblock = NULL;		lp->depp = $3;		lp->shp = $4;		if(wp)			wp->linep = lp; 		if(equal(leftp->namep, ".SUFFIXES") && $3==0)			leftp->linep = 0;		else if(leftp->linep == 0)			leftp->linep = lp;		else	{			for(lpp = leftp->linep; lpp->nxtlineblock;				lpp = lpp->nxtlineblock) ;				if(sepc==ALLDEPS && leftp->namep[0]=='.')					lpp->shp = 0;			lpp->nxtlineblock = lp;			}		}	}	| error	; namelist: NAME	= { lefts[0] = $1; nlefts = 1; }	| namelist NAME	= { lefts[nlefts++] = $2;	    	if(nlefts>=NLEFTS) fatal("Too many lefts"); }	; deplist:		{		char junk[100];		sprintf(junk, "%s:%d", filestack[ninclude-1].fname, yylineno);		fatal1("Must be a separator on rules line %s", junk);		}	| dlist	; dlist:  sepchar	= { prevdep = 0;  $$ = 0; allnowait = NO; }	| sepchar AMPER	= { prevdep = 0; $$ = 0; allnowait = YES; }	| dlist NAME	= {			  pp = ALLOC(depblock);			  pp->nxtdepblock = NULL;			  pp->depname = $2;			  pp->nowait = allnowait;			  if(prevdep == 0) $$ = pp;			  else  prevdep->nxtdepblock = pp;			  prevdep = pp;			  }	| dlist AMPER	= { if(prevdep) prevdep->nowait = YES; }	| dlist AMPERAMPER	; sepchar:  COLON 	= { sepc = ALLDEPS; }	| DOUBLECOLON	= { sepc = SOMEDEPS; }	; shellist:	= {$$ = 0; }	| shlist = { $$ = $1; }	; shlist:	SHELLINE   = { $$ = $1;  prevshp = $1; }	| shlist SHELLINE = { $$ = $1;			prevshp->nxtshblock = $2;			prevshp = $2;			}	; %%static char *zznextc;	/* null if need another line;			   otherwise points to next char */static int yylineno;static FILE * fin;static int retsh(char *);static int nextlin(void);static int isinclude(char *); int yyparse(void); intparse(char *name){FILE *stream; if(name == CHNULL)	{	stream = NULL;	name = "(builtin-rules)";	}else if(equal(name, "-"))	{	stream = stdin;	name = "(stdin)";	}else if( (stream = fopen(name, "r")) == NULL)	return NO;filestack[0].fname = copys(name);ninclude = 1;fin = stream;yylineno = 0;zznextc = 0; if( yyparse() )	fatal("Description file error"); if(fin)	fclose(fin);return YES;} intyylex(void){char *p;char *q;char word[INMAX]; if(! zznextc )	return nextlin() ; while( isspace(*zznextc) )	++zznextc;switch(*zznextc)	{	case '\0':		return nextlin() ; 	case '|':		if(zznextc[1]==':')			{			zznextc += 2;			return DOUBLECOLON;			}		break;	case ':':		if(*++zznextc == ':')			{			++zznextc;			return DOUBLECOLON;			}		return COLON;	case '>':		++zznextc;		return GREATER;	case '&':		if(*++zznextc == '&')			{			++zznextc;			return AMPERAMPER;			}		return AMPER;	case ';':		return retsh(zznextc) ;	} p = zznextc;q = word; while( ! ( funny[*p] & TERMINAL) )	*q++ = *p++; if(p != zznextc)	{	*q = '\0';	if((yylval.ynameblock=srchname(word))==0)		yylval.ynameblock = makename(word);	zznextc = p;	return NAME;	} else	{	char junk[100];	sprintf(junk, "Bad character %c (octal %o), line %d of file %s",		*zznextc, *zznextc, yylineno, filestack[ninclude-1].fname);	fatal(junk);	}return 0;	/* never executed */}    static intretsh(char *q){register char *p;struct shblock *sp; for(p=q+1 ; *p==' '||*p=='\t' ; ++p)  ; sp = ALLOC(shblock);sp->nxtshblock = NULL;sp->shbp = (fin ? copys(p) : p );yylval.yshblock = sp;zznextc = 0;return SHELLINE;} static intnextlin(void){static char yytext[INMAX];static char *yytextl	= yytext+INMAX;char *text, templin[INMAX];char c;char *p, *t;char lastch, *lastchp;extern char **linesptr;int incom;int kc; again: 	incom = NO;	zznextc = 0; if(fin == NULL)	{	if( (text = *linesptr++) == 0)		return 0;	++yylineno;	} else	{	for(p = text = yytext ; p<yytextl ; *p++ = kc)		switch(kc = getc(fin))			{			case '\t':				if(p == yytext)					incom = YES;				break; 			case ';':				incom = YES;				break; 			case '#':				if(! incom)					kc = '\0';				break; 			case '\n':				++yylineno;				if(p==yytext || p[-1]!='\\')					{					*p = '\0';					goto endloop;					}				p[-1] = ' ';				while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n')					if(kc == '\n')						++yylineno;					if(kc != EOF)					break;			case EOF:				*p = '\0';				if(ninclude > 1)					{					register struct fstack *stp;					fclose(fin);					--ninclude;					stp = filestack + ninclude;					fin = stp->fin;					yylineno = stp->lineno;					free(stp->fname);					goto again;					}				return 0;			} 	fatal("line too long");	} endloop: 	if((c = text[0]) == '\t')		return retsh(text) ;		if(isalpha(c) || isdigit(c) || c==' ' || c=='.'|| c=='_')		for(p=text+1; *p!='\0'; )			if(*p == ':')				break;			else if(*p++ == '=')				{				eqsign(text);				return MACRODEF;				} /* substitute for macros on dependency line up to the semicolon if any */ for(t = yytext ; *t!='\0' && *t!=';' ; ++t)	; lastchp = t;lastch = *t;*t = '\0';	/* replace the semi with a null so subst will stop */ /* Substitute for macros on dependency lines */subst(yytext, templin, &templin[sizeof templin - 1]); if(lastch)	/* copy the stuff after the semicolon */	{	*lastchp = lastch;	strcat(templin, lastchp);	} strcpy(yytext, templin); /* process include files after macro substitution */if(strncmp(text, "include", 7) == 0) { 	if (isinclude(text+7))		goto again;} for(p = zznextc = text ; *p ; ++p )	if(*p!=' ' && *p!='\t')		return START;goto again;}  static intisinclude(char *s){char *t;struct fstack *p; for(t=s; *t==' ' || *t=='\t' ; ++t)	;if(t == s)	return NO; for(s = t; *s!='\n' && *s!='#' && *s!='\0' ; ++s)	if(*s == ':')		return NO;*s = '\0'; if(ninclude >= MAXINCLUDE)	fatal("include depth exceeded");p = filestack + ninclude;p->fin = fin;p->lineno = yylineno;p->fname = copys(t);if( (fin = fopen(t, "r")) == NULL)	fatal1("Cannot open include file %s", t);yylineno = 0;++ninclude;return YES;}  intyyerror(char *s, ...){char buf[100]; sprintf(buf, "line %d of file %s: %s",		yylineno, filestack[ninclude-1].fname, s);fatal(buf);return 0;}