1 %{#include "defs" 2 static char *sccsid = "@(#)gram.y 4.1 (Berkeley) 81/02/28"; 3 %} 4 5 %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER 6 %union 7 { 8 struct shblock *yshblock; 9 struct depblock *ydepblock; 10 struct nameblock *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 %} 32 33 34 file: 35 | file comline 36 ; 37 38 comline: START 39 | MACRODEF 40 | START namelist deplist shellist = { 41 while( --nlefts >= 0) 42 { 43 leftp = lefts[nlefts]; 44 if(leftp->septype == 0) 45 leftp->septype = sepc; 46 else if(leftp->septype != sepc) 47 fprintf(stderr, "Inconsistent rules lines for `%s'\n", 48 leftp->namep); 49 else if(sepc==ALLDEPS && *(leftp->namep)!='.' && $4!=0) 50 { 51 for(lp=leftp->linep; lp->nxtlineblock!=0; lp=lp->nxtlineblock) 52 if(lp->shp) 53 fprintf(stderr, "Multiple rules lines for `%s'\n", 54 leftp->namep); 55 } 56 57 lp = ALLOC(lineblock); 58 lp->nxtlineblock = NULL; 59 lp->depp = $3; 60 lp->shp = $4; 61 62 if(! unequal(leftp->namep, ".SUFFIXES") && $3==0) 63 leftp->linep = 0; 64 else if(leftp->linep == 0) 65 leftp->linep = lp; 66 else { 67 for(lpp = leftp->linep; lpp->nxtlineblock; 68 lpp = lpp->nxtlineblock) ; 69 if(sepc==ALLDEPS && leftp->namep[0]=='.') 70 lpp->shp = 0; 71 lpp->nxtlineblock = lp; 72 } 73 } 74 } 75 | error 76 ; 77 78 namelist: NAME = { lefts[0] = $1; nlefts = 1; } 79 | namelist NAME = { lefts[nlefts++] = $2; 80 if(nlefts>=NLEFTS) fatal("Too many lefts"); } 81 ; 82 83 deplist: 84 { 85 char junk[10]; 86 sprintf(junk, "%d", yylineno); 87 fatal1("Must be a separator on rules line %s", junk); 88 } 89 | dlist 90 ; 91 92 dlist: sepchar = { prevdep = 0; $$ = 0; } 93 | dlist NAME = { 94 pp = ALLOC(depblock); 95 pp->nxtdepblock = NULL; 96 pp->depname = $2; 97 if(prevdep == 0) $$ = pp; 98 else prevdep->nxtdepblock = pp; 99 prevdep = pp; 100 } 101 ; 102 103 sepchar: COLON = { sepc = ALLDEPS; } 104 | DOUBLECOLON = { sepc = SOMEDEPS; } 105 ; 106 107 shellist: = {$$ = 0; } 108 | shlist = { $$ = $1; } 109 ; 110 111 shlist: SHELLINE = { $$ = $1; prevshp = $1; } 112 | shlist SHELLINE = { $$ = $1; 113 prevshp->nxtshblock = $2; 114 prevshp = $2; 115 } 116 ; 117 118 %% 119 120 char *zznextc; /* zero if need another line; otherwise points to next char */ 121 int yylineno; 122 extern FILE * fin; 123 124 yylex() 125 { 126 register char *p; 127 register char *q; 128 char word[INMAX]; 129 130 if(zznextc == 0) 131 return( nextlin() ); 132 133 while( isspace(*zznextc) ) 134 ++zznextc; 135 136 if(*zznextc == '\0') 137 return( nextlin() ); 138 139 if(*zznextc == ':') 140 { 141 if(*++zznextc == ':') 142 { 143 ++zznextc; 144 return(DOUBLECOLON); 145 } 146 else return(COLON); 147 } 148 149 if(*zznextc == '>') 150 { 151 ++zznextc; 152 return(GREATER); 153 } 154 155 if(*zznextc == ';') 156 return( retsh(zznextc) ); 157 158 p = zznextc; 159 q = word; 160 161 while( ! ( funny[*p] & TERMINAL) ) 162 *q++ = *p++; 163 164 if(p != zznextc) 165 { 166 *q = '\0'; 167 if((yylval.ynameblock=srchname(word))==0) 168 yylval.ynameblock = makename(word); 169 zznextc = p; 170 return(NAME); 171 } 172 173 else { 174 fprintf(stderr,"Bad character %c (octal %o), line %d", 175 *zznextc,*zznextc,yylineno); 176 fatal( (char *) NULL ); 177 } 178 return(0); /* never executed */ 179 } 180 181 182 183 184 185 retsh(q) 186 char *q; 187 { 188 register char *p; 189 struct shblock *sp; 190 char *copys(); 191 192 for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ; 193 194 sp = ALLOC(shblock); 195 sp->nxtshblock = NULL; 196 sp->shbp = (fin == NULL ? p : copys(p) ); 197 yylval.yshblock = sp; 198 zznextc = 0; 199 return(SHELLINE); 200 } 201 202 nextlin() 203 { 204 static char yytext[INMAX]; 205 static char *yytextl = yytext+INMAX; 206 char *text, templin[INMAX]; 207 register char c; 208 register char *p, *t; 209 char lastch, *lastchp; 210 extern char **linesptr; 211 int incom; 212 int kc; 213 214 again: 215 216 incom = NO; 217 zznextc = 0; 218 219 if(fin == NULL) 220 { 221 if( (text = *linesptr++) == 0) 222 return(0); 223 ++yylineno; 224 } 225 226 else { 227 for(p = text = yytext ; p<yytextl ; *p++ = kc) 228 switch(kc = getc(fin)) 229 { 230 case '\t': 231 if(p != yytext) 232 break; 233 case ';': 234 incom = YES; 235 break; 236 237 case '#': 238 if(! incom) 239 kc = '\0'; 240 break; 241 242 case '\n': 243 ++yylineno; 244 if(p==yytext || p[-1]!='\\') 245 { 246 *p = '\0'; 247 goto endloop; 248 } 249 p[-1] = ' '; 250 while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n') 251 if(kc == '\n') 252 ++yylineno; 253 254 if(kc != EOF) 255 break; 256 case EOF: 257 *p = '\0'; 258 return(0); 259 } 260 261 fatal("line too long"); 262 } 263 264 endloop: 265 266 if((c = text[0]) == '\t') 267 return( retsh(text) ); 268 269 if(isalpha(c) || isdigit(c) || c==' ' || c=='.') 270 for(p=text+1; *p!='\0'; ) 271 if(*p == ':') 272 break; 273 else if(*p++ == '=') 274 { 275 eqsign(text); 276 return(MACRODEF); 277 } 278 279 /* substitute for macros on dependency line up to the semicolon if any */ 280 281 for(t = yytext ; *t!='\0' && *t!=';' ; ++t) 282 ; 283 284 lastchp = t; 285 lastch = *t; 286 *t = '\0'; 287 288 subst(yytext, templin); /* Substitute for macros on dependency lines */ 289 290 if(lastch) 291 { 292 for(t = templin ; *t ; ++t) 293 ; 294 *t = lastch; 295 while( *++t = *++lastchp ) ; 296 } 297 298 p = templin; 299 t = yytext; 300 while( *t++ = *p++ ) 301 ; 302 303 for(p = zznextc = text ; *p ; ++p ) 304 if(*p!=' ' && *p!='\t') 305 return(START); 306 goto again; 307 } 308