📄 gram.y
字号:
/************************************************************************ * * * Copyright (c) 1986 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * * Modification History: * * */%{#ifndef lintstatic char *sccsid = "@(#)gram.y 4.2 (ULTRIX) 12/14/88";#endif lint#include "defs"%}%term NAME SHELLINE START COLON DOUBLECOLON EQUAL A_STRING VERSION%union { SHBLOCK yshblock; DEPBLOCK ydepblock; NAMEBLOCK ynameblock; CHARSTAR ycharstring; }%type <yshblock> SHELLINE, shlist, shellist%type <ynameblock> NAME, namelist, name%type <ydepblock> deplist, dlist%type <ycharstring> A_STRING%%%{DEPBLOCK pp;FSTATIC SHBLOCK prevshp;FSTATIC NAMEBLOCK lefts[NLEFTS];NAMEBLOCK leftp;FSTATIC int nlefts;LINEBLOCK lp, lpp;FSTATIC DEPBLOCK prevdep;FSTATIC int sepc;%}file: | file comline ;comline: START | START macrodef | START namelist deplist shellist = { if(mainname == NULL && IS_OFF(INTRULE)) if(lefts[0]->namep[0] != DOT || any(lefts[0]->namep, SLASH) ) mainname = lefts[0]; while( --nlefts >= 0) { leftp = lefts[nlefts]; if(leftp->septype == 0) leftp->septype = sepc; else if(leftp->septype != sepc) fprintf(stderr, "Inconsistent rules lines for `%s'\n", leftp->namep); else if(sepc==ALLDEPS && *(leftp->namep)!=DOT && $4!=0) { for(lp=leftp->linep; lp->nextline!=0; lp=lp->nextline) if(lp->shp) fprintf(stderr, "Multiple rules lines for `%s'\n", leftp->namep); } lp = ALLOC(lineblock); lp->nextline = 0; lp->depp = $3; lp->shp = $4; if(equal(leftp->namep, ".SUFFIXES") && $3==0) leftp->linep = 0; else if(leftp->linep == 0) leftp->linep = lp; else { for(lpp = leftp->linep; lpp->nextline!=0; lpp = lpp->nextline) ; if(sepc==ALLDEPS && leftp->namep[0]==DOT) lpp->shp = 0; lpp->nextline = lp; } } } | error ;macrodef: NAME EQUAL A_STRING = { setvar($1, $3); } ;namelist: name = { lefts[0] = $1; nlefts = 1; } | namelist name = { lefts[nlefts++] = $2; if(nlefts>NLEFTS) fatal("Too many lefts"); } ;name: NAME = { if(($$ = srchname($1)) == 0) $$ = makename($1); } | NAME VERSION = { if(($$ = srchname($1)) == 0) $$ = makename($1); } ;deplist: = { fatal1("Must be a separator on rules line %d", yylineno); } | dlist ;dlist: sepchar = { prevdep = 0; $$ = 0; } | dlist name = { pp = ALLOC(depblock); pp->nextdep = 0; pp->depname = $2; if(prevdep == 0) $$ = pp; else prevdep->nextdep = pp; prevdep = pp; } ;sepchar: COLON = { sepc = ALLDEPS; } | DOUBLECOLON = { sepc = SOMEDEPS; } ;shellist: = {$$ = 0; } | shlist = { $$ = $1; } ;shlist: SHELLINE = { $$ = $1; prevshp = $1; } | shlist SHELLINE = { $$ = $1; prevshp->nextsh = $2; prevshp = $2; } ;%%#include "ctype.h"CHARSTAR zznextc; /* zero if need another line; otherwise points to next char */int yylineno;static char inmacro = NO;yylex(){ register CHARSTAR p; register CHARSTAR q; static char word[128]; CHARSTAR pword; pword = word; if(zznextc == 0) return( nextlin() ); while( isspace(*zznextc) ) ++zznextc; if(inmacro == YES) { inmacro = NO; yylval.ycharstring = copys(zznextc); zznextc = 0; return(A_STRING); } if(*zznextc == CNULL) return( nextlin() ); if(*zznextc == KOLON) { if(*++zznextc == KOLON) { ++zznextc; return(DOUBLECOLON); } else return(COLON); } if(*zznextc == EQUALS) { inmacro = YES; ++zznextc; return(EQUAL); } if(*zznextc == SKOLON) return( retsh(zznextc) ); p = zznextc; q = word; while( ! ( funny[*p] & TERMINAL) ) *q++ = *p++; if(p != zznextc) { *q = CNULL; yylval.ycharstring = copys(pword); if(*p == RCURLY) { zznextc = p+1; return(VERSION); } if(*p == LCURLY) p++; zznextc = p; return(NAME); } else { fprintf(stderr,"Bad character %c (octal %o), line %d", *zznextc,*zznextc,yylineno); fatal(Nullstr); } return(0); /* never executed */}retsh(q)register CHARSTAR q;{ register CHARSTAR p; register int c; extern CHARSTAR *linesptr; SHBLOCK sp; for(p=q+1 ; *p==BLANK||*p==TAB ; ++p) ; sp = ALLOC(shblock); sp->nextsh = 0; sp->shbp = (fin == NULL ? p : copys(p) ); yylval.yshblock = sp; zznextc = 0;/* * The following if-else "thing" eats up newlines within * shell blocks. */ if(fin == NULL) { if(linesptr[0]) while(linesptr[1] && *linesptr[1] == NEWLINE) { yylineno++; linesptr++; } } else { while((c = GETC()) == NEWLINE) yylineno++; if(c != EOF) ungetc(c, fin); } return(SHELLINE);}nextlin(){ register char c; register CHARSTAR p, t; static char yytext[INMAX]; static CHARSTAR yytextl = yytext+INMAX; CHARSTAR text; char templin[INMAX]; char lastch; CHARSTAR lastchp; extern CHARSTAR *linesptr; register int incom; register int kc; register int nflg; int poundflg;again: incom = 0; zznextc = 0; poundflg = 0; if(fin == NULL) { if( (text = *linesptr++) == 0) return(0); ++yylineno; p = yytext; catstr(p, text); } else { yytext[0] = CNULL; for(p=yytext ; ; ++p) { if(p > yytextl) fatal("line too long"); kc = GETC(); if(kc == EOF) { *p = CNULL; return(0); } else if(kc == SKOLON) ++incom; else if (kc == TAB && p == yytext) ++incom; else if (kc==POUND && !incom && yytext[0] != TAB) { poundflg++; kc = CNULL; } else if (kc == NEWLINE) { ++yylineno; if(p==yytext || p[-1]!=BACKSLASH) break; if(sysvmode && (incom || yytext[0] == TAB)) *p++ = NEWLINE; else p[-1] = BLANK; nflg = YES; while( kc = GETC()) { if(kc != TAB && kc != BLANK && kc != NEWLINE) break; if(incom || yytext[0] == TAB) { if(nflg == YES && kc == TAB) { nflg = NO; continue; } if(kc == NEWLINE) { nflg = YES; } *p++ = kc; } if(kc == NEWLINE) ++yylineno; } if(kc == EOF) { *p = CNULL; return(0); } } *p = kc; } *p = CNULL; text = yytext; } c = text[0]; if(c == TAB) return( retsh(text) );/* * DO include FILES HERE. */ if(sindex(text, "include") == 0 && (text[7] == BLANK || text[7] == TAB)) { CHARSTAR pfile; char buf[1024]; for(p = &text[8]; *p != CNULL; p++) if(*p != TAB || *p != BLANK) break; pfile = p; for(; *p != CNULL && *p != NEWLINE && *p != TAB && *p != BLANK; p++); if(*p != CNULL) *p = CNULL; bzero(buf,1024); subst(pfile, buf);/* * Start using new file. */ fstack(buf, &fin, &yylineno); goto again; } if(isalpha(c) || isdigit(c) || c==BLANK || c==DOT) for(p=text+1; *p!=CNULL; p++) if(*p == KOLON || *p == EQUALS) break;/* substtitute for macros on dependency line up to the semicolon if any */ if(*p != EQUALS) { for(t = yytext ; *t!=CNULL && *t!=SKOLON ; ++t); lastchp = t; lastch = *t; *t = CNULL; subst(yytext, templin); /* Substitute for macros on dep lines */ if(lastch) { for(t = templin ; *t ; ++t); *t = lastch; while( *++t = *++lastchp ) ; } p = templin; t = yytext; while( *t++ = *p++ ); } if(poundflg == 0 || yytext[0] != CNULL) { /* fix from UCB .... strip blanks */ for(p = zznextc = text ; *p ; ++p ) if(*p!=' ' && *p!='\t') return(START); } goto again;}#include "stdio.h"/* * GETC automatically unravels stacked include files. That is, * during include file processing, when a new file is encountered * fstack will stack the FILE pointer argument. Subsequent * calls to GETC with the new FILE pointer will get characters * from the new file. When an EOF is encountered, GETC will * check to see if the file pointer has been stacked. If so, * a character from the previous file will be returned. * The external references are "GETC()" and "fstack(fname,stream,lno)". * "Fstack(stfname,ream,lno)" is used to stack an old file pointer before * the new file is assigned to the same variable. Also stacked are the * file name and the old current lineno, generally, yylineno. */static int morefiles;static struct sfiles{ char sfname[64]; FILE *sfilep; int syylno;} sfiles[20];GETC(){ register int c; c = getc(fin); while(c == EOF && morefiles) { fclose(fin); yylineno = sfiles[--morefiles].syylno; fin = sfiles[morefiles].sfilep; c = getc(fin); } return(c);}fstack(newname, oldfp, oldlno)register char *newname;register FILE **oldfp;register int *oldlno;{ if(access(newname, 4) != 0)/* * This get line can be removed if used elsewhere than make. */ if(get(newname, CD, Nullstr) == NO) fatal1("Cannot read or get %s", newname); if(IS_ON(DBUG)) printf("Include file: \"%s\"\n", newname);/* * Stack the new file name, the old file pointer and the * old yylineno; */ strcat(sfiles[morefiles].sfname, newname); sfiles[morefiles].sfilep = *oldfp; sfiles[morefiles++].syylno = *oldlno; yylineno = 0; if((*oldfp=fopen(newname, "r")) == NULL) fatal1("Cannot open %s", newname);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -