1 static char *sccsid = "@(#)main.c 4.10 (Berkeley) 87/11/15"; 2 # include "defs" 3 /* 4 command make to update programs. 5 Flags: 'd' print out debugging comments 6 'p' print out a version of the input graph 7 's' silent mode--don't print out commands 8 'f' the next argument is the name of the description file; 9 "makefile" is the default 10 'i' ignore error codes from the shell 11 'S' stop after any command fails (normally do parallel work) 12 'n' don't issue, just print, commands 13 't' touch (update time of) files but don't issue command 14 'q' don't do anything, but check if object is up to date; 15 returns exit code 0 if up to date, -1 if not 16 'e' environment variables have precedence over makefiles 17 */ 18 19 struct nameblock *mainname = NULL; 20 struct nameblock *firstname = NULL; 21 struct lineblock *sufflist = NULL; 22 struct varblock *firstvar = NULL; 23 struct pattern *firstpat = NULL; 24 struct dirhdr *firstod = NULL; 25 26 #include <signal.h> 27 int sigivalue = 0; 28 int sigqvalue = 0; 29 int waitpid = 0; 30 31 int dbgflag = NO; 32 int prtrflag = NO; 33 int silflag = NO; 34 int noexflag = NO; 35 int keepgoing = NO; 36 int noruleflag = NO; 37 int touchflag = NO; 38 int questflag = NO; 39 int ndocoms = NO; 40 int ignerr = NO; /* default is to stop on error */ 41 int okdel = YES; 42 int doenvlast = NO; 43 int inarglist; 44 #ifdef pwb 45 char *prompt = ">"; /* other systems -- pick what you want */ 46 #else 47 char *prompt = ""; /* other systems -- pick what you want */ 48 #endif 49 int nopdir = 0; 50 char junkname[20]; 51 char funny[128]; 52 char options[26 + 1] = { '-' }; 53 54 main(argc,argv) 55 int argc; 56 char *argv[]; 57 { 58 register struct nameblock *p; 59 int i, j; 60 int descset, nfargs; 61 TIMETYPE tjunk; 62 char c, *s; 63 static char onechar[2] = "X"; 64 #ifdef unix 65 int intrupt(); 66 #endif 67 char *op = options + 1; 68 69 70 #ifdef METERFILE 71 meter(METERFILE); 72 #endif 73 74 descset = 0; 75 76 funny['\0'] = (META | TERMINAL); 77 for(s = "=|^();&<>*?[]:$`'\"\\\n" ; *s ; ++s) 78 funny[*s] |= META; 79 for(s = "\n\t :;&>|" ; *s ; ++s) 80 funny[*s] |= TERMINAL; 81 82 83 inarglist = 1; 84 for(i=1; i<argc; ++i) 85 if(argv[i]!=0 && argv[i][0]!='-' && eqsign(argv[i])) 86 argv[i] = 0; 87 88 setvar("$","$"); 89 inarglist = 0; 90 91 for (i=1; i<argc; ++i) 92 if (argv[i]!=0 && argv[i][0]=='-') { 93 for (j=1 ; (c=argv[i][j])!='\0' ; ++j) { 94 *op++ = c; 95 switch (c) { 96 97 case 'd': 98 dbgflag = YES; 99 break; 100 101 case 'p': 102 prtrflag = YES; 103 break; 104 105 case 's': 106 silflag = YES; 107 break; 108 109 case 'i': 110 ignerr = YES; 111 break; 112 113 case 'S': 114 keepgoing = NO; 115 break; 116 117 case 'k': 118 keepgoing = YES; 119 break; 120 121 case 'n': 122 noexflag = YES; 123 break; 124 125 case 'r': 126 noruleflag = YES; 127 break; 128 129 case 't': 130 touchflag = YES; 131 break; 132 133 case 'q': 134 questflag = YES; 135 break; 136 137 case 'f': 138 op--; /* don't pass this one */ 139 if(i >= argc-1) 140 fatal("No description argument after -f flag"); 141 if( rddescf(argv[i+1]) ) 142 fatal1("Cannot open %s", argv[i+1]); 143 argv[i+1] = 0; 144 ++descset; 145 break; 146 147 case 'e': 148 doenvlast = YES; 149 break; 150 151 default: 152 onechar[0] = c; /* to make lint happy */ 153 fatal1("Unknown flag argument %s", onechar); 154 } 155 } 156 argv[i] = 0; 157 } 158 159 *op++ = '\0'; 160 if (strcmp(options, "-") == 0) 161 *options = '\0'; 162 setvar("MFLAGS", options); /* MFLAGS=options to make */ 163 164 setvar("MACHINE", MACHINE); 165 166 if( !descset ) 167 #ifdef unix 168 if( rddescf("makefile") ) rddescf("Makefile"); 169 #endif 170 #ifdef gcos 171 rddescf("makefile"); 172 #endif 173 174 if (doenvlast == YES) 175 readenv(); 176 177 if(prtrflag) printdesc(NO); 178 179 if( srchname(".IGNORE") ) ++ignerr; 180 if( srchname(".SILENT") ) silflag = 1; 181 if(p=srchname(".SUFFIXES")) sufflist = p->linep; 182 if( !sufflist ) fprintf(stderr,"No suffix list.\n"); 183 184 #ifdef unix 185 sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; 186 sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; 187 enbint(intrupt); 188 #endif 189 190 nfargs = 0; 191 192 for(i=1; i<argc; ++i) 193 if((s=argv[i]) != 0) 194 { 195 if((p=srchname(s)) == 0) 196 { 197 p = makename(s); 198 } 199 ++nfargs; 200 doname(p, 0, &tjunk); 201 if(dbgflag) printdesc(YES); 202 } 203 204 /* 205 If no file arguments have been encountered, make the first 206 name encountered that doesn't start with a dot 207 */ 208 209 if(nfargs == 0) 210 if(mainname == 0) 211 fatal("No arguments or description file"); 212 else { 213 doname(mainname, 0, &tjunk); 214 if(dbgflag) printdesc(YES); 215 } 216 217 exit(0); 218 } 219 220 #include <sys/stat.h> 221 222 #ifdef unix 223 intrupt() 224 { 225 struct varblock *varptr(); 226 char *p; 227 TIMETYPE exists(); 228 struct stat sbuf; 229 230 if(okdel && !noexflag && !touchflag && 231 (p = varptr("@")->varval) && 232 (stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) && 233 !isprecious(p) ) 234 { 235 fprintf(stderr, "\n*** %s removed.", p); 236 unlink(p); 237 } 238 239 if(junkname[0]) 240 unlink(junkname); 241 fprintf(stderr, "\n"); 242 exit(2); 243 } 244 245 246 247 248 isprecious(p) 249 char *p; 250 { 251 register struct lineblock *lp; 252 register struct depblock *dp; 253 register struct nameblock *np; 254 255 if(np = srchname(".PRECIOUS")) 256 for(lp = np->linep ; lp ; lp = lp->nxtlineblock) 257 for(dp = lp->depp ; dp ; dp = dp->nxtdepblock) 258 if(! unequal(p, dp->depname->namep)) 259 return(YES); 260 261 return(NO); 262 } 263 264 265 enbint(k) 266 int (*k)(); 267 { 268 if(sigivalue == 0) 269 signal(SIGINT,k); 270 if(sigqvalue == 0) 271 signal(SIGQUIT,k); 272 } 273 #endif 274 275 extern char *builtin[]; 276 277 char **linesptr = builtin; 278 279 FILE * fin; 280 int firstrd = 0; 281 282 283 rddescf(descfile) 284 char *descfile; 285 { 286 FILE * k; 287 288 /* read and parse description */ 289 290 if( !firstrd++ ) 291 { 292 if( !noruleflag ) 293 rdd1( (FILE *) NULL); 294 295 if (doenvlast == NO) 296 readenv(); 297 298 #ifdef pwb 299 { 300 char *nlog, s[BUFSIZ]; 301 nlog = logdir(); 302 if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL) 303 rdd1(k); 304 else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL) 305 rdd1(k); 306 307 if ( (k=fopen("makecomm", "r")) != NULL) 308 rdd1(k); 309 else if ( (k=fopen("Makecomm", "r")) != NULL) 310 rdd1(k); 311 } 312 #endif 313 314 } 315 if(! unequal(descfile, "-")) 316 return( rdd1(stdin) ); 317 318 if( (k = fopen(descfile,"r")) != NULL) 319 return( rdd1(k) ); 320 321 return(1); 322 } 323 324 325 326 327 rdd1(k) 328 FILE * k; 329 { 330 extern int yylineno; 331 extern char *zznextc; 332 333 fin = k; 334 yylineno = 0; 335 zznextc = 0; 336 337 if( yyparse() ) 338 fatal("Description file error"); 339 340 if(fin != NULL && fin != stdin) 341 fclose(fin); 342 343 return(0); 344 } 345 346 printdesc(prntflag) 347 int prntflag; 348 { 349 struct nameblock *p; 350 struct depblock *dp; 351 struct varblock *vp; 352 struct dirhdr *od; 353 struct shblock *sp; 354 struct lineblock *lp; 355 356 #ifdef unix 357 if(prntflag) 358 { 359 printf("Open directories:\n"); 360 for (od = firstod; od; od = od->nxtopendir) 361 printf("\t%d: %s\n", dirfd(od->dirfc), od->dirn); 362 } 363 #endif 364 365 if(firstvar != 0) printf("Macros:\n"); 366 for(vp = firstvar; vp ; vp = vp->nxtvarblock) 367 printf("\t%s = %s\n" , vp->varname , vp->varval); 368 369 for(p = firstname; p; p = p->nxtnameblock) 370 { 371 printf("\n\n%s",p->namep); 372 if(p->linep != 0) printf(":"); 373 if(prntflag) printf(" done=%d",p->done); 374 if(p==mainname) printf(" (MAIN NAME)"); 375 for(lp = p->linep ; lp ; lp = lp->nxtlineblock) 376 { 377 if( dp = lp->depp ) 378 { 379 printf("\n depends on:"); 380 for(; dp ; dp = dp->nxtdepblock) 381 if(dp->depname != 0) 382 printf(" %s ", dp->depname->namep); 383 } 384 385 if(sp = lp->shp) 386 { 387 printf("\n commands:\n"); 388 for( ; sp!=0 ; sp = sp->nxtshblock) 389 printf("\t%s\n", sp->shbp); 390 } 391 } 392 } 393 printf("\n"); 394 fflush(stdout); 395 } 396 397 readenv() 398 { 399 register char **ep, *p; 400 extern char **environ; 401 402 for(ep = environ ; *ep ; ++ep) { 403 for (p = *ep; *p; p++) { 404 if (isalnum(*p)) 405 continue; 406 if (*p == '=') { 407 eqsign(*ep); 408 } 409 break; 410 } 411 } 412 } 413