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 * doname.c 28 * 29 * Figure out which targets are out of date and rebuild them 30 */ 31 32 /* 33 * Included files 34 */ 35 #include <alloca.h> /* alloca() */ 36 37 38 #include <fcntl.h> 39 #include <mk/defs.h> 40 #include <mksh/i18n.h> /* get_char_semantics_value() */ 41 #include <mksh/macro.h> /* getvar(), expand_value() */ 42 #include <mksh/misc.h> /* getmem() */ 43 #include <poll.h> 44 45 46 #include <signal.h> 47 48 # include <stropts.h> 49 50 #include <sys/errno.h> 51 #include <sys/stat.h> 52 #include <sys/types.h> 53 #include <sys/utsname.h> /* uname() */ 54 #include <sys/wait.h> 55 #include <unistd.h> /* close() */ 56 57 /* 58 * Defined macros 59 */ 60 # define LOCALHOST "localhost" 61 62 #define MAXRULES 100 63 64 // Sleep for .1 seconds between stat()'s 65 const int STAT_RETRY_SLEEP_TIME = 100000; 66 67 /* 68 * typedefs & structs 69 */ 70 71 /* 72 * Static variables 73 */ 74 static char hostName[MAXNAMELEN] = ""; 75 static char userName[MAXNAMELEN] = ""; 76 77 78 static int second_pass = 0; 79 80 /* 81 * File table of contents 82 */ 83 extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic); 84 extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic); 85 static Boolean check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals); 86 void dynamic_dependencies(Name target); 87 static Doname run_command(register Property line, Boolean print_machine); 88 extern Doname execute_serial(Property line); 89 extern Name vpath_translation(register Name cmd); 90 extern void check_state(Name temp_file_name); 91 static void read_dependency_file(register Name filename); 92 static void check_read_state_file(void); 93 static void do_assign(register Name line, register Name target); 94 static void build_command_strings(Name target, register Property line); 95 static Doname touch_command(register Property line, register Name target, Doname result); 96 extern void update_target(Property line, Doname result); 97 static Doname sccs_get(register Name target, register Property *command); 98 extern void read_directory_of_file(register Name file); 99 static void add_pattern_conditionals(register Name target); 100 extern void set_locals(register Name target, register Property old_locals); 101 extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index); 102 extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics); 103 static void delete_query_chain(Chain ch); 104 105 // From read2.cc 106 extern Name normalize_name(register wchar_t *name_string, register int length); 107 108 109 110 /* 111 * DONE. 112 * 113 * doname_check(target, do_get, implicit, automatic) 114 * 115 * Will call doname() and then inspect the return value 116 * 117 * Return value: 118 * Indication if the build failed or not 119 * 120 * Parameters: 121 * target The target to build 122 * do_get Passed thru to doname() 123 * implicit Passed thru to doname() 124 * automatic Are we building a hidden dependency? 125 * 126 * Global variables used: 127 * build_failed_seen Set if -k is on and error occurs 128 * continue_after_error Indicates that -k is on 129 * report_dependencies No error msg if -P is on 130 */ 131 Doname 132 doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic) 133 { 134 int first_time = 1; 135 (void) fflush(stdout); 136 try_again: 137 switch (doname(target, do_get, implicit, automatic)) { 138 case build_ok: 139 second_pass = 0; 140 return build_ok; 141 case build_running: 142 second_pass = 0; 143 return build_running; 144 case build_failed: 145 if (!continue_after_error) { 146 fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"), 147 target->string_mb); 148 } 149 build_failed_seen = true; 150 second_pass = 0; 151 return build_failed; 152 case build_dont_know: 153 /* 154 * If we can't figure out how to build an automatic 155 * (hidden) dependency, we just ignore it. 156 * We later declare the target to be out of date just in 157 * case something changed. 158 * Also, don't complain if just reporting the dependencies 159 * and not building anything. 160 */ 161 if (automatic || (report_dependencies_level > 0)) { 162 second_pass = 0; 163 return build_dont_know; 164 } 165 if(first_time) { 166 first_time = 0; 167 second_pass = 1; 168 goto try_again; 169 } 170 second_pass = 0; 171 if (continue_after_error && !svr4) { 172 warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"), 173 target->string_mb); 174 build_failed_seen = true; 175 return build_failed; 176 } 177 fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb); 178 break; 179 } 180 #ifdef lint 181 return build_failed; 182 #endif 183 } 184 185 186 void 187 enter_explicit_rule_from_dynamic_rule(Name target, Name source) 188 { 189 Property line, source_line; 190 Dependency dependency; 191 192 source_line = get_prop(source->prop, line_prop); 193 line = maybe_append_prop(target, line_prop); 194 line->body.line.sccs_command = false; 195 line->body.line.target = target; 196 if (line->body.line.command_template == NULL) { 197 line->body.line.command_template = source_line->body.line.command_template; 198 for (dependency = source_line->body.line.dependencies; 199 dependency != NULL; 200 dependency = dependency->next) { 201 enter_dependency(line, dependency->name, false); 202 } 203 line->body.line.less = target; 204 } 205 line->body.line.percent = NULL; 206 } 207 208 209 210 Name 211 find_dyntarget(Name target) 212 { 213 Dyntarget p; 214 int i; 215 String_rec string; 216 wchar_t buffer[STRING_BUFFER_LENGTH]; 217 wchar_t *pp, * bufend; 218 wchar_t tbuffer[MAXPATHLEN]; 219 Wstring wcb(target); 220 221 for (p = dyntarget_list; p != NULL; p = p->next) { 222 INIT_STRING_FROM_STACK(string, buffer); 223 expand_value(p->name, &string, false); 224 i = 0; 225 pp = string.buffer.start; 226 bufend = pp + STRING_BUFFER_LENGTH; 227 while((*pp != nul_char) && (pp < bufend)) { 228 if(iswspace(*pp)) { 229 tbuffer[i] = nul_char; 230 if(i > 0) { 231 if (wcb.equal(tbuffer)) { 232 enter_explicit_rule_from_dynamic_rule(target, p->name); 233 return(target); 234 } 235 } 236 pp++; 237 i = 0; 238 continue; 239 } 240 tbuffer[i] = *pp; 241 i++; 242 pp++; 243 if(*pp == nul_char) { 244 tbuffer[i] = nul_char; 245 if(i > 0) { 246 if (wcb.equal(tbuffer)) { 247 enter_explicit_rule_from_dynamic_rule(target, p->name); 248 return(target); 249 } 250 } 251 break; 252 } 253 } 254 } 255 return(NULL); 256 } 257 258 /* 259 * DONE. 260 * 261 * doname(target, do_get, implicit) 262 * 263 * Chases all files the target depends on and builds any that 264 * are out of date. If the target is out of date it is then rebuilt. 265 * 266 * Return value: 267 * Indiates if build failed or nt 268 * 269 * Parameters: 270 * target Target to build 271 * do_get Run sccs get is nessecary 272 * implicit doname is trying to find an implicit rule 273 * 274 * Global variables used: 275 * assign_done True if command line assgnment has happened 276 * commands_done Preserved for the case that we need local value 277 * debug_level Should we trace make's actions? 278 * default_rule The rule for ".DEFAULT", used as last resort 279 * empty_name The Name "", used when looking for single sfx 280 * keep_state Indicates that .KEEP_STATE is on 281 * parallel True if building in parallel 282 * recursion_level Used for tracing 283 * report_dependencies make -P is on 284 */ 285 Doname 286 doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic) 287 { 288 Doname result = build_dont_know; 289 Chain out_of_date_list = NULL; 290 Chain target_group; 291 Property old_locals = NULL; 292 register Property line; 293 Property command = NULL; 294 register Dependency dependency; 295 Name less = NULL; 296 Name true_target = target; 297 Name *automatics = NULL; 298 register int auto_count; 299 Boolean rechecking_target = false; 300 Boolean saved_commands_done; 301 Boolean restart = false; 302 Boolean save_parallel = parallel; 303 Boolean doing_subtree = false; 304 305 Boolean recheck_conditionals = false; 306 307 if (target->state == build_running) { 308 return build_running; 309 } 310 line = get_prop(target->prop, line_prop); 311 if (line != NULL) { 312 /* 313 * If this target is a member of target group and one of the 314 * other members of the group is running, mark this target 315 * as running. 316 */ 317 for (target_group = line->body.line.target_group; 318 target_group != NULL; 319 target_group = target_group->next) { 320 if (is_running(target_group->name)) { 321 target->state = build_running; 322 add_pending(target, 323 recursion_level, 324 do_get, 325 implicit, 326 false); 327 return build_running; 328 } 329 } 330 } 331 /* 332 * If the target is a constructed one for a "::" target, 333 * we need to consider that. 334 */ 335 if (target->has_target_prop) { 336 true_target = get_prop(target->prop, 337 target_prop)->body.target.target; 338 if (true_target->colon_splits > 0) { 339 /* Make sure we have a valid time for :: targets */ 340 Property time; 341 342 time = get_prop(true_target->prop, time_prop); 343 if (time != NULL) { 344 true_target->stat.time = time->body.time.time; 345 } 346 } 347 } 348 (void) exists(true_target); 349 /* 350 * If the target has been processed, we don't need to do it again, 351 * unless it depends on conditional macros or a delayed assignment, 352 * or it has been done when KEEP_STATE is on. 353 */ 354 if (target->state == build_ok) { 355 if((!keep_state || (!target->depends_on_conditional && !assign_done))) { 356 return build_ok; 357 } else { 358 recheck_conditionals = true; 359 } 360 } 361 if (target->state == build_subtree) { 362 /* A dynamic macro subtree is being built */ 363 target->state = build_dont_know; 364 doing_subtree = true; 365 if (!target->checking_subtree) { 366 /* 367 * This target has been started before and therefore 368 * not all dependencies have to be built. 369 */ 370 restart = true; 371 } 372 } else if (target->state == build_pending) { 373 target->state = build_dont_know; 374 restart = true; 375 /* 376 } else if (parallel && 377 keep_state && 378 (target->conditional_cnt > 0)) { 379 if (!parallel_ok(target, false)) { 380 add_subtree(target, recursion_level, do_get, implicit); 381 target->state = build_running; 382 return build_running; 383 } 384 */ 385 } 386 /* 387 * If KEEP_STATE is on, we have to rebuild the target if the 388 * building of it caused new automatic dependencies to be reported. 389 * This is where we restart the build. 390 */ 391 if (line != NULL) { 392 line->body.line.percent = NULL; 393 } 394 recheck_target: 395 /* Init all local variables */ 396 result = build_dont_know; 397 out_of_date_list = NULL; 398 command = NULL; 399 less = NULL; 400 auto_count = 0; 401 if (!restart && line != NULL) { 402 /* 403 * If this target has never been built before, mark all 404 * of the dependencies as never built. 405 */ 406 for (dependency = line->body.line.dependencies; 407 dependency != NULL; 408 dependency = dependency->next) { 409 dependency->built = false; 410 } 411 } 412 /* Save the set of automatic depes defined for this target */ 413 if (keep_state && 414 (line != NULL) && 415 (line->body.line.dependencies != NULL)) { 416 Name *p; 417 418 /* 419 * First run thru the dependency list to see how many 420 * autos there are. 421 */ 422 for (dependency = line->body.line.dependencies; 423 dependency != NULL; 424 dependency = dependency->next) { 425 if (dependency->automatic && !dependency->stale) { 426 auto_count++; 427 } 428 } 429 /* Create vector to hold the current autos */ 430 automatics = 431 (Name *) alloca((int) (auto_count * sizeof (Name))); 432 /* Copy them */ 433 for (p = automatics, dependency = line->body.line.dependencies; 434 dependency != NULL; 435 dependency = dependency->next) { 436 if (dependency->automatic && !dependency->stale) { 437 *p++ = dependency->name; 438 } 439 } 440 } 441 if (debug_level > 1) { 442 (void) printf(NOCATGETS("%*sdoname(%s)\n"), 443 recursion_level, 444 "", 445 target->string_mb); 446 } 447 recursion_level++; 448 /* Avoid infinite loops */ 449 if (target->state == build_in_progress) { 450 warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"), 451 target->string_mb); 452 return build_ok; 453 } 454 target->state = build_in_progress; 455 456 /* Activate conditional macros for the target */ 457 if (!target->added_pattern_conditionals) { 458 add_pattern_conditionals(target); 459 target->added_pattern_conditionals = true; 460 } 461 if (target->conditional_cnt > 0) { 462 old_locals = (Property) alloca(target->conditional_cnt * 463 sizeof (Property_rec)); 464 set_locals(target, old_locals); 465 } 466 467 /* 468 * after making the call to dynamic_dependecies unconditional we can handle 469 * target names that are same as file name. In this case $$@ in the 470 * dependencies did not mean anything. WIth this change it expands it 471 * as expected. 472 */ 473 if (!target->has_depe_list_expanded) 474 { 475 dynamic_dependencies(target); 476 } 477 478 /* 479 * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT 480 * COMMANDS TO RUN 481 */ 482 if ((line = get_prop(target->prop, line_prop)) != NULL) { 483 if (check_dependencies(&result, 484 line, 485 do_get, 486 target, 487 true_target, 488 doing_subtree, 489 &out_of_date_list, 490 old_locals, 491 implicit, 492 &command, 493 less, 494 rechecking_target, 495 recheck_conditionals)) { 496 return build_running; 497 } 498 if (line->body.line.query != NULL) { 499 delete_query_chain(line->body.line.query); 500 } 501 line->body.line.query = out_of_date_list; 502 } 503 504 505 /* 506 * If the target is a :: type, do not try to find the rule for the target, 507 * all actions will be taken by separate branches. 508 * Else, we try to find an implicit rule using various methods, 509 * we quit as soon as one is found. 510 * 511 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target 512 * being rechecked - the target is being rechecked means that it already 513 * has explicit dependencies derived from an implicit rule found 514 * in previous step. 515 */ 516 if (target->colon_splits == 0 && !rechecking_target) { 517 /* Look for percent matched rule */ 518 if ((result == build_dont_know) && 519 (command == NULL)) { 520 switch (find_percent_rule( 521 target, 522 &command, 523 recheck_conditionals)) { 524 case build_failed: 525 result = build_failed; 526 break; 527 case build_running: 528 target->state = build_running; 529 add_pending(target, 530 --recursion_level, 531 do_get, 532 implicit, 533 false); 534 if (target->conditional_cnt > 0) { 535 reset_locals(target, 536 old_locals, 537 get_prop(target->prop, 538 conditional_prop), 539 0); 540 } 541 return build_running; 542 case build_ok: 543 result = build_ok; 544 break; 545 } 546 } 547 /* Look for double suffix rule */ 548 if (result == build_dont_know) { 549 Property member; 550 551 if (target->is_member && 552 ((member = get_prop(target->prop, member_prop)) != 553 NULL)) { 554 switch (find_ar_suffix_rule(target, 555 member->body. 556 member.member, 557 &command, 558 recheck_conditionals)) { 559 case build_failed: 560 result = build_failed; 561 break; 562 case build_running: 563 target->state = build_running; 564 add_pending(target, 565 --recursion_level, 566 do_get, 567 implicit, 568 false); 569 if (target->conditional_cnt > 0) { 570 reset_locals(target, 571 old_locals, 572 get_prop(target->prop, 573 conditional_prop), 574 0); 575 } 576 return build_running; 577 default: 578 /* ALWAYS bind $% for old style */ 579 /* ar rules */ 580 if (line == NULL) { 581 line = 582 maybe_append_prop(target, 583 line_prop); 584 } 585 line->body.line.percent = 586 member->body.member.member; 587 break; 588 } 589 } else { 590 switch (find_double_suffix_rule(target, 591 &command, 592 recheck_conditionals)) { 593 case build_failed: 594 result = build_failed; 595 break; 596 case build_running: 597 target->state = build_running; 598 add_pending(target, 599 --recursion_level, 600 do_get, 601 implicit, 602 false); 603 if (target->conditional_cnt > 0) { 604 reset_locals(target, 605 old_locals, 606 get_prop(target-> 607 prop, 608 conditional_prop), 609 0); 610 } 611 return build_running; 612 } 613 } 614 } 615 /* Look for single suffix rule */ 616 617 /* /tolik/ 618 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules. 619 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc" 620 */ 621 /* /tolik, 06.21.96/ 622 * Regression! See BugId 1255360 623 * If more than one percent rules are defined for the same target then 624 * the behaviour of 'make' with my previous fix may be different from one 625 * of the 'old make'. 626 * The global variable second_pass (maybe it should be an argument to doname()) 627 * is intended to avoid this regression. It is set in doname_check(). 628 * First, 'make' will work as it worked before. Only when it is 629 * going to say "don't know how to make target" it sets second_pass to true and 630 * run 'doname' again but now trying to use Single Suffix Rules. 631 */ 632 if ((result == build_dont_know) && !automatic && (!implicit || second_pass) && 633 ((line == NULL) || 634 ((line->body.line.target != NULL) && 635 !line->body.line.target->has_regular_dependency))) { 636 switch (find_suffix_rule(target, 637 target, 638 empty_name, 639 &command, 640 recheck_conditionals)) { 641 case build_failed: 642 result = build_failed; 643 break; 644 case build_running: 645 target->state = build_running; 646 add_pending(target, 647 --recursion_level, 648 do_get, 649 implicit, 650 false); 651 if (target->conditional_cnt > 0) { 652 reset_locals(target, 653 old_locals, 654 get_prop(target->prop, 655 conditional_prop), 656 0); 657 } 658 return build_running; 659 } 660 } 661 /* Try to sccs get */ 662 if ((command == NULL) && 663 (result == build_dont_know) && 664 do_get) { 665 result = sccs_get(target, &command); 666 } 667 668 /* Use .DEFAULT rule if it is defined. */ 669 if ((command == NULL) && 670 (result == build_dont_know) && 671 (true_target->colons == no_colon) && 672 default_rule && 673 !implicit) { 674 /* Make sure we have a line prop */ 675 line = maybe_append_prop(target, line_prop); 676 command = line; 677 Boolean out_of_date; 678 if (true_target->is_member) { 679 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, 680 line->body.line.dependency_time); 681 } else { 682 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, 683 line->body.line.dependency_time); 684 } 685 if (build_unconditional || out_of_date) { 686 line->body.line.is_out_of_date = true; 687 if (debug_level > 0) { 688 (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"), 689 recursion_level, 690 "", 691 true_target->string_mb); 692 } 693 } 694 line->body.line.sccs_command = false; 695 line->body.line.command_template = default_rule; 696 line->body.line.target = true_target; 697 line->body.line.star = NULL; 698 line->body.line.less = true_target; 699 line->body.line.percent = NULL; 700 } 701 } 702 703 /* We say "target up to date" if no cmd were executed for the target */ 704 if (!target->is_double_colon_parent) { 705 commands_done = false; 706 } 707 708 silent = silent_all; 709 ignore_errors = ignore_errors_all; 710 if (posix) 711 { 712 if (!silent) 713 { 714 silent = (Boolean) target->silent_mode; 715 } 716 if (!ignore_errors) 717 { 718 ignore_errors = (Boolean) target->ignore_error_mode; 719 } 720 } 721 722 int doname_dyntarget = 0; 723 r_command: 724 /* Run commands if any. */ 725 if ((command != NULL) && 726 (command->body.line.command_template != NULL)) { 727 if (result != build_failed) { 728 result = run_command(command, 729 (Boolean) ((parallel || save_parallel) && !silent)); 730 } 731 switch (result) { 732 case build_running: 733 add_running(target, 734 true_target, 735 command, 736 --recursion_level, 737 auto_count, 738 automatics, 739 do_get, 740 implicit); 741 target->state = build_running; 742 if ((line = get_prop(target->prop, 743 line_prop)) != NULL) { 744 if (line->body.line.query != NULL) { 745 delete_query_chain(line->body.line.query); 746 } 747 line->body.line.query = NULL; 748 } 749 if (target->conditional_cnt > 0) { 750 reset_locals(target, 751 old_locals, 752 get_prop(target->prop, 753 conditional_prop), 754 0); 755 } 756 return build_running; 757 case build_serial: 758 add_serial(target, 759 --recursion_level, 760 do_get, 761 implicit); 762 target->state = build_running; 763 line = get_prop(target->prop, line_prop); 764 if (line != NULL) { 765 if (line->body.line.query != NULL) { 766 delete_query_chain(line->body.line.query); 767 } 768 line->body.line.query = NULL; 769 } 770 if (target->conditional_cnt > 0) { 771 reset_locals(target, 772 old_locals, 773 get_prop(target->prop, 774 conditional_prop), 775 0); 776 } 777 return build_running; 778 case build_ok: 779 /* If all went OK set a nice timestamp */ 780 if (true_target->stat.time == file_doesnt_exist) { 781 true_target->stat.time = file_max_time; 782 } 783 break; 784 } 785 } else { 786 /* 787 * If no command was found for the target, and it doesn't 788 * exist, and it is mentioned as a target in the makefile, 789 * we say it is extremely new and that it is OK. 790 */ 791 if (target->colons != no_colon) { 792 if (true_target->stat.time == file_doesnt_exist){ 793 true_target->stat.time = file_max_time; 794 } 795 result = build_ok; 796 } 797 /* 798 * Trying dynamic targets. 799 */ 800 if(!doname_dyntarget) { 801 doname_dyntarget = 1; 802 Name dtarg = find_dyntarget(target); 803 if(dtarg!=NULL) { 804 if (!target->has_depe_list_expanded) { 805 dynamic_dependencies(target); 806 } 807 if ((line = get_prop(target->prop, line_prop)) != NULL) { 808 if (check_dependencies(&result, 809 line, 810 do_get, 811 target, 812 true_target, 813 doing_subtree, 814 &out_of_date_list, 815 old_locals, 816 implicit, 817 &command, 818 less, 819 rechecking_target, 820 recheck_conditionals)) 821 { 822 return build_running; 823 } 824 if (line->body.line.query != NULL) { 825 delete_query_chain(line->body.line.query); 826 } 827 line->body.line.query = out_of_date_list; 828 } 829 goto r_command; 830 } 831 } 832 /* 833 * If the file exists, it is OK that we couldnt figure 834 * out how to build it. 835 */ 836 (void) exists(target); 837 if ((target->stat.time != file_doesnt_exist) && 838 (result == build_dont_know)) { 839 result = build_ok; 840 } 841 } 842 843 /* 844 * Some of the following is duplicated in the function finish_doname. 845 * If anything is changed here, check to see if it needs to be 846 * changed there. 847 */ 848 if ((line = get_prop(target->prop, line_prop)) != NULL) { 849 if (line->body.line.query != NULL) { 850 delete_query_chain(line->body.line.query); 851 } 852 line->body.line.query = NULL; 853 } 854 target->state = result; 855 parallel = save_parallel; 856 if (target->conditional_cnt > 0) { 857 reset_locals(target, 858 old_locals, 859 get_prop(target->prop, conditional_prop), 860 0); 861 } 862 recursion_level--; 863 if (target->is_member) { 864 Property member; 865 866 /* Propagate the timestamp from the member file to the member*/ 867 if ((target->stat.time != file_max_time) && 868 ((member = get_prop(target->prop, member_prop)) != NULL) && 869 (exists(member->body.member.member) > file_doesnt_exist)) { 870 target->stat.time = 871 member->body.member.member->stat.time; 872 } 873 } 874 /* 875 * Check if we found any new auto dependencies when we 876 * built the target. 877 */ 878 if ((result == build_ok) && check_auto_dependencies(target, 879 auto_count, 880 automatics)) { 881 if (debug_level > 0) { 882 (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"), 883 recursion_level, 884 "", 885 true_target->string_mb); 886 } 887 rechecking_target = true; 888 saved_commands_done = commands_done; 889 goto recheck_target; 890 } 891 892 if (rechecking_target && !commands_done) { 893 commands_done = saved_commands_done; 894 } 895 896 return result; 897 } 898 899 /* 900 * DONE. 901 * 902 * check_dependencies(result, line, do_get, 903 * target, true_target, doing_subtree, out_of_date_tail, 904 * old_locals, implicit, command, less, rechecking_target) 905 * 906 * Return value: 907 * True returned if some dependencies left running 908 * 909 * Parameters: 910 * result Pointer to cell we update if build failed 911 * line We get the dependencies from here 912 * do_get Allow use of sccs get in recursive doname() 913 * target The target to chase dependencies for 914 * true_target The real one for :: and lib(member) 915 * doing_subtree True if building a conditional macro subtree 916 * out_of_date_tail Used to set the $? list 917 * old_locals Used for resetting the local macros 918 * implicit Called when scanning for implicit rules? 919 * command Place to stuff command 920 * less Set to $< value 921 * 922 * Global variables used: 923 * command_changed Set if we suspect .make.state needs rewrite 924 * debug_level Should we trace actions? 925 * force The Name " FORCE", compared against 926 * recursion_level Used for tracing 927 * rewrite_statefile Set if .make.state needs rewriting 928 * wait_name The Name ".WAIT", compared against 929 */ 930 static Boolean 931 check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals) 932 { 933 Boolean dependencies_running; 934 register Dependency dependency; 935 Doname dep_result; 936 Boolean dependency_changed = false; 937 938 line->body.line.dependency_time = file_doesnt_exist; 939 if (line->body.line.query != NULL) { 940 delete_query_chain(line->body.line.query); 941 } 942 line->body.line.query = NULL; 943 line->body.line.is_out_of_date = false; 944 dependencies_running = false; 945 /* 946 * Run thru all the dependencies and call doname() recursively 947 * on each of them. 948 */ 949 for (dependency = line->body.line.dependencies; 950 dependency != NULL; 951 dependency = dependency->next) { 952 Boolean this_dependency_changed = false; 953 954 if (!dependency->automatic && 955 (rechecking_target || target->rechecking_target)) { 956 /* 957 * We only bother with the autos when rechecking 958 */ 959 continue; 960 } 961 962 if (dependency->name == wait_name) { 963 /* 964 * The special target .WAIT means finish all of 965 * the prior dependencies before continuing. 966 */ 967 if (dependencies_running) { 968 break; 969 } 970 } else if ((!parallel_ok(dependency->name, false)) && 971 (dependencies_running)) { 972 /* 973 * If we can't execute the current dependency in 974 * parallel, hold off the dependency processing 975 * to preserve the order of the dependencies. 976 */ 977 break; 978 } else { 979 timestruc_t depe_time = file_doesnt_exist; 980 981 982 if (true_target->is_member) { 983 depe_time = exists(dependency->name); 984 } 985 if (dependency->built || 986 (dependency->name->state == build_failed)) { 987 dep_result = (Doname) dependency->name->state; 988 } else { 989 dep_result = doname_check(dependency->name, 990 do_get, 991 false, 992 (Boolean) dependency->automatic); 993 } 994 if (true_target->is_member || dependency->name->is_member) { 995 /* should compare only secs, cause lib members does not have nsec time resolution */ 996 if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) { 997 this_dependency_changed = 998 dependency_changed = 999 true; 1000 } 1001 } else { 1002 if (depe_time != dependency->name->stat.time) { 1003 this_dependency_changed = 1004 dependency_changed = 1005 true; 1006 } 1007 } 1008 dependency->built = true; 1009 switch (dep_result) { 1010 case build_running: 1011 dependencies_running = true; 1012 continue; 1013 case build_failed: 1014 *result = build_failed; 1015 break; 1016 case build_dont_know: 1017 /* 1018 * If make can't figure out how to make a dependency, maybe the dependency 1019 * is out of date. In this case, we just declare the target out of date 1020 * and go on. If we really need the dependency, the make'ing of the target 1021 * will fail. This will only happen for automatic (hidden) dependencies. 1022 */ 1023 if(!recheck_conditionals) { 1024 line->body.line.is_out_of_date = true; 1025 } 1026 /* 1027 * Make sure the dependency is not saved 1028 * in the state file. 1029 */ 1030 dependency->stale = true; 1031 rewrite_statefile = 1032 command_changed = 1033 true; 1034 if (debug_level > 0) { 1035 (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"), 1036 true_target->string_mb, 1037 dependency->name->string_mb); 1038 } 1039 break; 1040 } 1041 if (dependency->name->depends_on_conditional) { 1042 target->depends_on_conditional = true; 1043 } 1044 if (dependency->name == force) { 1045 target->stat.time = 1046 dependency->name->stat.time; 1047 } 1048 /* 1049 * Propagate new timestamp from "member" to 1050 * "lib.a(member)". 1051 */ 1052 (void) exists(dependency->name); 1053 1054 /* Collect the timestamp of the youngest dependency */ 1055 line->body.line.dependency_time = 1056 MAX(dependency->name->stat.time, 1057 line->body.line.dependency_time); 1058 1059 /* Correction: do not consider nanosecs for members */ 1060 if(true_target->is_member || dependency->name->is_member) { 1061 line->body.line.dependency_time.tv_nsec = 0; 1062 } 1063 1064 if (debug_level > 1) { 1065 (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"), 1066 recursion_level, 1067 "", 1068 dependency->name->string_mb, 1069 time_to_string(dependency->name-> 1070 stat.time)); 1071 if (dependency->name->stat.time > line->body.line.dependency_time) { 1072 (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"), 1073 recursion_level, 1074 "", 1075 true_target->string_mb, 1076 time_to_string(line->body.line. 1077 dependency_time)); 1078 } 1079 } 1080 1081 /* Build the $? list */ 1082 if (true_target->is_member) { 1083 if (this_dependency_changed == true) { 1084 true_target->stat.time = dependency->name->stat.time; 1085 true_target->stat.time.tv_sec--; 1086 } else { 1087 /* Dina: 1088 * The next statement is commented 1089 * out as a fix for bug #1051032. 1090 * if dependency hasn't changed 1091 * then there's no need to invalidate 1092 * true_target. This statemnt causes 1093 * make to take much longer to process 1094 * an already-built archive. Soren 1095 * said it was a quick fix for some 1096 * problem he doesn't remember. 1097 true_target->stat.time = file_no_time; 1098 */ 1099 (void) exists(true_target); 1100 } 1101 } else { 1102 (void) exists(true_target); 1103 } 1104 Boolean out_of_date; 1105 if (true_target->is_member || dependency->name->is_member) { 1106 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, 1107 dependency->name->stat.time); 1108 } else { 1109 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, 1110 dependency->name->stat.time); 1111 } 1112 if ((build_unconditional || out_of_date) && 1113 (dependency->name != force) && 1114 (dependency->stale == false)) { 1115 *out_of_date_tail = ALLOC(Chain); 1116 if (dependency->name->is_member && 1117 (get_prop(dependency->name->prop, 1118 member_prop) != NULL)) { 1119 (*out_of_date_tail)->name = 1120 get_prop(dependency->name->prop, 1121 member_prop)-> 1122 body.member.member; 1123 } else { 1124 (*out_of_date_tail)->name = 1125 dependency->name; 1126 } 1127 (*out_of_date_tail)->next = NULL; 1128 out_of_date_tail = &(*out_of_date_tail)->next; 1129 if (debug_level > 0) { 1130 if (dependency->name->stat.time == file_max_time) { 1131 (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"), 1132 recursion_level, 1133 "", 1134 true_target->string_mb, 1135 dependency->name->string_mb); 1136 } else { 1137 (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"), 1138 recursion_level, 1139 "", 1140 true_target->string_mb, 1141 dependency->name->string_mb); 1142 } 1143 } 1144 } 1145 if (dependency->name == force) { 1146 force->stat.time = 1147 file_max_time; 1148 force->state = build_dont_know; 1149 } 1150 } 1151 } 1152 if (dependencies_running) { 1153 if (doing_subtree) { 1154 if (target->conditional_cnt > 0) { 1155 reset_locals(target, 1156 old_locals, 1157 get_prop(target->prop, 1158 conditional_prop), 1159 0); 1160 } 1161 return true; 1162 } else { 1163 target->state = build_running; 1164 add_pending(target, 1165 --recursion_level, 1166 do_get, 1167 implicit, 1168 false); 1169 if (target->conditional_cnt > 0) { 1170 reset_locals(target, 1171 old_locals, 1172 get_prop(target->prop, 1173 conditional_prop), 1174 0); 1175 } 1176 return true; 1177 } 1178 } 1179 /* 1180 * Collect the timestamp of the youngest double colon target 1181 * dependency. 1182 */ 1183 if (target->is_double_colon_parent) { 1184 for (dependency = line->body.line.dependencies; 1185 dependency != NULL; 1186 dependency = dependency->next) { 1187 Property tmp_line; 1188 1189 if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) { 1190 if(tmp_line->body.line.dependency_time != file_max_time) { 1191 target->stat.time = 1192 MAX(tmp_line->body.line.dependency_time, 1193 target->stat.time); 1194 } 1195 } 1196 } 1197 } 1198 if ((true_target->is_member) && (dependency_changed == true)) { 1199 true_target->stat.time = file_no_time; 1200 } 1201 /* 1202 * After scanning all the dependencies, we check the rule 1203 * if we found one. 1204 */ 1205 if (line->body.line.command_template != NULL) { 1206 if (line->body.line.command_template_redefined) { 1207 warning(catgets(catd, 1, 24, "Too many rules defined for target %s"), 1208 target->string_mb); 1209 } 1210 *command = line; 1211 /* Check if the target is out of date */ 1212 Boolean out_of_date; 1213 if (true_target->is_member) { 1214 out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, 1215 line->body.line.dependency_time); 1216 } else { 1217 out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, 1218 line->body.line.dependency_time); 1219 } 1220 if (build_unconditional || out_of_date){ 1221 if(!recheck_conditionals) { 1222 line->body.line.is_out_of_date = true; 1223 } 1224 } 1225 line->body.line.sccs_command = false; 1226 line->body.line.target = true_target; 1227 if(gnu_style) { 1228 1229 // set $< for explicit rule 1230 if(line->body.line.dependencies != NULL) { 1231 less = line->body.line.dependencies->name; 1232 } 1233 1234 // set $* for explicit rule 1235 Name target_body; 1236 Name tt = true_target; 1237 Property member; 1238 register wchar_t *target_end; 1239 register Dependency suffix; 1240 register int suffix_length; 1241 Wstring targ_string; 1242 Wstring suf_string; 1243 1244 if (true_target->is_member && 1245 ((member = get_prop(target->prop, member_prop)) != 1246 NULL)) { 1247 tt = member->body.member.member; 1248 } 1249 targ_string.init(tt); 1250 target_end = targ_string.get_string() + tt->hash.length; 1251 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { 1252 suffix_length = suffix->name->hash.length; 1253 suf_string.init(suffix->name); 1254 if (tt->hash.length < suffix_length) { 1255 continue; 1256 } else if (!IS_WEQUALN(suf_string.get_string(), 1257 (target_end - suffix_length), 1258 suffix_length)) { 1259 continue; 1260 } 1261 target_body = GETNAME( 1262 targ_string.get_string(), 1263 (int)(tt->hash.length - suffix_length) 1264 ); 1265 line->body.line.star = target_body; 1266 } 1267 1268 // set result = build_ok so that implicit rules are not used. 1269 if(*result == build_dont_know) { 1270 *result = build_ok; 1271 } 1272 } 1273 if (less != NULL) { 1274 line->body.line.less = less; 1275 } 1276 } 1277 1278 return false; 1279 } 1280 1281 /* 1282 * dynamic_dependencies(target) 1283 * 1284 * Checks if any dependency contains a macro ref 1285 * If so, it replaces the dependency with the expanded version. 1286 * Here, "$@" gets translated to target->string. That is 1287 * the current name on the left of the colon in the 1288 * makefile. Thus, 1289 * xyz: s.$@.c 1290 * translates into 1291 * xyz: s.xyz.c 1292 * 1293 * Also, "$(@F)" translates to the same thing without a preceeding 1294 * directory path (if one exists). 1295 * Note, to enter "$@" on a dependency line in a makefile 1296 * "$$@" must be typed. This is because make expands 1297 * macros in dependency lists upon reading them. 1298 * dynamic_dependencies() also expands file wildcards. 1299 * If there are any Shell meta characters in the name, 1300 * search the directory, and replace the dependency 1301 * with the set of files the pattern matches 1302 * 1303 * Parameters: 1304 * target Target to sanitize dependencies for 1305 * 1306 * Global variables used: 1307 * c_at The Name "@", used to set macro value 1308 * debug_level Should we trace actions? 1309 * dot The Name ".", used to read directory 1310 * recursion_level Used for tracing 1311 */ 1312 void 1313 dynamic_dependencies(Name target) 1314 { 1315 wchar_t pattern[MAXPATHLEN]; 1316 register wchar_t *p; 1317 Property line; 1318 register Dependency dependency; 1319 register Dependency *remove; 1320 String_rec string; 1321 wchar_t buffer[MAXPATHLEN]; 1322 register Boolean set_at = false; 1323 register wchar_t *start; 1324 Dependency new_depe; 1325 register Boolean reuse_cell; 1326 Dependency first_member; 1327 Name directory; 1328 Name lib; 1329 Name member; 1330 Property prop; 1331 Name true_target = target; 1332 wchar_t *library; 1333 1334 if ((line = get_prop(target->prop, line_prop)) == NULL) { 1335 return; 1336 } 1337 /* If the target is constructed from a "::" target we consider that */ 1338 if (target->has_target_prop) { 1339 true_target = get_prop(target->prop, 1340 target_prop)->body.target.target; 1341 } 1342 /* Scan all dependencies and process the ones that contain "$" chars */ 1343 for (dependency = line->body.line.dependencies; 1344 dependency != NULL; 1345 dependency = dependency->next) { 1346 if (!dependency->name->dollar) { 1347 continue; 1348 } 1349 target->has_depe_list_expanded = true; 1350 1351 /* The make macro $@ is bound to the target name once per */ 1352 /* invocation of dynamic_dependencies() */ 1353 if (!set_at) { 1354 (void) SETVAR(c_at, true_target, false); 1355 set_at = true; 1356 } 1357 /* Expand this dependency string */ 1358 INIT_STRING_FROM_STACK(string, buffer); 1359 expand_value(dependency->name, &string, false); 1360 /* Scan the expanded string. It could contain whitespace */ 1361 /* which mean it expands to several dependencies */ 1362 start = string.buffer.start; 1363 while (iswspace(*start)) { 1364 start++; 1365 } 1366 /* Remove the cell (later) if the macro was empty */ 1367 if (start[0] == (int) nul_char) { 1368 dependency->name = NULL; 1369 } 1370 1371 /* azv 10/26/95 to fix bug BID_1170218 */ 1372 if ((start[0] == (int) period_char) && 1373 (start[1] == (int) slash_char)) { 1374 start += 2; 1375 } 1376 /* azv */ 1377 1378 first_member = NULL; 1379 /* We use the original dependency cell for the first */ 1380 /* dependency from the expansion */ 1381 reuse_cell = true; 1382 /* We also have to deal with dependencies that expand to */ 1383 /* lib.a(members) notation */ 1384 for (p = start; *p != (int) nul_char; p++) { 1385 if ((*p == (int) parenleft_char)) { 1386 lib = GETNAME(start, p - start); 1387 lib->is_member = true; 1388 first_member = dependency; 1389 start = p + 1; 1390 while (iswspace(*start)) { 1391 start++; 1392 } 1393 break; 1394 } 1395 } 1396 do { 1397 /* First skip whitespace */ 1398 for (p = start; *p != (int) nul_char; p++) { 1399 if ((*p == (int) nul_char) || 1400 iswspace(*p) || 1401 (*p == (int) parenright_char)) { 1402 break; 1403 } 1404 } 1405 /* Enter dependency from expansion */ 1406 if (p != start) { 1407 /* Create new dependency cell if */ 1408 /* this is not the first dependency */ 1409 /* picked from the expansion */ 1410 if (!reuse_cell) { 1411 new_depe = ALLOC(Dependency); 1412 new_depe->next = dependency->next; 1413 new_depe->automatic = false; 1414 new_depe->stale = false; 1415 new_depe->built = false; 1416 dependency->next = new_depe; 1417 dependency = new_depe; 1418 } 1419 reuse_cell = false; 1420 /* Internalize the dependency name */ 1421 // tolik. Fix for bug 4110429: inconsistent expansion for macros that 1422 // include "//" and "/./" 1423 //dependency->name = GETNAME(start, p - start); 1424 dependency->name = normalize_name(start, p - start); 1425 if ((debug_level > 0) && 1426 (first_member == NULL)) { 1427 (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"), 1428 recursion_level, 1429 "", 1430 dependency->name->string_mb, 1431 true_target->string_mb); 1432 } 1433 for (start = p; iswspace(*start); start++); 1434 p = start; 1435 } 1436 } while ((*p != (int) nul_char) && 1437 (*p != (int) parenright_char)); 1438 /* If the expansion was of lib.a(members) format we now */ 1439 /* enter the proper member cells */ 1440 if (first_member != NULL) { 1441 /* Scan the new dependencies and transform them from */ 1442 /* "foo" to "lib.a(foo)" */ 1443 for (; 1; first_member = first_member->next) { 1444 /* Build "lib.a(foo)" name */ 1445 INIT_STRING_FROM_STACK(string, buffer); 1446 APPEND_NAME(lib, 1447 &string, 1448 (int) lib->hash.length); 1449 append_char((int) parenleft_char, &string); 1450 APPEND_NAME(first_member->name, 1451 &string, 1452 FIND_LENGTH); 1453 append_char((int) parenright_char, &string); 1454 member = first_member->name; 1455 /* Replace "foo" with "lib.a(foo)" */ 1456 first_member->name = 1457 GETNAME(string.buffer.start, FIND_LENGTH); 1458 if (string.free_after_use) { 1459 retmem(string.buffer.start); 1460 } 1461 if (debug_level > 0) { 1462 (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"), 1463 recursion_level, 1464 "", 1465 first_member->name-> 1466 string_mb, 1467 true_target->string_mb); 1468 } 1469 first_member->name->is_member = lib->is_member; 1470 /* Add member property to member */ 1471 prop = maybe_append_prop(first_member->name, 1472 member_prop); 1473 prop->body.member.library = lib; 1474 prop->body.member.entry = NULL; 1475 prop->body.member.member = member; 1476 if (first_member == dependency) { 1477 break; 1478 } 1479 } 1480 } 1481 } 1482 Wstring wcb; 1483 /* Then scan all the dependencies again. This time we want to expand */ 1484 /* shell file wildcards */ 1485 for (remove = &line->body.line.dependencies, dependency = *remove; 1486 dependency != NULL; 1487 dependency = *remove) { 1488 if (dependency->name == NULL) { 1489 dependency = *remove = (*remove)->next; 1490 continue; 1491 } 1492 /* If dependency name string contains shell wildcards */ 1493 /* replace the name with the expansion */ 1494 if (dependency->name->wildcard) { 1495 wcb.init(dependency->name); 1496 if ((start = (wchar_t *) wschr(wcb.get_string(), 1497 (int) parenleft_char)) != NULL) { 1498 /* lib(*) type pattern */ 1499 library = buffer; 1500 (void) wsncpy(buffer, 1501 wcb.get_string(), 1502 start - wcb.get_string()); 1503 buffer[start-wcb.get_string()] = 1504 (int) nul_char; 1505 (void) wsncpy(pattern, 1506 start + 1, 1507 (int) (dependency->name->hash.length-(start-wcb.get_string())-2)); 1508 pattern[dependency->name->hash.length - 1509 (start-wcb.get_string()) - 2] = 1510 (int) nul_char; 1511 } else { 1512 library = NULL; 1513 (void) wsncpy(pattern, 1514 wcb.get_string(), 1515 (int) dependency->name->hash.length); 1516 pattern[dependency->name->hash.length] = 1517 (int) nul_char; 1518 } 1519 start = (wchar_t *) wsrchr(pattern, (int) slash_char); 1520 if (start == NULL) { 1521 directory = dot; 1522 p = pattern; 1523 } else { 1524 directory = GETNAME(pattern, start-pattern); 1525 p = start+1; 1526 } 1527 /* The expansion is handled by the read_dir() routine*/ 1528 if (read_dir(directory, p, line, library)) { 1529 *remove = (*remove)->next; 1530 } else { 1531 remove = &dependency->next; 1532 } 1533 } else { 1534 remove = &dependency->next; 1535 } 1536 } 1537 1538 /* Then unbind $@ */ 1539 (void) SETVAR(c_at, (Name) NULL, false); 1540 } 1541 1542 /* 1543 * DONE. 1544 * 1545 * run_command(line) 1546 * 1547 * Takes one Cmd_line and runs the commands from it. 1548 * 1549 * Return value: 1550 * Indicates if the command failed or not 1551 * 1552 * Parameters: 1553 * line The command line to run 1554 * 1555 * Global variables used: 1556 * commands_done Set if we do run command 1557 * current_line Set to the line we run a command from 1558 * current_target Set to the target we run a command for 1559 * file_number Used to form temp file name 1560 * keep_state Indicates that .KEEP_STATE is on 1561 * make_state The Name ".make.state", used to check timestamp 1562 * parallel True if currently building in parallel 1563 * parallel_process_cnt Count of parallel processes running 1564 * quest Indicates that make -q is on 1565 * rewrite_statefile Set if we do run a command 1566 * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value 1567 * temp_file_directory Used to form temp fie name 1568 * temp_file_name Set to the name of the temp file 1569 * touch Indicates that make -t is on 1570 */ 1571 static Doname 1572 run_command(register Property line, Boolean) 1573 { 1574 register Doname result = build_ok; 1575 register Boolean remember_only = false; 1576 register Name target = line->body.line.target; 1577 wchar_t *string; 1578 char tmp_file_path[MAXPATHLEN]; 1579 1580 if (!line->body.line.is_out_of_date && target->rechecking_target) { 1581 target->rechecking_target = false; 1582 return build_ok; 1583 } 1584 1585 /* 1586 * Build the command if we know the target is out of date, 1587 * or if we want to check cmd consistency. 1588 */ 1589 if (line->body.line.is_out_of_date || keep_state) { 1590 /* Hack for handling conditional macros in DMake. */ 1591 if (!line->body.line.dont_rebuild_command_used) { 1592 build_command_strings(target, line); 1593 } 1594 } 1595 /* Never mind */ 1596 if (!line->body.line.is_out_of_date) { 1597 return build_ok; 1598 } 1599 /* If quest, then exit(1) because the target is out of date */ 1600 if (quest) { 1601 if (posix) { 1602 result = execute_parallel(line, true); 1603 } 1604 exit_status = 1; 1605 exit(1); 1606 } 1607 /* We actually had to do something this time */ 1608 rewrite_statefile = commands_done = true; 1609 /* 1610 * If this is an sccs command, we have to do some extra checking 1611 * and possibly complain. If the file can't be gotten because it's 1612 * checked out, we complain and behave as if the command was 1613 * executed eventhough we ignored the command. 1614 */ 1615 if (!touch && 1616 line->body.line.sccs_command && 1617 (target->stat.time != file_doesnt_exist) && 1618 ((target->stat.mode & 0222) != 0)) { 1619 fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"), 1620 target->string_mb); 1621 target->has_complained = remember_only = true; 1622 } 1623 /* 1624 * If KEEP_STATE is on, we make sure we have the timestamp for 1625 * .make.state. If .make.state changes during the command run, 1626 * we reread .make.state after the command. We also setup the 1627 * environment variable that asks utilities to report dependencies. 1628 */ 1629 if (!touch && 1630 keep_state && 1631 !remember_only) { 1632 (void) exists(make_state); 1633 if((strlen(temp_file_directory) == 1) && 1634 (temp_file_directory[0] == '/')) { 1635 tmp_file_path[0] = '\0'; 1636 } else { 1637 strcpy(tmp_file_path, temp_file_directory); 1638 } 1639 sprintf(mbs_buffer, 1640 NOCATGETS("%s/.make.dependency.%08x.%d.%d"), 1641 tmp_file_path, 1642 hostid, 1643 getpid(), 1644 file_number++); 1645 MBSTOWCS(wcs_buffer, mbs_buffer); 1646 Boolean fnd; 1647 temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd); 1648 temp_file_name->stat.is_file = true; 1649 int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2; 1650 wchar_t *to = string = ALLOC_WC(len); 1651 for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) { 1652 if (*from == (int) space_char) { 1653 *to++ = (int) backslash_char; 1654 } 1655 *to++ = *from++; 1656 } 1657 *to++ = (int) space_char; 1658 MBSTOWCS(to, target->string_mb); 1659 Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd); 1660 (void) SETVAR(sunpro_dependencies, 1661 sprodep_name, 1662 false); 1663 retmem(string); 1664 } else { 1665 temp_file_name = NULL; 1666 } 1667 1668 /* 1669 * In case we are interrupted, we need to know what was going on. 1670 */ 1671 current_target = target; 1672 /* 1673 * We also need to be able to save an empty command instead of the 1674 * interrupted one in .make.state. 1675 */ 1676 current_line = line; 1677 if (remember_only) { 1678 /* Empty block!!! */ 1679 } else if (touch) { 1680 result = touch_command(line, target, result); 1681 if (posix) { 1682 result = execute_parallel(line, true); 1683 } 1684 } else { 1685 /* 1686 * If this is not a touch run, we need to execute the 1687 * proper command(s) for the target. 1688 */ 1689 if (parallel) { 1690 if (!parallel_ok(target, true)) { 1691 /* 1692 * We are building in parallel, but 1693 * this target must be built in serial. 1694 */ 1695 /* 1696 * If nothing else is building, 1697 * do this one, else wait. 1698 */ 1699 if (parallel_process_cnt == 0) { 1700 result = execute_parallel(line, true, target->localhost); 1701 } else { 1702 current_target = NULL; 1703 current_line = NULL; 1704 /* 1705 line->body.line.command_used = NULL; 1706 */ 1707 line->body.line.dont_rebuild_command_used = true; 1708 return build_serial; 1709 } 1710 } else { 1711 result = execute_parallel(line, false); 1712 switch (result) { 1713 case build_running: 1714 return build_running; 1715 case build_serial: 1716 if (parallel_process_cnt == 0) { 1717 result = execute_parallel(line, true, target->localhost); 1718 } else { 1719 current_target = NULL; 1720 current_line = NULL; 1721 target->parallel = false; 1722 line->body.line.command_used = 1723 NULL; 1724 return build_serial; 1725 } 1726 } 1727 } 1728 } else { 1729 result = execute_parallel(line, true, target->localhost); 1730 } 1731 } 1732 temp_file_name = NULL; 1733 if (report_dependencies_level == 0){ 1734 update_target(line, result); 1735 } 1736 current_target = NULL; 1737 current_line = NULL; 1738 return result; 1739 } 1740 1741 /* 1742 * execute_serial(line) 1743 * 1744 * Runs thru the command line for the target and 1745 * executes the rules one by one. 1746 * 1747 * Return value: 1748 * The result of the command build 1749 * 1750 * Parameters: 1751 * line The command to execute 1752 * 1753 * Static variables used: 1754 * 1755 * Global variables used: 1756 * continue_after_error -k flag 1757 * do_not_exec_rule -n flag 1758 * report_dependencies -P flag 1759 * silent Don't echo commands before executing 1760 * temp_file_name Temp file for auto dependencies 1761 * vpath_defined If true, translate path for command 1762 */ 1763 Doname 1764 execute_serial(Property line) 1765 { 1766 int child_pid = 0; 1767 Boolean printed_serial; 1768 Doname result = build_ok; 1769 Cmd_line rule, cmd_tail, command = NULL; 1770 char mbstring[MAXPATHLEN]; 1771 int filed; 1772 Name target = line->body.line.target; 1773 1774 target->has_recursive_dependency = false; 1775 // We have to create a copy of the rules chain for processing because 1776 // the original one can be destroyed during .make.state file rereading. 1777 for (rule = line->body.line.command_used; 1778 rule != NULL; 1779 rule = rule->next) { 1780 if (command == NULL) { 1781 command = cmd_tail = ALLOC(Cmd_line); 1782 } else { 1783 cmd_tail->next = ALLOC(Cmd_line); 1784 cmd_tail = cmd_tail->next; 1785 } 1786 *cmd_tail = *rule; 1787 } 1788 if (command) { 1789 cmd_tail->next = NULL; 1790 } 1791 for (rule = command; rule != NULL; rule = rule->next) { 1792 if (posix && (touch || quest) && !rule->always_exec) { 1793 continue; 1794 } 1795 if (vpath_defined) { 1796 rule->command_line = 1797 vpath_translation(rule->command_line); 1798 } 1799 /* Echo command line, maybe. */ 1800 if ((rule->command_line->hash.length > 0) && 1801 !silent && 1802 (!rule->silent || do_not_exec_rule) && 1803 (report_dependencies_level == 0)) { 1804 (void) printf("%s\n", rule->command_line->string_mb); 1805 } 1806 if (rule->command_line->hash.length > 0) { 1807 /* Do assignment if command line prefixed with "=" */ 1808 if (rule->assign) { 1809 result = build_ok; 1810 do_assign(rule->command_line, target); 1811 } else if (report_dependencies_level == 0) { 1812 /* Execute command line. */ 1813 setvar_envvar(); 1814 result = dosys(rule->command_line, 1815 (Boolean) rule->ignore_error, 1816 (Boolean) rule->make_refd, 1817 /* ds 98.04.23 bug #4085164. make should always show error messages */ 1818 false, 1819 /* BOOLEAN(rule->silent && 1820 rule->ignore_error), */ 1821 (Boolean) rule->always_exec, 1822 target); 1823 check_state(temp_file_name); 1824 } 1825 } else { 1826 result = build_ok; 1827 } 1828 if (result == build_failed) { 1829 if (silent || rule->silent) { 1830 (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"), 1831 rule->command_line->string_mb); 1832 } 1833 if (!rule->ignore_error && !ignore_errors) { 1834 if (!continue_after_error) { 1835 fatal(catgets(catd, 1, 244, "Command failed for target `%s'"), 1836 target->string_mb); 1837 } 1838 /* 1839 * Make sure a failing command is not 1840 * saved in .make.state. 1841 */ 1842 line->body.line.command_used = NULL; 1843 break; 1844 } else { 1845 result = build_ok; 1846 } 1847 } 1848 } 1849 for (rule = command; rule != NULL; rule = cmd_tail) { 1850 cmd_tail = rule->next; 1851 free(rule); 1852 } 1853 command = NULL; 1854 if (temp_file_name != NULL) { 1855 free_name(temp_file_name); 1856 } 1857 temp_file_name = NULL; 1858 1859 Property spro = get_prop(sunpro_dependencies->prop, macro_prop); 1860 if(spro != NULL) { 1861 Name val = spro->body.macro.value; 1862 if(val != NULL) { 1863 free_name(val); 1864 spro->body.macro.value = NULL; 1865 } 1866 } 1867 spro = get_prop(sunpro_dependencies->prop, env_mem_prop); 1868 if(spro) { 1869 char *val = spro->body.env_mem.value; 1870 if(val != NULL) { 1871 /* 1872 * Do not return memory allocated for SUNPRO_DEPENDENCIES 1873 * It will be returned in setvar_daemon() in macro.cc 1874 */ 1875 // retmem_mb(val); 1876 spro->body.env_mem.value = NULL; 1877 } 1878 } 1879 1880 return result; 1881 } 1882 1883 1884 1885 /* 1886 * vpath_translation(cmd) 1887 * 1888 * Translates one command line by 1889 * checking each word. If the word has an alias it is translated. 1890 * 1891 * Return value: 1892 * The translated command 1893 * 1894 * Parameters: 1895 * cmd Command to translate 1896 * 1897 * Global variables used: 1898 */ 1899 Name 1900 vpath_translation(register Name cmd) 1901 { 1902 wchar_t buffer[STRING_BUFFER_LENGTH]; 1903 String_rec new_cmd; 1904 wchar_t *p; 1905 wchar_t *start; 1906 1907 if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) { 1908 return cmd; 1909 } 1910 INIT_STRING_FROM_STACK(new_cmd, buffer); 1911 1912 Wstring wcb(cmd); 1913 p = wcb.get_string(); 1914 1915 while (*p != (int) nul_char) { 1916 while (iswspace(*p) && (*p != (int) nul_char)) { 1917 append_char(*p++, &new_cmd); 1918 } 1919 start = p; 1920 while (!iswspace(*p) && (*p != (int) nul_char)) { 1921 p++; 1922 } 1923 cmd = GETNAME(start, p - start); 1924 if (cmd->has_vpath_alias_prop) { 1925 cmd = get_prop(cmd->prop, vpath_alias_prop)-> 1926 body.vpath_alias.alias; 1927 APPEND_NAME(cmd, 1928 &new_cmd, 1929 (int) cmd->hash.length); 1930 } else { 1931 append_string(start, &new_cmd, p - start); 1932 } 1933 } 1934 cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH); 1935 if (new_cmd.free_after_use) { 1936 retmem(new_cmd.buffer.start); 1937 } 1938 return cmd; 1939 } 1940 1941 /* 1942 * check_state(temp_file_name) 1943 * 1944 * Reads and checks the state changed by the previously executed command. 1945 * 1946 * Parameters: 1947 * temp_file_name The auto dependency temp file 1948 * 1949 * Global variables used: 1950 */ 1951 void 1952 check_state(Name temp_file_name) 1953 { 1954 if (!keep_state) { 1955 return; 1956 } 1957 1958 /* 1959 * Then read the temp file that now might 1960 * contain dependency reports from utilities 1961 */ 1962 read_dependency_file(temp_file_name); 1963 1964 /* 1965 * And reread .make.state if it 1966 * changed (the command ran recursive makes) 1967 */ 1968 check_read_state_file(); 1969 if (temp_file_name != NULL) { 1970 (void) unlink(temp_file_name->string_mb); 1971 } 1972 } 1973 1974 /* 1975 * read_dependency_file(filename) 1976 * 1977 * Read the temp file used for reporting dependencies to make 1978 * 1979 * Parameters: 1980 * filename The name of the file with the state info 1981 * 1982 * Global variables used: 1983 * makefile_type The type of makefile being read 1984 * read_trace_level Debug flag 1985 * temp_file_number The always increasing number for unique files 1986 * trace_reader Debug flag 1987 */ 1988 static void 1989 read_dependency_file(register Name filename) 1990 { 1991 register Makefile_type save_makefile_type; 1992 1993 if (filename == NULL) { 1994 return; 1995 } 1996 filename->stat.time = file_no_time; 1997 if (exists(filename) > file_doesnt_exist) { 1998 save_makefile_type = makefile_type; 1999 makefile_type = reading_cpp_file; 2000 if (read_trace_level > 1) { 2001 trace_reader = true; 2002 } 2003 temp_file_number++; 2004 (void) read_simple_file(filename, 2005 false, 2006 false, 2007 false, 2008 false, 2009 false, 2010 false); 2011 trace_reader = false; 2012 makefile_type = save_makefile_type; 2013 } 2014 } 2015 2016 /* 2017 * check_read_state_file() 2018 * 2019 * Check if .make.state has changed 2020 * If it has we reread it 2021 * 2022 * Parameters: 2023 * 2024 * Global variables used: 2025 * make_state Make state file name 2026 * makefile_type Type of makefile being read 2027 * read_trace_level Debug flag 2028 * trace_reader Debug flag 2029 */ 2030 static void 2031 check_read_state_file(void) 2032 { 2033 timestruc_t previous = make_state->stat.time; 2034 register Makefile_type save_makefile_type; 2035 register Property makefile; 2036 2037 make_state->stat.time = file_no_time; 2038 if ((exists(make_state) == file_doesnt_exist) || 2039 (make_state->stat.time == previous)) { 2040 return; 2041 } 2042 save_makefile_type = makefile_type; 2043 makefile_type = rereading_statefile; 2044 /* Make sure we clear the old cached contents of .make.state */ 2045 makefile = maybe_append_prop(make_state, makefile_prop); 2046 if (makefile->body.makefile.contents != NULL) { 2047 retmem(makefile->body.makefile.contents); 2048 makefile->body.makefile.contents = NULL; 2049 } 2050 if (read_trace_level > 1) { 2051 trace_reader = true; 2052 } 2053 temp_file_number++; 2054 (void) read_simple_file(make_state, 2055 false, 2056 false, 2057 false, 2058 false, 2059 false, 2060 true); 2061 trace_reader = false; 2062 makefile_type = save_makefile_type; 2063 } 2064 2065 /* 2066 * do_assign(line, target) 2067 * 2068 * Handles runtime assignments for command lines prefixed with "=". 2069 * 2070 * Parameters: 2071 * line The command that contains an assignment 2072 * target The Name of the target, used for error reports 2073 * 2074 * Global variables used: 2075 * assign_done Set to indicate doname needs to reprocess 2076 */ 2077 static void 2078 do_assign(register Name line, register Name target) 2079 { 2080 Wstring wcb(line); 2081 register wchar_t *string = wcb.get_string(); 2082 register wchar_t *equal; 2083 register Name name; 2084 register Boolean append = false; 2085 2086 /* 2087 * If any runtime assignments are done, doname() must reprocess all 2088 * targets in the future since the macro values used to build the 2089 * command lines for the targets might have changed. 2090 */ 2091 assign_done = true; 2092 /* Skip white space. */ 2093 while (iswspace(*string)) { 2094 string++; 2095 } 2096 equal = string; 2097 /* Find "+=" or "=". */ 2098 while (!iswspace(*equal) && 2099 (*equal != (int) plus_char) && 2100 (*equal != (int) equal_char)) { 2101 equal++; 2102 } 2103 /* Internalize macro name. */ 2104 name = GETNAME(string, equal - string); 2105 /* Skip over "+=" "=". */ 2106 while (!((*equal == (int) nul_char) || 2107 (*equal == (int) equal_char) || 2108 (*equal == (int) plus_char))) { 2109 equal++; 2110 } 2111 switch (*equal) { 2112 case nul_char: 2113 fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"), 2114 line->string_mb, 2115 target->string_mb); 2116 case plus_char: 2117 append = true; 2118 equal++; 2119 break; 2120 } 2121 equal++; 2122 /* Skip over whitespace in front of value. */ 2123 while (iswspace(*equal)) { 2124 equal++; 2125 } 2126 /* Enter new macro value. */ 2127 enter_equal(name, 2128 GETNAME(equal, wcb.get_string() + line->hash.length - equal), 2129 append); 2130 } 2131 2132 /* 2133 * build_command_strings(target, line) 2134 * 2135 * Builds the command string to used when 2136 * building a target. If the string is different from the previous one 2137 * is_out_of_date is set. 2138 * 2139 * Parameters: 2140 * target Target to build commands for 2141 * line Where to stuff result 2142 * 2143 * Global variables used: 2144 * c_at The Name "@", used to set macro value 2145 * command_changed Set if command is different from old 2146 * debug_level Should we trace activities? 2147 * do_not_exec_rule Always echo when running -n 2148 * empty_name The Name "", used for empty rule 2149 * funny Semantics of characters 2150 * ignore_errors Used to init field for line 2151 * is_conditional Set to false befor evaling macro, checked 2152 * after expanding macros 2153 * keep_state Indicates that .KEEP_STATE is on 2154 * make_word_mentioned Set by macro eval, inits field for cmd 2155 * query The Name "?", used to set macro value 2156 * query_mentioned Set by macro eval, inits field for cmd 2157 * recursion_level Used for tracing 2158 * silent Used to init field for line 2159 */ 2160 static void 2161 build_command_strings(Name target, register Property line) 2162 { 2163 String_rec command_line; 2164 register Cmd_line command_template = line->body.line.command_template; 2165 register Cmd_line *insert = &line->body.line.command_used; 2166 register Cmd_line used = *insert; 2167 wchar_t buffer[STRING_BUFFER_LENGTH]; 2168 wchar_t *start; 2169 Name new_command_line; 2170 register Boolean new_command_longer = false; 2171 register Boolean ignore_all_command_dependency = true; 2172 Property member; 2173 static Name less_name; 2174 static Name percent_name; 2175 static Name star; 2176 Name tmp_name; 2177 2178 if (less_name == NULL) { 2179 MBSTOWCS(wcs_buffer, "<"); 2180 less_name = GETNAME(wcs_buffer, FIND_LENGTH); 2181 MBSTOWCS(wcs_buffer, "%"); 2182 percent_name = GETNAME(wcs_buffer, FIND_LENGTH); 2183 MBSTOWCS(wcs_buffer, "*"); 2184 star = GETNAME(wcs_buffer, FIND_LENGTH); 2185 } 2186 2187 /* We have to check if a target depends on conditional macros */ 2188 /* Targets that do must be reprocessed by doname() each time around */ 2189 /* since the macro values used when building the target might have */ 2190 /* changed */ 2191 conditional_macro_used = false; 2192 /* If we are building a lib.a(member) target $@ should be bound */ 2193 /* to lib.a */ 2194 if (target->is_member && 2195 ((member = get_prop(target->prop, member_prop)) != NULL)) { 2196 target = member->body.member.library; 2197 } 2198 /* If we are building a "::" help target $@ should be bound to */ 2199 /* the real target name */ 2200 /* A lib.a(member) target is never :: */ 2201 if (target->has_target_prop) { 2202 target = get_prop(target->prop, target_prop)-> 2203 body.target.target; 2204 } 2205 /* Bind the magic macros that make supplies */ 2206 tmp_name = target; 2207 if(tmp_name != NULL) { 2208 if (tmp_name->has_vpath_alias_prop) { 2209 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> 2210 body.vpath_alias.alias; 2211 } 2212 } 2213 (void) SETVAR(c_at, tmp_name, false); 2214 2215 tmp_name = line->body.line.star; 2216 if(tmp_name != NULL) { 2217 if (tmp_name->has_vpath_alias_prop) { 2218 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> 2219 body.vpath_alias.alias; 2220 } 2221 } 2222 (void) SETVAR(star, tmp_name, false); 2223 2224 tmp_name = line->body.line.less; 2225 if(tmp_name != NULL) { 2226 if (tmp_name->has_vpath_alias_prop) { 2227 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> 2228 body.vpath_alias.alias; 2229 } 2230 } 2231 (void) SETVAR(less_name, tmp_name, false); 2232 2233 tmp_name = line->body.line.percent; 2234 if(tmp_name != NULL) { 2235 if (tmp_name->has_vpath_alias_prop) { 2236 tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> 2237 body.vpath_alias.alias; 2238 } 2239 } 2240 (void) SETVAR(percent_name, tmp_name, false); 2241 2242 /* $? is seldom used and it is expensive to build */ 2243 /* so we store the list form and build the string on demand */ 2244 Chain query_list = NULL; 2245 Chain *query_list_tail = &query_list; 2246 2247 for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) { 2248 *query_list_tail = ALLOC(Chain); 2249 (*query_list_tail)->name = ch->name; 2250 if ((*query_list_tail)->name->has_vpath_alias_prop) { 2251 (*query_list_tail)->name = 2252 get_prop((*query_list_tail)->name->prop, 2253 vpath_alias_prop)->body.vpath_alias.alias; 2254 } 2255 (*query_list_tail)->next = NULL; 2256 query_list_tail = &(*query_list_tail)->next; 2257 } 2258 (void) setvar_daemon(query, 2259 (Name) query_list, 2260 false, 2261 chain_daemon, 2262 false, 2263 debug_level); 2264 2265 /* build $^ */ 2266 Chain hat_list = NULL; 2267 Chain *hat_list_tail = &hat_list; 2268 2269 for (Dependency dependency = line->body.line.dependencies; 2270 dependency != NULL; 2271 dependency = dependency->next) { 2272 /* skip automatic dependencies */ 2273 if (!dependency->automatic) { 2274 if ((dependency->name != force) && 2275 (dependency->stale == false)) { 2276 *hat_list_tail = ALLOC(Chain); 2277 2278 if (dependency->name->is_member && 2279 (get_prop(dependency->name->prop, member_prop) != NULL)) { 2280 (*hat_list_tail)->name = 2281 get_prop(dependency->name->prop, 2282 member_prop)->body.member.member; 2283 } else { 2284 (*hat_list_tail)->name = dependency->name; 2285 } 2286 2287 if((*hat_list_tail)->name != NULL) { 2288 if ((*hat_list_tail)->name->has_vpath_alias_prop) { 2289 (*hat_list_tail)->name = 2290 get_prop((*hat_list_tail)->name->prop, 2291 vpath_alias_prop)->body.vpath_alias.alias; 2292 } 2293 } 2294 2295 (*hat_list_tail)->next = NULL; 2296 hat_list_tail = &(*hat_list_tail)->next; 2297 } 2298 } 2299 } 2300 (void) setvar_daemon(hat, 2301 (Name) hat_list, 2302 false, 2303 chain_daemon, 2304 false, 2305 debug_level); 2306 2307 /* We have two command sequences we need to handle */ 2308 /* The old one that we probably read from .make.state */ 2309 /* and the new one we are building that will replace the old one */ 2310 /* Even when KEEP_STATE is not on we build a new command sequence and store */ 2311 /* it in the line prop. This command sequence is then executed by */ 2312 /* run_command(). If KEEP_STATE is on it is also later written to */ 2313 /* .make.state. The routine replaces the old command line by line with the */ 2314 /* new one trying to reuse Cmd_lines */ 2315 2316 /* If there is no old command_used we have to start creating */ 2317 /* Cmd_lines to keep the new cmd in */ 2318 if (used == NULL) { 2319 new_command_longer = true; 2320 *insert = used = ALLOC(Cmd_line); 2321 used->next = NULL; 2322 used->command_line = NULL; 2323 insert = &used->next; 2324 } 2325 /* Run thru the template for the new command and build the expanded */ 2326 /* new command lines */ 2327 for (; 2328 command_template != NULL; 2329 command_template = command_template->next, insert = &used->next, used = *insert) { 2330 /* If there is no old command_used Cmd_line we need to */ 2331 /* create one and say that cmd consistency failed */ 2332 if (used == NULL) { 2333 new_command_longer = true; 2334 *insert = used = ALLOC(Cmd_line); 2335 used->next = NULL; 2336 used->command_line = empty_name; 2337 } 2338 /* Prepare the Cmd_line for the processing */ 2339 /* The command line prefixes "@-=?" are stripped and that */ 2340 /* information is saved in the Cmd_line */ 2341 used->assign = false; 2342 used->ignore_error = ignore_errors; 2343 used->silent = silent; 2344 used->always_exec = false; 2345 /* Expand the macros in the command line */ 2346 INIT_STRING_FROM_STACK(command_line, buffer); 2347 make_word_mentioned = 2348 query_mentioned = 2349 false; 2350 expand_value(command_template->command_line, &command_line, true); 2351 /* If the macro $(MAKE) is mentioned in the command */ 2352 /* "make -n" runs actually execute the command */ 2353 used->make_refd = make_word_mentioned; 2354 used->ignore_command_dependency = query_mentioned; 2355 /* Strip the prefixes */ 2356 start = command_line.buffer.start; 2357 for (; 2358 iswspace(*start) || 2359 (get_char_semantics_value(*start) & (int) command_prefix_sem); 2360 start++) { 2361 switch (*start) { 2362 case question_char: 2363 used->ignore_command_dependency = true; 2364 break; 2365 case exclam_char: 2366 used->ignore_command_dependency = false; 2367 break; 2368 case equal_char: 2369 used->assign = true; 2370 break; 2371 case hyphen_char: 2372 used->ignore_error = true; 2373 break; 2374 case at_char: 2375 if (!do_not_exec_rule) { 2376 used->silent = true; 2377 } 2378 break; 2379 case plus_char: 2380 if(posix) { 2381 used->always_exec = true; 2382 } 2383 break; 2384 } 2385 } 2386 /* If all command lines of the template are prefixed with "?"*/ 2387 /* the VIRTUAL_ROOT is not used for cmd consistency checks */ 2388 if (!used->ignore_command_dependency) { 2389 ignore_all_command_dependency = false; 2390 } 2391 /* Internalize the expanded and stripped command line */ 2392 new_command_line = GETNAME(start, FIND_LENGTH); 2393 if ((used->command_line == NULL) && 2394 (line->body.line.sccs_command)) { 2395 used->command_line = new_command_line; 2396 new_command_longer = false; 2397 } 2398 /* Compare it with the old one for command consistency */ 2399 if (used->command_line != new_command_line) { 2400 Name vpath_translated = vpath_translation(new_command_line); 2401 if (keep_state && 2402 !used->ignore_command_dependency && (vpath_translated != used->command_line)) { 2403 if (debug_level > 0) { 2404 if (used->command_line != NULL 2405 && *used->command_line->string_mb != 2406 '\0') { 2407 (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"), 2408 recursion_level, 2409 "", 2410 target->string_mb, 2411 vpath_translated->string_mb, 2412 recursion_level, 2413 "", 2414 used-> 2415 command_line-> 2416 string_mb); 2417 } else { 2418 (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"), 2419 recursion_level, 2420 "", 2421 target->string_mb, 2422 vpath_translated->string_mb, 2423 recursion_level, 2424 ""); 2425 } 2426 } 2427 command_changed = true; 2428 line->body.line.is_out_of_date = true; 2429 } 2430 used->command_line = new_command_line; 2431 } 2432 if (command_line.free_after_use) { 2433 retmem(command_line.buffer.start); 2434 } 2435 } 2436 /* Check if the old command is longer than the new for */ 2437 /* command consistency */ 2438 if (used != NULL) { 2439 *insert = NULL; 2440 if (keep_state && 2441 !ignore_all_command_dependency) { 2442 if (debug_level > 0) { 2443 (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"), 2444 recursion_level, 2445 "", 2446 target->string_mb); 2447 } 2448 command_changed = true; 2449 line->body.line.is_out_of_date = true; 2450 } 2451 } 2452 /* Check if the new command is longer than the old command for */ 2453 /* command consistency */ 2454 if (new_command_longer && 2455 !ignore_all_command_dependency && 2456 keep_state) { 2457 if (debug_level > 0) { 2458 (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"), 2459 recursion_level, 2460 "", 2461 target->string_mb); 2462 } 2463 command_changed = true; 2464 line->body.line.is_out_of_date = true; 2465 } 2466 /* Unbind the magic macros */ 2467 (void) SETVAR(c_at, (Name) NULL, false); 2468 (void) SETVAR(star, (Name) NULL, false); 2469 (void) SETVAR(less_name, (Name) NULL, false); 2470 (void) SETVAR(percent_name, (Name) NULL, false); 2471 (void) SETVAR(query, (Name) NULL, false); 2472 if (query_list != NULL) { 2473 delete_query_chain(query_list); 2474 } 2475 (void) SETVAR(hat, (Name) NULL, false); 2476 if (hat_list != NULL) { 2477 delete_query_chain(hat_list); 2478 } 2479 2480 if (conditional_macro_used) { 2481 target->conditional_macro_list = cond_macro_list; 2482 cond_macro_list = NULL; 2483 target->depends_on_conditional = true; 2484 } 2485 } 2486 2487 /* 2488 * touch_command(line, target, result) 2489 * 2490 * If this is an "make -t" run we do this. 2491 * We touch all targets in the target group ("foo + fie:") if any. 2492 * 2493 * Return value: 2494 * Indicates if the command failed or not 2495 * 2496 * Parameters: 2497 * line The command line to update 2498 * target The target we are touching 2499 * result Initial value for the result we return 2500 * 2501 * Global variables used: 2502 * do_not_exec_rule Indicates that -n is on 2503 * silent Do not echo commands 2504 */ 2505 static Doname 2506 touch_command(register Property line, register Name target, Doname result) 2507 { 2508 Name name; 2509 register Chain target_group; 2510 String_rec touch_string; 2511 wchar_t buffer[MAXPATHLEN]; 2512 Name touch_cmd; 2513 Cmd_line rule; 2514 2515 for (name = target, target_group = NULL; name != NULL;) { 2516 if (!name->is_member) { 2517 /* 2518 * Build a touch command that can be passed 2519 * to dosys(). If KEEP_STATE is on, "make -t" 2520 * will save the proper command, not the 2521 * "touch" in .make.state. 2522 */ 2523 INIT_STRING_FROM_STACK(touch_string, buffer); 2524 MBSTOWCS(wcs_buffer, NOCATGETS("touch ")); 2525 append_string(wcs_buffer, &touch_string, FIND_LENGTH); 2526 touch_cmd = name; 2527 if (name->has_vpath_alias_prop) { 2528 touch_cmd = get_prop(name->prop, 2529 vpath_alias_prop)-> 2530 body.vpath_alias.alias; 2531 } 2532 APPEND_NAME(touch_cmd, 2533 &touch_string, 2534 FIND_LENGTH); 2535 touch_cmd = GETNAME(touch_string.buffer.start, 2536 FIND_LENGTH); 2537 if (touch_string.free_after_use) { 2538 retmem(touch_string.buffer.start); 2539 } 2540 if (!silent || 2541 do_not_exec_rule && 2542 (target_group == NULL)) { 2543 (void) printf("%s\n", touch_cmd->string_mb); 2544 } 2545 /* Run the touch command, or simulate it */ 2546 if (!do_not_exec_rule) { 2547 result = dosys(touch_cmd, 2548 false, 2549 false, 2550 false, 2551 false, 2552 name); 2553 } else { 2554 result = build_ok; 2555 } 2556 } else { 2557 result = build_ok; 2558 } 2559 if (target_group == NULL) { 2560 target_group = line->body.line.target_group; 2561 } else { 2562 target_group = target_group->next; 2563 } 2564 if (target_group != NULL) { 2565 name = target_group->name; 2566 } else { 2567 name = NULL; 2568 } 2569 } 2570 return result; 2571 } 2572 2573 /* 2574 * update_target(line, result) 2575 * 2576 * updates the status of a target after executing its commands. 2577 * 2578 * Parameters: 2579 * line The command line block to update 2580 * result Indicates that build is OK so can update 2581 * 2582 * Global variables used: 2583 * do_not_exec_rule Indicates that -n is on 2584 * touch Fake the new timestamp if we are just touching 2585 */ 2586 void 2587 update_target(Property line, Doname result) 2588 { 2589 Name target; 2590 Chain target_group; 2591 Property line2; 2592 timestruc_t old_stat_time; 2593 Property member; 2594 2595 /* 2596 * [tolik] Additional fix for bug 1063790. It was fixed 2597 * for serial make long ago, but DMake dumps core when 2598 * target is a symlink and sccs file is newer then target. 2599 * In this case, finish_children() calls update_target() 2600 * with line==NULL. 2601 */ 2602 if(line == NULL) { 2603 /* XXX. Should we do anything here? */ 2604 return; 2605 } 2606 2607 target = line->body.line.target; 2608 2609 if ((result == build_ok) && (line->body.line.command_used != NULL)) { 2610 if (do_not_exec_rule || 2611 touch || 2612 (target->is_member && 2613 (line->body.line.command_template != NULL) && 2614 (line->body.line.command_template->command_line->string_mb[0] == 0) && 2615 (line->body.line.command_template->next == NULL))) { 2616 /* If we are simulating execution we need to fake a */ 2617 /* new timestamp for the target we didnt build */ 2618 target->stat.time = file_max_time; 2619 } else { 2620 /* 2621 * If we really built the target we read the new 2622 * timestamp. 2623 * Fix for bug #1110906: if .c file is newer than 2624 * the corresponding .o file which is in an archive 2625 * file, make will compile the .c file but it won't 2626 * update the object in the .a file. 2627 */ 2628 old_stat_time = target->stat.time; 2629 target->stat.time = file_no_time; 2630 (void) exists(target); 2631 if ((target->is_member) && 2632 (target->stat.time == old_stat_time)) { 2633 member = get_prop(target->prop, member_prop); 2634 if (member != NULL) { 2635 target->stat.time = member->body.member.library->stat.time; 2636 target->stat.time.tv_sec++; 2637 } 2638 } 2639 } 2640 /* If the target is part of a group we need to propagate the */ 2641 /* result of the run to all members */ 2642 for (target_group = line->body.line.target_group; 2643 target_group != NULL; 2644 target_group = target_group->next) { 2645 target_group->name->stat.time = target->stat.time; 2646 line2 = maybe_append_prop(target_group->name, 2647 line_prop); 2648 line2->body.line.command_used = 2649 line->body.line.command_used; 2650 line2->body.line.target = target_group->name; 2651 } 2652 } 2653 target->has_built = true; 2654 } 2655 2656 /* 2657 * sccs_get(target, command) 2658 * 2659 * Figures out if it possible to sccs get a file 2660 * and builds the command to do it if it is. 2661 * 2662 * Return value: 2663 * Indicates if sccs get failed or not 2664 * 2665 * Parameters: 2666 * target Target to get 2667 * command Where to deposit command to use 2668 * 2669 * Global variables used: 2670 * debug_level Should we trace activities? 2671 * recursion_level Used for tracing 2672 * sccs_get_rule The rule to used for sccs getting 2673 */ 2674 static Doname 2675 sccs_get(register Name target, register Property *command) 2676 { 2677 register int result; 2678 char link[MAXPATHLEN]; 2679 String_rec string; 2680 wchar_t name[MAXPATHLEN]; 2681 register wchar_t *p; 2682 timestruc_t sccs_time; 2683 register Property line; 2684 int sym_link_depth = 0; 2685 2686 /* For sccs, we need to chase symlinks. */ 2687 while (target->stat.is_sym_link) { 2688 if (sym_link_depth++ > 90) { 2689 fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."), 2690 target->string_mb); 2691 } 2692 /* Read the value of the link. */ 2693 result = readlink_vroot(target->string_mb, 2694 link, 2695 sizeof(link), 2696 NULL, 2697 VROOT_DEFAULT); 2698 if (result == -1) { 2699 fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"), 2700 target->string_mb, errmsg(errno)); 2701 } 2702 link[result] = 0; 2703 /* Use the value to build the proper filename. */ 2704 INIT_STRING_FROM_STACK(string, name); 2705 2706 Wstring wcb(target); 2707 if ((link[0] != slash_char) && 2708 ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) { 2709 append_string(wcb.get_string(), &string, p - wcb.get_string() + 1); 2710 } 2711 append_string(link, &string, result); 2712 /* Replace the old name with the translated name. */ 2713 target = normalize_name(string.buffer.start, string.text.p - string.buffer.start); 2714 (void) exists(target); 2715 if (string.free_after_use) { 2716 retmem(string.buffer.start); 2717 } 2718 } 2719 2720 /* 2721 * read_dir() also reads the ?/SCCS dir and saves information 2722 * about which files have SCSC/s. files. 2723 */ 2724 if (target->stat.has_sccs == DONT_KNOW_SCCS) { 2725 read_directory_of_file(target); 2726 } 2727 switch (target->stat.has_sccs) { 2728 case DONT_KNOW_SCCS: 2729 /* We dont know by now there is no SCCS/s.* */ 2730 target->stat.has_sccs = NO_SCCS; 2731 case NO_SCCS: 2732 /* 2733 * If there is no SCCS/s.* but the plain file exists, 2734 * we say things are OK. 2735 */ 2736 if (target->stat.time > file_doesnt_exist) { 2737 return build_ok; 2738 } 2739 /* If we cant find the plain file, we give up. */ 2740 return build_dont_know; 2741 case HAS_SCCS: 2742 /* 2743 * Pay dirt. We now need to figure out if the plain file 2744 * is out of date relative to the SCCS/s.* file. 2745 */ 2746 sccs_time = exists(get_prop(target->prop, 2747 sccs_prop)->body.sccs.file); 2748 break; 2749 } 2750 2751 if ((!target->has_complained && 2752 (sccs_time != file_doesnt_exist) && 2753 (sccs_get_rule != NULL))) { 2754 /* only checking */ 2755 if (command == NULL) { 2756 return build_ok; 2757 } 2758 /* 2759 * We provide a command line for the target. The line is a 2760 * "sccs get" command from default.mk. 2761 */ 2762 line = maybe_append_prop(target, line_prop); 2763 *command = line; 2764 if (sccs_time > target->stat.time) { 2765 /* 2766 * And only if the plain file is out of date do we 2767 * request execution of the command. 2768 */ 2769 line->body.line.is_out_of_date = true; 2770 if (debug_level > 0) { 2771 (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"), 2772 recursion_level, 2773 "", 2774 target->string_mb); 2775 } 2776 } 2777 line->body.line.sccs_command = true; 2778 line->body.line.command_template = sccs_get_rule; 2779 if(!svr4 && (!allrules_read || posix)) { 2780 if((target->prop) && 2781 (target->prop->body.sccs.file) && 2782 (target->prop->body.sccs.file->string_mb)) { 2783 if((strlen(target->prop->body.sccs.file->string_mb) == 2784 strlen(target->string_mb) + 2) && 2785 (target->prop->body.sccs.file->string_mb[0] == 's') && 2786 (target->prop->body.sccs.file->string_mb[1] == '.')) { 2787 2788 line->body.line.command_template = get_posix_rule; 2789 } 2790 } 2791 } 2792 line->body.line.target = target; 2793 /* 2794 * Also make sure the rule is build with $* and $< 2795 * bound properly. 2796 */ 2797 line->body.line.star = NULL; 2798 line->body.line.less = NULL; 2799 line->body.line.percent = NULL; 2800 return build_ok; 2801 } 2802 return build_dont_know; 2803 } 2804 2805 /* 2806 * read_directory_of_file(file) 2807 * 2808 * Reads the directory the specified file lives in. 2809 * 2810 * Parameters: 2811 * file The file we need to read dir for 2812 * 2813 * Global variables used: 2814 * dot The Name ".", used as the default dir 2815 */ 2816 void 2817 read_directory_of_file(register Name file) 2818 { 2819 2820 Wstring file_string(file); 2821 wchar_t * wcb = file_string.get_string(); 2822 wchar_t usr_include_buf[MAXPATHLEN]; 2823 wchar_t usr_include_sys_buf[MAXPATHLEN]; 2824 2825 register Name directory = dot; 2826 register wchar_t *p = (wchar_t *) wsrchr(wcb, 2827 (int) slash_char); 2828 register int length = p - wcb; 2829 static Name usr_include; 2830 static Name usr_include_sys; 2831 2832 if (usr_include == NULL) { 2833 MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include")); 2834 usr_include = GETNAME(usr_include_buf, FIND_LENGTH); 2835 MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys")); 2836 usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH); 2837 } 2838 2839 /* 2840 * If the filename contains a "/" we have to extract the path 2841 * Else the path defaults to ".". 2842 */ 2843 if (p != NULL) { 2844 /* 2845 * Check some popular directories first to possibly 2846 * save time. Compare string length first to gain speed. 2847 */ 2848 if ((usr_include->hash.length == length) && 2849 IS_WEQUALN(usr_include_buf, 2850 wcb, 2851 length)) { 2852 directory = usr_include; 2853 } else if ((usr_include_sys->hash.length == length) && 2854 IS_WEQUALN(usr_include_sys_buf, 2855 wcb, 2856 length)) { 2857 directory = usr_include_sys; 2858 } else { 2859 directory = GETNAME(wcb, length); 2860 } 2861 } 2862 (void) read_dir(directory, 2863 (wchar_t *) NULL, 2864 (Property) NULL, 2865 (wchar_t *) NULL); 2866 } 2867 2868 /* 2869 * add_pattern_conditionals(target) 2870 * 2871 * Scan the list of conditionals defined for pattern targets and add any 2872 * that match this target to its list of conditionals. 2873 * 2874 * Parameters: 2875 * target The target we should add conditionals for 2876 * 2877 * Global variables used: 2878 * conditionals The list of pattern conditionals 2879 */ 2880 static void 2881 add_pattern_conditionals(register Name target) 2882 { 2883 register Property conditional; 2884 Property new_prop; 2885 Property *previous; 2886 Name_rec dummy; 2887 wchar_t *pattern; 2888 wchar_t *percent; 2889 int length; 2890 2891 Wstring wcb(target); 2892 Wstring wcb1; 2893 2894 for (conditional = get_prop(conditionals->prop, conditional_prop); 2895 conditional != NULL; 2896 conditional = get_prop(conditional->next, conditional_prop)) { 2897 wcb1.init(conditional->body.conditional.target); 2898 pattern = wcb1.get_string(); 2899 if (pattern[1] != 0) { 2900 percent = (wchar_t *) wschr(pattern, (int) percent_char); 2901 if (!wcb.equaln(pattern, percent-pattern) || 2902 !IS_WEQUAL(wcb.get_string(wcb.length()-wslen(percent+1)), percent+1)) { 2903 continue; 2904 } 2905 } 2906 for (previous = &target->prop; 2907 *previous != NULL; 2908 previous = &(*previous)->next) { 2909 if (((*previous)->type == conditional_prop) && 2910 ((*previous)->body.conditional.sequence > 2911 conditional->body.conditional.sequence)) { 2912 break; 2913 } 2914 } 2915 if (*previous == NULL) { 2916 new_prop = append_prop(target, conditional_prop); 2917 } else { 2918 dummy.prop = NULL; 2919 new_prop = append_prop(&dummy, conditional_prop); 2920 new_prop->next = *previous; 2921 *previous = new_prop; 2922 } 2923 target->conditional_cnt++; 2924 new_prop->body.conditional = conditional->body.conditional; 2925 } 2926 } 2927 2928 /* 2929 * set_locals(target, old_locals) 2930 * 2931 * Sets any conditional macros for the target. 2932 * Each target carries a possibly empty set of conditional properties. 2933 * 2934 * Parameters: 2935 * target The target to set conditional macros for 2936 * old_locals Space to store old values in 2937 * 2938 * Global variables used: 2939 * debug_level Should we trace activity? 2940 * is_conditional We need to preserve this value 2941 * recursion_level Used for tracing 2942 */ 2943 void 2944 set_locals(register Name target, register Property old_locals) 2945 { 2946 register Property conditional; 2947 register int i; 2948 register Boolean saved_conditional_macro_used; 2949 Chain cond_name; 2950 Chain cond_chain; 2951 2952 if (target->dont_activate_cond_values) { 2953 return; 2954 } 2955 2956 saved_conditional_macro_used = conditional_macro_used; 2957 2958 /* Scan the list of conditional properties and apply each one */ 2959 for (conditional = get_prop(target->prop, conditional_prop), i = 0; 2960 conditional != NULL; 2961 conditional = get_prop(conditional->next, conditional_prop), 2962 i++) { 2963 /* Save the old value */ 2964 old_locals[i].body.macro = 2965 maybe_append_prop(conditional->body.conditional.name, 2966 macro_prop)->body.macro; 2967 if (debug_level > 1) { 2968 (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "), 2969 recursion_level, 2970 ""); 2971 } 2972 /* Set the conditional value. Macros are expanded when the */ 2973 /* macro is refd as usual */ 2974 if ((conditional->body.conditional.name != virtual_root) || 2975 (conditional->body.conditional.value != virtual_root)) { 2976 (void) SETVAR(conditional->body.conditional.name, 2977 conditional->body.conditional.value, 2978 (Boolean) conditional->body.conditional.append); 2979 } 2980 cond_name = ALLOC(Chain); 2981 cond_name->name = conditional->body.conditional.name; 2982 } 2983 /* Put this target on the front of the chain of conditional targets */ 2984 cond_chain = ALLOC(Chain); 2985 cond_chain->name = target; 2986 cond_chain->next = conditional_targets; 2987 conditional_targets = cond_chain; 2988 conditional_macro_used = saved_conditional_macro_used; 2989 } 2990 2991 /* 2992 * reset_locals(target, old_locals, conditional, index) 2993 * 2994 * Removes any conditional macros for the target. 2995 * 2996 * Parameters: 2997 * target The target we are retoring values for 2998 * old_locals The values to restore 2999 * conditional The first conditional block for the target 3000 * index into the old_locals vector 3001 * Global variables used: 3002 * debug_level Should we trace activities? 3003 * recursion_level Used for tracing 3004 */ 3005 void 3006 reset_locals(register Name target, register Property old_locals, register Property conditional, register int index) 3007 { 3008 register Property this_conditional; 3009 Chain cond_chain; 3010 3011 if (target->dont_activate_cond_values) { 3012 return; 3013 } 3014 3015 /* Scan the list of conditional properties and restore the old value */ 3016 /* to each one Reverse the order relative to when we assigned macros */ 3017 this_conditional = get_prop(conditional->next, conditional_prop); 3018 if (this_conditional != NULL) { 3019 reset_locals(target, old_locals, this_conditional, index+1); 3020 } else { 3021 /* Remove conditional target from chain */ 3022 if (conditional_targets == NULL || 3023 conditional_targets->name != target) { 3024 warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain")); 3025 } else { 3026 cond_chain = conditional_targets->next; 3027 retmem_mb((caddr_t) conditional_targets); 3028 conditional_targets = cond_chain; 3029 } 3030 } 3031 get_prop(conditional->body.conditional.name->prop, 3032 macro_prop)->body.macro = old_locals[index].body.macro; 3033 if (conditional->body.conditional.name == virtual_root) { 3034 (void) SETVAR(virtual_root, getvar(virtual_root), false); 3035 } 3036 if (debug_level > 1) { 3037 if (old_locals[index].body.macro.value != NULL) { 3038 (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"), 3039 recursion_level, 3040 "", 3041 conditional->body.conditional.name-> 3042 string_mb, 3043 old_locals[index].body.macro.value-> 3044 string_mb); 3045 } else { 3046 (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"), 3047 recursion_level, 3048 "", 3049 conditional->body.conditional.name-> 3050 string_mb); 3051 } 3052 } 3053 } 3054 3055 /* 3056 * check_auto_dependencies(target, auto_count, automatics) 3057 * 3058 * Returns true if the target now has a dependency 3059 * it didn't previously have (saved on automatics). 3060 * 3061 * Return value: 3062 * true if new dependency found 3063 * 3064 * Parameters: 3065 * target Target we check 3066 * auto_count Number of old automatic vars 3067 * automatics Saved old automatics 3068 * 3069 * Global variables used: 3070 * keep_state Indicates that .KEEP_STATE is on 3071 */ 3072 Boolean 3073 check_auto_dependencies(Name target, int auto_count, Name *automatics) 3074 { 3075 Name *p; 3076 int n; 3077 Property line; 3078 Dependency dependency; 3079 3080 if (keep_state) { 3081 if ((line = get_prop(target->prop, line_prop)) == NULL) { 3082 return false; 3083 } 3084 /* Go thru new list of automatic depes */ 3085 for (dependency = line->body.line.dependencies; 3086 dependency != NULL; 3087 dependency = dependency->next) { 3088 /* And make sure that each one existed before we */ 3089 /* built the target */ 3090 if (dependency->automatic && !dependency->stale) { 3091 for (n = auto_count, p = automatics; 3092 n > 0; 3093 n--) { 3094 if (*p++ == dependency->name) { 3095 /* If we can find it on the */ 3096 /* saved list of autos we */ 3097 /* are OK */ 3098 goto not_new; 3099 } 3100 } 3101 /* But if we scan over the old list */ 3102 /* of auto. without finding it it is */ 3103 /* new and we must check it */ 3104 return true; 3105 } 3106 not_new:; 3107 } 3108 return false; 3109 } else { 3110 return false; 3111 } 3112 } 3113 3114 3115 // Recursively delete each of the Chain struct on the chain. 3116 3117 static void 3118 delete_query_chain(Chain ch) 3119 { 3120 if (ch == NULL) { 3121 return; 3122 } else { 3123 delete_query_chain(ch->next); 3124 retmem_mb((char *) ch); 3125 } 3126 } 3127 3128 Doname 3129 target_can_be_built(register Name target) { 3130 Doname result = build_dont_know; 3131 Name true_target = target; 3132 Property line; 3133 3134 if (target == wait_name) { 3135 return(build_ok); 3136 } 3137 /* 3138 * If the target is a constructed one for a "::" target, 3139 * we need to consider that. 3140 */ 3141 if (target->has_target_prop) { 3142 true_target = get_prop(target->prop, 3143 target_prop)->body.target.target; 3144 } 3145 3146 (void) exists(true_target); 3147 3148 if (true_target->state == build_running) { 3149 return(build_running); 3150 } 3151 if (true_target->stat.time != file_doesnt_exist) { 3152 result = build_ok; 3153 } 3154 3155 /* get line property for the target */ 3156 line = get_prop(true_target->prop, line_prop); 3157 3158 /* first check for explicit rule */ 3159 if (line != NULL && line->body.line.command_template != NULL) { 3160 result = build_ok; 3161 } 3162 /* try to find pattern rule */ 3163 if (result == build_dont_know) { 3164 result = find_percent_rule(target, NULL, false); 3165 } 3166 3167 /* try to find double suffix rule */ 3168 if (result == build_dont_know) { 3169 if (target->is_member) { 3170 Property member = get_prop(target->prop, member_prop); 3171 if (member != NULL && member->body.member.member != NULL) { 3172 result = find_ar_suffix_rule(target, member->body.member.member, NULL, false); 3173 } else { 3174 result = find_double_suffix_rule(target, NULL, false); 3175 } 3176 } else { 3177 result = find_double_suffix_rule(target, NULL, false); 3178 } 3179 } 3180 3181 /* try to find suffix rule */ 3182 if ((result == build_dont_know) && second_pass) { 3183 result = find_suffix_rule(target, target, empty_name, NULL, false); 3184 } 3185 3186 /* check for sccs */ 3187 if (result == build_dont_know) { 3188 result = sccs_get(target, NULL); 3189 } 3190 3191 /* try to find dyn target */ 3192 if (result == build_dont_know) { 3193 Name dtarg = find_dyntarget(target); 3194 if (dtarg != NULL) { 3195 result = target_can_be_built(dtarg); 3196 } 3197 } 3198 3199 /* check whether target was mentioned in makefile */ 3200 if (result == build_dont_know) { 3201 if (target->colons != no_colon) { 3202 result = build_ok; 3203 } 3204 } 3205 3206 /* result */ 3207 return result; 3208 }