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