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
find_suffix_rule(Name target,Name target_body,Name target_suffix,Property * command,Boolean rechecking)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
find_ar_suffix_rule(register Name target,Name true_target,Property * command,Boolean rechecking)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
find_double_suffix_rule(register Name target,Property * command,Boolean rechecking)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
build_suffix_list(register Name target_suffix)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
find_percent_rule(register Name target,Property * command,Boolean rechecking)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
match_found_with_pattern(Name target,Percent pat_rule,String percent,wchar_t * percent_buf)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
create_target_group_and_dependencies_list(Name target,Percent pat_rule,String percent)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
construct_string_from_pattern(Percent pat_rule,String percent,String result)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
dependency_exists(Name target,Property line)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
add_target_to_chain(Name target,Chain * query)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