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