1 %{#include "defs.h" 2 %} 3 4 %term NAME SHELLINE START MACRODEF COLON DOUBLECOLON GREATER AMPER AMPERAMPER 5 %union 6 { 7 struct shblock *yshblock; 8 depblkp ydepblock; 9 nameblkp ynameblock; 10 } 11 12 %type <yshblock> SHELLINE, shlist, shellist 13 %type <ynameblock> NAME, namelist 14 %type <ydepblock> deplist, dlist 15 16 17 %% 18 19 %{ 20 struct depblock *pp; 21 static struct shblock *prevshp; 22 23 static struct nameblock *lefts[NLEFTS]; 24 struct nameblock *leftp; 25 static int nlefts; 26 27 struct lineblock *lp, *lpp; 28 static struct depblock *prevdep; 29 static int sepc; 30 static int allnowait; 31 32 static struct fstack 33 { 34 FILE *fin; 35 char *fname; 36 int lineno; 37 } filestack[MAXINCLUDE]; 38 static int ninclude = 0; 39 %} 40 41 42 file: 43 | file comline 44 ; 45 46 comline: START 47 | MACRODEF 48 | START namelist deplist shellist = { 49 while( --nlefts >= 0) 50 { 51 wildp wp; 52 53 leftp = lefts[nlefts]; 54 if(wp = iswild(leftp->namep)) 55 { 56 leftp->septype = SOMEDEPS; 57 if(lastwild) 58 lastwild->next = wp; 59 else 60 firstwild = wp; 61 lastwild = wp; 62 } 63 64 if(leftp->septype == 0) 65 leftp->septype = sepc; 66 else if(leftp->septype != sepc) 67 { 68 if(! wp) 69 fprintf(stderr, 70 "Inconsistent rules lines for `%s'\n", 71 leftp->namep); 72 } 73 else if(sepc==ALLDEPS && leftp->namep[0]!='.' && $4!=0) 74 { 75 for(lp=leftp->linep; lp->nxtlineblock; lp=lp->nxtlineblock) 76 if(lp->shp) 77 fprintf(stderr, 78 "Multiple rules lines for `%s'\n", 79 leftp->namep); 80 } 81 82 lp = ALLOC(lineblock); 83 lp->nxtlineblock = NULL; 84 lp->depp = $3; 85 lp->shp = $4; 86 if(wp) 87 wp->linep = lp; 88 89 if(equal(leftp->namep, ".SUFFIXES") && $3==0) 90 leftp->linep = 0; 91 else if(leftp->linep == 0) 92 leftp->linep = lp; 93 else { 94 for(lpp = leftp->linep; lpp->nxtlineblock; 95 lpp = lpp->nxtlineblock) ; 96 if(sepc==ALLDEPS && leftp->namep[0]=='.') 97 lpp->shp = 0; 98 lpp->nxtlineblock = lp; 99 } 100 } 101 } 102 | error 103 ; 104 105 namelist: NAME = { lefts[0] = $1; nlefts = 1; } 106 | namelist NAME = { lefts[nlefts++] = $2; 107 if(nlefts>=NLEFTS) fatal("Too many lefts"); } 108 ; 109 110 deplist: 111 { 112 char junk[100]; 113 sprintf(junk, "%s:%d", filestack[ninclude-1].fname, yylineno); 114 fatal1("Must be a separator on rules line %s", junk); 115 } 116 | dlist 117 ; 118 119 dlist: sepchar = { prevdep = 0; $$ = 0; allnowait = NO; } 120 | sepchar AMPER = { prevdep = 0; $$ = 0; allnowait = YES; } 121 | dlist NAME = { 122 pp = ALLOC(depblock); 123 pp->nxtdepblock = NULL; 124 pp->depname = $2; 125 pp->nowait = allnowait; 126 if(prevdep == 0) $$ = pp; 127 else prevdep->nxtdepblock = pp; 128 prevdep = pp; 129 } 130 | dlist AMPER = { if(prevdep) prevdep->nowait = YES; } 131 | dlist AMPERAMPER 132 ; 133 134 sepchar: COLON = { sepc = ALLDEPS; } 135 | DOUBLECOLON = { sepc = SOMEDEPS; } 136 ; 137 138 shellist: = {$$ = 0; } 139 | shlist = { $$ = $1; } 140 ; 141 142 shlist: SHELLINE = { $$ = $1; prevshp = $1; } 143 | shlist SHELLINE = { $$ = $1; 144 prevshp->nxtshblock = $2; 145 prevshp = $2; 146 } 147 ; 148 149 %% 150 151 static char *zznextc; /* null if need another line; 152 otherwise points to next char */ 153 static int yylineno; 154 static FILE * fin; 155 static int retsh(char *); 156 static int nextlin(void); 157 static int isinclude(char *); 158 159 int yyparse(void); 160 161 int 162 parse(char *name) 163 { 164 FILE *stream; 165 166 if(name == CHNULL) 167 { 168 stream = NULL; 169 name = "(builtin-rules)"; 170 } 171 else if(equal(name, "-")) 172 { 173 stream = stdin; 174 name = "(stdin)"; 175 } 176 else if( (stream = fopen(name, "r")) == NULL) 177 return NO; 178 filestack[0].fname = copys(name); 179 ninclude = 1; 180 fin = stream; 181 yylineno = 0; 182 zznextc = 0; 183 184 if( yyparse() ) 185 fatal("Description file error"); 186 187 if(fin) 188 fclose(fin); 189 return YES; 190 } 191 192 int 193 yylex(void) 194 { 195 char *p; 196 char *q; 197 char word[INMAX]; 198 199 if(! zznextc ) 200 return nextlin() ; 201 202 while( isspace(*zznextc) ) 203 ++zznextc; 204 switch(*zznextc) 205 { 206 case '\0': 207 return nextlin() ; 208 209 case '|': 210 if(zznextc[1]==':') 211 { 212 zznextc += 2; 213 return DOUBLECOLON; 214 } 215 break; 216 case ':': 217 if(*++zznextc == ':') 218 { 219 ++zznextc; 220 return DOUBLECOLON; 221 } 222 return COLON; 223 case '>': 224 ++zznextc; 225 return GREATER; 226 case '&': 227 if(*++zznextc == '&') 228 { 229 ++zznextc; 230 return AMPERAMPER; 231 } 232 return AMPER; 233 case ';': 234 return retsh(zznextc) ; 235 } 236 237 p = zznextc; 238 q = word; 239 240 while( ! ( funny[*p] & TERMINAL) ) 241 *q++ = *p++; 242 243 if(p != zznextc) 244 { 245 *q = '\0'; 246 if((yylval.ynameblock=srchname(word))==0) 247 yylval.ynameblock = makename(word); 248 zznextc = p; 249 return NAME; 250 } 251 252 else { 253 char junk[100]; 254 sprintf(junk, "Bad character %c (octal %o), line %d of file %s", 255 *zznextc, *zznextc, yylineno, filestack[ninclude-1].fname); 256 fatal(junk); 257 } 258 return 0; /* never executed */ 259 } 260 261 262 263 264 static int 265 retsh(char *q) 266 { 267 register char *p; 268 struct shblock *sp; 269 270 for(p=q+1 ; *p==' '||*p=='\t' ; ++p) ; 271 272 sp = ALLOC(shblock); 273 sp->nxtshblock = NULL; 274 sp->shbp = (fin ? copys(p) : p ); 275 yylval.yshblock = sp; 276 zznextc = 0; 277 return SHELLINE; 278 } 279 280 static int 281 nextlin(void) 282 { 283 static char yytext[INMAX]; 284 static char *yytextl = yytext+INMAX; 285 char *text, templin[INMAX]; 286 char c; 287 char *p, *t; 288 char lastch, *lastchp; 289 extern char **linesptr; 290 int incom; 291 int kc; 292 293 again: 294 295 incom = NO; 296 zznextc = 0; 297 298 if(fin == NULL) 299 { 300 if( (text = *linesptr++) == 0) 301 return 0; 302 ++yylineno; 303 } 304 305 else { 306 for(p = text = yytext ; p<yytextl ; *p++ = kc) 307 switch(kc = getc(fin)) 308 { 309 case '\t': 310 if(p == yytext) 311 incom = YES; 312 break; 313 314 case ';': 315 incom = YES; 316 break; 317 318 case '#': 319 if(! incom) 320 kc = '\0'; 321 break; 322 323 case '\n': 324 ++yylineno; 325 if(p==yytext || p[-1]!='\\') 326 { 327 *p = '\0'; 328 goto endloop; 329 } 330 p[-1] = ' '; 331 while( (kc=getc(fin))=='\t' || kc==' ' || kc=='\n') 332 if(kc == '\n') 333 ++yylineno; 334 335 if(kc != EOF) 336 break; 337 case EOF: 338 *p = '\0'; 339 if(ninclude > 1) 340 { 341 register struct fstack *stp; 342 fclose(fin); 343 --ninclude; 344 stp = filestack + ninclude; 345 fin = stp->fin; 346 yylineno = stp->lineno; 347 free(stp->fname); 348 goto again; 349 } 350 return 0; 351 } 352 353 fatal("line too long"); 354 } 355 356 endloop: 357 358 if((c = text[0]) == '\t') 359 return retsh(text) ; 360 361 if(isalpha(c) || isdigit(c) || c==' ' || c=='.'|| c=='_') 362 for(p=text+1; *p!='\0'; ) 363 if(*p == ':') 364 break; 365 else if(*p++ == '=') 366 { 367 eqsign(text); 368 return MACRODEF; 369 } 370 371 /* substitute for macros on dependency line up to the semicolon if any */ 372 373 for(t = yytext ; *t!='\0' && *t!=';' ; ++t) 374 ; 375 376 lastchp = t; 377 lastch = *t; 378 *t = '\0'; /* replace the semi with a null so subst will stop */ 379 380 subst(yytext, templin); /* Substitute for macros on dependency lines */ 381 382 if(lastch) /* copy the stuff after the semicolon */ 383 { 384 *lastchp = lastch; 385 strcat(templin, lastchp); 386 } 387 388 strcpy(yytext, templin); 389 390 /* process include files after macro substitution */ 391 if(strncmp(text, "include", 7) == 0) { 392 if (isinclude(text+7)) 393 goto again; 394 } 395 396 for(p = zznextc = text ; *p ; ++p ) 397 if(*p!=' ' && *p!='\t') 398 return START; 399 goto again; 400 } 401 402 403 static int 404 isinclude(char *s) 405 { 406 char *t; 407 struct fstack *p; 408 409 for(t=s; *t==' ' || *t=='\t' ; ++t) 410 ; 411 if(t == s) 412 return NO; 413 414 for(s = t; *s!='\n' && *s!='#' && *s!='\0' ; ++s) 415 if(*s == ':') 416 return NO; 417 *s = '\0'; 418 419 if(ninclude >= MAXINCLUDE) 420 fatal("include depth exceeded"); 421 p = filestack + ninclude; 422 p->fin = fin; 423 p->lineno = yylineno; 424 p->fname = copys(t); 425 if( (fin = fopen(t, "r")) == NULL) 426 fatal1("Cannot open include file %s", t); 427 yylineno = 0; 428 ++ninclude; 429 return YES; 430 } 431 432 433 int 434 yyerror(char *s, ...) 435 { 436 char buf[100]; 437 438 sprintf(buf, "line %d of file %s: %s", 439 yylineno, filestack[ninclude-1].fname, s); 440 fatal(buf); 441 return 0; 442 } 443