1 /* $NetBSD: main.c,v 1.57 2000/06/06 03:00:11 sjg Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifdef MAKE_BOOTSTRAP 42 static char rcsid[] = "$NetBSD: main.c,v 1.57 2000/06/06 03:00:11 sjg Exp $"; 43 #else 44 #include <sys/cdefs.h> 45 #ifndef lint 46 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ 47 The Regents of the University of California. All rights reserved.\n"); 48 #endif /* not lint */ 49 50 #ifndef lint 51 #if 0 52 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 53 #else 54 __RCSID("$NetBSD: main.c,v 1.57 2000/06/06 03:00:11 sjg Exp $"); 55 #endif 56 #endif /* not lint */ 57 #endif 58 59 /*- 60 * main.c -- 61 * The main file for this entire program. Exit routines etc 62 * reside here. 63 * 64 * Utility functions defined in this file: 65 * Main_ParseArgLine Takes a line of arguments, breaks them and 66 * treats them as if they were given when first 67 * invoked. Used by the parse module to implement 68 * the .MFLAGS target. 69 * 70 * Error Print a tagged error message. The global 71 * MAKE variable must have been defined. This 72 * takes a format string and two optional 73 * arguments for it. 74 * 75 * Fatal Print an error message and exit. Also takes 76 * a format string and two arguments. 77 * 78 * Punt Aborts all jobs and exits with a message. Also 79 * takes a format string and two arguments. 80 * 81 * Finish Finish things up by printing the number of 82 * errors which occured, as passed to it, and 83 * exiting. 84 */ 85 86 #include <sys/types.h> 87 #include <sys/time.h> 88 #include <sys/param.h> 89 #include <sys/resource.h> 90 #include <sys/signal.h> 91 #include <sys/stat.h> 92 #ifndef MAKE_BOOTSTRAP 93 #include <sys/utsname.h> 94 #endif 95 #include <sys/wait.h> 96 #include <errno.h> 97 #include <fcntl.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #include <time.h> 101 #ifdef __STDC__ 102 #include <stdarg.h> 103 #else 104 #include <varargs.h> 105 #endif 106 #include "make.h" 107 #include "hash.h" 108 #include "dir.h" 109 #include "job.h" 110 #include "pathnames.h" 111 112 #ifndef DEFMAXLOCAL 113 #define DEFMAXLOCAL DEFMAXJOBS 114 #endif /* DEFMAXLOCAL */ 115 116 #define MAKEFLAGS ".MAKEFLAGS" 117 118 Lst create; /* Targets to be made */ 119 time_t now; /* Time at start of make */ 120 GNode *DEFAULT; /* .DEFAULT node */ 121 Boolean allPrecious; /* .PRECIOUS given on line by itself */ 122 123 static Boolean noBuiltins; /* -r flag */ 124 static Lst makefiles; /* ordered list of makefiles to read */ 125 static Boolean printVars; /* print value of one or more vars */ 126 static Lst variables; /* list of variables to print */ 127 int maxJobs; /* -j argument */ 128 static int maxLocal; /* -L argument */ 129 Boolean compatMake; /* -B argument */ 130 Boolean debug; /* -d flag */ 131 Boolean noExecute; /* -n flag */ 132 Boolean keepgoing; /* -k flag */ 133 Boolean queryFlag; /* -q flag */ 134 Boolean touchFlag; /* -t flag */ 135 Boolean usePipes; /* !-P flag */ 136 Boolean ignoreErrors; /* -i flag */ 137 Boolean beSilent; /* -s flag */ 138 Boolean oldVars; /* variable substitution style */ 139 Boolean checkEnvFirst; /* -e flag */ 140 static Boolean jobsRunning; /* TRUE if the jobs might be running */ 141 142 static char * Check_Cwd_av __P((int, char **, int)); 143 static void MainParseArgs __P((int, char **)); 144 char * chdir_verify_path __P((char *, char *)); 145 static int ReadMakefile __P((ClientData, ClientData)); 146 static void usage __P((void)); 147 148 static char *curdir; /* startup directory */ 149 static char *objdir; /* where we chdir'ed to */ 150 static char *progname; /* the program name */ 151 152 /*- 153 * MainParseArgs -- 154 * Parse a given argument vector. Called from main() and from 155 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 156 * 157 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 158 * 159 * Results: 160 * None 161 * 162 * Side Effects: 163 * Various global and local flags will be set depending on the flags 164 * given 165 */ 166 static void 167 MainParseArgs(argc, argv) 168 int argc; 169 char **argv; 170 { 171 char *p; 172 int c; 173 int forceJobs = 0; 174 175 optind = 1; /* since we're called more than once */ 176 #ifdef REMOTE 177 # define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst" 178 #else 179 # define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst" 180 #endif 181 rearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { 182 switch(c) { 183 case 'D': 184 Var_Set(optarg, "1", VAR_GLOBAL); 185 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 186 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 187 break; 188 case 'I': 189 Parse_AddIncludeDir(optarg); 190 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 191 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 192 break; 193 case 'V': 194 printVars = TRUE; 195 (void)Lst_AtEnd(variables, (ClientData)optarg); 196 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 197 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 198 break; 199 case 'B': 200 compatMake = TRUE; 201 break; 202 #ifdef REMOTE 203 case 'L': 204 maxLocal = strtol(optarg, &p, 0); 205 if (*p != '\0' || maxLocal < 1) { 206 (void) fprintf(stderr, "make: illegal argument to -L -- must be positive integer!\n"); 207 exit(1); 208 } 209 Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); 210 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 211 break; 212 #endif 213 case 'P': 214 usePipes = FALSE; 215 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); 216 break; 217 case 'S': 218 keepgoing = FALSE; 219 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 220 break; 221 case 'd': { 222 char *modules = optarg; 223 224 for (; *modules; ++modules) 225 switch (*modules) { 226 case 'A': 227 debug = ~0; 228 break; 229 case 'a': 230 debug |= DEBUG_ARCH; 231 break; 232 case 'c': 233 debug |= DEBUG_COND; 234 break; 235 case 'd': 236 debug |= DEBUG_DIR; 237 break; 238 case 'f': 239 debug |= DEBUG_FOR; 240 break; 241 case 'g': 242 if (modules[1] == '1') { 243 debug |= DEBUG_GRAPH1; 244 ++modules; 245 } 246 else if (modules[1] == '2') { 247 debug |= DEBUG_GRAPH2; 248 ++modules; 249 } 250 break; 251 case 'j': 252 debug |= DEBUG_JOB; 253 break; 254 case 'm': 255 debug |= DEBUG_MAKE; 256 break; 257 case 's': 258 debug |= DEBUG_SUFF; 259 break; 260 case 't': 261 debug |= DEBUG_TARG; 262 break; 263 case 'v': 264 debug |= DEBUG_VAR; 265 break; 266 default: 267 (void)fprintf(stderr, 268 "make: illegal argument to d option -- %c\n", 269 *modules); 270 usage(); 271 } 272 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 273 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 274 break; 275 } 276 case 'e': 277 checkEnvFirst = TRUE; 278 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 279 break; 280 case 'f': 281 (void)Lst_AtEnd(makefiles, (ClientData)optarg); 282 break; 283 case 'i': 284 ignoreErrors = TRUE; 285 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 286 break; 287 case 'j': 288 forceJobs = TRUE; 289 maxJobs = strtol(optarg, &p, 0); 290 if (*p != '\0' || maxJobs < 1) { 291 (void) fprintf(stderr, "make: illegal argument to -j -- must be positive integer!\n"); 292 exit(1); 293 } 294 #ifndef REMOTE 295 maxLocal = maxJobs; 296 #endif 297 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 298 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 299 break; 300 case 'k': 301 keepgoing = TRUE; 302 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 303 break; 304 case 'm': 305 (void) Dir_AddDir(sysIncPath, optarg); 306 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 307 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 308 break; 309 case 'n': 310 noExecute = TRUE; 311 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 312 break; 313 case 'q': 314 queryFlag = TRUE; 315 /* Kind of nonsensical, wot? */ 316 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 317 break; 318 case 'r': 319 noBuiltins = TRUE; 320 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 321 break; 322 case 's': 323 beSilent = TRUE; 324 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 325 break; 326 case 't': 327 touchFlag = TRUE; 328 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 329 break; 330 default: 331 case '?': 332 usage(); 333 } 334 } 335 336 /* 337 * Be compatible if user did not specify -j and did not explicitly 338 * turned compatibility on 339 */ 340 if (!compatMake && !forceJobs) 341 compatMake = TRUE; 342 343 oldVars = TRUE; 344 345 /* 346 * See if the rest of the arguments are variable assignments and 347 * perform them if so. Else take them to be targets and stuff them 348 * on the end of the "create" list. 349 */ 350 for (argv += optind, argc -= optind; *argv; ++argv, --argc) 351 if (Parse_IsVar(*argv)) 352 Parse_DoVar(*argv, VAR_CMD); 353 else { 354 if (!**argv) 355 Punt("illegal (null) argument."); 356 if (**argv == '-') { 357 if ((*argv)[1]) 358 optind = 0; /* -flag... */ 359 else 360 optind = 1; /* - */ 361 goto rearg; 362 } 363 (void)Lst_AtEnd(create, (ClientData)estrdup(*argv)); 364 } 365 } 366 367 /*- 368 * Main_ParseArgLine -- 369 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 370 * is encountered and by main() when reading the .MAKEFLAGS envariable. 371 * Takes a line of arguments and breaks it into its 372 * component words and passes those words and the number of them to the 373 * MainParseArgs function. 374 * The line should have all its leading whitespace removed. 375 * 376 * Results: 377 * None 378 * 379 * Side Effects: 380 * Only those that come from the various arguments. 381 */ 382 void 383 Main_ParseArgLine(line) 384 char *line; /* Line to fracture */ 385 { 386 char **argv; /* Manufactured argument vector */ 387 int argc; /* Number of arguments in argv */ 388 char *args; /* Space used by the args */ 389 char *buf, *p1; 390 char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1); 391 size_t len; 392 393 if (line == NULL) 394 return; 395 for (; *line == ' '; ++line) 396 continue; 397 if (!*line) 398 return; 399 400 buf = emalloc(len = strlen(line) + strlen(argv0) + 2); 401 (void)snprintf(buf, len, "%s %s", argv0, line); 402 if (p1) 403 free(p1); 404 405 argv = brk_string(buf, &argc, TRUE, &args); 406 free(buf); 407 MainParseArgs(argc, argv); 408 409 free(args); 410 free(argv); 411 } 412 413 char * 414 chdir_verify_path(path, obpath) 415 char *path; 416 char *obpath; 417 { 418 struct stat sb; 419 420 if (strchr(path, '$') != 0) { 421 path = Var_Subst(NULL, path, VAR_GLOBAL, 0); 422 } 423 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 424 if (chdir(path)) { 425 (void)fprintf(stderr, "make warning: %s: %s.\n", 426 path, strerror(errno)); 427 return 0; 428 } 429 else { 430 if (path[0] != '/') { 431 (void) snprintf(obpath, MAXPATHLEN, "%s/%s", 432 curdir, path); 433 return obpath; 434 } 435 else 436 return path; 437 } 438 } 439 440 return 0; 441 } 442 443 444 /*- 445 * main -- 446 * The main function, for obvious reasons. Initializes variables 447 * and a few modules, then parses the arguments give it in the 448 * environment and on the command line. Reads the system makefile 449 * followed by either Makefile, makefile or the file given by the 450 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 451 * flags it has received by then uses either the Make or the Compat 452 * module to create the initial list of targets. 453 * 454 * Results: 455 * If -q was given, exits -1 if anything was out-of-date. Else it exits 456 * 0. 457 * 458 * Side Effects: 459 * The program exits when done. Targets are created. etc. etc. etc. 460 */ 461 int 462 main(argc, argv) 463 int argc; 464 char **argv; 465 { 466 Lst targs; /* target nodes to create -- passed to Make_Init */ 467 Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ 468 struct stat sb, sa; 469 char *p, *p1, *path, *pathp, *pwd; 470 char mdpath[MAXPATHLEN + 1]; 471 char obpath[MAXPATHLEN + 1]; 472 char cdpath[MAXPATHLEN + 1]; 473 char *machine = getenv("MACHINE"); 474 char *machine_arch = getenv("MACHINE_ARCH"); 475 char *syspath = getenv("MAKESYSPATH"); 476 Lst sysMkPath; /* Path of sys.mk */ 477 char *cp = NULL, *start; 478 /* avoid faults on read-only strings */ 479 static char defsyspath[] = _PATH_DEFSYSPATH; 480 481 if ((progname = strrchr(argv[0], '/')) != NULL) 482 progname++; 483 else 484 progname = argv[0]; 485 #ifdef RLIMIT_NOFILE 486 /* 487 * get rid of resource limit on file descriptors 488 */ 489 { 490 struct rlimit rl; 491 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 492 rl.rlim_cur != rl.rlim_max) { 493 rl.rlim_cur = rl.rlim_max; 494 (void) setrlimit(RLIMIT_NOFILE, &rl); 495 } 496 } 497 #endif 498 /* 499 * Find where we are and take care of PWD for the automounter... 500 * All this code is so that we know where we are when we start up 501 * on a different machine with pmake. 502 */ 503 curdir = cdpath; 504 if (getcwd(curdir, MAXPATHLEN) == NULL) { 505 (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 506 exit(2); 507 } 508 509 if (stat(curdir, &sa) == -1) { 510 (void)fprintf(stderr, "make: %s: %s.\n", 511 curdir, strerror(errno)); 512 exit(2); 513 } 514 515 /* 516 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX 517 * since the value of curdir can very depending on how we got 518 * here. Ie sitting at a shell prompt (shell that provides $PWD) 519 * or via subdir.mk in which case its likely a shell which does 520 * not provide it. 521 * So, to stop it breaking this case only, we ignore PWD if 522 * MAKEOBJDIRPREFIX is set. 523 */ 524 if ((pwd = getenv("PWD")) != NULL && 525 getenv("MAKEOBJDIRPREFIX") == NULL) { 526 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && 527 sa.st_dev == sb.st_dev) 528 (void) strcpy(curdir, pwd); 529 } 530 531 /* 532 * Get the name of this type of MACHINE from utsname 533 * so we can share an executable for similar machines. 534 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 535 * 536 * Note that both MACHINE and MACHINE_ARCH are decided at 537 * run-time. 538 */ 539 if (!machine) { 540 #ifndef MAKE_BOOTSTRAP 541 struct utsname utsname; 542 543 if (uname(&utsname) == -1) { 544 perror("make: uname"); 545 exit(2); 546 } 547 machine = utsname.machine; 548 #else 549 machine = MACHINE; 550 #endif 551 } 552 553 if (!machine_arch) { 554 #ifndef MACHINE_ARCH 555 #ifdef __ARCHITECTURE__ 556 machine_arch = __ARCHITECTURE__; 557 #else 558 machine_arch = "unknown"; /* XXX: no uname -p yet */ 559 #endif 560 #else 561 machine_arch = MACHINE_ARCH; 562 #endif 563 } 564 565 /* 566 * Just in case MAKEOBJDIR wants us to do something tricky. 567 */ 568 Var_Init(); /* Initialize the lists of variables for 569 * parsing arguments */ 570 Var_Set(".CURDIR", curdir, VAR_GLOBAL); 571 Var_Set("MACHINE", machine, VAR_GLOBAL); 572 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 573 574 /* 575 * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory 576 * exists, change into it and build there. (If a .${MACHINE} suffix 577 * exists, use that directory instead). 578 * Otherwise check MAKEOBJDIRPREFIX`cwd` (or by default, 579 * _PATH_OBJDIRPREFIX`cwd`) and build there if it exists. 580 * If all fails, use the current directory to build. 581 * 582 * Once things are initted, 583 * have to add the original directory to the search path, 584 * and modify the paths for the Makefiles apropriately. The 585 * current directory is also placed as a variable for make scripts. 586 */ 587 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { 588 if (!(path = getenv("MAKEOBJDIR"))) { 589 path = _PATH_OBJDIR; 590 pathp = _PATH_OBJDIRPREFIX; 591 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", 592 path, machine); 593 if (!(objdir = chdir_verify_path(mdpath, obpath))) 594 if (!(objdir=chdir_verify_path(path, obpath))) { 595 (void) snprintf(mdpath, MAXPATHLEN, 596 "%s%s", pathp, curdir); 597 if (!(objdir=chdir_verify_path(mdpath, 598 obpath))) 599 objdir = curdir; 600 } 601 } 602 else if (!(objdir = chdir_verify_path(path, obpath))) 603 objdir = curdir; 604 } 605 else { 606 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); 607 if (!(objdir = chdir_verify_path(mdpath, obpath))) 608 objdir = curdir; 609 } 610 611 setenv("PWD", objdir, 1); 612 613 create = Lst_Init(FALSE); 614 makefiles = Lst_Init(FALSE); 615 printVars = FALSE; 616 variables = Lst_Init(FALSE); 617 beSilent = FALSE; /* Print commands as executed */ 618 ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 619 noExecute = FALSE; /* Execute all commands */ 620 keepgoing = FALSE; /* Stop on error */ 621 allPrecious = FALSE; /* Remove targets when interrupted */ 622 queryFlag = FALSE; /* This is not just a check-run */ 623 noBuiltins = FALSE; /* Read the built-in rules */ 624 touchFlag = FALSE; /* Actually update targets */ 625 usePipes = TRUE; /* Catch child output in pipes */ 626 debug = 0; /* No debug verbosity, please. */ 627 jobsRunning = FALSE; 628 629 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 630 #ifdef REMOTE 631 maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 632 #else 633 maxJobs = maxLocal; 634 #endif 635 compatMake = FALSE; /* No compat mode */ 636 637 638 /* 639 * Initialize the parsing, directory and variable modules to prepare 640 * for the reading of inclusion paths and variable settings on the 641 * command line 642 */ 643 644 /* 645 * Initialize directory structures so -I flags can be processed 646 * correctly, if we have a different objdir, then let the directory 647 * know our curdir. 648 */ 649 Dir_Init(curdir != objdir ? curdir : NULL); 650 Parse_Init(); /* Need to initialize the paths of #include 651 * directories */ 652 Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 653 654 /* 655 * Initialize various variables. 656 * MAKE also gets this name, for compatibility 657 * .MAKEFLAGS gets set to the empty string just in case. 658 * MFLAGS also gets initialized empty, for compatibility. 659 */ 660 Var_Set("MAKE", argv[0], VAR_GLOBAL); 661 Var_Set(".MAKE", argv[0], VAR_GLOBAL); 662 Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 663 Var_Set("MFLAGS", "", VAR_GLOBAL); 664 665 /* 666 * First snag any flags out of the MAKE environment variable. 667 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 668 * in a different format). 669 */ 670 #ifdef POSIX 671 Main_ParseArgLine(getenv("MAKEFLAGS")); 672 #else 673 Main_ParseArgLine(getenv("MAKE")); 674 #endif 675 676 MainParseArgs(argc, argv); 677 678 /* 679 * Initialize archive, target and suffix modules in preparation for 680 * parsing the makefile(s) 681 */ 682 Arch_Init(); 683 Targ_Init(); 684 Suff_Init(); 685 686 DEFAULT = NILGNODE; 687 (void)time(&now); 688 689 /* 690 * Set up the .TARGETS variable to contain the list of targets to be 691 * created. If none specified, make the variable empty -- the parser 692 * will fill the thing in with the default or .MAIN target. 693 */ 694 if (!Lst_IsEmpty(create)) { 695 LstNode ln; 696 697 for (ln = Lst_First(create); ln != NILLNODE; 698 ln = Lst_Succ(ln)) { 699 char *name = (char *)Lst_Datum(ln); 700 701 Var_Append(".TARGETS", name, VAR_GLOBAL); 702 } 703 } else 704 Var_Set(".TARGETS", "", VAR_GLOBAL); 705 706 707 /* 708 * If no user-supplied system path was given (through the -m option) 709 * add the directories from the DEFSYSPATH (more than one may be given 710 * as dir1:...:dirn) to the system include path. 711 */ 712 if (Lst_IsEmpty(sysIncPath)) { 713 if (syspath == NULL || *syspath == '\0') 714 syspath = defsyspath; 715 else 716 syspath = strdup(syspath); 717 718 for (start = syspath; *start != '\0'; start = cp) { 719 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 720 continue; 721 if (*cp == '\0') { 722 (void) Dir_AddDir(sysIncPath, start); 723 } else { 724 *cp++ = '\0'; 725 (void) Dir_AddDir(sysIncPath, start); 726 } 727 } 728 if (syspath != defsyspath) 729 free(syspath); 730 } 731 732 /* 733 * Read in the built-in rules first, followed by the specified 734 * makefile, if it was (makefile != (char *) NULL), or the default 735 * Makefile and makefile, in that order, if it wasn't. 736 */ 737 if (!noBuiltins) { 738 LstNode ln; 739 740 sysMkPath = Lst_Init (FALSE); 741 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath); 742 if (Lst_IsEmpty(sysMkPath)) 743 Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 744 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile); 745 if (ln != NILLNODE) 746 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 747 } 748 749 if (!Lst_IsEmpty(makefiles)) { 750 LstNode ln; 751 752 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); 753 if (ln != NILLNODE) 754 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 755 } else if (!ReadMakefile("makefile", NULL)) 756 (void)ReadMakefile("Makefile", NULL); 757 758 (void)ReadMakefile(".depend", NULL); 759 760 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 761 if (p1) 762 free(p1); 763 764 /* Install all the flags into the MAKE envariable. */ 765 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 766 #ifdef POSIX 767 setenv("MAKEFLAGS", p, 1); 768 #else 769 setenv("MAKE", p, 1); 770 #endif 771 if (p1) 772 free(p1); 773 774 Check_Cwd_av(0, NULL, 0); /* initialize it */ 775 776 777 /* 778 * For compatibility, look at the directories in the VPATH variable 779 * and add them to the search path, if the variable is defined. The 780 * variable's value is in the same format as the PATH envariable, i.e. 781 * <directory>:<directory>:<directory>... 782 */ 783 if (Var_Exists("VPATH", VAR_CMD)) { 784 char *vpath, *path, *cp, savec; 785 /* 786 * GCC stores string constants in read-only memory, but 787 * Var_Subst will want to write this thing, so store it 788 * in an array 789 */ 790 static char VPATH[] = "${VPATH}"; 791 792 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 793 path = vpath; 794 do { 795 /* skip to end of directory */ 796 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 797 continue; 798 /* Save terminator character so know when to stop */ 799 savec = *cp; 800 *cp = '\0'; 801 /* Add directory to search path */ 802 (void) Dir_AddDir(dirSearchPath, path); 803 *cp = savec; 804 path = cp + 1; 805 } while (savec == ':'); 806 (void)free((Address)vpath); 807 } 808 809 /* 810 * Now that all search paths have been read for suffixes et al, it's 811 * time to add the default search path to their lists... 812 */ 813 Suff_DoPaths(); 814 815 /* 816 * Propagate attributes through :: dependency lists. 817 */ 818 Targ_Propagate(); 819 820 /* print the initial graph, if the user requested it */ 821 if (DEBUG(GRAPH1)) 822 Targ_PrintGraph(1); 823 824 /* print the values of any variables requested by the user */ 825 if (printVars) { 826 LstNode ln; 827 828 for (ln = Lst_First(variables); ln != NILLNODE; 829 ln = Lst_Succ(ln)) { 830 char *value = Var_Value((char *)Lst_Datum(ln), 831 VAR_GLOBAL, &p1); 832 833 printf("%s\n", value ? value : ""); 834 if (p1) 835 free(p1); 836 } 837 } 838 839 /* 840 * Have now read the entire graph and need to make a list of targets 841 * to create. If none was given on the command line, we consult the 842 * parsing module to find the main target(s) to create. 843 */ 844 if (Lst_IsEmpty(create)) 845 targs = Parse_MainName(); 846 else 847 targs = Targ_FindList(create, TARG_CREATE); 848 849 if (!compatMake && !printVars) { 850 /* 851 * Initialize job module before traversing the graph, now that 852 * any .BEGIN and .END targets have been read. This is done 853 * only if the -q flag wasn't given (to prevent the .BEGIN from 854 * being executed should it exist). 855 */ 856 if (!queryFlag) { 857 if (maxLocal == -1) 858 maxLocal = maxJobs; 859 Job_Init(maxJobs, maxLocal); 860 jobsRunning = TRUE; 861 } 862 863 /* Traverse the graph, checking on all the targets */ 864 outOfDate = Make_Run(targs); 865 } else if (!printVars) { 866 /* 867 * Compat_Init will take care of creating all the targets as 868 * well as initializing the module. 869 */ 870 Compat_Run(targs); 871 } 872 873 #ifdef CLEANUP 874 Lst_Destroy(targs, NOFREE); 875 Lst_Destroy(variables, NOFREE); 876 Lst_Destroy(makefiles, NOFREE); 877 Lst_Destroy(create, (void (*) __P((ClientData))) free); 878 #endif 879 880 /* print the graph now it's been processed if the user requested it */ 881 if (DEBUG(GRAPH2)) 882 Targ_PrintGraph(2); 883 884 Suff_End(); 885 Targ_End(); 886 Arch_End(); 887 Var_End(); 888 Parse_End(); 889 Dir_End(); 890 Job_End(); 891 892 if (queryFlag && outOfDate) 893 return(1); 894 else 895 return(0); 896 } 897 898 /*- 899 * ReadMakefile -- 900 * Open and parse the given makefile. 901 * 902 * Results: 903 * TRUE if ok. FALSE if couldn't open file. 904 * 905 * Side Effects: 906 * lots 907 */ 908 static Boolean 909 ReadMakefile(p, q) 910 ClientData p, q; 911 { 912 char *fname = p; /* makefile to read */ 913 extern Lst parseIncPath; 914 FILE *stream; 915 size_t len = MAXPATHLEN; 916 char *name, *path = emalloc(len); 917 918 if (!strcmp(fname, "-")) { 919 Parse_File("(stdin)", stdin); 920 Var_Set("MAKEFILE", "", VAR_GLOBAL); 921 } else { 922 if ((stream = fopen(fname, "r")) != NULL) 923 goto found; 924 /* if we've chdir'd, rebuild the path name */ 925 if (curdir != objdir && *fname != '/') { 926 size_t plen = strlen(curdir) + strlen(fname) + 2; 927 if (len < plen) 928 path = erealloc(path, len = 2 * plen); 929 930 (void)snprintf(path, len, "%s/%s", curdir, fname); 931 if ((stream = fopen(path, "r")) != NULL) { 932 fname = path; 933 goto found; 934 } 935 } 936 /* look in -I and system include directories. */ 937 name = Dir_FindFile(fname, parseIncPath); 938 if (!name) 939 name = Dir_FindFile(fname, sysIncPath); 940 if (!name || !(stream = fopen(name, "r"))) { 941 free(path); 942 return(FALSE); 943 } 944 fname = name; 945 /* 946 * set the MAKEFILE variable desired by System V fans -- the 947 * placement of the setting here means it gets set to the last 948 * makefile specified, as it is set by SysV make. 949 */ 950 found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); 951 Parse_File(fname, stream); 952 (void)fclose(stream); 953 } 954 free(path); 955 return(TRUE); 956 } 957 958 959 /* 960 * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR 961 * in situations that would not arrise with ./obj (links or not). 962 * This tends to break things like: 963 * 964 * build: 965 * ${MAKE} includes 966 * 967 * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as 968 * opposed to an argument) in a command line and if so returns 969 * ${.CURDIR} so caller can chdir() so that the assumptions made by 970 * the Makefile hold true. 971 * 972 * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped. 973 * 974 * The chdir() only happens in the child process, and does nothing if 975 * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it 976 * should not break anything. Also if NOCHECKMAKECHDIR is set we 977 * do nothing - to ensure historic semantics can be retained. 978 */ 979 static int Check_Cwd_Off = 0; 980 981 static char * 982 Check_Cwd_av(ac, av, copy) 983 int ac; 984 char **av; 985 int copy; 986 { 987 static char *make[4]; 988 static char *curdir = NULL; 989 char *cp, **mp; 990 int is_cmd, next_cmd; 991 int i; 992 int n; 993 994 if (Check_Cwd_Off) 995 return NULL; 996 997 if (make[0] == NULL) { 998 if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) { 999 Check_Cwd_Off = 1; 1000 return NULL; 1001 } 1002 1003 make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp); 1004 if ((make[0] = strrchr(make[1], '/')) == NULL) { 1005 make[0] = make[1]; 1006 make[1] = NULL; 1007 } else 1008 ++make[0]; 1009 make[2] = NULL; 1010 curdir = Var_Value(".CURDIR", VAR_GLOBAL, &cp); 1011 } 1012 if (ac == 0 || av == NULL) 1013 return NULL; /* initialization only */ 1014 1015 if (getenv("MAKEOBJDIR") == NULL && 1016 getenv("MAKEOBJDIRPREFIX") == NULL) 1017 return NULL; 1018 1019 1020 next_cmd = 1; 1021 for (i = 0; i < ac; ++i) { 1022 is_cmd = next_cmd; 1023 1024 n = strlen(av[i]); 1025 cp = &(av[i])[n - 1]; 1026 if (strspn(av[i], "|&;") == n) { 1027 next_cmd = 1; 1028 continue; 1029 } else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') { 1030 next_cmd = 1; 1031 if (copy) { 1032 do { 1033 *cp-- = '\0'; 1034 } while (*cp == ';' || *cp == '&' || *cp == '|' || 1035 *cp == ')' || *cp == '}') ; 1036 } else { 1037 /* 1038 * XXX this should not happen. 1039 */ 1040 fprintf(stderr, "WARNING: raw arg ends in shell meta '%s'\n", 1041 av[i]); 1042 } 1043 } else 1044 next_cmd = 0; 1045 1046 cp = av[i]; 1047 if (*cp == ';' || *cp == '&' || *cp == '|') 1048 is_cmd = 1; 1049 1050 #ifdef check_cwd_debug 1051 fprintf(stderr, "av[%d] == %s '%s'", 1052 i, (is_cmd) ? "cmd" : "arg", av[i]); 1053 #endif 1054 if (is_cmd != 0) { 1055 if (*cp == '(' || *cp == '{' || 1056 *cp == ';' || *cp == '&' || *cp == '|') { 1057 do { 1058 ++cp; 1059 } while (*cp == '(' || *cp == '{' || 1060 *cp == ';' || *cp == '&' || *cp == '|'); 1061 if (*cp == '\0') { 1062 next_cmd = 1; 1063 continue; 1064 } 1065 } 1066 if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) { 1067 #ifdef check_cwd_debug 1068 fprintf(stderr, " == cd, done.\n"); 1069 #endif 1070 return NULL; 1071 } 1072 for (mp = make; *mp != NULL; ++mp) { 1073 n = strlen(*mp); 1074 if (strcmp(cp, *mp) == 0) { 1075 #ifdef check_cwd_debug 1076 fprintf(stderr, " %s == '%s', chdir(%s)\n", 1077 cp, *mp, curdir); 1078 #endif 1079 return curdir; 1080 } 1081 } 1082 } 1083 #ifdef check_cwd_debug 1084 fprintf(stderr, "\n"); 1085 #endif 1086 } 1087 return NULL; 1088 } 1089 1090 char * 1091 Check_Cwd_Cmd(cmd) 1092 char *cmd; 1093 { 1094 char *cp, *bp, **av; 1095 int ac; 1096 1097 if (Check_Cwd_Off) 1098 return NULL; 1099 1100 if (cmd) { 1101 av = brk_string(cmd, &ac, TRUE, &bp); 1102 #ifdef check_cwd_debug 1103 fprintf(stderr, "splitting: '%s' -> %d words\n", 1104 cmd, ac); 1105 #endif 1106 } else { 1107 ac = 0; 1108 av = NULL; 1109 bp = NULL; 1110 } 1111 cp = Check_Cwd_av(ac, av, 1); 1112 if (bp) { 1113 free(av); 1114 free(bp); 1115 } 1116 return cp; 1117 } 1118 1119 void 1120 Check_Cwd(argv) 1121 char **argv; 1122 { 1123 char *cp; 1124 int ac; 1125 1126 if (Check_Cwd_Off) 1127 return; 1128 1129 for (ac = 0; argv[ac] != NULL; ++ac) 1130 /* NOTHING */; 1131 if (ac == 3 && *argv[1] == '-') { 1132 cp = Check_Cwd_Cmd(argv[2]); 1133 } else { 1134 cp = Check_Cwd_av(ac, argv, 0); 1135 } 1136 if (cp) { 1137 chdir(cp); 1138 } 1139 } 1140 1141 /*- 1142 * Cmd_Exec -- 1143 * Execute the command in cmd, and return the output of that command 1144 * in a string. 1145 * 1146 * Results: 1147 * A string containing the output of the command, or the empty string 1148 * If err is not NULL, it contains the reason for the command failure 1149 * 1150 * Side Effects: 1151 * The string must be freed by the caller. 1152 */ 1153 char * 1154 Cmd_Exec(cmd, err) 1155 char *cmd; 1156 char **err; 1157 { 1158 char *args[4]; /* Args for invoking the shell */ 1159 int fds[2]; /* Pipe streams */ 1160 int cpid; /* Child PID */ 1161 int pid; /* PID from wait() */ 1162 char *res; /* result */ 1163 int status; /* command exit status */ 1164 Buffer buf; /* buffer to store the result */ 1165 char *cp; 1166 int cc; 1167 1168 1169 *err = NULL; 1170 1171 /* 1172 * Set up arguments for shell 1173 */ 1174 args[0] = "sh"; 1175 args[1] = "-c"; 1176 args[2] = cmd; 1177 args[3] = NULL; 1178 1179 /* 1180 * Open a pipe for fetching its output 1181 */ 1182 if (pipe(fds) == -1) { 1183 *err = "Couldn't create pipe for \"%s\""; 1184 goto bad; 1185 } 1186 1187 /* 1188 * Fork 1189 */ 1190 switch (cpid = vfork()) { 1191 case 0: 1192 /* 1193 * Close input side of pipe 1194 */ 1195 (void) close(fds[0]); 1196 1197 /* 1198 * Duplicate the output stream to the shell's output, then 1199 * shut the extra thing down. Note we don't fetch the error 1200 * stream...why not? Why? 1201 */ 1202 (void) dup2(fds[1], 1); 1203 (void) close(fds[1]); 1204 1205 (void) execv("/bin/sh", args); 1206 _exit(1); 1207 /*NOTREACHED*/ 1208 1209 case -1: 1210 *err = "Couldn't exec \"%s\""; 1211 goto bad; 1212 1213 default: 1214 /* 1215 * No need for the writing half 1216 */ 1217 (void) close(fds[1]); 1218 1219 buf = Buf_Init (MAKE_BSIZE); 1220 1221 do { 1222 char result[BUFSIZ]; 1223 cc = read(fds[0], result, sizeof(result)); 1224 if (cc > 0) 1225 Buf_AddBytes(buf, cc, (Byte *) result); 1226 } 1227 while (cc > 0 || (cc == -1 && errno == EINTR)); 1228 1229 /* 1230 * Close the input side of the pipe. 1231 */ 1232 (void) close(fds[0]); 1233 1234 /* 1235 * Wait for the process to exit. 1236 */ 1237 while(((pid = wait(&status)) != cpid) && (pid >= 0)) 1238 continue; 1239 1240 res = (char *)Buf_GetAll (buf, &cc); 1241 Buf_Destroy (buf, FALSE); 1242 1243 if (cc == 0) 1244 *err = "Couldn't read shell's output for \"%s\""; 1245 1246 if (status) 1247 *err = "\"%s\" returned non-zero status"; 1248 1249 /* 1250 * Null-terminate the result, convert newlines to spaces and 1251 * install it in the variable. 1252 */ 1253 res[cc] = '\0'; 1254 cp = &res[cc]; 1255 1256 if (cc > 0 && *--cp == '\n') { 1257 /* 1258 * A final newline is just stripped 1259 */ 1260 *cp-- = '\0'; 1261 } 1262 while (cp >= res) { 1263 if (*cp == '\n') { 1264 *cp = ' '; 1265 } 1266 cp--; 1267 } 1268 break; 1269 } 1270 return res; 1271 bad: 1272 res = emalloc(1); 1273 *res = '\0'; 1274 return res; 1275 } 1276 1277 /*- 1278 * Error -- 1279 * Print an error message given its format. 1280 * 1281 * Results: 1282 * None. 1283 * 1284 * Side Effects: 1285 * The message is printed. 1286 */ 1287 /* VARARGS */ 1288 void 1289 #ifdef __STDC__ 1290 Error(char *fmt, ...) 1291 #else 1292 Error(va_alist) 1293 va_dcl 1294 #endif 1295 { 1296 va_list ap; 1297 #ifdef __STDC__ 1298 va_start(ap, fmt); 1299 #else 1300 char *fmt; 1301 1302 va_start(ap); 1303 fmt = va_arg(ap, char *); 1304 #endif 1305 fprintf(stderr, "%s: ", progname); 1306 (void)vfprintf(stderr, fmt, ap); 1307 va_end(ap); 1308 (void)fprintf(stderr, "\n"); 1309 (void)fflush(stderr); 1310 } 1311 1312 /*- 1313 * Fatal -- 1314 * Produce a Fatal error message. If jobs are running, waits for them 1315 * to finish. 1316 * 1317 * Results: 1318 * None 1319 * 1320 * Side Effects: 1321 * The program exits 1322 */ 1323 /* VARARGS */ 1324 void 1325 #ifdef __STDC__ 1326 Fatal(char *fmt, ...) 1327 #else 1328 Fatal(va_alist) 1329 va_dcl 1330 #endif 1331 { 1332 va_list ap; 1333 #ifdef __STDC__ 1334 va_start(ap, fmt); 1335 #else 1336 char *fmt; 1337 1338 va_start(ap); 1339 fmt = va_arg(ap, char *); 1340 #endif 1341 if (jobsRunning) 1342 Job_Wait(); 1343 1344 (void)vfprintf(stderr, fmt, ap); 1345 va_end(ap); 1346 (void)fprintf(stderr, "\n"); 1347 (void)fflush(stderr); 1348 1349 if (DEBUG(GRAPH2)) 1350 Targ_PrintGraph(2); 1351 exit(2); /* Not 1 so -q can distinguish error */ 1352 } 1353 1354 /* 1355 * Punt -- 1356 * Major exception once jobs are being created. Kills all jobs, prints 1357 * a message and exits. 1358 * 1359 * Results: 1360 * None 1361 * 1362 * Side Effects: 1363 * All children are killed indiscriminately and the program Lib_Exits 1364 */ 1365 /* VARARGS */ 1366 void 1367 #ifdef __STDC__ 1368 Punt(char *fmt, ...) 1369 #else 1370 Punt(va_alist) 1371 va_dcl 1372 #endif 1373 { 1374 va_list ap; 1375 #ifdef __STDC__ 1376 va_start(ap, fmt); 1377 #else 1378 char *fmt; 1379 1380 va_start(ap); 1381 fmt = va_arg(ap, char *); 1382 #endif 1383 1384 (void)fprintf(stderr, "make: "); 1385 (void)vfprintf(stderr, fmt, ap); 1386 va_end(ap); 1387 (void)fprintf(stderr, "\n"); 1388 (void)fflush(stderr); 1389 1390 DieHorribly(); 1391 } 1392 1393 /*- 1394 * DieHorribly -- 1395 * Exit without giving a message. 1396 * 1397 * Results: 1398 * None 1399 * 1400 * Side Effects: 1401 * A big one... 1402 */ 1403 void 1404 DieHorribly() 1405 { 1406 if (jobsRunning) 1407 Job_AbortAll(); 1408 if (DEBUG(GRAPH2)) 1409 Targ_PrintGraph(2); 1410 exit(2); /* Not 1, so -q can distinguish error */ 1411 } 1412 1413 /* 1414 * Finish -- 1415 * Called when aborting due to errors in child shell to signal 1416 * abnormal exit. 1417 * 1418 * Results: 1419 * None 1420 * 1421 * Side Effects: 1422 * The program exits 1423 */ 1424 void 1425 Finish(errors) 1426 int errors; /* number of errors encountered in Make_Make */ 1427 { 1428 Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 1429 } 1430 1431 /* 1432 * emalloc -- 1433 * malloc, but die on error. 1434 */ 1435 void * 1436 emalloc(len) 1437 size_t len; 1438 { 1439 void *p; 1440 1441 if ((p = malloc(len)) == NULL) 1442 enomem(); 1443 return(p); 1444 } 1445 1446 /* 1447 * estrdup -- 1448 * strdup, but die on error. 1449 */ 1450 char * 1451 estrdup(str) 1452 const char *str; 1453 { 1454 char *p; 1455 1456 if ((p = strdup(str)) == NULL) 1457 enomem(); 1458 return(p); 1459 } 1460 1461 /* 1462 * erealloc -- 1463 * realloc, but die on error. 1464 */ 1465 void * 1466 erealloc(ptr, size) 1467 void *ptr; 1468 size_t size; 1469 { 1470 if ((ptr = realloc(ptr, size)) == NULL) 1471 enomem(); 1472 return(ptr); 1473 } 1474 1475 /* 1476 * enomem -- 1477 * die when out of memory. 1478 */ 1479 void 1480 enomem() 1481 { 1482 (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 1483 exit(2); 1484 } 1485 1486 /* 1487 * enunlink -- 1488 * Remove a file carefully, avoiding directories. 1489 */ 1490 int 1491 eunlink(file) 1492 const char *file; 1493 { 1494 struct stat st; 1495 1496 if (lstat(file, &st) == -1) 1497 return -1; 1498 1499 if (S_ISDIR(st.st_mode)) { 1500 errno = EISDIR; 1501 return -1; 1502 } 1503 return unlink(file); 1504 } 1505 1506 /* 1507 * usage -- 1508 * exit with usage message 1509 */ 1510 static void 1511 usage() 1512 { 1513 (void)fprintf(stderr, 1514 "usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ 1515 [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ 1516 [variable=value] [target ...]\n"); 1517 exit(2); 1518 } 1519 1520 1521 int 1522 PrintAddr(a, b) 1523 ClientData a; 1524 ClientData b; 1525 { 1526 printf("%lx ", (unsigned long) a); 1527 return b ? 0 : 0; 1528 } 1529