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