1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * main.cc 28 * 29 * make program main routine plus some helper routines 30 */ 31 32 /* 33 * Included files 34 */ 35 #include <bsd/bsd.h> /* bsd_signal() */ 36 37 38 #include <locale.h> /* setlocale() */ 39 #include <libgen.h> 40 #include <mk/defs.h> 41 #include <mksh/macro.h> /* getvar() */ 42 #include <mksh/misc.h> /* getmem(), setup_char_semantics() */ 43 44 #include <pwd.h> /* getpwnam() */ 45 #include <setjmp.h> 46 #include <signal.h> 47 #include <stdlib.h> 48 #include <sys/errno.h> /* ENOENT */ 49 #include <sys/stat.h> /* fstat() */ 50 #include <fcntl.h> /* open() */ 51 52 # include <sys/systeminfo.h> /* sysinfo() */ 53 54 #include <sys/types.h> /* stat() */ 55 #include <sys/wait.h> /* wait() */ 56 #include <unistd.h> /* execv(), unlink(), access() */ 57 #include <vroot/report.h> /* report_dependency(), get_report_file() */ 58 59 // From read2.cc 60 extern Name normalize_name(register wchar_t *name_string, register int length); 61 62 extern void job_adjust_fini(); 63 64 65 /* 66 * Defined macros 67 */ 68 #define LD_SUPPORT_ENV_VAR "SGS_SUPPORT_32" 69 #define LD_SUPPORT_ENV_VAR_32 "SGS_SUPPORT_32" 70 #define LD_SUPPORT_ENV_VAR_64 "SGS_SUPPORT_64" 71 #define LD_SUPPORT_MAKE_LIB "libmakestate.so.1" 72 #ifdef __i386 73 #define LD_SUPPORT_MAKE_ARCH "i386" 74 #elif __sparc 75 #define LD_SUPPORT_MAKE_ARCH "sparc" 76 #else 77 #error "Unsupported architecture" 78 #endif 79 80 /* 81 * typedefs & structs 82 */ 83 84 /* 85 * Static variables 86 */ 87 static char *argv_zero_string; 88 static Boolean build_failed_ever_seen; 89 static Boolean continue_after_error_ever_seen; /* `-k' */ 90 static Boolean dmake_group_specified; /* `-g' */ 91 static Boolean dmake_max_jobs_specified; /* `-j' */ 92 static Boolean dmake_mode_specified; /* `-m' */ 93 static Boolean dmake_add_mode_specified; /* `-x' */ 94 static Boolean dmake_output_mode_specified; /* `-x DMAKE_OUTPUT_MODE=' */ 95 static Boolean dmake_compat_mode_specified; /* `-x SUN_MAKE_COMPAT_MODE=' */ 96 static Boolean dmake_odir_specified; /* `-o' */ 97 static Boolean dmake_rcfile_specified; /* `-c' */ 98 static Boolean env_wins; /* `-e' */ 99 static Boolean ignore_default_mk; /* `-r' */ 100 static Boolean list_all_targets; /* `-T' */ 101 static int mf_argc; 102 static char **mf_argv; 103 static Dependency_rec not_auto_depen_struct; 104 static Dependency not_auto_depen = ¬_auto_depen_struct; 105 static Boolean pmake_cap_r_specified; /* `-R' */ 106 static Boolean pmake_machinesfile_specified; /* `-M' */ 107 static Boolean stop_after_error_ever_seen; /* `-S' */ 108 static Boolean trace_status; /* `-p' */ 109 110 #ifdef DMAKE_STATISTICS 111 static Boolean getname_stat = false; 112 #endif 113 114 static time_t start_time; 115 static int g_argc; 116 static char **g_argv; 117 118 /* 119 * File table of contents 120 */ 121 extern "C" void cleanup_after_exit(void); 122 123 extern "C" { 124 extern void dmake_exit_callback(void); 125 extern void dmake_message_callback(char *); 126 } 127 128 extern Name normalize_name(register wchar_t *name_string, register int length); 129 130 extern int main(int, char * []); 131 132 static void append_makeflags_string(Name, String); 133 static void doalarm(int); 134 static void enter_argv_values(int , char **, ASCII_Dyn_Array *); 135 static void make_targets(int, char **, Boolean); 136 static int parse_command_option(char); 137 static void read_command_options(int, char **); 138 static void read_environment(Boolean); 139 static void read_files_and_state(int, char **); 140 static Boolean read_makefile(Name, Boolean, Boolean, Boolean); 141 static void report_recursion(Name); 142 static void set_sgs_support(void); 143 static void setup_for_projectdir(void); 144 static void setup_makeflags_argv(void); 145 static void report_dir_enter_leave(Boolean entering); 146 147 extern void expand_value(Name, register String , Boolean); 148 149 static const char verstring[] = "illumos make"; 150 151 jmp_buf jmpbuffer; 152 153 /* 154 * main(argc, argv) 155 * 156 * Parameters: 157 * argc You know what this is 158 * argv You know what this is 159 * 160 * Static variables used: 161 * list_all_targets make -T seen 162 * trace_status make -p seen 163 * 164 * Global variables used: 165 * debug_level Should we trace make actions? 166 * keep_state Set if .KEEP_STATE seen 167 * makeflags The Name "MAKEFLAGS", used to get macro 168 * remote_command_name Name of remote invocation cmd ("on") 169 * running_list List of parallel running processes 170 * stdout_stderr_same true if stdout and stderr are the same 171 * auto_dependencies The Name "SUNPRO_DEPENDENCIES" 172 * temp_file_directory Set to the dir where we create tmp file 173 * trace_reader Set to reflect tracing status 174 * working_on_targets Set when building user targets 175 */ 176 int 177 main(int argc, char *argv[]) 178 { 179 /* 180 * cp is a -> to the value of the MAKEFLAGS env var, 181 * which has to be regular chars. 182 */ 183 register char *cp; 184 char make_state_dir[MAXPATHLEN]; 185 Boolean parallel_flag = false; 186 char *prognameptr; 187 char *slash_ptr; 188 mode_t um; 189 int i; 190 struct itimerval value; 191 char def_dmakerc_path[MAXPATHLEN]; 192 Name dmake_name, dmake_name2; 193 Name dmake_value, dmake_value2; 194 Property prop, prop2; 195 struct stat statbuf; 196 int statval; 197 198 struct stat out_stat, err_stat; 199 hostid = gethostid(); 200 bsd_signals(); 201 202 (void) setlocale(LC_ALL, ""); 203 204 205 #ifdef DMAKE_STATISTICS 206 if (getenv("DMAKE_STATISTICS")) { 207 getname_stat = true; 208 } 209 #endif 210 211 #ifndef TEXT_DOMAIN 212 #define TEXT_DOMAIN "SYS_TEST" 213 #endif 214 textdomain(TEXT_DOMAIN); 215 216 g_argc = argc; 217 g_argv = (char **) malloc((g_argc + 1) * sizeof(char *)); 218 for (i = 0; i < argc; i++) { 219 g_argv[i] = argv[i]; 220 } 221 g_argv[i] = NULL; 222 223 /* 224 * Set argv_zero_string to some form of argv[0] for 225 * recursive MAKE builds. 226 */ 227 228 if (*argv[0] == (int) slash_char) { 229 /* argv[0] starts with a slash */ 230 argv_zero_string = strdup(argv[0]); 231 } else if (strchr(argv[0], (int) slash_char) == NULL) { 232 /* argv[0] contains no slashes */ 233 argv_zero_string = strdup(argv[0]); 234 } else { 235 /* 236 * argv[0] contains at least one slash, 237 * but doesn't start with a slash 238 */ 239 char *tmp_current_path; 240 char *tmp_string; 241 242 tmp_current_path = get_current_path(); 243 tmp_string = getmem(strlen(tmp_current_path) + 1 + 244 strlen(argv[0]) + 1); 245 (void) sprintf(tmp_string, 246 "%s/%s", 247 tmp_current_path, 248 argv[0]); 249 argv_zero_string = strdup(tmp_string); 250 retmem_mb(tmp_string); 251 } 252 253 /* 254 * The following flags are reset if we don't have the 255 * (.nse_depinfo or .make.state) files locked and only set 256 * AFTER the file has been locked. This ensures that if the user 257 * interrupts the program while file_lock() is waiting to lock 258 * the file, the interrupt handler doesn't remove a lock 259 * that doesn't belong to us. 260 */ 261 make_state_lockfile = NULL; 262 make_state_locked = false; 263 264 265 /* 266 * look for last slash char in the path to look at the binary 267 * name. This is to resolve the hard link and invoke make 268 * in svr4 mode. 269 */ 270 271 /* Sun OS make standart */ 272 svr4 = false; 273 posix = false; 274 if(!strcmp(argv_zero_string, "/usr/xpg4/bin/make")) { 275 svr4 = false; 276 posix = true; 277 } else { 278 prognameptr = strrchr(argv[0], '/'); 279 if(prognameptr) { 280 prognameptr++; 281 } else { 282 prognameptr = argv[0]; 283 } 284 if(!strcmp(prognameptr, "svr4.make")) { 285 svr4 = true; 286 posix = false; 287 } 288 } 289 if (getenv(USE_SVR4_MAKE) || getenv("USE_SVID")){ 290 svr4 = true; 291 posix = false; 292 } 293 294 /* 295 * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, . 296 */ 297 char * dmake_compat_mode_var = getenv("SUN_MAKE_COMPAT_MODE"); 298 if (dmake_compat_mode_var != NULL) { 299 if (0 == strcasecmp(dmake_compat_mode_var, "GNU")) { 300 gnu_style = true; 301 } 302 //svr4 = false; 303 //posix = false; 304 } 305 306 /* 307 * Temporary directory set up. 308 */ 309 char * tmpdir_var = getenv("TMPDIR"); 310 if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) { 311 strcpy(mbs_buffer, tmpdir_var); 312 for (tmpdir_var = mbs_buffer+strlen(mbs_buffer); 313 *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer; 314 *tmpdir_var = '\0'); 315 if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */ 316 sprintf(mbs_buffer2, "%s/dmake.tst.%d.XXXXXX", 317 mbs_buffer, getpid()); 318 int fd = mkstemp(mbs_buffer2); 319 if (fd >= 0) { 320 close(fd); 321 unlink(mbs_buffer2); 322 tmpdir = strdup(mbs_buffer); 323 } 324 } 325 } 326 327 /* find out if stdout and stderr point to the same place */ 328 if (fstat(1, &out_stat) < 0) { 329 fatal(gettext("fstat of standard out failed: %s"), errmsg(errno)); 330 } 331 if (fstat(2, &err_stat) < 0) { 332 fatal(gettext("fstat of standard error failed: %s"), errmsg(errno)); 333 } 334 if ((out_stat.st_dev == err_stat.st_dev) && 335 (out_stat.st_ino == err_stat.st_ino)) { 336 stdout_stderr_same = true; 337 } else { 338 stdout_stderr_same = false; 339 } 340 /* Make the vroot package scan the path using shell semantics */ 341 set_path_style(0); 342 343 setup_char_semantics(); 344 345 setup_for_projectdir(); 346 347 /* 348 * If running with .KEEP_STATE, curdir will be set with 349 * the connected directory. 350 */ 351 (void) atexit(cleanup_after_exit); 352 353 load_cached_names(); 354 355 /* 356 * Set command line flags 357 */ 358 setup_makeflags_argv(); 359 read_command_options(mf_argc, mf_argv); 360 read_command_options(argc, argv); 361 if (debug_level > 0) { 362 cp = getenv(makeflags->string_mb); 363 (void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp); 364 } 365 366 setup_interrupt(handle_interrupt); 367 368 read_files_and_state(argc, argv); 369 370 /* 371 * Find the dmake_output_mode: TXT1, TXT2 or HTML1. 372 */ 373 MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE"); 374 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); 375 prop2 = get_prop(dmake_name2->prop, macro_prop); 376 if (prop2 == NULL) { 377 /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */ 378 output_mode = txt1_mode; 379 } else { 380 dmake_value2 = prop2->body.macro.value; 381 if ((dmake_value2 == NULL) || 382 (IS_EQUAL(dmake_value2->string_mb, "TXT1"))) { 383 output_mode = txt1_mode; 384 } else if (IS_EQUAL(dmake_value2->string_mb, "TXT2")) { 385 output_mode = txt2_mode; 386 } else if (IS_EQUAL(dmake_value2->string_mb, "HTML1")) { 387 output_mode = html1_mode; 388 } else { 389 warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"), 390 dmake_value2->string_mb); 391 } 392 } 393 /* 394 * Find the dmake_mode: parallel, or serial. 395 */ 396 if ((!pmake_cap_r_specified) && 397 (!pmake_machinesfile_specified)) { 398 char *s, *b; 399 400 if ((s = strdup(argv[0])) == NULL) 401 fatal(gettext("Out of memory")); 402 403 b = basename(s); 404 405 MBSTOWCS(wcs_buffer, "DMAKE_MODE"); 406 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); 407 prop2 = get_prop(dmake_name2->prop, macro_prop); 408 // If we're invoked as 'make' run serially, regardless of DMAKE_MODE 409 // If we're invoked as 'make' but passed -j, run parallel 410 // If we're invoked as 'dmake', without DMAKE_MODE, default parallel 411 // If we're invoked as 'dmake' and DMAKE_MODE is set, honour it. 412 if ((strcmp(b, "make") == 0) && 413 !dmake_max_jobs_specified) { 414 dmake_mode_type = serial_mode; 415 no_parallel = true; 416 } else if (prop2 == NULL) { 417 /* DMAKE_MODE not defined, default based on our name */ 418 if (strcmp(b, "dmake") == 0) { 419 dmake_mode_type = parallel_mode; 420 no_parallel = false; 421 } 422 } else { 423 dmake_value2 = prop2->body.macro.value; 424 if (IS_EQUAL(dmake_value2->string_mb, "parallel")) { 425 dmake_mode_type = parallel_mode; 426 no_parallel = false; 427 } else if (IS_EQUAL(dmake_value2->string_mb, "serial")) { 428 dmake_mode_type = serial_mode; 429 no_parallel = true; 430 } else { 431 fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb); 432 } 433 } 434 free(s); 435 } 436 437 parallel_flag = true; 438 putenv(strdup("DMAKE_CHILD=TRUE")); 439 440 // 441 // If dmake is running with -t option, set dmake_mode_type to serial. 442 // This is done because doname() calls touch_command() that runs serially. 443 // If we do not do that, maketool will have problems. 444 // 445 if(touch) { 446 dmake_mode_type = serial_mode; 447 no_parallel = true; 448 } 449 450 /* 451 * Check whether stdout and stderr are physically same. 452 * This is in order to decide whether we need to redirect 453 * stderr separately from stdout. 454 * This check is performed only if __DMAKE_SEPARATE_STDERR 455 * is not set. This variable may be used in order to preserve 456 * the 'old' behaviour. 457 */ 458 out_err_same = true; 459 char * dmake_sep_var = getenv("__DMAKE_SEPARATE_STDERR"); 460 if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, "NO"))) { 461 struct stat stdout_stat; 462 struct stat stderr_stat; 463 if( (fstat(1, &stdout_stat) == 0) 464 && (fstat(2, &stderr_stat) == 0) ) 465 { 466 if( (stdout_stat.st_dev != stderr_stat.st_dev) 467 || (stdout_stat.st_ino != stderr_stat.st_ino) ) 468 { 469 out_err_same = false; 470 } 471 } 472 } 473 474 475 /* 476 * Enable interrupt handler for alarms 477 */ 478 (void) bsd_signal(SIGALRM, (SIG_PF)doalarm); 479 480 /* 481 * Check if make should report 482 */ 483 if (getenv(sunpro_dependencies->string_mb) != NULL) { 484 FILE *report_file; 485 486 report_dependency(""); 487 report_file = get_report_file(); 488 if ((report_file != NULL) && (report_file != (FILE*)-1)) { 489 (void) fprintf(report_file, "\n"); 490 } 491 } 492 493 /* 494 * Make sure SUNPRO_DEPENDENCIES is exported (or not) properly. 495 */ 496 if (keep_state) { 497 maybe_append_prop(sunpro_dependencies, macro_prop)-> 498 body.macro.exported = true; 499 } else { 500 maybe_append_prop(sunpro_dependencies, macro_prop)-> 501 body.macro.exported = false; 502 } 503 504 working_on_targets = true; 505 if (trace_status) { 506 dump_make_state(); 507 fclose(stdout); 508 fclose(stderr); 509 exit_status = 0; 510 exit(0); 511 } 512 if (list_all_targets) { 513 dump_target_list(); 514 fclose(stdout); 515 fclose(stderr); 516 exit_status = 0; 517 exit(0); 518 } 519 trace_reader = false; 520 521 /* 522 * Set temp_file_directory to the directory the .make.state 523 * file is written to. 524 */ 525 if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) { 526 temp_file_directory = strdup(get_current_path()); 527 } else { 528 *slash_ptr = (int) nul_char; 529 (void) strcpy(make_state_dir, make_state->string_mb); 530 *slash_ptr = (int) slash_char; 531 /* when there is only one slash and it's the first 532 ** character, make_state_dir should point to '/'. 533 */ 534 if(make_state_dir[0] == '\0') { 535 make_state_dir[0] = '/'; 536 make_state_dir[1] = '\0'; 537 } 538 if (make_state_dir[0] == (int) slash_char) { 539 temp_file_directory = strdup(make_state_dir); 540 } else { 541 char tmp_current_path2[MAXPATHLEN]; 542 543 (void) sprintf(tmp_current_path2, 544 "%s/%s", 545 get_current_path(), 546 make_state_dir); 547 temp_file_directory = strdup(tmp_current_path2); 548 } 549 } 550 551 552 report_dir_enter_leave(true); 553 554 make_targets(argc, argv, parallel_flag); 555 556 report_dir_enter_leave(false); 557 558 if (build_failed_ever_seen) { 559 if (posix) { 560 exit_status = 1; 561 } 562 exit(1); 563 } 564 exit_status = 0; 565 exit(0); 566 /* NOTREACHED */ 567 } 568 569 /* 570 * cleanup_after_exit() 571 * 572 * Called from exit(), performs cleanup actions. 573 * 574 * Parameters: 575 * status The argument exit() was called with 576 * arg Address of an argument vector to 577 * cleanup_after_exit() 578 * 579 * Global variables used: 580 * command_changed Set if we think .make.state should be rewritten 581 * current_line Is set we set commands_changed 582 * do_not_exec_rule 583 * True if -n flag on 584 * done The Name ".DONE", rule we run 585 * keep_state Set if .KEEP_STATE seen 586 * parallel True if building in parallel 587 * quest If -q is on we do not run .DONE 588 * report_dependencies 589 * True if -P flag on 590 * running_list List of parallel running processes 591 * temp_file_name The temp file is removed, if any 592 */ 593 extern "C" void 594 cleanup_after_exit(void) 595 { 596 Running rp; 597 598 extern long getname_bytes_count; 599 extern long getname_names_count; 600 extern long getname_struct_count; 601 extern long freename_bytes_count; 602 extern long freename_names_count; 603 extern long freename_struct_count; 604 extern long other_alloc; 605 606 extern long env_alloc_num; 607 extern long env_alloc_bytes; 608 609 610 #ifdef DMAKE_STATISTICS 611 if(getname_stat) { 612 printf(">>> Getname statistics:\n"); 613 printf(" Allocated:\n"); 614 printf(" Names: %ld\n", getname_names_count); 615 printf(" Strings: %ld Kb (%ld bytes)\n", getname_bytes_count/1000, getname_bytes_count); 616 printf(" Structs: %ld Kb (%ld bytes)\n", getname_struct_count/1000, getname_struct_count); 617 printf(" Total bytes: %ld Kb (%ld bytes)\n", getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count); 618 619 printf("\n Unallocated: %ld\n", freename_names_count); 620 printf(" Names: %ld\n", freename_names_count); 621 printf(" Strings: %ld Kb (%ld bytes)\n", freename_bytes_count/1000, freename_bytes_count); 622 printf(" Structs: %ld Kb (%ld bytes)\n", freename_struct_count/1000, freename_struct_count); 623 printf(" Total bytes: %ld Kb (%ld bytes)\n", freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count); 624 625 printf("\n Total used: %ld Kb (%ld bytes)\n", (getname_struct_count/1000 + getname_bytes_count/1000) - (freename_struct_count/1000 + freename_bytes_count/1000), (getname_struct_count + getname_bytes_count) - (freename_struct_count + freename_bytes_count)); 626 627 printf("\n>>> Other:\n"); 628 printf( 629 " Env (%ld): %ld Kb (%ld bytes)\n", 630 env_alloc_num, 631 env_alloc_bytes/1000, 632 env_alloc_bytes 633 ); 634 635 } 636 #endif 637 638 parallel = false; 639 /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */ 640 if (!getenv(USE_SVR4_MAKE)){ 641 /* Build the target .DONE or .FAILED if we caught an error */ 642 if (!quest && !list_all_targets) { 643 Name failed_name; 644 645 MBSTOWCS(wcs_buffer, ".FAILED"); 646 failed_name = GETNAME(wcs_buffer, FIND_LENGTH); 647 if ((exit_status != 0) && (failed_name->prop != NULL)) { 648 /* 649 * [tolik] switch DMake to serial mode 650 */ 651 dmake_mode_type = serial_mode; 652 no_parallel = true; 653 (void) doname(failed_name, false, true); 654 } else { 655 if (!trace_status) { 656 /* 657 * Switch DMake to serial mode 658 */ 659 dmake_mode_type = serial_mode; 660 no_parallel = true; 661 (void) doname(done, false, true); 662 } 663 } 664 } 665 } 666 /* 667 * Remove the temp file utilities report dependencies thru if it 668 * is still around 669 */ 670 if (temp_file_name != NULL) { 671 (void) unlink(temp_file_name->string_mb); 672 } 673 /* 674 * Do not save the current command in .make.state if make 675 * was interrupted. 676 */ 677 if (current_line != NULL) { 678 command_changed = true; 679 current_line->body.line.command_used = NULL; 680 } 681 /* 682 * For each parallel build process running, remove the temp files 683 * and zap the command line so it won't be put in .make.state 684 */ 685 for (rp = running_list; rp != NULL; rp = rp->next) { 686 if (rp->temp_file != NULL) { 687 (void) unlink(rp->temp_file->string_mb); 688 } 689 if (rp->stdout_file != NULL) { 690 (void) unlink(rp->stdout_file); 691 retmem_mb(rp->stdout_file); 692 rp->stdout_file = NULL; 693 } 694 if (rp->stderr_file != NULL) { 695 (void) unlink(rp->stderr_file); 696 retmem_mb(rp->stderr_file); 697 rp->stderr_file = NULL; 698 } 699 command_changed = true; 700 /* 701 line = get_prop(rp->target->prop, line_prop); 702 if (line != NULL) { 703 line->body.line.command_used = NULL; 704 } 705 */ 706 } 707 /* Remove the statefile lock file if the file has been locked */ 708 if ((make_state_lockfile != NULL) && (make_state_locked)) { 709 (void) unlink(make_state_lockfile); 710 make_state_lockfile = NULL; 711 make_state_locked = false; 712 } 713 /* Write .make.state */ 714 write_state_file(1, (Boolean) 1); 715 716 job_adjust_fini(); 717 } 718 719 /* 720 * handle_interrupt() 721 * 722 * This is where C-C traps are caught. 723 * 724 * Parameters: 725 * 726 * Global variables used (except DMake 1.0): 727 * current_target Sometimes the current target is removed 728 * do_not_exec_rule But not if -n is on 729 * quest or -q 730 * running_list List of parallel running processes 731 * touch Current target is not removed if -t on 732 */ 733 void 734 handle_interrupt(int) 735 { 736 Property member; 737 Running rp; 738 739 (void) fflush(stdout); 740 if (childPid > 0) { 741 kill(childPid, SIGTERM); 742 childPid = -1; 743 } 744 for (rp = running_list; rp != NULL; rp = rp->next) { 745 if (rp->state != build_running) { 746 continue; 747 } 748 if (rp->pid > 0) { 749 kill(rp->pid, SIGTERM); 750 rp->pid = -1; 751 } 752 } 753 if (getpid() == getpgrp()) { 754 bsd_signal(SIGTERM, SIG_IGN); 755 kill (-getpid(), SIGTERM); 756 } 757 /* Clean up all parallel children already finished */ 758 finish_children(false); 759 760 /* Make sure the processes running under us terminate first */ 761 762 while (wait((int *) NULL) != -1); 763 /* Delete the current targets unless they are precious */ 764 if ((current_target != NULL) && 765 current_target->is_member && 766 ((member = get_prop(current_target->prop, member_prop)) != NULL)) { 767 current_target = member->body.member.library; 768 } 769 if (!do_not_exec_rule && 770 !touch && 771 !quest && 772 (current_target != NULL) && 773 !(current_target->stat.is_precious || all_precious)) { 774 775 /* BID_1030811 */ 776 /* azv 16 Oct 95 */ 777 current_target->stat.time = file_no_time; 778 779 if (exists(current_target) != file_doesnt_exist) { 780 (void) fprintf(stderr, 781 "\n*** %s ", 782 current_target->string_mb); 783 if (current_target->stat.is_dir) { 784 (void) fprintf(stderr, 785 gettext("not removed.\n"), 786 current_target->string_mb); 787 } else if (unlink(current_target->string_mb) == 0) { 788 (void) fprintf(stderr, 789 gettext("removed.\n"), 790 current_target->string_mb); 791 } else { 792 (void) fprintf(stderr, 793 gettext("could not be removed: %s.\n"), 794 current_target->string_mb, 795 errmsg(errno)); 796 } 797 } 798 } 799 for (rp = running_list; rp != NULL; rp = rp->next) { 800 if (rp->state != build_running) { 801 continue; 802 } 803 if (rp->target->is_member && 804 ((member = get_prop(rp->target->prop, member_prop)) != 805 NULL)) { 806 rp->target = member->body.member.library; 807 } 808 if (!do_not_exec_rule && 809 !touch && 810 !quest && 811 !(rp->target->stat.is_precious || all_precious)) { 812 813 rp->target->stat.time = file_no_time; 814 if (exists(rp->target) != file_doesnt_exist) { 815 (void) fprintf(stderr, 816 "\n*** %s ", 817 rp->target->string_mb); 818 if (rp->target->stat.is_dir) { 819 (void) fprintf(stderr, 820 gettext("not removed.\n"), 821 rp->target->string_mb); 822 } else if (unlink(rp->target->string_mb) == 0) { 823 (void) fprintf(stderr, 824 gettext("removed.\n"), 825 rp->target->string_mb); 826 } else { 827 (void) fprintf(stderr, 828 gettext("could not be removed: %s.\n"), 829 rp->target->string_mb, 830 errmsg(errno)); 831 } 832 } 833 } 834 } 835 836 837 /* Have we locked .make.state or .nse_depinfo? */ 838 if ((make_state_lockfile != NULL) && (make_state_locked)) { 839 unlink(make_state_lockfile); 840 make_state_lockfile = NULL; 841 make_state_locked = false; 842 } 843 /* 844 * Re-read .make.state file (it might be changed by recursive make) 845 */ 846 check_state(NULL); 847 848 report_dir_enter_leave(false); 849 850 exit_status = 2; 851 exit(2); 852 } 853 854 /* 855 * doalarm(sig, ...) 856 * 857 * Handle the alarm interrupt but do nothing. Side effect is to 858 * cause return from wait3. 859 * 860 * Parameters: 861 * sig 862 * 863 * Global variables used: 864 */ 865 /*ARGSUSED*/ 866 static void 867 doalarm(int) 868 { 869 return; 870 } 871 872 873 /* 874 * read_command_options(argc, argv) 875 * 876 * Scan the cmd line options and process the ones that start with "-" 877 * 878 * Return value: 879 * -M argument, if any 880 * 881 * Parameters: 882 * argc You know what this is 883 * argv You know what this is 884 * 885 * Global variables used: 886 */ 887 static void 888 read_command_options(register int argc, register char **argv) 889 { 890 register int ch; 891 int current_optind = 1; 892 int last_optind_with_double_hyphen = 0; 893 int last_optind; 894 int last_current_optind; 895 register int i; 896 register int j; 897 register int k; 898 register int makefile_next = 0; /* 899 * flag to note options: 900 * -c, f, g, j, m, o 901 */ 902 const char *tptr; 903 const char *CMD_OPTS; 904 905 extern char *optarg; 906 extern int optind, opterr, optopt; 907 908 #define SUNPRO_CMD_OPTS "-~Bbc:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:" 909 910 # define SVR4_CMD_OPTS "-c:ef:g:ij:km:nO:o:pqrsTtVv" 911 912 /* 913 * Added V in SVR4_CMD_OPTS also, which is going to be a hidden 914 * option, just to make sure that the getopt doesn't fail when some 915 * users leave their USE_SVR4_MAKE set and try to use the makefiles 916 * that are designed to issue commands like $(MAKE) -V. Anyway it 917 * sets the same flag but ensures that getopt doesn't fail. 918 */ 919 920 opterr = 0; 921 optind = 1; 922 while (1) { 923 last_optind=optind; /* Save optind and current_optind values */ 924 last_current_optind=current_optind; /* in case we have to repeat this round. */ 925 if (svr4) { 926 CMD_OPTS=SVR4_CMD_OPTS; 927 ch = getopt(argc, argv, SVR4_CMD_OPTS); 928 } else { 929 CMD_OPTS=SUNPRO_CMD_OPTS; 930 ch = getopt(argc, argv, SUNPRO_CMD_OPTS); 931 } 932 if (ch == EOF) { 933 if(optind < argc) { 934 /* 935 * Fixing bug 4102537: 936 * Strange behaviour of command make using -- option. 937 * Not all argv have been processed 938 * Skip non-flag argv and continue processing. 939 */ 940 optind++; 941 current_optind++; 942 continue; 943 } else { 944 break; 945 } 946 947 } 948 if (ch == '?') { 949 if (optopt == '-') { 950 /* Bug 5060758: getopt() changed behavior (s10_60), 951 * and now we have to deal with cases when options 952 * with double hyphen appear here, from -$(MAKEFLAGS) 953 */ 954 i = current_optind; 955 if (argv[i][0] == '-') { 956 if (argv[i][1] == '-') { 957 if (argv[i][2] != '\0') { 958 /* Check if this option is allowed */ 959 tptr = strchr(CMD_OPTS, argv[i][2]); 960 if (tptr) { 961 if (last_optind_with_double_hyphen != current_optind) { 962 /* This is first time we are trying to fix "--" 963 * problem with this option. If we come here second 964 * time, we will go to fatal error. 965 */ 966 last_optind_with_double_hyphen = current_optind; 967 968 /* Eliminate first hyphen character */ 969 for (j=0; argv[i][j] != '\0'; j++) { 970 argv[i][j] = argv[i][j+1]; 971 } 972 973 /* Repeat the processing of this argument */ 974 optind=last_optind; 975 current_optind=last_current_optind; 976 continue; 977 } 978 } 979 } 980 } 981 } 982 } 983 } 984 985 if (ch == '?') { 986 if (svr4) { 987 fprintf(stderr, 988 gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); 989 fprintf(stderr, 990 gettext(" [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n")); 991 fprintf(stderr, 992 gettext(" [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n")); 993 tptr = strchr(SVR4_CMD_OPTS, optopt); 994 } else { 995 fprintf(stderr, 996 gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); 997 fprintf(stderr, 998 gettext(" [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n")); 999 fprintf(stderr, 1000 gettext(" [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n")); 1001 fprintf(stderr, 1002 gettext(" [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); 1003 tptr = strchr(SUNPRO_CMD_OPTS, optopt); 1004 } 1005 if (!tptr) { 1006 fatal(gettext("Unknown option `-%c'"), optopt); 1007 } else { 1008 fatal(gettext("Missing argument after `-%c'"), optopt); 1009 } 1010 } 1011 1012 1013 1014 makefile_next |= parse_command_option(ch); 1015 /* 1016 * If we're done processing all of the options of 1017 * ONE argument string... 1018 */ 1019 if (current_optind < optind) { 1020 i = current_optind; 1021 k = 0; 1022 /* If there's an argument for an option... */ 1023 if ((optind - current_optind) > 1) { 1024 k = i + 1; 1025 } 1026 switch (makefile_next) { 1027 case 0: 1028 argv[i] = NULL; 1029 /* This shouldn't happen */ 1030 if (k) { 1031 argv[k] = NULL; 1032 } 1033 break; 1034 case 1: /* -f seen */ 1035 argv[i] = (char *)"-f"; 1036 break; 1037 case 2: /* -c seen */ 1038 argv[i] = (char *)"-c"; 1039 break; 1040 case 4: /* -g seen */ 1041 argv[i] = (char *)"-g"; 1042 break; 1043 case 8: /* -j seen */ 1044 argv[i] = (char *)"-j"; 1045 break; 1046 case 16: /* -M seen */ 1047 argv[i] = (char *)"-M"; 1048 break; 1049 case 32: /* -m seen */ 1050 argv[i] = (char *)"-m"; 1051 break; 1052 case 128: /* -O seen */ 1053 argv[i] = (char *)"-O"; 1054 break; 1055 case 256: /* -K seen */ 1056 argv[i] = (char *)"-K"; 1057 break; 1058 case 512: /* -o seen */ 1059 argv[i] = (char *)"-o"; 1060 break; 1061 case 1024: /* -x seen */ 1062 argv[i] = (char *)"-x"; 1063 break; 1064 default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */ 1065 fatal(gettext("Illegal command line. More than one option requiring\nan argument given in the same argument group")); 1066 } 1067 1068 makefile_next = 0; 1069 current_optind = optind; 1070 } 1071 } 1072 } 1073 1074 static void 1075 quote_str(char *str, char *qstr) 1076 { 1077 char *to; 1078 char *from; 1079 1080 to = qstr; 1081 for (from = str; *from; from++) { 1082 switch (*from) { 1083 case ';': /* End of command */ 1084 case '(': /* Start group */ 1085 case ')': /* End group */ 1086 case '{': /* Start group */ 1087 case '}': /* End group */ 1088 case '[': /* Reg expr - any of a set of chars */ 1089 case ']': /* End of set of chars */ 1090 case '|': /* Pipe or logical-or */ 1091 case '^': /* Old-fashioned pipe */ 1092 case '&': /* Background or logical-and */ 1093 case '<': /* Redirect stdin */ 1094 case '>': /* Redirect stdout */ 1095 case '*': /* Reg expr - any sequence of chars */ 1096 case '?': /* Reg expr - any single char */ 1097 case '$': /* Variable substitution */ 1098 case '\'': /* Singe quote - turn off all magic */ 1099 case '"': /* Double quote - span whitespace */ 1100 case '`': /* Backquote - run a command */ 1101 case '#': /* Comment */ 1102 case ' ': /* Space (for MACRO=value1 value2 */ 1103 case '\\': /* Escape char - turn off magic of next char */ 1104 *to++ = '\\'; 1105 break; 1106 1107 default: 1108 break; 1109 } 1110 *to++ = *from; 1111 } 1112 *to = '\0'; 1113 } 1114 1115 static void 1116 unquote_str(char *str, char *qstr) 1117 { 1118 char *to; 1119 char *from; 1120 1121 to = qstr; 1122 for (from = str; *from; from++) { 1123 if (*from == '\\') { 1124 from++; 1125 } 1126 *to++ = *from; 1127 } 1128 *to = '\0'; 1129 } 1130 1131 /* 1132 * Convert the MAKEFLAGS string value into a vector of char *, similar 1133 * to argv. 1134 */ 1135 static void 1136 setup_makeflags_argv() 1137 { 1138 char *cp; 1139 char *cp1; 1140 char *cp2; 1141 char *cp3; 1142 char *cp_orig; 1143 Boolean add_hyphen; 1144 int i; 1145 char tmp_char; 1146 1147 mf_argc = 1; 1148 cp = getenv(makeflags->string_mb); 1149 cp_orig = cp; 1150 1151 if (cp) { 1152 /* 1153 * If new MAKEFLAGS format, no need to add hyphen. 1154 * If old MAKEFLAGS format, add hyphen before flags. 1155 */ 1156 1157 if ((strchr(cp, (int) hyphen_char) != NULL) || 1158 (strchr(cp, (int) equal_char) != NULL)) { 1159 1160 /* New MAKEFLAGS format */ 1161 1162 add_hyphen = false; 1163 1164 /* Check if MAKEFLAGS value begins with multiple 1165 * hyphen characters, and remove all duplicates. 1166 * Usually it happens when the next command is 1167 * used: $(MAKE) -$(MAKEFLAGS) 1168 * 1169 * This was a workaround for BugID 5060758, but 1170 * appears to have survived as a fix in make. 1171 */ 1172 while (*cp) { 1173 if (*cp != (int) hyphen_char) { 1174 break; 1175 } 1176 cp++; 1177 if (*cp == (int) hyphen_char) { 1178 /* There are two hyphens. Skip one */ 1179 cp_orig = cp; 1180 cp++; 1181 } 1182 if (!(*cp)) { 1183 /* There are hyphens only. Skip all */ 1184 cp_orig = cp; 1185 break; 1186 } 1187 } 1188 } else { 1189 1190 /* Old MAKEFLAGS format */ 1191 1192 add_hyphen = true; 1193 } 1194 } 1195 1196 /* Find the number of arguments in MAKEFLAGS */ 1197 while (cp && *cp) { 1198 /* Skip white spaces */ 1199 while (cp && *cp && isspace(*cp)) { 1200 cp++; 1201 } 1202 if (cp && *cp) { 1203 /* Increment arg count */ 1204 mf_argc++; 1205 /* Go to next white space */ 1206 while (cp && *cp && !isspace(*cp)) { 1207 if(*cp == (int) backslash_char) { 1208 cp++; 1209 } 1210 cp++; 1211 } 1212 } 1213 } 1214 /* Allocate memory for the new MAKEFLAGS argv */ 1215 mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *)); 1216 mf_argv[0] = (char *)"MAKEFLAGS"; 1217 /* 1218 * Convert the MAKEFLAGS string value into a vector of char *, 1219 * similar to argv. 1220 */ 1221 cp = cp_orig; 1222 for (i = 1; i < mf_argc; i++) { 1223 /* Skip white spaces */ 1224 while (cp && *cp && isspace(*cp)) { 1225 cp++; 1226 } 1227 if (cp && *cp) { 1228 cp_orig = cp; 1229 /* Go to next white space */ 1230 while (cp && *cp && !isspace(*cp)) { 1231 if(*cp == (int) backslash_char) { 1232 cp++; 1233 } 1234 cp++; 1235 } 1236 tmp_char = *cp; 1237 *cp = (int) nul_char; 1238 if (add_hyphen) { 1239 mf_argv[i] = getmem(2 + strlen(cp_orig)); 1240 mf_argv[i][0] = '\0'; 1241 (void) strcat(mf_argv[i], "-"); 1242 // (void) strcat(mf_argv[i], cp_orig); 1243 unquote_str(cp_orig, mf_argv[i]+1); 1244 } else { 1245 mf_argv[i] = getmem(2 + strlen(cp_orig)); 1246 //mf_argv[i] = strdup(cp_orig); 1247 unquote_str(cp_orig, mf_argv[i]); 1248 } 1249 *cp = tmp_char; 1250 } 1251 } 1252 mf_argv[i] = NULL; 1253 } 1254 1255 /* 1256 * parse_command_option(ch) 1257 * 1258 * Parse make command line options. 1259 * 1260 * Return value: 1261 * Indicates if any -f -c or -M were seen 1262 * 1263 * Parameters: 1264 * ch The character to parse 1265 * 1266 * Static variables used: 1267 * dmake_group_specified Set for make -g 1268 * dmake_max_jobs_specified Set for make -j 1269 * dmake_mode_specified Set for make -m 1270 * dmake_add_mode_specified Set for make -x 1271 * dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE= 1272 * dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE= 1273 * dmake_odir_specified Set for make -o 1274 * dmake_rcfile_specified Set for make -c 1275 * env_wins Set for make -e 1276 * ignore_default_mk Set for make -r 1277 * trace_status Set for make -p 1278 * 1279 * Global variables used: 1280 * .make.state path & name set for make -K 1281 * continue_after_error Set for make -k 1282 * debug_level Set for make -d 1283 * do_not_exec_rule Set for make -n 1284 * filter_stderr Set for make -X 1285 * ignore_errors_all Set for make -i 1286 * no_parallel Set for make -R 1287 * quest Set for make -q 1288 * read_trace_level Set for make -D 1289 * report_dependencies Set for make -P 1290 * silent_all Set for make -s 1291 * touch Set for make -t 1292 */ 1293 static int 1294 parse_command_option(register char ch) 1295 { 1296 static int invert_next = 0; 1297 int invert_this = invert_next; 1298 1299 invert_next = 0; 1300 switch (ch) { 1301 case '-': /* Ignore "--" */ 1302 return 0; 1303 case '~': /* Invert next option */ 1304 invert_next = 1; 1305 return 0; 1306 case 'B': /* Obsolete */ 1307 return 0; 1308 case 'b': /* Obsolete */ 1309 return 0; 1310 case 'c': /* Read alternative dmakerc file */ 1311 if (invert_this) { 1312 dmake_rcfile_specified = false; 1313 } else { 1314 dmake_rcfile_specified = true; 1315 } 1316 return 2; 1317 case 'D': /* Show lines read */ 1318 if (invert_this) { 1319 read_trace_level--; 1320 } else { 1321 read_trace_level++; 1322 } 1323 return 0; 1324 case 'd': /* Debug flag */ 1325 if (invert_this) { 1326 debug_level--; 1327 } else { 1328 debug_level++; 1329 } 1330 return 0; 1331 case 'e': /* Environment override flag */ 1332 if (invert_this) { 1333 env_wins = false; 1334 } else { 1335 env_wins = true; 1336 } 1337 return 0; 1338 case 'f': /* Read alternative makefile(s) */ 1339 return 1; 1340 case 'g': /* Use alternative DMake group */ 1341 if (invert_this) { 1342 dmake_group_specified = false; 1343 } else { 1344 dmake_group_specified = true; 1345 } 1346 return 4; 1347 case 'i': /* Ignore errors */ 1348 if (invert_this) { 1349 ignore_errors_all = false; 1350 } else { 1351 ignore_errors_all = true; 1352 } 1353 return 0; 1354 case 'j': /* Use alternative DMake max jobs */ 1355 if (invert_this) { 1356 dmake_max_jobs_specified = false; 1357 } else { 1358 dmake_mode_type = parallel_mode; 1359 no_parallel = false; 1360 dmake_max_jobs_specified = true; 1361 } 1362 return 8; 1363 case 'K': /* Read alternative .make.state */ 1364 return 256; 1365 case 'k': /* Keep making even after errors */ 1366 if (invert_this) { 1367 continue_after_error = false; 1368 } else { 1369 continue_after_error = true; 1370 continue_after_error_ever_seen = true; 1371 } 1372 return 0; 1373 case 'M': /* Read alternative make.machines file */ 1374 if (invert_this) { 1375 pmake_machinesfile_specified = false; 1376 } else { 1377 pmake_machinesfile_specified = true; 1378 dmake_mode_type = parallel_mode; 1379 no_parallel = false; 1380 } 1381 return 16; 1382 case 'm': /* Use alternative DMake build mode */ 1383 if (invert_this) { 1384 dmake_mode_specified = false; 1385 } else { 1386 dmake_mode_specified = true; 1387 } 1388 return 32; 1389 case 'x': /* Use alternative DMake mode */ 1390 if (invert_this) { 1391 dmake_add_mode_specified = false; 1392 } else { 1393 dmake_add_mode_specified = true; 1394 } 1395 return 1024; 1396 case 'N': /* Reverse -n */ 1397 if (invert_this) { 1398 do_not_exec_rule = true; 1399 } else { 1400 do_not_exec_rule = false; 1401 } 1402 return 0; 1403 case 'n': /* Print, not exec commands */ 1404 if (invert_this) { 1405 do_not_exec_rule = false; 1406 } else { 1407 do_not_exec_rule = true; 1408 } 1409 return 0; 1410 case 'O': /* Integrate with maketool, obsolete */ 1411 return 0; 1412 case 'o': /* Use alternative dmake output dir */ 1413 if (invert_this) { 1414 dmake_odir_specified = false; 1415 } else { 1416 dmake_odir_specified = true; 1417 } 1418 return 512; 1419 case 'P': /* Print for selected targets */ 1420 if (invert_this) { 1421 report_dependencies_level--; 1422 } else { 1423 report_dependencies_level++; 1424 } 1425 return 0; 1426 case 'p': /* Print description */ 1427 if (invert_this) { 1428 trace_status = false; 1429 do_not_exec_rule = false; 1430 } else { 1431 trace_status = true; 1432 do_not_exec_rule = true; 1433 } 1434 return 0; 1435 case 'q': /* Question flag */ 1436 if (invert_this) { 1437 quest = false; 1438 } else { 1439 quest = true; 1440 } 1441 return 0; 1442 case 'R': /* Don't run in parallel */ 1443 if (invert_this) { 1444 pmake_cap_r_specified = false; 1445 no_parallel = false; 1446 } else { 1447 pmake_cap_r_specified = true; 1448 dmake_mode_type = serial_mode; 1449 no_parallel = true; 1450 } 1451 return 0; 1452 case 'r': /* Turn off internal rules */ 1453 if (invert_this) { 1454 ignore_default_mk = false; 1455 } else { 1456 ignore_default_mk = true; 1457 } 1458 return 0; 1459 case 'S': /* Reverse -k */ 1460 if (invert_this) { 1461 continue_after_error = true; 1462 } else { 1463 continue_after_error = false; 1464 stop_after_error_ever_seen = true; 1465 } 1466 return 0; 1467 case 's': /* Silent flag */ 1468 if (invert_this) { 1469 silent_all = false; 1470 } else { 1471 silent_all = true; 1472 } 1473 return 0; 1474 case 'T': /* Print target list */ 1475 if (invert_this) { 1476 list_all_targets = false; 1477 do_not_exec_rule = false; 1478 } else { 1479 list_all_targets = true; 1480 do_not_exec_rule = true; 1481 } 1482 return 0; 1483 case 't': /* Touch flag */ 1484 if (invert_this) { 1485 touch = false; 1486 } else { 1487 touch = true; 1488 } 1489 return 0; 1490 case 'u': /* Unconditional flag */ 1491 if (invert_this) { 1492 build_unconditional = false; 1493 } else { 1494 build_unconditional = true; 1495 } 1496 return 0; 1497 case 'V': /* SVR4 mode */ 1498 svr4 = true; 1499 return 0; 1500 case 'v': /* Version flag */ 1501 if (invert_this) { 1502 } else { 1503 fprintf(stdout, "%s: %s\n", getprogname(), verstring); 1504 exit_status = 0; 1505 exit(0); 1506 } 1507 return 0; 1508 case 'w': /* Unconditional flag */ 1509 if (invert_this) { 1510 report_cwd = false; 1511 } else { 1512 report_cwd = true; 1513 } 1514 return 0; 1515 #if 0 1516 case 'X': /* Filter stdout */ 1517 if (invert_this) { 1518 filter_stderr = false; 1519 } else { 1520 filter_stderr = true; 1521 } 1522 return 0; 1523 #endif 1524 default: 1525 break; 1526 } 1527 return 0; 1528 } 1529 1530 /* 1531 * setup_for_projectdir() 1532 * 1533 * Read the PROJECTDIR variable, if defined, and set the sccs path 1534 * 1535 * Parameters: 1536 * 1537 * Global variables used: 1538 * sccs_dir_path Set to point to SCCS dir to use 1539 */ 1540 static void 1541 setup_for_projectdir(void) 1542 { 1543 static char path[MAXPATHLEN]; 1544 char cwdpath[MAXPATHLEN]; 1545 uid_t uid; 1546 int done=0; 1547 1548 /* Check if we should use PROJECTDIR when reading the SCCS dir. */ 1549 sccs_dir_path = getenv("PROJECTDIR"); 1550 if ((sccs_dir_path != NULL) && 1551 (sccs_dir_path[0] != (int) slash_char)) { 1552 struct passwd *pwent; 1553 1554 { 1555 uid = getuid(); 1556 pwent = getpwuid(uid); 1557 if (pwent == NULL) { 1558 fatal(gettext("Bogus USERID ")); 1559 } 1560 if ((pwent = getpwnam(sccs_dir_path)) == NULL) { 1561 /*empty block : it'll go & check cwd */ 1562 } 1563 else { 1564 (void) sprintf(path, "%s/src", pwent->pw_dir); 1565 if (access(path, F_OK) == 0) { 1566 sccs_dir_path = path; 1567 done = 1; 1568 } else { 1569 (void) sprintf(path, "%s/source", pwent->pw_dir); 1570 if (access(path, F_OK) == 0) { 1571 sccs_dir_path = path; 1572 done = 1; 1573 } 1574 } 1575 } 1576 if (!done) { 1577 if (getcwd(cwdpath, MAXPATHLEN - 1 )) { 1578 1579 (void) sprintf(path, "%s/%s", cwdpath,sccs_dir_path); 1580 if (access(path, F_OK) == 0) { 1581 sccs_dir_path = path; 1582 done = 1; 1583 } else { 1584 fatal(gettext("Bogus PROJECTDIR '%s'"), sccs_dir_path); 1585 } 1586 } 1587 } 1588 } 1589 } 1590 } 1591 1592 char * 1593 make_install_prefix(void) 1594 { 1595 int ret; 1596 char origin[PATH_MAX]; 1597 char *dir; 1598 1599 if ((ret = readlink("/proc/self/path/a.out", origin, 1600 PATH_MAX - 1)) < 0) 1601 fatal("failed to read origin from /proc\n"); 1602 1603 1604 origin[ret] = '\0'; 1605 return strdup(dirname(origin)); 1606 } 1607 1608 static char * 1609 add_to_env(const char *var, const char *value, const char *fallback) 1610 { 1611 const char *oldpath; 1612 char *newpath; 1613 1614 oldpath = getenv(var); 1615 if (oldpath == NULL) { 1616 if (value != NULL) { 1617 asprintf(&newpath, "%s=%s", 1618 var, value); 1619 } else { 1620 asprintf(&newpath, "%s=%s", 1621 var, fallback); 1622 } 1623 } else { 1624 if (value != NULL) { 1625 asprintf(&newpath, "%s=%s:%s", 1626 var, oldpath, value); 1627 } else { 1628 asprintf(&newpath, "%s=%s:%s", 1629 var, oldpath, fallback); 1630 } 1631 } 1632 1633 return (newpath); 1634 } 1635 1636 /* 1637 * set_sgs_support() 1638 * 1639 * Add the libmakestate.so.1 lib to the env var SGS_SUPPORT 1640 * if it's not already in there. 1641 * The SGS_SUPPORT env var and libmakestate.so.1 is used by 1642 * the linker ld to report .make.state info back to make. 1643 * 1644 * In the new world we always will set the 32-bit and 64-bit versions of this 1645 * variable explicitly so that we can take into account the correct isa and our 1646 * prefix. So say that the prefix was /opt/local. Then we would want to search 1647 * /opt/local/lib/libmakestate.so.1:libmakestate.so.1. We still want to search 1648 * the original location just as a safety measure. 1649 */ 1650 static void 1651 set_sgs_support() 1652 { 1653 int len; 1654 char *newpath, *newpath64; 1655 char *lib32, *lib64; 1656 static char *prev_path, *prev_path64; 1657 char *origin = make_install_prefix(); 1658 struct stat st; 1659 1660 asprintf(&lib32, "%s/%s/%s", origin, "../lib", 1661 LD_SUPPORT_MAKE_LIB); 1662 1663 if (stat(lib32, &st) != 0) { 1664 free(lib32); 1665 // Try the tools path 1666 asprintf(&lib32, "%s/%s/%s/%s", origin, "../../lib/", 1667 LD_SUPPORT_MAKE_ARCH, LD_SUPPORT_MAKE_LIB); 1668 1669 if (stat(lib32, &st) != 0) { 1670 free(lib32); 1671 lib32 = NULL; 1672 } 1673 } 1674 1675 asprintf(&lib64, "%s/%s/64/%s", origin, "../lib", 1676 LD_SUPPORT_MAKE_LIB); 1677 1678 if (stat(lib64, &st) != 0) { 1679 free(lib64); 1680 // Try the tools path 1681 asprintf(&lib64, "%s/%s/%s/64/%s", origin, "../../lib/", 1682 LD_SUPPORT_MAKE_ARCH, LD_SUPPORT_MAKE_LIB); 1683 1684 if (stat(lib64, &st) != 0) { 1685 free(lib64); 1686 lib64 = NULL; 1687 } 1688 } 1689 1690 newpath = add_to_env(LD_SUPPORT_ENV_VAR_32, lib32, LD_SUPPORT_MAKE_LIB); 1691 newpath64 = add_to_env(LD_SUPPORT_ENV_VAR_64, lib64, LD_SUPPORT_MAKE_LIB); 1692 1693 putenv(newpath); 1694 if (prev_path) { 1695 free(prev_path); 1696 } 1697 prev_path = newpath; 1698 1699 putenv(newpath64); 1700 if (prev_path64) { 1701 free(prev_path64); 1702 } 1703 prev_path64 = newpath64; 1704 free(lib32); 1705 free(lib64); 1706 free(origin); 1707 } 1708 1709 /* 1710 * read_files_and_state(argc, argv) 1711 * 1712 * Read the makefiles we care about and the environment 1713 * Also read the = style command line options 1714 * 1715 * Parameters: 1716 * argc You know what this is 1717 * argv You know what this is 1718 * 1719 * Static variables used: 1720 * env_wins make -e, determines if env vars are RO 1721 * ignore_default_mk make -r, determines if make.rules is read 1722 * not_auto_depen dwight 1723 * 1724 * Global variables used: 1725 * default_target_to_build Set to first proper target from file 1726 * do_not_exec_rule Set to false when makfile is made 1727 * dot The Name ".", used to read current dir 1728 * empty_name The Name "", use as macro value 1729 * keep_state Set if KEEP_STATE is in environment 1730 * make_state The Name ".make.state", used to read file 1731 * makefile_type Set to type of file being read 1732 * makeflags The Name "MAKEFLAGS", used to set macro value 1733 * not_auto dwight 1734 * read_trace_level Checked to se if the reader should trace 1735 * report_dependencies If -P is on we do not read .make.state 1736 * trace_reader Set if reader should trace 1737 * virtual_root The Name "VIRTUAL_ROOT", used to check value 1738 */ 1739 static void 1740 read_files_and_state(int argc, char **argv) 1741 { 1742 wchar_t buffer[1000]; 1743 wchar_t buffer_posix[1000]; 1744 register char ch; 1745 register char *cp; 1746 Property def_make_macro = NULL; 1747 Name def_make_name; 1748 Name default_makefile; 1749 String_rec dest; 1750 wchar_t destbuffer[STRING_BUFFER_LENGTH]; 1751 register int i; 1752 register int j; 1753 Name keep_state_name; 1754 int length; 1755 Name Makefile; 1756 register Property macro; 1757 struct stat make_state_stat; 1758 Name makefile_name; 1759 register int makefile_next = 0; 1760 register Boolean makefile_read = false; 1761 String_rec makeflags_string; 1762 String_rec makeflags_string_posix; 1763 String_rec * makeflags_string_current; 1764 Name makeflags_value_saved; 1765 register Name name; 1766 Name new_make_value; 1767 Boolean save_do_not_exec_rule; 1768 Name sdotMakefile; 1769 Name sdotmakefile_name; 1770 static wchar_t state_file_str; 1771 static char state_file_str_mb[MAXPATHLEN]; 1772 static struct _Name state_filename; 1773 Boolean temp; 1774 char tmp_char; 1775 wchar_t *tmp_wcs_buffer; 1776 register Name value; 1777 ASCII_Dyn_Array makeflags_and_macro; 1778 Boolean is_xpg4; 1779 1780 /* 1781 * Remember current mode. It may be changed after reading makefile 1782 * and we will have to correct MAKEFLAGS variable. 1783 */ 1784 is_xpg4 = posix; 1785 1786 MBSTOWCS(wcs_buffer, "KEEP_STATE"); 1787 keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH); 1788 MBSTOWCS(wcs_buffer, "Makefile"); 1789 Makefile = GETNAME(wcs_buffer, FIND_LENGTH); 1790 MBSTOWCS(wcs_buffer, "makefile"); 1791 makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); 1792 MBSTOWCS(wcs_buffer, "s.makefile"); 1793 sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH); 1794 MBSTOWCS(wcs_buffer, "s.Makefile"); 1795 sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH); 1796 1797 /* 1798 * initialize global dependency entry for .NOT_AUTO 1799 */ 1800 not_auto_depen->next = NULL; 1801 not_auto_depen->name = not_auto; 1802 not_auto_depen->automatic = not_auto_depen->stale = false; 1803 1804 /* 1805 * Read internal definitions and rules. 1806 */ 1807 if (read_trace_level > 1) { 1808 trace_reader = true; 1809 } 1810 if (!ignore_default_mk) { 1811 if (svr4) { 1812 MBSTOWCS(wcs_buffer, "svr4.make.rules"); 1813 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 1814 } else { 1815 MBSTOWCS(wcs_buffer, "make.rules"); 1816 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 1817 } 1818 default_makefile->stat.is_file = true; 1819 1820 (void) read_makefile(default_makefile, 1821 true, 1822 false, 1823 true); 1824 } 1825 1826 /* 1827 * If the user did not redefine the MAKE macro in the 1828 * default makefile (make.rules), then we'd like to 1829 * change the macro value of MAKE to be some form 1830 * of argv[0] for recursive MAKE builds. 1831 */ 1832 MBSTOWCS(wcs_buffer, "MAKE"); 1833 def_make_name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 1834 def_make_macro = get_prop(def_make_name->prop, macro_prop); 1835 if ((def_make_macro != NULL) && 1836 (IS_EQUAL(def_make_macro->body.macro.value->string_mb, 1837 "make"))) { 1838 MBSTOWCS(wcs_buffer, argv_zero_string); 1839 new_make_value = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 1840 (void) SETVAR(def_make_name, 1841 new_make_value, 1842 false); 1843 } 1844 1845 default_target_to_build = NULL; 1846 trace_reader = false; 1847 1848 /* 1849 * Read environment args. Let file args which follow override unless 1850 * -e option seen. If -e option is not mentioned. 1851 */ 1852 read_environment(env_wins); 1853 if (getvar(virtual_root)->hash.length == 0) { 1854 maybe_append_prop(virtual_root, macro_prop) 1855 ->body.macro.exported = true; 1856 MBSTOWCS(wcs_buffer, "/"); 1857 (void) SETVAR(virtual_root, 1858 GETNAME(wcs_buffer, FIND_LENGTH), 1859 false); 1860 } 1861 1862 /* 1863 * We now scan mf_argv and argv to see if we need to set 1864 * any of the DMake-added options/variables in MAKEFLAGS. 1865 */ 1866 1867 makeflags_and_macro.start = 0; 1868 makeflags_and_macro.size = 0; 1869 enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro); 1870 enter_argv_values(argc, argv, &makeflags_and_macro); 1871 1872 /* 1873 * Set MFLAGS and MAKEFLAGS 1874 * 1875 * Before reading makefile we do not know exactly which mode 1876 * (posix or not) is used. So prepare two MAKEFLAGS strings 1877 * for both posix and solaris modes because they are different. 1878 */ 1879 INIT_STRING_FROM_STACK(makeflags_string, buffer); 1880 INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix); 1881 append_char((int) hyphen_char, &makeflags_string); 1882 append_char((int) hyphen_char, &makeflags_string_posix); 1883 1884 switch (read_trace_level) { 1885 case 2: 1886 append_char('D', &makeflags_string); 1887 append_char('D', &makeflags_string_posix); 1888 case 1: 1889 append_char('D', &makeflags_string); 1890 append_char('D', &makeflags_string_posix); 1891 } 1892 switch (debug_level) { 1893 case 2: 1894 append_char('d', &makeflags_string); 1895 append_char('d', &makeflags_string_posix); 1896 case 1: 1897 append_char('d', &makeflags_string); 1898 append_char('d', &makeflags_string_posix); 1899 } 1900 if (env_wins) { 1901 append_char('e', &makeflags_string); 1902 append_char('e', &makeflags_string_posix); 1903 } 1904 if (ignore_errors_all) { 1905 append_char('i', &makeflags_string); 1906 append_char('i', &makeflags_string_posix); 1907 } 1908 if (continue_after_error) { 1909 if (stop_after_error_ever_seen) { 1910 append_char('S', &makeflags_string_posix); 1911 append_char((int) space_char, &makeflags_string_posix); 1912 append_char((int) hyphen_char, &makeflags_string_posix); 1913 } 1914 append_char('k', &makeflags_string); 1915 append_char('k', &makeflags_string_posix); 1916 } else { 1917 if (stop_after_error_ever_seen 1918 && continue_after_error_ever_seen) { 1919 append_char('k', &makeflags_string_posix); 1920 append_char((int) space_char, &makeflags_string_posix); 1921 append_char((int) hyphen_char, &makeflags_string_posix); 1922 append_char('S', &makeflags_string_posix); 1923 } 1924 } 1925 if (do_not_exec_rule) { 1926 append_char('n', &makeflags_string); 1927 append_char('n', &makeflags_string_posix); 1928 } 1929 switch (report_dependencies_level) { 1930 case 4: 1931 append_char('P', &makeflags_string); 1932 append_char('P', &makeflags_string_posix); 1933 case 3: 1934 append_char('P', &makeflags_string); 1935 append_char('P', &makeflags_string_posix); 1936 case 2: 1937 append_char('P', &makeflags_string); 1938 append_char('P', &makeflags_string_posix); 1939 case 1: 1940 append_char('P', &makeflags_string); 1941 append_char('P', &makeflags_string_posix); 1942 } 1943 if (trace_status) { 1944 append_char('p', &makeflags_string); 1945 append_char('p', &makeflags_string_posix); 1946 } 1947 if (quest) { 1948 append_char('q', &makeflags_string); 1949 append_char('q', &makeflags_string_posix); 1950 } 1951 if (silent_all) { 1952 append_char('s', &makeflags_string); 1953 append_char('s', &makeflags_string_posix); 1954 } 1955 if (touch) { 1956 append_char('t', &makeflags_string); 1957 append_char('t', &makeflags_string_posix); 1958 } 1959 if (build_unconditional) { 1960 append_char('u', &makeflags_string); 1961 append_char('u', &makeflags_string_posix); 1962 } 1963 if (report_cwd) { 1964 append_char('w', &makeflags_string); 1965 append_char('w', &makeflags_string_posix); 1966 } 1967 /* -c dmake_rcfile */ 1968 if (dmake_rcfile_specified) { 1969 MBSTOWCS(wcs_buffer, "DMAKE_RCFILE"); 1970 dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH); 1971 append_makeflags_string(dmake_rcfile, &makeflags_string); 1972 append_makeflags_string(dmake_rcfile, &makeflags_string_posix); 1973 } 1974 /* -g dmake_group */ 1975 if (dmake_group_specified) { 1976 MBSTOWCS(wcs_buffer, "DMAKE_GROUP"); 1977 dmake_group = GETNAME(wcs_buffer, FIND_LENGTH); 1978 append_makeflags_string(dmake_group, &makeflags_string); 1979 append_makeflags_string(dmake_group, &makeflags_string_posix); 1980 } 1981 /* -j dmake_max_jobs */ 1982 if (dmake_max_jobs_specified) { 1983 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS"); 1984 dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH); 1985 append_makeflags_string(dmake_max_jobs, &makeflags_string); 1986 append_makeflags_string(dmake_max_jobs, &makeflags_string_posix); 1987 } 1988 /* -m dmake_mode */ 1989 if (dmake_mode_specified) { 1990 MBSTOWCS(wcs_buffer, "DMAKE_MODE"); 1991 dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH); 1992 append_makeflags_string(dmake_mode, &makeflags_string); 1993 append_makeflags_string(dmake_mode, &makeflags_string_posix); 1994 } 1995 /* -x dmake_compat_mode */ 1996 // if (dmake_compat_mode_specified) { 1997 // MBSTOWCS(wcs_buffer, "SUN_MAKE_COMPAT_MODE"); 1998 // dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH); 1999 // append_makeflags_string(dmake_compat_mode, &makeflags_string); 2000 // append_makeflags_string(dmake_compat_mode, &makeflags_string_posix); 2001 // } 2002 /* -x dmake_output_mode */ 2003 if (dmake_output_mode_specified) { 2004 MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE"); 2005 dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2006 append_makeflags_string(dmake_output_mode, &makeflags_string); 2007 append_makeflags_string(dmake_output_mode, &makeflags_string_posix); 2008 } 2009 /* -o dmake_odir */ 2010 if (dmake_odir_specified) { 2011 MBSTOWCS(wcs_buffer, "DMAKE_ODIR"); 2012 dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH); 2013 append_makeflags_string(dmake_odir, &makeflags_string); 2014 append_makeflags_string(dmake_odir, &makeflags_string_posix); 2015 } 2016 /* -M pmake_machinesfile */ 2017 if (pmake_machinesfile_specified) { 2018 MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE"); 2019 pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH); 2020 append_makeflags_string(pmake_machinesfile, &makeflags_string); 2021 append_makeflags_string(pmake_machinesfile, &makeflags_string_posix); 2022 } 2023 /* -R */ 2024 if (pmake_cap_r_specified) { 2025 append_char((int) space_char, &makeflags_string); 2026 append_char((int) hyphen_char, &makeflags_string); 2027 append_char('R', &makeflags_string); 2028 append_char((int) space_char, &makeflags_string_posix); 2029 append_char((int) hyphen_char, &makeflags_string_posix); 2030 append_char('R', &makeflags_string_posix); 2031 } 2032 2033 /* 2034 * Make sure MAKEFLAGS is exported 2035 */ 2036 maybe_append_prop(makeflags, macro_prop)-> 2037 body.macro.exported = true; 2038 2039 if (makeflags_string.buffer.start[1] != (int) nul_char) { 2040 if (makeflags_string.buffer.start[1] != (int) space_char) { 2041 MBSTOWCS(wcs_buffer, "MFLAGS"); 2042 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2043 GETNAME(makeflags_string.buffer.start, 2044 FIND_LENGTH), 2045 false); 2046 } else { 2047 MBSTOWCS(wcs_buffer, "MFLAGS"); 2048 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2049 GETNAME(makeflags_string.buffer.start + 2, 2050 FIND_LENGTH), 2051 false); 2052 } 2053 } 2054 2055 /* 2056 * Add command line macro to POSIX makeflags_string 2057 */ 2058 if (makeflags_and_macro.start) { 2059 tmp_char = (char) space_char; 2060 cp = makeflags_and_macro.start; 2061 do { 2062 append_char(tmp_char, &makeflags_string_posix); 2063 } while ( tmp_char = *cp++ ); 2064 retmem_mb(makeflags_and_macro.start); 2065 } 2066 2067 /* 2068 * Now set the value of MAKEFLAGS macro in accordance 2069 * with current mode. 2070 */ 2071 macro = maybe_append_prop(makeflags, macro_prop); 2072 temp = (Boolean) macro->body.macro.read_only; 2073 macro->body.macro.read_only = false; 2074 if(posix || gnu_style) { 2075 makeflags_string_current = &makeflags_string_posix; 2076 } else { 2077 makeflags_string_current = &makeflags_string; 2078 } 2079 if (makeflags_string_current->buffer.start[1] == (int) nul_char) { 2080 makeflags_value_saved = 2081 GETNAME( makeflags_string_current->buffer.start + 1 2082 , FIND_LENGTH 2083 ); 2084 } else { 2085 if (makeflags_string_current->buffer.start[1] != (int) space_char) { 2086 makeflags_value_saved = 2087 GETNAME( makeflags_string_current->buffer.start 2088 , FIND_LENGTH 2089 ); 2090 } else { 2091 makeflags_value_saved = 2092 GETNAME( makeflags_string_current->buffer.start + 2 2093 , FIND_LENGTH 2094 ); 2095 } 2096 } 2097 (void) SETVAR( makeflags 2098 , makeflags_value_saved 2099 , false 2100 ); 2101 macro->body.macro.read_only = temp; 2102 2103 /* 2104 * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args. 2105 */ 2106 save_do_not_exec_rule = do_not_exec_rule; 2107 do_not_exec_rule = false; 2108 if (read_trace_level > 0) { 2109 trace_reader = true; 2110 } 2111 2112 for (i = 1; i < argc; i++) { 2113 if (argv[i] && 2114 (argv[i][0] == (int) hyphen_char) && 2115 (argv[i][1] == 'f') && 2116 (argv[i][2] == (int) nul_char)) { 2117 argv[i] = NULL; /* Remove -f */ 2118 if (i >= argc - 1) { 2119 fatal(gettext("No filename argument after -f flag")); 2120 } 2121 MBSTOWCS(wcs_buffer, argv[++i]); 2122 primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2123 (void) read_makefile(primary_makefile, true, true, true); 2124 argv[i] = NULL; /* Remove filename */ 2125 makefile_read = true; 2126 } else if (argv[i] && 2127 (argv[i][0] == (int) hyphen_char) && 2128 (argv[i][1] == 'c' || 2129 argv[i][1] == 'g' || 2130 argv[i][1] == 'j' || 2131 argv[i][1] == 'K' || 2132 argv[i][1] == 'M' || 2133 argv[i][1] == 'm' || 2134 argv[i][1] == 'O' || 2135 argv[i][1] == 'o') && 2136 (argv[i][2] == (int) nul_char)) { 2137 argv[i] = NULL; 2138 argv[++i] = NULL; 2139 } 2140 } 2141 2142 /* 2143 * If no command line "-f" args then look for "makefile", and then for 2144 * "Makefile" if "makefile" isn't found. 2145 */ 2146 if (!makefile_read) { 2147 (void) read_dir(dot, 2148 (wchar_t *) NULL, 2149 (Property) NULL, 2150 (wchar_t *) NULL); 2151 if (!posix) { 2152 if (makefile_name->stat.is_file) { 2153 if (Makefile->stat.is_file) { 2154 warning(gettext("Both `makefile' and `Makefile' exist")); 2155 } 2156 primary_makefile = makefile_name; 2157 makefile_read = read_makefile(makefile_name, 2158 false, 2159 false, 2160 true); 2161 } 2162 if (!makefile_read && 2163 Makefile->stat.is_file) { 2164 primary_makefile = Makefile; 2165 makefile_read = read_makefile(Makefile, 2166 false, 2167 false, 2168 true); 2169 } 2170 } else { 2171 2172 enum sccs_stat save_m_has_sccs = NO_SCCS; 2173 enum sccs_stat save_M_has_sccs = NO_SCCS; 2174 2175 if (makefile_name->stat.is_file) { 2176 if (Makefile->stat.is_file) { 2177 warning(gettext("Both `makefile' and `Makefile' exist")); 2178 } 2179 } 2180 if (makefile_name->stat.is_file) { 2181 if (makefile_name->stat.has_sccs == NO_SCCS) { 2182 primary_makefile = makefile_name; 2183 makefile_read = read_makefile(makefile_name, 2184 false, 2185 false, 2186 true); 2187 } else { 2188 save_m_has_sccs = makefile_name->stat.has_sccs; 2189 makefile_name->stat.has_sccs = NO_SCCS; 2190 primary_makefile = makefile_name; 2191 makefile_read = read_makefile(makefile_name, 2192 false, 2193 false, 2194 true); 2195 } 2196 } 2197 if (!makefile_read && 2198 Makefile->stat.is_file) { 2199 if (Makefile->stat.has_sccs == NO_SCCS) { 2200 primary_makefile = Makefile; 2201 makefile_read = read_makefile(Makefile, 2202 false, 2203 false, 2204 true); 2205 } else { 2206 save_M_has_sccs = Makefile->stat.has_sccs; 2207 Makefile->stat.has_sccs = NO_SCCS; 2208 primary_makefile = Makefile; 2209 makefile_read = read_makefile(Makefile, 2210 false, 2211 false, 2212 true); 2213 } 2214 } 2215 if (!makefile_read && 2216 makefile_name->stat.is_file) { 2217 makefile_name->stat.has_sccs = save_m_has_sccs; 2218 primary_makefile = makefile_name; 2219 makefile_read = read_makefile(makefile_name, 2220 false, 2221 false, 2222 true); 2223 } 2224 if (!makefile_read && 2225 Makefile->stat.is_file) { 2226 Makefile->stat.has_sccs = save_M_has_sccs; 2227 primary_makefile = Makefile; 2228 makefile_read = read_makefile(Makefile, 2229 false, 2230 false, 2231 true); 2232 } 2233 } 2234 } 2235 do_not_exec_rule = save_do_not_exec_rule; 2236 allrules_read = makefile_read; 2237 trace_reader = false; 2238 2239 /* 2240 * Now get current value of MAKEFLAGS and compare it with 2241 * the saved value we set before reading makefile. 2242 * If they are different then MAKEFLAGS is subsequently set by 2243 * makefile, just leave it there. Otherwise, if make mode 2244 * is changed by using .POSIX target in makefile we need 2245 * to correct MAKEFLAGS value. 2246 */ 2247 Name mf_val = getvar(makeflags); 2248 if( (posix != is_xpg4) 2249 && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb))) 2250 { 2251 if (makeflags_string_posix.buffer.start[1] == (int) nul_char) { 2252 (void) SETVAR(makeflags, 2253 GETNAME(makeflags_string_posix.buffer.start + 1, 2254 FIND_LENGTH), 2255 false); 2256 } else { 2257 if (makeflags_string_posix.buffer.start[1] != (int) space_char) { 2258 (void) SETVAR(makeflags, 2259 GETNAME(makeflags_string_posix.buffer.start, 2260 FIND_LENGTH), 2261 false); 2262 } else { 2263 (void) SETVAR(makeflags, 2264 GETNAME(makeflags_string_posix.buffer.start + 2, 2265 FIND_LENGTH), 2266 false); 2267 } 2268 } 2269 } 2270 2271 if (makeflags_string.free_after_use) { 2272 retmem(makeflags_string.buffer.start); 2273 } 2274 if (makeflags_string_posix.free_after_use) { 2275 retmem(makeflags_string_posix.buffer.start); 2276 } 2277 makeflags_string.buffer.start = NULL; 2278 makeflags_string_posix.buffer.start = NULL; 2279 2280 if (posix) { 2281 /* 2282 * If the user did not redefine the ARFLAGS macro in the 2283 * default makefile (make.rules), then we'd like to 2284 * change the macro value of ARFLAGS to be in accordance 2285 * with "POSIX" requirements. 2286 */ 2287 MBSTOWCS(wcs_buffer, "ARFLAGS"); 2288 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2289 macro = get_prop(name->prop, macro_prop); 2290 if ((macro != NULL) && /* Maybe (macro == NULL) || ? */ 2291 (IS_EQUAL(macro->body.macro.value->string_mb, 2292 "rv"))) { 2293 MBSTOWCS(wcs_buffer, "-rv"); 2294 value = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2295 (void) SETVAR(name, 2296 value, 2297 false); 2298 } 2299 } 2300 2301 if (!posix && !svr4) { 2302 set_sgs_support(); 2303 } 2304 2305 2306 /* 2307 * Make sure KEEP_STATE is in the environment if KEEP_STATE is on. 2308 */ 2309 macro = get_prop(keep_state_name->prop, macro_prop); 2310 if ((macro != NULL) && 2311 macro->body.macro.exported) { 2312 keep_state = true; 2313 } 2314 if (keep_state) { 2315 if (macro == NULL) { 2316 macro = maybe_append_prop(keep_state_name, 2317 macro_prop); 2318 } 2319 macro->body.macro.exported = true; 2320 (void) SETVAR(keep_state_name, 2321 empty_name, 2322 false); 2323 2324 /* 2325 * Read state file 2326 */ 2327 2328 /* Before we read state, let's make sure we have 2329 ** right state file. 2330 */ 2331 /* just in case macro references are used in make_state file 2332 ** name, we better expand them at this stage using expand_value. 2333 */ 2334 INIT_STRING_FROM_STACK(dest, destbuffer); 2335 expand_value(make_state, &dest, false); 2336 2337 make_state = GETNAME(dest.buffer.start, FIND_LENGTH); 2338 2339 if(!stat(make_state->string_mb, &make_state_stat)) { 2340 if(!(make_state_stat.st_mode & S_IFREG) ) { 2341 /* copy the make_state structure to the other 2342 ** and then let make_state point to the new 2343 ** one. 2344 */ 2345 memcpy(&state_filename, make_state,sizeof(state_filename)); 2346 state_filename.string_mb = state_file_str_mb; 2347 /* Just a kludge to avoid two slashes back to back */ 2348 if((make_state->hash.length == 1)&& 2349 (make_state->string_mb[0] == '/')) { 2350 make_state->hash.length = 0; 2351 make_state->string_mb[0] = '\0'; 2352 } 2353 sprintf(state_file_str_mb,"%s%s", 2354 make_state->string_mb,"/.make.state"); 2355 make_state = &state_filename; 2356 /* adjust the length to reflect the appended string */ 2357 make_state->hash.length += 12; 2358 } 2359 } else { /* the file doesn't exist or no permission */ 2360 char tmp_path[MAXPATHLEN]; 2361 char *slashp; 2362 2363 if (slashp = strrchr(make_state->string_mb, '/')) { 2364 strncpy(tmp_path, make_state->string_mb, 2365 (slashp - make_state->string_mb)); 2366 tmp_path[slashp - make_state->string_mb]=0; 2367 if(strlen(tmp_path)) { 2368 if(stat(tmp_path, &make_state_stat)) { 2369 warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path); 2370 } 2371 if (access(tmp_path, F_OK) != 0) { 2372 warning(gettext("can't access dir %s"),tmp_path); 2373 } 2374 } 2375 } 2376 } 2377 if (report_dependencies_level != 1) { 2378 Makefile_type makefile_type_temp = makefile_type; 2379 makefile_type = reading_statefile; 2380 if (read_trace_level > 1) { 2381 trace_reader = true; 2382 } 2383 (void) read_simple_file(make_state, 2384 false, 2385 false, 2386 false, 2387 false, 2388 false, 2389 true); 2390 trace_reader = false; 2391 makefile_type = makefile_type_temp; 2392 } 2393 } 2394 } 2395 2396 /* 2397 * Scan the argv for options and "=" type args and make them readonly. 2398 */ 2399 static void 2400 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro) 2401 { 2402 register char *cp; 2403 register int i; 2404 int length; 2405 register Name name; 2406 int opt_separator = argc; 2407 char tmp_char; 2408 wchar_t *tmp_wcs_buffer; 2409 register Name value; 2410 Boolean append = false; 2411 Property macro; 2412 struct stat statbuf; 2413 2414 2415 /* Read argv options and "=" type args and make them readonly. */ 2416 makefile_type = reading_nothing; 2417 for (i = 1; i < argc; ++i) { 2418 append = false; 2419 if (argv[i] == NULL) { 2420 continue; 2421 } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) || 2422 ((argv[i][0] == (int) ' ') && 2423 (argv[i][1] == (int) '-') && 2424 (argv[i][2] == (int) ' ') && 2425 (argv[i][3] == (int) '-'))) { 2426 argv[i] = NULL; 2427 opt_separator = i; 2428 continue; 2429 } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) { 2430 switch (parse_command_option(argv[i][1])) { 2431 case 1: /* -f seen */ 2432 ++i; 2433 continue; 2434 case 2: /* -c seen */ 2435 if (argv[i+1] == NULL) { 2436 fatal(gettext("No dmake rcfile argument after -c flag")); 2437 } 2438 MBSTOWCS(wcs_buffer, "DMAKE_RCFILE"); 2439 name = GETNAME(wcs_buffer, FIND_LENGTH); 2440 break; 2441 case 4: /* -g seen */ 2442 if (argv[i+1] == NULL) { 2443 fatal(gettext("No dmake group argument after -g flag")); 2444 } 2445 MBSTOWCS(wcs_buffer, "DMAKE_GROUP"); 2446 name = GETNAME(wcs_buffer, FIND_LENGTH); 2447 break; 2448 case 8: /* -j seen */ 2449 if (argv[i+1] == NULL) { 2450 fatal(gettext("No dmake max jobs argument after -j flag")); 2451 } 2452 MBSTOWCS(wcs_buffer, "DMAKE_MAX_JOBS"); 2453 name = GETNAME(wcs_buffer, FIND_LENGTH); 2454 break; 2455 case 16: /* -M seen */ 2456 if (argv[i+1] == NULL) { 2457 fatal(gettext("No pmake machinesfile argument after -M flag")); 2458 } 2459 MBSTOWCS(wcs_buffer, "PMAKE_MACHINESFILE"); 2460 name = GETNAME(wcs_buffer, FIND_LENGTH); 2461 break; 2462 case 32: /* -m seen */ 2463 if (argv[i+1] == NULL) { 2464 fatal(gettext("No dmake mode argument after -m flag")); 2465 } 2466 MBSTOWCS(wcs_buffer, "DMAKE_MODE"); 2467 name = GETNAME(wcs_buffer, FIND_LENGTH); 2468 break; 2469 case 256: /* -K seen */ 2470 if (argv[i+1] == NULL) { 2471 fatal(gettext("No makestate filename argument after -K flag")); 2472 } 2473 MBSTOWCS(wcs_buffer, argv[i+1]); 2474 make_state = GETNAME(wcs_buffer, FIND_LENGTH); 2475 keep_state = true; 2476 argv[i] = NULL; 2477 argv[i+1] = NULL; 2478 continue; 2479 case 512: /* -o seen */ 2480 if (argv[i+1] == NULL) { 2481 fatal(gettext("No dmake output dir argument after -o flag")); 2482 } 2483 MBSTOWCS(wcs_buffer, "DMAKE_ODIR"); 2484 name = GETNAME(wcs_buffer, FIND_LENGTH); 2485 break; 2486 case 1024: /* -x seen */ 2487 if (argv[i+1] == NULL) { 2488 fatal(gettext("No argument after -x flag")); 2489 } 2490 length = strlen( "SUN_MAKE_COMPAT_MODE="); 2491 if (strncmp(argv[i+1], "SUN_MAKE_COMPAT_MODE=", length) == 0) { 2492 argv[i+1] = &argv[i+1][length]; 2493 MBSTOWCS(wcs_buffer, "SUN_MAKE_COMPAT_MODE"); 2494 name = GETNAME(wcs_buffer, FIND_LENGTH); 2495 dmake_compat_mode_specified = dmake_add_mode_specified; 2496 break; 2497 } 2498 length = strlen( "DMAKE_OUTPUT_MODE="); 2499 if (strncmp(argv[i+1], "DMAKE_OUTPUT_MODE=", length) == 0) { 2500 argv[i+1] = &argv[i+1][length]; 2501 MBSTOWCS(wcs_buffer, "DMAKE_OUTPUT_MODE"); 2502 name = GETNAME(wcs_buffer, FIND_LENGTH); 2503 dmake_output_mode_specified = dmake_add_mode_specified; 2504 } else { 2505 warning(gettext("Unknown argument `%s' after -x flag (ignored)"), 2506 argv[i+1]); 2507 argv[i] = argv[i + 1] = NULL; 2508 continue; 2509 } 2510 break; 2511 default: /* Shouldn't reach here */ 2512 argv[i] = NULL; 2513 continue; 2514 } 2515 argv[i] = NULL; 2516 if (i == (argc - 1)) { 2517 break; 2518 } 2519 if ((length = strlen(argv[i+1])) >= MAXPATHLEN) { 2520 tmp_wcs_buffer = ALLOC_WC(length + 1); 2521 (void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1); 2522 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 2523 retmem(tmp_wcs_buffer); 2524 } else { 2525 MBSTOWCS(wcs_buffer, argv[i+1]); 2526 value = GETNAME(wcs_buffer, FIND_LENGTH); 2527 } 2528 argv[i+1] = NULL; 2529 } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) { 2530 /* 2531 * Combine all macro in dynamic array 2532 */ 2533 if(*(cp-1) == (int) plus_char) 2534 { 2535 if(isspace(*(cp-2))) { 2536 append = true; 2537 cp--; 2538 } 2539 } 2540 if(!append) 2541 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]); 2542 2543 while (isspace(*(cp-1))) { 2544 cp--; 2545 } 2546 tmp_char = *cp; 2547 *cp = (int) nul_char; 2548 MBSTOWCS(wcs_buffer, argv[i]); 2549 *cp = tmp_char; 2550 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2551 while (*cp != (int) equal_char) { 2552 cp++; 2553 } 2554 cp++; 2555 while (isspace(*cp) && (*cp != (int) nul_char)) { 2556 cp++; 2557 } 2558 if ((length = strlen(cp)) >= MAXPATHLEN) { 2559 tmp_wcs_buffer = ALLOC_WC(length + 1); 2560 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1); 2561 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 2562 retmem(tmp_wcs_buffer); 2563 } else { 2564 MBSTOWCS(wcs_buffer, cp); 2565 value = GETNAME(wcs_buffer, FIND_LENGTH); 2566 } 2567 argv[i] = NULL; 2568 } else { 2569 /* Illegal MAKEFLAGS argument */ 2570 continue; 2571 } 2572 if(append) { 2573 setvar_append(name, value); 2574 append = false; 2575 } else { 2576 macro = maybe_append_prop(name, macro_prop); 2577 macro->body.macro.exported = true; 2578 SETVAR(name, value, false)->body.macro.read_only = true; 2579 } 2580 } 2581 } 2582 2583 /* 2584 * Append the DMake option and value to the MAKEFLAGS string. 2585 */ 2586 static void 2587 append_makeflags_string(Name name, register String makeflags_string) 2588 { 2589 const char *option; 2590 2591 if (strcmp(name->string_mb, "DMAKE_GROUP") == 0) { 2592 option = " -g "; 2593 } else if (strcmp(name->string_mb, "DMAKE_MAX_JOBS") == 0) { 2594 option = " -j "; 2595 } else if (strcmp(name->string_mb, "DMAKE_MODE") == 0) { 2596 option = " -m "; 2597 } else if (strcmp(name->string_mb, "DMAKE_ODIR") == 0) { 2598 option = " -o "; 2599 } else if (strcmp(name->string_mb, "DMAKE_RCFILE") == 0) { 2600 option = " -c "; 2601 } else if (strcmp(name->string_mb, "PMAKE_MACHINESFILE") == 0) { 2602 option = " -M "; 2603 } else if (strcmp(name->string_mb, "DMAKE_OUTPUT_MODE") == 0) { 2604 option = " -x DMAKE_OUTPUT_MODE="; 2605 } else if (strcmp(name->string_mb, "SUN_MAKE_COMPAT_MODE") == 0) { 2606 option = " -x SUN_MAKE_COMPAT_MODE="; 2607 } else { 2608 fatal(gettext("Internal error: name not recognized in append_makeflags_string()")); 2609 } 2610 Property prop = maybe_append_prop(name, macro_prop); 2611 if( prop == 0 || prop->body.macro.value == 0 || 2612 prop->body.macro.value->string_mb == 0 ) { 2613 return; 2614 } 2615 char mbs_value[MAXPATHLEN + 100]; 2616 strcpy(mbs_value, option); 2617 strcat(mbs_value, prop->body.macro.value->string_mb); 2618 MBSTOWCS(wcs_buffer, mbs_value); 2619 append_string(wcs_buffer, makeflags_string, FIND_LENGTH); 2620 } 2621 2622 /* 2623 * read_environment(read_only) 2624 * 2625 * This routine reads the process environment when make starts and enters 2626 * it as make macros. The environment variable SHELL is ignored. 2627 * 2628 * Parameters: 2629 * read_only Should we make env vars read only? 2630 * 2631 * Global variables used: 2632 * report_pwd Set if this make was started by other make 2633 */ 2634 static void 2635 read_environment(Boolean read_only) 2636 { 2637 register char **environment; 2638 int length; 2639 wchar_t *tmp_wcs_buffer; 2640 Boolean alloced_tmp_wcs_buffer = false; 2641 register wchar_t *name; 2642 register wchar_t *value; 2643 register Name macro; 2644 Property val; 2645 Boolean read_only_saved; 2646 2647 reading_environment = true; 2648 environment = environ; 2649 for (; *environment; environment++) { 2650 read_only_saved = read_only; 2651 if ((length = strlen(*environment)) >= MAXPATHLEN) { 2652 tmp_wcs_buffer = ALLOC_WC(length + 1); 2653 alloced_tmp_wcs_buffer = true; 2654 (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1); 2655 name = tmp_wcs_buffer; 2656 } else { 2657 MBSTOWCS(wcs_buffer, *environment); 2658 name = wcs_buffer; 2659 } 2660 value = (wchar_t *) wcschr(name, (int) equal_char); 2661 2662 /* 2663 * Looks like there's a bug in the system, but sometimes 2664 * you can get blank lines in *environment. 2665 */ 2666 if (!value) { 2667 continue; 2668 } 2669 MBSTOWCS(wcs_buffer2, "SHELL="); 2670 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2671 continue; 2672 } 2673 MBSTOWCS(wcs_buffer2, "MAKEFLAGS="); 2674 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2675 report_pwd = true; 2676 /* 2677 * In POSIX mode we do not want MAKEFLAGS to be readonly. 2678 * If the MAKEFLAGS macro is subsequently set by the makefile, 2679 * it replaces the MAKEFLAGS variable currently found in the 2680 * environment. 2681 * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8. 2682 */ 2683 if(posix) { 2684 read_only_saved = false; 2685 } 2686 } 2687 2688 /* 2689 * We ignore SUNPRO_DEPENDENCIES. This environment variable is 2690 * set by make and read by cpp which then writes info to 2691 * .make.dependency.xxx. When make is invoked by another make 2692 * (recursive make), we don't want to read this because then 2693 * the child make will end up writing to the parent 2694 * directory's .make.state and clobbering them. 2695 */ 2696 MBSTOWCS(wcs_buffer2, "SUNPRO_DEPENDENCIES"); 2697 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 2698 continue; 2699 } 2700 2701 macro = GETNAME(name, value - name); 2702 maybe_append_prop(macro, macro_prop)->body.macro.exported = 2703 true; 2704 if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) { 2705 val = setvar_daemon(macro, 2706 (Name) NULL, 2707 false, no_daemon, false, debug_level); 2708 } else { 2709 val = setvar_daemon(macro, 2710 GETNAME(value + 1, FIND_LENGTH), 2711 false, no_daemon, false, debug_level); 2712 } 2713 val->body.macro.read_only = read_only_saved; 2714 if (alloced_tmp_wcs_buffer) { 2715 retmem(tmp_wcs_buffer); 2716 alloced_tmp_wcs_buffer = false; 2717 } 2718 } 2719 reading_environment = false; 2720 } 2721 2722 /* 2723 * read_makefile(makefile, complain, must_exist, report_file) 2724 * 2725 * Read one makefile and check the result 2726 * 2727 * Return value: 2728 * false is the read failed 2729 * 2730 * Parameters: 2731 * makefile The file to read 2732 * complain Passed thru to read_simple_file() 2733 * must_exist Passed thru to read_simple_file() 2734 * report_file Passed thru to read_simple_file() 2735 * 2736 * Global variables used: 2737 * makefile_type Set to indicate we are reading main file 2738 * recursion_level Initialized 2739 */ 2740 static Boolean 2741 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file) 2742 { 2743 Boolean b; 2744 2745 makefile_type = reading_makefile; 2746 recursion_level = 0; 2747 reading_dependencies = true; 2748 b = read_simple_file(makefile, true, true, complain, 2749 must_exist, report_file, false); 2750 reading_dependencies = false; 2751 return b; 2752 } 2753 2754 /* 2755 * make_targets(argc, argv, parallel_flag) 2756 * 2757 * Call doname on the specified targets 2758 * 2759 * Parameters: 2760 * argc You know what this is 2761 * argv You know what this is 2762 * parallel_flag True if building in parallel 2763 * 2764 * Global variables used: 2765 * build_failed_seen Used to generated message after failed -k 2766 * commands_done Used to generate message "Up to date" 2767 * default_target_to_build First proper target in makefile 2768 * init The Name ".INIT", use to run command 2769 * parallel Global parallel building flag 2770 * quest make -q, suppresses messages 2771 * recursion_level Initialized, used for tracing 2772 * report_dependencies make -P, regroves whole process 2773 */ 2774 static void 2775 make_targets(int argc, char **argv, Boolean parallel_flag) 2776 { 2777 int i; 2778 char *cp; 2779 Doname result; 2780 register Boolean target_to_make_found = false; 2781 2782 (void) doname(init, true, true); 2783 recursion_level = 1; 2784 parallel = parallel_flag; 2785 /* 2786 * make remaining args 2787 */ 2788 /* 2789 if ((report_dependencies_level == 0) && parallel) { 2790 */ 2791 if (parallel) { 2792 /* 2793 * If building targets in parallel, start all of the 2794 * remaining args to build in parallel. 2795 */ 2796 for (i = 1; i < argc; i++) { 2797 if ((cp = argv[i]) != NULL) { 2798 commands_done = false; 2799 if ((cp[0] == (int) period_char) && 2800 (cp[1] == (int) slash_char)) { 2801 cp += 2; 2802 } 2803 if((cp[0] == (int) ' ') && 2804 (cp[1] == (int) '-') && 2805 (cp[2] == (int) ' ') && 2806 (cp[3] == (int) '-')) { 2807 argv[i] = NULL; 2808 continue; 2809 } 2810 MBSTOWCS(wcs_buffer, cp); 2811 //default_target_to_build = GETNAME(wcs_buffer, 2812 // FIND_LENGTH); 2813 default_target_to_build = normalize_name(wcs_buffer, 2814 wcslen(wcs_buffer)); 2815 if (default_target_to_build == wait_name) { 2816 if (parallel_process_cnt > 0) { 2817 finish_running(); 2818 } 2819 continue; 2820 } 2821 top_level_target = get_wstring(default_target_to_build->string_mb); 2822 /* 2823 * If we can't execute the current target in 2824 * parallel, hold off the target processing 2825 * to preserve the order of the targets as they appeared 2826 * in command line. 2827 */ 2828 if (!parallel_ok(default_target_to_build, false) 2829 && parallel_process_cnt > 0) { 2830 finish_running(); 2831 } 2832 result = doname_check(default_target_to_build, 2833 true, 2834 false, 2835 false); 2836 gather_recursive_deps(); 2837 if (/* !commands_done && */ 2838 (result == build_ok) && 2839 !quest && 2840 (report_dependencies_level == 0) /* && 2841 (exists(default_target_to_build) > file_doesnt_exist) */) { 2842 if (posix) { 2843 if (!commands_done) { 2844 (void) printf(gettext("`%s' is updated.\n"), 2845 default_target_to_build->string_mb); 2846 } else { 2847 if (no_action_was_taken) { 2848 (void) printf(gettext("`%s': no action was taken.\n"), 2849 default_target_to_build->string_mb); 2850 } 2851 } 2852 } else { 2853 default_target_to_build->stat.time = file_no_time; 2854 if (!commands_done && 2855 (exists(default_target_to_build) > file_doesnt_exist)) { 2856 (void) printf(gettext("`%s' is up to date.\n"), 2857 default_target_to_build->string_mb); 2858 } 2859 } 2860 } 2861 } 2862 } 2863 /* Now wait for all of the targets to finish running */ 2864 finish_running(); 2865 // setjmp(jmpbuffer); 2866 2867 } 2868 for (i = 1; i < argc; i++) { 2869 if ((cp = argv[i]) != NULL) { 2870 target_to_make_found = true; 2871 if ((cp[0] == (int) period_char) && 2872 (cp[1] == (int) slash_char)) { 2873 cp += 2; 2874 } 2875 if((cp[0] == (int) ' ') && 2876 (cp[1] == (int) '-') && 2877 (cp[2] == (int) ' ') && 2878 (cp[3] == (int) '-')) { 2879 argv[i] = NULL; 2880 continue; 2881 } 2882 MBSTOWCS(wcs_buffer, cp); 2883 default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer)); 2884 top_level_target = get_wstring(default_target_to_build->string_mb); 2885 report_recursion(default_target_to_build); 2886 commands_done = false; 2887 if (parallel) { 2888 result = (Doname) default_target_to_build->state; 2889 } else { 2890 result = doname_check(default_target_to_build, 2891 true, 2892 false, 2893 false); 2894 } 2895 gather_recursive_deps(); 2896 if (build_failed_seen) { 2897 build_failed_ever_seen = true; 2898 warning(gettext("Target `%s' not remade because of errors"), 2899 default_target_to_build->string_mb); 2900 } 2901 build_failed_seen = false; 2902 if (report_dependencies_level > 0) { 2903 print_dependencies(default_target_to_build, 2904 get_prop(default_target_to_build->prop, 2905 line_prop)); 2906 } 2907 default_target_to_build->stat.time = 2908 file_no_time; 2909 if (default_target_to_build->colon_splits > 0) { 2910 default_target_to_build->state = 2911 build_dont_know; 2912 } 2913 if (!parallel && 2914 /* !commands_done && */ 2915 (result == build_ok) && 2916 !quest && 2917 (report_dependencies_level == 0) /* && 2918 (exists(default_target_to_build) > file_doesnt_exist) */) { 2919 if (posix) { 2920 if (!commands_done) { 2921 (void) printf(gettext("`%s' is updated.\n"), 2922 default_target_to_build->string_mb); 2923 } else { 2924 if (no_action_was_taken) { 2925 (void) printf(gettext("`%s': no action was taken.\n"), 2926 default_target_to_build->string_mb); 2927 } 2928 } 2929 } else { 2930 if (!commands_done && 2931 (exists(default_target_to_build) > file_doesnt_exist)) { 2932 (void) printf(gettext("`%s' is up to date.\n"), 2933 default_target_to_build->string_mb); 2934 } 2935 } 2936 } 2937 } 2938 } 2939 2940 /* 2941 * If no file arguments have been encountered, 2942 * make the first name encountered that doesnt start with a dot 2943 */ 2944 if (!target_to_make_found) { 2945 if (default_target_to_build == NULL) { 2946 fatal(gettext("No arguments to build")); 2947 } 2948 commands_done = false; 2949 top_level_target = get_wstring(default_target_to_build->string_mb); 2950 report_recursion(default_target_to_build); 2951 2952 2953 if (getenv("SPRO_EXPAND_ERRORS")){ 2954 (void) printf("::(%s)\n", 2955 default_target_to_build->string_mb); 2956 } 2957 2958 2959 result = doname_parallel(default_target_to_build, true, false); 2960 gather_recursive_deps(); 2961 if (build_failed_seen) { 2962 build_failed_ever_seen = true; 2963 warning(gettext("Target `%s' not remade because of errors"), 2964 default_target_to_build->string_mb); 2965 } 2966 build_failed_seen = false; 2967 if (report_dependencies_level > 0) { 2968 print_dependencies(default_target_to_build, 2969 get_prop(default_target_to_build-> 2970 prop, 2971 line_prop)); 2972 } 2973 default_target_to_build->stat.time = file_no_time; 2974 if (default_target_to_build->colon_splits > 0) { 2975 default_target_to_build->state = build_dont_know; 2976 } 2977 if (/* !commands_done && */ 2978 (result == build_ok) && 2979 !quest && 2980 (report_dependencies_level == 0) /* && 2981 (exists(default_target_to_build) > file_doesnt_exist) */) { 2982 if (posix) { 2983 if (!commands_done) { 2984 (void) printf(gettext("`%s' is updated.\n"), 2985 default_target_to_build->string_mb); 2986 } else { 2987 if (no_action_was_taken) { 2988 (void) printf(gettext("`%s': no action was taken.\n"), 2989 default_target_to_build->string_mb); 2990 } 2991 } 2992 } else { 2993 if (!commands_done && 2994 (exists(default_target_to_build) > file_doesnt_exist)) { 2995 (void) printf(gettext("`%s' is up to date.\n"), 2996 default_target_to_build->string_mb); 2997 } 2998 } 2999 } 3000 } 3001 } 3002 3003 /* 3004 * report_recursion(target) 3005 * 3006 * If this is a recursive make and the parent make has KEEP_STATE on 3007 * this routine reports the dependency to the parent make 3008 * 3009 * Parameters: 3010 * target Target to report 3011 * 3012 * Global variables used: 3013 * makefiles_used List of makefiles read 3014 * recursive_name The Name ".RECURSIVE", printed 3015 * report_dependency dwight 3016 */ 3017 static void 3018 report_recursion(register Name target) 3019 { 3020 register FILE *report_file = get_report_file(); 3021 3022 if ((report_file == NULL) || (report_file == (FILE*)-1)) { 3023 return; 3024 } 3025 if (primary_makefile == NULL) { 3026 /* 3027 * This can happen when there is no makefile and 3028 * only implicit rules are being used. 3029 */ 3030 return; 3031 } 3032 (void) fprintf(report_file, 3033 "%s: %s ", 3034 get_target_being_reported_for(), 3035 recursive_name->string_mb); 3036 report_dependency(get_current_path()); 3037 report_dependency(target->string_mb); 3038 report_dependency(primary_makefile->string_mb); 3039 (void) fprintf(report_file, "\n"); 3040 } 3041 3042 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */ 3043 /* NIKMOL */ 3044 extern void 3045 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro) 3046 { 3047 register char *cp0; /* work pointer in macro */ 3048 register char *cp1; /* work pointer in array */ 3049 register char *cp2; /* work pointer in array */ 3050 register char *cp3; /* work pointer in array */ 3051 register char *name; /* macro name */ 3052 register char *value; /* macro value */ 3053 register int len_array; 3054 register int len_macro; 3055 3056 char * esc_value = NULL; 3057 int esc_len; 3058 3059 if (!(len_macro = strlen(macro))) return; 3060 name = macro; 3061 while (isspace(*(name))) { 3062 name++; 3063 } 3064 if (!(value = strchr(name, (int) equal_char))) { 3065 /* no '=' in macro */ 3066 goto ERROR_MACRO; 3067 } 3068 cp0 = value; 3069 value++; 3070 while (isspace(*(value))) { 3071 value++; 3072 } 3073 while (isspace(*(cp0-1))) { 3074 cp0--; 3075 } 3076 if (cp0 <= name) goto ERROR_MACRO; /* no name */ 3077 if (!(Ar->size)) goto ALLOC_ARRAY; 3078 cp1 = Ar->start; 3079 3080 LOOK_FOR_NAME: 3081 if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO; 3082 if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO; 3083 if (strncmp(cp1, name, (size_t)(cp0-name))) { 3084 /* another name */ 3085 cp1++; 3086 goto LOOK_FOR_NAME; 3087 } 3088 if (cp1 != Ar->start) { 3089 if (!isspace(*(cp1-1))) { 3090 /* another name */ 3091 cp1++; 3092 goto LOOK_FOR_NAME; 3093 } 3094 } 3095 for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) { 3096 if (isspace(*cp3)) continue; 3097 /* else: another name */ 3098 cp1++; 3099 goto LOOK_FOR_NAME; 3100 } 3101 /* Look for the next macro name in array */ 3102 cp3 = cp2+1; 3103 if (*cp3 != (int) doublequote_char) { 3104 /* internal error */ 3105 goto ERROR_MACRO; 3106 } 3107 if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) { 3108 /* internal error */ 3109 goto ERROR_MACRO; 3110 } 3111 cp3++; 3112 while (isspace(*cp3)) { 3113 cp3++; 3114 } 3115 3116 cp2 = cp1; /* remove old macro */ 3117 if ((*cp3) && (cp3 < Ar->start + Ar->size)) { 3118 for (; cp3 < Ar->start + Ar->size; cp3++) { 3119 *cp2++ = *cp3; 3120 } 3121 } 3122 for (; cp2 < Ar->start + Ar->size; cp2++) { 3123 *cp2 = 0; 3124 } 3125 if (*cp1) { 3126 /* check next name */ 3127 goto LOOK_FOR_NAME; 3128 } 3129 goto APPEND_MACRO; 3130 3131 ALLOC_ARRAY: 3132 if (Ar->size) { 3133 cp1 = Ar->start; 3134 } else { 3135 cp1 = 0; 3136 } 3137 Ar->size += 128; 3138 Ar->start = getmem(Ar->size); 3139 for (len_array=0; len_array < Ar->size; len_array++) { 3140 Ar->start[len_array] = 0; 3141 } 3142 if (cp1) { 3143 strcpy(Ar->start, cp1); 3144 retmem((wchar_t *) cp1); 3145 } 3146 3147 APPEND_MACRO: 3148 len_array = strlen(Ar->start); 3149 esc_value = (char*)malloc(strlen(value)*2 + 1); 3150 quote_str(value, esc_value); 3151 esc_len = strlen(esc_value) - strlen(value); 3152 if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY; 3153 strcat(Ar->start, " "); 3154 strncat(Ar->start, name, cp0-name); 3155 strcat(Ar->start, "="); 3156 strncat(Ar->start, esc_value, strlen(esc_value)); 3157 free(esc_value); 3158 return; 3159 ERROR_MACRO: 3160 /* Macro without '=' or with invalid left/right part */ 3161 return; 3162 } 3163 3164 static void 3165 report_dir_enter_leave(Boolean entering) 3166 { 3167 char rcwd[MAXPATHLEN]; 3168 static char * mlev = NULL; 3169 char * make_level_str = NULL; 3170 int make_level_val = 0; 3171 3172 make_level_str = getenv("MAKELEVEL"); 3173 if(make_level_str) { 3174 make_level_val = atoi(make_level_str); 3175 } 3176 if(mlev == NULL) { 3177 mlev = (char*) malloc(MAXPATHLEN); 3178 } 3179 if(entering) { 3180 sprintf(mlev, "MAKELEVEL=%d", make_level_val + 1); 3181 } else { 3182 make_level_val--; 3183 sprintf(mlev, "MAKELEVEL=%d", make_level_val); 3184 } 3185 putenv(mlev); 3186 3187 if(report_cwd) { 3188 if(make_level_val <= 0) { 3189 if(entering) { 3190 sprintf(rcwd, 3191 gettext("%s: Entering directory `%s'\n"), 3192 getprogname(), 3193 get_current_path()); 3194 } else { 3195 sprintf(rcwd, 3196 gettext("%s: Leaving directory `%s'\n"), 3197 getprogname(), 3198 get_current_path()); 3199 } 3200 } else { 3201 if(entering) { 3202 sprintf(rcwd, 3203 gettext("%s[%d]: Entering directory `%s'\n"), 3204 getprogname(), 3205 make_level_val, get_current_path()); 3206 } else { 3207 sprintf(rcwd, 3208 gettext("%s[%d]: Leaving directory `%s'\n"), 3209 getprogname(), 3210 make_level_val, get_current_path()); 3211 } 3212 } 3213 printf("%s", rcwd); 3214 } 3215 } 3216