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.
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.
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]
22 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
29 * Handle suffix and percent rules
36 #include <mksh/macro.h> /* expand_value() */
37 #include <mksh/misc.h> /* retmem() */
51 static wchar_t WIDE_NULL
[1] = {(wchar_t) nul_char
};
54 * File table of contents
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
);
69 * find_suffix_rule(target, target_body, target_suffix, command, rechecking)
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.
80 * Indicates if search failed or not
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
90 * Global variables used:
91 * debug_level Indicates how much tracing to do
92 * recursion_level Used for tracing
95 static Boolean actual_doname
= false;
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.
106 static Boolean we_are_in_tilde
= false;
109 find_suffix_rule(Name target
, Name target_body
, Name target_suffix
, Property
*command
, Boolean rechecking
)
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
;
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
);
125 * To avoid infinite recursion
127 if(we_are_in_tilde
) {
128 we_are_in_tilde
= false;
129 return(build_dont_know
);
133 * If the target is a constructed one for a "::" target,
134 * we need to consider that.
136 if (target
->has_target_prop
) {
137 true_target
= get_prop(target
->prop
,
138 target_prop
)->body
.target
.target
;
140 if (debug_level
> 1) {
141 (void) printf("%*sfind_suffix_rule(%s,%s,%s)\n",
144 true_target
->string_mb
,
145 target_body
->string_mb
,
146 target_suffix
->string_mb
);
148 if (command
!= NULL
) {
149 if ((true_target
->suffix_scan_done
== true) && (*command
== NULL
)) {
153 true_target
->suffix_scan_done
= true;
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.
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
);
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
);
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
) {
175 for (source_suffix
= get_prop(target_suffix
->prop
,
177 source_suffix
!= NULL
;
178 source_suffix
= get_prop(source_suffix
->next
,
180 /* Build the synthesized source name. */
181 (void) mbstowcs(put_suffix
,
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
] =
189 if (debug_level
> 1) {
190 WCSTOMBS(mbs_buffer
, sourcename
);
191 (void) printf(gettext("%*sTrying %s\n"),
196 source
= getname_fn(sourcename
, FIND_LENGTH
, false, &name_found
);
198 * If the source file is not registered as
199 * a file, this source suffix did not match.
201 if(vpath_defined
&& !posix
&& !svr4
) {
202 (void) exists(source
);
204 if (!source
->stat
.is_file
) {
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.
222 if(source
->string_mb
[source
->hash
.length
- 1] == '~' &&
223 ( svr4
|| posix_tilde_attempt
) )
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
))
235 if(np
= (char *) memchr((char *)p
+1,'/',source
->hash
.length
- (p
- source
->string_mb
))) {
239 /* copy everything including '/' */
240 strncpy(tmpbuf
, source
->string_mb
, p
- source
->string_mb
+ 1);
241 strcat(tmpbuf
, "s.");
243 retmem((wchar_t *) source
->string_mb
);
244 source
->string_mb
= tmpbuf
;
247 strcpy(tmpbuf
, "s.");
248 strcat(tmpbuf
, source
->string_mb
);
249 retmem((wchar_t *) source
->string_mb
);
250 source
->string_mb
= tmpbuf
;
253 source
->hash
.length
= strlen(source
->string_mb
);
254 if(exists(source
) == file_doesnt_exist
)
257 we_are_in_tilde
= true;
265 if(posix
&& posix_tilde_attempt
) {
266 if(exists(source
) == file_doesnt_exist
) {
275 if (command
!= NULL
) {
280 * The source file is a file.
281 * Make sure it is up to date.
283 if (dependency_exists(source
,
284 get_prop(target
->prop
,
286 result
= (Doname
) source
->state
;
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
,
294 result
= doname(source
,
300 result
= target_can_be_built(source
);
302 if (result
== build_ok
) {
313 case build_dont_know
:
315 * If we still can't build the source,
316 * this rule is not a match,
319 if (source
->stat
.time
== file_doesnt_exist
) {
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
;
343 if (sourcename
!= static_string_buf_3M
) {
349 if (debug_level
> 1) {
350 WCSTOMBS(mbs_buffer
, sourcename
);
351 (void) printf(gettext("%*sFound %s\n"),
357 if (source
->depends_on_conditional
) {
358 target
->depends_on_conditional
= true;
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.
365 line
= maybe_append_prop(target
, line_prop
);
366 if (*command
== NULL
) {
369 if ((source
->stat
.time
> (*command
)->body
.line
.dependency_time
) &&
371 (void) printf(gettext("%*sDate(%s)=%s Date-dependencies(%s)=%s\n"),
375 time_to_string(source
->
377 true_target
->string_mb
,
378 time_to_string((*command
)->
383 * Determine if this new dependency made the
384 * target out of date.
386 (*command
)->body
.line
.dependency_time
=
387 MAX((*command
)->body
.line
.dependency_time
,
390 if (target
->is_member
) {
391 out_of_date
= (Boolean
) OUT_OF_DATE_SEC(target
->stat
.time
,
392 (*command
)->body
.line
.dependency_time
);
394 out_of_date
= (Boolean
) OUT_OF_DATE(target
->stat
.time
,
395 (*command
)->body
.line
.dependency_time
);
397 if (build_unconditional
|| out_of_date
) {
399 line
->body
.line
.is_out_of_date
= true;
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"),
405 true_target
->string_mb
,
406 source_suffix
->body
.suffix
.suffix
->string_mb
,
407 target_suffix
->string_mb
,
412 * Add the implicit rule as the target's explicit
413 * rule if none actually given, and register
415 * The time checking above really should be
416 * conditional on actual use of implicit rule
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
;
424 enter_dependency(line
, source
, false);
425 line
->body
.line
.target
= true_target
;
427 * Also make sure the rule is built with
428 * $* and $< bound properly.
430 line
->body
.line
.star
= target_body
;
434 extern Boolean dollarless_flag
;
435 extern Name dollarless_value
;
438 MBSTOWCS(wcs_buffer
, source
->string_mb
);
439 dollarless_value
= GETNAME(wcs_buffer
,FIND_LENGTH
);
442 dollarless_flag
= false;
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
) {
453 if(posix
&& posix_tilde_attempt
) {
454 posix_tilde_attempt
= false;
457 if ((command
!= NULL
) &&
458 ((*command
) != NULL
) &&
459 ((*command
)->body
.line
.star
== NULL
)) {
460 (*command
)->body
.line
.star
= target_body
;
463 if (sourcename
!= static_string_buf_3M
) {
466 /* Return here in case no rule matched the target */
467 return build_dont_know
;
471 * find_ar_suffix_rule(target, true_target, command, rechecking)
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".
479 * Indicates if search failed or not
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
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)
495 find_ar_suffix_rule(register Name target
, Name true_target
, Property
*command
, Boolean rechecking
)
498 register Dependency suffix
;
499 register int suffix_length
;
504 Wstring
targ_string(true_target
);
508 MBSTOWCS(wcs_buffer
, ".a");
509 dot_a
= GETNAME(wcs_buffer
, FIND_LENGTH
);
511 target_end
= targ_string
.get_string() + true_target
->hash
.length
;
514 * We compare the tail of the target name with the suffixes
517 if (debug_level
> 1) {
518 (void) printf("%*sfind_ar_suffix_rule(%s)\n",
521 true_target
->string_mb
);
524 * Scan the .SUFFIXES list to see if the target matches any of
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
,
537 * The target tail matched a suffix from the .SUFFIXES list.
538 * Now check for a rule to match.
540 target
->suffix_scan_done
= false;
541 body
= GETNAME(targ_string
.get_string(),
542 (int)(true_target
->hash
.length
-
544 we_are_in_tilde
= false;
545 switch (find_suffix_rule(target
,
551 line
= get_prop(target
->prop
, line_prop
);
552 line
->body
.line
.star
= body
;
555 return build_running
;
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.
564 return build_dont_know
;
568 * find_double_suffix_rule(target, command, rechecking)
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.
576 * Indicates if scan failed or not
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
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)
590 find_double_suffix_rule(register Name target
, Property
*command
, Boolean rechecking
)
592 Name true_target
= target
;
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;
604 * If the target is a constructed one for a "::" target,
605 * we need to consider that.
607 if (target
->has_target_prop
) {
608 true_target
= get_prop(target
->prop
,
609 target_prop
)->body
.target
.target
;
611 targ_string
.init(true_target
);
614 * We compare the tail of the target name with the
615 * suffixes from .SUFFIXES.
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",
622 true_target
->string_mb
);
625 * Scan the .SUFFIXES list to see if the target matches
626 * any of those suffixes.
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
) {
637 } else if (!IS_WEQUALN(suf_string
.get_string(),
638 (target_end
- suffix_length
),
643 * The target tail matched a suffix from the .SUFFIXES list.
644 * Now check for a rule to match.
646 we_are_in_tilde
= false;
647 target_body
= GETNAME(
648 targ_string
.get_string(),
649 (int)(true_target
->hash
.length
- suffix_length
)
651 switch (find_suffix_rule(target
,
659 return build_running
;
661 if (true_target
->suffix_scan_done
== true) {
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.
672 true_target
->suffix_scan_done
= true;
673 return build_dont_know
;
677 * build_suffix_list(target_suffix)
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.
688 * target_suffix The suffix we build a match list for
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
697 build_suffix_list(register Name target_suffix
)
699 register Dependency source_suffix
;
700 wchar_t rule_name
[MAXPATHLEN
];
701 register Property line
;
702 register Property suffix
;
705 /* If this is before default.mk has been read we just return to try */
707 if ((suffixes
== NULL
) || !working_on_targets
) {
710 if (debug_level
> 1) {
711 (void) printf("%*sbuild_suffix_list(%s) ",
714 target_suffix
->string_mb
);
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
) {
723 * Build the name "<suffix-on-list><target-suffix>".
724 * (a popular one would be ".c.o").
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
);
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.
738 if (((rule
= getname_fn(rule_name
,
739 (int) (source_suffix
->name
->
741 target_suffix
->hash
.length
),
743 ((line
= get_prop(rule
->prop
, line_prop
)) != NULL
)) {
744 if (debug_level
> 1) {
745 (void) printf("%s ", rule
->string_mb
);
748 * This makes it possible to quickly determine if
749 * it will pay to look for a suffix property.
751 target_suffix
->has_suffixes
= true;
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.
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
;
764 if (debug_level
> 1) {
770 * find_percent_rule(target, command, rechecking)
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.
780 * Indicates if the scan failed or not
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
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
795 find_percent_rule(register Name target
, Property
*command
, Boolean rechecking
)
797 register Percent pat_rule
, pat_depe
;
798 register Name depe_to_check
;
799 register Dependency depe
;
800 register Property line
;
802 wchar_t string_buf
[STRING_BUFFER_LENGTH
];
804 wchar_t percent_buf
[STRING_BUFFER_LENGTH
];
805 Name true_target
= target
;
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
;
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
;
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
;
823 if (debug_level
> 1) {
824 (void) printf(gettext("%*sLooking for %% rule for %s\n"),
827 true_target
->string_mb
);
829 for (pat_rule
= percent_list
;
831 pat_rule
= pat_rule
->next
) {
832 /* Avoid infinite recursion when expanding patterns */
833 if (pat_rule
->being_expanded
== true) {
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
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.
849 rule_maybe_ok
= true;
851 /* used to track first percent dependency */
853 nonpattern_less
= true;
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
)) {
860 if (pat_rule
->dependencies
!= NULL
) {
861 for (pat_depe
= pat_rule
->dependencies
;
863 pat_depe
= pat_depe
->next
) {
864 /* checking result for dependency */
865 result
= build_dont_know
;
867 dep_name_found
= true;
868 if (pat_depe
->name
->percent
) {
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
,
879 if ((less
== NULL
) || nonpattern_less
) {
880 less
= depe_to_check
;
881 nonpattern_less
= false;
884 /* nonpattern dependency */
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
,
897 less
= depe_to_check
;
901 if (depe_to_check
== empty_name
) {
904 if (debug_level
> 1) {
905 (void) printf(gettext("%*sTrying %s\n"),
908 depe_to_check
->string_mb
);
911 pat_rule
->being_expanded
= true;
913 /* suppress message output */
914 int save_debug_level
= debug_level
;
917 /* check whether dependency can be built */
918 if (dependency_exists(depe_to_check
,
919 get_prop(target
->prop
,
922 result
= (Doname
) depe_to_check
->state
;
925 result
= doname(depe_to_check
, true, true);
927 result
= target_can_be_built(depe_to_check
);
929 if(!dep_name_found
) {
930 if(result
!= build_ok
&& result
!= build_running
) {
931 free_name(depe_to_check
);
933 store_name(depe_to_check
);
937 if(result
!= build_ok
&& is_pattern
) {
938 rule_maybe_ok
= false;
941 /* restore debug_level */
942 debug_level
= save_debug_level
;
945 if (pat_depe
->name
->percent
) {
946 if (string
.free_after_use
) {
947 retmem(string
.buffer
.start
);
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;
960 /* this pattern rule is the needed one since all dependencies could be built */
961 if (result
== build_ok
|| result
== build_running
) {
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.
969 if(rule_maybe_ok
&& rule_candidate
== NULL
) {
970 rule_candidate
= pat_rule
;
974 /* if no pattern matching rule was found, use the remembered candidate
975 or return build_dont_know if there is no candidate.
977 if (result
!= build_ok
&& result
!= build_running
) {
979 pat_rule
= rule_candidate
;
981 return build_dont_know
;
985 /* if we are performing only check whether dependency could be built with existing rules,
987 if (command
== NULL
) {
988 if(pat_rule
!= NULL
) {
989 pat_rule
->being_expanded
= false;
994 if (debug_level
> 1) {
995 (void) printf(gettext("%*sMatched %s:"),
1000 for (pat_depe
= pat_rule
->dependencies
;
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
);
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
);
1016 if (depe_to_check
!= empty_name
) {
1017 (void) printf(" %s", depe_to_check
->string_mb
);
1021 (void) printf(gettext(" from: %s:"),
1022 pat_rule
->name
->string_mb
);
1024 for (pat_depe
= pat_rule
->dependencies
;
1026 pat_depe
= pat_depe
->next
) {
1027 (void) printf(" %s", pat_depe
->name
->string_mb
);
1030 (void) printf("\n");
1033 if (true_target
->colons
== no_colon
) {
1034 true_target
->colons
= one_colon
;
1037 /* create deppendency list and target group from matched pattern rule */
1038 create_target_group_and_dependencies_list(target
, pat_rule
, &percent
);
1041 line
= get_prop(target
->prop
, line_prop
);
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
);
1051 if (line
->body
.line
.dependencies
!= NULL
) {
1052 /* build all collected dependencies */
1053 for (depe
= line
->body
.line
.dependencies
;
1055 depe
= depe
->next
) {
1056 actual_doname
= true;
1057 result
= doname_check(depe
->name
, true, true, depe
->automatic
);
1059 actual_doname
= false;
1060 if (result
== build_failed
) {
1061 pat_rule
->being_expanded
= false;
1062 return build_failed
;
1064 if (result
== build_running
) {
1065 pat_rule
->being_expanded
= false;
1066 return build_running
;
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"),
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
));
1080 line
->body
.line
.dependency_time
=
1081 MAX(line
->body
.line
.dependency_time
, depe
->name
->stat
.time
);
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
);
1088 out_of_date
= (Boolean
) OUT_OF_DATE(target
->stat
.time
, depe
->name
->stat
.time
);
1090 if (build_unconditional
|| out_of_date
) {
1092 line
->body
.line
.is_out_of_date
= true;
1094 add_target_to_chain(depe
->name
, &(line
->body
.line
.query
));
1096 if (debug_level
> 0) {
1097 (void) printf(gettext("%*sBuilding %s using pattern rule %s:"),
1100 true_target
->string_mb
,
1101 pat_rule
->name
->string_mb
);
1103 for (pat_depe
= pat_rule
->dependencies
;
1105 pat_depe
= pat_depe
->next
) {
1106 (void) printf(" %s", pat_depe
->name
->string_mb
);
1109 (void) printf(gettext(" because it is out of date relative to %s\n"),
1110 depe
->name
->string_mb
);
1115 if ((true_target
->stat
.time
<= file_doesnt_exist
) ||
1116 (true_target
->stat
.time
< line
->body
.line
.dependency_time
)) {
1118 line
->body
.line
.is_out_of_date
= true;
1120 if (debug_level
> 0) {
1121 (void) printf(gettext("%*sBuilding %s using pattern rule %s: "),
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"));
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
;
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
;
1144 if (lmn_target
->parenleft
) {
1145 Wstring
lmn_string(lmn_target
);
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
);
1150 if ((left
== NULL
) || (right
== NULL
)) {
1151 line
->body
.line
.percent
= NULL
;
1153 line
->body
.line
.percent
= GETNAME(left
+ 1, right
- left
- 1);
1156 line
->body
.line
.percent
= NULL
;
1158 pat_rule
->being_expanded
= false;
1164 * match_found_with_pattern
1165 * ( target, pat_rule, percent, percent_buf)
1167 * matches "target->string" with a % pattern.
1168 * If pattern contains a MACRO definition, it's expanded first.
1171 * true if a match was found
1174 * target The target we're trying to match
1176 * percent record that contains "percent_buf" below
1177 * percent_buf This is where the patched % part of pattern is stored
1182 match_found_with_pattern(Name target
, Percent pat_rule
, String percent
, wchar_t *percent_buf
) {
1184 wchar_t string_buf
[STRING_BUFFER_LENGTH
];
1186 /* construct prefix string and check whether prefix matches */
1187 Name prefix
= pat_rule
->patterns
[0];
1190 Wstring
targ_string(target
);
1191 Wstring
pref_string(prefix
);
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;
1203 if (!targ_string
.equaln(string
.buffer
.start
, prefix_length
)) {
1207 prefix_length
= prefix
->hash
.length
;
1208 if (!targ_string
.equaln(&pref_string
, prefix_length
)) {
1213 /* do the same with pattern suffix */
1214 Name suffix
= pat_rule
->patterns
[pat_rule
->patterns_total
- 1];
1215 suf_string
.init(suffix
);
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
) {
1225 if (!targ_string
.equal(string
.buffer
.start
, target
->hash
.length
- suffix_length
)) {
1229 suffix_length
= (int) suffix
->hash
.length
;
1230 if(suffix_length
> target
->hash
.length
) {
1233 if (!targ_string
.equal(&suf_string
, target
->hash
.length
- suffix_length
)) {
1238 Boolean match_found
= false;
1239 int percent_length
= target
->hash
.length
- prefix_length
- suffix_length
;
1241 while (!match_found
&& (percent_length
>= 0)) {
1242 /* init result string */
1243 INIT_STRING_FROM_STACK(string
, string_buf
);
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
;
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
);
1256 /* check for match */
1257 if (targ_string
.equal(string
.buffer
.start
, 0)) {
1270 * create_target_group_and_dependencies_list
1271 * (target, pat_rule, percent)
1273 * constructs dependency list and a target group from pattern.
1275 * If we have the lines
1276 * %/%.a + %/%.b + C%/CC%.c: yyy %.d bb%/BB%.e
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
1283 * and construct dependency list that looks like this:
1284 * yyy xx.d bbxx/BBxx.e + already existed dependencies
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.
1295 * Global variables used:
1300 create_target_group_and_dependencies_list(Name target
, Percent pat_rule
, String percent
) {
1302 wchar_t string_buf
[STRING_BUFFER_LENGTH
];
1305 Property line
= maybe_append_prop(target
, line_prop
);
1306 Chain new_target_group
= NULL
;
1307 Chain
*new_target_group_tail
= &new_target_group
;
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);
1320 depe
= pat_depe
->name
;
1322 INIT_STRING_FROM_STACK(string
, string_buf
);
1323 expand_value(depe
, &string
, false);
1324 depe
= GETNAME(string
.buffer
.start
, FIND_LENGTH
);
1326 enter_dependency(line
, depe
, false);
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
) {
1342 /* check for duplicates */
1344 for (tgm
= new_target_group
; tgm
!= NULL
; tgm
= tgm
->next
) {
1345 if (new_target
== tgm
->name
) {
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
;
1360 /* now we gathered all dependencies and created target group */
1361 line
->body
.line
.target_group
= new_target_group
;
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
;
1373 * construct_string_from_pattern
1374 * (pat_rule, percent, result)
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.
1383 * pat_rule matched pattern rule
1384 * percent string containing matched % sign part.
1385 * result holds the result of string construction.
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
],
1397 append_string(pat_rule
->patterns
[i
]->string_mb
,
1399 pat_rule
->patterns
[i
]->hash
.length
);
1402 if (i
< pat_rule
->patterns_total
- 1) {
1403 append_string(percent
->buffer
.start
,
1405 percent
->text
.p
- percent
->buffer
.start
);
1409 if ((result
->buffer
.start
[0] == (int) period_char
) &&
1410 (result
->buffer
.start
[1] == (int) slash_char
)) {
1411 result
->buffer
.start
+= 2;
1416 * dependency_exists(target, line)
1418 * Returns true if the target exists in the
1419 * dependency list of the line.
1422 * True if target is on dependency list
1425 * target Target we scan for
1426 * line We get the dependency list from here
1428 * Global variables used:
1431 dependency_exists(Name target
, Property line
)
1438 for (dp
= line
->body
.line
.dependencies
; dp
!= NULL
; dp
= dp
->next
) {
1439 if (dp
->name
== target
) {
1447 add_target_to_chain(Name target
, Chain
* query
)
1449 if (target
->is_member
&& (get_prop(target
->prop
, member_prop
) != NULL
)) {
1450 target
= get_prop(target
->prop
, member_prop
)->body
.member
.member
;
1453 for (query_tail
= query
; *query_tail
!= NULL
; query_tail
= &(*query_tail
)->next
) {
1454 if ((*query_tail
)->name
== target
) {
1458 *query_tail
= ALLOC(Chain
);
1459 (*query_tail
)->name
= target
;
1460 (*query_tail
)->next
= NULL
;