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