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