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