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