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