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