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 2004 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * implicit.c 28 * 29 * Handle suffix and percent rules 30 */ 31 32 /* 33 * Included files 34 */ 35 #include <mk/defs.h> 36 #include <mksh/macro.h> /* expand_value() */ 37 #include <mksh/misc.h> /* retmem() */ 38 #include <libintl.h> 39 40 /* 41 * Defined macros 42 */ 43 44 /* 45 * typedefs & structs 46 */ 47 48 /* 49 * Static variables 50 */ 51 static wchar_t WIDE_NULL[1] = {(wchar_t) nul_char}; 52 53 /* 54 * File table of contents 55 */ 56 extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking); 57 extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking); 58 extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking); 59 extern void build_suffix_list(register Name target_suffix); 60 extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking); 61 static void create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent); 62 static Boolean match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf); 63 static void construct_string_from_pattern(Percent pat_rule, String percent, String result); 64 static Boolean dependency_exists(Name target, Property line); 65 extern Property maybe_append_prop(Name, Property_id); 66 extern void add_target_to_chain(Name target, Chain * query); 67 68 /* 69 * find_suffix_rule(target, target_body, target_suffix, command, rechecking) 70 * 71 * Does the lookup for single and double suffix rules. 72 * It calls build_suffix_list() to build the list of possible suffixes 73 * for the given target. 74 * It then scans the list to find the first possible source file that 75 * exists. This is done by concatenating the body of the target name 76 * (target name less target suffix) and the source suffix and checking 77 * if the resulting file exists. 78 * 79 * Return value: 80 * Indicates if search failed or not 81 * 82 * Parameters: 83 * target The target we need a rule for 84 * target_body The target name without the suffix 85 * target_suffix The suffix of the target 86 * command Pointer to slot to deposit cmd in if found 87 * rechecking true if we are rechecking target which depends 88 * on conditional macro and keep_state is set 89 * 90 * Global variables used: 91 * debug_level Indicates how much tracing to do 92 * recursion_level Used for tracing 93 */ 94 95 static Boolean actual_doname = false; 96 97 /* /tolik/ 98 * fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules. 99 * When make attemps to apply % rule it didn't look for a single suffix rule because 100 * if "doname" is called from "find_percent_rule" argument "implicit" is set to true 101 * and find_suffix_rule was not called. I've commented the checking of "implicit" 102 * in "doname" and make got infinite recursion for SVR4 tilde rules. 103 * Usage of "we_are_in_tilde" is intended to avoid this recursion. 104 */ 105 106 static Boolean we_are_in_tilde = false; 107 108 Doname 109 find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking) 110 { 111 static wchar_t static_string_buf_3M [ 3 * MAXPATHLEN ]; 112 Name true_target = target; 113 wchar_t *sourcename = (wchar_t*)static_string_buf_3M; 114 register wchar_t *put_suffix; 115 register Property source_suffix; 116 register Name source; 117 Doname result; 118 register Property line; 119 extern Boolean tilde_rule; 120 Boolean name_found = true; 121 Boolean posix_tilde_attempt = true; 122 int src_len = MAXPATHLEN + strlen(target_body->string_mb); 123 124 /* 125 * To avoid infinite recursion 126 */ 127 if(we_are_in_tilde) { 128 we_are_in_tilde = false; 129 return(build_dont_know); 130 } 131 132 /* 133 * If the target is a constructed one for a "::" target, 134 * we need to consider that. 135 */ 136 if (target->has_target_prop) { 137 true_target = get_prop(target->prop, 138 target_prop)->body.target.target; 139 } 140 if (debug_level > 1) { 141 (void) printf("%*sfind_suffix_rule(%s,%s,%s)\n", 142 recursion_level, 143 "", 144 true_target->string_mb, 145 target_body->string_mb, 146 target_suffix->string_mb); 147 } 148 if (command != NULL) { 149 if ((true_target->suffix_scan_done == true) && (*command == NULL)) { 150 return build_ok; 151 } 152 } 153 true_target->suffix_scan_done = true; 154 /* 155 * Enter all names from the directory where the target lives as 156 * files that makes sense. 157 * This will make finding the synthesized source possible. 158 */ 159 read_directory_of_file(target_body); 160 /* Cache the suffixes for this target suffix if not done. */ 161 if (!target_suffix->has_read_suffixes) { 162 build_suffix_list(target_suffix); 163 } 164 /* Preload the sourcename vector with the head of the target name. */ 165 if (src_len >= sizeof(static_string_buf_3M)) { 166 sourcename = ALLOC_WC(src_len); 167 } 168 (void) mbstowcs(sourcename, 169 target_body->string_mb, 170 (int) target_body->hash.length); 171 put_suffix = sourcename + target_body->hash.length; 172 /* Scan the suffix list for the target if one exists. */ 173 if (target_suffix->has_suffixes) { 174 posix_attempts: 175 for (source_suffix = get_prop(target_suffix->prop, 176 suffix_prop); 177 source_suffix != NULL; 178 source_suffix = get_prop(source_suffix->next, 179 suffix_prop)) { 180 /* Build the synthesized source name. */ 181 (void) mbstowcs(put_suffix, 182 source_suffix->body. 183 suffix.suffix->string_mb, 184 (int) source_suffix->body. 185 suffix.suffix->hash.length); 186 put_suffix[source_suffix->body. 187 suffix.suffix->hash.length] = 188 (int) nul_char; 189 if (debug_level > 1) { 190 WCSTOMBS(mbs_buffer, sourcename); 191 (void) printf(gettext("%*sTrying %s\n"), 192 recursion_level, 193 "", 194 mbs_buffer); 195 } 196 source = getname_fn(sourcename, FIND_LENGTH, false, &name_found); 197 /* 198 * If the source file is not registered as 199 * a file, this source suffix did not match. 200 */ 201 if(vpath_defined && !posix && !svr4) { 202 (void) exists(source); 203 } 204 if (!source->stat.is_file) { 205 if(!(posix|svr4)) 206 { 207 if(!name_found) { 208 free_name(source); 209 } 210 continue; 211 } 212 213 /* following code will ensure that the corresponding 214 ** tilde rules are executed when corresponding s. file 215 ** exists in the current directory. Though the current 216 ** target ends with a ~ character, there wont be any 217 ** any file in the current directory with that suffix 218 ** as it's fictitious. Even if it exists, it'll 219 ** execute all the rules for the ~ target. 220 */ 221 222 if(source->string_mb[source->hash.length - 1] == '~' && 223 ( svr4 || posix_tilde_attempt ) ) 224 { 225 char *p, *np; 226 char *tmpbuf; 227 228 tmpbuf = getmem(source->hash.length + 8); 229 /* + 8 to add "s." or "SCCS/s." */ 230 memset(tmpbuf,0,source->hash.length + 8); 231 source->string_mb[source->hash.length - 1] = '\0'; 232 if(p = (char *) memchr((char *)source->string_mb,'/',source->hash.length)) 233 { 234 while(1) { 235 if(np = (char *) memchr((char *)p+1,'/',source->hash.length - (p - source->string_mb))) { 236 p = np; 237 } else {break;} 238 } 239 /* copy everything including '/' */ 240 strncpy(tmpbuf, source->string_mb, p - source->string_mb + 1); 241 strcat(tmpbuf, "s."); 242 strcat(tmpbuf, p+1); 243 retmem((wchar_t *) source->string_mb); 244 source->string_mb = tmpbuf; 245 246 } else { 247 strcpy(tmpbuf, "s."); 248 strcat(tmpbuf, source->string_mb); 249 retmem((wchar_t *) source->string_mb); 250 source->string_mb = tmpbuf; 251 252 } 253 source->hash.length = strlen(source->string_mb); 254 if(exists(source) == file_doesnt_exist) 255 continue; 256 tilde_rule = true; 257 we_are_in_tilde = true; 258 } else { 259 if(!name_found) { 260 free_name(source); 261 } 262 continue; 263 } 264 } else { 265 if(posix && posix_tilde_attempt) { 266 if(exists(source) == file_doesnt_exist) { 267 if(!name_found) { 268 free_name(source); 269 } 270 continue; 271 } 272 } 273 } 274 275 if (command != NULL) { 276 if(!name_found) { 277 store_name(source); 278 } 279 /* 280 * The source file is a file. 281 * Make sure it is up to date. 282 */ 283 if (dependency_exists(source, 284 get_prop(target->prop, 285 line_prop))) { 286 result = (Doname) source->state; 287 } else { 288 #if 0 /* with_squiggle sends false, which is buggy. : djay */ 289 result = doname(source, 290 (Boolean) source_suffix->body. 291 suffix.suffix->with_squiggle, 292 true); 293 #else 294 result = doname(source, 295 true, 296 true); 297 #endif 298 } 299 } else { 300 result = target_can_be_built(source); 301 302 if (result == build_ok) { 303 return result; 304 } else { 305 if(!name_found) { 306 free_name(source); 307 } 308 continue; 309 } 310 } 311 312 switch (result) { 313 case build_dont_know: 314 /* 315 * If we still can't build the source, 316 * this rule is not a match, 317 * try the next one. 318 */ 319 if (source->stat.time == file_doesnt_exist) { 320 if(!name_found) { 321 free_name(source); 322 } 323 continue; 324 } 325 case build_running: 326 if(!name_found) { 327 store_name(source); 328 } 329 true_target->suffix_scan_done = false; 330 line = maybe_append_prop(target, line_prop); 331 enter_dependency(line, source, false); 332 line->body.line.target = true_target; 333 return build_running; 334 case build_ok: 335 if(!name_found) { 336 store_name(source); 337 } 338 break; 339 case build_failed: 340 if(!name_found) { 341 store_name(source); 342 } 343 if (sourcename != static_string_buf_3M) { 344 retmem(sourcename); 345 } 346 return build_failed; 347 } 348 349 if (debug_level > 1) { 350 WCSTOMBS(mbs_buffer, sourcename); 351 (void) printf(gettext("%*sFound %s\n"), 352 recursion_level, 353 "", 354 mbs_buffer); 355 } 356 357 if (source->depends_on_conditional) { 358 target->depends_on_conditional = true; 359 } 360 /* 361 * Since it is possible that the same target is built several times during 362 * the make run, we have to patch the target with all information we found 363 * here. Thus, the target will have an explicit rule the next time around. 364 */ 365 line = maybe_append_prop(target, line_prop); 366 if (*command == NULL) { 367 *command = line; 368 } 369 if ((source->stat.time > (*command)->body.line.dependency_time) && 370 (debug_level > 1)) { 371 (void) printf(gettext("%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), 372 recursion_level, 373 "", 374 source->string_mb, 375 time_to_string(source-> 376 stat.time), 377 true_target->string_mb, 378 time_to_string((*command)-> 379 body.line. 380 dependency_time)); 381 } 382 /* 383 * Determine if this new dependency made the 384 * target out of date. 385 */ 386 (*command)->body.line.dependency_time = 387 MAX((*command)->body.line.dependency_time, 388 source->stat.time); 389 Boolean out_of_date; 390 if (target->is_member) { 391 out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, 392 (*command)->body.line.dependency_time); 393 } else { 394 out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, 395 (*command)->body.line.dependency_time); 396 } 397 if (build_unconditional || out_of_date) { 398 if(!rechecking) { 399 line->body.line.is_out_of_date = true; 400 } 401 if (debug_level > 0) { 402 (void) printf(gettext("%*sBuilding %s using suffix rule for %s%s because it is out of date relative to %s\n"), 403 recursion_level, 404 "", 405 true_target->string_mb, 406 source_suffix->body.suffix.suffix->string_mb, 407 target_suffix->string_mb, 408 source->string_mb); 409 } 410 } 411 /* 412 * Add the implicit rule as the target's explicit 413 * rule if none actually given, and register 414 * dependency. 415 * The time checking above really should be 416 * conditional on actual use of implicit rule 417 * as well. 418 */ 419 line->body.line.sccs_command = false; 420 if (line->body.line.command_template == NULL) { 421 line->body.line.command_template = 422 source_suffix->body.suffix.command_template; 423 } 424 enter_dependency(line, source, false); 425 line->body.line.target = true_target; 426 /* 427 * Also make sure the rule is built with 428 * $* and $< bound properly. 429 */ 430 line->body.line.star = target_body; 431 if(svr4|posix) { 432 char * p; 433 char tstr[256]; 434 extern Boolean dollarless_flag; 435 extern Name dollarless_value; 436 437 if(tilde_rule) { 438 MBSTOWCS(wcs_buffer, source->string_mb); 439 dollarless_value = GETNAME(wcs_buffer,FIND_LENGTH); 440 } 441 else { 442 dollarless_flag = false; 443 } 444 } 445 line->body.line.less = source; 446 line->body.line.percent = NULL; 447 add_target_to_chain(source, &(line->body.line.query)); 448 if (sourcename != static_string_buf_3M) { 449 retmem(sourcename); 450 } 451 return build_ok; 452 } 453 if(posix && posix_tilde_attempt) { 454 posix_tilde_attempt = false; 455 goto posix_attempts; 456 } 457 if ((command != NULL) && 458 ((*command) != NULL) && 459 ((*command)->body.line.star == NULL)) { 460 (*command)->body.line.star = target_body; 461 } 462 } 463 if (sourcename != static_string_buf_3M) { 464 retmem(sourcename); 465 } 466 /* Return here in case no rule matched the target */ 467 return build_dont_know; 468 } 469 470 /* 471 * find_ar_suffix_rule(target, true_target, command, rechecking) 472 * 473 * Scans the .SUFFIXES list and tries 474 * to find a suffix on it that matches the tail of the target member name. 475 * If it finds a matching suffix it calls find_suffix_rule() to find 476 * a rule for the target using the suffix ".a". 477 * 478 * Return value: 479 * Indicates if search failed or not 480 * 481 * Parameters: 482 * target The target we need a rule for 483 * true_target The proper name 484 * command Pointer to slot where we stuff cmd, if found 485 * rechecking true if we are rechecking target which depends 486 * on conditional macro and keep_state is set 487 * 488 * Global variables used: 489 * debug_level Indicates how much tracing to do 490 * dot_a The Name ".a", compared against 491 * recursion_level Used for tracing 492 * suffixes List of suffixes used for scan (from .SUFFIXES) 493 */ 494 Doname 495 find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking) 496 { 497 wchar_t *target_end; 498 register Dependency suffix; 499 register int suffix_length; 500 Property line; 501 Name body; 502 static Name dot_a; 503 504 Wstring targ_string(true_target); 505 Wstring suf_string; 506 507 if (dot_a == NULL) { 508 MBSTOWCS(wcs_buffer, ".a"); 509 dot_a = GETNAME(wcs_buffer, FIND_LENGTH); 510 } 511 target_end = targ_string.get_string() + true_target->hash.length; 512 513 /* 514 * We compare the tail of the target name with the suffixes 515 * from .SUFFIXES. 516 */ 517 if (debug_level > 1) { 518 (void) printf("%*sfind_ar_suffix_rule(%s)\n", 519 recursion_level, 520 "", 521 true_target->string_mb); 522 } 523 /* 524 * Scan the .SUFFIXES list to see if the target matches any of 525 * those suffixes. 526 */ 527 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { 528 /* Compare one suffix. */ 529 suffix_length = suffix->name->hash.length; 530 suf_string.init(suffix->name); 531 if (!IS_WEQUALN(suf_string.get_string(), 532 target_end - suffix_length, 533 suffix_length)) { 534 goto not_this_one; 535 } 536 /* 537 * The target tail matched a suffix from the .SUFFIXES list. 538 * Now check for a rule to match. 539 */ 540 target->suffix_scan_done = false; 541 body = GETNAME(targ_string.get_string(), 542 (int)(true_target->hash.length - 543 suffix_length)); 544 we_are_in_tilde = false; 545 switch (find_suffix_rule(target, 546 body, 547 dot_a, 548 command, 549 rechecking)) { 550 case build_ok: 551 line = get_prop(target->prop, line_prop); 552 line->body.line.star = body; 553 return build_ok; 554 case build_running: 555 return build_running; 556 } 557 /* 558 * If no rule was found, we try the next suffix to see 559 * if it matches the target tail, and so on. 560 * Go here if the suffix did not match the target tail. 561 */ 562 not_this_one:; 563 } 564 return build_dont_know; 565 } 566 567 /* 568 * find_double_suffix_rule(target, command, rechecking) 569 * 570 * Scans the .SUFFIXES list and tries 571 * to find a suffix on it that matches the tail of the target name. 572 * If it finds a matching suffix it calls find_suffix_rule() to find 573 * a rule for the target. 574 * 575 * Return value: 576 * Indicates if scan failed or not 577 * 578 * Parameters: 579 * target Target we need a rule for 580 * command Pointer to slot where we stuff cmd, if found 581 * rechecking true if we are rechecking target which depends 582 * on conditional macro and keep_state is set 583 * 584 * Global variables used: 585 * debug_level Indicates how much tracing to do 586 * recursion_level Used for tracing 587 * suffixes List of suffixes used for scan (from .SUFFIXES) 588 */ 589 Doname 590 find_double_suffix_rule(register Name target, Property *command, Boolean rechecking) 591 { 592 Name true_target = target; 593 Name target_body; 594 register wchar_t *target_end; 595 register Dependency suffix; 596 register int suffix_length; 597 Boolean scanned_once = false; 598 Boolean name_found = true; 599 600 Wstring targ_string; 601 Wstring suf_string; 602 603 /* 604 * If the target is a constructed one for a "::" target, 605 * we need to consider that. 606 */ 607 if (target->has_target_prop) { 608 true_target = get_prop(target->prop, 609 target_prop)->body.target.target; 610 } 611 targ_string.init(true_target); 612 613 /* 614 * We compare the tail of the target name with the 615 * suffixes from .SUFFIXES. 616 */ 617 target_end = targ_string.get_string() + true_target->hash.length; 618 if (debug_level > 1) { 619 (void) printf("%*sfind_double_suffix_rule(%s)\n", 620 recursion_level, 621 "", 622 true_target->string_mb); 623 } 624 /* 625 * Scan the .SUFFIXES list to see if the target matches 626 * any of those suffixes. 627 */ 628 for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { 629 target->suffix_scan_done = false; 630 true_target->suffix_scan_done = false; 631 /* Compare one suffix. */ 632 suffix_length = suffix->name->hash.length; 633 suf_string.init(suffix->name); 634 /* Check the lengths, or else RTC will report rua. */ 635 if (true_target->hash.length < suffix_length) { 636 goto not_this_one; 637 } else if (!IS_WEQUALN(suf_string.get_string(), 638 (target_end - suffix_length), 639 suffix_length)) { 640 goto not_this_one; 641 } 642 /* 643 * The target tail matched a suffix from the .SUFFIXES list. 644 * Now check for a rule to match. 645 */ 646 we_are_in_tilde = false; 647 target_body = GETNAME( 648 targ_string.get_string(), 649 (int)(true_target->hash.length - suffix_length) 650 ); 651 switch (find_suffix_rule(target, 652 target_body, 653 suffix->name, 654 command, 655 rechecking)) { 656 case build_ok: 657 return build_ok; 658 case build_running: 659 return build_running; 660 } 661 if (true_target->suffix_scan_done == true) { 662 scanned_once = true; 663 } 664 /* 665 * If no rule was found, we try the next suffix to see 666 * if it matches the target tail. And so on. 667 * Go here if the suffix did not match the target tail. 668 */ 669 not_this_one:; 670 } 671 if (scanned_once) 672 true_target->suffix_scan_done = true; 673 return build_dont_know; 674 } 675 676 /* 677 * build_suffix_list(target_suffix) 678 * 679 * Scans the .SUFFIXES list and figures out 680 * which suffixes this target can be derived from. 681 * The target itself is not know here, we just know the suffix of the 682 * target. For each suffix on the list the target can be derived iff 683 * a rule exists for the name "<suffix-on-list><target-suffix>". 684 * A list of all possible building suffixes is built, with the rule for 685 * each, and tacked to the target suffix nameblock. 686 * 687 * Parameters: 688 * target_suffix The suffix we build a match list for 689 * 690 * Global variables used: 691 * debug_level Indicates how much tracing to do 692 * recursion_level Used for tracing 693 * suffixes List of suffixes used for scan (from .SUFFIXES) 694 * working_on_targets Indicates that this is a real target 695 */ 696 void 697 build_suffix_list(register Name target_suffix) 698 { 699 register Dependency source_suffix; 700 wchar_t rule_name[MAXPATHLEN]; 701 register Property line; 702 register Property suffix; 703 Name rule; 704 705 /* If this is before default.mk has been read we just return to try */ 706 /* again later */ 707 if ((suffixes == NULL) || !working_on_targets) { 708 return; 709 } 710 if (debug_level > 1) { 711 (void) printf("%*sbuild_suffix_list(%s) ", 712 recursion_level, 713 "", 714 target_suffix->string_mb); 715 } 716 /* Mark the target suffix saying we cashed its list */ 717 target_suffix->has_read_suffixes = true; 718 /* Scan the .SUFFIXES list */ 719 for (source_suffix = suffixes; 720 source_suffix != NULL; 721 source_suffix = source_suffix->next) { 722 /* 723 * Build the name "<suffix-on-list><target-suffix>". 724 * (a popular one would be ".c.o"). 725 */ 726 (void) mbstowcs(rule_name, 727 source_suffix->name->string_mb, 728 (int) source_suffix->name->hash.length); 729 (void) mbstowcs(rule_name + source_suffix->name->hash.length, 730 target_suffix->string_mb, 731 (int) target_suffix->hash.length); 732 /* 733 * Check if that name has a rule. If not, it cannot match 734 * any implicit rule scan and is ignored. 735 * The GETNAME() call only checks for presence, it will not 736 * enter the name if it is not defined. 737 */ 738 if (((rule = getname_fn(rule_name, 739 (int) (source_suffix->name-> 740 hash.length + 741 target_suffix->hash.length), 742 true)) != NULL) && 743 ((line = get_prop(rule->prop, line_prop)) != NULL)) { 744 if (debug_level > 1) { 745 (void) printf("%s ", rule->string_mb); 746 } 747 /* 748 * This makes it possible to quickly determine if 749 * it will pay to look for a suffix property. 750 */ 751 target_suffix->has_suffixes = true; 752 /* 753 * Add the suffix property to the target suffix 754 * and save the rule with it. 755 * All information the implicit rule scanner need 756 * is saved in the suffix property. 757 */ 758 suffix = append_prop(target_suffix, suffix_prop); 759 suffix->body.suffix.suffix = source_suffix->name; 760 suffix->body.suffix.command_template = 761 line->body.line.command_template; 762 } 763 } 764 if (debug_level > 1) { 765 (void) printf("\n"); 766 } 767 } 768 769 /* 770 * find_percent_rule(target, command, rechecking) 771 * 772 * Tries to find a rule from the list of wildcard matched rules. 773 * It scans the list attempting to match the target. 774 * For each target match it checks if the corresponding source exists. 775 * If it does the match is returned. 776 * The percent_list is built at makefile read time. 777 * Each percent rule get one entry on the list. 778 * 779 * Return value: 780 * Indicates if the scan failed or not 781 * 782 * Parameters: 783 * target The target we need a rule for 784 * command Pointer to slot where we stuff cmd, if found 785 * rechecking true if we are rechecking target which depends 786 * on conditional macro and keep_state is set 787 * 788 * Global variables used: 789 * debug_level Indicates how much tracing to do 790 * percent_list List of all percent rules 791 * recursion_level Used for tracing 792 * empty_name 793 */ 794 Doname 795 find_percent_rule(register Name target, Property *command, Boolean rechecking) 796 { 797 register Percent pat_rule, pat_depe; 798 register Name depe_to_check; 799 register Dependency depe; 800 register Property line; 801 String_rec string; 802 wchar_t string_buf[STRING_BUFFER_LENGTH]; 803 String_rec percent; 804 wchar_t percent_buf[STRING_BUFFER_LENGTH]; 805 Name true_target = target; 806 Name less; 807 Boolean nonpattern_less; 808 Boolean dep_name_found = false; 809 Doname result = build_dont_know; 810 Percent rule_candidate = NULL; 811 Boolean rule_maybe_ok; 812 Boolean is_pattern; 813 814 /* If the target is constructed for a "::" target we consider that */ 815 if (target->has_target_prop) { 816 true_target = get_prop(target->prop, 817 target_prop)->body.target.target; 818 } 819 if (target->has_long_member_name) { 820 true_target = get_prop(target->prop, 821 long_member_name_prop)->body.long_member_name.member_name; 822 } 823 if (debug_level > 1) { 824 (void) printf(gettext("%*sLooking for %% rule for %s\n"), 825 recursion_level, 826 "", 827 true_target->string_mb); 828 } 829 for (pat_rule = percent_list; 830 pat_rule != NULL; 831 pat_rule = pat_rule->next) { 832 /* Avoid infinite recursion when expanding patterns */ 833 if (pat_rule->being_expanded == true) { 834 continue; 835 } 836 837 /* Mark this pat_rule as "maybe ok". If no % rule is found 838 make will use this rule. The following algorithm is used: 839 1) make scans all pattern rules in order to find the rule 840 where ALL dependencies, including nonpattern ones, exist or 841 can be built (GNU behaviour). If such rule is found make 842 will apply it. 843 2) During this check make also remembers the first pattern rule 844 where all PATTERN dependencies can be build (no matter what 845 happens with nonpattern dependencies). 846 3) If no rule satisfying 1) is found, make will apply the rule 847 remembered in 2) if there is one. 848 */ 849 rule_maybe_ok = true; 850 851 /* used to track first percent dependency */ 852 less = NULL; 853 nonpattern_less = true; 854 855 /* check whether pattern matches. 856 if it matches, percent string will contain matched percent part of pattern */ 857 if (!match_found_with_pattern(true_target, pat_rule, &percent, percent_buf)) { 858 continue; 859 } 860 if (pat_rule->dependencies != NULL) { 861 for (pat_depe = pat_rule->dependencies; 862 pat_depe != NULL; 863 pat_depe = pat_depe->next) { 864 /* checking result for dependency */ 865 result = build_dont_know; 866 867 dep_name_found = true; 868 if (pat_depe->name->percent) { 869 is_pattern = true; 870 /* build dependency name */ 871 INIT_STRING_FROM_STACK(string, string_buf); 872 construct_string_from_pattern(pat_depe, &percent, &string); 873 depe_to_check = getname_fn(string.buffer.start, 874 FIND_LENGTH, 875 false, 876 &dep_name_found 877 ); 878 879 if ((less == NULL) || nonpattern_less) { 880 less = depe_to_check; 881 nonpattern_less = false; 882 } 883 } else { 884 /* nonpattern dependency */ 885 is_pattern = false; 886 depe_to_check = pat_depe->name; 887 if(depe_to_check->dollar) { 888 INIT_STRING_FROM_STACK(string, string_buf); 889 expand_value(depe_to_check, &string, false); 890 depe_to_check = getname_fn(string.buffer.start, 891 FIND_LENGTH, 892 false, 893 &dep_name_found 894 ); 895 } 896 if (less == NULL) { 897 less = depe_to_check; 898 } 899 } 900 901 if (depe_to_check == empty_name) { 902 result = build_ok; 903 } else { 904 if (debug_level > 1) { 905 (void) printf(gettext("%*sTrying %s\n"), 906 recursion_level, 907 "", 908 depe_to_check->string_mb); 909 } 910 911 pat_rule->being_expanded = true; 912 913 /* suppress message output */ 914 int save_debug_level = debug_level; 915 debug_level = 0; 916 917 /* check whether dependency can be built */ 918 if (dependency_exists(depe_to_check, 919 get_prop(target->prop, 920 line_prop))) 921 { 922 result = (Doname) depe_to_check->state; 923 } else { 924 if(actual_doname) { 925 result = doname(depe_to_check, true, true); 926 } else { 927 result = target_can_be_built(depe_to_check); 928 } 929 if(!dep_name_found) { 930 if(result != build_ok && result != build_running) { 931 free_name(depe_to_check); 932 } else { 933 store_name(depe_to_check); 934 } 935 } 936 } 937 if(result != build_ok && is_pattern) { 938 rule_maybe_ok = false; 939 } 940 941 /* restore debug_level */ 942 debug_level = save_debug_level; 943 } 944 945 if (pat_depe->name->percent) { 946 if (string.free_after_use) { 947 retmem(string.buffer.start); 948 } 949 } 950 /* make can't figure out how to make this dependency */ 951 if (result != build_ok && result != build_running) { 952 pat_rule->being_expanded = false; 953 break; 954 } 955 } 956 } else { 957 result = build_ok; 958 } 959 960 /* this pattern rule is the needed one since all dependencies could be built */ 961 if (result == build_ok || result == build_running) { 962 break; 963 } 964 965 /* Make does not know how to build some of dependencies from this rule. 966 But if all "pattern" dependencies can be built, we remember this rule 967 as a candidate for the case if no other pattern rule found. 968 */ 969 if(rule_maybe_ok && rule_candidate == NULL) { 970 rule_candidate = pat_rule; 971 } 972 } 973 974 /* if no pattern matching rule was found, use the remembered candidate 975 or return build_dont_know if there is no candidate. 976 */ 977 if (result != build_ok && result != build_running) { 978 if(rule_candidate) { 979 pat_rule = rule_candidate; 980 } else { 981 return build_dont_know; 982 } 983 } 984 985 /* if we are performing only check whether dependency could be built with existing rules, 986 return success */ 987 if (command == NULL) { 988 if(pat_rule != NULL) { 989 pat_rule->being_expanded = false; 990 } 991 return result; 992 } 993 994 if (debug_level > 1) { 995 (void) printf(gettext("%*sMatched %s:"), 996 recursion_level, 997 "", 998 target->string_mb); 999 1000 for (pat_depe = pat_rule->dependencies; 1001 pat_depe != NULL; 1002 pat_depe = pat_depe->next) { 1003 if (pat_depe->name->percent) { 1004 INIT_STRING_FROM_STACK(string, string_buf); 1005 construct_string_from_pattern(pat_depe, &percent, &string); 1006 depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); 1007 } else { 1008 depe_to_check = pat_depe->name; 1009 if(depe_to_check->dollar) { 1010 INIT_STRING_FROM_STACK(string, string_buf); 1011 expand_value(depe_to_check, &string, false); 1012 depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); 1013 } 1014 } 1015 1016 if (depe_to_check != empty_name) { 1017 (void) printf(" %s", depe_to_check->string_mb); 1018 } 1019 } 1020 1021 (void) printf(gettext(" from: %s:"), 1022 pat_rule->name->string_mb); 1023 1024 for (pat_depe = pat_rule->dependencies; 1025 pat_depe != NULL; 1026 pat_depe = pat_depe->next) { 1027 (void) printf(" %s", pat_depe->name->string_mb); 1028 } 1029 1030 (void) printf("\n"); 1031 } 1032 1033 if (true_target->colons == no_colon) { 1034 true_target->colons = one_colon; 1035 } 1036 1037 /* create deppendency list and target group from matched pattern rule */ 1038 create_target_group_and_dependencies_list(target, pat_rule, &percent); 1039 1040 /* save command */ 1041 line = get_prop(target->prop, line_prop); 1042 *command = line; 1043 1044 /* free query chain if one exist */ 1045 while(line->body.line.query != NULL) { 1046 Chain to_free = line->body.line.query; 1047 line->body.line.query = line->body.line.query->next; 1048 retmem_mb((char *) to_free); 1049 } 1050 1051 if (line->body.line.dependencies != NULL) { 1052 /* build all collected dependencies */ 1053 for (depe = line->body.line.dependencies; 1054 depe != NULL; 1055 depe = depe->next) { 1056 actual_doname = true; 1057 result = doname_check(depe->name, true, true, depe->automatic); 1058 1059 actual_doname = false; 1060 if (result == build_failed) { 1061 pat_rule->being_expanded = false; 1062 return build_failed; 1063 } 1064 if (result == build_running) { 1065 pat_rule->being_expanded = false; 1066 return build_running; 1067 } 1068 1069 if ((depe->name->stat.time > line->body.line.dependency_time) && 1070 (debug_level > 1)) { 1071 (void) printf(gettext("%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), 1072 recursion_level, 1073 "", 1074 depe->name->string_mb, 1075 time_to_string(depe->name->stat.time), 1076 true_target->string_mb, 1077 time_to_string(line->body.line.dependency_time)); 1078 } 1079 1080 line->body.line.dependency_time = 1081 MAX(line->body.line.dependency_time, depe->name->stat.time); 1082 1083 /* determine whether this dependency made target out of date */ 1084 Boolean out_of_date; 1085 if (target->is_member || depe->name->is_member) { 1086 out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, depe->name->stat.time); 1087 } else { 1088 out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, depe->name->stat.time); 1089 } 1090 if (build_unconditional || out_of_date) { 1091 if(!rechecking) { 1092 line->body.line.is_out_of_date = true; 1093 } 1094 add_target_to_chain(depe->name, &(line->body.line.query)); 1095 1096 if (debug_level > 0) { 1097 (void) printf(gettext("%*sBuilding %s using pattern rule %s:"), 1098 recursion_level, 1099 "", 1100 true_target->string_mb, 1101 pat_rule->name->string_mb); 1102 1103 for (pat_depe = pat_rule->dependencies; 1104 pat_depe != NULL; 1105 pat_depe = pat_depe->next) { 1106 (void) printf(" %s", pat_depe->name->string_mb); 1107 } 1108 1109 (void) printf(gettext(" because it is out of date relative to %s\n"), 1110 depe->name->string_mb); 1111 } 1112 } 1113 } 1114 } else { 1115 if ((true_target->stat.time <= file_doesnt_exist) || 1116 (true_target->stat.time < line->body.line.dependency_time)) { 1117 if(!rechecking) { 1118 line->body.line.is_out_of_date = true; 1119 } 1120 if (debug_level > 0) { 1121 (void) printf(gettext("%*sBuilding %s using pattern rule %s: "), 1122 recursion_level, 1123 "", 1124 true_target->string_mb, 1125 pat_rule->name->string_mb, 1126 (target->stat.time > file_doesnt_exist) ? 1127 gettext("because it is out of date") : 1128 gettext("because it does not exist")); 1129 } 1130 } 1131 } 1132 1133 /* enter explicit rule from percent rule */ 1134 Name lmn_target = true_target; 1135 if (true_target->has_long_member_name) { 1136 lmn_target = get_prop(true_target->prop, long_member_name_prop)->body.long_member_name.member_name; 1137 } 1138 line->body.line.sccs_command = false; 1139 line->body.line.target = true_target; 1140 line->body.line.command_template = pat_rule->command_template; 1141 line->body.line.star = GETNAME(percent.buffer.start, FIND_LENGTH); 1142 line->body.line.less = less; 1143 1144 if (lmn_target->parenleft) { 1145 Wstring lmn_string(lmn_target); 1146 1147 wchar_t *left = (wchar_t *) wcschr(lmn_string.get_string(), (int) parenleft_char); 1148 wchar_t *right = (wchar_t *) wcschr(lmn_string.get_string(), (int) parenright_char); 1149 1150 if ((left == NULL) || (right == NULL)) { 1151 line->body.line.percent = NULL; 1152 } else { 1153 line->body.line.percent = GETNAME(left + 1, right - left - 1); 1154 } 1155 } else { 1156 line->body.line.percent = NULL; 1157 } 1158 pat_rule->being_expanded = false; 1159 1160 return result; 1161 } 1162 1163 /* 1164 * match_found_with_pattern 1165 * ( target, pat_rule, percent, percent_buf) 1166 * 1167 * matches "target->string" with a % pattern. 1168 * If pattern contains a MACRO definition, it's expanded first. 1169 * 1170 * Return value: 1171 * true if a match was found 1172 * 1173 * Parameters: 1174 * target The target we're trying to match 1175 * pattern 1176 * percent record that contains "percent_buf" below 1177 * percent_buf This is where the patched % part of pattern is stored 1178 * 1179 */ 1180 1181 static Boolean 1182 match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf) { 1183 String_rec string; 1184 wchar_t string_buf[STRING_BUFFER_LENGTH]; 1185 1186 /* construct prefix string and check whether prefix matches */ 1187 Name prefix = pat_rule->patterns[0]; 1188 int prefix_length; 1189 1190 Wstring targ_string(target); 1191 Wstring pref_string(prefix); 1192 Wstring suf_string; 1193 1194 if (prefix->dollar) { 1195 INIT_STRING_FROM_STACK(string, string_buf); 1196 expand_value(prefix, &string, false); 1197 prefix_length = string.text.p - string.buffer.start; 1198 if ((string.buffer.start[0] == (int) period_char) && 1199 (string.buffer.start[1] == (int) slash_char)) { 1200 string.buffer.start += 2; 1201 prefix_length -= 2; 1202 } 1203 if (!targ_string.equaln(string.buffer.start, prefix_length)) { 1204 return false; 1205 } 1206 } else { 1207 prefix_length = prefix->hash.length; 1208 if (!targ_string.equaln(&pref_string, prefix_length)) { 1209 return false; 1210 } 1211 } 1212 1213 /* do the same with pattern suffix */ 1214 Name suffix = pat_rule->patterns[pat_rule->patterns_total - 1]; 1215 suf_string.init(suffix); 1216 1217 int suffix_length; 1218 if (suffix->dollar) { 1219 INIT_STRING_FROM_STACK(string, string_buf); 1220 expand_value(suffix, &string, false); 1221 suffix_length = string.text.p - string.buffer.start; 1222 if(suffix_length > target->hash.length) { 1223 return false; 1224 } 1225 if (!targ_string.equal(string.buffer.start, target->hash.length - suffix_length)) { 1226 return false; 1227 } 1228 } else { 1229 suffix_length = (int) suffix->hash.length; 1230 if(suffix_length > target->hash.length) { 1231 return false; 1232 } 1233 if (!targ_string.equal(&suf_string, target->hash.length - suffix_length)) { 1234 return false; 1235 } 1236 } 1237 1238 Boolean match_found = false; 1239 int percent_length = target->hash.length - prefix_length - suffix_length; 1240 1241 while (!match_found && (percent_length >= 0)) { 1242 /* init result string */ 1243 INIT_STRING_FROM_STACK(string, string_buf); 1244 1245 /* init percent string */ 1246 percent->buffer.start = percent_buf; 1247 percent->text.p = percent_buf; 1248 percent->text.end = NULL; 1249 percent->free_after_use = false; 1250 percent->buffer.end = percent_buf + STRING_BUFFER_LENGTH; 1251 1252 /* construct percent and result strings */ 1253 targ_string.append_to_str(percent, prefix_length, percent_length); 1254 construct_string_from_pattern(pat_rule, percent, &string); 1255 1256 /* check for match */ 1257 if (targ_string.equal(string.buffer.start, 0)) { 1258 match_found = true; 1259 } else { 1260 percent_length--; 1261 } 1262 } 1263 1264 /* result */ 1265 return match_found; 1266 } 1267 1268 1269 /* 1270 * create_target_group_and_dependencies_list 1271 * (target, pat_rule, percent) 1272 * 1273 * constructs dependency list and a target group from pattern. 1274 * 1275 * If we have the lines 1276 * %/%.a + %/%.b + C%/CC%.c: yyy %.d bb%/BB%.e 1277 * commands 1278 * 1279 * and we have matched the pattern xx/xx.a with %/%.a, then we 1280 * construct a target group that looks like this: 1281 * xx/xx.a + xx/xx.b + Cxx/CCxx.c: dependencies 1282 * 1283 * and construct dependency list that looks like this: 1284 * yyy xx.d bbxx/BBxx.e + already existed dependencies 1285 * 1286 * Return value: 1287 * none 1288 * 1289 * Parameters: 1290 * target The target we are building, in the previous 1291 * example, this is xx/xx.a 1292 * pat_rule the % pattern that matched "target", here %/%.a 1293 * percent string containing matched % part. In the example=xx. 1294 * 1295 * Global variables used: 1296 * empty_name 1297 */ 1298 1299 static void 1300 create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent) { 1301 String_rec string; 1302 wchar_t string_buf[STRING_BUFFER_LENGTH]; 1303 Percent pat_depe; 1304 Name depe; 1305 Property line = maybe_append_prop(target, line_prop); 1306 Chain new_target_group = NULL; 1307 Chain *new_target_group_tail = &new_target_group; 1308 Chain group_member; 1309 1310 /* create and append dependencies from rule */ 1311 for (pat_depe = pat_rule->dependencies; pat_depe != NULL; pat_depe = pat_depe->next) { 1312 if (pat_depe->name->percent) { 1313 INIT_STRING_FROM_STACK(string, string_buf); 1314 construct_string_from_pattern(pat_depe, percent, &string); 1315 depe = GETNAME(string.buffer.start, FIND_LENGTH); 1316 if (depe != empty_name) { 1317 enter_dependency(line, depe, false); 1318 } 1319 } else { 1320 depe = pat_depe->name; 1321 if(depe->dollar) { 1322 INIT_STRING_FROM_STACK(string, string_buf); 1323 expand_value(depe, &string, false); 1324 depe = GETNAME(string.buffer.start, FIND_LENGTH); 1325 } 1326 enter_dependency(line, depe, false); 1327 } 1328 } 1329 1330 /* if matched pattern is a group member, create new target group */ 1331 for (group_member = pat_rule->target_group; group_member != NULL; group_member = group_member->next) { 1332 Name new_target = group_member->name; 1333 if (group_member->name->percent) { 1334 INIT_STRING_FROM_STACK(string, string_buf); 1335 construct_string_from_pattern(group_member->percent_member, percent, &string); 1336 new_target = GETNAME(string.buffer.start, FIND_LENGTH); 1337 if (new_target == empty_name) { 1338 continue; 1339 } 1340 } 1341 1342 /* check for duplicates */ 1343 Chain tgm; 1344 for (tgm = new_target_group; tgm != NULL; tgm = tgm->next) { 1345 if (new_target == tgm->name) { 1346 break; 1347 } 1348 } 1349 if (tgm != NULL) { 1350 continue; 1351 } 1352 1353 /* insert it into the targets list */ 1354 (*new_target_group_tail) = ALLOC(Chain); 1355 (*new_target_group_tail)->name = new_target; 1356 (*new_target_group_tail)->next = NULL; 1357 new_target_group_tail = &(*new_target_group_tail)->next; 1358 } 1359 1360 /* now we gathered all dependencies and created target group */ 1361 line->body.line.target_group = new_target_group; 1362 1363 /* update properties for group members */ 1364 for (group_member = new_target_group; group_member != NULL; group_member = group_member->next) { 1365 if (group_member->name != target) { 1366 group_member->name->prop = target->prop; 1367 group_member->name->conditional_cnt = target->conditional_cnt; 1368 } 1369 } 1370 } 1371 1372 /* 1373 * construct_string_from_pattern 1374 * (pat_rule, percent, result) 1375 * 1376 * after pattern matched a target this routine is called to construct targets and dependencies 1377 * strings from this matched pattern rule and a string (percent) with substitutes % sign in pattern. 1378 * 1379 * Return value: 1380 * none 1381 * 1382 * Parameters: 1383 * pat_rule matched pattern rule 1384 * percent string containing matched % sign part. 1385 * result holds the result of string construction. 1386 * 1387 */ 1388 static void 1389 construct_string_from_pattern(Percent pat_rule, String percent, String result) { 1390 for (int i = 0; i < pat_rule->patterns_total; i++) { 1391 if (pat_rule->patterns[i]->dollar) { 1392 expand_value(pat_rule->patterns[i], 1393 result, 1394 false); 1395 1396 } else { 1397 append_string(pat_rule->patterns[i]->string_mb, 1398 result, 1399 pat_rule->patterns[i]->hash.length); 1400 } 1401 1402 if (i < pat_rule->patterns_total - 1) { 1403 append_string(percent->buffer.start, 1404 result, 1405 percent->text.p - percent->buffer.start); 1406 } 1407 } 1408 1409 if ((result->buffer.start[0] == (int) period_char) && 1410 (result->buffer.start[1] == (int) slash_char)) { 1411 result->buffer.start += 2; 1412 } 1413 } 1414 1415 /* 1416 * dependency_exists(target, line) 1417 * 1418 * Returns true if the target exists in the 1419 * dependency list of the line. 1420 * 1421 * Return value: 1422 * True if target is on dependency list 1423 * 1424 * Parameters: 1425 * target Target we scan for 1426 * line We get the dependency list from here 1427 * 1428 * Global variables used: 1429 */ 1430 static Boolean 1431 dependency_exists(Name target, Property line) 1432 { 1433 Dependency dp; 1434 1435 if (line == NULL) { 1436 return false; 1437 } 1438 for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) { 1439 if (dp->name == target) { 1440 return true; 1441 } 1442 } 1443 return false; 1444 } 1445 1446 void 1447 add_target_to_chain(Name target, Chain * query) 1448 { 1449 if (target->is_member && (get_prop(target->prop, member_prop) != NULL)) { 1450 target = get_prop(target->prop, member_prop)->body.member.member; 1451 } 1452 Chain *query_tail; 1453 for (query_tail = query; *query_tail != NULL; query_tail = &(*query_tail)->next) { 1454 if ((*query_tail)->name == target) { 1455 return; 1456 } 1457 } 1458 *query_tail = ALLOC(Chain); 1459 (*query_tail)->name = target; 1460 (*query_tail)->next = NULL; 1461 } 1462 1463