1 static char *sccsid = "@(#)main.c 4.11 (Berkeley) 88/09/13"; 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 if (rddescf("makefile")) 168 rddescf("Makefile"); 169 rddescf(".depend"); 170 } 171 172 if (doenvlast == YES) 173 readenv(); 174 175 if(prtrflag) printdesc(NO); 176 177 if( srchname(".IGNORE") ) ++ignerr; 178 if( srchname(".SILENT") ) silflag = 1; 179 if(p=srchname(".SUFFIXES")) sufflist = p->linep; 180 if( !sufflist ) fprintf(stderr,"No suffix list.\n"); 181 182 #ifdef unix 183 sigivalue = (int) signal(SIGINT, SIG_IGN) & 01; 184 sigqvalue = (int) signal(SIGQUIT, SIG_IGN) & 01; 185 enbint(intrupt); 186 #endif 187 188 nfargs = 0; 189 190 for(i=1; i<argc; ++i) 191 if((s=argv[i]) != 0) 192 { 193 if((p=srchname(s)) == 0) 194 { 195 p = makename(s); 196 } 197 ++nfargs; 198 doname(p, 0, &tjunk); 199 if(dbgflag) printdesc(YES); 200 } 201 202 /* 203 If no file arguments have been encountered, make the first 204 name encountered that doesn't start with a dot 205 */ 206 207 if(nfargs == 0) 208 if(mainname == 0) 209 fatal("No arguments or description file"); 210 else { 211 doname(mainname, 0, &tjunk); 212 if(dbgflag) printdesc(YES); 213 } 214 215 exit(0); 216 } 217 218 #include <sys/stat.h> 219 220 #ifdef unix 221 intrupt() 222 { 223 struct varblock *varptr(); 224 char *p; 225 TIMETYPE exists(); 226 struct stat sbuf; 227 228 if(okdel && !noexflag && !touchflag && 229 (p = varptr("@")->varval) && 230 (stat(p, &sbuf) >= 0 && (sbuf.st_mode&S_IFMT) == S_IFREG) && 231 !isprecious(p) ) 232 { 233 fprintf(stderr, "\n*** %s removed.", p); 234 unlink(p); 235 } 236 237 if(junkname[0]) 238 unlink(junkname); 239 fprintf(stderr, "\n"); 240 exit(2); 241 } 242 243 244 245 246 isprecious(p) 247 char *p; 248 { 249 register struct lineblock *lp; 250 register struct depblock *dp; 251 register struct nameblock *np; 252 253 if(np = srchname(".PRECIOUS")) 254 for(lp = np->linep ; lp ; lp = lp->nxtlineblock) 255 for(dp = lp->depp ; dp ; dp = dp->nxtdepblock) 256 if(! unequal(p, dp->depname->namep)) 257 return(YES); 258 259 return(NO); 260 } 261 262 263 enbint(k) 264 int (*k)(); 265 { 266 if(sigivalue == 0) 267 signal(SIGINT,k); 268 if(sigqvalue == 0) 269 signal(SIGQUIT,k); 270 } 271 #endif 272 273 extern char *builtin[]; 274 275 char **linesptr = builtin; 276 277 FILE * fin; 278 int firstrd = 0; 279 280 281 rddescf(descfile) 282 char *descfile; 283 { 284 FILE * k; 285 286 /* read and parse description */ 287 288 if( !firstrd++ ) 289 { 290 if( !noruleflag ) 291 rdd1( (FILE *) NULL); 292 293 if (doenvlast == NO) 294 readenv(); 295 296 #ifdef pwb 297 { 298 char *nlog, s[BUFSIZ]; 299 nlog = logdir(); 300 if ( (k=fopen( concat(nlog,"/makecomm",s), "r")) != NULL) 301 rdd1(k); 302 else if ( (k=fopen( concat(nlog,"/Makecomm",s), "r")) != NULL) 303 rdd1(k); 304 305 if ( (k=fopen("makecomm", "r")) != NULL) 306 rdd1(k); 307 else if ( (k=fopen("Makecomm", "r")) != NULL) 308 rdd1(k); 309 } 310 #endif 311 312 } 313 if(! unequal(descfile, "-")) 314 return( rdd1(stdin) ); 315 316 if( (k = fopen(descfile,"r")) != NULL) 317 return( rdd1(k) ); 318 319 return(1); 320 } 321 322 323 324 325 rdd1(k) 326 FILE * k; 327 { 328 extern int yylineno; 329 extern char *zznextc; 330 331 fin = k; 332 yylineno = 0; 333 zznextc = 0; 334 335 if( yyparse() ) 336 fatal("Description file error"); 337 338 if(fin != NULL && fin != stdin) 339 fclose(fin); 340 341 return(0); 342 } 343 344 printdesc(prntflag) 345 int prntflag; 346 { 347 struct nameblock *p; 348 struct depblock *dp; 349 struct varblock *vp; 350 struct dirhdr *od; 351 struct shblock *sp; 352 struct lineblock *lp; 353 354 #ifdef unix 355 if(prntflag) 356 { 357 printf("Open directories:\n"); 358 for (od = firstod; od; od = od->nxtopendir) 359 printf("\t%d: %s\n", dirfd(od->dirfc), od->dirn); 360 } 361 #endif 362 363 if(firstvar != 0) printf("Macros:\n"); 364 for(vp = firstvar; vp ; vp = vp->nxtvarblock) 365 printf("\t%s = %s\n" , vp->varname , vp->varval); 366 367 for(p = firstname; p; p = p->nxtnameblock) 368 { 369 printf("\n\n%s",p->namep); 370 if(p->linep != 0) printf(":"); 371 if(prntflag) printf(" done=%d",p->done); 372 if(p==mainname) printf(" (MAIN NAME)"); 373 for(lp = p->linep ; lp ; lp = lp->nxtlineblock) 374 { 375 if( dp = lp->depp ) 376 { 377 printf("\n depends on:"); 378 for(; dp ; dp = dp->nxtdepblock) 379 if(dp->depname != 0) 380 printf(" %s ", dp->depname->namep); 381 } 382 383 if(sp = lp->shp) 384 { 385 printf("\n commands:\n"); 386 for( ; sp!=0 ; sp = sp->nxtshblock) 387 printf("\t%s\n", sp->shbp); 388 } 389 } 390 } 391 printf("\n"); 392 fflush(stdout); 393 } 394 395 readenv() 396 { 397 register char **ep, *p; 398 extern char **environ; 399 400 for(ep = environ ; *ep ; ++ep) { 401 for (p = *ep; *p; p++) { 402 if (isalnum(*p)) 403 continue; 404 if (*p == '=') { 405 eqsign(*ep); 406 } 407 break; 408 } 409 } 410 } 411