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