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