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