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