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