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