xref: /titanic_41/usr/src/cmd/make/bin/implicit.cc (revision 3625efb1376c3d31a0e742ed72b778e5b3add543)
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