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