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