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