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