A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 /* 2 * CDDL HEADER START 3 * 4 * This file and its contents are supplied under the terms of the 5 * Common Development and Distribution License ("CDDL"), version 1.0. 6 * You may use this file only in accordance with the terms of version 7 * 1.0 of the CDDL. 8 * 9 * A full copy of the text of the CDDL should have accompanied this 10 * source. A copy of the CDDL is also available via the Internet at 11 * http://www.opensource.org/licenses/cddl1.txt 12 * See the License for the specific language governing permissions 13 * and limitations under the License. 14 * 15 * When distributing Covered Code, include this CDDL HEADER in each 16 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 */ 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* 28 * @(#)main.cc 1.158 06/12/12 29 */ 30 31 #pragma ident "@(#)main.cc 1.158 06/12/12" 32 33 /* 34 * Copyright 2017-2021 J. Schilling 35 * 36 * @(#)main.cc 1.60 21/08/30 2017-2021 J. Schilling 37 */ 38 #include <schily/mconfig.h> 39 #ifndef lint 40 static UConst char sccsid[] = 41 "@(#)main.cc 1.60 21/08/30 2017-2021 J. Schilling"; 42 #endif 43 44 /* 45 * main.cc 46 * 47 * make program main routine plus some helper routines 48 */ 49 50 /* 51 * Included files 52 */ 53 #if defined(TEAMWARE_MAKE_CMN) 54 # include <avo/intl.h> 55 # include <avo/libcli.h> /* libcli_init() */ 56 # include <avo/cli_license.h> /* avo_cli_get_license() */ 57 # include <avo/find_dir.h> /* avo_find_run_dir() */ 58 # include <avo/version_string.h> 59 # include <avo/util.h> /* avo_init() */ 60 #ifdef USE_DMS_CCR 61 # include <avo/usage_tracking.h> 62 #else 63 # include <avo/cleanup.h> 64 #endif 65 #endif 66 67 #if defined(TEAMWARE_MAKE_CMN) 68 /* This is for dmake only (not for Solaris make). 69 * Include code to check updates (dmake patches) 70 */ 71 #ifdef _CHECK_UPDATE_H 72 #include <libAU.h> 73 #endif 74 #endif 75 76 #include <bsd/bsd.h> /* bsd_signal() */ 77 78 #ifdef DISTRIBUTED 79 # include <dm/Avo_AcknowledgeMsg.h> 80 # include <rw/xdrstrea.h> 81 # include <dmrc/dmrc.h> /* dmakerc file processing */ 82 #endif 83 84 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 85 #include <schily/locale.h> /* setlocale() */ 86 #else 87 #include <locale.h> /* setlocale() */ 88 #endif 89 #include <mk/copyright.h> 90 #include <mk/defs.h> 91 #include <mksh/macro.h> /* getvar() */ 92 #include <mksh/misc.h> /* getmem(), setup_char_semantics() */ 93 94 #if defined(TEAMWARE_MAKE_CMN) 95 #ifdef USE_DMS_CCR 96 # include <pubdmsi18n/pubdmsi18n.h> /* libpubdmsi18n_init() */ 97 #endif 98 #endif 99 100 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 101 #include <schily/pwd.h> /* getpwnam() */ 102 #include <schily/setjmp.h> 103 104 #include <schily/wait.h> /* wait() */ 105 #else 106 #include <pwd.h> /* getpwnam() */ 107 #include <setjmp.h> 108 109 #include <sys/wait.h> /* wait() */ 110 #define WAIT_T int 111 #endif 112 #include <vroot/report.h> /* report_dependency(), get_report_file() */ 113 114 // From read2.cc 115 extern Name normalize_name(register wchar_t *name_string, register int length); 116 117 // From parallel.cc 118 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 119 #define MAXJOBS_ADJUST_RFE4694000 120 121 #ifdef MAXJOBS_ADJUST_RFE4694000 122 extern void job_adjust_fini(); 123 #endif /* MAXJOBS_ADJUST_RFE4694000 */ 124 #endif /* TEAMWARE_MAKE_CMN */ 125 126 #include <ctype.h> 127 128 #ifdef HAVE_LIBGEN_H 129 #include <libgen.h> 130 #endif 131 #include <schily/schily.h> 132 133 #ifdef ultrix /* No prototypes in SIG_DFL macro */ 134 #undef SUN5_0 135 #endif 136 137 /* 138 * Defined macros 139 */ 140 #define LD_SUPPORT_ENV_VAR NOCATGETS("SGS_SUPPORT") 141 #define LD_SUPPORT_ENV_VAR_32 NOCATGETS("SGS_SUPPORT_32") 142 #define LD_SUPPORT_ENV_VAR_64 NOCATGETS("SGS_SUPPORT_64") 143 #define LD_SUPPORT_MAKE_LIB NOCATGETS("libmakestate.so.1") 144 #ifdef sun 145 #ifdef __i386 146 #define LD_SUPPORT_MAKE_ARCH "i386/" 147 #endif 148 #ifdef __sparc 149 #define LD_SUPPORT_MAKE_ARCH "sparc/" 150 #endif 151 #endif /* sun */ 152 153 /* 154 * typedefs & structs 155 */ 156 157 /* 158 * Static variables 159 */ 160 static char *argv_zero_string; 161 static char *argv_zero_base; 162 static char *dmake_compat_value; 163 static Boolean build_failed_ever_seen; 164 static Boolean continue_after_error_ever_seen; /* `-k' */ 165 static Boolean dmake_group_specified; /* `-g' */ 166 static Boolean dmake_max_jobs_specified; /* `-j' */ 167 static Boolean dmake_mode_specified; /* `-m' */ 168 static Boolean dmake_add_mode_specified; /* `-x' */ 169 static Boolean dmake_output_mode_specified; /* `-x DMAKE_OUTPUT_MODE=' */ 170 static Boolean dmake_compat_mode_specified; /* `-x SUN_MAKE_COMPAT_MODE=' */ 171 static Boolean dmake_odir_specified; /* `-o' */ 172 static Boolean dmake_rcfile_specified; /* `-c' */ 173 static Boolean env_wins; /* `-e' */ 174 static Boolean ignore_default_mk; /* `-r' */ 175 static Boolean list_all_targets; /* `-T' */ 176 static int mf_argc; 177 static char **mf_argv; 178 static Dependency_rec not_auto_depen_struct; 179 static Dependency not_auto_depen = ¬_auto_depen_struct; 180 static Boolean pmake_cap_r_specified; /* `-R' */ 181 static Boolean pmake_machinesfile_specified; /* `-M' */ 182 static Boolean stop_after_error_ever_seen; /* `-S' */ 183 static Boolean trace_status; /* `-p' */ 184 185 #ifdef DMAKE_STATISTICS 186 static Boolean getname_stat = false; 187 #endif 188 189 static int g_argc; 190 static char **g_argv; 191 #if defined(TEAMWARE_MAKE_CMN) 192 static time_t start_time; 193 #ifdef USE_DMS_CCR 194 static Avo_usage_tracking *usageTracking = NULL; 195 #else 196 static Avo_cleanup *cleanup = NULL; 197 #endif 198 #endif 199 200 /* 201 * File table of contents 202 */ 203 #ifdef HAVE_ATEXIT 204 extern "C" void cleanup_after_exit(void); 205 #else 206 extern void cleanup_after_exit(int, ...); 207 #endif 208 209 #ifdef TEAMWARE_MAKE_CMN 210 extern "C" { 211 extern void dmake_exit_callback(void); 212 extern void dmake_message_callback(char *); 213 } 214 #endif 215 216 extern Name normalize_name(register wchar_t *name_string, register int length); 217 218 extern int main(int, char * []); 219 220 static void scan_dmake_compat_mode(char *); 221 static void append_makeflags_string(Name, String); 222 static void doalarm(int); 223 static void enter_argv_values(int , char **, ASCII_Dyn_Array *); 224 static void make_targets(int, char **, Boolean); 225 static int parse_command_option(char); 226 static void read_command_options(int, char **); 227 static void read_environment(Boolean); 228 static void read_files_and_state(int, char **); 229 static Boolean read_makefile(Name, Boolean, Boolean, Boolean); 230 static void report_recursion(Name); 231 static void set_sgs_support(void); 232 static void setup_for_projectdir(void); 233 static void setup_makeflags_argv(void); 234 static void dir_enter_leave(Boolean entering); 235 static void report_dir_enter_leave(Boolean entering); 236 237 238 #ifdef DISTRIBUTED 239 extern int dmake_ofd; 240 extern FILE* dmake_ofp; 241 extern int rxmPid; 242 extern XDR xdrs_out; 243 #endif 244 #ifdef TEAMWARE_MAKE_CMN 245 extern char verstring[]; 246 #else 247 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 248 extern char verstring[]; 249 #endif 250 #endif 251 252 jmp_buf jmpbuffer; 253 254 /* 255 * main(argc, argv) 256 * 257 * Parameters: 258 * argc You know what this is 259 * argv You know what this is 260 * 261 * Static variables used: 262 * list_all_targets make -T seen 263 * trace_status make -p seen 264 * 265 * Global variables used: 266 * debug_level Should we trace make actions? 267 * keep_state Set if .KEEP_STATE seen 268 * makeflags The Name "MAKEFLAGS", used to get macro 269 * remote_command_name Name of remote invocation cmd ("on") 270 * running_list List of parallel running processes 271 * stdout_stderr_same true if stdout and stderr are the same 272 * auto_dependencies The Name "SUNPRO_DEPENDENCIES" 273 * temp_file_directory Set to the dir where we create tmp file 274 * trace_reader Set to reflect tracing status 275 * working_on_targets Set when building user targets 276 */ 277 int 278 main(int argc, char *argv[]) 279 { 280 /* 281 * cp is a -> to the value of the MAKEFLAGS env var, 282 * which has to be regular chars. 283 */ 284 register char *cp; 285 char make_state_dir[MAXPATHLEN]; 286 Boolean parallel_flag = false; 287 char *prognameptr; 288 char *slash_ptr; 289 mode_t um; 290 int i; 291 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 292 struct itimerval value; 293 char def_dmakerc_path[MAXPATHLEN]; 294 Name dmake_name, dmake_name2; 295 Name dmake_value, dmake_value2; 296 Property prop, prop2; 297 struct stat statbuf; 298 int statval; 299 #endif 300 301 #ifndef PARALLEL 302 struct stat out_stat, err_stat; 303 #endif 304 hostid = gethostid(); 305 #ifdef TEAMWARE_MAKE_CMN 306 avo_get_user(NULL, NULL); // Initialize user name 307 #endif 308 bsd_signals(); 309 310 (void) setlocale(LC_ALL, ""); 311 312 #ifdef DMAKE_STATISTICS 313 if (getenv(NOCATGETS("DMAKE_STATISTICS"))) { 314 getname_stat = true; 315 } 316 #endif 317 318 319 /* 320 * avo_init() sets the umask to 0. Save it here and restore 321 * it after the avo_init() call. 322 */ 323 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) 324 um = umask(0); 325 avo_init(argv[0]); 326 umask(um); 327 328 #ifdef USE_DMS_CCR 329 usageTracking = new Avo_usage_tracking(NOCATGETS("dmake"), argc, argv); 330 #else 331 cleanup = new Avo_cleanup(NOCATGETS("dmake"), argc, argv); 332 #endif 333 #endif 334 335 #if defined(TEAMWARE_MAKE_CMN) 336 libcli_init(); 337 338 #ifdef _CHECK_UPDATE_H 339 /* This is for dmake only (not for Solaris make). 340 * Check (in background) if there is an update (dmake patch) 341 * and inform user 342 */ 343 { 344 Avo_err *err; 345 char *dir; 346 err = avo_find_run_dir(&dir); 347 if (AVO_OK == err) { 348 AU_check_update_service(NOCATGETS("Dmake"), dir); 349 } 350 } 351 #endif /* _CHECK_UPDATE_H */ 352 #endif 353 354 // ---> fprintf(stderr, gettext("--- SUN make ---\n")); 355 356 357 #if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) 358 /* 359 * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init() 360 * from avo_util library. 361 */ 362 libmksdmsi18n_init(); 363 #ifdef USE_DMS_CCR 364 libpubdmsi18n_init(); 365 #endif 366 #endif 367 368 #if !defined(TEXT_DOMAIN) /* Should be defined by CC -D */ 369 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 370 #endif 371 textdomain(TEXT_DOMAIN); 372 373 g_argc = argc; 374 g_argv = (char **) malloc((g_argc + 1) * sizeof(char *)); 375 for (i = 0; i < argc; i++) { 376 g_argv[i] = argv[i]; 377 } 378 g_argv[i] = NULL; 379 380 /* 381 * Set argv_zero_string to some form of argv[0] for 382 * recursive MAKE builds. 383 */ 384 385 if (*argv[0] == (int) slash_char) { 386 /* argv[0] starts with a slash */ 387 argv_zero_string = strdup(argv[0]); 388 } else if (strchr(argv[0], (int) slash_char) == NULL) { 389 /* argv[0] contains no slashes */ 390 argv_zero_string = strdup(argv[0]); 391 } else { 392 /* 393 * argv[0] contains at least one slash, 394 * but doesn't start with a slash 395 * so it is relative to the current working directory. 396 * Build an absolute path name for argv[0] to the called make 397 * binary path before we may do a chdir() from a -C option. 398 */ 399 char *tmp_current_path; 400 char *tmp_string; 401 402 tmp_current_path = get_current_path(); 403 tmp_string = getmem(strlen(tmp_current_path) + 1 + 404 strlen(argv[0]) + 1); 405 (void) sprintf(tmp_string, 406 "%s/%s", 407 tmp_current_path, 408 argv[0]); 409 argv_zero_string = strdup(tmp_string); 410 retmem_mb(tmp_string); 411 } 412 if ((argv_zero_base = strrchr(argv_zero_string, '/')) == NULL) 413 argv_zero_base = argv_zero_string; 414 else 415 argv_zero_base++; 416 417 /* 418 * The following flags are reset if we don't have the 419 * (.nse_depinfo or .make.state) files locked and only set 420 * AFTER the file has been locked. This ensures that if the user 421 * interrupts the program while file_lock() is waiting to lock 422 * the file, the interrupt handler doesn't remove a lock 423 * that doesn't belong to us. 424 */ 425 make_state_lockfile = NULL; 426 make_state_locked = false; 427 428 #ifdef NSE 429 nse_depinfo_lockfile[0] = '\0'; 430 nse_depinfo_locked = false; 431 #endif 432 433 /* 434 * look for last slash char in the path to look at the binary 435 * name. This is to resolve the hard link and invoke make 436 * in svr4 mode. 437 * 438 * WARNING: /usr/bin/make and /usr/xpg4/bin/make must be 439 * hardlinked or we will not be able to distinct them. 440 */ 441 442 /* Sun OS make standard */ 443 svr4 = false; 444 posix = false; 445 make_run_dir = find_run_dir(); 446 if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) { 447 svr4 = false; 448 posix = true; 449 } else if (make_run_dir && (cp = strstr(make_run_dir, "xpg4/bin")) && 450 strcmp(cp, "xpg4/bin") == 0) { 451 svr4 = false; 452 posix = true; 453 } else if ((cp = strstr(argv_zero_string, "xpg4/bin/make")) && 454 strcmp(cp, "xpg4/bin/make") == 0) { 455 svr4 = false; 456 posix = true; 457 } else { 458 prognameptr = strrchr(argv[0], '/'); 459 if(prognameptr) { 460 prognameptr++; 461 } else { 462 prognameptr = argv[0]; 463 } 464 if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) { 465 svr4 = true; 466 posix = false; 467 } 468 } 469 if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){ 470 svr4 = true; 471 posix = false; 472 } 473 474 /* 475 * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style. 476 */ 477 scan_dmake_compat_mode(getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE"))); 478 479 /* 480 * Temporary directory set up. 481 */ 482 char * tmpdir_var = getenv(NOCATGETS("TMPDIR")); 483 if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) { 484 strcpy(mbs_buffer, tmpdir_var); 485 for (tmpdir_var = mbs_buffer+strlen(mbs_buffer); 486 *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer; 487 *tmpdir_var = '\0'); 488 if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */ 489 sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"), 490 mbs_buffer, getpid()); 491 int fd = mkstemp(mbs_buffer2); 492 if (fd >= 0) { 493 close(fd); 494 unlink(mbs_buffer2); 495 tmpdir = strdup(mbs_buffer); 496 } 497 } 498 } 499 500 #ifndef PARALLEL 501 /* find out if stdout and stderr point to the same place */ 502 if (fstat(1, &out_stat) < 0) { 503 fatal(gettext("fstat of standard out failed: %s"), errmsg(errno)); 504 } 505 if (fstat(2, &err_stat) < 0) { 506 fatal(gettext("fstat of standard error failed: %s"), errmsg(errno)); 507 } 508 if ((out_stat.st_dev == err_stat.st_dev) && 509 (out_stat.st_ino == err_stat.st_ino)) { 510 stdout_stderr_same = true; 511 } else { 512 stdout_stderr_same = false; 513 } 514 #else 515 stdout_stderr_same = false; 516 #endif 517 /* Make the vroot package scan the path using shell semantics */ 518 set_path_style(0); 519 520 setup_char_semantics(); 521 522 /* 523 * If running with .KEEP_STATE, curdir will be set with 524 * the connected directory. 525 */ 526 #ifdef HAVE_ATEXIT 527 (void) atexit(cleanup_after_exit); 528 #else 529 (void) on_exit(cleanup_after_exit, (char *) NULL); 530 #endif 531 532 load_cached_names(); 533 534 /* 535 * Set command line flags 536 * 537 * Warning: Do not keep pointers from get_current_path() calls while 538 * parsing the options as they could become invalid from a -C option. 539 */ 540 setup_makeflags_argv(); 541 read_command_options(mf_argc, mf_argv); 542 read_command_options(argc, argv); 543 if (debug_level > 0) { 544 cp = getenv(makeflags->string_mb); 545 (void) printf(gettext("MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp); 546 } 547 if (dmake_compat_value) { /* -x SUN_MAKE_COMPAT_MODE=xxx */ 548 char *p = strchr(dmake_compat_value, '='); /* != NULL */ 549 550 scan_dmake_compat_mode(++p); 551 552 /* 553 * Calling setup_char_semantics() again is needed in case that 554 * svr4 did change it's value. 555 */ 556 for (i = 0; i < CHAR_SEMANTICS_ENTRIES; i++) 557 char_semantics[i] = 0; 558 setup_char_semantics(); 559 } 560 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 561 if (posix) 562 job_adjust_posix(); /* DMAKE_ADJUST_MAX_JOBS=M2 */ 563 #endif 564 565 /* 566 * If there have been -C options, they have been evaluated with the 567 * last call to read_command_options() and we thus may need to 568 * re-initialize CURDIR before we read the Makefiles in order to let 569 * them overwrite CURDIR if they like. 570 */ 571 if (current_path_reset) 572 (void) get_current_path(); 573 /* 574 * Need to set this up after parsing options and after a 575 * possible -C option has been processed. 576 */ 577 setup_for_projectdir(); 578 579 dir_enter_leave(true); /* Must be before next call */ 580 setup_interrupt(handle_interrupt); 581 582 read_files_and_state(argc, argv); 583 584 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 585 /* 586 * Find the dmake_output_mode: TXT1, TXT2 or HTML1. 587 */ 588 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); 589 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); 590 prop2 = get_prop(dmake_name2->prop, macro_prop); 591 if (prop2 == NULL) { 592 /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */ 593 output_mode = txt1_mode; 594 } else { 595 dmake_value2 = prop2->body.macro.value; 596 if ((dmake_value2 == NULL) || 597 (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) { 598 output_mode = txt1_mode; 599 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) { 600 output_mode = txt2_mode; 601 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) { 602 output_mode = html1_mode; 603 } else { 604 warning(gettext("Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"), 605 dmake_value2->string_mb); 606 } 607 } 608 /* 609 * Find the dmake_mode: distributed, parallel, or serial. 610 */ 611 #ifdef DO_NOTPARALLEL 612 if (notparallel) { 613 dmake_mode_type = serial_mode; 614 no_parallel = true; 615 } else 616 #endif 617 if ((!pmake_cap_r_specified) && 618 (!pmake_machinesfile_specified)) { 619 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); 620 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); 621 prop2 = get_prop(dmake_name2->prop, macro_prop); 622 623 if ((IS_EQUAL(argv_zero_base, NOCATGETS("make")) || 624 IS_EQUAL(argv_zero_base, NOCATGETS("svr4.make"))) && 625 !dmake_max_jobs_specified) { 626 /* 627 * "make" and "svr4.make" default to serial mode, except when 628 * -j was specified. 629 */ 630 dmake_mode_type = serial_mode; 631 no_parallel = true; 632 } else if (prop2 == NULL) { 633 #ifdef TEAMWARE_MAKE_CMN 634 /* DMAKE_MODE not defined, default to distributed mode */ 635 dmake_mode_type = distributed_mode; 636 no_parallel = false; 637 #else 638 /* 639 * If we ever implement support for something like the TeamWare 640 * .dmakerc, we need to move the printout down after the check 641 * for the .dmakerc file. 642 */ 643 if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) { 644 putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE")); 645 (void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n")); 646 } 647 dmake_mode_type = parallel_mode; 648 no_parallel = false; 649 #endif 650 } else { 651 dmake_value2 = prop2->body.macro.value; 652 if ((dmake_value2 == NULL) || 653 (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) { 654 dmake_mode_type = distributed_mode; 655 no_parallel = false; 656 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) { 657 dmake_mode_type = parallel_mode; 658 no_parallel = false; 659 #ifdef SGE_SUPPORT 660 grid = false; 661 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("grid"))) { 662 dmake_mode_type = parallel_mode; 663 no_parallel = false; 664 grid = true; 665 #endif 666 } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) { 667 dmake_mode_type = serial_mode; 668 no_parallel = true; 669 } else { 670 fatal(gettext("Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb); 671 } 672 } 673 674 if ((!list_all_targets) && 675 (report_dependencies_level == 0)) { 676 /* 677 * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined. 678 * They could be defined in the env, in the makefile, or on the 679 * command line. 680 * If neither is defined, and $(HOME)/.dmakerc does not exists, 681 * then print a message, and default to parallel mode. 682 */ 683 #ifdef DISTRIBUTED 684 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); 685 dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); 686 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); 687 dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); 688 if ((((prop = get_prop(dmake_name->prop, macro_prop)) == NULL) || 689 ((dmake_value = prop->body.macro.value) == NULL)) && 690 (((prop2 = get_prop(dmake_name2->prop, macro_prop)) == NULL) || 691 ((dmake_value2 = prop2->body.macro.value) == NULL))) { 692 Boolean empty_dmakerc = true; 693 char *homedir = getenv(NOCATGETS("HOME")); 694 if ((homedir != NULL) && (strlen(homedir) < (sizeof(def_dmakerc_path) - 16))) { 695 sprintf(def_dmakerc_path, NOCATGETS("%s/.dmakerc"), homedir); 696 if ((((statval = stat(def_dmakerc_path, &statbuf)) != 0) && (errno == ENOENT)) || 697 ((statval == 0) && (statbuf.st_size == 0))) { 698 } else { 699 Avo_dmakerc *rcfile = new Avo_dmakerc(); 700 Avo_err *err = rcfile->read(def_dmakerc_path, NULL, TRUE); 701 if (err) { 702 fatal(err->str); 703 } 704 empty_dmakerc = rcfile->was_empty(); 705 delete rcfile; 706 } 707 } 708 if (empty_dmakerc) { 709 if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) { 710 putenv((char *)NOCATGETS("DMAKE_DEF_PRINTED=TRUE")); 711 (void) fprintf(stdout, gettext("dmake: defaulting to parallel mode.\n")); 712 (void) fprintf(stdout, gettext("See the man page dmake(1) for more information on setting up the .dmakerc file.\n")); 713 } 714 dmake_mode_type = parallel_mode; 715 no_parallel = false; 716 } 717 } 718 #else 719 if(dmake_mode_type == distributed_mode) { 720 (void) fprintf(stdout, NOCATGETS("dmake: Distributed mode not implemented.\n")); 721 (void) fprintf(stdout, NOCATGETS(" Defaulting to parallel mode.\n")); 722 dmake_mode_type = parallel_mode; 723 no_parallel = false; 724 } 725 #endif /* DISTRIBUTED */ 726 } 727 } 728 #endif 729 730 #ifdef TEAMWARE_MAKE_CMN 731 parallel_flag = true; 732 /* XXX - This is a major hack for DMake/Licensing. */ 733 if (getenv(NOCATGETS("DMAKE_CHILD")) == NULL) { 734 if (!avo_cli_search_license(argv[0], dmake_exit_callback, TRUE, dmake_message_callback)) { 735 /* 736 * If the user can not get a TeamWare license, 737 * default to serial mode. 738 */ 739 dmake_mode_type = serial_mode; 740 no_parallel = true; 741 } else { 742 putenv((char *)NOCATGETS("DMAKE_CHILD=TRUE")); 743 } 744 start_time = time(NULL); 745 /* 746 * XXX - Hack to disable SIGALRM's from licensing library's 747 * setitimer(). 748 */ 749 value.it_interval.tv_sec = 0; 750 value.it_interval.tv_usec = 0; 751 value.it_value.tv_sec = 0; 752 value.it_value.tv_usec = 0; 753 (void) setitimer(ITIMER_REAL, &value, NULL); 754 } 755 756 // 757 // If dmake is running with -t option, set dmake_mode_type to serial. 758 // This is done because doname() calls touch_command() that runs serially. 759 // If we do not do that, maketool will have problems. 760 // 761 if(touch) { 762 dmake_mode_type = serial_mode; 763 no_parallel = true; 764 } 765 #else 766 #ifdef PMAKE 767 if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake")) || 768 dmake_max_jobs_specified) { 769 parallel_flag = true; 770 } else 771 #endif 772 parallel_flag = false; 773 #ifdef PMAKE 774 /* 775 * If dmake is running with -t option, set dmake_mode_type to serial. 776 * This is done because doname() calls touch_command() that runs 777 * serially. 778 * If we do not do that, maketool will have problems. 779 */ 780 if (touch) { 781 dmake_mode_type = serial_mode; 782 no_parallel = true; 783 } 784 #endif 785 #endif 786 787 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && defined(REDIRECT_ERR) 788 /* 789 * Check whether stdout and stderr are physically same. 790 * This is in order to decide whether we need to redirect 791 * stderr separately from stdout. 792 * This check is performed only if __DMAKE_SEPARATE_STDERR 793 * is not set. This variable may be used in order to preserve 794 * the 'old' behaviour. 795 */ 796 out_err_same = true; 797 char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR")); 798 if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) { 799 struct stat stdout_stat; 800 struct stat stderr_stat; 801 if( (fstat(1, &stdout_stat) == 0) 802 && (fstat(2, &stderr_stat) == 0) ) 803 { 804 if( (stdout_stat.st_dev != stderr_stat.st_dev) 805 || (stdout_stat.st_ino != stderr_stat.st_ino) ) 806 { 807 out_err_same = false; 808 } 809 } 810 } 811 #endif 812 813 #ifdef DISTRIBUTED 814 /* 815 * At this point, DMake should startup an rxm with any and all 816 * DMake command line options. Rxm will, among other things, 817 * read the rc file. 818 */ 819 if ((!list_all_targets) && 820 (report_dependencies_level == 0) && 821 (dmake_mode_type == distributed_mode)) { 822 startup_rxm(); 823 } 824 #endif 825 826 /* 827 * Enable interrupt handler for alarms 828 */ 829 (void) bsd_signal(SIGALRM, (SIG_PF)doalarm); 830 831 /* 832 * Check if make should report 833 */ 834 if (getenv(sunpro_dependencies->string_mb) != NULL) { 835 FILE *report_file; 836 837 report_dependency(""); 838 report_file = get_report_file(); 839 if ((report_file != NULL) && (report_file != (FILE*)-1)) { 840 (void) fprintf(report_file, "\n"); 841 } 842 } 843 844 /* 845 * Make sure SUNPRO_DEPENDENCIES is exported (or not) properly 846 * and NSE_DEP. 847 */ 848 if (keep_state) { 849 maybe_append_prop(sunpro_dependencies, macro_prop)-> 850 body.macro.exported = true; 851 #ifdef NSE 852 (void) setenv(NOCATGETS("NSE_DEP"), get_current_path()); 853 #endif 854 } else { 855 maybe_append_prop(sunpro_dependencies, macro_prop)-> 856 body.macro.exported = false; 857 } 858 859 working_on_targets = true; 860 if (trace_status) { 861 dump_make_state(); 862 fclose(stdout); 863 fclose(stderr); 864 exit_status = 0; 865 exit(0); 866 } 867 if (list_all_targets) { 868 dump_target_list(); 869 fclose(stdout); 870 fclose(stderr); 871 exit_status = 0; 872 exit(0); 873 } 874 trace_reader = false; 875 876 /* 877 * Set temp_file_directory to the directory the .make.state 878 * file is written to. 879 */ 880 if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) { 881 temp_file_directory = strdup(get_current_path()); 882 } else { 883 *slash_ptr = (int) nul_char; 884 (void) strcpy(make_state_dir, make_state->string_mb); 885 *slash_ptr = (int) slash_char; 886 /* when there is only one slash and it's the first 887 ** character, make_state_dir should point to '/'. 888 */ 889 if(make_state_dir[0] == '\0') { 890 make_state_dir[0] = '/'; 891 make_state_dir[1] = '\0'; 892 } 893 if (make_state_dir[0] == (int) slash_char) { 894 temp_file_directory = strdup(make_state_dir); 895 } else { 896 char tmp_current_path2[MAXPATHLEN]; 897 898 (void) sprintf(tmp_current_path2, 899 "%s/%s", 900 get_current_path(), 901 make_state_dir); 902 temp_file_directory = strdup(tmp_current_path2); 903 } 904 } 905 906 #ifdef DISTRIBUTED 907 building_serial = false; 908 #endif 909 910 report_dir_enter_leave(true); 911 912 make_targets(argc, argv, parallel_flag); 913 914 report_dir_enter_leave(false); 915 dir_enter_leave(false); 916 917 #ifdef NSE 918 exit(nse_exit_status()); 919 #else 920 if (build_failed_ever_seen) { 921 if (posix) { 922 exit_status = 1; 923 } 924 exit(1); 925 } 926 exit_status = 0; 927 exit(0); 928 #endif 929 /* NOTREACHED */ 930 } 931 932 /* 933 * scan_dmake_compat_mode() 934 * 935 * Called from main(), handles SUN_MAKE_COMPAT_MODE. 936 * 937 * Parameters: 938 * dmake_compat_mode_var The SUN_MAKE_COMPAT_MODE= environ 939 * or the -x SUN_MAKE_COMPAT_MODE= 940 * argument. 941 * 942 * Global variables used: 943 * sunpro_compat 944 * gnu_style 945 * svr4 946 * posix 947 */ 948 static void 949 scan_dmake_compat_mode(char *dmake_compat_mode_var) 950 { 951 if (dmake_compat_mode_var != NULL) { 952 sunpro_compat = true; 953 if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) { 954 sunpro_compat = false; 955 gnu_style = true; 956 svr4 = false; 957 posix = false; 958 } else if (0 == strcasecmp(dmake_compat_mode_var, 959 NOCATGETS("POSIX"))) { 960 sunpro_compat = false; 961 gnu_style = false; 962 svr4 = false; 963 posix = true; 964 } else if (0 == strcasecmp(dmake_compat_mode_var, 965 NOCATGETS("SUN"))) { 966 sunpro_compat = true; 967 gnu_style = false; 968 svr4 = false; 969 posix = false; 970 } else if (0 == strcasecmp(dmake_compat_mode_var, 971 NOCATGETS("SVR4"))) { 972 sunpro_compat = false; 973 gnu_style = false; 974 svr4 = true; 975 posix = false; 976 } 977 //svr4 = false; 978 //posix = false; 979 } 980 } 981 982 /* 983 * cleanup_after_exit() 984 * 985 * Called from exit(), performs cleanup actions. 986 * 987 * Parameters: 988 * status The argument exit() was called with 989 * arg Address of an argument vector to 990 * cleanup_after_exit() 991 * 992 * Global variables used: 993 * command_changed Set if we think .make.state should be rewritten 994 * current_line Is set we set commands_changed 995 * do_not_exec_rule 996 * True if -n flag on 997 * done The Name ".DONE", rule we run 998 * keep_state Set if .KEEP_STATE seen 999 * parallel True if building in parallel 1000 * quest If -q is on we do not run .DONE 1001 * report_dependencies 1002 * True if -P flag on 1003 * running_list List of parallel running processes 1004 * temp_file_name The temp file is removed, if any 1005 * usage_tracking Should have been constructed in main() 1006 * should destroyed just before exiting 1007 */ 1008 #ifdef HAVE_ATEXIT 1009 extern "C" void 1010 cleanup_after_exit(void) 1011 #else 1012 void cleanup_after_exit(int status, ...) 1013 #endif 1014 { 1015 Running rp; 1016 #ifdef NSE 1017 char push_cmd[NSE_TFS_PUSH_LEN + 3 + 1018 (MAXPATHLEN * MB_LEN_MAX) + 12]; 1019 char *active; 1020 #endif 1021 1022 extern long getname_bytes_count; 1023 extern long getname_names_count; 1024 extern long getname_struct_count; 1025 extern long freename_bytes_count; 1026 extern long freename_names_count; 1027 extern long freename_struct_count; 1028 extern long other_alloc; 1029 1030 extern long env_alloc_num; 1031 extern long env_alloc_bytes; 1032 1033 1034 #ifdef DMAKE_STATISTICS 1035 if(getname_stat) { 1036 printf(NOCATGETS(">>> Getname statistics:\n")); 1037 printf(NOCATGETS(" Allocated:\n")); 1038 printf(NOCATGETS(" Names: %ld\n"), getname_names_count); 1039 printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count); 1040 printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count); 1041 printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count); 1042 1043 printf(NOCATGETS("\n Unallocated: %ld\n"), freename_names_count); 1044 printf(NOCATGETS(" Names: %ld\n"), freename_names_count); 1045 printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count); 1046 printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count); 1047 printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count); 1048 1049 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)); 1050 1051 printf(NOCATGETS("\n>>> Other:\n")); 1052 printf( 1053 NOCATGETS(" Env (%ld): %ld Kb (%ld bytes)\n"), 1054 env_alloc_num, 1055 env_alloc_bytes/1000, 1056 env_alloc_bytes 1057 ); 1058 1059 } 1060 #endif 1061 1062 /* 1063 #ifdef DISTRIBUTED 1064 if (get_parent() == TRUE) { 1065 #endif 1066 */ 1067 1068 parallel = false; 1069 #ifdef SUN5_0 1070 /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */ 1071 if (!getenv(USE_SVR4_MAKE)){ 1072 #endif 1073 /* Build the target .DONE or .FAILED if we caught an error */ 1074 if (!quest && !list_all_targets) { 1075 Name failed_name; 1076 1077 MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED")); 1078 failed_name = GETNAME(wcs_buffer, FIND_LENGTH); 1079 #ifdef HAVE_ATEXIT 1080 if ((exit_status != 0) && (failed_name->prop != NULL)) { 1081 #else 1082 if ((status != 0) && (failed_name->prop != NULL)) { 1083 #endif 1084 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1085 /* 1086 * [tolik] switch DMake to serial mode 1087 */ 1088 dmake_mode_type = serial_mode; 1089 no_parallel = true; 1090 #endif 1091 (void) doname(failed_name, false, true); 1092 } else { 1093 if (!trace_status) { 1094 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1095 /* 1096 * Switch DMake to serial mode 1097 */ 1098 dmake_mode_type = serial_mode; 1099 no_parallel = true; 1100 #endif 1101 (void) doname(done, false, true); 1102 } 1103 } 1104 } 1105 #ifdef SUN5_0 1106 } 1107 #endif 1108 /* 1109 * Remove the temp file utilities report dependencies thru if it 1110 * is still around 1111 */ 1112 if (temp_file_name != NULL) { 1113 (void) unlink(temp_file_name->string_mb); 1114 } 1115 /* 1116 * Do not save the current command in .make.state if make 1117 * was interrupted. 1118 */ 1119 if (current_line != NULL) { 1120 command_changed = true; 1121 current_line->body.line.command_used = NULL; 1122 } 1123 /* 1124 * For each parallel build process running, remove the temp files 1125 * and zap the command line so it won't be put in .make.state 1126 */ 1127 for (rp = running_list; rp != NULL; rp = rp->next) { 1128 if (rp->temp_file != NULL) { 1129 (void) unlink(rp->temp_file->string_mb); 1130 } 1131 if (rp->stdout_file != NULL) { 1132 (void) unlink(rp->stdout_file); 1133 retmem_mb(rp->stdout_file); 1134 rp->stdout_file = NULL; 1135 } 1136 if (rp->stderr_file != NULL) { 1137 (void) unlink(rp->stderr_file); 1138 retmem_mb(rp->stderr_file); 1139 rp->stderr_file = NULL; 1140 } 1141 command_changed = true; 1142 /* 1143 line = get_prop(rp->target->prop, line_prop); 1144 if (line != NULL) { 1145 line->body.line.command_used = NULL; 1146 } 1147 */ 1148 } 1149 /* Remove the statefile lock file if the file has been locked */ 1150 if ((make_state_lockfile != NULL) && (make_state_locked)) { 1151 (void) unlink(make_state_lockfile); 1152 make_state_lockfile = NULL; 1153 make_state_locked = false; 1154 } 1155 /* Write .make.state */ 1156 write_state_file(1, (Boolean) 1); 1157 1158 #ifdef TEAMWARE_MAKE_CMN 1159 // Deleting the usage tracking object sends the usage mail 1160 #ifdef USE_DMS_CCR 1161 //usageTracking->setExitStatus(exit_status, NULL); 1162 //delete usageTracking; 1163 #else 1164 cleanup->set_exit_status(exit_status); 1165 delete cleanup; 1166 #endif 1167 #endif 1168 1169 #ifdef NSE 1170 /* If running inside an activated environment, push the */ 1171 /* .nse_depinfo file (if written) */ 1172 active = getenv(NSE_VARIANT_ENV); 1173 if (keep_state && 1174 (active != NULL) && 1175 !IS_EQUAL(active, NSE_RT_SOURCE_NAME) && 1176 !do_not_exec_rule && 1177 (report_dependencies_level == 0)) { 1178 (void) sprintf(push_cmd, 1179 "%s %s/%s", 1180 NSE_TFS_PUSH, 1181 get_current_path(), 1182 NSE_DEPINFO); 1183 (void) system(push_cmd); 1184 } 1185 #endif 1186 1187 /* 1188 #ifdef DISTRIBUTED 1189 } 1190 #endif 1191 */ 1192 1193 #if (defined(TEAMWARE_MAKE_CMN) || defined(PMAKE)) && \ 1194 defined (MAXJOBS_ADJUST_RFE4694000) 1195 job_adjust_fini(); 1196 #endif 1197 1198 #ifdef DISTRIBUTED 1199 if (rxmPid > 0) { 1200 // Tell rxm to exit by sending it an Avo_AcknowledgeMsg 1201 Avo_AcknowledgeMsg acknowledgeMsg; 1202 RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; 1203 1204 int xdrResult = xdr(&xdrs_out, msg); 1205 1206 if (xdrResult) { 1207 fflush(dmake_ofp); 1208 } else { 1209 /* 1210 fatal(gettext("couldn't tell rxm to exit")); 1211 */ 1212 kill(rxmPid, SIGTERM); 1213 } 1214 1215 waitpid(rxmPid, NULL, 0); 1216 rxmPid = 0; 1217 } 1218 #endif 1219 } 1220 1221 /* 1222 * handle_interrupt() 1223 * 1224 * This is where C-C traps are caught. 1225 * 1226 * Parameters: 1227 * 1228 * Global variables used (except DMake 1.0): 1229 * current_target Sometimes the current target is removed 1230 * do_not_exec_rule But not if -n is on 1231 * quest or -q 1232 * running_list List of parallel running processes 1233 * touch Current target is not removed if -t on 1234 */ 1235 void 1236 handle_interrupt(int) 1237 { 1238 Property member; 1239 Running rp; 1240 1241 (void) fflush(stdout); 1242 #ifdef DISTRIBUTED 1243 if (rxmPid > 0) { 1244 // Tell rxm to exit by sending it an Avo_AcknowledgeMsg 1245 Avo_AcknowledgeMsg acknowledgeMsg; 1246 RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; 1247 1248 int xdrResult = xdr(&xdrs_out, msg); 1249 1250 if (xdrResult) { 1251 fflush(dmake_ofp); 1252 } else { 1253 kill(rxmPid, SIGTERM); 1254 rxmPid = 0; 1255 } 1256 } 1257 #endif 1258 if (childPid > 0) { 1259 kill(childPid, SIGTERM); 1260 childPid = -1; 1261 } 1262 for (rp = running_list; rp != NULL; rp = rp->next) { 1263 if (rp->state != build_running) { 1264 continue; 1265 } 1266 if (rp->pid > 0) { 1267 kill(rp->pid, SIGTERM); 1268 rp->pid = -1; 1269 } 1270 } 1271 if (getpid() == getpgrp()) { 1272 #ifdef SUN5_0 1273 bsd_signal(SIGTERM, SIG_IGN); 1274 #else 1275 bsd_signal(SIGTERM, (void (*)(int)) SIG_IGN); 1276 #endif 1277 kill (-getpid(), SIGTERM); 1278 } 1279 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1280 /* Clean up all parallel/distributed children already finished */ 1281 finish_children(false); 1282 #endif 1283 1284 /* Make sure the processes running under us terminate first */ 1285 1286 while (wait((WAIT_T *) NULL) != -1); 1287 /* Delete the current targets unless they are precious or phony */ 1288 if ((current_target != NULL) && 1289 current_target->is_member && 1290 ((member = get_prop(current_target->prop, member_prop)) != NULL)) { 1291 current_target = member->body.member.library; 1292 } 1293 if (!do_not_exec_rule && 1294 !touch && 1295 !quest && 1296 (current_target != NULL) && 1297 !(current_target->stat.is_precious || all_precious || 1298 current_target->stat.is_phony)) { 1299 1300 /* BID_1030811 */ 1301 /* azv 16 Oct 95 */ 1302 current_target->stat.time = file_no_time; 1303 1304 if (exists(current_target) != file_doesnt_exist) { 1305 (void) fprintf(stderr, 1306 "\n*** %s ", 1307 current_target->string_mb); 1308 if (current_target->stat.is_dir) { 1309 (void) fprintf(stderr, 1310 gettext("not removed.\n")); 1311 } else if (unlink(current_target->string_mb) == 0) { 1312 (void) fprintf(stderr, 1313 gettext("removed.\n")); 1314 } else { 1315 (void) fprintf(stderr, 1316 gettext("could not be removed: %s.\n"), 1317 errmsg(errno)); 1318 } 1319 } 1320 } 1321 for (rp = running_list; rp != NULL; rp = rp->next) { 1322 if (rp->state != build_running) { 1323 continue; 1324 } 1325 if (rp->target->is_member && 1326 ((member = get_prop(rp->target->prop, member_prop)) != 1327 NULL)) { 1328 rp->target = member->body.member.library; 1329 } 1330 if (!do_not_exec_rule && 1331 !touch && 1332 !quest && 1333 !(rp->target->stat.is_precious || all_precious || 1334 rp->target->stat.is_phony)) { 1335 1336 rp->target->stat.time = file_no_time; 1337 if (exists(rp->target) != file_doesnt_exist) { 1338 (void) fprintf(stderr, 1339 "\n*** %s ", 1340 rp->target->string_mb); 1341 if (rp->target->stat.is_dir) { 1342 (void) fprintf(stderr, 1343 gettext("not removed.\n")); 1344 } else if (unlink(rp->target->string_mb) == 0) { 1345 (void) fprintf(stderr, 1346 gettext("removed.\n")); 1347 } else { 1348 (void) fprintf(stderr, 1349 gettext("could not be removed: %s.\n"), 1350 errmsg(errno)); 1351 } 1352 } 1353 } 1354 } 1355 1356 #ifdef SGE_SUPPORT 1357 /* Remove SGE script file */ 1358 if (grid) { 1359 unlink(script_file); 1360 } 1361 #endif 1362 1363 /* Have we locked .make.state or .nse_depinfo? */ 1364 if ((make_state_lockfile != NULL) && (make_state_locked)) { 1365 unlink(make_state_lockfile); 1366 make_state_lockfile = NULL; 1367 make_state_locked = false; 1368 } 1369 #ifdef NSE 1370 if ((nse_depinfo_lockfile[0] != '\0') && (nse_depinfo_locked)) { 1371 unlink(nse_depinfo_lockfile); 1372 nse_depinfo_lockfile[0] = '\0'; 1373 nse_depinfo_locked = false; 1374 } 1375 #endif 1376 /* 1377 * Re-read .make.state file (it might be changed by recursive make) 1378 */ 1379 check_state(NULL); 1380 1381 report_dir_enter_leave(false); 1382 1383 exit_status = 2; 1384 exit(2); 1385 } 1386 1387 /* 1388 * doalarm(sig, ...) 1389 * 1390 * Handle the alarm interrupt but do nothing. Side effect is to 1391 * cause return from wait3. 1392 * 1393 * Parameters: 1394 * sig 1395 * 1396 * Global variables used: 1397 */ 1398 /*ARGSUSED*/ 1399 static void 1400 doalarm(int) 1401 { 1402 return; 1403 } 1404 1405 1406 /* 1407 * read_command_options(argc, argv) 1408 * 1409 * Scan the cmd line options and process the ones that start with "-" 1410 * 1411 * Return value: 1412 * -M argument, if any 1413 * 1414 * Parameters: 1415 * argc You know what this is 1416 * argv You know what this is 1417 * 1418 * Global variables used: 1419 */ 1420 static void 1421 read_command_options(register int argc, register char **argv) 1422 { 1423 register int ch; 1424 int current_optind = 1; 1425 int last_optind_with_double_hyphen = 0; 1426 int last_optind; 1427 int last_current_optind; 1428 register int i; 1429 register int j; 1430 register int k; 1431 register int makefile_next = 0; /* 1432 * flag to note options: 1433 * -c, f, g, j, m, o 1434 */ 1435 const char *tptr; 1436 const char *CMD_OPTS; 1437 1438 extern char *optarg; 1439 extern int optind, opterr, optopt; 1440 1441 #define SUNPRO_CMD_OPTS "-~aBbC:c:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:" 1442 1443 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1444 # define SVR4_CMD_OPTS "-C:c:ef:g:ij:km:nO:o:pqrsTtVv" 1445 #else 1446 # define SVR4_CMD_OPTS "-C:ef:iknpqrstV" 1447 #endif 1448 1449 /* 1450 * Added V in SVR4_CMD_OPTS also, which is going to be a hidden 1451 * option, just to make sure that the getopt doesn't fail when some 1452 * users leave their USE_SVR4_MAKE set and try to use the makefiles 1453 * that are designed to issue commands like $(MAKE) -V. Anyway it 1454 * sets the same flag but ensures that getopt doesn't fail. 1455 */ 1456 1457 opterr = 0; 1458 optind = 1; 1459 while (1) { 1460 last_optind=optind; /* Save optind and current_optind values */ 1461 last_current_optind=current_optind; /* in case we have to repeat this round. */ 1462 if (svr4) { 1463 CMD_OPTS=SVR4_CMD_OPTS; 1464 ch = getopt(argc, argv, SVR4_CMD_OPTS); 1465 } else { 1466 CMD_OPTS=SUNPRO_CMD_OPTS; 1467 ch = getopt(argc, argv, SUNPRO_CMD_OPTS); 1468 } 1469 if (ch == EOF) { 1470 if(optind < argc) { 1471 /* 1472 * Fixing bug 4102537: 1473 * Strange behaviour of command make using -- option. 1474 * Not all argv have been processed 1475 * Skip non-flag argv and continue processing. 1476 */ 1477 optind++; 1478 current_optind++; 1479 continue; 1480 } else { 1481 break; 1482 } 1483 1484 } 1485 if (ch == '?') { 1486 if (optopt == '-') { 1487 /* Bug 5060758: getopt() changed behavior (s10_60), 1488 * and now we have to deal with cases when options 1489 * with double hyphen appear here, from -$(MAKEFLAGS) 1490 */ 1491 i = current_optind; 1492 if (argv[i][0] == '-') { 1493 if (argv[i][1] == '-') { 1494 if (argv[i][2] != '\0') { 1495 /* Check if this option is allowed */ 1496 tptr = strchr(CMD_OPTS, argv[i][2]); 1497 if (tptr) { 1498 if (last_optind_with_double_hyphen != current_optind) { 1499 /* This is first time we are trying to fix "--" 1500 * problem with this option. If we come here second 1501 * time, we will go to fatal error. 1502 */ 1503 last_optind_with_double_hyphen = current_optind; 1504 1505 /* Eliminate first hyphen character */ 1506 for (j=0; argv[i][j] != '\0'; j++) { 1507 argv[i][j] = argv[i][j+1]; 1508 } 1509 1510 /* Repeat the processing of this argument */ 1511 optind=last_optind; 1512 current_optind=last_current_optind; 1513 continue; 1514 } 1515 } 1516 } 1517 } 1518 } 1519 } 1520 } 1521 1522 if (ch == '?') { 1523 if (svr4) { 1524 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1525 fprintf(stderr, 1526 gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n")); 1527 fprintf(stderr, 1528 gettext(" [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n")); 1529 fprintf(stderr, 1530 gettext(" [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n")); 1531 #else 1532 fprintf(stderr, 1533 gettext("Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n")); 1534 fprintf(stderr, 1535 gettext(" [ -s ][ -t ]\n")); 1536 #endif 1537 tptr = strchr(SVR4_CMD_OPTS, optopt); 1538 } else { 1539 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 1540 if (IS_EQUAL(argv_zero_base, NOCATGETS("dmake"))) { 1541 fprintf(stderr, 1542 gettext("Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ][ -C directory ]\n")); 1543 fprintf(stderr, 1544 gettext(" [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n")); 1545 fprintf(stderr, 1546 gettext(" [ -a] [ -d ][ -dd ][ -D ][ -DD ]\n")); 1547 fprintf(stderr, 1548 gettext(" [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n")); 1549 fprintf(stderr, 1550 gettext(" [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); 1551 } else 1552 #endif 1553 { 1554 fprintf(stderr, 1555 gettext("Usage : make [ -f makefile ][ -K statefile ]...\n")); 1556 fprintf(stderr, 1557 gettext(" [ -a ][ -d ][ -dd ][ -D ][ -DD ] [ -C directory]\n")); 1558 fprintf(stderr, 1559 gettext(" [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n")); 1560 fprintf(stderr, 1561 gettext(" [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); 1562 } 1563 tptr = strchr(SUNPRO_CMD_OPTS, optopt); 1564 } 1565 if (!tptr) { 1566 fatal(gettext("Unknown option `-%c'"), optopt); 1567 } else { 1568 fatal(gettext("Missing argument after `-%c'"), optopt); 1569 } 1570 } 1571 1572 makefile_next |= parse_command_option(ch); 1573 /* 1574 * If we're done processing all of the options of 1575 * ONE argument string... 1576 */ 1577 if (current_optind < optind) { 1578 i = current_optind; 1579 k = 0; 1580 /* If there's an argument for an option... */ 1581 if ((optind - current_optind) > 1) { 1582 k = i + 1; 1583 } 1584 switch (makefile_next) { 1585 case 0: 1586 argv[i] = NULL; 1587 /* This shouldn't happen */ 1588 if (k) { 1589 argv[k] = NULL; 1590 } 1591 break; 1592 case 1: /* -f seen */ 1593 argv[i] = (char *)NOCATGETS("-f"); 1594 break; 1595 case 2: /* -c seen */ 1596 argv[i] = (char *)NOCATGETS("-c"); 1597 #ifndef TEAMWARE_MAKE_CMN 1598 warning(gettext("Ignoring DistributedMake -c option")); 1599 #endif 1600 break; 1601 case 4: /* -g seen */ 1602 argv[i] = (char *)NOCATGETS("-g"); 1603 #ifndef TEAMWARE_MAKE_CMN 1604 warning(gettext("Ignoring DistributedMake -g option")); 1605 #endif 1606 break; 1607 case 8: /* -j seen */ 1608 if (sunpro_compat) /* Disallow -j5 */ 1609 argv[i] = (char *)NOCATGETS("-j"); 1610 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE) 1611 warning(gettext("Ignoring DistributedMake -j option")); 1612 #endif 1613 break; 1614 case 16: /* -M seen */ 1615 argv[i] = (char *)NOCATGETS("-M"); 1616 #ifndef TEAMWARE_MAKE_CMN 1617 warning(gettext("Ignoring ParallelMake -M option")); 1618 #endif 1619 break; 1620 case 32: /* -m seen */ 1621 argv[i] = (char *)NOCATGETS("-m"); 1622 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE) 1623 warning(gettext("Ignoring DistributedMake -m option")); 1624 #endif 1625 break; 1626 #ifndef PARALLEL 1627 case 128: /* -O seen */ 1628 argv[i] = (char *)NOCATGETS("-O"); 1629 break; 1630 #endif 1631 case 256: /* -K seen */ 1632 argv[i] = (char *)NOCATGETS("-K"); 1633 break; 1634 case 512: /* -o seen */ 1635 argv[i] = (char *)NOCATGETS("-o"); 1636 #ifndef TEAMWARE_MAKE_CMN 1637 warning(gettext("Ignoring DistributedMake -o option")); 1638 #endif 1639 break; 1640 case 1024: /* -x seen */ 1641 argv[i] = (char *)NOCATGETS("-x"); 1642 if (argv[i+1] && 1643 strstr(argv[i+1], 1644 NOCATGETS("SUN_MAKE_COMPAT_MODE=")) == 1645 argv[i+1]) { 1646 if (dmake_add_mode_specified) 1647 dmake_compat_value = argv[i+1]; 1648 else 1649 dmake_compat_value = NULL; 1650 } 1651 #if !defined(TEAMWARE_MAKE_CMN) && !defined(PMAKE) 1652 warning(gettext("Ignoring DistributedMake -x option")); 1653 #endif 1654 break; 1655 case 2048: { 1656 char *ap = argv[i+1]; 1657 1658 if (argv[i][2]) /* e.g. -Cdir */ 1659 ap = &argv[i][2]; 1660 if (ap == NULL) { 1661 fatal(gettext("No argument after -C flag")); 1662 } 1663 if (chdir(ap) != 0) { 1664 fatal(gettext("Failed to change to directory %s: %s"), 1665 ap, strerror(errno)); 1666 } 1667 current_path_reset = true; 1668 } 1669 break; 1670 default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */ 1671 fatal(gettext("Illegal command line. More than one option requiring\nan argument given in the same argument group")); 1672 } 1673 1674 makefile_next = 0; 1675 current_optind = optind; 1676 } 1677 } 1678 } 1679 1680 static void 1681 quote_str(char *str, char *qstr) 1682 { 1683 char *to; 1684 char *from; 1685 1686 to = qstr; 1687 for (from = str; *from; from++) { 1688 switch (*from) { 1689 case ';': /* End of command */ 1690 case '(': /* Start group */ 1691 case ')': /* End group */ 1692 case '{': /* Start group */ 1693 case '}': /* End group */ 1694 case '[': /* Reg expr - any of a set of chars */ 1695 case ']': /* End of set of chars */ 1696 case '|': /* Pipe or logical-or */ 1697 case '^': /* Old-fashioned pipe */ 1698 case '&': /* Background or logical-and */ 1699 case '<': /* Redirect stdin */ 1700 case '>': /* Redirect stdout */ 1701 case '*': /* Reg expr - any sequence of chars */ 1702 case '?': /* Reg expr - any single char */ 1703 case '$': /* Variable substitution */ 1704 case '\'': /* Singe quote - turn off all magic */ 1705 case '"': /* Double quote - span whitespace */ 1706 case '`': /* Backquote - run a command */ 1707 case '#': /* Comment */ 1708 case ' ': /* Space (for MACRO=value1 value2 */ 1709 case '\\': /* Escape char - turn off magic of next char */ 1710 *to++ = '\\'; 1711 break; 1712 1713 default: 1714 break; 1715 } 1716 *to++ = *from; 1717 } 1718 *to = '\0'; 1719 } 1720 1721 static void 1722 unquote_str(char *str, char *qstr) 1723 { 1724 char *to; 1725 char *from; 1726 1727 to = qstr; 1728 for (from = str; *from; from++) { 1729 if (*from == '\\' && from[1] != '\0') { 1730 from++; 1731 } 1732 *to++ = *from; 1733 } 1734 *to = '\0'; 1735 } 1736 1737 /* 1738 * Convert the MAKEFLAGS string value into a vector of char *, similar 1739 * to argv. 1740 */ 1741 static void 1742 setup_makeflags_argv() 1743 { 1744 char *cp; 1745 char *cp1; 1746 char *cp2; 1747 char *cp3; 1748 char *cp_orig; 1749 Boolean add_hyphen; 1750 int i; 1751 char tmp_char; 1752 1753 mf_argc = 1; 1754 cp = getenv(makeflags->string_mb); 1755 cp_orig = cp; 1756 1757 if (cp) { 1758 /* 1759 * If new MAKEFLAGS format, no need to add hyphen. 1760 * If old MAKEFLAGS format, add hyphen before flags. 1761 */ 1762 1763 if ((strchr(cp, (int) hyphen_char) != NULL) || 1764 (strchr(cp, (int) equal_char) != NULL)) { 1765 1766 /* New MAKEFLAGS format */ 1767 1768 add_hyphen = false; 1769 #ifdef ADDFIX5060758 1770 /* Check if MAKEFLAGS value begins with multiple 1771 * hyphen characters, and remove all duplicates. 1772 * Usually it happens when the next command is 1773 * used: $(MAKE) -$(MAKEFLAGS) 1774 * This is a workaround for BugID 5060758. 1775 */ 1776 while (*cp) { 1777 if (*cp != (int) hyphen_char) { 1778 break; 1779 } 1780 cp++; 1781 if (*cp == (int) hyphen_char) { 1782 /* There are two hyphens. Skip one */ 1783 cp_orig = cp; 1784 cp++; 1785 } 1786 if (!(*cp)) { 1787 /* There are hyphens only. Skip all */ 1788 cp_orig = cp; 1789 break; 1790 } 1791 } 1792 #endif 1793 } else { 1794 1795 /* Old MAKEFLAGS format */ 1796 1797 add_hyphen = true; 1798 } 1799 } 1800 1801 /* Find the number of arguments in MAKEFLAGS */ 1802 while (cp && *cp) { 1803 /* Skip white spaces */ 1804 while (cp && *cp && isspace(*cp)) { 1805 cp++; 1806 } 1807 if (cp && *cp) { 1808 /* Increment arg count */ 1809 mf_argc++; 1810 /* Go to next white space */ 1811 while (cp && *cp && !isspace(*cp)) { 1812 if(*cp == (int) backslash_char) { 1813 cp++; 1814 } 1815 cp++; 1816 } 1817 } 1818 } 1819 /* Allocate memory for the new MAKEFLAGS argv */ 1820 mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *)); 1821 mf_argv[0] = (char *)NOCATGETS("MAKEFLAGS"); 1822 /* 1823 * Convert the MAKEFLAGS string value into a vector of char *, 1824 * similar to argv. 1825 */ 1826 cp = cp_orig; 1827 for (i = 1; i < mf_argc; i++) { 1828 /* Skip white spaces */ 1829 while (cp && *cp && isspace(*cp)) { 1830 cp++; 1831 } 1832 if (cp && *cp) { 1833 cp_orig = cp; 1834 /* Go to next white space */ 1835 while (cp && *cp && !isspace(*cp)) { 1836 if(*cp == (int) backslash_char) { 1837 cp++; 1838 } 1839 cp++; 1840 } 1841 tmp_char = *cp; 1842 *cp = (int) nul_char; 1843 if (add_hyphen) { 1844 mf_argv[i] = getmem(2 + strlen(cp_orig)); 1845 mf_argv[i][0] = '\0'; 1846 (void) strcat(mf_argv[i], "-"); 1847 // (void) strcat(mf_argv[i], cp_orig); 1848 unquote_str(cp_orig, mf_argv[i]+1); 1849 } else { 1850 mf_argv[i] = getmem(2 + strlen(cp_orig)); 1851 //mf_argv[i] = strdup(cp_orig); 1852 unquote_str(cp_orig, mf_argv[i]); 1853 } 1854 *cp = tmp_char; 1855 } else { 1856 mf_argv[i] = NULL; 1857 } 1858 } 1859 mf_argv[i] = NULL; 1860 1861 for (i = 1; i < mf_argc; i++) { 1862 if (strncmp(mf_argv[i], NOCATGETS("-C"), 2) == 0) { 1863 int j = i; 1864 1865 /* 1866 * Ignore -C and argument. 1867 */ 1868 if (mf_argv[i][2]) { 1869 j += 1; 1870 mf_argc -= 1; 1871 } else { 1872 j += 2; 1873 mf_argc -= 2; 1874 } 1875 for ( ; i <= mf_argc; i++, j++) 1876 mf_argv[i] = mf_argv[j]; 1877 } 1878 } 1879 } 1880 1881 /* 1882 * parse_command_option(ch) 1883 * 1884 * Parse make command line options. 1885 * 1886 * Return value: 1887 * Indicates if any -f -c or -M were seen 1888 * 1889 * Parameters: 1890 * ch The character to parse 1891 * 1892 * Static variables used: 1893 * dmake_group_specified Set for make -g 1894 * dmake_max_jobs_specified Set for make -j 1895 * dmake_mode_specified Set for make -m 1896 * dmake_add_mode_specified Set for make -x 1897 * dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE= 1898 * dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE= 1899 * dmake_odir_specified Set for make -o 1900 * dmake_rcfile_specified Set for make -c 1901 * env_wins Set for make -e 1902 * ignore_default_mk Set for make -r 1903 * trace_status Set for make -p 1904 * 1905 * Global variables used: 1906 * .make.state path & name set for make -K 1907 * continue_after_error Set for make -k 1908 * debug_level Set for make -d 1909 * do_not_exec_rule Set for make -n 1910 * filter_stderr Set for make -X 1911 * ignore_errors_all Set for make -i 1912 * no_parallel Set for make -R 1913 * quest Set for make -q 1914 * read_trace_level Set for make -D 1915 * report_dependencies Set for make -P 1916 * send_mtool_msgs Set for make -K 1917 * silent_all Set for make -s 1918 * touch Set for make -t 1919 */ 1920 static int 1921 parse_command_option(register char ch) 1922 { 1923 static int invert_next = 0; 1924 int invert_this = invert_next; 1925 1926 invert_next = 0; 1927 switch (ch) { 1928 case '-': /* Ignore "--" */ 1929 return 0; 1930 case '~': /* Invert next option */ 1931 invert_next = 1; 1932 return 0; 1933 #ifdef DO_ARCHCONF 1934 case 'a': /* Do not set up uname, ... vars */ 1935 if (invert_this) { 1936 no_archconf = false; 1937 } else { 1938 no_archconf = true; 1939 } 1940 return 0; 1941 #endif 1942 case 'B': /* Obsolete */ 1943 return 0; 1944 case 'b': /* Obsolete */ 1945 return 0; 1946 case 'c': /* Read alternative dmakerc file */ 1947 if (invert_this) { 1948 dmake_rcfile_specified = false; 1949 } else { 1950 dmake_rcfile_specified = true; 1951 } 1952 return 2; 1953 case 'C': /* Change directory */ 1954 return 2048; 1955 case 'D': /* Show lines read */ 1956 if (invert_this) { 1957 read_trace_level--; 1958 } else { 1959 read_trace_level++; 1960 } 1961 return 0; 1962 case 'd': /* Debug flag */ 1963 if (invert_this) { 1964 debug_level--; 1965 } else { 1966 #if defined( HP_UX) || defined(linux) 1967 if (debug_level < 2) /* Fixes a bug on HP-UX */ 1968 #endif 1969 debug_level++; 1970 } 1971 return 0; 1972 #ifdef NSE 1973 case 'E': 1974 if (invert_this) { 1975 nse = false; 1976 } else { 1977 nse = true; 1978 } 1979 nse_init_source_suffixes(); 1980 return 0; 1981 #endif 1982 case 'e': /* Environment override flag */ 1983 if (invert_this) { 1984 env_wins = false; 1985 } else { 1986 env_wins = true; 1987 } 1988 return 0; 1989 case 'f': /* Read alternative makefile(s) */ 1990 return 1; 1991 case 'g': /* Use alternative DMake group */ 1992 if (invert_this) { 1993 dmake_group_specified = false; 1994 } else { 1995 dmake_group_specified = true; 1996 } 1997 return 4; 1998 case 'i': /* Ignore errors */ 1999 if (invert_this) { 2000 ignore_errors_all = false; 2001 } else { 2002 ignore_errors_all = true; 2003 } 2004 return 0; 2005 case 'j': /* Use alternative DMake max jobs */ 2006 if (invert_this) { 2007 dmake_max_jobs_specified = false; 2008 } else { 2009 dmake_max_jobs_specified = true; 2010 } 2011 return 8; 2012 case 'K': /* Read alternative .make.state */ 2013 return 256; 2014 case 'k': /* Keep making even after errors */ 2015 if (invert_this) { 2016 continue_after_error = false; 2017 } else { 2018 continue_after_error = true; 2019 continue_after_error_ever_seen = true; 2020 } 2021 return 0; 2022 case 'M': /* Read alternative make.machines file */ 2023 if (invert_this) { 2024 pmake_machinesfile_specified = false; 2025 } else { 2026 pmake_machinesfile_specified = true; 2027 dmake_mode_type = parallel_mode; 2028 no_parallel = false; 2029 } 2030 return 16; 2031 case 'm': /* Use alternative DMake build mode */ 2032 if (invert_this) { 2033 dmake_mode_specified = false; 2034 } else { 2035 dmake_mode_specified = true; 2036 } 2037 return 32; 2038 case 'x': /* Use alternative DMake mode */ 2039 if (invert_this) { 2040 dmake_add_mode_specified = false; 2041 } else { 2042 dmake_add_mode_specified = true; 2043 } 2044 return 1024; 2045 case 'N': /* Reverse -n */ 2046 if (invert_this) { 2047 do_not_exec_rule = true; 2048 } else { 2049 do_not_exec_rule = false; 2050 } 2051 return 0; 2052 case 'n': /* Print, not exec commands */ 2053 if (invert_this) { 2054 do_not_exec_rule = false; 2055 } else { 2056 do_not_exec_rule = true; 2057 } 2058 return 0; 2059 #ifndef PARALLEL 2060 case 'O': /* Send job start & result msgs */ 2061 if (invert_this) { 2062 send_mtool_msgs = false; 2063 } else { 2064 #ifdef DISTRIBUTED 2065 send_mtool_msgs = true; 2066 #endif 2067 } 2068 return 128; 2069 #endif 2070 case 'o': /* Use alternative dmake output dir */ 2071 if (invert_this) { 2072 dmake_odir_specified = false; 2073 } else { 2074 dmake_odir_specified = true; 2075 } 2076 return 512; 2077 case 'P': /* Print for selected targets */ 2078 if (invert_this) { 2079 report_dependencies_level--; 2080 } else { 2081 report_dependencies_level++; 2082 } 2083 return 0; 2084 case 'p': /* Print description */ 2085 if (invert_this) { 2086 trace_status = false; 2087 do_not_exec_rule = false; 2088 } else { 2089 trace_status = true; 2090 do_not_exec_rule = true; 2091 } 2092 return 0; 2093 case 'q': /* Question flag */ 2094 if (invert_this) { 2095 quest = false; 2096 } else { 2097 quest = true; 2098 } 2099 return 0; 2100 case 'R': /* Don't run in parallel */ 2101 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 2102 if (invert_this) { 2103 pmake_cap_r_specified = false; 2104 no_parallel = false; 2105 } else { 2106 pmake_cap_r_specified = true; 2107 dmake_mode_type = serial_mode; 2108 no_parallel = true; 2109 } 2110 #else 2111 warning(gettext("Ignoring ParallelMake -R option")); 2112 #endif 2113 return 0; 2114 case 'r': /* Turn off internal rules */ 2115 if (invert_this) { 2116 ignore_default_mk = false; 2117 } else { 2118 ignore_default_mk = true; 2119 } 2120 return 0; 2121 case 'S': /* Reverse -k */ 2122 if (invert_this) { 2123 continue_after_error = true; 2124 } else { 2125 continue_after_error = false; 2126 stop_after_error_ever_seen = true; 2127 } 2128 return 0; 2129 case 's': /* Silent flag */ 2130 if (invert_this) { 2131 silent_all = false; 2132 } else { 2133 silent_all = true; 2134 } 2135 return 0; 2136 case 'T': /* Print target list */ 2137 if (invert_this) { 2138 list_all_targets = false; 2139 do_not_exec_rule = false; 2140 } else { 2141 list_all_targets = true; 2142 do_not_exec_rule = true; 2143 } 2144 return 0; 2145 case 't': /* Touch flag */ 2146 if (invert_this) { 2147 touch = false; 2148 } else { 2149 touch = true; 2150 } 2151 return 0; 2152 case 'u': /* Unconditional flag */ 2153 if (invert_this) { 2154 build_unconditional = false; 2155 } else { 2156 build_unconditional = true; 2157 } 2158 return 0; 2159 case 'V': /* SVR4 mode */ 2160 svr4 = true; 2161 return 0; 2162 case 'v': /* Version flag */ 2163 if (invert_this) { 2164 } else { 2165 #ifdef TEAMWARE_MAKE_CMN 2166 fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring); 2167 #ifdef SUN5_0 2168 exit_status = 0; 2169 #endif 2170 exit(0); 2171 #else 2172 #if defined(SCHILY_BUILD) || defined(SCHILY_INCLUDES) 2173 fprintf(stdout, NOCATGETS("%s: %s\n"), 2174 argv_zero_base, verstring); 2175 fprintf(stdout, "\n"); 2176 fprintf(stdout, "Copyright (C) 1987-2006 Sun Microsystems\n"); 2177 fprintf(stdout, "Copyright (C) 1996-2021 Joerg Schilling\n"); 2178 exit_status = 0; 2179 exit(0); 2180 #else 2181 warning(gettext("Ignoring DistributedMake -v option")); 2182 #endif 2183 #endif 2184 } 2185 return 0; 2186 case 'w': /* Report working directory flag */ 2187 if (invert_this) { 2188 report_cwd = false; 2189 } else { 2190 report_cwd = true; 2191 } 2192 return 0; 2193 #if 0 2194 case 'X': /* Filter stdout */ 2195 if (invert_this) { 2196 filter_stderr = false; 2197 } else { 2198 filter_stderr = true; 2199 } 2200 return 0; 2201 #endif 2202 default: 2203 break; 2204 } 2205 return 0; 2206 } 2207 2208 /* 2209 * setup_for_projectdir() 2210 * 2211 * Read the PROJECTDIR variable, if defined, and set the sccs path 2212 * 2213 * Parameters: 2214 * 2215 * Global variables used: 2216 * sccs_dir_path Set to point to SCCS dir to use 2217 */ 2218 static void 2219 setup_for_projectdir(void) 2220 { 2221 static char path[MAXPATHLEN]; 2222 char cwdpath[MAXPATHLEN]; 2223 uid_t uid; 2224 int done=0; 2225 2226 /* Check if we should use PROJECTDIR when reading the SCCS dir. */ 2227 sccs_dir_path = getenv(NOCATGETS("PROJECTDIR")); 2228 if ((sccs_dir_path != NULL) && 2229 (sccs_dir_path[0] != (int) slash_char)) { 2230 struct passwd *pwent; 2231 2232 { 2233 uid = getuid(); 2234 pwent = getpwuid(uid); 2235 if (pwent == NULL) { 2236 fatal(gettext("Bogus USERID ")); 2237 } 2238 if ((pwent = getpwnam(sccs_dir_path)) == NULL) { 2239 /*empty block : it'll go & check cwd */ 2240 } 2241 else { 2242 (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir); 2243 if (access(path, F_OK) == 0) { 2244 sccs_dir_path = path; 2245 done = 1; 2246 } else { 2247 (void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir); 2248 if (access(path, F_OK) == 0) { 2249 sccs_dir_path = path; 2250 done = 1; 2251 } 2252 } 2253 } 2254 if (!done) { 2255 if (getcwd(cwdpath, MAXPATHLEN - 1 )) { 2256 2257 (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path); 2258 if (access(path, F_OK) == 0) { 2259 sccs_dir_path = path; 2260 done = 1; 2261 } else { 2262 fatal(gettext("Bogus PROJECTDIR '%s'"), sccs_dir_path); 2263 } 2264 } 2265 } 2266 } 2267 } 2268 } 2269 2270 static char * 2271 append_to_env(const char *env, const char *value, const char *deflt) 2272 { 2273 size_t len; 2274 char *oldpath = getenv(env); 2275 char *newpath; 2276 2277 if (value == NULL) 2278 value = deflt; 2279 2280 if (oldpath == NULL) { 2281 len = strlen(env) + 1 + 2282 strlen(value) + 1; 2283 newpath = (char *) malloc(len); 2284 if (newpath) 2285 sprintf(newpath, "%s=", env); 2286 } else { 2287 len = strlen(env) + 1 + strlen(oldpath) + 1 + 2288 strlen(value) + 1; 2289 newpath = (char *) malloc(len); 2290 if (newpath) 2291 sprintf(newpath, "%s=%s", env, oldpath); 2292 } 2293 if (newpath == NULL) 2294 return (newpath); 2295 2296 #if defined(TEAMWARE_MAKE_CMN) 2297 2298 /* function maybe_append_str_to_env_var() is defined in avo_util library 2299 * Serial make should not use this library !!! 2300 */ 2301 maybe_append_str_to_env_var(newpath, value); 2302 #else 2303 if (oldpath == NULL) { 2304 strcat(newpath, value); 2305 } else { 2306 strcat(newpath, ":"); 2307 strcat(newpath, value); 2308 } 2309 #endif 2310 2311 return (newpath); 2312 } 2313 2314 static char * 2315 get_run_lib(const char *run_dir, const char *subdir) 2316 { 2317 size_t len; 2318 char *lib; 2319 struct stat stb; 2320 2321 if (run_dir == NULL) 2322 return (NULL); 2323 2324 len = strlen(run_dir) + 1 + 5 /* Nul + strlen("/lib/") */ 2325 + (subdir ? strlen(subdir) : 0) 2326 + strlen(LD_SUPPORT_MAKE_LIB); 2327 lib = (char *) malloc(len); 2328 if (lib) { 2329 strcpy(lib, run_dir); 2330 strcat(lib, "/lib/"); 2331 if (subdir) 2332 strcat(lib, subdir); 2333 strcat(lib, LD_SUPPORT_MAKE_LIB); 2334 if (stat(lib, &stb) < 0) { 2335 free(lib); 2336 lib = NULL; 2337 } 2338 } 2339 #ifdef LD_SUPPORT_MAKE_ARCH 2340 if (lib == NULL) { /* Try tools path */ 2341 len += 3 + strlen(LD_SUPPORT_MAKE_ARCH); 2342 2343 lib = (char *) malloc(len); 2344 if (lib) { 2345 /* 2346 * OpenSolaris ON tools path: 2347 * tools/..../bin/i386/make 2348 * tools/..../lib/i386/libmakestate.so.1 2349 * or 2350 * tools/..../lib/i386/64/libmakestate.so.1 2351 */ 2352 strcpy(lib, run_dir); 2353 strcat(lib, "/../lib/"); 2354 strcat(lib, LD_SUPPORT_MAKE_ARCH); 2355 if (subdir) 2356 strcat(lib, subdir); 2357 strcat(lib, LD_SUPPORT_MAKE_LIB); 2358 if (stat(lib, &stb) < 0) { 2359 free(lib); 2360 lib = NULL; 2361 } 2362 } 2363 } 2364 #endif 2365 return (lib); 2366 } 2367 2368 /* 2369 * set_sgs_support() 2370 * 2371 * Add the libmakestate.so.1 lib to the env var SGS_SUPPORT 2372 * if it's not already in there. 2373 * The SGS_SUPPORT env var and libmakestate.so.1 is used by 2374 * the linker ld to report .make.state info back to make. 2375 * 2376 * In case there is a slash in the path for libmakestate.so.1, 2377 * we cannot use SGS_SUPPORT, but need SGS_SUPPORT_32 and SGS_SUPPORT_64. 2378 * 2379 * If SGS_SUPPORT_32 or SGS_SUPPORT_64 is present, we manage these 2380 * variables as well. 2381 */ 2382 static void 2383 set_sgs_support() 2384 { 2385 char *newpath; 2386 char *lib; 2387 static char *prev_path; 2388 static char *prev_path_32; 2389 static char *prev_path_64; 2390 char *run_dir = strdup(make_run_dir); 2391 2392 if (run_dir && strstr(run_dir, "xpg4/bin")) 2393 run_dir = dirname(run_dir); /* Strip last dir component */ 2394 run_dir = dirname(run_dir); /* Strip last dir component */ 2395 2396 lib = get_run_lib(run_dir, NULL); 2397 newpath = append_to_env(LD_SUPPORT_ENV_VAR, lib, LD_SUPPORT_MAKE_LIB); 2398 2399 /* 2400 * Newer Solaris linker versions may switch to 64 bit binaries. 2401 * A simple SGS_SUPPORT entry would not work in case it contains 2402 * a slash. So do not create a SGS_SUPPORT entry in this case but 2403 * rather directly create SGS_SUPPORT_32 and SGS_SUPPORT_64. 2404 */ 2405 if (newpath && strchr(newpath, (int) slash_char)) { 2406 free(newpath); 2407 if (lib) 2408 free(lib); 2409 goto need_specific; 2410 } 2411 2412 if (newpath) 2413 putenv(newpath); 2414 if (prev_path) { 2415 free(prev_path); 2416 } 2417 prev_path = newpath; 2418 if (lib) 2419 free(lib); 2420 2421 if (getenv(LD_SUPPORT_ENV_VAR_32) == NULL && 2422 getenv(LD_SUPPORT_ENV_VAR_64) == NULL) 2423 return; 2424 2425 need_specific: 2426 2427 lib = get_run_lib(run_dir, NULL); 2428 newpath = append_to_env(LD_SUPPORT_ENV_VAR_32, lib, LD_SUPPORT_MAKE_LIB); 2429 2430 if (newpath) 2431 putenv(newpath); 2432 if (prev_path_32) { 2433 free(prev_path_32); 2434 } 2435 prev_path_32 = newpath; 2436 if (lib) 2437 free(lib); 2438 2439 lib = get_run_lib(run_dir, "64/"); 2440 newpath = append_to_env(LD_SUPPORT_ENV_VAR_64, lib, LD_SUPPORT_MAKE_LIB); 2441 2442 if (newpath) 2443 putenv(newpath); 2444 if (prev_path_64) { 2445 free(prev_path_64); 2446 } 2447 prev_path_64 = newpath; 2448 if (lib) 2449 free(lib); 2450 } 2451 2452 /* 2453 * read_files_and_state(argc, argv) 2454 * 2455 * Read the makefiles we care about and the environment 2456 * Also read the = style command line options 2457 * 2458 * Parameters: 2459 * argc You know what this is 2460 * argv You know what this is 2461 * 2462 * Static variables used: 2463 * env_wins make -e, determines if env vars are RO 2464 * ignore_default_mk make -r, determines if make.rules is read 2465 * not_auto_depen dwight 2466 * 2467 * Global variables used: 2468 * default_target_to_build Set to first proper target from file 2469 * do_not_exec_rule Set to false when makfile is made 2470 * dot The Name ".", used to read current dir 2471 * empty_name The Name "", use as macro value 2472 * keep_state Set if KEEP_STATE is in environment 2473 * make_state The Name ".make.state", used to read file 2474 * makefile_type Set to type of file being read 2475 * makeflags The Name "MAKEFLAGS", used to set macro value 2476 * not_auto dwight 2477 * nse Set if NSE_ENV is in the environment 2478 * read_trace_level Checked to se if the reader should trace 2479 * report_dependencies If -P is on we do not read .make.state 2480 * trace_reader Set if reader should trace 2481 * virtual_root The Name "VIRTUAL_ROOT", used to check value 2482 */ 2483 static void 2484 read_files_and_state(int argc, char **argv) 2485 { 2486 wchar_t buffer[1000]; 2487 wchar_t buffer_posix[1000]; 2488 register char ch; 2489 register char *cp; 2490 Property def_make_macro = NULL; 2491 Name def_make_name; 2492 Name default_makefile; 2493 String_rec dest; 2494 wchar_t destbuffer[STRING_BUFFER_LENGTH]; 2495 register int i; 2496 register int j; 2497 Name keep_state_name; 2498 int length; 2499 Name Makefile; 2500 register Property macro; 2501 struct stat make_state_stat; 2502 Name makefile_name; 2503 register int makefile_next = 0; 2504 register Boolean makefile_read = false; 2505 String_rec makeflags_string; 2506 String_rec makeflags_string_posix; 2507 String_rec * makeflags_string_current; 2508 Name makeflags_value_saved; 2509 register Name name; 2510 Name new_make_value; 2511 Boolean save_do_not_exec_rule; 2512 Name sdotMakefile; 2513 Name sdotmakefile_name; 2514 static wchar_t state_file_str; 2515 static char state_file_str_mb[MAXPATHLEN]; 2516 static struct _Name state_filename; 2517 Boolean temp; 2518 char tmp_char; 2519 wchar_t *tmp_wcs_buffer; 2520 register Name value; 2521 ASCII_Dyn_Array makeflags_and_macro; 2522 Boolean is_xpg4; 2523 2524 /* 2525 * Remember current mode. It may be changed after reading makefile 2526 * and we will have to correct MAKEFLAGS variable. 2527 */ 2528 is_xpg4 = posix; 2529 2530 MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE")); 2531 keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH); 2532 MBSTOWCS(wcs_buffer, NOCATGETS("Makefile")); 2533 Makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2534 MBSTOWCS(wcs_buffer, NOCATGETS("makefile")); 2535 makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); 2536 MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile")); 2537 sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH); 2538 MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile")); 2539 sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH); 2540 2541 /* 2542 * Set flag if NSE is active 2543 */ 2544 #ifdef NSE 2545 if (getenv(NOCATGETS("NSE_ENV")) != NULL) { 2546 nse = true; 2547 } 2548 #endif 2549 2550 /* 2551 * initialize global dependency entry for .NOT_AUTO 2552 */ 2553 not_auto_depen->next = NULL; 2554 not_auto_depen->name = not_auto; 2555 not_auto_depen->automatic = not_auto_depen->stale = false; 2556 2557 /* 2558 * Read internal definitions and rules. 2559 */ 2560 if (read_trace_level > 1) { 2561 trace_reader = true; 2562 } 2563 if (!ignore_default_mk) { 2564 #if defined(SUN5_0) || defined(HP_UX) || defined(linux) 2565 if (svr4) { 2566 MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules")); 2567 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2568 } else { 2569 MBSTOWCS(wcs_buffer, NOCATGETS("make.rules")); 2570 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2571 } 2572 #else 2573 MBSTOWCS(wcs_buffer, NOCATGETS("default.mk")); 2574 default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2575 #endif 2576 default_makefile->stat.is_file = true; 2577 2578 (void) read_makefile(default_makefile, 2579 true, 2580 false, 2581 true); 2582 } 2583 2584 /* 2585 * If the user did not redefine the MAKE macro in the 2586 * default makefile (make.rules), then we'd like to 2587 * change the macro value of MAKE to be some form 2588 * of argv[0] for recursive MAKE builds. 2589 * Since POSIX claims for the option -r: 2590 * Clear the suffix list and do not use the built-in rules. 2591 * $(MAKE) should not be affected by -r. We need to provide a 2592 * useful default in case $(MAKE) has not been defined at all. 2593 */ 2594 MBSTOWCS(wcs_buffer, NOCATGETS("MAKE")); 2595 def_make_name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2596 def_make_macro = get_prop(def_make_name->prop, macro_prop); 2597 if ((def_make_macro == NULL) || 2598 ((def_make_macro != NULL) && 2599 (IS_EQUAL(def_make_macro->body.macro.value->string_mb, 2600 NOCATGETS("make"))))) { 2601 MBSTOWCS(wcs_buffer, argv_zero_string); 2602 new_make_value = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 2603 (void) SETVAR(def_make_name, 2604 new_make_value, 2605 false); 2606 } 2607 2608 #ifdef DO_MAKE_NAME 2609 if (!sunpro_compat && !svr4) { 2610 MBSTOWCS(wcs_buffer, NOCATGETS("sunpro")); 2611 SETVAR(sunpro_make_name, 2612 GETNAME(wcs_buffer, FIND_LENGTH), 2613 false); 2614 } 2615 #endif 2616 #ifdef DO_ARCHCONF 2617 if (!sunpro_compat && !svr4 && !no_archconf) { 2618 setup_arch(); 2619 } 2620 #endif 2621 2622 default_target_to_build = NULL; 2623 trace_reader = false; 2624 2625 /* 2626 * Read environment args. Let file args which follow override unless 2627 * -e option seen. If -e option is not mentioned. 2628 */ 2629 read_environment(env_wins); 2630 if (getvar(virtual_root)->hash.length == 0) { 2631 maybe_append_prop(virtual_root, macro_prop) 2632 ->body.macro.exported = true; 2633 MBSTOWCS(wcs_buffer, "/"); 2634 (void) SETVAR(virtual_root, 2635 GETNAME(wcs_buffer, FIND_LENGTH), 2636 false); 2637 } 2638 2639 /* 2640 * We now scan mf_argv and argv to see if we need to set 2641 * any of the DMake-added options/variables in MAKEFLAGS. 2642 */ 2643 2644 makeflags_and_macro.start = 0; 2645 makeflags_and_macro.size = 0; 2646 enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro); 2647 enter_argv_values(argc, argv, &makeflags_and_macro); 2648 2649 /* 2650 * Set MFLAGS and MAKEFLAGS 2651 * 2652 * Before reading makefile we do not know exactly which mode 2653 * (posix or not) is used. So prepare two MAKEFLAGS strings 2654 * for both posix and solaris modes because they are different. 2655 */ 2656 INIT_STRING_FROM_STACK(makeflags_string, buffer); 2657 INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix); 2658 append_char((int) hyphen_char, &makeflags_string); 2659 append_char((int) hyphen_char, &makeflags_string_posix); 2660 2661 #ifdef DO_ARCHCONF 2662 if (no_archconf) { 2663 append_char('a', &makeflags_string); 2664 append_char('a', &makeflags_string_posix); 2665 } 2666 #endif 2667 switch (read_trace_level) { 2668 case 2: 2669 append_char('D', &makeflags_string); 2670 append_char('D', &makeflags_string_posix); 2671 case 1: 2672 append_char('D', &makeflags_string); 2673 append_char('D', &makeflags_string_posix); 2674 } 2675 switch (debug_level) { 2676 case 2: 2677 append_char('d', &makeflags_string); 2678 append_char('d', &makeflags_string_posix); 2679 case 1: 2680 append_char('d', &makeflags_string); 2681 append_char('d', &makeflags_string_posix); 2682 } 2683 #ifdef NSE 2684 if (nse) { 2685 append_char('E', &makeflags_string); 2686 } 2687 #endif 2688 if (env_wins) { 2689 append_char('e', &makeflags_string); 2690 append_char('e', &makeflags_string_posix); 2691 } 2692 if (ignore_errors_all) { 2693 append_char('i', &makeflags_string); 2694 append_char('i', &makeflags_string_posix); 2695 } 2696 if (continue_after_error) { 2697 if (stop_after_error_ever_seen) { 2698 append_char('S', &makeflags_string_posix); 2699 append_char((int) space_char, &makeflags_string_posix); 2700 append_char((int) hyphen_char, &makeflags_string_posix); 2701 } 2702 append_char('k', &makeflags_string); 2703 append_char('k', &makeflags_string_posix); 2704 } else { 2705 if (stop_after_error_ever_seen 2706 && continue_after_error_ever_seen) { 2707 append_char('k', &makeflags_string_posix); 2708 append_char((int) space_char, &makeflags_string_posix); 2709 append_char((int) hyphen_char, &makeflags_string_posix); 2710 append_char('S', &makeflags_string_posix); 2711 } 2712 } 2713 if (do_not_exec_rule) { 2714 append_char('n', &makeflags_string); 2715 append_char('n', &makeflags_string_posix); 2716 } 2717 switch (report_dependencies_level) { 2718 case 4: 2719 append_char('P', &makeflags_string); 2720 append_char('P', &makeflags_string_posix); 2721 case 3: 2722 append_char('P', &makeflags_string); 2723 append_char('P', &makeflags_string_posix); 2724 case 2: 2725 append_char('P', &makeflags_string); 2726 append_char('P', &makeflags_string_posix); 2727 case 1: 2728 append_char('P', &makeflags_string); 2729 append_char('P', &makeflags_string_posix); 2730 } 2731 if (trace_status) { 2732 append_char('p', &makeflags_string); 2733 append_char('p', &makeflags_string_posix); 2734 } 2735 if (quest) { 2736 append_char('q', &makeflags_string); 2737 append_char('q', &makeflags_string_posix); 2738 } 2739 if (ignore_default_mk) { 2740 append_char('r', &makeflags_string); 2741 append_char('r', &makeflags_string_posix); 2742 } 2743 if (silent_all) { 2744 append_char('s', &makeflags_string); 2745 append_char('s', &makeflags_string_posix); 2746 } 2747 if (touch) { 2748 append_char('t', &makeflags_string); 2749 append_char('t', &makeflags_string_posix); 2750 } 2751 if (build_unconditional) { 2752 append_char('u', &makeflags_string); 2753 append_char('u', &makeflags_string_posix); 2754 } 2755 if (report_cwd) { 2756 append_char('w', &makeflags_string); 2757 append_char('w', &makeflags_string_posix); 2758 } 2759 #ifndef PARALLEL 2760 /* -c dmake_rcfile */ 2761 if (dmake_rcfile_specified) { 2762 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); 2763 dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH); 2764 append_makeflags_string(dmake_rcfile, &makeflags_string); 2765 append_makeflags_string(dmake_rcfile, &makeflags_string_posix); 2766 } 2767 /* -g dmake_group */ 2768 if (dmake_group_specified) { 2769 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); 2770 dmake_group = GETNAME(wcs_buffer, FIND_LENGTH); 2771 append_makeflags_string(dmake_group, &makeflags_string); 2772 append_makeflags_string(dmake_group, &makeflags_string_posix); 2773 } 2774 /* -j dmake_max_jobs */ 2775 if (dmake_max_jobs_specified) { 2776 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); 2777 dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH); 2778 append_makeflags_string(dmake_max_jobs, &makeflags_string); 2779 append_makeflags_string(dmake_max_jobs, &makeflags_string_posix); 2780 } 2781 /* -m dmake_mode */ 2782 if (dmake_mode_specified) { 2783 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); 2784 dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2785 append_makeflags_string(dmake_mode, &makeflags_string); 2786 append_makeflags_string(dmake_mode, &makeflags_string_posix); 2787 } 2788 /* -x dmake_compat_mode */ 2789 if (dmake_compat_mode_specified) { 2790 MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); 2791 dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2792 append_makeflags_string(dmake_compat_mode, &makeflags_string); 2793 append_makeflags_string(dmake_compat_mode, &makeflags_string_posix); 2794 } 2795 /* -x dmake_output_mode */ 2796 if (dmake_output_mode_specified) { 2797 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); 2798 dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH); 2799 append_makeflags_string(dmake_output_mode, &makeflags_string); 2800 append_makeflags_string(dmake_output_mode, &makeflags_string_posix); 2801 } 2802 /* -o dmake_odir */ 2803 if (dmake_odir_specified) { 2804 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); 2805 dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH); 2806 append_makeflags_string(dmake_odir, &makeflags_string); 2807 append_makeflags_string(dmake_odir, &makeflags_string_posix); 2808 } 2809 /* -M pmake_machinesfile */ 2810 if (pmake_machinesfile_specified) { 2811 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); 2812 pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH); 2813 append_makeflags_string(pmake_machinesfile, &makeflags_string); 2814 append_makeflags_string(pmake_machinesfile, &makeflags_string_posix); 2815 } 2816 /* -R */ 2817 if (pmake_cap_r_specified) { 2818 append_char((int) space_char, &makeflags_string); 2819 append_char((int) hyphen_char, &makeflags_string); 2820 append_char('R', &makeflags_string); 2821 append_char((int) space_char, &makeflags_string_posix); 2822 append_char((int) hyphen_char, &makeflags_string_posix); 2823 append_char('R', &makeflags_string_posix); 2824 } 2825 #endif 2826 2827 /* 2828 * Make sure MAKEFLAGS is exported 2829 */ 2830 maybe_append_prop(makeflags, macro_prop)-> 2831 body.macro.exported = true; 2832 2833 if (makeflags_string.buffer.start[1] != (int) nul_char) { 2834 if (makeflags_string.buffer.start[1] != (int) space_char) { 2835 MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS")); 2836 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2837 GETNAME(makeflags_string.buffer.start, 2838 FIND_LENGTH), 2839 false); 2840 } else { 2841 MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS")); 2842 (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), 2843 GETNAME(makeflags_string.buffer.start + 2, 2844 FIND_LENGTH), 2845 false); 2846 } 2847 } 2848 2849 /* 2850 * Add command line macro to POSIX makeflags_string 2851 */ 2852 if (makeflags_and_macro.start) { 2853 tmp_char = (char) space_char; 2854 cp = makeflags_and_macro.start; 2855 do { 2856 if (!sunpro_compat && !svr4) 2857 append_char(tmp_char, &makeflags_string); 2858 append_char(tmp_char, &makeflags_string_posix); 2859 } while ((tmp_char = *cp++) != '\0'); 2860 retmem_mb(makeflags_and_macro.start); 2861 } 2862 2863 /* 2864 * Now set the value of MAKEFLAGS macro in accordance 2865 * with current mode. 2866 */ 2867 macro = maybe_append_prop(makeflags, macro_prop); 2868 temp = (Boolean) macro->body.macro.read_only; 2869 macro->body.macro.read_only = false; 2870 if(posix || gnu_style) { 2871 makeflags_string_current = &makeflags_string_posix; 2872 } else { 2873 makeflags_string_current = &makeflags_string; 2874 } 2875 if (makeflags_string_current->buffer.start[1] == (int) nul_char) { 2876 makeflags_value_saved = 2877 GETNAME( makeflags_string_current->buffer.start + 1 2878 , FIND_LENGTH 2879 ); 2880 } else { 2881 if (makeflags_string_current->buffer.start[1] != (int) space_char) { 2882 makeflags_value_saved = 2883 GETNAME( makeflags_string_current->buffer.start 2884 , FIND_LENGTH 2885 ); 2886 } else { 2887 makeflags_value_saved = 2888 GETNAME( makeflags_string_current->buffer.start + 2 2889 , FIND_LENGTH 2890 ); 2891 } 2892 } 2893 (void) SETVAR( makeflags 2894 , makeflags_value_saved 2895 , false 2896 ); 2897 macro->body.macro.read_only = temp; 2898 2899 /* 2900 * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args. 2901 */ 2902 save_do_not_exec_rule = do_not_exec_rule; 2903 do_not_exec_rule = false; 2904 if (read_trace_level > 0) { 2905 trace_reader = true; 2906 } 2907 2908 for (i = 1; i < argc; i++) { 2909 if (argv[i] && 2910 (argv[i][0] == (int) hyphen_char) && 2911 (argv[i][1] == 'f') && 2912 (argv[i][2] == (int) nul_char)) { 2913 argv[i] = NULL; /* Remove -f */ 2914 if (i >= argc - 1) { 2915 fatal(gettext("No filename argument after -f flag")); 2916 } 2917 MBSTOWCS(wcs_buffer, argv[++i]); 2918 primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH); 2919 (void) read_makefile(primary_makefile, true, true, true); 2920 argv[i] = NULL; /* Remove filename */ 2921 makefile_read = true; 2922 } else if (argv[i] && 2923 (argv[i][0] == (int) hyphen_char) && 2924 (argv[i][1] == 'C' || 2925 argv[i][1] == 'c' || 2926 argv[i][1] == 'g' || 2927 argv[i][1] == 'j' || 2928 argv[i][1] == 'K' || 2929 argv[i][1] == 'M' || 2930 argv[i][1] == 'm' || 2931 argv[i][1] == 'O' || 2932 argv[i][1] == 'o') && 2933 (argv[i][2] == (int) nul_char)) { 2934 argv[i] = NULL; 2935 argv[++i] = NULL; 2936 } 2937 } 2938 2939 /* 2940 * If no command line "-f" args then look for "makefile", and then for 2941 * "Makefile" if "makefile" isn't found. 2942 */ 2943 if (!makefile_read) { 2944 (void) read_dir(dot, 2945 (wchar_t *) NULL, 2946 (Property) NULL, 2947 (wchar_t *) NULL); 2948 if (!posix) { 2949 if (makefile_name->stat.is_file) { 2950 if (Makefile->stat.is_file) { 2951 warning(gettext("Both `makefile' and `Makefile' exist")); 2952 } 2953 primary_makefile = makefile_name; 2954 makefile_read = read_makefile(makefile_name, 2955 false, 2956 false, 2957 true); 2958 } 2959 if (!makefile_read && 2960 Makefile->stat.is_file) { 2961 primary_makefile = Makefile; 2962 makefile_read = read_makefile(Makefile, 2963 false, 2964 false, 2965 true); 2966 } 2967 } else { 2968 2969 enum sccs_stat save_m_has_sccs = NO_SCCS; 2970 enum sccs_stat save_M_has_sccs = NO_SCCS; 2971 2972 if (makefile_name->stat.is_file) { 2973 if (Makefile->stat.is_file) { 2974 warning(gettext("Both `makefile' and `Makefile' exist")); 2975 } 2976 } 2977 if (makefile_name->stat.is_file) { 2978 if (makefile_name->stat.has_sccs == NO_SCCS) { 2979 primary_makefile = makefile_name; 2980 makefile_read = read_makefile(makefile_name, 2981 false, 2982 false, 2983 true); 2984 } else { 2985 save_m_has_sccs = makefile_name->stat.has_sccs; 2986 makefile_name->stat.has_sccs = NO_SCCS; 2987 primary_makefile = makefile_name; 2988 makefile_read = read_makefile(makefile_name, 2989 false, 2990 false, 2991 true); 2992 } 2993 } 2994 if (!makefile_read && 2995 Makefile->stat.is_file) { 2996 if (Makefile->stat.has_sccs == NO_SCCS) { 2997 primary_makefile = Makefile; 2998 makefile_read = read_makefile(Makefile, 2999 false, 3000 false, 3001 true); 3002 } else { 3003 save_M_has_sccs = Makefile->stat.has_sccs; 3004 Makefile->stat.has_sccs = NO_SCCS; 3005 primary_makefile = Makefile; 3006 makefile_read = read_makefile(Makefile, 3007 false, 3008 false, 3009 true); 3010 } 3011 } 3012 if (!makefile_read && 3013 makefile_name->stat.is_file) { 3014 makefile_name->stat.has_sccs = save_m_has_sccs; 3015 primary_makefile = makefile_name; 3016 makefile_read = read_makefile(makefile_name, 3017 false, 3018 false, 3019 true); 3020 } 3021 if (!makefile_read && 3022 Makefile->stat.is_file) { 3023 Makefile->stat.has_sccs = save_M_has_sccs; 3024 primary_makefile = Makefile; 3025 makefile_read = read_makefile(Makefile, 3026 false, 3027 false, 3028 true); 3029 } 3030 } 3031 } 3032 do_not_exec_rule = save_do_not_exec_rule; 3033 allrules_read = makefile_read; 3034 trace_reader = false; 3035 3036 /* 3037 * Now get current value of MAKEFLAGS and compare it with 3038 * the saved value we set before reading makefile. 3039 * If they are different then MAKEFLAGS is subsequently set by 3040 * makefile, just leave it there. Otherwise, if make mode 3041 * is changed by using .POSIX target in makefile we need 3042 * to correct MAKEFLAGS value. 3043 */ 3044 Name mf_val = getvar(makeflags); 3045 if( (posix != is_xpg4) 3046 && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb))) 3047 { 3048 if (makeflags_string_posix.buffer.start[1] == (int) nul_char) { 3049 (void) SETVAR(makeflags, 3050 GETNAME(makeflags_string_posix.buffer.start + 1, 3051 FIND_LENGTH), 3052 false); 3053 } else { 3054 if (makeflags_string_posix.buffer.start[1] != (int) space_char) { 3055 (void) SETVAR(makeflags, 3056 GETNAME(makeflags_string_posix.buffer.start, 3057 FIND_LENGTH), 3058 false); 3059 } else { 3060 (void) SETVAR(makeflags, 3061 GETNAME(makeflags_string_posix.buffer.start + 2, 3062 FIND_LENGTH), 3063 false); 3064 } 3065 } 3066 } 3067 3068 if (makeflags_string.free_after_use) { 3069 retmem(makeflags_string.buffer.start); 3070 } 3071 if (makeflags_string_posix.free_after_use) { 3072 retmem(makeflags_string_posix.buffer.start); 3073 } 3074 makeflags_string.buffer.start = NULL; 3075 makeflags_string_posix.buffer.start = NULL; 3076 3077 if (posix) { 3078 /* 3079 * If the user did not redefine the ARFLAGS macro in the 3080 * default makefile (make.rules), then we'd like to 3081 * change the macro value of ARFLAGS to be in accordance 3082 * with "POSIX" requirements. 3083 */ 3084 MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS")); 3085 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 3086 macro = get_prop(name->prop, macro_prop); 3087 if ((macro != NULL) && /* Maybe (macro == NULL) || ? */ 3088 (IS_EQUAL(macro->body.macro.value->string_mb, 3089 NOCATGETS("rv")))) { 3090 MBSTOWCS(wcs_buffer, NOCATGETS("-rv")); 3091 value = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 3092 (void) SETVAR(name, 3093 value, 3094 false); 3095 } 3096 } 3097 3098 if (!posix && !svr4) { 3099 set_sgs_support(); 3100 } 3101 3102 3103 /* 3104 * Make sure KEEP_STATE is in the environment if KEEP_STATE is on. 3105 */ 3106 macro = get_prop(keep_state_name->prop, macro_prop); 3107 if ((macro != NULL) && 3108 macro->body.macro.exported) { 3109 keep_state = true; 3110 } 3111 if (keep_state) { 3112 if (macro == NULL) { 3113 macro = maybe_append_prop(keep_state_name, 3114 macro_prop); 3115 } 3116 macro->body.macro.exported = true; 3117 (void) SETVAR(keep_state_name, 3118 empty_name, 3119 false); 3120 3121 /* 3122 * Read state file 3123 */ 3124 3125 /* Before we read state, let's make sure we have 3126 ** right state file. 3127 */ 3128 /* just in case macro references are used in make_state file 3129 ** name, we better expand them at this stage using expand_value. 3130 */ 3131 INIT_STRING_FROM_STACK(dest, destbuffer); 3132 expand_value(make_state, &dest, false); 3133 3134 make_state = GETNAME(dest.buffer.start, FIND_LENGTH); 3135 3136 if(!stat(make_state->string_mb, &make_state_stat)) { 3137 if(!(make_state_stat.st_mode & S_IFREG) ) { 3138 /* copy the make_state structure to the other 3139 ** and then let make_state point to the new 3140 ** one. 3141 */ 3142 memcpy(&state_filename, make_state,sizeof(state_filename)); 3143 state_filename.string_mb = state_file_str_mb; 3144 /* Just a kludge to avoid two slashes back to back */ 3145 if((make_state->hash.length == 1)&& 3146 (make_state->string_mb[0] == '/')) { 3147 make_state->hash.length = 0; 3148 make_state->string_mb[0] = '\0'; 3149 } 3150 sprintf(state_file_str_mb,NOCATGETS("%s%s"), 3151 make_state->string_mb,NOCATGETS("/.make.state")); 3152 make_state = &state_filename; 3153 /* adjust the length to reflect the appended string */ 3154 make_state->hash.length += 12; 3155 } 3156 } else { /* the file doesn't exist or no permission */ 3157 char tmp_path[MAXPATHLEN]; 3158 char *slashp; 3159 3160 if ((slashp = strrchr(make_state->string_mb, '/')) != 0) { 3161 strncpy(tmp_path, make_state->string_mb, 3162 (slashp - make_state->string_mb)); 3163 tmp_path[slashp - make_state->string_mb]=0; 3164 if(strlen(tmp_path)) { 3165 if(stat(tmp_path, &make_state_stat)) { 3166 warning(gettext("directory %s for .KEEP_STATE_FILE does not exist"),tmp_path); 3167 } 3168 if (access(tmp_path, F_OK) != 0) { 3169 warning(gettext("can't access dir %s"),tmp_path); 3170 } 3171 } 3172 } 3173 } 3174 if (report_dependencies_level != 1) { 3175 Makefile_type makefile_type_temp = makefile_type; 3176 makefile_type = reading_statefile; 3177 if (read_trace_level > 1) { 3178 trace_reader = true; 3179 } 3180 (void) read_simple_file(make_state, 3181 false, 3182 false, 3183 false, 3184 false, 3185 false, 3186 true); 3187 trace_reader = false; 3188 makefile_type = makefile_type_temp; 3189 } 3190 } 3191 } 3192 3193 /* 3194 * Scan the argv for options and "=" type args and make them readonly. 3195 */ 3196 static void 3197 enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro) 3198 { 3199 register char *cp; 3200 register int i; 3201 int length; 3202 register Name name; 3203 int opt_separator = argc; 3204 char tmp_char; 3205 wchar_t *tmp_wcs_buffer; 3206 register Name value; 3207 Boolean append = false; 3208 Boolean gnuassign = false; 3209 Property macro; 3210 struct stat statbuf; 3211 3212 3213 /* Read argv options and "=" type args and make them readonly. */ 3214 makefile_type = reading_nothing; 3215 for (i = 1; i < argc; ++i) { 3216 append = false; 3217 if (argv[i] == NULL) { 3218 continue; 3219 } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) || 3220 ((argv[i][0] == (int) ' ') && 3221 (argv[i][1] == (int) '-') && 3222 (argv[i][2] == (int) ' ') && 3223 (argv[i][3] == (int) '-'))) { 3224 argv[i] = NULL; 3225 opt_separator = i; 3226 continue; 3227 } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) { 3228 char *ap = argv[i+1]; 3229 3230 switch (parse_command_option(argv[i][1])) { 3231 case 1: /* -f seen */ 3232 ++i; 3233 continue; 3234 case 2: /* -c seen */ 3235 if (argv[i+1] == NULL) { 3236 fatal(gettext("No dmake rcfile argument after -c flag")); 3237 } 3238 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); 3239 name = GETNAME(wcs_buffer, FIND_LENGTH); 3240 break; 3241 case 4: /* -g seen */ 3242 if (argv[i+1] == NULL) { 3243 fatal(gettext("No dmake group argument after -g flag")); 3244 } 3245 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); 3246 name = GETNAME(wcs_buffer, FIND_LENGTH); 3247 break; 3248 case 8: /* -j seen */ 3249 if (argv[i][2]) /* e.g. -j5 */ 3250 ap = &argv[i][2]; 3251 if (ap == NULL) { 3252 fatal(gettext("No dmake max jobs argument after -j flag")); 3253 } 3254 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); 3255 name = GETNAME(wcs_buffer, FIND_LENGTH); 3256 break; 3257 case 16: /* -M seen */ 3258 if (argv[i+1] == NULL) { 3259 fatal(gettext("No pmake machinesfile argument after -M flag")); 3260 } 3261 MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); 3262 name = GETNAME(wcs_buffer, FIND_LENGTH); 3263 break; 3264 case 32: /* -m seen */ 3265 if (argv[i+1] == NULL) { 3266 fatal(gettext("No dmake mode argument after -m flag")); 3267 } 3268 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); 3269 name = GETNAME(wcs_buffer, FIND_LENGTH); 3270 break; 3271 case 128: /* -O seen */ 3272 if (argv[i+1] == NULL) { 3273 fatal(gettext("No file descriptor argument after -O flag")); 3274 } 3275 mtool_msgs_fd = atoi(argv[i+1]); 3276 /* find out if mtool_msgs_fd is a valid file descriptor */ 3277 if (fstat(mtool_msgs_fd, &statbuf) < 0) { 3278 fatal(gettext("Invalid file descriptor %d after -O flag"), mtool_msgs_fd); 3279 } 3280 argv[i] = NULL; 3281 argv[i+1] = NULL; 3282 continue; 3283 case 256: /* -K seen */ 3284 if (argv[i+1] == NULL) { 3285 fatal(gettext("No makestate filename argument after -K flag")); 3286 } 3287 MBSTOWCS(wcs_buffer, argv[i+1]); 3288 make_state = GETNAME(wcs_buffer, FIND_LENGTH); 3289 keep_state = true; 3290 argv[i] = NULL; 3291 argv[i+1] = NULL; 3292 continue; 3293 case 512: /* -o seen */ 3294 if (argv[i+1] == NULL) { 3295 fatal(gettext("No dmake output dir argument after -o flag")); 3296 } 3297 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); 3298 name = GETNAME(wcs_buffer, FIND_LENGTH); 3299 break; 3300 case 1024: /* -x seen */ 3301 if (argv[i+1] == NULL) { 3302 fatal(gettext("No argument after -x flag")); 3303 } 3304 length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE=")); 3305 if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) { 3306 argv[i+1] = ap = &argv[i+1][length]; 3307 MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); 3308 name = GETNAME(wcs_buffer, FIND_LENGTH); 3309 dmake_compat_mode_specified = dmake_add_mode_specified; 3310 break; 3311 } 3312 length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE=")); 3313 if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) { 3314 argv[i+1] = ap = &argv[i+1][length]; 3315 MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); 3316 name = GETNAME(wcs_buffer, FIND_LENGTH); 3317 dmake_output_mode_specified = dmake_add_mode_specified; 3318 } else { 3319 warning(gettext("Unknown argument `%s' after -x flag (ignored)"), 3320 argv[i+1]); 3321 argv[i] = argv[i + 1] = NULL; 3322 continue; 3323 } 3324 break; 3325 case 2048: /* -C seen */ 3326 if (argv[i][2]) /* e.g. -Cdir */ 3327 ap = &argv[i][2]; 3328 else 3329 argv[i+1] = NULL; 3330 argv[i] = NULL; 3331 continue; 3332 default: /* Shouldn't reach here */ 3333 argv[i] = NULL; 3334 continue; 3335 } 3336 argv[i] = NULL; 3337 if (argv[i+1] == ap) /* If optarg is separate */ 3338 argv[i+1] = NULL; 3339 else 3340 i--; 3341 if (i == (argc - 1)) { 3342 break; 3343 } 3344 if ((length = strlen(ap)) >= MAXPATHLEN) { 3345 tmp_wcs_buffer = ALLOC_WC(length + 1); 3346 (void) mbstowcs(tmp_wcs_buffer, ap, length + 1); 3347 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 3348 retmem(tmp_wcs_buffer); 3349 } else { 3350 MBSTOWCS(wcs_buffer, ap); 3351 value = GETNAME(wcs_buffer, FIND_LENGTH); 3352 } 3353 } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) { 3354 Boolean expand = false; 3355 Boolean gnuassign = false; 3356 3357 if (*(cp-1) == (int) plus_char) { 3358 if (isspace(*(cp-2))) { /* += */ 3359 append = true; 3360 cp--; 3361 } 3362 } else if (*(cp-1) == (int) colon_char) { 3363 if (*(cp-2) == (int) plus_char && 3364 isspace(*(cp-3))) { /* +:= */ 3365 append = true; 3366 expand = true; 3367 cp -= 2; 3368 } else if (*(cp-2) == (int) colon_char) { 3369 if (*(cp-3) == (int) colon_char) { 3370 /* :::= */ 3371 cp -= 3; 3372 expand = true; 3373 #ifdef GNU_ASSIGN_BY_DEFAULT 3374 } else { 3375 #else 3376 } else if (posix || gnu_style) { 3377 #endif 3378 /* ::= */ 3379 cp -= 2; 3380 expand = true; 3381 gnuassign = true; 3382 } 3383 } 3384 } 3385 3386 /* 3387 * Combine all macro in dynamic array 3388 */ 3389 if (!append) 3390 append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]); 3391 3392 while (isspace(*(cp-1))) { 3393 cp--; 3394 } 3395 tmp_char = *cp; 3396 *cp = (int) nul_char; 3397 MBSTOWCS(wcs_buffer, argv[i]); 3398 *cp = tmp_char; 3399 name = GETNAME(wcs_buffer, wcslen(wcs_buffer)); 3400 if (gnuassign && 3401 name->stat.macro_type == unknown_macro_type) 3402 name->stat.macro_type = gnu_assign; 3403 while (*cp != (int) equal_char) { 3404 cp++; 3405 } 3406 cp++; 3407 while (isspace(*cp) && (*cp != (int) nul_char)) { 3408 cp++; 3409 } 3410 if ((length = strlen(cp)) >= MAXPATHLEN) { 3411 tmp_wcs_buffer = ALLOC_WC(length + 1); 3412 (void) mbstowcs(tmp_wcs_buffer, cp, length + 1); 3413 value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); 3414 retmem(tmp_wcs_buffer); 3415 } else { 3416 MBSTOWCS(wcs_buffer, cp); 3417 value = GETNAME(wcs_buffer, FIND_LENGTH); 3418 } 3419 if (expand) { 3420 String_rec val; 3421 wchar_t buffer[STRING_BUFFER_LENGTH]; 3422 3423 INIT_STRING_FROM_STACK(val, buffer); 3424 expand_value(value, &val, false); 3425 value = GETNAME(val.buffer.start, FIND_LENGTH); 3426 } 3427 argv[i] = NULL; 3428 } else { 3429 /* Illegal MAKEFLAGS argument */ 3430 continue; 3431 } 3432 if(append) { 3433 setvar_append(name, value); 3434 append = false; 3435 } else { 3436 macro = maybe_append_prop(name, macro_prop); 3437 macro->body.macro.exported = true; 3438 SETVAR(name, value, false)->body.macro.read_only = true; 3439 } 3440 } 3441 } 3442 3443 /* 3444 * Append the DMake option and value to the MAKEFLAGS string. 3445 */ 3446 static void 3447 append_makeflags_string(Name name, register String makeflags_string) 3448 { 3449 char *option; 3450 3451 if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) { 3452 option = (char *)NOCATGETS(" -g "); 3453 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) { 3454 option = (char *)NOCATGETS(" -j "); 3455 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) { 3456 option = (char *)NOCATGETS(" -m "); 3457 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) { 3458 option = (char *)NOCATGETS(" -o "); 3459 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) { 3460 option = (char *)NOCATGETS(" -c "); 3461 } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) { 3462 option = (char *)NOCATGETS(" -M "); 3463 } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) { 3464 option = (char *)NOCATGETS(" -x DMAKE_OUTPUT_MODE="); 3465 } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) { 3466 option = (char *)NOCATGETS(" -x SUN_MAKE_COMPAT_MODE="); 3467 } else { 3468 fatal(gettext("Internal error: name not recognized in append_makeflags_string()")); 3469 } 3470 Property prop = maybe_append_prop(name, macro_prop); 3471 if( prop == 0 || prop->body.macro.value == 0 || 3472 prop->body.macro.value->string_mb == 0 ) { 3473 return; 3474 } 3475 char mbs_value[MAXPATHLEN + 100]; 3476 strcpy(mbs_value, option); 3477 strcat(mbs_value, prop->body.macro.value->string_mb); 3478 MBSTOWCS(wcs_buffer, mbs_value); 3479 append_string(wcs_buffer, makeflags_string, FIND_LENGTH); 3480 } 3481 3482 /* 3483 * read_environment(read_only) 3484 * 3485 * This routine reads the process environment when make starts and enters 3486 * it as make macros. The environment variable SHELL is ignored. 3487 * 3488 * Parameters: 3489 * read_only Should we make env vars read only? 3490 * 3491 * Global variables used: 3492 * report_pwd Set if this make was started by other make 3493 */ 3494 static void 3495 read_environment(Boolean read_only) 3496 { 3497 register char **environment; 3498 int length; 3499 wchar_t *tmp_wcs_buffer; 3500 Boolean alloced_tmp_wcs_buffer = false; 3501 register wchar_t *name; 3502 register wchar_t *value; 3503 register Name macro; 3504 Property val; 3505 Boolean read_only_saved; 3506 3507 reading_environment = true; 3508 environment = environ; 3509 for (; *environment; environment++) { 3510 read_only_saved = read_only; 3511 if ((length = strlen(*environment)) >= MAXPATHLEN) { 3512 tmp_wcs_buffer = ALLOC_WC(length + 1); 3513 alloced_tmp_wcs_buffer = true; 3514 (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1); 3515 name = tmp_wcs_buffer; 3516 } else { 3517 MBSTOWCS(wcs_buffer, *environment); 3518 name = wcs_buffer; 3519 } 3520 value = (wchar_t *) wcschr(name, (int) equal_char); 3521 3522 /* 3523 * Looks like there's a bug in the system, but sometimes 3524 * you can get blank lines in *environment. 3525 */ 3526 if (!value) { 3527 continue; 3528 } 3529 MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL=")); 3530 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 3531 continue; 3532 } 3533 MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS=")); 3534 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 3535 report_pwd = true; 3536 /* 3537 * In POSIX mode we do not want MAKEFLAGS to be readonly. 3538 * If the MAKEFLAGS macro is subsequently set by the makefile, 3539 * it replaces the MAKEFLAGS variable currently found in the 3540 * environment. 3541 * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8. 3542 */ 3543 if(posix) { 3544 read_only_saved = false; 3545 } 3546 } 3547 3548 /* 3549 * We ignore SUNPRO_DEPENDENCIES and NSE_DEP. Those 3550 * environment variables are set by make and read by 3551 * cpp which then writes info to .make.dependency.xxx and 3552 * .nse_depinfo. When make is invoked by another make 3553 * (recursive make), we don't want to read this because 3554 * then the child make will end up writing to the parent 3555 * directory's .make.state and .nse_depinfo and clobbering 3556 * them. 3557 */ 3558 MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES")); 3559 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 3560 continue; 3561 } 3562 #ifdef NSE 3563 MBSTOWCS(wcs_buffer2, NOCATGETS("NSE_DEP")); 3564 if (IS_WEQUALN(name, wcs_buffer2, wcslen(wcs_buffer2))) { 3565 continue; 3566 } 3567 #endif 3568 3569 macro = GETNAME(name, value - name); 3570 maybe_append_prop(macro, macro_prop)->body.macro.exported = 3571 true; 3572 if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) { 3573 val = setvar_daemon(macro, 3574 (Name) NULL, 3575 false, no_daemon, false, debug_level); 3576 } else { 3577 val = setvar_daemon(macro, 3578 GETNAME(value + 1, FIND_LENGTH), 3579 false, no_daemon, false, debug_level); 3580 } 3581 #ifdef NSE 3582 /* 3583 * Must be after the call to setvar() as it sets 3584 * imported to false. 3585 */ 3586 maybe_append_prop(macro, macro_prop)->body.macro.imported = true; 3587 #endif 3588 val->body.macro.read_only = read_only_saved; 3589 if (alloced_tmp_wcs_buffer) { 3590 retmem(tmp_wcs_buffer); 3591 alloced_tmp_wcs_buffer = false; 3592 } 3593 } 3594 reading_environment = false; 3595 } 3596 3597 /* 3598 * read_makefile(makefile, complain, must_exist, report_file) 3599 * 3600 * Read one makefile and check the result 3601 * 3602 * Return value: 3603 * false is the read failed 3604 * 3605 * Parameters: 3606 * makefile The file to read 3607 * complain Passed thru to read_simple_file() 3608 * must_exist Passed thru to read_simple_file() 3609 * report_file Passed thru to read_simple_file() 3610 * 3611 * Global variables used: 3612 * makefile_type Set to indicate we are reading main file 3613 * recursion_level Initialized 3614 */ 3615 static Boolean 3616 read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file) 3617 { 3618 Boolean b; 3619 3620 makefile_type = reading_makefile; 3621 recursion_level = 0; 3622 #ifdef NSE 3623 wcscpy(current_makefile, makefile->string); 3624 #endif 3625 reading_dependencies = true; 3626 b = read_simple_file(makefile, true, true, complain, 3627 must_exist, report_file, false); 3628 reading_dependencies = false; 3629 return b; 3630 } 3631 3632 /* 3633 * make_targets(argc, argv, parallel_flag) 3634 * 3635 * Call doname on the specified targets 3636 * 3637 * Parameters: 3638 * argc You know what this is 3639 * argv You know what this is 3640 * parallel_flag True if building in parallel 3641 * 3642 * Global variables used: 3643 * build_failed_seen Used to generated message after failed -k 3644 * commands_done Used to generate message "Up to date" 3645 * default_target_to_build First proper target in makefile 3646 * init The Name ".INIT", use to run command 3647 * parallel Global parallel building flag 3648 * quest make -q, suppresses messages 3649 * recursion_level Initialized, used for tracing 3650 * report_dependencies make -P, regroves whole process 3651 */ 3652 static void 3653 make_targets(int argc, char **argv, Boolean parallel_flag) 3654 { 3655 int i; 3656 char *cp; 3657 Doname result; 3658 register Boolean target_to_make_found = false; 3659 3660 (void) doname(init, true, true); 3661 recursion_level = 1; 3662 parallel = parallel_flag; 3663 /* 3664 * make remaining args 3665 */ 3666 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 3667 /* 3668 if ((report_dependencies_level == 0) && parallel) { 3669 */ 3670 if (parallel) { 3671 /* 3672 * If building targets in parallel, start all of the 3673 * remaining args to build in parallel. 3674 */ 3675 for (i = 1; i < argc; i++) { 3676 if ((cp = argv[i]) != NULL) { 3677 commands_done = false; 3678 if ((cp[0] == (int) period_char) && 3679 (cp[1] == (int) slash_char)) { 3680 cp += 2; 3681 } 3682 if((cp[0] == (int) ' ') && 3683 (cp[1] == (int) '-') && 3684 (cp[2] == (int) ' ') && 3685 (cp[3] == (int) '-')) { 3686 argv[i] = NULL; 3687 continue; 3688 } 3689 MBSTOWCS(wcs_buffer, cp); 3690 //default_target_to_build = GETNAME(wcs_buffer, 3691 // FIND_LENGTH); 3692 default_target_to_build = normalize_name(wcs_buffer, 3693 wcslen(wcs_buffer)); 3694 if (default_target_to_build == wait_name) { 3695 if (parallel_process_cnt > 0) { 3696 finish_running(); 3697 } 3698 continue; 3699 } 3700 top_level_target = get_wstring(default_target_to_build->string_mb); 3701 /* 3702 * If we can't execute the current target in 3703 * parallel, hold off the target processing 3704 * to preserve the order of the targets as they appeared 3705 * in command line. 3706 */ 3707 if (!parallel_ok(default_target_to_build, false) 3708 && parallel_process_cnt > 0) { 3709 finish_running(); 3710 } 3711 result = doname_check(default_target_to_build, 3712 true, 3713 false, 3714 false); 3715 gather_recursive_deps(); 3716 if (/* !commands_done && */ 3717 (result == build_ok) && 3718 !quest && 3719 (report_dependencies_level == 0) /* && 3720 (exists(default_target_to_build) > file_doesnt_exist) */) { 3721 if (posix) { 3722 if (!commands_done) { 3723 (void) printf(gettext("`%s' is updated.\n"), 3724 default_target_to_build->string_mb); 3725 } else { 3726 if (no_action_was_taken) { 3727 (void) printf(gettext("`%s': no action was taken.\n"), 3728 default_target_to_build->string_mb); 3729 } 3730 } 3731 } else { 3732 default_target_to_build->stat.time = file_no_time; 3733 if (!commands_done && 3734 !default_target_to_build->stat.is_phony && 3735 (exists(default_target_to_build) > file_doesnt_exist)) { 3736 (void) printf(gettext("`%s' is up to date.\n"), 3737 default_target_to_build->string_mb); 3738 } 3739 } 3740 } 3741 } 3742 } 3743 /* Now wait for all of the targets to finish running */ 3744 finish_running(); 3745 // setjmp(jmpbuffer); 3746 3747 } 3748 #endif 3749 for (i = 1; i < argc; i++) { 3750 if ((cp = argv[i]) != NULL) { 3751 target_to_make_found = true; 3752 if ((cp[0] == (int) period_char) && 3753 (cp[1] == (int) slash_char)) { 3754 cp += 2; 3755 } 3756 if((cp[0] == (int) ' ') && 3757 (cp[1] == (int) '-') && 3758 (cp[2] == (int) ' ') && 3759 (cp[3] == (int) '-')) { 3760 argv[i] = NULL; 3761 continue; 3762 } 3763 MBSTOWCS(wcs_buffer, cp); 3764 default_target_to_build = normalize_name(wcs_buffer, wcslen(wcs_buffer)); 3765 top_level_target = get_wstring(default_target_to_build->string_mb); 3766 report_recursion(default_target_to_build); 3767 commands_done = false; 3768 if (parallel) { 3769 result = (Doname) default_target_to_build->state; 3770 } else { 3771 result = doname_check(default_target_to_build, 3772 true, 3773 false, 3774 false); 3775 } 3776 gather_recursive_deps(); 3777 if (build_failed_seen) { 3778 build_failed_ever_seen = true; 3779 warning(gettext("Target `%s' not remade because of errors"), 3780 default_target_to_build->string_mb); 3781 } 3782 build_failed_seen = false; 3783 if (report_dependencies_level > 0) { 3784 print_dependencies(default_target_to_build, 3785 get_prop(default_target_to_build->prop, 3786 line_prop)); 3787 } 3788 default_target_to_build->stat.time = 3789 file_no_time; 3790 if (default_target_to_build->colon_splits > 0) { 3791 default_target_to_build->state = 3792 build_dont_know; 3793 } 3794 if (!parallel && 3795 /* !commands_done && */ 3796 (result == build_ok) && 3797 !quest && 3798 (report_dependencies_level == 0) /* && 3799 (exists(default_target_to_build) > file_doesnt_exist) */) { 3800 if (posix) { 3801 if (!commands_done) { 3802 (void) printf(gettext("`%s' is updated.\n"), 3803 default_target_to_build->string_mb); 3804 } else { 3805 if (no_action_was_taken) { 3806 (void) printf(gettext("`%s': no action was taken.\n"), 3807 default_target_to_build->string_mb); 3808 } 3809 } 3810 } else { 3811 if (!commands_done && 3812 !default_target_to_build->stat.is_phony && 3813 (exists(default_target_to_build) > file_doesnt_exist)) { 3814 (void) printf(gettext("`%s' is up to date.\n"), 3815 default_target_to_build->string_mb); 3816 } 3817 } 3818 } 3819 } 3820 } 3821 3822 /* 3823 * If no file arguments have been encountered, 3824 * make the first name encountered that doesnt start with a dot 3825 */ 3826 if (!target_to_make_found) { 3827 if (default_target_to_build == NULL) { 3828 fatal(gettext("No arguments to build")); 3829 } 3830 commands_done = false; 3831 top_level_target = get_wstring(default_target_to_build->string_mb); 3832 report_recursion(default_target_to_build); 3833 3834 3835 if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){ 3836 (void) printf(NOCATGETS("::(%s)\n"), 3837 default_target_to_build->string_mb); 3838 } 3839 3840 3841 #if defined(TEAMWARE_MAKE_CMN) || defined(PMAKE) 3842 result = doname_parallel(default_target_to_build, true, false); 3843 #else 3844 result = doname_check(default_target_to_build, true, 3845 false, false); 3846 #endif 3847 gather_recursive_deps(); 3848 if (build_failed_seen) { 3849 build_failed_ever_seen = true; 3850 warning(gettext("Target `%s' not remade because of errors"), 3851 default_target_to_build->string_mb); 3852 } 3853 build_failed_seen = false; 3854 if (report_dependencies_level > 0) { 3855 print_dependencies(default_target_to_build, 3856 get_prop(default_target_to_build-> 3857 prop, 3858 line_prop)); 3859 } 3860 default_target_to_build->stat.time = file_no_time; 3861 if (default_target_to_build->colon_splits > 0) { 3862 default_target_to_build->state = build_dont_know; 3863 } 3864 if (/* !commands_done && */ 3865 (result == build_ok) && 3866 !quest && 3867 (report_dependencies_level == 0) /* && 3868 (exists(default_target_to_build) > file_doesnt_exist) */) { 3869 if (posix) { 3870 if (!commands_done) { 3871 (void) printf(gettext("`%s' is updated.\n"), 3872 default_target_to_build->string_mb); 3873 } else { 3874 if (no_action_was_taken) { 3875 (void) printf(gettext("`%s': no action was taken.\n"), 3876 default_target_to_build->string_mb); 3877 } 3878 } 3879 } else { 3880 if (!commands_done && 3881 !default_target_to_build->stat.is_phony && 3882 (exists(default_target_to_build) > file_doesnt_exist)) { 3883 (void) printf(gettext("`%s' is up to date.\n"), 3884 default_target_to_build->string_mb); 3885 } 3886 } 3887 } 3888 } 3889 } 3890 3891 /* 3892 * report_recursion(target) 3893 * 3894 * If this is a recursive make and the parent make has KEEP_STATE on 3895 * this routine reports the dependency to the parent make 3896 * 3897 * Parameters: 3898 * target Target to report 3899 * 3900 * Global variables used: 3901 * makefiles_used List of makefiles read 3902 * recursive_name The Name ".RECURSIVE", printed 3903 * report_dependency dwight 3904 */ 3905 static void 3906 report_recursion(register Name target) 3907 { 3908 register FILE *report_file = get_report_file(); 3909 3910 if ((report_file == NULL) || (report_file == (FILE*)-1)) { 3911 return; 3912 } 3913 if (primary_makefile == NULL) { 3914 /* 3915 * This can happen when there is no makefile and 3916 * only implicit rules are being used. 3917 */ 3918 #ifdef NSE 3919 nse_no_makefile(target); 3920 #endif 3921 return; 3922 } 3923 (void) fprintf(report_file, 3924 "%s: %s ", 3925 get_target_being_reported_for(), 3926 recursive_name->string_mb); 3927 report_dependency(get_current_path()); 3928 report_dependency(target->string_mb); 3929 report_dependency(primary_makefile->string_mb); 3930 (void) fprintf(report_file, "\n"); 3931 } 3932 3933 /* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */ 3934 /* NIKMOL */ 3935 extern void 3936 append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro) 3937 { 3938 register char *cp0; /* work pointer in macro */ 3939 register char *cp1; /* work pointer in array */ 3940 register char *cp2; /* work pointer in array */ 3941 register char *cp3; /* work pointer in array */ 3942 register char *name; /* macro name */ 3943 register char *value; /* macro value */ 3944 register int len_array; 3945 register int len_macro; 3946 Boolean isassign = false; 3947 Boolean isgnuassign = false; 3948 3949 char * esc_value = NULL; 3950 int esc_len; 3951 3952 if (!(len_macro = strlen(macro))) return; 3953 name = macro; 3954 while (isspace(*(name))) { 3955 name++; 3956 } 3957 if (!(value = strchr(name, (int) equal_char))) { 3958 /* no '=' in macro */ 3959 goto ERROR_MACRO; 3960 } 3961 cp0 = value; 3962 value++; 3963 while (isspace(*(value))) { 3964 value++; 3965 } 3966 3967 if (cp0[-1] == ':' && cp0[-2] == ':') { 3968 cp0 -= 2; 3969 if (cp0[-1] == ':') { 3970 cp0--; 3971 isassign = true; 3972 #ifdef GNU_ASSIGN_BY_DEFAULT 3973 } else { 3974 isgnuassign = true; 3975 } 3976 #else 3977 } else if (posix || gnu_style) { 3978 isgnuassign = true; 3979 } else { 3980 cp0 += 2; 3981 } 3982 #endif 3983 } 3984 while (isspace(*(cp0-1))) { 3985 cp0--; 3986 } 3987 if (cp0 <= name) goto ERROR_MACRO; /* no name */ 3988 if (!(Ar->size)) goto ALLOC_ARRAY; 3989 cp1 = Ar->start; 3990 3991 LOOK_FOR_NAME: 3992 if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO; 3993 if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO; 3994 if (strncmp(cp1, name, (size_t)(cp0-name))) { 3995 /* another name */ 3996 cp1++; 3997 goto LOOK_FOR_NAME; 3998 } 3999 if (cp1 != Ar->start) { 4000 if (!isspace(*(cp1-1))) { 4001 /* another name */ 4002 cp1++; 4003 goto LOOK_FOR_NAME; 4004 } 4005 } 4006 for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) { 4007 if (isspace(*cp3)) continue; 4008 /* else: another name */ 4009 cp1++; 4010 goto LOOK_FOR_NAME; 4011 } 4012 /* Look for the next macro name in array */ 4013 cp3 = cp2+1; 4014 if (*cp3 != (int) doublequote_char) { 4015 /* internal error */ 4016 goto ERROR_MACRO; 4017 } 4018 if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) { 4019 /* internal error */ 4020 goto ERROR_MACRO; 4021 } 4022 cp3++; 4023 while (isspace(*cp3)) { 4024 cp3++; 4025 } 4026 4027 cp2 = cp1; /* remove old macro */ 4028 if ((*cp3) && (cp3 < Ar->start + Ar->size)) { 4029 for (; cp3 < Ar->start + Ar->size; cp3++) { 4030 *cp2++ = *cp3; 4031 } 4032 } 4033 for (; cp2 < Ar->start + Ar->size; cp2++) { 4034 *cp2 = 0; 4035 } 4036 if (*cp1) { 4037 /* check next name */ 4038 goto LOOK_FOR_NAME; 4039 } 4040 goto APPEND_MACRO; 4041 4042 ALLOC_ARRAY: 4043 if (Ar->size) { 4044 cp1 = Ar->start; 4045 } else { 4046 cp1 = 0; 4047 } 4048 Ar->size += 128; 4049 Ar->start = getmem(Ar->size); 4050 for (len_array=0; len_array < Ar->size; len_array++) { 4051 Ar->start[len_array] = 0; 4052 } 4053 if (cp1) { 4054 strcpy(Ar->start, cp1); 4055 retmem((wchar_t *) cp1); 4056 } 4057 4058 APPEND_MACRO: 4059 len_array = strlen(Ar->start); 4060 esc_value = (char*)malloc(strlen(value)*2 + 1); 4061 quote_str(value, esc_value); 4062 esc_len = strlen(esc_value) - strlen(value); 4063 if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY; 4064 strcat(Ar->start, " "); 4065 strncat(Ar->start, name, cp0-name); 4066 if (isassign) 4067 strcat(Ar->start, ":::="); 4068 else if (isgnuassign) 4069 strcat(Ar->start, "::="); 4070 else 4071 strcat(Ar->start, "="); 4072 strncat(Ar->start, esc_value, strlen(esc_value)); 4073 free(esc_value); 4074 return; 4075 ERROR_MACRO: 4076 /* Macro without '=' or with invalid left/right part */ 4077 return; 4078 } 4079 4080 #ifdef TEAMWARE_MAKE_CMN 4081 /* 4082 * This function, if registered w/ avo_cli_get_license(), will be called 4083 * if the application is about to exit because: 4084 * 1) there has been certain unrecoverable error(s) that cause the 4085 * application to exit immediately. 4086 * 2) the user has lost a license while the application is running. 4087 */ 4088 extern "C" void 4089 dmake_exit_callback(void) 4090 { 4091 fatal(gettext("can not get a license, exiting...")); 4092 exit(1); 4093 } 4094 4095 /* 4096 * This function, if registered w/ avo_cli_get_license(), will be called 4097 * if the application can not get a license. 4098 */ 4099 extern "C" void 4100 dmake_message_callback(char *err_msg) 4101 { 4102 static Boolean first = true; 4103 4104 if (!first) { 4105 return; 4106 } 4107 first = false; 4108 if ((!list_all_targets) && 4109 (report_dependencies_level == 0) && 4110 (dmake_mode_type != serial_mode)) { 4111 warning(gettext("can not get a TeamWare license, defaulting to serial mode...")); 4112 } 4113 } 4114 #endif 4115 4116 #ifdef DISTRIBUTED 4117 /* 4118 * Returns whether -c is set or not. 4119 */ 4120 Boolean 4121 get_dmake_rcfile_specified(void) 4122 { 4123 return(dmake_rcfile_specified); 4124 } 4125 4126 /* 4127 * Returns whether -g is set or not. 4128 */ 4129 Boolean 4130 get_dmake_group_specified(void) 4131 { 4132 return(dmake_group_specified); 4133 } 4134 4135 /* 4136 * Returns whether -j is set or not. 4137 */ 4138 Boolean 4139 get_dmake_max_jobs_specified(void) 4140 { 4141 return(dmake_max_jobs_specified); 4142 } 4143 4144 /* 4145 * Returns whether -m is set or not. 4146 */ 4147 Boolean 4148 get_dmake_mode_specified(void) 4149 { 4150 return(dmake_mode_specified); 4151 } 4152 4153 /* 4154 * Returns whether -o is set or not. 4155 */ 4156 Boolean 4157 get_dmake_odir_specified(void) 4158 { 4159 return(dmake_odir_specified); 4160 } 4161 4162 #endif 4163 4164 static void 4165 dir_enter_leave(Boolean entering) 4166 { 4167 static char * mlev = NULL; 4168 char * make_level_str = NULL; 4169 int make_level_val = 0; 4170 4171 make_level_str = getenv(NOCATGETS("MAKELEVEL")); 4172 if (make_level_str) { 4173 make_level_val = atoi(make_level_str); 4174 } 4175 if (mlev == NULL) { 4176 mlev = (char*) malloc(MAXPATHLEN); 4177 } 4178 if (entering) { 4179 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1); 4180 } else { 4181 make_level_val--; 4182 sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val); 4183 } 4184 putenv(mlev); 4185 } 4186 4187 static void 4188 report_dir_enter_leave(Boolean entering) 4189 { 4190 char rcwd[MAXPATHLEN]; 4191 char * make_level_str = NULL; 4192 int make_level_val = 0; 4193 4194 make_level_str = getenv(NOCATGETS("MAKELEVEL")); 4195 if (make_level_str) { 4196 make_level_val = atoi(make_level_str); 4197 } 4198 /* 4199 * We previously did increment our environment, so we need to 4200 * correct this to get the correct value for this level. 4201 */ 4202 make_level_val--; 4203 4204 if (report_cwd) { 4205 if (make_level_val <= 0) { 4206 if (entering) { 4207 #ifdef TEAMWARE_MAKE_CMN 4208 sprintf( rcwd 4209 , gettext("dmake: Entering directory `%s'\n") 4210 , get_current_path()); 4211 #else 4212 sprintf( rcwd 4213 , gettext("make: Entering directory `%s'\n") 4214 , get_current_path()); 4215 #endif 4216 } else { 4217 #ifdef TEAMWARE_MAKE_CMN 4218 sprintf( rcwd 4219 , gettext("dmake: Leaving directory `%s'\n") 4220 , get_current_path()); 4221 #else 4222 sprintf( rcwd 4223 , gettext("make: Leaving directory `%s'\n") 4224 , get_current_path()); 4225 #endif 4226 } 4227 } else { 4228 if (entering) { 4229 #ifdef TEAMWARE_MAKE_CMN 4230 sprintf( rcwd 4231 , gettext("dmake[%d]: Entering directory `%s'\n") 4232 , make_level_val, get_current_path()); 4233 #else 4234 sprintf( rcwd 4235 , gettext("make[%d]: Entering directory `%s'\n") 4236 , make_level_val, get_current_path()); 4237 #endif 4238 } else { 4239 #ifdef TEAMWARE_MAKE_CMN 4240 sprintf( rcwd 4241 , gettext("dmake[%d]: Leaving directory `%s'\n") 4242 , make_level_val, get_current_path()); 4243 #else 4244 sprintf( rcwd 4245 , gettext("make[%d]: Leaving directory `%s'\n") 4246 , make_level_val, get_current_path()); 4247 #endif 4248 } 4249 } 4250 printf(NOCATGETS("%s"), rcwd); 4251 } 4252 } 4253 4254 char * 4255 find_run_dir() 4256 { 4257 #ifdef HAVE_GETEXECNAME 4258 /* 4259 * This is the easy method but it works only on Solaris. 4260 * Try to use it as it helps us to avoid linking against libschily. 4261 */ 4262 const char *exname = getexecname(); 4263 char xpath[MAXPATHLEN]; 4264 int amt; 4265 4266 /* 4267 * If getexecname() exists, it always returns a name for dynamically 4268 * linked processes. 4269 */ 4270 if (exname == NULL || *exname != '/') { 4271 if ((amt = readlink("/proc/self/path/a.out", 4272 xpath, MAXPATHLEN-1)) < 0) { 4273 return (NULL); 4274 } 4275 xpath[amt] = '\0'; 4276 } else { 4277 strlcpy(xpath, exname, MAXPATHLEN); 4278 } 4279 return (strdup(dirname(xpath))); 4280 #else 4281 char *exname = getexecpath(); 4282 char *ret; 4283 4284 if (exname == NULL) { 4285 if (strchr(g_argv[0], (int) slash_char) == NULL) { 4286 /* 4287 * Do pathname search only if we have been 4288 * called via PATH. 4289 */ 4290 exname = findinpath(g_argv[0], X_OK, TRUE, NULL); 4291 } else { 4292 /* 4293 * If arvg[0] starts with a slash, use it, 4294 * else use its concatenation with `pwd`. 4295 */ 4296 if (*g_argv[0] == slash_char) 4297 exname = strdup(g_argv[0]); 4298 else 4299 exname = strdup(argv_zero_string); 4300 } 4301 } 4302 if (exname == NULL) 4303 return (NULL); 4304 ret = strdup(dirname(exname)); 4305 free(exname); 4306 return (ret); 4307 #endif 4308 }