xref: /illumos-gate/usr/src/cmd/make/bin/doname.cc (revision e7afc443)
110d63b7dSRichard Lowe /*
210d63b7dSRichard Lowe  * CDDL HEADER START
310d63b7dSRichard Lowe  *
410d63b7dSRichard Lowe  * The contents of this file are subject to the terms of the
510d63b7dSRichard Lowe  * Common Development and Distribution License (the "License").
610d63b7dSRichard Lowe  * You may not use this file except in compliance with the License.
710d63b7dSRichard Lowe  *
810d63b7dSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910d63b7dSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
1010d63b7dSRichard Lowe  * See the License for the specific language governing permissions
1110d63b7dSRichard Lowe  * and limitations under the License.
1210d63b7dSRichard Lowe  *
1310d63b7dSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
1410d63b7dSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510d63b7dSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
1610d63b7dSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
1710d63b7dSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
1810d63b7dSRichard Lowe  *
1910d63b7dSRichard Lowe  * CDDL HEADER END
2010d63b7dSRichard Lowe  */
2110d63b7dSRichard Lowe /*
2210d63b7dSRichard Lowe  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
2310d63b7dSRichard Lowe  * Use is subject to license terms.
2467c3092cSAndrew Stormont  *
2548bbca81SDaniel Hoffman  * Copyright (c) 2016 by Delphix. All rights reserved.
268e0c8248SAndrew Stormont  * Copyright 2019 RackTop Systems.
2710d63b7dSRichard Lowe  */
2810d63b7dSRichard Lowe 
2910d63b7dSRichard Lowe /*
3010d63b7dSRichard Lowe  *	doname.c
3110d63b7dSRichard Lowe  *
3210d63b7dSRichard Lowe  *	Figure out which targets are out of date and rebuild them
3310d63b7dSRichard Lowe  */
3410d63b7dSRichard Lowe 
3510d63b7dSRichard Lowe /*
3610d63b7dSRichard Lowe  * Included files
3710d63b7dSRichard Lowe  */
3810d63b7dSRichard Lowe #include <alloca.h>		/* alloca() */
3910d63b7dSRichard Lowe #include <fcntl.h>
4010d63b7dSRichard Lowe #include <mk/defs.h>
4110d63b7dSRichard Lowe #include <mksh/i18n.h>		/* get_char_semantics_value() */
4210d63b7dSRichard Lowe #include <mksh/macro.h>		/* getvar(), expand_value() */
4310d63b7dSRichard Lowe #include <mksh/misc.h>		/* getmem() */
4410d63b7dSRichard Lowe #include <poll.h>
4510d63b7dSRichard Lowe #include <libintl.h>
4610d63b7dSRichard Lowe #include <signal.h>
4710d63b7dSRichard Lowe #include <stropts.h>
4810d63b7dSRichard Lowe #include <sys/errno.h>
4910d63b7dSRichard Lowe #include <sys/stat.h>
5010d63b7dSRichard Lowe #include <sys/types.h>
5110d63b7dSRichard Lowe #include <sys/utsname.h>	/* uname() */
5210d63b7dSRichard Lowe #include <sys/wait.h>
5310d63b7dSRichard Lowe #include <unistd.h>		/* close() */
5410d63b7dSRichard Lowe 
5510d63b7dSRichard Lowe /*
5610d63b7dSRichard Lowe  * Defined macros
5710d63b7dSRichard Lowe  */
5810d63b7dSRichard Lowe #	define LOCALHOST "localhost"
5910d63b7dSRichard Lowe 
6010d63b7dSRichard Lowe #define MAXRULES 100
6110d63b7dSRichard Lowe 
6210d63b7dSRichard Lowe // Sleep for .1 seconds between stat()'s
6310d63b7dSRichard Lowe const int	STAT_RETRY_SLEEP_TIME = 100000;
6410d63b7dSRichard Lowe 
6510d63b7dSRichard Lowe /*
6610d63b7dSRichard Lowe  * typedefs & structs
6710d63b7dSRichard Lowe  */
6810d63b7dSRichard Lowe 
6910d63b7dSRichard Lowe /*
7010d63b7dSRichard Lowe  * Static variables
7110d63b7dSRichard Lowe  */
7210d63b7dSRichard Lowe static char	hostName[MAXNAMELEN] = "";
7310d63b7dSRichard Lowe static char	userName[MAXNAMELEN] = "";
7410d63b7dSRichard Lowe 
7510d63b7dSRichard Lowe 
7610d63b7dSRichard Lowe static int	second_pass = 0;
7710d63b7dSRichard Lowe 
7810d63b7dSRichard Lowe /*
7910d63b7dSRichard Lowe  * File table of contents
8010d63b7dSRichard Lowe  */
81*e7afc443SToomas Soome extern	Doname		doname_check(Name target, Boolean do_get, Boolean implicit, Boolean automatic);
82*e7afc443SToomas Soome extern	Doname		doname(Name target, Boolean do_get, Boolean implicit, Boolean automatic);
8310d63b7dSRichard Lowe static	Boolean		check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals);
8410d63b7dSRichard Lowe void		dynamic_dependencies(Name target);
85*e7afc443SToomas Soome static	Doname		run_command(Property line, Boolean print_machine);
8610d63b7dSRichard Lowe extern	Doname		execute_serial(Property line);
87*e7afc443SToomas Soome extern	Name		vpath_translation(Name cmd);
8810d63b7dSRichard Lowe extern	void		check_state(Name temp_file_name);
89*e7afc443SToomas Soome static	void		read_dependency_file(Name filename);
9010d63b7dSRichard Lowe static	void		check_read_state_file(void);
91*e7afc443SToomas Soome static	void		do_assign(Name line, Name target);
92*e7afc443SToomas Soome static	void		build_command_strings(Name target, Property line);
93*e7afc443SToomas Soome static	Doname		touch_command(Property line, Name target, Doname result);
9410d63b7dSRichard Lowe extern	void		update_target(Property line, Doname result);
95*e7afc443SToomas Soome static	Doname		sccs_get(Name target, Property *command);
96*e7afc443SToomas Soome extern	void		read_directory_of_file(Name file);
97*e7afc443SToomas Soome static	void		add_pattern_conditionals(Name target);
98*e7afc443SToomas Soome extern	void		set_locals(Name target, Property old_locals);
99*e7afc443SToomas Soome extern	void		reset_locals(Name target, Property old_locals, Property conditional, int index);
10010d63b7dSRichard Lowe extern	Boolean		check_auto_dependencies(Name target, int auto_count, Name *automatics);
10110d63b7dSRichard Lowe static	void		delete_query_chain(Chain ch);
10210d63b7dSRichard Lowe 
10310d63b7dSRichard Lowe // From read2.cc
104*e7afc443SToomas Soome extern	Name		normalize_name(wchar_t *name_string, int length);
10510d63b7dSRichard Lowe 
10610d63b7dSRichard Lowe 
10710d63b7dSRichard Lowe 
10810d63b7dSRichard Lowe /*
10910d63b7dSRichard Lowe  * DONE.
11010d63b7dSRichard Lowe  *
11110d63b7dSRichard Lowe  *	doname_check(target, do_get, implicit, automatic)
11210d63b7dSRichard Lowe  *
11310d63b7dSRichard Lowe  *	Will call doname() and then inspect the return value
11410d63b7dSRichard Lowe  *
11510d63b7dSRichard Lowe  *	Return value:
11610d63b7dSRichard Lowe  *				Indication if the build failed or not
11710d63b7dSRichard Lowe  *
11810d63b7dSRichard Lowe  *	Parameters:
11910d63b7dSRichard Lowe  *		target		The target to build
12010d63b7dSRichard Lowe  *		do_get		Passed thru to doname()
12110d63b7dSRichard Lowe  *		implicit	Passed thru to doname()
12210d63b7dSRichard Lowe  *		automatic	Are we building a hidden dependency?
12310d63b7dSRichard Lowe  *
12410d63b7dSRichard Lowe  *	Global variables used:
12510d63b7dSRichard Lowe  *		build_failed_seen	Set if -k is on and error occurs
12610d63b7dSRichard Lowe  *		continue_after_error	Indicates that -k is on
12710d63b7dSRichard Lowe  *		report_dependencies	No error msg if -P is on
12810d63b7dSRichard Lowe  */
12910d63b7dSRichard Lowe Doname
doname_check(Name target,Boolean do_get,Boolean implicit,Boolean automatic)130*e7afc443SToomas Soome doname_check(Name target, Boolean do_get, Boolean implicit, Boolean automatic)
13110d63b7dSRichard Lowe {
13210d63b7dSRichard Lowe 	int first_time = 1;
1332e8f3c34SToomas Soome 	Doname rv = build_failed;
1342e8f3c34SToomas Soome 
13510d63b7dSRichard Lowe 	(void) fflush(stdout);
13610d63b7dSRichard Lowe try_again:
13710d63b7dSRichard Lowe 	switch (doname(target, do_get, implicit, automatic)) {
13810d63b7dSRichard Lowe 	case build_ok:
13910d63b7dSRichard Lowe 		second_pass = 0;
1402e8f3c34SToomas Soome 		rv = build_ok;
1412e8f3c34SToomas Soome 		break;
14210d63b7dSRichard Lowe 	case build_running:
14310d63b7dSRichard Lowe 		second_pass = 0;
1442e8f3c34SToomas Soome 		rv = build_running;
1452e8f3c34SToomas Soome 		break;
14610d63b7dSRichard Lowe 	case build_failed:
14710d63b7dSRichard Lowe 		if (!continue_after_error) {
1482e8f3c34SToomas Soome 			fatal(
1492e8f3c34SToomas Soome 			    gettext("Target `%s' not remade because of errors"),
1502e8f3c34SToomas Soome 			    target->string_mb);
15110d63b7dSRichard Lowe 		}
15210d63b7dSRichard Lowe 		build_failed_seen = true;
15310d63b7dSRichard Lowe 		second_pass = 0;
1542e8f3c34SToomas Soome 		rv = build_failed;
1552e8f3c34SToomas Soome 		break;
15610d63b7dSRichard Lowe 	case build_dont_know:
15710d63b7dSRichard Lowe 		/*
15810d63b7dSRichard Lowe 		 * If we can't figure out how to build an automatic
15910d63b7dSRichard Lowe 		 * (hidden) dependency, we just ignore it.
16010d63b7dSRichard Lowe 		 * We later declare the target to be out of date just in
16110d63b7dSRichard Lowe 		 * case something changed.
16210d63b7dSRichard Lowe 		 * Also, don't complain if just reporting the dependencies
16310d63b7dSRichard Lowe 		 * and not building anything.
16410d63b7dSRichard Lowe 		 */
16510d63b7dSRichard Lowe 		if (automatic || (report_dependencies_level > 0)) {
16610d63b7dSRichard Lowe 			second_pass = 0;
1672e8f3c34SToomas Soome 			rv = build_dont_know;
1682e8f3c34SToomas Soome 			break;
16910d63b7dSRichard Lowe 		}
17010d63b7dSRichard Lowe 		if(first_time) {
17110d63b7dSRichard Lowe 			first_time = 0;
17210d63b7dSRichard Lowe 			second_pass = 1;
17310d63b7dSRichard Lowe 			goto try_again;
17410d63b7dSRichard Lowe 		}
17510d63b7dSRichard Lowe 		second_pass = 0;
17610d63b7dSRichard Lowe 		if (continue_after_error && !svr4) {
17710d63b7dSRichard Lowe 			warning(gettext("Don't know how to make target `%s'"),
17810d63b7dSRichard Lowe 				target->string_mb);
17910d63b7dSRichard Lowe 			build_failed_seen = true;
1802e8f3c34SToomas Soome 			rv = build_failed;
1812e8f3c34SToomas Soome 			break;
18210d63b7dSRichard Lowe 		}
1832e8f3c34SToomas Soome 		fatal(gettext("Don't know how to make target `%s'"),
1842e8f3c34SToomas Soome 		    target->string_mb);
18510d63b7dSRichard Lowe 		break;
18610d63b7dSRichard Lowe 	}
1872e8f3c34SToomas Soome 	return (rv);
18810d63b7dSRichard Lowe }
18910d63b7dSRichard Lowe 
19010d63b7dSRichard Lowe 
19110d63b7dSRichard Lowe void
enter_explicit_rule_from_dynamic_rule(Name target,Name source)19210d63b7dSRichard Lowe enter_explicit_rule_from_dynamic_rule(Name target, Name source)
19310d63b7dSRichard Lowe {
19410d63b7dSRichard Lowe 	Property line, source_line;
19510d63b7dSRichard Lowe 	Dependency dependency;
19610d63b7dSRichard Lowe 
19710d63b7dSRichard Lowe 	source_line = get_prop(source->prop, line_prop);
19810d63b7dSRichard Lowe 	line = maybe_append_prop(target, line_prop);
19910d63b7dSRichard Lowe 	line->body.line.sccs_command = false;
20010d63b7dSRichard Lowe 	line->body.line.target = target;
20110d63b7dSRichard Lowe 	if (line->body.line.command_template == NULL) {
20210d63b7dSRichard Lowe 		line->body.line.command_template = source_line->body.line.command_template;
20310d63b7dSRichard Lowe 		for (dependency = source_line->body.line.dependencies;
20410d63b7dSRichard Lowe 		     dependency != NULL;
20510d63b7dSRichard Lowe 		     dependency = dependency->next) {
20610d63b7dSRichard Lowe 			enter_dependency(line, dependency->name, false);
20710d63b7dSRichard Lowe 		}
20810d63b7dSRichard Lowe 		line->body.line.less = target;
20910d63b7dSRichard Lowe 	}
21010d63b7dSRichard Lowe 	line->body.line.percent = NULL;
21110d63b7dSRichard Lowe }
21210d63b7dSRichard Lowe 
21310d63b7dSRichard Lowe 
21410d63b7dSRichard Lowe 
21510d63b7dSRichard Lowe Name
find_dyntarget(Name target)21610d63b7dSRichard Lowe find_dyntarget(Name target)
21710d63b7dSRichard Lowe {
21810d63b7dSRichard Lowe 	Dyntarget		p;
21910d63b7dSRichard Lowe 	int			i;
22010d63b7dSRichard Lowe 	String_rec		string;
22110d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
22210d63b7dSRichard Lowe 	wchar_t			*pp, * bufend;
22310d63b7dSRichard Lowe 	wchar_t			tbuffer[MAXPATHLEN];
22410d63b7dSRichard Lowe 	Wstring			wcb(target);
22510d63b7dSRichard Lowe 
22610d63b7dSRichard Lowe 	for (p = dyntarget_list; p != NULL; p = p->next) {
22710d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(string, buffer);
22810d63b7dSRichard Lowe 		expand_value(p->name, &string, false);
22910d63b7dSRichard Lowe 		i = 0;
23010d63b7dSRichard Lowe 		pp = string.buffer.start;
23110d63b7dSRichard Lowe 		bufend = pp + STRING_BUFFER_LENGTH;
23210d63b7dSRichard Lowe 		while((*pp != nul_char) && (pp < bufend)) {
23310d63b7dSRichard Lowe 			if(iswspace(*pp)) {
23410d63b7dSRichard Lowe 				tbuffer[i] = nul_char;
23510d63b7dSRichard Lowe 				if(i > 0) {
23610d63b7dSRichard Lowe 					if (wcb.equal(tbuffer)) {
23710d63b7dSRichard Lowe 						enter_explicit_rule_from_dynamic_rule(target, p->name);
23810d63b7dSRichard Lowe 						return(target);
23910d63b7dSRichard Lowe 					}
24010d63b7dSRichard Lowe 				}
24110d63b7dSRichard Lowe 				pp++;
24210d63b7dSRichard Lowe 				i = 0;
24310d63b7dSRichard Lowe 				continue;
24410d63b7dSRichard Lowe 			}
24510d63b7dSRichard Lowe 			tbuffer[i] = *pp;
24610d63b7dSRichard Lowe 			i++;
24710d63b7dSRichard Lowe 			pp++;
24810d63b7dSRichard Lowe 			if(*pp == nul_char) {
24910d63b7dSRichard Lowe 				tbuffer[i] = nul_char;
25010d63b7dSRichard Lowe 				if(i > 0) {
25110d63b7dSRichard Lowe 					if (wcb.equal(tbuffer)) {
25210d63b7dSRichard Lowe 						enter_explicit_rule_from_dynamic_rule(target, p->name);
25310d63b7dSRichard Lowe 						return(target);
25410d63b7dSRichard Lowe 					}
25510d63b7dSRichard Lowe 				}
25610d63b7dSRichard Lowe 				break;
25710d63b7dSRichard Lowe 			}
25810d63b7dSRichard Lowe 		}
25910d63b7dSRichard Lowe 	}
26010d63b7dSRichard Lowe 	return(NULL);
26110d63b7dSRichard Lowe }
26210d63b7dSRichard Lowe 
26310d63b7dSRichard Lowe /*
26410d63b7dSRichard Lowe  * DONE.
26510d63b7dSRichard Lowe  *
26610d63b7dSRichard Lowe  *	doname(target, do_get, implicit)
26710d63b7dSRichard Lowe  *
26810d63b7dSRichard Lowe  *	Chases all files the target depends on and builds any that
26910d63b7dSRichard Lowe  *	are out of date. If the target is out of date it is then rebuilt.
27010d63b7dSRichard Lowe  *
27110d63b7dSRichard Lowe  *	Return value:
27210d63b7dSRichard Lowe  *				Indiates if build failed or nt
27310d63b7dSRichard Lowe  *
27410d63b7dSRichard Lowe  *	Parameters:
27510d63b7dSRichard Lowe  *		target		Target to build
27610d63b7dSRichard Lowe  *		do_get		Run sccs get is nessecary
27710d63b7dSRichard Lowe  *		implicit	doname is trying to find an implicit rule
27810d63b7dSRichard Lowe  *
27910d63b7dSRichard Lowe  *	Global variables used:
28010d63b7dSRichard Lowe  *		assign_done	True if command line assgnment has happened
28110d63b7dSRichard Lowe  *		commands_done	Preserved for the case that we need local value
28210d63b7dSRichard Lowe  *		debug_level	Should we trace make's actions?
28310d63b7dSRichard Lowe  *		default_rule	The rule for ".DEFAULT", used as last resort
28410d63b7dSRichard Lowe  *		empty_name	The Name "", used when looking for single sfx
28510d63b7dSRichard Lowe  *		keep_state	Indicates that .KEEP_STATE is on
28610d63b7dSRichard Lowe  *		parallel	True if building in parallel
28710d63b7dSRichard Lowe  *		recursion_level	Used for tracing
28810d63b7dSRichard Lowe  *		report_dependencies make -P is on
28910d63b7dSRichard Lowe  */
29010d63b7dSRichard Lowe Doname
doname(Name target,Boolean do_get,Boolean implicit,Boolean automatic)291*e7afc443SToomas Soome doname(Name target, Boolean do_get, Boolean implicit, Boolean automatic)
29210d63b7dSRichard Lowe {
29310d63b7dSRichard Lowe 	Doname			result = build_dont_know;
29410d63b7dSRichard Lowe 	Chain			out_of_date_list = NULL;
29510d63b7dSRichard Lowe 	Chain			target_group;
29610d63b7dSRichard Lowe 	Property		old_locals = NULL;
297*e7afc443SToomas Soome 	Property	line;
29810d63b7dSRichard Lowe 	Property		command = NULL;
299*e7afc443SToomas Soome 	Dependency	dependency;
30010d63b7dSRichard Lowe 	Name			less = NULL;
30110d63b7dSRichard Lowe 	Name			true_target = target;
30210d63b7dSRichard Lowe 	Name			*automatics = NULL;
303*e7afc443SToomas Soome 	int		auto_count;
30410d63b7dSRichard Lowe 	Boolean			rechecking_target = false;
30510d63b7dSRichard Lowe 	Boolean			saved_commands_done;
30610d63b7dSRichard Lowe 	Boolean			restart = false;
30710d63b7dSRichard Lowe 	Boolean			save_parallel = parallel;
30810d63b7dSRichard Lowe 	Boolean			doing_subtree = false;
30910d63b7dSRichard Lowe 
31010d63b7dSRichard Lowe 	Boolean			recheck_conditionals = false;
31110d63b7dSRichard Lowe 
31210d63b7dSRichard Lowe 	if (target->state == build_running) {
31310d63b7dSRichard Lowe 		return build_running;
31410d63b7dSRichard Lowe 	}
31510d63b7dSRichard Lowe 	line = get_prop(target->prop, line_prop);
31610d63b7dSRichard Lowe 	if (line != NULL) {
31710d63b7dSRichard Lowe 		/*
31810d63b7dSRichard Lowe 		 * If this target is a member of target group and one of the
31910d63b7dSRichard Lowe 		 * other members of the group is running, mark this target
32010d63b7dSRichard Lowe 		 * as running.
32110d63b7dSRichard Lowe 		 */
32210d63b7dSRichard Lowe 		for (target_group = line->body.line.target_group;
32310d63b7dSRichard Lowe 		     target_group != NULL;
32410d63b7dSRichard Lowe 		     target_group = target_group->next) {
32510d63b7dSRichard Lowe 			if (is_running(target_group->name)) {
32610d63b7dSRichard Lowe 				target->state = build_running;
32710d63b7dSRichard Lowe 				add_pending(target,
32810d63b7dSRichard Lowe 					    recursion_level,
32910d63b7dSRichard Lowe 					    do_get,
33010d63b7dSRichard Lowe 					    implicit,
33110d63b7dSRichard Lowe 					    false);
33210d63b7dSRichard Lowe 				return build_running;
33310d63b7dSRichard Lowe 			}
33410d63b7dSRichard Lowe 		}
33510d63b7dSRichard Lowe 	}
33610d63b7dSRichard Lowe 	/*
33710d63b7dSRichard Lowe 	 * If the target is a constructed one for a "::" target,
33810d63b7dSRichard Lowe 	 * we need to consider that.
33910d63b7dSRichard Lowe 	 */
34010d63b7dSRichard Lowe 	if (target->has_target_prop) {
34110d63b7dSRichard Lowe 		true_target = get_prop(target->prop,
34210d63b7dSRichard Lowe 				       target_prop)->body.target.target;
34310d63b7dSRichard Lowe 		if (true_target->colon_splits > 0) {
34410d63b7dSRichard Lowe 			/* Make sure we have a valid time for :: targets */
34510d63b7dSRichard Lowe 			Property        time;
34610d63b7dSRichard Lowe 
34710d63b7dSRichard Lowe 			time = get_prop(true_target->prop, time_prop);
34810d63b7dSRichard Lowe 			if (time != NULL) {
34910d63b7dSRichard Lowe 				true_target->stat.time = time->body.time.time;
35010d63b7dSRichard Lowe 			}
35110d63b7dSRichard Lowe 		}
35210d63b7dSRichard Lowe 	}
35310d63b7dSRichard Lowe 	(void) exists(true_target);
35410d63b7dSRichard Lowe 	/*
35510d63b7dSRichard Lowe 	 * If the target has been processed, we don't need to do it again,
35610d63b7dSRichard Lowe 	 * unless it depends on conditional macros or a delayed assignment,
35710d63b7dSRichard Lowe 	 * or it has been done when KEEP_STATE is on.
35810d63b7dSRichard Lowe 	 */
35910d63b7dSRichard Lowe 	if (target->state == build_ok) {
36010d63b7dSRichard Lowe 		if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
36110d63b7dSRichard Lowe 			return build_ok;
36210d63b7dSRichard Lowe 		} else {
36310d63b7dSRichard Lowe 			recheck_conditionals = true;
36410d63b7dSRichard Lowe 		}
3652e8f3c34SToomas Soome 	}
36610d63b7dSRichard Lowe 	if (target->state == build_subtree) {
36710d63b7dSRichard Lowe 		/* A dynamic macro subtree is being built */
36810d63b7dSRichard Lowe 		target->state = build_dont_know;
36910d63b7dSRichard Lowe 		doing_subtree = true;
37010d63b7dSRichard Lowe 		if (!target->checking_subtree) {
37110d63b7dSRichard Lowe 			/*
37210d63b7dSRichard Lowe 			 * This target has been started before and therefore
37310d63b7dSRichard Lowe 			 * not all dependencies have to be built.
37410d63b7dSRichard Lowe 			 */
37510d63b7dSRichard Lowe 			restart = true;
37610d63b7dSRichard Lowe 		}
37710d63b7dSRichard Lowe 	} else if (target->state == build_pending) {
37810d63b7dSRichard Lowe 		target->state = build_dont_know;
37910d63b7dSRichard Lowe 		restart = true;
38010d63b7dSRichard Lowe /*
38110d63b7dSRichard Lowe 	} else if (parallel &&
38210d63b7dSRichard Lowe 		   keep_state &&
38310d63b7dSRichard Lowe 		   (target->conditional_cnt > 0)) {
38410d63b7dSRichard Lowe 	    if (!parallel_ok(target, false)) {
38510d63b7dSRichard Lowe 		add_subtree(target, recursion_level, do_get, implicit);
38610d63b7dSRichard Lowe 		target->state = build_running;
38710d63b7dSRichard Lowe 		return build_running;
38810d63b7dSRichard Lowe 	    }
38910d63b7dSRichard Lowe  */
39010d63b7dSRichard Lowe 	}
39110d63b7dSRichard Lowe 	/*
39210d63b7dSRichard Lowe 	 * If KEEP_STATE is on, we have to rebuild the target if the
39310d63b7dSRichard Lowe 	 * building of it caused new automatic dependencies to be reported.
39410d63b7dSRichard Lowe 	 * This is where we restart the build.
39510d63b7dSRichard Lowe 	 */
39610d63b7dSRichard Lowe 	if (line != NULL) {
39710d63b7dSRichard Lowe 		line->body.line.percent = NULL;
39810d63b7dSRichard Lowe 	}
39910d63b7dSRichard Lowe recheck_target:
40010d63b7dSRichard Lowe 	/* Init all local variables */
40110d63b7dSRichard Lowe 	result = build_dont_know;
40210d63b7dSRichard Lowe 	out_of_date_list = NULL;
40310d63b7dSRichard Lowe 	command = NULL;
40410d63b7dSRichard Lowe 	less = NULL;
40510d63b7dSRichard Lowe 	auto_count = 0;
40610d63b7dSRichard Lowe 	if (!restart && line != NULL) {
40710d63b7dSRichard Lowe 		/*
40810d63b7dSRichard Lowe 		 * If this target has never been built before, mark all
40910d63b7dSRichard Lowe 		 * of the dependencies as never built.
41010d63b7dSRichard Lowe 		 */
41110d63b7dSRichard Lowe 		for (dependency = line->body.line.dependencies;
41210d63b7dSRichard Lowe 		     dependency != NULL;
41310d63b7dSRichard Lowe 		     dependency = dependency->next) {
41410d63b7dSRichard Lowe 			dependency->built = false;
41510d63b7dSRichard Lowe 		}
41610d63b7dSRichard Lowe 	}
41710d63b7dSRichard Lowe 	/* Save the set of automatic depes defined for this target */
41810d63b7dSRichard Lowe 	if (keep_state &&
41910d63b7dSRichard Lowe 	    (line != NULL) &&
42010d63b7dSRichard Lowe 	    (line->body.line.dependencies != NULL)) {
42110d63b7dSRichard Lowe 		Name *p;
42210d63b7dSRichard Lowe 
42310d63b7dSRichard Lowe 		/*
42410d63b7dSRichard Lowe 		 * First run thru the dependency list to see how many
42510d63b7dSRichard Lowe 		 * autos there are.
42610d63b7dSRichard Lowe 		 */
42710d63b7dSRichard Lowe 		for (dependency = line->body.line.dependencies;
42810d63b7dSRichard Lowe 		     dependency != NULL;
42910d63b7dSRichard Lowe 		     dependency = dependency->next) {
43010d63b7dSRichard Lowe 			if (dependency->automatic && !dependency->stale) {
43110d63b7dSRichard Lowe 				auto_count++;
43210d63b7dSRichard Lowe 			}
43310d63b7dSRichard Lowe 		}
43410d63b7dSRichard Lowe 		/* Create vector to hold the current autos */
43510d63b7dSRichard Lowe 		automatics =
43610d63b7dSRichard Lowe 		  (Name *) alloca((int) (auto_count * sizeof (Name)));
43710d63b7dSRichard Lowe 		/* Copy them */
43810d63b7dSRichard Lowe 		for (p = automatics, dependency = line->body.line.dependencies;
43910d63b7dSRichard Lowe 		     dependency != NULL;
44010d63b7dSRichard Lowe 		     dependency = dependency->next) {
44110d63b7dSRichard Lowe 			if (dependency->automatic && !dependency->stale) {
44210d63b7dSRichard Lowe 				*p++ = dependency->name;
44310d63b7dSRichard Lowe 			}
44410d63b7dSRichard Lowe 		}
44510d63b7dSRichard Lowe 	}
44610d63b7dSRichard Lowe 	if (debug_level > 1) {
44710d63b7dSRichard Lowe 		(void) printf("%*sdoname(%s)\n",
44810d63b7dSRichard Lowe 			      recursion_level,
44910d63b7dSRichard Lowe 			      "",
45010d63b7dSRichard Lowe 			      target->string_mb);
45110d63b7dSRichard Lowe 	}
45210d63b7dSRichard Lowe 	recursion_level++;
45310d63b7dSRichard Lowe 	/* Avoid infinite loops */
45410d63b7dSRichard Lowe 	if (target->state == build_in_progress) {
45510d63b7dSRichard Lowe 		warning(gettext("Infinite loop: Target `%s' depends on itself"),
45610d63b7dSRichard Lowe 			target->string_mb);
45710d63b7dSRichard Lowe 		return build_ok;
45810d63b7dSRichard Lowe 	}
45910d63b7dSRichard Lowe 	target->state = build_in_progress;
46010d63b7dSRichard Lowe 
46110d63b7dSRichard Lowe 	/* Activate conditional macros for the target */
46210d63b7dSRichard Lowe 	if (!target->added_pattern_conditionals) {
46310d63b7dSRichard Lowe 		add_pattern_conditionals(target);
46410d63b7dSRichard Lowe 		target->added_pattern_conditionals = true;
46510d63b7dSRichard Lowe 	}
46610d63b7dSRichard Lowe 	if (target->conditional_cnt > 0) {
46710d63b7dSRichard Lowe 		old_locals = (Property) alloca(target->conditional_cnt *
46810d63b7dSRichard Lowe 					       sizeof (Property_rec));
46910d63b7dSRichard Lowe 		set_locals(target, old_locals);
47010d63b7dSRichard Lowe 	}
47110d63b7dSRichard Lowe 
47210d63b7dSRichard Lowe /*
47310d63b7dSRichard Lowe  * after making the call to dynamic_dependecies unconditional we can handle
47448bbca81SDaniel Hoffman  * target names that are same as file name. In this case $$@ in the
47510d63b7dSRichard Lowe  * dependencies did not mean anything. WIth this change it expands it
47610d63b7dSRichard Lowe  * as expected.
47710d63b7dSRichard Lowe  */
47810d63b7dSRichard Lowe 	if (!target->has_depe_list_expanded)
47910d63b7dSRichard Lowe 	{
48010d63b7dSRichard Lowe 		dynamic_dependencies(target);
48110d63b7dSRichard Lowe 	}
48210d63b7dSRichard Lowe 
48310d63b7dSRichard Lowe /*
48410d63b7dSRichard Lowe  *	FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
48510d63b7dSRichard Lowe  *	COMMANDS TO RUN
48610d63b7dSRichard Lowe  */
48710d63b7dSRichard Lowe 	if ((line = get_prop(target->prop, line_prop)) != NULL) {
48810d63b7dSRichard Lowe 		if (check_dependencies(&result,
48910d63b7dSRichard Lowe 				       line,
49010d63b7dSRichard Lowe 				       do_get,
49110d63b7dSRichard Lowe 				       target,
49210d63b7dSRichard Lowe 				       true_target,
49310d63b7dSRichard Lowe 				       doing_subtree,
49410d63b7dSRichard Lowe 				       &out_of_date_list,
49510d63b7dSRichard Lowe 				       old_locals,
49610d63b7dSRichard Lowe 				       implicit,
49710d63b7dSRichard Lowe 				       &command,
49810d63b7dSRichard Lowe 				       less,
49910d63b7dSRichard Lowe 				       rechecking_target,
50010d63b7dSRichard Lowe 				       recheck_conditionals)) {
50110d63b7dSRichard Lowe 			return build_running;
50210d63b7dSRichard Lowe 		}
50310d63b7dSRichard Lowe 		if (line->body.line.query != NULL) {
50410d63b7dSRichard Lowe 			delete_query_chain(line->body.line.query);
50510d63b7dSRichard Lowe 		}
50610d63b7dSRichard Lowe 		line->body.line.query = out_of_date_list;
50710d63b7dSRichard Lowe 	}
50810d63b7dSRichard Lowe 
50910d63b7dSRichard Lowe 
51010d63b7dSRichard Lowe /*
51110d63b7dSRichard Lowe  * If the target is a :: type, do not try to find the rule for the target,
51210d63b7dSRichard Lowe  * all actions will be taken by separate branches.
51310d63b7dSRichard Lowe  * Else, we try to find an implicit rule using various methods,
51410d63b7dSRichard Lowe  * we quit as soon as one is found.
51510d63b7dSRichard Lowe  *
51610d63b7dSRichard Lowe  * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
51710d63b7dSRichard Lowe  * being rechecked - the target is being rechecked means that it already
51810d63b7dSRichard Lowe  * has explicit dependencies derived from an implicit rule found
51910d63b7dSRichard Lowe  * in previous step.
52010d63b7dSRichard Lowe  */
52110d63b7dSRichard Lowe 	if (target->colon_splits == 0 && !rechecking_target) {
52210d63b7dSRichard Lowe 		/* Look for percent matched rule */
52310d63b7dSRichard Lowe 		if ((result == build_dont_know) &&
52410d63b7dSRichard Lowe 		    (command == NULL)) {
52510d63b7dSRichard Lowe 			switch (find_percent_rule(
52610d63b7dSRichard Lowe 					target,
52710d63b7dSRichard Lowe 					&command,
52810d63b7dSRichard Lowe 					recheck_conditionals)) {
52910d63b7dSRichard Lowe 			case build_failed:
53010d63b7dSRichard Lowe 				result = build_failed;
53110d63b7dSRichard Lowe 				break;
53210d63b7dSRichard Lowe 			case build_running:
53310d63b7dSRichard Lowe 				target->state = build_running;
53410d63b7dSRichard Lowe 				add_pending(target,
53510d63b7dSRichard Lowe 					    --recursion_level,
53610d63b7dSRichard Lowe 					    do_get,
53710d63b7dSRichard Lowe 					    implicit,
53810d63b7dSRichard Lowe 					    false);
53910d63b7dSRichard Lowe 				if (target->conditional_cnt > 0) {
54010d63b7dSRichard Lowe 					reset_locals(target,
54110d63b7dSRichard Lowe 						     old_locals,
54210d63b7dSRichard Lowe 						     get_prop(target->prop,
54310d63b7dSRichard Lowe 							     conditional_prop),
54410d63b7dSRichard Lowe 						     0);
54510d63b7dSRichard Lowe 				}
54610d63b7dSRichard Lowe 				return build_running;
54710d63b7dSRichard Lowe 			case build_ok:
54810d63b7dSRichard Lowe 				result = build_ok;
54910d63b7dSRichard Lowe 				break;
55010d63b7dSRichard Lowe 			}
55110d63b7dSRichard Lowe 		}
55210d63b7dSRichard Lowe 		/* Look for double suffix rule */
55310d63b7dSRichard Lowe 		if (result == build_dont_know) {
55410d63b7dSRichard Lowe 			Property member;
55510d63b7dSRichard Lowe 
55610d63b7dSRichard Lowe 			if (target->is_member &&
55710d63b7dSRichard Lowe 			    ((member = get_prop(target->prop, member_prop)) !=
55810d63b7dSRichard Lowe 			     NULL)) {
55910d63b7dSRichard Lowe 			        switch (find_ar_suffix_rule(target,
56010d63b7dSRichard Lowe 						member->body.
56110d63b7dSRichard Lowe 						member.member,
56210d63b7dSRichard Lowe 						&command,
56310d63b7dSRichard Lowe 						recheck_conditionals)) {
56410d63b7dSRichard Lowe 				case build_failed:
56510d63b7dSRichard Lowe 					result = build_failed;
56610d63b7dSRichard Lowe 					break;
56710d63b7dSRichard Lowe 				case build_running:
56810d63b7dSRichard Lowe 					target->state = build_running;
56910d63b7dSRichard Lowe 					add_pending(target,
57010d63b7dSRichard Lowe 						    --recursion_level,
57110d63b7dSRichard Lowe 						    do_get,
57210d63b7dSRichard Lowe 						    implicit,
57310d63b7dSRichard Lowe 						    false);
57410d63b7dSRichard Lowe 				    if (target->conditional_cnt > 0) {
57510d63b7dSRichard Lowe 					    reset_locals(target,
57610d63b7dSRichard Lowe 							 old_locals,
57710d63b7dSRichard Lowe 							 get_prop(target->prop,
57810d63b7dSRichard Lowe 							     conditional_prop),
57910d63b7dSRichard Lowe 							 0);
58010d63b7dSRichard Lowe 				    }
58110d63b7dSRichard Lowe 					return build_running;
58210d63b7dSRichard Lowe 				default:
58310d63b7dSRichard Lowe 					/* ALWAYS bind $% for old style */
58410d63b7dSRichard Lowe 					/* ar rules */
58510d63b7dSRichard Lowe 					if (line == NULL) {
58610d63b7dSRichard Lowe 						line =
58710d63b7dSRichard Lowe 						  maybe_append_prop(target,
58810d63b7dSRichard Lowe 								    line_prop);
58910d63b7dSRichard Lowe 					}
59010d63b7dSRichard Lowe 					line->body.line.percent =
59110d63b7dSRichard Lowe 					  member->body.member.member;
59210d63b7dSRichard Lowe 					break;
59310d63b7dSRichard Lowe 				}
59410d63b7dSRichard Lowe 			} else {
59510d63b7dSRichard Lowe 				switch (find_double_suffix_rule(target,
59610d63b7dSRichard Lowe 						&command,
59710d63b7dSRichard Lowe 						recheck_conditionals)) {
59810d63b7dSRichard Lowe 				case build_failed:
59910d63b7dSRichard Lowe 					result = build_failed;
60010d63b7dSRichard Lowe 					break;
60110d63b7dSRichard Lowe 				case build_running:
60210d63b7dSRichard Lowe 					target->state = build_running;
60310d63b7dSRichard Lowe 					add_pending(target,
60410d63b7dSRichard Lowe 						    --recursion_level,
60510d63b7dSRichard Lowe 						    do_get,
60610d63b7dSRichard Lowe 						    implicit,
60710d63b7dSRichard Lowe 						    false);
60810d63b7dSRichard Lowe 					if (target->conditional_cnt > 0) {
60910d63b7dSRichard Lowe 						reset_locals(target,
61010d63b7dSRichard Lowe 							     old_locals,
61110d63b7dSRichard Lowe 							     get_prop(target->
61210d63b7dSRichard Lowe 								      prop,
61310d63b7dSRichard Lowe 								      conditional_prop),
61410d63b7dSRichard Lowe 							     0);
61510d63b7dSRichard Lowe 					}
61610d63b7dSRichard Lowe 					return build_running;
61710d63b7dSRichard Lowe 				}
61810d63b7dSRichard Lowe 			}
61910d63b7dSRichard Lowe 		}
62010d63b7dSRichard Lowe 		/* Look for single suffix rule */
62110d63b7dSRichard Lowe 
62210d63b7dSRichard Lowe /* /tolik/
62310d63b7dSRichard Lowe  * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
62410d63b7dSRichard Lowe  * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
62510d63b7dSRichard Lowe  */
62610d63b7dSRichard Lowe /* /tolik, 06.21.96/
62710d63b7dSRichard Lowe  * Regression! See BugId 1255360
62810d63b7dSRichard Lowe  * If more than one percent rules are defined for the same target then
62910d63b7dSRichard Lowe  * the behaviour of 'make' with my previous fix may be different from one
63048bbca81SDaniel Hoffman  * of the 'old make'.
63110d63b7dSRichard Lowe  * The global variable second_pass (maybe it should be an argument to doname())
63210d63b7dSRichard Lowe  * is intended to avoid this regression. It is set in doname_check().
63310d63b7dSRichard Lowe  * First, 'make' will work as it worked before. Only when it is
63410d63b7dSRichard Lowe  * going to say "don't know how to make target" it sets second_pass to true and
63510d63b7dSRichard Lowe  * run 'doname' again but now trying to use Single Suffix Rules.
63610d63b7dSRichard Lowe  */
63710d63b7dSRichard Lowe 		if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
63810d63b7dSRichard Lowe 		    ((line == NULL) ||
63910d63b7dSRichard Lowe 		     ((line->body.line.target != NULL) &&
64010d63b7dSRichard Lowe 		      !line->body.line.target->has_regular_dependency))) {
64110d63b7dSRichard Lowe 			switch (find_suffix_rule(target,
64210d63b7dSRichard Lowe 						 target,
64310d63b7dSRichard Lowe 						 empty_name,
64410d63b7dSRichard Lowe 						 &command,
64510d63b7dSRichard Lowe 						 recheck_conditionals)) {
64610d63b7dSRichard Lowe 			case build_failed:
64710d63b7dSRichard Lowe 				result = build_failed;
64810d63b7dSRichard Lowe 				break;
64910d63b7dSRichard Lowe 			case build_running:
65010d63b7dSRichard Lowe 				target->state = build_running;
65110d63b7dSRichard Lowe 				add_pending(target,
65210d63b7dSRichard Lowe 					    --recursion_level,
65310d63b7dSRichard Lowe 					    do_get,
65410d63b7dSRichard Lowe 					    implicit,
65510d63b7dSRichard Lowe 					    false);
65610d63b7dSRichard Lowe 				if (target->conditional_cnt > 0) {
65710d63b7dSRichard Lowe 					reset_locals(target,
65810d63b7dSRichard Lowe 						     old_locals,
65910d63b7dSRichard Lowe 						     get_prop(target->prop,
66010d63b7dSRichard Lowe 							     conditional_prop),
66110d63b7dSRichard Lowe 						     0);
66210d63b7dSRichard Lowe 				}
66310d63b7dSRichard Lowe 				return build_running;
66410d63b7dSRichard Lowe 			}
66510d63b7dSRichard Lowe 		}
66610d63b7dSRichard Lowe 		/* Try to sccs get */
66710d63b7dSRichard Lowe 		if ((command == NULL) &&
66810d63b7dSRichard Lowe 		    (result == build_dont_know) &&
66910d63b7dSRichard Lowe 		    do_get) {
67010d63b7dSRichard Lowe 			result = sccs_get(target, &command);
67110d63b7dSRichard Lowe 		}
67210d63b7dSRichard Lowe 
67310d63b7dSRichard Lowe 		/* Use .DEFAULT rule if it is defined. */
67410d63b7dSRichard Lowe 		if ((command == NULL) &&
67510d63b7dSRichard Lowe 		    (result == build_dont_know) &&
67610d63b7dSRichard Lowe 		    (true_target->colons == no_colon) &&
67710d63b7dSRichard Lowe 		    default_rule &&
67810d63b7dSRichard Lowe 		    !implicit) {
67910d63b7dSRichard Lowe 			/* Make sure we have a line prop */
68010d63b7dSRichard Lowe 			line = maybe_append_prop(target, line_prop);
68110d63b7dSRichard Lowe 			command = line;
68210d63b7dSRichard Lowe 			Boolean out_of_date;
68310d63b7dSRichard Lowe 			if (true_target->is_member) {
68410d63b7dSRichard Lowe 				out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
68510d63b7dSRichard Lowe 									line->body.line.dependency_time);
68610d63b7dSRichard Lowe 			} else {
68710d63b7dSRichard Lowe 				out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
68810d63b7dSRichard Lowe 								    line->body.line.dependency_time);
68910d63b7dSRichard Lowe 			}
69010d63b7dSRichard Lowe 			if (build_unconditional || out_of_date) {
69110d63b7dSRichard Lowe 				line->body.line.is_out_of_date = true;
69210d63b7dSRichard Lowe 				if (debug_level > 0) {
69310d63b7dSRichard Lowe 					(void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
69410d63b7dSRichard Lowe 						      recursion_level,
69510d63b7dSRichard Lowe 						      "",
69610d63b7dSRichard Lowe 						      true_target->string_mb);
69710d63b7dSRichard Lowe 				}
69810d63b7dSRichard Lowe 			}
69910d63b7dSRichard Lowe 			line->body.line.sccs_command = false;
70010d63b7dSRichard Lowe 			line->body.line.command_template = default_rule;
70110d63b7dSRichard Lowe 			line->body.line.target = true_target;
70210d63b7dSRichard Lowe 			line->body.line.star = NULL;
70310d63b7dSRichard Lowe 			line->body.line.less = true_target;
70410d63b7dSRichard Lowe 			line->body.line.percent = NULL;
70510d63b7dSRichard Lowe 		}
70610d63b7dSRichard Lowe 	}
70710d63b7dSRichard Lowe 
70810d63b7dSRichard Lowe 	/* We say "target up to date" if no cmd were executed for the target */
70910d63b7dSRichard Lowe 	if (!target->is_double_colon_parent) {
71010d63b7dSRichard Lowe 		commands_done = false;
71110d63b7dSRichard Lowe 	}
71210d63b7dSRichard Lowe 
71310d63b7dSRichard Lowe 	silent = silent_all;
71410d63b7dSRichard Lowe 	ignore_errors = ignore_errors_all;
71510d63b7dSRichard Lowe 	if  (posix)
71610d63b7dSRichard Lowe 	{
71710d63b7dSRichard Lowe 	  if  (!silent)
71810d63b7dSRichard Lowe 	  {
71910d63b7dSRichard Lowe             silent = (Boolean) target->silent_mode;
72010d63b7dSRichard Lowe 	  }
72110d63b7dSRichard Lowe 	  if  (!ignore_errors)
72210d63b7dSRichard Lowe 	  {
72310d63b7dSRichard Lowe             ignore_errors = (Boolean) target->ignore_error_mode;
72410d63b7dSRichard Lowe 	  }
72510d63b7dSRichard Lowe 	}
72610d63b7dSRichard Lowe 
72710d63b7dSRichard Lowe 	int doname_dyntarget = 0;
72810d63b7dSRichard Lowe r_command:
72910d63b7dSRichard Lowe 	/* Run commands if any. */
73010d63b7dSRichard Lowe 	if ((command != NULL) &&
73110d63b7dSRichard Lowe 	    (command->body.line.command_template != NULL)) {
73210d63b7dSRichard Lowe 		if (result != build_failed) {
73348bbca81SDaniel Hoffman 			result = run_command(command,
73410d63b7dSRichard Lowe 					     (Boolean) ((parallel || save_parallel) && !silent));
73510d63b7dSRichard Lowe 		}
73610d63b7dSRichard Lowe 		switch (result) {
73710d63b7dSRichard Lowe 		case build_running:
73810d63b7dSRichard Lowe 			add_running(target,
73910d63b7dSRichard Lowe 				    true_target,
74010d63b7dSRichard Lowe 				    command,
74110d63b7dSRichard Lowe 				    --recursion_level,
74210d63b7dSRichard Lowe 				    auto_count,
74310d63b7dSRichard Lowe 				    automatics,
74410d63b7dSRichard Lowe 				    do_get,
74510d63b7dSRichard Lowe 				    implicit);
74610d63b7dSRichard Lowe 			target->state = build_running;
74710d63b7dSRichard Lowe 			if ((line = get_prop(target->prop,
74810d63b7dSRichard Lowe 					     line_prop)) != NULL) {
74910d63b7dSRichard Lowe 				if (line->body.line.query != NULL) {
75010d63b7dSRichard Lowe 					delete_query_chain(line->body.line.query);
75110d63b7dSRichard Lowe 				}
75210d63b7dSRichard Lowe 				line->body.line.query = NULL;
75310d63b7dSRichard Lowe 			}
75410d63b7dSRichard Lowe 			if (target->conditional_cnt > 0) {
75510d63b7dSRichard Lowe 				reset_locals(target,
75610d63b7dSRichard Lowe 					     old_locals,
75710d63b7dSRichard Lowe 					     get_prop(target->prop,
75810d63b7dSRichard Lowe 						     conditional_prop),
75910d63b7dSRichard Lowe 					     0);
76010d63b7dSRichard Lowe 			}
76110d63b7dSRichard Lowe 			return build_running;
76210d63b7dSRichard Lowe 		case build_serial:
76310d63b7dSRichard Lowe 			add_serial(target,
76410d63b7dSRichard Lowe 				   --recursion_level,
76510d63b7dSRichard Lowe 				   do_get,
76610d63b7dSRichard Lowe 				   implicit);
76710d63b7dSRichard Lowe 			target->state = build_running;
76810d63b7dSRichard Lowe 			line = get_prop(target->prop, line_prop);
76910d63b7dSRichard Lowe 			if (line != NULL) {
77010d63b7dSRichard Lowe 				if (line->body.line.query != NULL) {
77110d63b7dSRichard Lowe 					delete_query_chain(line->body.line.query);
77210d63b7dSRichard Lowe 				}
77310d63b7dSRichard Lowe 				line->body.line.query = NULL;
77410d63b7dSRichard Lowe 			}
77510d63b7dSRichard Lowe 			if (target->conditional_cnt > 0) {
77610d63b7dSRichard Lowe 				reset_locals(target,
77710d63b7dSRichard Lowe 					     old_locals,
77810d63b7dSRichard Lowe 					     get_prop(target->prop,
77910d63b7dSRichard Lowe 						     conditional_prop),
78010d63b7dSRichard Lowe 					     0);
78110d63b7dSRichard Lowe 			}
78210d63b7dSRichard Lowe 			return build_running;
78310d63b7dSRichard Lowe 		case build_ok:
78410d63b7dSRichard Lowe 			/* If all went OK set a nice timestamp */
78510d63b7dSRichard Lowe 			if (true_target->stat.time == file_doesnt_exist) {
78610d63b7dSRichard Lowe 				true_target->stat.time = file_max_time;
78710d63b7dSRichard Lowe 			}
78810d63b7dSRichard Lowe 			break;
78910d63b7dSRichard Lowe 		}
79010d63b7dSRichard Lowe 	} else {
79110d63b7dSRichard Lowe 		/*
79210d63b7dSRichard Lowe 		 * If no command was found for the target, and it doesn't
79310d63b7dSRichard Lowe 		 * exist, and it is mentioned as a target in the makefile,
79410d63b7dSRichard Lowe 		 * we say it is extremely new and that it is OK.
79510d63b7dSRichard Lowe 		 */
79610d63b7dSRichard Lowe 		if (target->colons != no_colon) {
79710d63b7dSRichard Lowe 			if (true_target->stat.time == file_doesnt_exist){
79810d63b7dSRichard Lowe 				true_target->stat.time = file_max_time;
79910d63b7dSRichard Lowe 			}
80010d63b7dSRichard Lowe 			result = build_ok;
80110d63b7dSRichard Lowe 		}
80210d63b7dSRichard Lowe 		/*
80310d63b7dSRichard Lowe 		 * Trying dynamic targets.
80410d63b7dSRichard Lowe 		 */
80510d63b7dSRichard Lowe 		if(!doname_dyntarget) {
80610d63b7dSRichard Lowe 			doname_dyntarget = 1;
80710d63b7dSRichard Lowe 			Name dtarg = find_dyntarget(target);
80810d63b7dSRichard Lowe 			if(dtarg!=NULL) {
80910d63b7dSRichard Lowe 				if (!target->has_depe_list_expanded) {
81010d63b7dSRichard Lowe 					dynamic_dependencies(target);
81110d63b7dSRichard Lowe 				}
81210d63b7dSRichard Lowe 				if ((line = get_prop(target->prop, line_prop)) != NULL) {
81310d63b7dSRichard Lowe 					if (check_dependencies(&result,
81410d63b7dSRichard Lowe 					                       line,
81510d63b7dSRichard Lowe 					                       do_get,
81610d63b7dSRichard Lowe 					                       target,
81710d63b7dSRichard Lowe 					                       true_target,
81810d63b7dSRichard Lowe 					                       doing_subtree,
81910d63b7dSRichard Lowe 					                       &out_of_date_list,
82010d63b7dSRichard Lowe 					                       old_locals,
82110d63b7dSRichard Lowe 					                       implicit,
82210d63b7dSRichard Lowe 					                       &command,
82310d63b7dSRichard Lowe 					                       less,
82410d63b7dSRichard Lowe 					                       rechecking_target,
82510d63b7dSRichard Lowe 					                       recheck_conditionals))
82610d63b7dSRichard Lowe 					{
82710d63b7dSRichard Lowe 						return build_running;
82810d63b7dSRichard Lowe 					}
82910d63b7dSRichard Lowe 					if (line->body.line.query != NULL) {
83010d63b7dSRichard Lowe 						delete_query_chain(line->body.line.query);
83110d63b7dSRichard Lowe 					}
83210d63b7dSRichard Lowe 					line->body.line.query = out_of_date_list;
83310d63b7dSRichard Lowe 				}
83410d63b7dSRichard Lowe 				goto r_command;
83510d63b7dSRichard Lowe 			}
83610d63b7dSRichard Lowe 		}
83710d63b7dSRichard Lowe 		/*
83810d63b7dSRichard Lowe 		 * If the file exists, it is OK that we couldnt figure
83910d63b7dSRichard Lowe 		 * out how to build it.
84010d63b7dSRichard Lowe 		 */
84110d63b7dSRichard Lowe 		(void) exists(target);
84210d63b7dSRichard Lowe 		if ((target->stat.time != file_doesnt_exist) &&
84310d63b7dSRichard Lowe 		    (result == build_dont_know)) {
84410d63b7dSRichard Lowe 			result = build_ok;
84510d63b7dSRichard Lowe 		}
84610d63b7dSRichard Lowe 	}
84710d63b7dSRichard Lowe 
84810d63b7dSRichard Lowe 	/*
84910d63b7dSRichard Lowe 	 * Some of the following is duplicated in the function finish_doname.
85010d63b7dSRichard Lowe 	 * If anything is changed here, check to see if it needs to be
85110d63b7dSRichard Lowe 	 * changed there.
85210d63b7dSRichard Lowe 	 */
85310d63b7dSRichard Lowe 	if ((line = get_prop(target->prop, line_prop)) != NULL) {
85410d63b7dSRichard Lowe 		if (line->body.line.query != NULL) {
85510d63b7dSRichard Lowe 			delete_query_chain(line->body.line.query);
85610d63b7dSRichard Lowe 		}
85710d63b7dSRichard Lowe 		line->body.line.query = NULL;
85810d63b7dSRichard Lowe 	}
85910d63b7dSRichard Lowe 	target->state = result;
86010d63b7dSRichard Lowe 	parallel = save_parallel;
86110d63b7dSRichard Lowe 	if (target->conditional_cnt > 0) {
86210d63b7dSRichard Lowe 		reset_locals(target,
86310d63b7dSRichard Lowe 			     old_locals,
86410d63b7dSRichard Lowe 			     get_prop(target->prop, conditional_prop),
86510d63b7dSRichard Lowe 			     0);
86610d63b7dSRichard Lowe 	}
86710d63b7dSRichard Lowe 	recursion_level--;
86810d63b7dSRichard Lowe 	if (target->is_member) {
86910d63b7dSRichard Lowe 		Property member;
87010d63b7dSRichard Lowe 
87110d63b7dSRichard Lowe 		/* Propagate the timestamp from the member file to the member*/
87210d63b7dSRichard Lowe 		if ((target->stat.time != file_max_time) &&
87310d63b7dSRichard Lowe 		    ((member = get_prop(target->prop, member_prop)) != NULL) &&
87410d63b7dSRichard Lowe 		    (exists(member->body.member.member) > file_doesnt_exist)) {
87510d63b7dSRichard Lowe 			target->stat.time =
87610d63b7dSRichard Lowe 			  member->body.member.member->stat.time;
87710d63b7dSRichard Lowe 		}
87810d63b7dSRichard Lowe 	}
87910d63b7dSRichard Lowe 	/*
88010d63b7dSRichard Lowe 	 * Check if we found any new auto dependencies when we
88110d63b7dSRichard Lowe 	 * built the target.
88210d63b7dSRichard Lowe 	 */
88310d63b7dSRichard Lowe 	if ((result == build_ok) && check_auto_dependencies(target,
88410d63b7dSRichard Lowe 							    auto_count,
88510d63b7dSRichard Lowe 							    automatics)) {
88610d63b7dSRichard Lowe 		if (debug_level > 0) {
88710d63b7dSRichard Lowe 			(void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
88810d63b7dSRichard Lowe 				      recursion_level,
88910d63b7dSRichard Lowe 				      "",
89010d63b7dSRichard Lowe 				      true_target->string_mb);
89110d63b7dSRichard Lowe 		}
89210d63b7dSRichard Lowe 		rechecking_target = true;
89310d63b7dSRichard Lowe 		saved_commands_done = commands_done;
89410d63b7dSRichard Lowe 		goto recheck_target;
89510d63b7dSRichard Lowe 	}
89610d63b7dSRichard Lowe 
89710d63b7dSRichard Lowe 	if (rechecking_target && !commands_done) {
89810d63b7dSRichard Lowe 		commands_done = saved_commands_done;
89910d63b7dSRichard Lowe 	}
90010d63b7dSRichard Lowe 
90110d63b7dSRichard Lowe 	return result;
90210d63b7dSRichard Lowe }
90310d63b7dSRichard Lowe 
90410d63b7dSRichard Lowe /*
90510d63b7dSRichard Lowe  * DONE.
90610d63b7dSRichard Lowe  *
90710d63b7dSRichard Lowe  *	check_dependencies(result, line, do_get,
90810d63b7dSRichard Lowe  *			target, true_target, doing_subtree, out_of_date_tail,
90910d63b7dSRichard Lowe  *			old_locals, implicit, command, less, rechecking_target)
91010d63b7dSRichard Lowe  *
91110d63b7dSRichard Lowe  *	Return value:
91210d63b7dSRichard Lowe  *				True returned if some dependencies left running
91348bbca81SDaniel Hoffman  *
91410d63b7dSRichard Lowe  *	Parameters:
91510d63b7dSRichard Lowe  *		result		Pointer to cell we update if build failed
91610d63b7dSRichard Lowe  *		line		We get the dependencies from here
91710d63b7dSRichard Lowe  *		do_get		Allow use of sccs get in recursive doname()
91810d63b7dSRichard Lowe  *		target		The target to chase dependencies for
91910d63b7dSRichard Lowe  *		true_target	The real one for :: and lib(member)
92010d63b7dSRichard Lowe  *		doing_subtree	True if building a conditional macro subtree
92110d63b7dSRichard Lowe  *		out_of_date_tail Used to set the $? list
92210d63b7dSRichard Lowe  *		old_locals	Used for resetting the local macros
92310d63b7dSRichard Lowe  *		implicit	Called when scanning for implicit rules?
92410d63b7dSRichard Lowe  *		command		Place to stuff command
92510d63b7dSRichard Lowe  *		less		Set to $< value
92610d63b7dSRichard Lowe  *
92710d63b7dSRichard Lowe  *	Global variables used:
92810d63b7dSRichard Lowe  *		command_changed	Set if we suspect .make.state needs rewrite
92910d63b7dSRichard Lowe  *		debug_level	Should we trace actions?
93010d63b7dSRichard Lowe  *		force		The Name " FORCE", compared against
93110d63b7dSRichard Lowe  *		recursion_level	Used for tracing
93210d63b7dSRichard Lowe  *		rewrite_statefile Set if .make.state needs rewriting
93310d63b7dSRichard Lowe  *		wait_name	The Name ".WAIT", compared against
93410d63b7dSRichard Lowe  */
93510d63b7dSRichard Lowe static Boolean
check_dependencies(Doname * result,Property line,Boolean do_get,Name target,Name true_target,Boolean doing_subtree,Chain * out_of_date_tail,Property old_locals,Boolean implicit,Property * command,Name less,Boolean rechecking_target,Boolean recheck_conditionals)93610d63b7dSRichard Lowe check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals)
93710d63b7dSRichard Lowe {
93810d63b7dSRichard Lowe 	Boolean			dependencies_running;
939*e7afc443SToomas Soome 	Dependency	dependency;
94010d63b7dSRichard Lowe 	Doname			dep_result;
94110d63b7dSRichard Lowe 	Boolean			dependency_changed = false;
94210d63b7dSRichard Lowe 
94310d63b7dSRichard Lowe 	line->body.line.dependency_time = file_doesnt_exist;
94410d63b7dSRichard Lowe 	if (line->body.line.query != NULL) {
94510d63b7dSRichard Lowe 		delete_query_chain(line->body.line.query);
94610d63b7dSRichard Lowe 	}
94710d63b7dSRichard Lowe 	line->body.line.query = NULL;
94810d63b7dSRichard Lowe 	line->body.line.is_out_of_date = false;
94910d63b7dSRichard Lowe 	dependencies_running = false;
95010d63b7dSRichard Lowe 	/*
95110d63b7dSRichard Lowe 	 * Run thru all the dependencies and call doname() recursively
95210d63b7dSRichard Lowe 	 * on each of them.
95310d63b7dSRichard Lowe 	 */
95410d63b7dSRichard Lowe 	for (dependency = line->body.line.dependencies;
95510d63b7dSRichard Lowe 	     dependency != NULL;
95610d63b7dSRichard Lowe 	     dependency = dependency->next) {
95710d63b7dSRichard Lowe 		Boolean this_dependency_changed = false;
95810d63b7dSRichard Lowe 
95910d63b7dSRichard Lowe 		if (!dependency->automatic &&
96010d63b7dSRichard Lowe 		    (rechecking_target || target->rechecking_target)) {
96110d63b7dSRichard Lowe 			/*
96210d63b7dSRichard Lowe 			 * We only bother with the autos when rechecking
96310d63b7dSRichard Lowe 			 */
96410d63b7dSRichard Lowe 			continue;
96510d63b7dSRichard Lowe 		}
96610d63b7dSRichard Lowe 
96710d63b7dSRichard Lowe 		if (dependency->name == wait_name) {
96810d63b7dSRichard Lowe 			/*
96910d63b7dSRichard Lowe 			 * The special target .WAIT means finish all of
97010d63b7dSRichard Lowe 			 * the prior dependencies before continuing.
97110d63b7dSRichard Lowe 			 */
97210d63b7dSRichard Lowe 			if (dependencies_running) {
97310d63b7dSRichard Lowe 				break;
97410d63b7dSRichard Lowe 			}
97510d63b7dSRichard Lowe 		} else if ((!parallel_ok(dependency->name, false)) &&
97610d63b7dSRichard Lowe 			   (dependencies_running)) {
97710d63b7dSRichard Lowe 			/*
97810d63b7dSRichard Lowe 			 * If we can't execute the current dependency in
97910d63b7dSRichard Lowe 			 * parallel, hold off the dependency processing
98010d63b7dSRichard Lowe 			 * to preserve the order of the dependencies.
98110d63b7dSRichard Lowe 			 */
98210d63b7dSRichard Lowe 			break;
98310d63b7dSRichard Lowe 		} else {
98410d63b7dSRichard Lowe 			timestruc_t	depe_time = file_doesnt_exist;
98510d63b7dSRichard Lowe 
98610d63b7dSRichard Lowe 
98710d63b7dSRichard Lowe 			if (true_target->is_member) {
98810d63b7dSRichard Lowe 				depe_time = exists(dependency->name);
98910d63b7dSRichard Lowe 			}
99010d63b7dSRichard Lowe 			if (dependency->built ||
99110d63b7dSRichard Lowe 			    (dependency->name->state == build_failed)) {
99210d63b7dSRichard Lowe 				dep_result = (Doname) dependency->name->state;
99310d63b7dSRichard Lowe 			} else {
99410d63b7dSRichard Lowe 				dep_result = doname_check(dependency->name,
99510d63b7dSRichard Lowe 							  do_get,
99610d63b7dSRichard Lowe 							  false,
99710d63b7dSRichard Lowe 							  (Boolean) dependency->automatic);
99810d63b7dSRichard Lowe 			}
99910d63b7dSRichard Lowe 			if (true_target->is_member || dependency->name->is_member) {
100010d63b7dSRichard Lowe 				/* should compare only secs, cause lib members does not have nsec time resolution */
100110d63b7dSRichard Lowe 				if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
100210d63b7dSRichard Lowe 					this_dependency_changed =
100310d63b7dSRichard Lowe 					  dependency_changed =
100410d63b7dSRichard Lowe 					    true;
100510d63b7dSRichard Lowe 				}
100610d63b7dSRichard Lowe 			} else {
100710d63b7dSRichard Lowe 				if (depe_time != dependency->name->stat.time) {
100810d63b7dSRichard Lowe 					this_dependency_changed =
100910d63b7dSRichard Lowe 					  dependency_changed =
101010d63b7dSRichard Lowe 					    true;
101110d63b7dSRichard Lowe 				}
101210d63b7dSRichard Lowe 			}
101310d63b7dSRichard Lowe 			dependency->built = true;
101410d63b7dSRichard Lowe 			switch (dep_result) {
101510d63b7dSRichard Lowe 			case build_running:
101610d63b7dSRichard Lowe 				dependencies_running = true;
101710d63b7dSRichard Lowe 				continue;
101810d63b7dSRichard Lowe 			case build_failed:
101910d63b7dSRichard Lowe 				*result = build_failed;
102010d63b7dSRichard Lowe 				break;
102110d63b7dSRichard Lowe 			case build_dont_know:
102210d63b7dSRichard Lowe /*
102310d63b7dSRichard Lowe  * If make can't figure out how to make a dependency, maybe the dependency
102410d63b7dSRichard Lowe  * is out of date. In this case, we just declare the target out of date
102510d63b7dSRichard Lowe  * and go on. If we really need the dependency, the make'ing of the target
102610d63b7dSRichard Lowe  * will fail. This will only happen for automatic (hidden) dependencies.
102710d63b7dSRichard Lowe  */
102810d63b7dSRichard Lowe 				if(!recheck_conditionals) {
102910d63b7dSRichard Lowe 					line->body.line.is_out_of_date = true;
103010d63b7dSRichard Lowe 				}
103110d63b7dSRichard Lowe 				/*
103210d63b7dSRichard Lowe 				 * Make sure the dependency is not saved
103310d63b7dSRichard Lowe 				 * in the state file.
103410d63b7dSRichard Lowe 				 */
103510d63b7dSRichard Lowe 				dependency->stale = true;
103610d63b7dSRichard Lowe 				rewrite_statefile =
103710d63b7dSRichard Lowe 				  command_changed =
103810d63b7dSRichard Lowe 				    true;
103910d63b7dSRichard Lowe 				if (debug_level > 0) {
104010d63b7dSRichard Lowe 					(void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
104110d63b7dSRichard Lowe 						     true_target->string_mb,
104210d63b7dSRichard Lowe 						     dependency->name->string_mb);
104310d63b7dSRichard Lowe 				}
104410d63b7dSRichard Lowe 				break;
104510d63b7dSRichard Lowe 			}
104610d63b7dSRichard Lowe 			if (dependency->name->depends_on_conditional) {
104710d63b7dSRichard Lowe 				target->depends_on_conditional = true;
104810d63b7dSRichard Lowe 			}
104910d63b7dSRichard Lowe 			if (dependency->name == force) {
105010d63b7dSRichard Lowe 				target->stat.time =
105110d63b7dSRichard Lowe 				  dependency->name->stat.time;
105210d63b7dSRichard Lowe 			}
105310d63b7dSRichard Lowe 			/*
105410d63b7dSRichard Lowe 			 * Propagate new timestamp from "member" to
105510d63b7dSRichard Lowe 			 * "lib.a(member)".
105610d63b7dSRichard Lowe 			 */
105710d63b7dSRichard Lowe 			(void) exists(dependency->name);
105810d63b7dSRichard Lowe 
105910d63b7dSRichard Lowe 			/* Collect the timestamp of the youngest dependency */
106010d63b7dSRichard Lowe 			line->body.line.dependency_time =
106110d63b7dSRichard Lowe 			  MAX(dependency->name->stat.time,
106210d63b7dSRichard Lowe 			      line->body.line.dependency_time);
106310d63b7dSRichard Lowe 
106410d63b7dSRichard Lowe 			/* Correction: do not consider nanosecs for members */
106510d63b7dSRichard Lowe 			if(true_target->is_member || dependency->name->is_member) {
106610d63b7dSRichard Lowe 				line->body.line.dependency_time.tv_nsec = 0;
106710d63b7dSRichard Lowe 			}
106810d63b7dSRichard Lowe 
106910d63b7dSRichard Lowe 			if (debug_level > 1) {
107010d63b7dSRichard Lowe 				(void) printf(gettext("%*sDate(%s)=%s \n"),
107110d63b7dSRichard Lowe 					      recursion_level,
107210d63b7dSRichard Lowe 					      "",
107310d63b7dSRichard Lowe 					      dependency->name->string_mb,
107410d63b7dSRichard Lowe 					      time_to_string(dependency->name->
107510d63b7dSRichard Lowe 							     stat.time));
107610d63b7dSRichard Lowe 				if (dependency->name->stat.time > line->body.line.dependency_time) {
107710d63b7dSRichard Lowe 					(void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
107810d63b7dSRichard Lowe 						      recursion_level,
107910d63b7dSRichard Lowe 						      "",
108010d63b7dSRichard Lowe 						      true_target->string_mb,
108110d63b7dSRichard Lowe 						      time_to_string(line->body.line.
108210d63b7dSRichard Lowe 								     dependency_time));
108310d63b7dSRichard Lowe 				}
108410d63b7dSRichard Lowe 			}
108510d63b7dSRichard Lowe 
108610d63b7dSRichard Lowe 			/* Build the $? list */
108710d63b7dSRichard Lowe 			if (true_target->is_member) {
108810d63b7dSRichard Lowe 				if (this_dependency_changed == true) {
108910d63b7dSRichard Lowe 					true_target->stat.time = dependency->name->stat.time;
109010d63b7dSRichard Lowe 					true_target->stat.time.tv_sec--;
109110d63b7dSRichard Lowe 				} else {
109248bbca81SDaniel Hoffman 					/* Dina:
109310d63b7dSRichard Lowe 					 * The next statement is commented
109410d63b7dSRichard Lowe 					 * out as a fix for bug #1051032.
109510d63b7dSRichard Lowe 					 * if dependency hasn't changed
109610d63b7dSRichard Lowe 					 * then there's no need to invalidate
109710d63b7dSRichard Lowe 					 * true_target. This statemnt causes
109810d63b7dSRichard Lowe 					 * make to take much longer to process
109910d63b7dSRichard Lowe 					 * an already-built archive. Soren
110010d63b7dSRichard Lowe 					 * said it was a quick fix for some
110110d63b7dSRichard Lowe 					 * problem he doesn't remember.
110210d63b7dSRichard Lowe 					true_target->stat.time = file_no_time;
110310d63b7dSRichard Lowe 					 */
110410d63b7dSRichard Lowe 					(void) exists(true_target);
110510d63b7dSRichard Lowe 				}
110610d63b7dSRichard Lowe 			} else {
110710d63b7dSRichard Lowe 				(void) exists(true_target);
110810d63b7dSRichard Lowe 			}
110910d63b7dSRichard Lowe 			Boolean out_of_date;
111010d63b7dSRichard Lowe 			if (true_target->is_member || dependency->name->is_member) {
111110d63b7dSRichard Lowe 				out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
111210d63b7dSRichard Lowe 							                dependency->name->stat.time);
111310d63b7dSRichard Lowe 			} else {
111410d63b7dSRichard Lowe 				out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
111510d63b7dSRichard Lowe 							            dependency->name->stat.time);
111610d63b7dSRichard Lowe 			}
111710d63b7dSRichard Lowe 			if ((build_unconditional || out_of_date) &&
111810d63b7dSRichard Lowe 			    (dependency->name != force) &&
111910d63b7dSRichard Lowe 			    (dependency->stale == false)) {
112010d63b7dSRichard Lowe 				*out_of_date_tail = ALLOC(Chain);
112110d63b7dSRichard Lowe 				if (dependency->name->is_member &&
112210d63b7dSRichard Lowe 				    (get_prop(dependency->name->prop,
112310d63b7dSRichard Lowe 					      member_prop) != NULL)) {
112410d63b7dSRichard Lowe 					(*out_of_date_tail)->name =
112510d63b7dSRichard Lowe 					  get_prop(dependency->name->prop,
112610d63b7dSRichard Lowe 						   member_prop)->
112710d63b7dSRichard Lowe 						     body.member.member;
112810d63b7dSRichard Lowe 				} else {
112910d63b7dSRichard Lowe 					(*out_of_date_tail)->name =
113010d63b7dSRichard Lowe 					  dependency->name;
113110d63b7dSRichard Lowe 				}
113210d63b7dSRichard Lowe 				(*out_of_date_tail)->next = NULL;
113310d63b7dSRichard Lowe 				out_of_date_tail = &(*out_of_date_tail)->next;
113410d63b7dSRichard Lowe 				if (debug_level > 0) {
113510d63b7dSRichard Lowe 					if (dependency->name->stat.time == file_max_time) {
113610d63b7dSRichard Lowe 						(void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
113710d63b7dSRichard Lowe 							      recursion_level,
113810d63b7dSRichard Lowe 							      "",
113910d63b7dSRichard Lowe 							      true_target->string_mb,
114010d63b7dSRichard Lowe 							      dependency->name->string_mb);
114110d63b7dSRichard Lowe 					} else {
114210d63b7dSRichard Lowe 						(void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
114310d63b7dSRichard Lowe 							      recursion_level,
114410d63b7dSRichard Lowe 							      "",
114510d63b7dSRichard Lowe 							      true_target->string_mb,
114610d63b7dSRichard Lowe 							      dependency->name->string_mb);
114710d63b7dSRichard Lowe 					}
114810d63b7dSRichard Lowe 				}
114910d63b7dSRichard Lowe 			}
115010d63b7dSRichard Lowe 			if (dependency->name == force) {
115110d63b7dSRichard Lowe 				force->stat.time =
115210d63b7dSRichard Lowe 				  file_max_time;
115310d63b7dSRichard Lowe 				force->state = build_dont_know;
115410d63b7dSRichard Lowe 			}
115510d63b7dSRichard Lowe 		}
115610d63b7dSRichard Lowe 	}
115710d63b7dSRichard Lowe 	if (dependencies_running) {
115810d63b7dSRichard Lowe 		if (doing_subtree) {
115910d63b7dSRichard Lowe 			if (target->conditional_cnt > 0) {
116010d63b7dSRichard Lowe 				reset_locals(target,
116110d63b7dSRichard Lowe 					     old_locals,
116210d63b7dSRichard Lowe 					     get_prop(target->prop,
116310d63b7dSRichard Lowe 						      conditional_prop),
116410d63b7dSRichard Lowe 					     0);
116510d63b7dSRichard Lowe 			}
116610d63b7dSRichard Lowe 			return true;
116710d63b7dSRichard Lowe 		} else {
116810d63b7dSRichard Lowe 			target->state = build_running;
116910d63b7dSRichard Lowe 			add_pending(target,
117010d63b7dSRichard Lowe 				    --recursion_level,
117110d63b7dSRichard Lowe 				    do_get,
117210d63b7dSRichard Lowe 				    implicit,
117310d63b7dSRichard Lowe 				    false);
117410d63b7dSRichard Lowe 			if (target->conditional_cnt > 0) {
117510d63b7dSRichard Lowe 				reset_locals(target,
117610d63b7dSRichard Lowe 					     old_locals,
117710d63b7dSRichard Lowe 					     get_prop(target->prop,
117810d63b7dSRichard Lowe 						      conditional_prop),
117910d63b7dSRichard Lowe 					     0);
118010d63b7dSRichard Lowe 			}
118110d63b7dSRichard Lowe 			return true;
118210d63b7dSRichard Lowe 		}
118310d63b7dSRichard Lowe 	}
118410d63b7dSRichard Lowe 	/*
118510d63b7dSRichard Lowe 	 * Collect the timestamp of the youngest double colon target
118610d63b7dSRichard Lowe 	 * dependency.
118710d63b7dSRichard Lowe 	 */
118810d63b7dSRichard Lowe 	if (target->is_double_colon_parent) {
118910d63b7dSRichard Lowe 		for (dependency = line->body.line.dependencies;
119010d63b7dSRichard Lowe 		     dependency != NULL;
119110d63b7dSRichard Lowe 		     dependency = dependency->next) {
119210d63b7dSRichard Lowe 			Property        tmp_line;
119310d63b7dSRichard Lowe 
119410d63b7dSRichard Lowe 			if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
119510d63b7dSRichard Lowe 				if(tmp_line->body.line.dependency_time != file_max_time) {
119610d63b7dSRichard Lowe 					target->stat.time =
119710d63b7dSRichard Lowe 					  MAX(tmp_line->body.line.dependency_time,
119810d63b7dSRichard Lowe 					      target->stat.time);
119910d63b7dSRichard Lowe 				}
120010d63b7dSRichard Lowe 			}
120110d63b7dSRichard Lowe 		}
120210d63b7dSRichard Lowe 	}
120310d63b7dSRichard Lowe 	if ((true_target->is_member) && (dependency_changed == true)) {
120410d63b7dSRichard Lowe 		true_target->stat.time = file_no_time;
120510d63b7dSRichard Lowe 	}
120610d63b7dSRichard Lowe 	/*
120710d63b7dSRichard Lowe 	 * After scanning all the dependencies, we check the rule
120810d63b7dSRichard Lowe 	 * if we found one.
120910d63b7dSRichard Lowe 	 */
121010d63b7dSRichard Lowe 	if (line->body.line.command_template != NULL) {
121110d63b7dSRichard Lowe 		if (line->body.line.command_template_redefined) {
121210d63b7dSRichard Lowe 			warning(gettext("Too many rules defined for target %s"),
121310d63b7dSRichard Lowe 				target->string_mb);
121410d63b7dSRichard Lowe 		}
121510d63b7dSRichard Lowe 		*command = line;
121610d63b7dSRichard Lowe 		/* Check if the target is out of date */
121710d63b7dSRichard Lowe 		Boolean out_of_date;
121810d63b7dSRichard Lowe 		if (true_target->is_member) {
121910d63b7dSRichard Lowe 			out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
122010d63b7dSRichard Lowe 				                                line->body.line.dependency_time);
122110d63b7dSRichard Lowe 		} else {
122210d63b7dSRichard Lowe 			out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
122310d63b7dSRichard Lowe 				                            line->body.line.dependency_time);
122410d63b7dSRichard Lowe 		}
122510d63b7dSRichard Lowe 		if (build_unconditional || out_of_date){
122610d63b7dSRichard Lowe 			if(!recheck_conditionals) {
122710d63b7dSRichard Lowe 				line->body.line.is_out_of_date = true;
122810d63b7dSRichard Lowe 			}
122910d63b7dSRichard Lowe 		}
123010d63b7dSRichard Lowe 		line->body.line.sccs_command = false;
123110d63b7dSRichard Lowe 		line->body.line.target = true_target;
123210d63b7dSRichard Lowe 		if(gnu_style) {
123310d63b7dSRichard Lowe 
123410d63b7dSRichard Lowe 			// set $< for explicit rule
123510d63b7dSRichard Lowe 			if(line->body.line.dependencies != NULL) {
123610d63b7dSRichard Lowe 				less = line->body.line.dependencies->name;
123710d63b7dSRichard Lowe 			}
123810d63b7dSRichard Lowe 
123910d63b7dSRichard Lowe 			// set $* for explicit rule
124010d63b7dSRichard Lowe 			Name			target_body;
124110d63b7dSRichard Lowe 			Name			tt = true_target;
124210d63b7dSRichard Lowe 			Property		member;
1243*e7afc443SToomas Soome 			wchar_t	*target_end;
1244*e7afc443SToomas Soome 			Dependency	suffix;
1245*e7afc443SToomas Soome 			int		suffix_length;
124610d63b7dSRichard Lowe 			Wstring			targ_string;
124710d63b7dSRichard Lowe 			Wstring			suf_string;
124810d63b7dSRichard Lowe 
124910d63b7dSRichard Lowe 			if (true_target->is_member &&
125010d63b7dSRichard Lowe 			    ((member = get_prop(target->prop, member_prop)) !=
125110d63b7dSRichard Lowe 			     NULL)) {
125210d63b7dSRichard Lowe 				tt = member->body.member.member;
125310d63b7dSRichard Lowe 			}
125410d63b7dSRichard Lowe 			targ_string.init(tt);
125510d63b7dSRichard Lowe 			target_end = targ_string.get_string() + tt->hash.length;
125610d63b7dSRichard Lowe 			for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
125710d63b7dSRichard Lowe 				suffix_length = suffix->name->hash.length;
125810d63b7dSRichard Lowe 				suf_string.init(suffix->name);
125910d63b7dSRichard Lowe 				if (tt->hash.length < suffix_length) {
126010d63b7dSRichard Lowe 					continue;
126110d63b7dSRichard Lowe 				} else if (!IS_WEQUALN(suf_string.get_string(),
126210d63b7dSRichard Lowe 						(target_end - suffix_length),
126310d63b7dSRichard Lowe 						suffix_length)) {
126410d63b7dSRichard Lowe 					continue;
126510d63b7dSRichard Lowe 				}
126610d63b7dSRichard Lowe 				target_body = GETNAME(
126710d63b7dSRichard Lowe 					targ_string.get_string(),
126810d63b7dSRichard Lowe 					(int)(tt->hash.length - suffix_length)
126910d63b7dSRichard Lowe 				);
127010d63b7dSRichard Lowe 				line->body.line.star = target_body;
127110d63b7dSRichard Lowe 			}
127210d63b7dSRichard Lowe 
127310d63b7dSRichard Lowe 			// set result = build_ok so that implicit rules are not used.
127410d63b7dSRichard Lowe 			if(*result == build_dont_know) {
127510d63b7dSRichard Lowe 				*result = build_ok;
127610d63b7dSRichard Lowe 			}
127710d63b7dSRichard Lowe 		}
127810d63b7dSRichard Lowe 		if (less != NULL) {
127910d63b7dSRichard Lowe 			line->body.line.less = less;
128010d63b7dSRichard Lowe 		}
128110d63b7dSRichard Lowe 	}
128210d63b7dSRichard Lowe 
128310d63b7dSRichard Lowe 	return false;
128410d63b7dSRichard Lowe }
128510d63b7dSRichard Lowe 
128610d63b7dSRichard Lowe /*
128710d63b7dSRichard Lowe  *	dynamic_dependencies(target)
128810d63b7dSRichard Lowe  *
128910d63b7dSRichard Lowe  *	Checks if any dependency contains a macro ref
129010d63b7dSRichard Lowe  *	If so, it replaces the dependency with the expanded version.
129110d63b7dSRichard Lowe  *	Here, "$@" gets translated to target->string. That is
129210d63b7dSRichard Lowe  *	the current name on the left of the colon in the
129310d63b7dSRichard Lowe  *	makefile.  Thus,
129410d63b7dSRichard Lowe  *		xyz:	s.$@.c
129510d63b7dSRichard Lowe  *	translates into
129610d63b7dSRichard Lowe  *		xyz:	s.xyz.c
129710d63b7dSRichard Lowe  *
129810d63b7dSRichard Lowe  *	Also, "$(@F)" translates to the same thing without a preceeding
129910d63b7dSRichard Lowe  *	directory path (if one exists).
130010d63b7dSRichard Lowe  *	Note, to enter "$@" on a dependency line in a makefile
130110d63b7dSRichard Lowe  *	"$$@" must be typed. This is because make expands
130210d63b7dSRichard Lowe  *	macros in dependency lists upon reading them.
130310d63b7dSRichard Lowe  *	dynamic_dependencies() also expands file wildcards.
130410d63b7dSRichard Lowe  *	If there are any Shell meta characters in the name,
130510d63b7dSRichard Lowe  *	search the directory, and replace the dependency
130610d63b7dSRichard Lowe  *	with the set of files the pattern matches
130710d63b7dSRichard Lowe  *
130810d63b7dSRichard Lowe  *	Parameters:
130910d63b7dSRichard Lowe  *		target		Target to sanitize dependencies for
131010d63b7dSRichard Lowe  *
131110d63b7dSRichard Lowe  *	Global variables used:
131210d63b7dSRichard Lowe  *		c_at		The Name "@", used to set macro value
131310d63b7dSRichard Lowe  *		debug_level	Should we trace actions?
131410d63b7dSRichard Lowe  *		dot		The Name ".", used to read directory
131510d63b7dSRichard Lowe  *		recursion_level	Used for tracing
131610d63b7dSRichard Lowe  */
131710d63b7dSRichard Lowe void
dynamic_dependencies(Name target)131810d63b7dSRichard Lowe dynamic_dependencies(Name target)
131910d63b7dSRichard Lowe {
132010d63b7dSRichard Lowe 	wchar_t			pattern[MAXPATHLEN];
1321*e7afc443SToomas Soome 	wchar_t	*p;
132210d63b7dSRichard Lowe 	Property		line;
1323*e7afc443SToomas Soome 	Dependency	dependency;
1324*e7afc443SToomas Soome 	Dependency	*remove;
132510d63b7dSRichard Lowe 	String_rec		string;
132610d63b7dSRichard Lowe 	wchar_t			buffer[MAXPATHLEN];
1327*e7afc443SToomas Soome 	Boolean	set_at = false;
1328*e7afc443SToomas Soome 	wchar_t	*start;
132910d63b7dSRichard Lowe 	Dependency		new_depe;
1330*e7afc443SToomas Soome 	Boolean	reuse_cell;
133110d63b7dSRichard Lowe 	Dependency		first_member;
133210d63b7dSRichard Lowe 	Name			directory;
133310d63b7dSRichard Lowe 	Name			lib;
133410d63b7dSRichard Lowe 	Name			member;
133510d63b7dSRichard Lowe 	Property		prop;
133610d63b7dSRichard Lowe 	Name			true_target = target;
133710d63b7dSRichard Lowe 	wchar_t			*library;
133810d63b7dSRichard Lowe 
133910d63b7dSRichard Lowe 	if ((line = get_prop(target->prop, line_prop)) == NULL) {
134010d63b7dSRichard Lowe 		return;
134110d63b7dSRichard Lowe 	}
134210d63b7dSRichard Lowe 	/* If the target is constructed from a "::" target we consider that */
134310d63b7dSRichard Lowe 	if (target->has_target_prop) {
134410d63b7dSRichard Lowe 		true_target = get_prop(target->prop,
134510d63b7dSRichard Lowe 				       target_prop)->body.target.target;
134610d63b7dSRichard Lowe 	}
134710d63b7dSRichard Lowe 	/* Scan all dependencies and process the ones that contain "$" chars */
134810d63b7dSRichard Lowe 	for (dependency = line->body.line.dependencies;
134910d63b7dSRichard Lowe 	     dependency != NULL;
135010d63b7dSRichard Lowe 	     dependency = dependency->next) {
135110d63b7dSRichard Lowe 		if (!dependency->name->dollar) {
135210d63b7dSRichard Lowe 			continue;
135310d63b7dSRichard Lowe 		}
135410d63b7dSRichard Lowe 		target->has_depe_list_expanded = true;
135510d63b7dSRichard Lowe 
135610d63b7dSRichard Lowe 		/* The make macro $@ is bound to the target name once per */
135710d63b7dSRichard Lowe 		/* invocation of dynamic_dependencies() */
135810d63b7dSRichard Lowe 		if (!set_at) {
135910d63b7dSRichard Lowe 			(void) SETVAR(c_at, true_target, false);
136010d63b7dSRichard Lowe 			set_at = true;
136110d63b7dSRichard Lowe 		}
136210d63b7dSRichard Lowe 		/* Expand this dependency string */
136310d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(string, buffer);
136410d63b7dSRichard Lowe 		expand_value(dependency->name, &string, false);
136510d63b7dSRichard Lowe 		/* Scan the expanded string. It could contain whitespace */
136610d63b7dSRichard Lowe 		/* which mean it expands to several dependencies */
136710d63b7dSRichard Lowe 		start = string.buffer.start;
136810d63b7dSRichard Lowe 		while (iswspace(*start)) {
136910d63b7dSRichard Lowe 			start++;
137010d63b7dSRichard Lowe 		}
137110d63b7dSRichard Lowe 		/* Remove the cell (later) if the macro was empty */
137210d63b7dSRichard Lowe 		if (start[0] == (int) nul_char) {
137310d63b7dSRichard Lowe 			dependency->name = NULL;
137410d63b7dSRichard Lowe 		}
137510d63b7dSRichard Lowe 
137610d63b7dSRichard Lowe /* azv 10/26/95 to fix bug BID_1170218 */
137710d63b7dSRichard Lowe 		if ((start[0] == (int) period_char) &&
137810d63b7dSRichard Lowe 		    (start[1] == (int) slash_char)) {
137910d63b7dSRichard Lowe 			start += 2;
138010d63b7dSRichard Lowe 		}
138110d63b7dSRichard Lowe /* azv */
138210d63b7dSRichard Lowe 
138310d63b7dSRichard Lowe 		first_member = NULL;
138410d63b7dSRichard Lowe 		/* We use the original dependency cell for the first */
138510d63b7dSRichard Lowe 		/* dependency from the expansion */
138610d63b7dSRichard Lowe 		reuse_cell = true;
138710d63b7dSRichard Lowe 		/* We also have to deal with dependencies that expand to */
138810d63b7dSRichard Lowe 		/* lib.a(members) notation */
138910d63b7dSRichard Lowe 		for (p = start; *p != (int) nul_char; p++) {
139010d63b7dSRichard Lowe 			if ((*p == (int) parenleft_char)) {
139110d63b7dSRichard Lowe 				lib = GETNAME(start, p - start);
139210d63b7dSRichard Lowe 				lib->is_member = true;
139310d63b7dSRichard Lowe 				first_member = dependency;
139410d63b7dSRichard Lowe 				start = p + 1;
139510d63b7dSRichard Lowe 				while (iswspace(*start)) {
139610d63b7dSRichard Lowe 					start++;
139710d63b7dSRichard Lowe 				}
139810d63b7dSRichard Lowe 				break;
139910d63b7dSRichard Lowe 			}
140010d63b7dSRichard Lowe 		}
140110d63b7dSRichard Lowe 		do {
140210d63b7dSRichard Lowe 		    /* First skip whitespace */
140310d63b7dSRichard Lowe 			for (p = start; *p != (int) nul_char; p++) {
140410d63b7dSRichard Lowe 				if ((*p == (int) nul_char) ||
140510d63b7dSRichard Lowe 				    iswspace(*p) ||
140610d63b7dSRichard Lowe 				    (*p == (int) parenright_char)) {
140710d63b7dSRichard Lowe 					break;
140810d63b7dSRichard Lowe 				}
140910d63b7dSRichard Lowe 			}
141010d63b7dSRichard Lowe 			/* Enter dependency from expansion */
141110d63b7dSRichard Lowe 			if (p != start) {
141210d63b7dSRichard Lowe 				/* Create new dependency cell if */
141310d63b7dSRichard Lowe 				/* this is not the first dependency */
141410d63b7dSRichard Lowe 				/* picked from the expansion */
141510d63b7dSRichard Lowe 				if (!reuse_cell) {
141610d63b7dSRichard Lowe 					new_depe = ALLOC(Dependency);
141710d63b7dSRichard Lowe 					new_depe->next = dependency->next;
141810d63b7dSRichard Lowe 					new_depe->automatic = false;
141910d63b7dSRichard Lowe 					new_depe->stale = false;
142010d63b7dSRichard Lowe 					new_depe->built = false;
142110d63b7dSRichard Lowe 					dependency->next = new_depe;
142210d63b7dSRichard Lowe 					dependency = new_depe;
142310d63b7dSRichard Lowe 				}
142410d63b7dSRichard Lowe 				reuse_cell = false;
142510d63b7dSRichard Lowe 				/* Internalize the dependency name */
142610d63b7dSRichard Lowe 				// tolik. Fix for bug 4110429: inconsistent expansion for macros that
142710d63b7dSRichard Lowe 				// include "//" and "/./"
142810d63b7dSRichard Lowe 				//dependency->name = GETNAME(start, p - start);
142910d63b7dSRichard Lowe 				dependency->name = normalize_name(start, p - start);
143010d63b7dSRichard Lowe 				if ((debug_level > 0) &&
143110d63b7dSRichard Lowe 				    (first_member == NULL)) {
143210d63b7dSRichard Lowe 					(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
143310d63b7dSRichard Lowe 						      recursion_level,
143410d63b7dSRichard Lowe 						      "",
143510d63b7dSRichard Lowe 						      dependency->name->string_mb,
143610d63b7dSRichard Lowe 						      true_target->string_mb);
143710d63b7dSRichard Lowe 				}
143810d63b7dSRichard Lowe 				for (start = p; iswspace(*start); start++);
143910d63b7dSRichard Lowe 				p = start;
144010d63b7dSRichard Lowe 			}
144110d63b7dSRichard Lowe 		} while ((*p != (int) nul_char) &&
144210d63b7dSRichard Lowe 			 (*p != (int) parenright_char));
144310d63b7dSRichard Lowe 		/* If the expansion was of lib.a(members) format we now */
144410d63b7dSRichard Lowe 		/* enter the proper member cells */
144510d63b7dSRichard Lowe 		if (first_member != NULL) {
144610d63b7dSRichard Lowe 			/* Scan the new dependencies and transform them from */
144710d63b7dSRichard Lowe 			/* "foo" to "lib.a(foo)" */
144810d63b7dSRichard Lowe 			for (; 1; first_member = first_member->next) {
144910d63b7dSRichard Lowe 				/* Build "lib.a(foo)" name */
145010d63b7dSRichard Lowe 				INIT_STRING_FROM_STACK(string, buffer);
145110d63b7dSRichard Lowe 				APPEND_NAME(lib,
145210d63b7dSRichard Lowe 					      &string,
145310d63b7dSRichard Lowe 					      (int) lib->hash.length);
145410d63b7dSRichard Lowe 				append_char((int) parenleft_char, &string);
145510d63b7dSRichard Lowe 				APPEND_NAME(first_member->name,
145610d63b7dSRichard Lowe 					      &string,
145710d63b7dSRichard Lowe 					      FIND_LENGTH);
145810d63b7dSRichard Lowe 				append_char((int) parenright_char, &string);
145910d63b7dSRichard Lowe 				member = first_member->name;
146010d63b7dSRichard Lowe 				/* Replace "foo" with "lib.a(foo)" */
146110d63b7dSRichard Lowe 				first_member->name =
146210d63b7dSRichard Lowe 				  GETNAME(string.buffer.start, FIND_LENGTH);
146310d63b7dSRichard Lowe 				if (string.free_after_use) {
146410d63b7dSRichard Lowe 					retmem(string.buffer.start);
146510d63b7dSRichard Lowe 				}
146610d63b7dSRichard Lowe 				if (debug_level > 0) {
146710d63b7dSRichard Lowe 					(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
146810d63b7dSRichard Lowe 						      recursion_level,
146910d63b7dSRichard Lowe 						      "",
147010d63b7dSRichard Lowe 						      first_member->name->
147110d63b7dSRichard Lowe 						      string_mb,
147210d63b7dSRichard Lowe 						      true_target->string_mb);
147310d63b7dSRichard Lowe 				}
147410d63b7dSRichard Lowe 				first_member->name->is_member = lib->is_member;
147510d63b7dSRichard Lowe 				/* Add member property to member */
147610d63b7dSRichard Lowe 				prop = maybe_append_prop(first_member->name,
147710d63b7dSRichard Lowe 							 member_prop);
147810d63b7dSRichard Lowe 				prop->body.member.library = lib;
147910d63b7dSRichard Lowe 				prop->body.member.entry = NULL;
148010d63b7dSRichard Lowe 				prop->body.member.member = member;
148110d63b7dSRichard Lowe 				if (first_member == dependency) {
148210d63b7dSRichard Lowe 					break;
148310d63b7dSRichard Lowe 				}
148410d63b7dSRichard Lowe 			}
148510d63b7dSRichard Lowe 		}
148610d63b7dSRichard Lowe 	}
148710d63b7dSRichard Lowe 	Wstring wcb;
148810d63b7dSRichard Lowe 	/* Then scan all the dependencies again. This time we want to expand */
148910d63b7dSRichard Lowe 	/* shell file wildcards */
149010d63b7dSRichard Lowe 	for (remove = &line->body.line.dependencies, dependency = *remove;
149110d63b7dSRichard Lowe 	     dependency != NULL;
149210d63b7dSRichard Lowe 	     dependency = *remove) {
149310d63b7dSRichard Lowe 		if (dependency->name == NULL) {
149410d63b7dSRichard Lowe 			dependency = *remove = (*remove)->next;
149510d63b7dSRichard Lowe 			continue;
149610d63b7dSRichard Lowe 		}
149710d63b7dSRichard Lowe 		/* If dependency name string contains shell wildcards */
149810d63b7dSRichard Lowe 		/* replace the name with the expansion */
149910d63b7dSRichard Lowe 		if (dependency->name->wildcard) {
150010d63b7dSRichard Lowe 			wcb.init(dependency->name);
150110d63b7dSRichard Lowe 			if ((start = (wchar_t *) wcschr(wcb.get_string(),
150210d63b7dSRichard Lowe 					   (int) parenleft_char)) != NULL) {
150310d63b7dSRichard Lowe 				/* lib(*) type pattern */
150410d63b7dSRichard Lowe 				library = buffer;
150510d63b7dSRichard Lowe 				(void) wcsncpy(buffer,
150610d63b7dSRichard Lowe 					      wcb.get_string(),
150710d63b7dSRichard Lowe 					      start - wcb.get_string());
150810d63b7dSRichard Lowe 				buffer[start-wcb.get_string()] =
150910d63b7dSRichard Lowe 				  (int) nul_char;
151010d63b7dSRichard Lowe 				(void) wcsncpy(pattern,
151110d63b7dSRichard Lowe 					      start + 1,
151210d63b7dSRichard Lowe (int) (dependency->name->hash.length-(start-wcb.get_string())-2));
151310d63b7dSRichard Lowe 				pattern[dependency->name->hash.length -
151410d63b7dSRichard Lowe 					(start-wcb.get_string()) - 2] =
151510d63b7dSRichard Lowe 					  (int) nul_char;
151610d63b7dSRichard Lowe 			} else {
151710d63b7dSRichard Lowe 				library = NULL;
151810d63b7dSRichard Lowe 				(void) wcsncpy(pattern,
151910d63b7dSRichard Lowe 					      wcb.get_string(),
152010d63b7dSRichard Lowe 					      (int) dependency->name->hash.length);
152110d63b7dSRichard Lowe 				pattern[dependency->name->hash.length] =
152210d63b7dSRichard Lowe 				  (int) nul_char;
152310d63b7dSRichard Lowe 			}
152410d63b7dSRichard Lowe 			start = (wchar_t *) wcsrchr(pattern, (int) slash_char);
152510d63b7dSRichard Lowe 			if (start == NULL) {
152610d63b7dSRichard Lowe 				directory = dot;
152710d63b7dSRichard Lowe 				p = pattern;
152810d63b7dSRichard Lowe 			} else {
152910d63b7dSRichard Lowe 				directory = GETNAME(pattern, start-pattern);
153010d63b7dSRichard Lowe 				p = start+1;
153110d63b7dSRichard Lowe 			}
153210d63b7dSRichard Lowe 			/* The expansion is handled by the read_dir() routine*/
153310d63b7dSRichard Lowe 			if (read_dir(directory, p, line, library)) {
153410d63b7dSRichard Lowe 				*remove = (*remove)->next;
153510d63b7dSRichard Lowe 			} else {
153610d63b7dSRichard Lowe 				remove = &dependency->next;
153710d63b7dSRichard Lowe 			}
153810d63b7dSRichard Lowe 		} else {
153910d63b7dSRichard Lowe 			remove = &dependency->next;
154010d63b7dSRichard Lowe 		}
154110d63b7dSRichard Lowe         }
154210d63b7dSRichard Lowe 
154310d63b7dSRichard Lowe 	/* Then unbind $@ */
154410d63b7dSRichard Lowe 	(void) SETVAR(c_at, (Name) NULL, false);
154510d63b7dSRichard Lowe }
154610d63b7dSRichard Lowe 
154710d63b7dSRichard Lowe /*
154810d63b7dSRichard Lowe  * DONE.
154910d63b7dSRichard Lowe  *
155010d63b7dSRichard Lowe  *	run_command(line)
155110d63b7dSRichard Lowe  *
155210d63b7dSRichard Lowe  *	Takes one Cmd_line and runs the commands from it.
155310d63b7dSRichard Lowe  *
155410d63b7dSRichard Lowe  *	Return value:
155510d63b7dSRichard Lowe  *				Indicates if the command failed or not
155610d63b7dSRichard Lowe  *
155710d63b7dSRichard Lowe  *	Parameters:
155810d63b7dSRichard Lowe  *		line		The command line to run
155910d63b7dSRichard Lowe  *
156010d63b7dSRichard Lowe  *	Global variables used:
156110d63b7dSRichard Lowe  *		commands_done	Set if we do run command
156210d63b7dSRichard Lowe  *		current_line	Set to the line we run a command from
156310d63b7dSRichard Lowe  *		current_target	Set to the target we run a command for
156410d63b7dSRichard Lowe  *		file_number	Used to form temp file name
156510d63b7dSRichard Lowe  *		keep_state	Indicates that .KEEP_STATE is on
156610d63b7dSRichard Lowe  *		make_state	The Name ".make.state", used to check timestamp
156710d63b7dSRichard Lowe  *		parallel	True if currently building in parallel
156810d63b7dSRichard Lowe  *		parallel_process_cnt Count of parallel processes running
156910d63b7dSRichard Lowe  *		quest		Indicates that make -q is on
157010d63b7dSRichard Lowe  *		rewrite_statefile Set if we do run a command
157110d63b7dSRichard Lowe  *		sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
157210d63b7dSRichard Lowe  *		temp_file_directory Used to form temp fie name
157310d63b7dSRichard Lowe  *		temp_file_name	Set to the name of the temp file
157410d63b7dSRichard Lowe  *		touch		Indicates that make -t is on
157510d63b7dSRichard Lowe  */
157610d63b7dSRichard Lowe static Doname
run_command(Property line,Boolean)1577*e7afc443SToomas Soome run_command(Property line, Boolean)
157810d63b7dSRichard Lowe {
1579*e7afc443SToomas Soome 	Doname		result = build_ok;
1580*e7afc443SToomas Soome 	Boolean	remember_only = false;
1581*e7afc443SToomas Soome 	Name		target = line->body.line.target;
158210d63b7dSRichard Lowe 	wchar_t			*string;
158310d63b7dSRichard Lowe 	char			tmp_file_path[MAXPATHLEN];
158410d63b7dSRichard Lowe 
158510d63b7dSRichard Lowe 	if (!line->body.line.is_out_of_date && target->rechecking_target) {
158610d63b7dSRichard Lowe 		target->rechecking_target = false;
158710d63b7dSRichard Lowe 		return build_ok;
158810d63b7dSRichard Lowe 	}
158910d63b7dSRichard Lowe 
159010d63b7dSRichard Lowe 	/*
159110d63b7dSRichard Lowe 	 * Build the command if we know the target is out of date,
159210d63b7dSRichard Lowe 	 * or if we want to check cmd consistency.
159310d63b7dSRichard Lowe 	 */
159410d63b7dSRichard Lowe 	if (line->body.line.is_out_of_date || keep_state) {
159510d63b7dSRichard Lowe 		/* Hack for handling conditional macros in DMake. */
159610d63b7dSRichard Lowe 		if (!line->body.line.dont_rebuild_command_used) {
159710d63b7dSRichard Lowe 			build_command_strings(target, line);
159810d63b7dSRichard Lowe 		}
159910d63b7dSRichard Lowe 	}
160010d63b7dSRichard Lowe 	/* Never mind */
160110d63b7dSRichard Lowe 	if (!line->body.line.is_out_of_date) {
160210d63b7dSRichard Lowe 		return build_ok;
160310d63b7dSRichard Lowe 	}
160410d63b7dSRichard Lowe 	/* If quest, then exit(1) because the target is out of date */
160510d63b7dSRichard Lowe 	if (quest) {
160610d63b7dSRichard Lowe 		if (posix) {
160710d63b7dSRichard Lowe 			result = execute_parallel(line, true);
160810d63b7dSRichard Lowe 		}
160910d63b7dSRichard Lowe 		exit_status = 1;
161010d63b7dSRichard Lowe 		exit(1);
161110d63b7dSRichard Lowe 	}
161210d63b7dSRichard Lowe 	/* We actually had to do something this time */
161310d63b7dSRichard Lowe 	rewrite_statefile = commands_done = true;
161410d63b7dSRichard Lowe 	/*
161510d63b7dSRichard Lowe 	 * If this is an sccs command, we have to do some extra checking
161610d63b7dSRichard Lowe 	 * and possibly complain. If the file can't be gotten because it's
161710d63b7dSRichard Lowe 	 * checked out, we complain and behave as if the command was
161810d63b7dSRichard Lowe 	 * executed eventhough we ignored the command.
161910d63b7dSRichard Lowe 	 */
162010d63b7dSRichard Lowe 	if (!touch &&
162110d63b7dSRichard Lowe 	    line->body.line.sccs_command &&
162210d63b7dSRichard Lowe 	    (target->stat.time != file_doesnt_exist) &&
162310d63b7dSRichard Lowe 	    ((target->stat.mode & 0222) != 0)) {
162410d63b7dSRichard Lowe 		fatal(gettext("%s is writable so it cannot be sccs gotten"),
162510d63b7dSRichard Lowe 		      target->string_mb);
162610d63b7dSRichard Lowe 		target->has_complained = remember_only = true;
162710d63b7dSRichard Lowe 	}
162810d63b7dSRichard Lowe 	/*
162910d63b7dSRichard Lowe 	 * If KEEP_STATE is on, we make sure we have the timestamp for
163010d63b7dSRichard Lowe 	 * .make.state. If .make.state changes during the command run,
163110d63b7dSRichard Lowe 	 * we reread .make.state after the command. We also setup the
163210d63b7dSRichard Lowe 	 * environment variable that asks utilities to report dependencies.
163310d63b7dSRichard Lowe 	 */
163410d63b7dSRichard Lowe 	if (!touch &&
163510d63b7dSRichard Lowe 	    keep_state &&
163610d63b7dSRichard Lowe 	    !remember_only) {
163710d63b7dSRichard Lowe 		(void) exists(make_state);
163848bbca81SDaniel Hoffman 		if((strlen(temp_file_directory) == 1) &&
163910d63b7dSRichard Lowe 			(temp_file_directory[0] == '/')) {
164010d63b7dSRichard Lowe 		   tmp_file_path[0] = '\0';
164110d63b7dSRichard Lowe 		} else {
164210d63b7dSRichard Lowe 		   strcpy(tmp_file_path, temp_file_directory);
164310d63b7dSRichard Lowe 		}
164410d63b7dSRichard Lowe 		sprintf(mbs_buffer,
164510d63b7dSRichard Lowe 				"%s/.make.dependency.%08x.%d.%d",
164610d63b7dSRichard Lowe 			        tmp_file_path,
164710d63b7dSRichard Lowe 			        hostid,
164810d63b7dSRichard Lowe 			        getpid(),
164910d63b7dSRichard Lowe 			        file_number++);
165010d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, mbs_buffer);
165110d63b7dSRichard Lowe 		Boolean fnd;
165210d63b7dSRichard Lowe 		temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
165310d63b7dSRichard Lowe 		temp_file_name->stat.is_file = true;
165410d63b7dSRichard Lowe 		int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
165510d63b7dSRichard Lowe 		wchar_t *to = string = ALLOC_WC(len);
165610d63b7dSRichard Lowe 		for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
165710d63b7dSRichard Lowe 			if (*from == (int) space_char) {
165810d63b7dSRichard Lowe 				*to++ = (int) backslash_char;
165910d63b7dSRichard Lowe 			}
166010d63b7dSRichard Lowe 			*to++ = *from++;
166110d63b7dSRichard Lowe 		}
166210d63b7dSRichard Lowe 		*to++ = (int) space_char;
166310d63b7dSRichard Lowe 		MBSTOWCS(to, target->string_mb);
166410d63b7dSRichard Lowe 		Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
166510d63b7dSRichard Lowe 		(void) SETVAR(sunpro_dependencies,
166610d63b7dSRichard Lowe 			      sprodep_name,
166710d63b7dSRichard Lowe 			      false);
166810d63b7dSRichard Lowe 		retmem(string);
166910d63b7dSRichard Lowe 	} else {
167010d63b7dSRichard Lowe 		temp_file_name = NULL;
167110d63b7dSRichard Lowe 	}
167210d63b7dSRichard Lowe 
167310d63b7dSRichard Lowe 	/*
167410d63b7dSRichard Lowe 	 * In case we are interrupted, we need to know what was going on.
167510d63b7dSRichard Lowe 	 */
167610d63b7dSRichard Lowe 	current_target = target;
167710d63b7dSRichard Lowe 	/*
167810d63b7dSRichard Lowe 	 * We also need to be able to save an empty command instead of the
167910d63b7dSRichard Lowe 	 * interrupted one in .make.state.
168010d63b7dSRichard Lowe 	 */
168110d63b7dSRichard Lowe 	current_line = line;
168210d63b7dSRichard Lowe 	if (remember_only) {
168310d63b7dSRichard Lowe 		/* Empty block!!! */
168410d63b7dSRichard Lowe 	} else if (touch) {
168510d63b7dSRichard Lowe 		result = touch_command(line, target, result);
168610d63b7dSRichard Lowe 		if (posix) {
168710d63b7dSRichard Lowe 			result = execute_parallel(line, true);
168810d63b7dSRichard Lowe 		}
168910d63b7dSRichard Lowe 	} else {
169010d63b7dSRichard Lowe 		/*
169110d63b7dSRichard Lowe 		 * If this is not a touch run, we need to execute the
169210d63b7dSRichard Lowe 		 * proper command(s) for the target.
169310d63b7dSRichard Lowe 		 */
169410d63b7dSRichard Lowe 		if (parallel) {
169510d63b7dSRichard Lowe 			if (!parallel_ok(target, true)) {
169610d63b7dSRichard Lowe 				/*
169710d63b7dSRichard Lowe 				 * We are building in parallel, but
169810d63b7dSRichard Lowe 				 * this target must be built in serial.
169910d63b7dSRichard Lowe 				 */
170010d63b7dSRichard Lowe 				/*
170110d63b7dSRichard Lowe 				 * If nothing else is building,
170210d63b7dSRichard Lowe 				 * do this one, else wait.
170310d63b7dSRichard Lowe 				 */
170410d63b7dSRichard Lowe 				if (parallel_process_cnt == 0) {
170510d63b7dSRichard Lowe 					result = execute_parallel(line, true, target->localhost);
170610d63b7dSRichard Lowe 				} else {
170710d63b7dSRichard Lowe 					current_target = NULL;
170810d63b7dSRichard Lowe 					current_line = NULL;
170910d63b7dSRichard Lowe /*
171010d63b7dSRichard Lowe 					line->body.line.command_used = NULL;
171110d63b7dSRichard Lowe  */
171210d63b7dSRichard Lowe 					line->body.line.dont_rebuild_command_used = true;
171310d63b7dSRichard Lowe 					return build_serial;
171410d63b7dSRichard Lowe 				}
171510d63b7dSRichard Lowe 			} else {
171610d63b7dSRichard Lowe 				result = execute_parallel(line, false);
171710d63b7dSRichard Lowe 				switch (result) {
171810d63b7dSRichard Lowe 				case build_running:
171910d63b7dSRichard Lowe 					return build_running;
172010d63b7dSRichard Lowe 				case build_serial:
172110d63b7dSRichard Lowe 					if (parallel_process_cnt == 0) {
172210d63b7dSRichard Lowe 						result = execute_parallel(line, true, target->localhost);
172310d63b7dSRichard Lowe 					} else {
172410d63b7dSRichard Lowe 						current_target = NULL;
172510d63b7dSRichard Lowe 						current_line = NULL;
172610d63b7dSRichard Lowe 						target->parallel = false;
172710d63b7dSRichard Lowe 						line->body.line.command_used =
17282e8f3c34SToomas Soome 						    NULL;
172910d63b7dSRichard Lowe 						return build_serial;
173010d63b7dSRichard Lowe 					}
173110d63b7dSRichard Lowe 				}
173210d63b7dSRichard Lowe 			}
173310d63b7dSRichard Lowe 		} else {
173410d63b7dSRichard Lowe 			result = execute_parallel(line, true, target->localhost);
173510d63b7dSRichard Lowe 		}
173610d63b7dSRichard Lowe 	}
173710d63b7dSRichard Lowe 	temp_file_name = NULL;
173810d63b7dSRichard Lowe 	if (report_dependencies_level == 0){
173910d63b7dSRichard Lowe 		update_target(line, result);
174010d63b7dSRichard Lowe 	}
174110d63b7dSRichard Lowe 	current_target = NULL;
174210d63b7dSRichard Lowe 	current_line = NULL;
174310d63b7dSRichard Lowe 	return result;
174410d63b7dSRichard Lowe }
174510d63b7dSRichard Lowe 
174610d63b7dSRichard Lowe /*
174710d63b7dSRichard Lowe  *	execute_serial(line)
174810d63b7dSRichard Lowe  *
174910d63b7dSRichard Lowe  *	Runs thru the command line for the target and
175010d63b7dSRichard Lowe  *	executes the rules one by one.
175110d63b7dSRichard Lowe  *
175210d63b7dSRichard Lowe  *	Return value:
175310d63b7dSRichard Lowe  *				The result of the command build
175410d63b7dSRichard Lowe  *
175548bbca81SDaniel Hoffman  *	Parameters:
175610d63b7dSRichard Lowe  *		line		The command to execute
175710d63b7dSRichard Lowe  *
175810d63b7dSRichard Lowe  *	Static variables used:
175910d63b7dSRichard Lowe  *
176010d63b7dSRichard Lowe  *	Global variables used:
176110d63b7dSRichard Lowe  *		continue_after_error -k flag
176210d63b7dSRichard Lowe  *		do_not_exec_rule -n flag
176310d63b7dSRichard Lowe  *		report_dependencies -P flag
176410d63b7dSRichard Lowe  *		silent		Don't echo commands before executing
176510d63b7dSRichard Lowe  *		temp_file_name	Temp file for auto dependencies
176610d63b7dSRichard Lowe  *		vpath_defined	If true, translate path for command
176710d63b7dSRichard Lowe  */
176810d63b7dSRichard Lowe Doname
execute_serial(Property line)176910d63b7dSRichard Lowe execute_serial(Property line)
177010d63b7dSRichard Lowe {
177110d63b7dSRichard Lowe 	int			child_pid = 0;
177210d63b7dSRichard Lowe 	Boolean			printed_serial;
177310d63b7dSRichard Lowe 	Doname			result = build_ok;
177410d63b7dSRichard Lowe 	Cmd_line		rule, cmd_tail, command = NULL;
177510d63b7dSRichard Lowe 	char			mbstring[MAXPATHLEN];
177610d63b7dSRichard Lowe 	int			filed;
177710d63b7dSRichard Lowe 	Name			target = line->body.line.target;
177810d63b7dSRichard Lowe 
177910d63b7dSRichard Lowe 	target->has_recursive_dependency = false;
178010d63b7dSRichard Lowe 	// We have to create a copy of the rules chain for processing because
178110d63b7dSRichard Lowe 	// the original one can be destroyed during .make.state file rereading.
178210d63b7dSRichard Lowe 	for (rule = line->body.line.command_used;
178310d63b7dSRichard Lowe 	     rule != NULL;
178410d63b7dSRichard Lowe 	     rule = rule->next) {
178510d63b7dSRichard Lowe 		if (command == NULL) {
178610d63b7dSRichard Lowe 			command = cmd_tail = ALLOC(Cmd_line);
178710d63b7dSRichard Lowe 		} else {
178810d63b7dSRichard Lowe 			cmd_tail->next = ALLOC(Cmd_line);
178910d63b7dSRichard Lowe 			cmd_tail = cmd_tail->next;
179010d63b7dSRichard Lowe 		}
179110d63b7dSRichard Lowe 		*cmd_tail = *rule;
179210d63b7dSRichard Lowe 	}
179310d63b7dSRichard Lowe 	if (command) {
179410d63b7dSRichard Lowe 		cmd_tail->next = NULL;
179510d63b7dSRichard Lowe 	}
179610d63b7dSRichard Lowe 	for (rule = command; rule != NULL; rule = rule->next) {
179710d63b7dSRichard Lowe 		if (posix && (touch || quest) && !rule->always_exec) {
179810d63b7dSRichard Lowe 			continue;
179910d63b7dSRichard Lowe 		}
180010d63b7dSRichard Lowe 		if (vpath_defined) {
180110d63b7dSRichard Lowe 			rule->command_line =
180210d63b7dSRichard Lowe 			  vpath_translation(rule->command_line);
180310d63b7dSRichard Lowe 		}
180410d63b7dSRichard Lowe 		/* Echo command line, maybe. */
180510d63b7dSRichard Lowe 		if ((rule->command_line->hash.length > 0) &&
180610d63b7dSRichard Lowe 		    !silent &&
180710d63b7dSRichard Lowe 		    (!rule->silent || do_not_exec_rule) &&
180810d63b7dSRichard Lowe 		    (report_dependencies_level == 0)) {
180910d63b7dSRichard Lowe 			(void) printf("%s\n", rule->command_line->string_mb);
181010d63b7dSRichard Lowe 		}
181110d63b7dSRichard Lowe 		if (rule->command_line->hash.length > 0) {
181210d63b7dSRichard Lowe 			/* Do assignment if command line prefixed with "=" */
181310d63b7dSRichard Lowe 			if (rule->assign) {
181410d63b7dSRichard Lowe 				result = build_ok;
181510d63b7dSRichard Lowe 				do_assign(rule->command_line, target);
181610d63b7dSRichard Lowe 			} else if (report_dependencies_level == 0) {
181710d63b7dSRichard Lowe 				/* Execute command line. */
181810d63b7dSRichard Lowe 				setvar_envvar();
181910d63b7dSRichard Lowe 				result = dosys(rule->command_line,
182010d63b7dSRichard Lowe 				               (Boolean) rule->ignore_error,
182110d63b7dSRichard Lowe 				               (Boolean) rule->make_refd,
182210d63b7dSRichard Lowe 				               /* ds 98.04.23 bug #4085164. make should always show error messages */
182310d63b7dSRichard Lowe 				               false,
182410d63b7dSRichard Lowe 				               /* BOOLEAN(rule->silent &&
182510d63b7dSRichard Lowe 				                       rule->ignore_error), */
182610d63b7dSRichard Lowe 				               (Boolean) rule->always_exec,
182710d63b7dSRichard Lowe 				               target);
182810d63b7dSRichard Lowe 				check_state(temp_file_name);
182910d63b7dSRichard Lowe 			}
183010d63b7dSRichard Lowe 		} else {
183110d63b7dSRichard Lowe 			result = build_ok;
183210d63b7dSRichard Lowe 		}
183310d63b7dSRichard Lowe 		if (result == build_failed) {
183410d63b7dSRichard Lowe 			if (silent || rule->silent) {
183510d63b7dSRichard Lowe 				(void) printf(gettext("The following command caused the error:\n%s\n"),
183610d63b7dSRichard Lowe 				              rule->command_line->string_mb);
183710d63b7dSRichard Lowe 			}
183810d63b7dSRichard Lowe 			if (!rule->ignore_error && !ignore_errors) {
183910d63b7dSRichard Lowe 				if (!continue_after_error) {
184010d63b7dSRichard Lowe 					fatal(gettext("Command failed for target `%s'"),
184110d63b7dSRichard Lowe 					      target->string_mb);
184210d63b7dSRichard Lowe 				}
184310d63b7dSRichard Lowe 				/*
184410d63b7dSRichard Lowe 				 * Make sure a failing command is not
184510d63b7dSRichard Lowe 				 * saved in .make.state.
184610d63b7dSRichard Lowe 				 */
184710d63b7dSRichard Lowe 				line->body.line.command_used = NULL;
184810d63b7dSRichard Lowe 				break;
184910d63b7dSRichard Lowe 			} else {
185010d63b7dSRichard Lowe 				result = build_ok;
185110d63b7dSRichard Lowe 			}
185210d63b7dSRichard Lowe 		}
185310d63b7dSRichard Lowe 	}
185410d63b7dSRichard Lowe 	for (rule = command; rule != NULL; rule = cmd_tail) {
185510d63b7dSRichard Lowe 		cmd_tail = rule->next;
185610d63b7dSRichard Lowe 		free(rule);
185710d63b7dSRichard Lowe 	}
185810d63b7dSRichard Lowe 	command = NULL;
185910d63b7dSRichard Lowe 	if (temp_file_name != NULL) {
186010d63b7dSRichard Lowe 		free_name(temp_file_name);
186110d63b7dSRichard Lowe 	}
186210d63b7dSRichard Lowe         temp_file_name = NULL;
186310d63b7dSRichard Lowe 
186410d63b7dSRichard Lowe 	Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
186510d63b7dSRichard Lowe 	if(spro != NULL) {
186610d63b7dSRichard Lowe 		Name val = spro->body.macro.value;
186710d63b7dSRichard Lowe 		if(val != NULL) {
186810d63b7dSRichard Lowe 			free_name(val);
186910d63b7dSRichard Lowe 			spro->body.macro.value = NULL;
187010d63b7dSRichard Lowe 		}
187110d63b7dSRichard Lowe 	}
187210d63b7dSRichard Lowe 	spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
187310d63b7dSRichard Lowe 	if(spro) {
187410d63b7dSRichard Lowe 		char *val = spro->body.env_mem.value;
187510d63b7dSRichard Lowe 		if(val != NULL) {
187648bbca81SDaniel Hoffman 			/*
187710d63b7dSRichard Lowe 			 * Do not return memory allocated for SUNPRO_DEPENDENCIES
187848bbca81SDaniel Hoffman 			 * It will be returned in setvar_daemon() in macro.cc
187910d63b7dSRichard Lowe 			 */
188010d63b7dSRichard Lowe 			//	retmem_mb(val);
188110d63b7dSRichard Lowe 			spro->body.env_mem.value = NULL;
188210d63b7dSRichard Lowe 		}
188310d63b7dSRichard Lowe 	}
188448bbca81SDaniel Hoffman 
188510d63b7dSRichard Lowe         return result;
188610d63b7dSRichard Lowe }
188710d63b7dSRichard Lowe 
188810d63b7dSRichard Lowe 
188910d63b7dSRichard Lowe 
189010d63b7dSRichard Lowe /*
189110d63b7dSRichard Lowe  *	vpath_translation(cmd)
189210d63b7dSRichard Lowe  *
189310d63b7dSRichard Lowe  *	Translates one command line by
189410d63b7dSRichard Lowe  *	checking each word. If the word has an alias it is translated.
189510d63b7dSRichard Lowe  *
189610d63b7dSRichard Lowe  *	Return value:
189710d63b7dSRichard Lowe  *				The translated command
189810d63b7dSRichard Lowe  *
189910d63b7dSRichard Lowe  *	Parameters:
190010d63b7dSRichard Lowe  *		cmd		Command to translate
190110d63b7dSRichard Lowe  *
190210d63b7dSRichard Lowe  *	Global variables used:
190310d63b7dSRichard Lowe  */
190410d63b7dSRichard Lowe Name
vpath_translation(Name cmd)1905*e7afc443SToomas Soome vpath_translation(Name cmd)
190610d63b7dSRichard Lowe {
190710d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
190810d63b7dSRichard Lowe 	String_rec		new_cmd;
190910d63b7dSRichard Lowe 	wchar_t			*p;
191010d63b7dSRichard Lowe 	wchar_t			*start;
191110d63b7dSRichard Lowe 
191210d63b7dSRichard Lowe 	if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
191310d63b7dSRichard Lowe 		return cmd;
191410d63b7dSRichard Lowe 	}
191510d63b7dSRichard Lowe 	INIT_STRING_FROM_STACK(new_cmd, buffer);
191610d63b7dSRichard Lowe 
191710d63b7dSRichard Lowe 	Wstring wcb(cmd);
191810d63b7dSRichard Lowe 	p = wcb.get_string();
191910d63b7dSRichard Lowe 
192010d63b7dSRichard Lowe 	while (*p != (int) nul_char) {
192110d63b7dSRichard Lowe 		while (iswspace(*p) && (*p != (int) nul_char)) {
192210d63b7dSRichard Lowe 			append_char(*p++, &new_cmd);
192310d63b7dSRichard Lowe 		}
192410d63b7dSRichard Lowe 		start = p;
192510d63b7dSRichard Lowe 		while (!iswspace(*p) && (*p != (int) nul_char)) {
192610d63b7dSRichard Lowe 			p++;
192710d63b7dSRichard Lowe 		}
192810d63b7dSRichard Lowe 		cmd = GETNAME(start, p - start);
192910d63b7dSRichard Lowe 		if (cmd->has_vpath_alias_prop) {
193010d63b7dSRichard Lowe 			cmd = get_prop(cmd->prop, vpath_alias_prop)->
193110d63b7dSRichard Lowe 						body.vpath_alias.alias;
193210d63b7dSRichard Lowe 			APPEND_NAME(cmd,
193310d63b7dSRichard Lowe 				      &new_cmd,
193410d63b7dSRichard Lowe 				      (int) cmd->hash.length);
193510d63b7dSRichard Lowe 		} else {
193610d63b7dSRichard Lowe 			append_string(start, &new_cmd, p - start);
193710d63b7dSRichard Lowe 		}
193810d63b7dSRichard Lowe 	}
193910d63b7dSRichard Lowe 	cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
194010d63b7dSRichard Lowe 	if (new_cmd.free_after_use) {
194110d63b7dSRichard Lowe 		retmem(new_cmd.buffer.start);
194210d63b7dSRichard Lowe 	}
194310d63b7dSRichard Lowe 	return cmd;
194410d63b7dSRichard Lowe }
194510d63b7dSRichard Lowe 
194610d63b7dSRichard Lowe /*
194710d63b7dSRichard Lowe  *	check_state(temp_file_name)
194810d63b7dSRichard Lowe  *
194910d63b7dSRichard Lowe  *	Reads and checks the state changed by the previously executed command.
195010d63b7dSRichard Lowe  *
195110d63b7dSRichard Lowe  *	Parameters:
195210d63b7dSRichard Lowe  *		temp_file_name	The auto dependency temp file
195310d63b7dSRichard Lowe  *
195410d63b7dSRichard Lowe  *	Global variables used:
195510d63b7dSRichard Lowe  */
195610d63b7dSRichard Lowe void
check_state(Name temp_file_name)195710d63b7dSRichard Lowe check_state(Name temp_file_name)
195810d63b7dSRichard Lowe {
195910d63b7dSRichard Lowe 	if (!keep_state) {
196010d63b7dSRichard Lowe 		return;
196110d63b7dSRichard Lowe 	}
196210d63b7dSRichard Lowe 
196310d63b7dSRichard Lowe 	/*
196448bbca81SDaniel Hoffman 	 * Then read the temp file that now might
196548bbca81SDaniel Hoffman 	 * contain dependency reports from utilities
196610d63b7dSRichard Lowe 	 */
196710d63b7dSRichard Lowe 	read_dependency_file(temp_file_name);
196810d63b7dSRichard Lowe 
196910d63b7dSRichard Lowe 	/*
197010d63b7dSRichard Lowe 	 * And reread .make.state if it
197148bbca81SDaniel Hoffman 	 * changed (the command ran recursive makes)
197210d63b7dSRichard Lowe 	 */
197310d63b7dSRichard Lowe 	check_read_state_file();
197410d63b7dSRichard Lowe 	if (temp_file_name != NULL) {
197510d63b7dSRichard Lowe 		(void) unlink(temp_file_name->string_mb);
197610d63b7dSRichard Lowe 	}
197710d63b7dSRichard Lowe }
197810d63b7dSRichard Lowe 
197910d63b7dSRichard Lowe /*
198010d63b7dSRichard Lowe  *	read_dependency_file(filename)
198110d63b7dSRichard Lowe  *
198210d63b7dSRichard Lowe  *	Read the temp file used for reporting dependencies to make
198310d63b7dSRichard Lowe  *
198410d63b7dSRichard Lowe  *	Parameters:
198510d63b7dSRichard Lowe  *		filename	The name of the file with the state info
198610d63b7dSRichard Lowe  *
198710d63b7dSRichard Lowe  *	Global variables used:
198810d63b7dSRichard Lowe  *		makefile_type	The type of makefile being read
198910d63b7dSRichard Lowe  *		read_trace_level Debug flag
199010d63b7dSRichard Lowe  *		temp_file_number The always increasing number for unique files
199110d63b7dSRichard Lowe  *		trace_reader	Debug flag
199210d63b7dSRichard Lowe  */
199310d63b7dSRichard Lowe static void
read_dependency_file(Name filename)1994*e7afc443SToomas Soome read_dependency_file(Name filename)
199510d63b7dSRichard Lowe {
1996*e7afc443SToomas Soome 	Makefile_type	save_makefile_type;
199710d63b7dSRichard Lowe 
199810d63b7dSRichard Lowe 	if (filename == NULL) {
199910d63b7dSRichard Lowe 		return;
200010d63b7dSRichard Lowe 	}
200110d63b7dSRichard Lowe 	filename->stat.time = file_no_time;
200210d63b7dSRichard Lowe 	if (exists(filename) > file_doesnt_exist) {
200310d63b7dSRichard Lowe 		save_makefile_type = makefile_type;
200410d63b7dSRichard Lowe 		makefile_type = reading_cpp_file;
200510d63b7dSRichard Lowe 		if (read_trace_level > 1) {
200610d63b7dSRichard Lowe 			trace_reader = true;
200710d63b7dSRichard Lowe 		}
200810d63b7dSRichard Lowe 		temp_file_number++;
200910d63b7dSRichard Lowe 		(void) read_simple_file(filename,
201010d63b7dSRichard Lowe 					false,
201110d63b7dSRichard Lowe 					false,
201210d63b7dSRichard Lowe 					false,
201310d63b7dSRichard Lowe 					false,
201410d63b7dSRichard Lowe 					false,
201510d63b7dSRichard Lowe 					false);
201610d63b7dSRichard Lowe 		trace_reader = false;
201710d63b7dSRichard Lowe 		makefile_type = save_makefile_type;
201810d63b7dSRichard Lowe 	}
201910d63b7dSRichard Lowe }
202010d63b7dSRichard Lowe 
202110d63b7dSRichard Lowe /*
202210d63b7dSRichard Lowe  *	check_read_state_file()
202310d63b7dSRichard Lowe  *
202410d63b7dSRichard Lowe  *	Check if .make.state has changed
202510d63b7dSRichard Lowe  *	If it has we reread it
202610d63b7dSRichard Lowe  *
202710d63b7dSRichard Lowe  *	Parameters:
202810d63b7dSRichard Lowe  *
202910d63b7dSRichard Lowe  *	Global variables used:
203010d63b7dSRichard Lowe  *		make_state	Make state file name
203110d63b7dSRichard Lowe  *		makefile_type	Type of makefile being read
203210d63b7dSRichard Lowe  *		read_trace_level Debug flag
203310d63b7dSRichard Lowe  *		trace_reader	Debug flag
203410d63b7dSRichard Lowe  */
203510d63b7dSRichard Lowe static void
check_read_state_file(void)203610d63b7dSRichard Lowe check_read_state_file(void)
203710d63b7dSRichard Lowe {
203810d63b7dSRichard Lowe 	timestruc_t		previous = make_state->stat.time;
2039*e7afc443SToomas Soome 	Makefile_type	save_makefile_type;
2040*e7afc443SToomas Soome 	Property	makefile;
204110d63b7dSRichard Lowe 
204210d63b7dSRichard Lowe 	make_state->stat.time = file_no_time;
204310d63b7dSRichard Lowe 	if ((exists(make_state) == file_doesnt_exist) ||
204410d63b7dSRichard Lowe 	    (make_state->stat.time == previous)) {
204510d63b7dSRichard Lowe 		return;
204610d63b7dSRichard Lowe 	}
204710d63b7dSRichard Lowe 	save_makefile_type = makefile_type;
204810d63b7dSRichard Lowe 	makefile_type = rereading_statefile;
204910d63b7dSRichard Lowe 	/* Make sure we clear the old cached contents of .make.state */
205010d63b7dSRichard Lowe 	makefile = maybe_append_prop(make_state, makefile_prop);
205110d63b7dSRichard Lowe 	if (makefile->body.makefile.contents != NULL) {
205210d63b7dSRichard Lowe 		retmem(makefile->body.makefile.contents);
205310d63b7dSRichard Lowe 		makefile->body.makefile.contents = NULL;
205410d63b7dSRichard Lowe 	}
205510d63b7dSRichard Lowe 	if (read_trace_level > 1) {
205610d63b7dSRichard Lowe 		trace_reader = true;
205710d63b7dSRichard Lowe 	}
205810d63b7dSRichard Lowe 	temp_file_number++;
205910d63b7dSRichard Lowe 	(void) read_simple_file(make_state,
206010d63b7dSRichard Lowe 				false,
206110d63b7dSRichard Lowe 				false,
206210d63b7dSRichard Lowe 				false,
206310d63b7dSRichard Lowe 				false,
206410d63b7dSRichard Lowe 				false,
206510d63b7dSRichard Lowe 				true);
206610d63b7dSRichard Lowe 	trace_reader = false;
206710d63b7dSRichard Lowe 	makefile_type = save_makefile_type;
206810d63b7dSRichard Lowe }
206910d63b7dSRichard Lowe 
207010d63b7dSRichard Lowe /*
207110d63b7dSRichard Lowe  *	do_assign(line, target)
207210d63b7dSRichard Lowe  *
207310d63b7dSRichard Lowe  *	Handles runtime assignments for command lines prefixed with "=".
207410d63b7dSRichard Lowe  *
207510d63b7dSRichard Lowe  *	Parameters:
207610d63b7dSRichard Lowe  *		line		The command that contains an assignment
207710d63b7dSRichard Lowe  *		target		The Name of the target, used for error reports
207810d63b7dSRichard Lowe  *
207910d63b7dSRichard Lowe  *	Global variables used:
208010d63b7dSRichard Lowe  *		assign_done	Set to indicate doname needs to reprocess
208110d63b7dSRichard Lowe  */
208210d63b7dSRichard Lowe static void
do_assign(Name line,Name target)2083*e7afc443SToomas Soome do_assign(Name line, Name target)
208410d63b7dSRichard Lowe {
208510d63b7dSRichard Lowe 	Wstring wcb(line);
2086*e7afc443SToomas Soome 	wchar_t	*string = wcb.get_string();
2087*e7afc443SToomas Soome 	wchar_t	*equal;
2088*e7afc443SToomas Soome 	Name		name;
2089*e7afc443SToomas Soome 	Boolean	append = false;
209010d63b7dSRichard Lowe 
209110d63b7dSRichard Lowe 	/*
209210d63b7dSRichard Lowe 	 * If any runtime assignments are done, doname() must reprocess all
209310d63b7dSRichard Lowe 	 * targets in the future since the macro values used to build the
209410d63b7dSRichard Lowe 	 * command lines for the targets might have changed.
209510d63b7dSRichard Lowe 	 */
209610d63b7dSRichard Lowe 	assign_done = true;
209710d63b7dSRichard Lowe 	/* Skip white space. */
209810d63b7dSRichard Lowe 	while (iswspace(*string)) {
209910d63b7dSRichard Lowe 		string++;
210010d63b7dSRichard Lowe 	}
210110d63b7dSRichard Lowe 	equal = string;
210210d63b7dSRichard Lowe 	/* Find "+=" or "=". */
210310d63b7dSRichard Lowe 	while (!iswspace(*equal) &&
210410d63b7dSRichard Lowe 	       (*equal != (int) plus_char) &&
210510d63b7dSRichard Lowe 	       (*equal != (int) equal_char)) {
210610d63b7dSRichard Lowe 		equal++;
210710d63b7dSRichard Lowe 	}
210810d63b7dSRichard Lowe 	/* Internalize macro name. */
210910d63b7dSRichard Lowe 	name = GETNAME(string, equal - string);
211010d63b7dSRichard Lowe 	/* Skip over "+=" "=". */
211110d63b7dSRichard Lowe 	while (!((*equal == (int) nul_char) ||
211210d63b7dSRichard Lowe 		 (*equal == (int) equal_char) ||
211310d63b7dSRichard Lowe 		 (*equal == (int) plus_char))) {
211410d63b7dSRichard Lowe 		equal++;
211510d63b7dSRichard Lowe 	}
211610d63b7dSRichard Lowe 	switch (*equal) {
211710d63b7dSRichard Lowe 	case nul_char:
211810d63b7dSRichard Lowe 		fatal(gettext("= expected in rule `%s' for target `%s'"),
211910d63b7dSRichard Lowe 		      line->string_mb,
212010d63b7dSRichard Lowe 		      target->string_mb);
212110d63b7dSRichard Lowe 	case plus_char:
212210d63b7dSRichard Lowe 		append = true;
212310d63b7dSRichard Lowe 		equal++;
212410d63b7dSRichard Lowe 		break;
212510d63b7dSRichard Lowe 	}
212610d63b7dSRichard Lowe 	equal++;
212710d63b7dSRichard Lowe 	/* Skip over whitespace in front of value. */
212810d63b7dSRichard Lowe 	while (iswspace(*equal)) {
212910d63b7dSRichard Lowe 		equal++;
213010d63b7dSRichard Lowe 	}
213110d63b7dSRichard Lowe 	/* Enter new macro value. */
213210d63b7dSRichard Lowe 	enter_equal(name,
213310d63b7dSRichard Lowe 		    GETNAME(equal, wcb.get_string() + line->hash.length - equal),
213410d63b7dSRichard Lowe 		    append);
213510d63b7dSRichard Lowe }
213610d63b7dSRichard Lowe 
213710d63b7dSRichard Lowe /*
213810d63b7dSRichard Lowe  *	build_command_strings(target, line)
213910d63b7dSRichard Lowe  *
214010d63b7dSRichard Lowe  *	Builds the command string to used when
214110d63b7dSRichard Lowe  *	building a target. If the string is different from the previous one
214210d63b7dSRichard Lowe  *	is_out_of_date is set.
214310d63b7dSRichard Lowe  *
214410d63b7dSRichard Lowe  *	Parameters:
214510d63b7dSRichard Lowe  *		target		Target to build commands for
214610d63b7dSRichard Lowe  *		line		Where to stuff result
214710d63b7dSRichard Lowe  *
214810d63b7dSRichard Lowe  *	Global variables used:
214910d63b7dSRichard Lowe  *		c_at		The Name "@", used to set macro value
215010d63b7dSRichard Lowe  *		command_changed	Set if command is different from old
215110d63b7dSRichard Lowe  *		debug_level	Should we trace activities?
215210d63b7dSRichard Lowe  *		do_not_exec_rule Always echo when running -n
215310d63b7dSRichard Lowe  *		empty_name	The Name "", used for empty rule
215410d63b7dSRichard Lowe  *		funny		Semantics of characters
215510d63b7dSRichard Lowe  *		ignore_errors	Used to init field for line
215610d63b7dSRichard Lowe  *		is_conditional	Set to false befor evaling macro, checked
215710d63b7dSRichard Lowe  *				after expanding macros
215810d63b7dSRichard Lowe  *		keep_state	Indicates that .KEEP_STATE is on
215910d63b7dSRichard Lowe  *		make_word_mentioned Set by macro eval, inits field for cmd
216010d63b7dSRichard Lowe  *		query		The Name "?", used to set macro value
216110d63b7dSRichard Lowe  *		query_mentioned	Set by macro eval, inits field for cmd
216210d63b7dSRichard Lowe  *		recursion_level	Used for tracing
216310d63b7dSRichard Lowe  *		silent		Used to init field for line
216410d63b7dSRichard Lowe  */
216510d63b7dSRichard Lowe static void
build_command_strings(Name target,Property line)2166*e7afc443SToomas Soome build_command_strings(Name target, Property line)
216710d63b7dSRichard Lowe {
216810d63b7dSRichard Lowe 	String_rec		command_line;
2169*e7afc443SToomas Soome 	Cmd_line	command_template = line->body.line.command_template;
2170*e7afc443SToomas Soome 	Cmd_line	*insert = &line->body.line.command_used;
2171*e7afc443SToomas Soome 	Cmd_line	used = *insert;
217210d63b7dSRichard Lowe 	wchar_t			buffer[STRING_BUFFER_LENGTH];
217310d63b7dSRichard Lowe 	wchar_t			*start;
217410d63b7dSRichard Lowe 	Name			new_command_line;
2175*e7afc443SToomas Soome 	Boolean	new_command_longer = false;
2176*e7afc443SToomas Soome 	Boolean	ignore_all_command_dependency = true;
217710d63b7dSRichard Lowe 	Property		member;
217810d63b7dSRichard Lowe 	static Name		less_name;
217910d63b7dSRichard Lowe 	static Name		percent_name;
218010d63b7dSRichard Lowe 	static Name		star;
218110d63b7dSRichard Lowe 	Name			tmp_name;
218210d63b7dSRichard Lowe 
218310d63b7dSRichard Lowe 	if (less_name == NULL) {
218410d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "<");
218510d63b7dSRichard Lowe 		less_name = GETNAME(wcs_buffer, FIND_LENGTH);
218610d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "%");
218710d63b7dSRichard Lowe 		percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
218810d63b7dSRichard Lowe 		MBSTOWCS(wcs_buffer, "*");
218910d63b7dSRichard Lowe 		star = GETNAME(wcs_buffer, FIND_LENGTH);
219010d63b7dSRichard Lowe 	}
219110d63b7dSRichard Lowe 
219210d63b7dSRichard Lowe 	/* We have to check if a target depends on conditional macros */
219310d63b7dSRichard Lowe 	/* Targets that do must be reprocessed by doname() each time around */
219410d63b7dSRichard Lowe 	/* since the macro values used when building the target might have */
219510d63b7dSRichard Lowe 	/* changed */
219610d63b7dSRichard Lowe 	conditional_macro_used = false;
219710d63b7dSRichard Lowe 	/* If we are building a lib.a(member) target $@ should be bound */
219810d63b7dSRichard Lowe 	/* to lib.a */
219910d63b7dSRichard Lowe 	if (target->is_member &&
220010d63b7dSRichard Lowe 	    ((member = get_prop(target->prop, member_prop)) != NULL)) {
220110d63b7dSRichard Lowe 		target = member->body.member.library;
220210d63b7dSRichard Lowe 	}
220310d63b7dSRichard Lowe 	/* If we are building a "::" help target $@ should be bound to */
220410d63b7dSRichard Lowe 	/* the real target name */
220510d63b7dSRichard Lowe 	/* A lib.a(member) target is never :: */
220610d63b7dSRichard Lowe 	if (target->has_target_prop) {
220710d63b7dSRichard Lowe 		target = get_prop(target->prop, target_prop)->
220810d63b7dSRichard Lowe 		  body.target.target;
220910d63b7dSRichard Lowe 	}
221010d63b7dSRichard Lowe 	/* Bind the magic macros that make supplies */
221110d63b7dSRichard Lowe 	tmp_name = target;
221210d63b7dSRichard Lowe 	if(tmp_name != NULL) {
221310d63b7dSRichard Lowe 		if (tmp_name->has_vpath_alias_prop) {
221410d63b7dSRichard Lowe 			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
221510d63b7dSRichard Lowe 					body.vpath_alias.alias;
221610d63b7dSRichard Lowe 		}
221710d63b7dSRichard Lowe 	}
221810d63b7dSRichard Lowe 	(void) SETVAR(c_at, tmp_name, false);
221910d63b7dSRichard Lowe 
222010d63b7dSRichard Lowe 	tmp_name = line->body.line.star;
222110d63b7dSRichard Lowe 	if(tmp_name != NULL) {
222210d63b7dSRichard Lowe 		if (tmp_name->has_vpath_alias_prop) {
222310d63b7dSRichard Lowe 			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
222410d63b7dSRichard Lowe 					body.vpath_alias.alias;
222510d63b7dSRichard Lowe 		}
222610d63b7dSRichard Lowe 	}
222710d63b7dSRichard Lowe 	(void) SETVAR(star, tmp_name, false);
222810d63b7dSRichard Lowe 
222910d63b7dSRichard Lowe 	tmp_name = line->body.line.less;
223010d63b7dSRichard Lowe 	if(tmp_name != NULL) {
223110d63b7dSRichard Lowe 		if (tmp_name->has_vpath_alias_prop) {
223210d63b7dSRichard Lowe 			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
223310d63b7dSRichard Lowe 					body.vpath_alias.alias;
223410d63b7dSRichard Lowe 		}
223510d63b7dSRichard Lowe 	}
223610d63b7dSRichard Lowe 	(void) SETVAR(less_name, tmp_name, false);
223710d63b7dSRichard Lowe 
223810d63b7dSRichard Lowe 	tmp_name = line->body.line.percent;
223910d63b7dSRichard Lowe 	if(tmp_name != NULL) {
224010d63b7dSRichard Lowe 		if (tmp_name->has_vpath_alias_prop) {
224110d63b7dSRichard Lowe 			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
224210d63b7dSRichard Lowe 					body.vpath_alias.alias;
224310d63b7dSRichard Lowe 		}
224410d63b7dSRichard Lowe 	}
224510d63b7dSRichard Lowe 	(void) SETVAR(percent_name, tmp_name, false);
224610d63b7dSRichard Lowe 
224710d63b7dSRichard Lowe 	/* $? is seldom used and it is expensive to build */
224810d63b7dSRichard Lowe 	/* so we store the list form and build the string on demand */
224910d63b7dSRichard Lowe 	Chain query_list = NULL;
225010d63b7dSRichard Lowe 	Chain *query_list_tail = &query_list;
225110d63b7dSRichard Lowe 
225210d63b7dSRichard Lowe 	for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
225310d63b7dSRichard Lowe 		*query_list_tail = ALLOC(Chain);
225410d63b7dSRichard Lowe 		(*query_list_tail)->name = ch->name;
225510d63b7dSRichard Lowe 		if ((*query_list_tail)->name->has_vpath_alias_prop) {
225610d63b7dSRichard Lowe 			(*query_list_tail)->name =
225710d63b7dSRichard Lowe 				get_prop((*query_list_tail)->name->prop,
225810d63b7dSRichard Lowe 					vpath_alias_prop)->body.vpath_alias.alias;
225910d63b7dSRichard Lowe 		}
226010d63b7dSRichard Lowe 		(*query_list_tail)->next = NULL;
226110d63b7dSRichard Lowe 		query_list_tail = &(*query_list_tail)->next;
226210d63b7dSRichard Lowe 	}
226310d63b7dSRichard Lowe 	(void) setvar_daemon(query,
226410d63b7dSRichard Lowe 			     (Name) query_list,
226510d63b7dSRichard Lowe 			     false,
226610d63b7dSRichard Lowe 			     chain_daemon,
226710d63b7dSRichard Lowe                              false,
226810d63b7dSRichard Lowe                              debug_level);
226910d63b7dSRichard Lowe 
227010d63b7dSRichard Lowe 	/* build $^ */
227110d63b7dSRichard Lowe 	Chain hat_list = NULL;
227210d63b7dSRichard Lowe 	Chain *hat_list_tail = &hat_list;
227310d63b7dSRichard Lowe 
227448bbca81SDaniel Hoffman 	for (Dependency dependency = line->body.line.dependencies;
227510d63b7dSRichard Lowe 		dependency != NULL;
227610d63b7dSRichard Lowe 		dependency = dependency->next) {
227710d63b7dSRichard Lowe 		/* skip automatic dependencies */
227810d63b7dSRichard Lowe 		if (!dependency->automatic) {
227910d63b7dSRichard Lowe 			if ((dependency->name != force) &&
228010d63b7dSRichard Lowe 				(dependency->stale == false)) {
228110d63b7dSRichard Lowe 				*hat_list_tail = ALLOC(Chain);
228248bbca81SDaniel Hoffman 
228310d63b7dSRichard Lowe 				if (dependency->name->is_member &&
228410d63b7dSRichard Lowe 					(get_prop(dependency->name->prop, member_prop) != NULL)) {
228548bbca81SDaniel Hoffman 					(*hat_list_tail)->name =
228610d63b7dSRichard Lowe 							get_prop(dependency->name->prop,
228710d63b7dSRichard Lowe 								member_prop)->body.member.member;
228810d63b7dSRichard Lowe 				} else {
228910d63b7dSRichard Lowe 					(*hat_list_tail)->name = dependency->name;
229010d63b7dSRichard Lowe 				}
229110d63b7dSRichard Lowe 
229210d63b7dSRichard Lowe 				if((*hat_list_tail)->name != NULL) {
229310d63b7dSRichard Lowe 					if ((*hat_list_tail)->name->has_vpath_alias_prop) {
229410d63b7dSRichard Lowe 						(*hat_list_tail)->name =
229510d63b7dSRichard Lowe 							get_prop((*hat_list_tail)->name->prop,
229610d63b7dSRichard Lowe 								vpath_alias_prop)->body.vpath_alias.alias;
229710d63b7dSRichard Lowe 					}
229810d63b7dSRichard Lowe 				}
229910d63b7dSRichard Lowe 
230010d63b7dSRichard Lowe 				(*hat_list_tail)->next = NULL;
230110d63b7dSRichard Lowe 				hat_list_tail = &(*hat_list_tail)->next;
230210d63b7dSRichard Lowe 			}
230310d63b7dSRichard Lowe 		}
230410d63b7dSRichard Lowe 	}
230510d63b7dSRichard Lowe 	(void) setvar_daemon(hat,
230610d63b7dSRichard Lowe 			     (Name) hat_list,
230710d63b7dSRichard Lowe 			     false,
230810d63b7dSRichard Lowe 			     chain_daemon,
230910d63b7dSRichard Lowe                              false,
231010d63b7dSRichard Lowe                              debug_level);
231110d63b7dSRichard Lowe 
231210d63b7dSRichard Lowe /* We have two command sequences we need to handle */
231310d63b7dSRichard Lowe /* The old one that we probably read from .make.state */
231410d63b7dSRichard Lowe /* and the new one we are building that will replace the old one */
231510d63b7dSRichard Lowe /* Even when KEEP_STATE is not on we build a new command sequence and store */
231610d63b7dSRichard Lowe /* it in the line prop. This command sequence is then executed by */
231710d63b7dSRichard Lowe /* run_command(). If KEEP_STATE is on it is also later written to */
231810d63b7dSRichard Lowe /* .make.state. The routine replaces the old command line by line with the */
231910d63b7dSRichard Lowe /* new one trying to reuse Cmd_lines */
232010d63b7dSRichard Lowe 
232110d63b7dSRichard Lowe 	/* If there is no old command_used we have to start creating */
232210d63b7dSRichard Lowe 	/* Cmd_lines to keep the new cmd in */
232310d63b7dSRichard Lowe 	if (used == NULL) {
232410d63b7dSRichard Lowe 		new_command_longer = true;
232510d63b7dSRichard Lowe 		*insert = used = ALLOC(Cmd_line);
232610d63b7dSRichard Lowe 		used->next = NULL;
232710d63b7dSRichard Lowe 		used->command_line = NULL;
232810d63b7dSRichard Lowe 		insert = &used->next;
232910d63b7dSRichard Lowe 	}
233010d63b7dSRichard Lowe 	/* Run thru the template for the new command and build the expanded */
233110d63b7dSRichard Lowe 	/* new command lines */
233210d63b7dSRichard Lowe 	for (;
233310d63b7dSRichard Lowe 	     command_template != NULL;
233410d63b7dSRichard Lowe 	     command_template = command_template->next, insert = &used->next, used = *insert) {
233510d63b7dSRichard Lowe 		/* If there is no old command_used Cmd_line we need to */
233610d63b7dSRichard Lowe 		/* create one and say that cmd consistency failed */
233710d63b7dSRichard Lowe 		if (used == NULL) {
233810d63b7dSRichard Lowe 			new_command_longer = true;
233910d63b7dSRichard Lowe 			*insert = used = ALLOC(Cmd_line);
234010d63b7dSRichard Lowe 			used->next = NULL;
234110d63b7dSRichard Lowe 			used->command_line = empty_name;
234210d63b7dSRichard Lowe 		}
234310d63b7dSRichard Lowe 		/* Prepare the Cmd_line for the processing */
234410d63b7dSRichard Lowe 		/* The command line prefixes "@-=?" are stripped and that */
234510d63b7dSRichard Lowe 		/* information is saved in the Cmd_line */
234610d63b7dSRichard Lowe 		used->assign = false;
234710d63b7dSRichard Lowe 		used->ignore_error = ignore_errors;
234810d63b7dSRichard Lowe 		used->silent = silent;
234910d63b7dSRichard Lowe 		used->always_exec = false;
235010d63b7dSRichard Lowe 		/* Expand the macros in the command line */
235110d63b7dSRichard Lowe 		INIT_STRING_FROM_STACK(command_line, buffer);
235210d63b7dSRichard Lowe 		make_word_mentioned =
235310d63b7dSRichard Lowe 		  query_mentioned =
235410d63b7dSRichard Lowe 		    false;
235510d63b7dSRichard Lowe 		expand_value(command_template->command_line, &command_line, true);
235610d63b7dSRichard Lowe 		/* If the macro $(MAKE) is mentioned in the command */
235710d63b7dSRichard Lowe 		/* "make -n" runs actually execute the command */
235810d63b7dSRichard Lowe 		used->make_refd = make_word_mentioned;
235910d63b7dSRichard Lowe 		used->ignore_command_dependency = query_mentioned;
236010d63b7dSRichard Lowe 		/* Strip the prefixes */
236110d63b7dSRichard Lowe 		start = command_line.buffer.start;
236210d63b7dSRichard Lowe 		for (;
236310d63b7dSRichard Lowe 		     iswspace(*start) ||
236410d63b7dSRichard Lowe 		     (get_char_semantics_value(*start) & (int) command_prefix_sem);
236510d63b7dSRichard Lowe 		     start++) {
236610d63b7dSRichard Lowe 			switch (*start) {
236710d63b7dSRichard Lowe 			case question_char:
236810d63b7dSRichard Lowe 				used->ignore_command_dependency = true;
236910d63b7dSRichard Lowe 				break;
237010d63b7dSRichard Lowe 			case exclam_char:
237110d63b7dSRichard Lowe 				used->ignore_command_dependency = false;
237210d63b7dSRichard Lowe 				break;
237310d63b7dSRichard Lowe 			case equal_char:
237410d63b7dSRichard Lowe 				used->assign = true;
237510d63b7dSRichard Lowe 				break;
237610d63b7dSRichard Lowe 			case hyphen_char:
237710d63b7dSRichard Lowe 				used->ignore_error = true;
237810d63b7dSRichard Lowe 				break;
237910d63b7dSRichard Lowe 			case at_char:
238010d63b7dSRichard Lowe 				if (!do_not_exec_rule) {
238110d63b7dSRichard Lowe 					used->silent = true;
238210d63b7dSRichard Lowe 				}
238310d63b7dSRichard Lowe 				break;
238410d63b7dSRichard Lowe 			case plus_char:
238510d63b7dSRichard Lowe 				if(posix) {
238610d63b7dSRichard Lowe 				  used->always_exec  = true;
238710d63b7dSRichard Lowe 				}
238810d63b7dSRichard Lowe 				break;
238910d63b7dSRichard Lowe 			}
239010d63b7dSRichard Lowe 		}
239110d63b7dSRichard Lowe 		/* If all command lines of the template are prefixed with "?"*/
239210d63b7dSRichard Lowe 		/* the VIRTUAL_ROOT is not used for cmd consistency checks */
239310d63b7dSRichard Lowe 		if (!used->ignore_command_dependency) {
239410d63b7dSRichard Lowe 			ignore_all_command_dependency = false;
239510d63b7dSRichard Lowe 		}
239610d63b7dSRichard Lowe 		/* Internalize the expanded and stripped command line */
239710d63b7dSRichard Lowe 		new_command_line = GETNAME(start, FIND_LENGTH);
239810d63b7dSRichard Lowe 		if ((used->command_line == NULL) &&
239910d63b7dSRichard Lowe 		    (line->body.line.sccs_command)) {
240010d63b7dSRichard Lowe 			used->command_line = new_command_line;
240110d63b7dSRichard Lowe 			new_command_longer = false;
240210d63b7dSRichard Lowe 		}
240310d63b7dSRichard Lowe 		/* Compare it with the old one for command consistency */
240410d63b7dSRichard Lowe 		if (used->command_line != new_command_line) {
240510d63b7dSRichard Lowe 			Name vpath_translated = vpath_translation(new_command_line);
240610d63b7dSRichard Lowe 			if (keep_state &&
240710d63b7dSRichard Lowe 			    !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
240810d63b7dSRichard Lowe 				if (debug_level > 0) {
240910d63b7dSRichard Lowe 					if (used->command_line != NULL
241010d63b7dSRichard Lowe 					    && *used->command_line->string_mb !=
241110d63b7dSRichard Lowe 					    '\0') {
241210d63b7dSRichard Lowe 						(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
241310d63b7dSRichard Lowe 							      recursion_level,
241410d63b7dSRichard Lowe 							      "",
241510d63b7dSRichard Lowe 							      target->string_mb,
241610d63b7dSRichard Lowe 							      vpath_translated->string_mb,
241710d63b7dSRichard Lowe 							      recursion_level,
241810d63b7dSRichard Lowe 							      "",
241910d63b7dSRichard Lowe 							      used->
242010d63b7dSRichard Lowe 							      command_line->
242110d63b7dSRichard Lowe 							      string_mb);
242210d63b7dSRichard Lowe 					} else {
242310d63b7dSRichard Lowe 						(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
242410d63b7dSRichard Lowe 							      recursion_level,
242510d63b7dSRichard Lowe 							      "",
242610d63b7dSRichard Lowe 							      target->string_mb,
242710d63b7dSRichard Lowe 							      vpath_translated->string_mb,
242810d63b7dSRichard Lowe 							      recursion_level,
242910d63b7dSRichard Lowe 							      "");
243010d63b7dSRichard Lowe 					}
243110d63b7dSRichard Lowe 				}
243210d63b7dSRichard Lowe 				command_changed = true;
243310d63b7dSRichard Lowe                                 line->body.line.is_out_of_date = true;
243410d63b7dSRichard Lowe 			}
243510d63b7dSRichard Lowe 			used->command_line = new_command_line;
243610d63b7dSRichard Lowe 		}
243710d63b7dSRichard Lowe 		if (command_line.free_after_use) {
243810d63b7dSRichard Lowe 			retmem(command_line.buffer.start);
243910d63b7dSRichard Lowe 		}
244010d63b7dSRichard Lowe 	}
244110d63b7dSRichard Lowe 	/* Check if the old command is longer than the new for */
244210d63b7dSRichard Lowe 	/* command consistency */
244310d63b7dSRichard Lowe 	if (used != NULL) {
244410d63b7dSRichard Lowe 		*insert = NULL;
244510d63b7dSRichard Lowe 		if (keep_state &&
244610d63b7dSRichard Lowe 		    !ignore_all_command_dependency) {
244710d63b7dSRichard Lowe 			if (debug_level > 0) {
244810d63b7dSRichard Lowe 				(void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
244910d63b7dSRichard Lowe 					      recursion_level,
245010d63b7dSRichard Lowe 					      "",
245110d63b7dSRichard Lowe 					      target->string_mb);
245210d63b7dSRichard Lowe 			}
245310d63b7dSRichard Lowe 			command_changed = true;
245410d63b7dSRichard Lowe                         line->body.line.is_out_of_date = true;
245510d63b7dSRichard Lowe 		}
245610d63b7dSRichard Lowe 	}
245710d63b7dSRichard Lowe 	/* Check if the new command is longer than the old command for */
245810d63b7dSRichard Lowe 	/* command consistency */
245910d63b7dSRichard Lowe 	if (new_command_longer &&
246010d63b7dSRichard Lowe 	    !ignore_all_command_dependency &&
246110d63b7dSRichard Lowe 	    keep_state) {
246210d63b7dSRichard Lowe 		if (debug_level > 0) {
246310d63b7dSRichard Lowe 			(void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
246410d63b7dSRichard Lowe 				      recursion_level,
246510d63b7dSRichard Lowe 				      "",
246610d63b7dSRichard Lowe 				      target->string_mb);
246710d63b7dSRichard Lowe 		}
246810d63b7dSRichard Lowe 		command_changed = true;
246910d63b7dSRichard Lowe                 line->body.line.is_out_of_date = true;
247010d63b7dSRichard Lowe 	}
247110d63b7dSRichard Lowe 	/* Unbind the magic macros */
247210d63b7dSRichard Lowe 	(void) SETVAR(c_at, (Name) NULL, false);
247310d63b7dSRichard Lowe 	(void) SETVAR(star, (Name) NULL, false);
247410d63b7dSRichard Lowe 	(void) SETVAR(less_name, (Name) NULL, false);
247510d63b7dSRichard Lowe 	(void) SETVAR(percent_name, (Name) NULL, false);
247610d63b7dSRichard Lowe 	(void) SETVAR(query, (Name) NULL, false);
247710d63b7dSRichard Lowe         if (query_list != NULL) {
24782e8f3c34SToomas Soome 		delete_query_chain(query_list);
247910d63b7dSRichard Lowe         }
248010d63b7dSRichard Lowe 	(void) SETVAR(hat, (Name) NULL, false);
248110d63b7dSRichard Lowe         if (hat_list != NULL) {
24822e8f3c34SToomas Soome 		delete_query_chain(hat_list);
248310d63b7dSRichard Lowe         }
248410d63b7dSRichard Lowe 
248510d63b7dSRichard Lowe 	if (conditional_macro_used) {
248610d63b7dSRichard Lowe 		target->conditional_macro_list = cond_macro_list;
248710d63b7dSRichard Lowe 		cond_macro_list = NULL;
248810d63b7dSRichard Lowe 		target->depends_on_conditional = true;
248910d63b7dSRichard Lowe 	}
249010d63b7dSRichard Lowe }
249110d63b7dSRichard Lowe 
249210d63b7dSRichard Lowe /*
249310d63b7dSRichard Lowe  *	touch_command(line, target, result)
249410d63b7dSRichard Lowe  *
249510d63b7dSRichard Lowe  *	If this is an "make -t" run we do this.
249610d63b7dSRichard Lowe  *	We touch all targets in the target group ("foo + fie:") if any.
249710d63b7dSRichard Lowe  *
249810d63b7dSRichard Lowe  *	Return value:
249910d63b7dSRichard Lowe  *				Indicates if the command failed or not
250010d63b7dSRichard Lowe  *
250110d63b7dSRichard Lowe  *	Parameters:
250210d63b7dSRichard Lowe  *		line		The command line to update
250310d63b7dSRichard Lowe  *		target		The target we are touching
250410d63b7dSRichard Lowe  *		result		Initial value for the result we return
250510d63b7dSRichard Lowe  *
250610d63b7dSRichard Lowe  *	Global variables used:
250710d63b7dSRichard Lowe  *		do_not_exec_rule Indicates that -n is on
250810d63b7dSRichard Lowe  *		silent		Do not echo commands
250910d63b7dSRichard Lowe  */
251010d63b7dSRichard Lowe static Doname
touch_command(Property line,Name target,Doname result)2511*e7afc443SToomas Soome touch_command(Property line, Name target, Doname result)
251210d63b7dSRichard Lowe {
251310d63b7dSRichard Lowe 	Name			name;
2514*e7afc443SToomas Soome 	Chain		target_group;
251510d63b7dSRichard Lowe 	String_rec		touch_string;
251610d63b7dSRichard Lowe 	wchar_t			buffer[MAXPATHLEN];
251710d63b7dSRichard Lowe 	Name			touch_cmd;
251810d63b7dSRichard Lowe 	Cmd_line		rule;
251910d63b7dSRichard Lowe 
252010d63b7dSRichard Lowe 	for (name = target, target_group = NULL; name != NULL;) {
252110d63b7dSRichard Lowe 		if (!name->is_member) {
252210d63b7dSRichard Lowe 			/*
252310d63b7dSRichard Lowe 			 * Build a touch command that can be passed
252410d63b7dSRichard Lowe 			 * to dosys(). If KEEP_STATE is on, "make -t"
252510d63b7dSRichard Lowe 			 * will save the proper command, not the
252610d63b7dSRichard Lowe 			 * "touch" in .make.state.
252710d63b7dSRichard Lowe 			 */
252810d63b7dSRichard Lowe 			INIT_STRING_FROM_STACK(touch_string, buffer);
252910d63b7dSRichard Lowe 			MBSTOWCS(wcs_buffer, "touch ");
253010d63b7dSRichard Lowe 			append_string(wcs_buffer, &touch_string, FIND_LENGTH);
253110d63b7dSRichard Lowe 			touch_cmd = name;
253210d63b7dSRichard Lowe 			if (name->has_vpath_alias_prop) {
253310d63b7dSRichard Lowe 				touch_cmd = get_prop(name->prop,
253410d63b7dSRichard Lowe 						 vpath_alias_prop)->
253510d63b7dSRichard Lowe 						   body.vpath_alias.alias;
253610d63b7dSRichard Lowe 			}
253710d63b7dSRichard Lowe 			APPEND_NAME(touch_cmd,
253810d63b7dSRichard Lowe 				      &touch_string,
253910d63b7dSRichard Lowe 				      FIND_LENGTH);
254010d63b7dSRichard Lowe 			touch_cmd = GETNAME(touch_string.buffer.start,
254110d63b7dSRichard Lowe 					    FIND_LENGTH);
254210d63b7dSRichard Lowe 			if (touch_string.free_after_use) {
254310d63b7dSRichard Lowe 				retmem(touch_string.buffer.start);
254410d63b7dSRichard Lowe 			}
254510d63b7dSRichard Lowe 			if (!silent ||
254610d63b7dSRichard Lowe 			    do_not_exec_rule &&
254710d63b7dSRichard Lowe 			    (target_group == NULL)) {
254810d63b7dSRichard Lowe 				(void) printf("%s\n", touch_cmd->string_mb);
254910d63b7dSRichard Lowe 			}
255010d63b7dSRichard Lowe 			/* Run the touch command, or simulate it */
255110d63b7dSRichard Lowe 			if (!do_not_exec_rule) {
255210d63b7dSRichard Lowe 				result = dosys(touch_cmd,
255310d63b7dSRichard Lowe 					       false,
255410d63b7dSRichard Lowe 					       false,
255510d63b7dSRichard Lowe 					       false,
255610d63b7dSRichard Lowe 					       false,
255710d63b7dSRichard Lowe 					       name);
255810d63b7dSRichard Lowe 			} else {
255910d63b7dSRichard Lowe 				result = build_ok;
256010d63b7dSRichard Lowe 			}
256110d63b7dSRichard Lowe 		} else {
256210d63b7dSRichard Lowe 			result = build_ok;
256310d63b7dSRichard Lowe 		}
256410d63b7dSRichard Lowe 		if (target_group == NULL) {
256510d63b7dSRichard Lowe 			target_group = line->body.line.target_group;
256610d63b7dSRichard Lowe 		} else {
256710d63b7dSRichard Lowe 			target_group = target_group->next;
256810d63b7dSRichard Lowe 		}
256910d63b7dSRichard Lowe 		if (target_group != NULL) {
257010d63b7dSRichard Lowe 			name = target_group->name;
257110d63b7dSRichard Lowe 		} else {
257210d63b7dSRichard Lowe 			name = NULL;
257310d63b7dSRichard Lowe 		}
257410d63b7dSRichard Lowe 	}
257510d63b7dSRichard Lowe 	return result;
257610d63b7dSRichard Lowe }
257710d63b7dSRichard Lowe 
257810d63b7dSRichard Lowe /*
257910d63b7dSRichard Lowe  *	update_target(line, result)
258010d63b7dSRichard Lowe  *
258110d63b7dSRichard Lowe  *	updates the status of a target after executing its commands.
258210d63b7dSRichard Lowe  *
258310d63b7dSRichard Lowe  *	Parameters:
258410d63b7dSRichard Lowe  *		line		The command line block to update
258510d63b7dSRichard Lowe  *		result		Indicates that build is OK so can update
258610d63b7dSRichard Lowe  *
258710d63b7dSRichard Lowe  *	Global variables used:
258810d63b7dSRichard Lowe  *		do_not_exec_rule Indicates that -n is on
258910d63b7dSRichard Lowe  *		touch		Fake the new timestamp if we are just touching
259010d63b7dSRichard Lowe  */
259110d63b7dSRichard Lowe void
update_target(Property line,Doname result)259210d63b7dSRichard Lowe update_target(Property line, Doname result)
259310d63b7dSRichard Lowe {
259410d63b7dSRichard Lowe 	Name			target;
259510d63b7dSRichard Lowe 	Chain			target_group;
259610d63b7dSRichard Lowe 	Property		line2;
259710d63b7dSRichard Lowe 	timestruc_t		old_stat_time;
259810d63b7dSRichard Lowe 	Property		member;
259910d63b7dSRichard Lowe 
260010d63b7dSRichard Lowe 	/*
260110d63b7dSRichard Lowe 	 * [tolik] Additional fix for bug 1063790. It was fixed
260210d63b7dSRichard Lowe 	 * for serial make long ago, but DMake dumps core when
260348bbca81SDaniel Hoffman 	 * target is a symlink and sccs file is newer then target.
260410d63b7dSRichard Lowe 	 * In this case, finish_children() calls update_target()
260510d63b7dSRichard Lowe 	 * with line==NULL.
260610d63b7dSRichard Lowe 	 */
260710d63b7dSRichard Lowe 	if(line == NULL) {
260810d63b7dSRichard Lowe 		/* XXX. Should we do anything here? */
260910d63b7dSRichard Lowe 		return;
261048bbca81SDaniel Hoffman 	}
261110d63b7dSRichard Lowe 
261210d63b7dSRichard Lowe 	target = line->body.line.target;
261310d63b7dSRichard Lowe 
261410d63b7dSRichard Lowe 	if ((result == build_ok) && (line->body.line.command_used != NULL)) {
261510d63b7dSRichard Lowe 		if (do_not_exec_rule ||
261610d63b7dSRichard Lowe 		    touch ||
261710d63b7dSRichard Lowe 		    (target->is_member &&
261810d63b7dSRichard Lowe 		     (line->body.line.command_template != NULL) &&
261910d63b7dSRichard Lowe 		     (line->body.line.command_template->command_line->string_mb[0] == 0) &&
262010d63b7dSRichard Lowe 		     (line->body.line.command_template->next == NULL))) {
262110d63b7dSRichard Lowe 			/* If we are simulating execution we need to fake a */
262210d63b7dSRichard Lowe 			/* new timestamp for the target we didnt build */
262310d63b7dSRichard Lowe 			target->stat.time = file_max_time;
262410d63b7dSRichard Lowe 		} else {
262510d63b7dSRichard Lowe 			/*
262610d63b7dSRichard Lowe 			 * If we really built the target we read the new
262710d63b7dSRichard Lowe 			 * timestamp.
262810d63b7dSRichard Lowe 			 * Fix for bug #1110906: if .c file is newer than
262910d63b7dSRichard Lowe 			 * the corresponding .o file which is in an archive
263010d63b7dSRichard Lowe 			 * file, make will compile the .c file but it won't
263110d63b7dSRichard Lowe 			 * update the object in the .a file.
263210d63b7dSRichard Lowe 			 */
263310d63b7dSRichard Lowe 			old_stat_time = target->stat.time;
263410d63b7dSRichard Lowe 			target->stat.time = file_no_time;
263510d63b7dSRichard Lowe 			(void) exists(target);
263610d63b7dSRichard Lowe 			if ((target->is_member) &&
263710d63b7dSRichard Lowe 			    (target->stat.time == old_stat_time)) {
263810d63b7dSRichard Lowe 				member = get_prop(target->prop, member_prop);
263910d63b7dSRichard Lowe 				if (member != NULL) {
264010d63b7dSRichard Lowe 					target->stat.time = member->body.member.library->stat.time;
264110d63b7dSRichard Lowe 					target->stat.time.tv_sec++;
264210d63b7dSRichard Lowe 				}
264310d63b7dSRichard Lowe 			}
264410d63b7dSRichard Lowe 		}
264510d63b7dSRichard Lowe 		/* If the target is part of a group we need to propagate the */
264610d63b7dSRichard Lowe 		/* result of the run to all members */
264710d63b7dSRichard Lowe 		for (target_group = line->body.line.target_group;
264810d63b7dSRichard Lowe 		     target_group != NULL;
264910d63b7dSRichard Lowe 		     target_group = target_group->next) {
265010d63b7dSRichard Lowe 			target_group->name->stat.time = target->stat.time;
265110d63b7dSRichard Lowe 			line2 = maybe_append_prop(target_group->name,
265210d63b7dSRichard Lowe 						  line_prop);
265310d63b7dSRichard Lowe 			line2->body.line.command_used =
265410d63b7dSRichard Lowe 			  line->body.line.command_used;
265510d63b7dSRichard Lowe 			line2->body.line.target = target_group->name;
265610d63b7dSRichard Lowe 		}
265710d63b7dSRichard Lowe 	}
265810d63b7dSRichard Lowe 	target->has_built = true;
265910d63b7dSRichard Lowe }
266010d63b7dSRichard Lowe 
266110d63b7dSRichard Lowe /*
266210d63b7dSRichard Lowe  *	sccs_get(target, command)
266310d63b7dSRichard Lowe  *
266410d63b7dSRichard Lowe  *	Figures out if it possible to sccs get a file
266510d63b7dSRichard Lowe  *	and builds the command to do it if it is.
266610d63b7dSRichard Lowe  *
266710d63b7dSRichard Lowe  *	Return value:
266810d63b7dSRichard Lowe  *				Indicates if sccs get failed or not
266910d63b7dSRichard Lowe  *
267010d63b7dSRichard Lowe  *	Parameters:
267110d63b7dSRichard Lowe  *		target		Target to get
267210d63b7dSRichard Lowe  *		command		Where to deposit command to use
267310d63b7dSRichard Lowe  *
267410d63b7dSRichard Lowe  *	Global variables used:
267510d63b7dSRichard Lowe  *		debug_level	Should we trace activities?
267610d63b7dSRichard Lowe  *		recursion_level	Used for tracing
267710d63b7dSRichard Lowe  *		sccs_get_rule	The rule to used for sccs getting
267810d63b7dSRichard Lowe  */
267910d63b7dSRichard Lowe static Doname
sccs_get(Name target,Property * command)2680*e7afc443SToomas Soome sccs_get(Name target, Property *command)
268110d63b7dSRichard Lowe {
2682*e7afc443SToomas Soome 	int		result;
268310d63b7dSRichard Lowe 	char			link[MAXPATHLEN];
268410d63b7dSRichard Lowe 	String_rec		string;
268510d63b7dSRichard Lowe 	wchar_t			name[MAXPATHLEN];
2686*e7afc443SToomas Soome 	wchar_t	*p;
268710d63b7dSRichard Lowe 	timestruc_t		sccs_time;
2688*e7afc443SToomas Soome 	Property	line;
268910d63b7dSRichard Lowe 	int			sym_link_depth = 0;
269010d63b7dSRichard Lowe 
269110d63b7dSRichard Lowe 	/* For sccs, we need to chase symlinks. */
269210d63b7dSRichard Lowe         while (target->stat.is_sym_link) {
269310d63b7dSRichard Lowe 		if (sym_link_depth++ > 90) {
269410d63b7dSRichard Lowe 			fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
269510d63b7dSRichard Lowe 			      target->string_mb);
269610d63b7dSRichard Lowe 		}
269710d63b7dSRichard Lowe                 /* Read the value of the link. */
269810d63b7dSRichard Lowe                 result = readlink_vroot(target->string_mb,
269910d63b7dSRichard Lowe 					link,
270010d63b7dSRichard Lowe 					sizeof(link),
270110d63b7dSRichard Lowe 					NULL,
270210d63b7dSRichard Lowe 					VROOT_DEFAULT);
270310d63b7dSRichard Lowe                 if (result == -1) {
270410d63b7dSRichard Lowe                         fatal(gettext("Can't read symbolic link `%s': %s"),
270510d63b7dSRichard Lowe                               target->string_mb, errmsg(errno));
270610d63b7dSRichard Lowe 		}
270710d63b7dSRichard Lowe 		link[result] = 0;
270810d63b7dSRichard Lowe                 /* Use the value to build the proper filename. */
270910d63b7dSRichard Lowe                 INIT_STRING_FROM_STACK(string, name);
271010d63b7dSRichard Lowe 
271110d63b7dSRichard Lowe 		Wstring wcb(target);
271210d63b7dSRichard Lowe                 if ((link[0] != slash_char) &&
271310d63b7dSRichard Lowe                     ((p = (wchar_t *) wcsrchr(wcb.get_string(), slash_char)) != NULL)) {
271410d63b7dSRichard Lowe                         append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
271510d63b7dSRichard Lowe 		}
271610d63b7dSRichard Lowe                 append_string(link, &string, result);
271710d63b7dSRichard Lowe                 /* Replace the old name with the translated name. */
271810d63b7dSRichard Lowe 		target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
271910d63b7dSRichard Lowe                 (void) exists(target);
272010d63b7dSRichard Lowe                 if (string.free_after_use) {
272110d63b7dSRichard Lowe                         retmem(string.buffer.start);
272210d63b7dSRichard Lowe 		}
272310d63b7dSRichard Lowe         }
272410d63b7dSRichard Lowe 
272510d63b7dSRichard Lowe 	/*
272610d63b7dSRichard Lowe 	 * read_dir() also reads the ?/SCCS dir and saves information
272710d63b7dSRichard Lowe 	 * about which files have SCSC/s. files.
272810d63b7dSRichard Lowe 	 */
272910d63b7dSRichard Lowe 	if (target->stat.has_sccs == DONT_KNOW_SCCS) {
273010d63b7dSRichard Lowe 		read_directory_of_file(target);
273110d63b7dSRichard Lowe 	}
273210d63b7dSRichard Lowe 	switch (target->stat.has_sccs) {
273310d63b7dSRichard Lowe 	case DONT_KNOW_SCCS:
273410d63b7dSRichard Lowe 		/* We dont know by now there is no SCCS/s.* */
273510d63b7dSRichard Lowe 		target->stat.has_sccs = NO_SCCS;
27368e0c8248SAndrew Stormont 		/* FALLTHROUGH */
273710d63b7dSRichard Lowe 	case NO_SCCS:
273810d63b7dSRichard Lowe 		/*
273910d63b7dSRichard Lowe 		 * If there is no SCCS/s.* but the plain file exists,
274010d63b7dSRichard Lowe 		 * we say things are OK.
274110d63b7dSRichard Lowe 		 */
274210d63b7dSRichard Lowe 		if (target->stat.time > file_doesnt_exist) {
274310d63b7dSRichard Lowe 			return build_ok;
274410d63b7dSRichard Lowe 		}
274510d63b7dSRichard Lowe 		/* If we cant find the plain file, we give up. */
274610d63b7dSRichard Lowe 		return build_dont_know;
274710d63b7dSRichard Lowe 	case HAS_SCCS:
274810d63b7dSRichard Lowe 		/*
274910d63b7dSRichard Lowe 		 * Pay dirt. We now need to figure out if the plain file
275010d63b7dSRichard Lowe 		 * is out of date relative to the SCCS/s.* file.
275110d63b7dSRichard Lowe 		 */
275210d63b7dSRichard Lowe 		sccs_time = exists(get_prop(target->prop,
275310d63b7dSRichard Lowe 					    sccs_prop)->body.sccs.file);
275410d63b7dSRichard Lowe 		break;
275510d63b7dSRichard Lowe 	}
275610d63b7dSRichard Lowe 
275710d63b7dSRichard Lowe 	if ((!target->has_complained &&
275810d63b7dSRichard Lowe 	    (sccs_time != file_doesnt_exist) &&
275910d63b7dSRichard Lowe 	    (sccs_get_rule != NULL))) {
276010d63b7dSRichard Lowe 		/* only checking */
276110d63b7dSRichard Lowe 		if (command == NULL) {
276210d63b7dSRichard Lowe 			return build_ok;
276310d63b7dSRichard Lowe 		}
276410d63b7dSRichard Lowe 		/*
276510d63b7dSRichard Lowe 		 * We provide a command line for the target. The line is a
276610d63b7dSRichard Lowe 		 * "sccs get" command from default.mk.
276710d63b7dSRichard Lowe 		 */
276810d63b7dSRichard Lowe 		line = maybe_append_prop(target, line_prop);
276910d63b7dSRichard Lowe 		*command = line;
277010d63b7dSRichard Lowe 		if (sccs_time > target->stat.time) {
277110d63b7dSRichard Lowe 			/*
277210d63b7dSRichard Lowe 			 * And only if the plain file is out of date do we
277310d63b7dSRichard Lowe 			 * request execution of the command.
277410d63b7dSRichard Lowe 			 */
277510d63b7dSRichard Lowe 			line->body.line.is_out_of_date = true;
277610d63b7dSRichard Lowe 			if (debug_level > 0) {
277710d63b7dSRichard Lowe 				(void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
277810d63b7dSRichard Lowe 					      recursion_level,
277910d63b7dSRichard Lowe 					      "",
278010d63b7dSRichard Lowe 					      target->string_mb);
278110d63b7dSRichard Lowe 			}
278210d63b7dSRichard Lowe 		}
278310d63b7dSRichard Lowe 		line->body.line.sccs_command = true;
278410d63b7dSRichard Lowe 		line->body.line.command_template = sccs_get_rule;
278510d63b7dSRichard Lowe 		if(!svr4 && (!allrules_read || posix)) {
278610d63b7dSRichard Lowe 		   if((target->prop) &&
278710d63b7dSRichard Lowe 		      (target->prop->body.sccs.file) &&
278810d63b7dSRichard Lowe 		      (target->prop->body.sccs.file->string_mb)) {
278910d63b7dSRichard Lowe 		      if((strlen(target->prop->body.sccs.file->string_mb) ==
279048bbca81SDaniel Hoffman 			strlen(target->string_mb) + 2) &&
279110d63b7dSRichard Lowe 		        (target->prop->body.sccs.file->string_mb[0] == 's') &&
279210d63b7dSRichard Lowe 		        (target->prop->body.sccs.file->string_mb[1] == '.')) {
279310d63b7dSRichard Lowe 
279410d63b7dSRichard Lowe 		         line->body.line.command_template = get_posix_rule;
279510d63b7dSRichard Lowe 		      }
279610d63b7dSRichard Lowe 		   }
279710d63b7dSRichard Lowe 		}
279810d63b7dSRichard Lowe 		line->body.line.target = target;
279910d63b7dSRichard Lowe 		/*
280010d63b7dSRichard Lowe 		 * Also make sure the rule is build with $* and $<
280110d63b7dSRichard Lowe 		 * bound properly.
280210d63b7dSRichard Lowe 		 */
280310d63b7dSRichard Lowe 		line->body.line.star = NULL;
280410d63b7dSRichard Lowe 		line->body.line.less = NULL;
280510d63b7dSRichard Lowe 		line->body.line.percent = NULL;
280610d63b7dSRichard Lowe 		return build_ok;
280710d63b7dSRichard Lowe 	}
280810d63b7dSRichard Lowe 	return build_dont_know;
280910d63b7dSRichard Lowe }
281010d63b7dSRichard Lowe 
281110d63b7dSRichard Lowe /*
281210d63b7dSRichard Lowe  *	read_directory_of_file(file)
281310d63b7dSRichard Lowe  *
281410d63b7dSRichard Lowe  *	Reads the directory the specified file lives in.
281510d63b7dSRichard Lowe  *
281610d63b7dSRichard Lowe  *	Parameters:
281710d63b7dSRichard Lowe  *		file		The file we need to read dir for
281810d63b7dSRichard Lowe  *
281910d63b7dSRichard Lowe  *	Global variables used:
282010d63b7dSRichard Lowe  *		dot		The Name ".", used as the default dir
282110d63b7dSRichard Lowe  */
282210d63b7dSRichard Lowe void
read_directory_of_file(Name file)2823*e7afc443SToomas Soome read_directory_of_file(Name file)
282410d63b7dSRichard Lowe {
282510d63b7dSRichard Lowe 
282610d63b7dSRichard Lowe 	Wstring file_string(file);
282710d63b7dSRichard Lowe 	wchar_t * wcb = file_string.get_string();
282810d63b7dSRichard Lowe 	wchar_t usr_include_buf[MAXPATHLEN];
282910d63b7dSRichard Lowe 	wchar_t usr_include_sys_buf[MAXPATHLEN];
283010d63b7dSRichard Lowe 
2831*e7afc443SToomas Soome 	Name		directory = dot;
2832*e7afc443SToomas Soome 	wchar_t	*p = (wchar_t *) wcsrchr(wcb,
283310d63b7dSRichard Lowe 							(int) slash_char);
2834*e7afc443SToomas Soome 	int		length = p - wcb;
283510d63b7dSRichard Lowe 	static Name		usr_include;
283610d63b7dSRichard Lowe 	static Name		usr_include_sys;
283710d63b7dSRichard Lowe 
283810d63b7dSRichard Lowe 	if (usr_include == NULL) {
283910d63b7dSRichard Lowe 		MBSTOWCS(usr_include_buf, "/usr/include");
284010d63b7dSRichard Lowe 		usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
284110d63b7dSRichard Lowe 		MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
284210d63b7dSRichard Lowe 		usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
284310d63b7dSRichard Lowe 	}
284410d63b7dSRichard Lowe 
284510d63b7dSRichard Lowe 	/*
284610d63b7dSRichard Lowe 	 * If the filename contains a "/" we have to extract the path
284710d63b7dSRichard Lowe 	 * Else the path defaults to ".".
284810d63b7dSRichard Lowe 	 */
284910d63b7dSRichard Lowe 	if (p != NULL) {
285010d63b7dSRichard Lowe 		/*
285110d63b7dSRichard Lowe 		 * Check some popular directories first to possibly
285210d63b7dSRichard Lowe 		 * save time. Compare string length first to gain speed.
285310d63b7dSRichard Lowe 		 */
285410d63b7dSRichard Lowe 		if ((usr_include->hash.length == length) &&
285510d63b7dSRichard Lowe 		    IS_WEQUALN(usr_include_buf,
285610d63b7dSRichard Lowe 			       wcb,
285710d63b7dSRichard Lowe 			       length)) {
285810d63b7dSRichard Lowe 			directory = usr_include;
285910d63b7dSRichard Lowe 		} else if ((usr_include_sys->hash.length == length) &&
286010d63b7dSRichard Lowe 		           IS_WEQUALN(usr_include_sys_buf,
286110d63b7dSRichard Lowe 		                      wcb,
286210d63b7dSRichard Lowe 		                      length)) {
286310d63b7dSRichard Lowe 			directory = usr_include_sys;
286410d63b7dSRichard Lowe 		} else {
286510d63b7dSRichard Lowe 			directory = GETNAME(wcb, length);
286610d63b7dSRichard Lowe 		}
286710d63b7dSRichard Lowe 	}
286810d63b7dSRichard Lowe 	(void) read_dir(directory,
286910d63b7dSRichard Lowe 			(wchar_t *) NULL,
287010d63b7dSRichard Lowe 			(Property) NULL,
287110d63b7dSRichard Lowe 			(wchar_t *) NULL);
287210d63b7dSRichard Lowe }
287310d63b7dSRichard Lowe 
287410d63b7dSRichard Lowe /*
287510d63b7dSRichard Lowe  *	add_pattern_conditionals(target)
287610d63b7dSRichard Lowe  *
287710d63b7dSRichard Lowe  *	Scan the list of conditionals defined for pattern targets and add any
287810d63b7dSRichard Lowe  *	that match this target to its list of conditionals.
287910d63b7dSRichard Lowe  *
288010d63b7dSRichard Lowe  *	Parameters:
288110d63b7dSRichard Lowe  *		target		The target we should add conditionals for
288210d63b7dSRichard Lowe  *
288310d63b7dSRichard Lowe  *	Global variables used:
288410d63b7dSRichard Lowe  *		conditionals	The list of pattern conditionals
288510d63b7dSRichard Lowe  */
288610d63b7dSRichard Lowe static void
add_pattern_conditionals(Name target)2887*e7afc443SToomas Soome add_pattern_conditionals(Name target)
288810d63b7dSRichard Lowe {
2889*e7afc443SToomas Soome 	Property	conditional;
289010d63b7dSRichard Lowe 	Property		new_prop;
289110d63b7dSRichard Lowe 	Property		*previous;
289210d63b7dSRichard Lowe 	Name_rec		dummy;
289310d63b7dSRichard Lowe 	wchar_t			*pattern;
289410d63b7dSRichard Lowe 	wchar_t			*percent;
289510d63b7dSRichard Lowe 	int			length;
289610d63b7dSRichard Lowe 
289710d63b7dSRichard Lowe 	Wstring wcb(target);
289810d63b7dSRichard Lowe 	Wstring wcb1;
289910d63b7dSRichard Lowe 
290010d63b7dSRichard Lowe 	for (conditional = get_prop(conditionals->prop, conditional_prop);
290110d63b7dSRichard Lowe 	     conditional != NULL;
290210d63b7dSRichard Lowe 	     conditional = get_prop(conditional->next, conditional_prop)) {
290310d63b7dSRichard Lowe 		wcb1.init(conditional->body.conditional.target);
290410d63b7dSRichard Lowe 		pattern = wcb1.get_string();
290510d63b7dSRichard Lowe 		if (pattern[1] != 0) {
290610d63b7dSRichard Lowe 			percent = (wchar_t *) wcschr(pattern, (int) percent_char);
290767c3092cSAndrew Stormont 			/* Check for possible buffer under-read */
290867c3092cSAndrew Stormont 			if ((length = wcb.length()-wcslen(percent+1)) <= 0) {
290967c3092cSAndrew Stormont 				continue;
291067c3092cSAndrew Stormont 			}
291110d63b7dSRichard Lowe 			if (!wcb.equaln(pattern, percent-pattern) ||
291267c3092cSAndrew Stormont 			    !IS_WEQUAL(wcb.get_string(length), percent+1)) {
291310d63b7dSRichard Lowe 				continue;
291410d63b7dSRichard Lowe 			}
291510d63b7dSRichard Lowe 		}
291610d63b7dSRichard Lowe 		for (previous = &target->prop;
291710d63b7dSRichard Lowe 		     *previous != NULL;
291810d63b7dSRichard Lowe 		     previous = &(*previous)->next) {
291910d63b7dSRichard Lowe 			if (((*previous)->type == conditional_prop) &&
292010d63b7dSRichard Lowe 			    ((*previous)->body.conditional.sequence >
292110d63b7dSRichard Lowe 			     conditional->body.conditional.sequence)) {
292210d63b7dSRichard Lowe 				break;
292310d63b7dSRichard Lowe 			}
292410d63b7dSRichard Lowe 		}
292510d63b7dSRichard Lowe 		if (*previous == NULL) {
292610d63b7dSRichard Lowe 			new_prop = append_prop(target, conditional_prop);
292710d63b7dSRichard Lowe 		} else {
292810d63b7dSRichard Lowe 			dummy.prop = NULL;
292910d63b7dSRichard Lowe 			new_prop = append_prop(&dummy, conditional_prop);
293010d63b7dSRichard Lowe 			new_prop->next = *previous;
293110d63b7dSRichard Lowe 			*previous = new_prop;
293210d63b7dSRichard Lowe 		}
293310d63b7dSRichard Lowe 		target->conditional_cnt++;
293410d63b7dSRichard Lowe 		new_prop->body.conditional = conditional->body.conditional;
293510d63b7dSRichard Lowe 	}
293610d63b7dSRichard Lowe }
293710d63b7dSRichard Lowe 
293810d63b7dSRichard Lowe /*
293910d63b7dSRichard Lowe  *	set_locals(target, old_locals)
294010d63b7dSRichard Lowe  *
294110d63b7dSRichard Lowe  *	Sets any conditional macros for the target.
294210d63b7dSRichard Lowe  *	Each target carries a possibly empty set of conditional properties.
294310d63b7dSRichard Lowe  *
294410d63b7dSRichard Lowe  *	Parameters:
294510d63b7dSRichard Lowe  *		target		The target to set conditional macros for
294610d63b7dSRichard Lowe  *		old_locals	Space to store old values in
294710d63b7dSRichard Lowe  *
294810d63b7dSRichard Lowe  *	Global variables used:
294910d63b7dSRichard Lowe  *		debug_level	Should we trace activity?
295010d63b7dSRichard Lowe  *		is_conditional	We need to preserve this value
295110d63b7dSRichard Lowe  *		recursion_level	Used for tracing
295210d63b7dSRichard Lowe  */
295310d63b7dSRichard Lowe void
set_locals(Name target,Property old_locals)2954*e7afc443SToomas Soome set_locals(Name target, Property old_locals)
295510d63b7dSRichard Lowe {
2956*e7afc443SToomas Soome 	Property	conditional;
2957*e7afc443SToomas Soome 	int		i;
2958*e7afc443SToomas Soome 	Boolean	saved_conditional_macro_used;
295910d63b7dSRichard Lowe 	Chain			cond_name;
296010d63b7dSRichard Lowe 	Chain			cond_chain;
296110d63b7dSRichard Lowe 
296210d63b7dSRichard Lowe 	if (target->dont_activate_cond_values) {
296310d63b7dSRichard Lowe 		return;
296410d63b7dSRichard Lowe 	}
296510d63b7dSRichard Lowe 
296610d63b7dSRichard Lowe 	saved_conditional_macro_used = conditional_macro_used;
296710d63b7dSRichard Lowe 
296810d63b7dSRichard Lowe 	/* Scan the list of conditional properties and apply each one */
296910d63b7dSRichard Lowe 	for (conditional = get_prop(target->prop, conditional_prop), i = 0;
297010d63b7dSRichard Lowe 	     conditional != NULL;
297110d63b7dSRichard Lowe 	     conditional = get_prop(conditional->next, conditional_prop),
297210d63b7dSRichard Lowe 	     i++) {
297310d63b7dSRichard Lowe 		/* Save the old value */
297410d63b7dSRichard Lowe 		old_locals[i].body.macro =
297510d63b7dSRichard Lowe 		  maybe_append_prop(conditional->body.conditional.name,
297610d63b7dSRichard Lowe 				    macro_prop)->body.macro;
297710d63b7dSRichard Lowe 		if (debug_level > 1) {
297810d63b7dSRichard Lowe 			(void) printf(gettext("%*sActivating conditional value: "),
297910d63b7dSRichard Lowe 				      recursion_level,
298010d63b7dSRichard Lowe 				      "");
298110d63b7dSRichard Lowe 		}
298210d63b7dSRichard Lowe 		/* Set the conditional value. Macros are expanded when the */
298310d63b7dSRichard Lowe 		/* macro is refd as usual */
298410d63b7dSRichard Lowe 		if ((conditional->body.conditional.name != virtual_root) ||
298510d63b7dSRichard Lowe 		    (conditional->body.conditional.value != virtual_root)) {
298610d63b7dSRichard Lowe 			(void) SETVAR(conditional->body.conditional.name,
298710d63b7dSRichard Lowe 				      conditional->body.conditional.value,
298810d63b7dSRichard Lowe 				      (Boolean) conditional->body.conditional.append);
298910d63b7dSRichard Lowe 		}
299010d63b7dSRichard Lowe 		cond_name = ALLOC(Chain);
299110d63b7dSRichard Lowe 		cond_name->name = conditional->body.conditional.name;
299210d63b7dSRichard Lowe 	}
299310d63b7dSRichard Lowe 	/* Put this target on the front of the chain of conditional targets */
299410d63b7dSRichard Lowe 	cond_chain = ALLOC(Chain);
299510d63b7dSRichard Lowe 	cond_chain->name = target;
299610d63b7dSRichard Lowe 	cond_chain->next = conditional_targets;
299710d63b7dSRichard Lowe 	conditional_targets = cond_chain;
299810d63b7dSRichard Lowe 	conditional_macro_used = saved_conditional_macro_used;
299910d63b7dSRichard Lowe }
300010d63b7dSRichard Lowe 
300110d63b7dSRichard Lowe /*
300210d63b7dSRichard Lowe  *	reset_locals(target, old_locals, conditional, index)
300310d63b7dSRichard Lowe  *
300410d63b7dSRichard Lowe  *	Removes any conditional macros for the target.
300510d63b7dSRichard Lowe  *
300610d63b7dSRichard Lowe  *	Parameters:
300710d63b7dSRichard Lowe  *		target		The target we are retoring values for
300810d63b7dSRichard Lowe  *		old_locals	The values to restore
300910d63b7dSRichard Lowe  *		conditional	The first conditional block for the target
301010d63b7dSRichard Lowe  *		index		into the old_locals vector
301110d63b7dSRichard Lowe  *	Global variables used:
301210d63b7dSRichard Lowe  *		debug_level	Should we trace activities?
301310d63b7dSRichard Lowe  *		recursion_level	Used for tracing
301410d63b7dSRichard Lowe  */
301510d63b7dSRichard Lowe void
reset_locals(Name target,Property old_locals,Property conditional,int index)3016*e7afc443SToomas Soome reset_locals(Name target, Property old_locals, Property conditional, int index)
301710d63b7dSRichard Lowe {
3018*e7afc443SToomas Soome 	Property	this_conditional;
301910d63b7dSRichard Lowe 	Chain			cond_chain;
302010d63b7dSRichard Lowe 
302110d63b7dSRichard Lowe 	if (target->dont_activate_cond_values) {
302210d63b7dSRichard Lowe 		return;
302310d63b7dSRichard Lowe 	}
302410d63b7dSRichard Lowe 
302510d63b7dSRichard Lowe 	/* Scan the list of conditional properties and restore the old value */
302610d63b7dSRichard Lowe 	/* to each one Reverse the order relative to when we assigned macros */
302710d63b7dSRichard Lowe 	this_conditional = get_prop(conditional->next, conditional_prop);
302810d63b7dSRichard Lowe 	if (this_conditional != NULL) {
302910d63b7dSRichard Lowe 		reset_locals(target, old_locals, this_conditional, index+1);
303010d63b7dSRichard Lowe 	} else {
303110d63b7dSRichard Lowe 		/* Remove conditional target from chain */
303210d63b7dSRichard Lowe 		if (conditional_targets == NULL ||
303310d63b7dSRichard Lowe 		    conditional_targets->name != target) {
303410d63b7dSRichard Lowe 			warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
303510d63b7dSRichard Lowe 		} else {
303610d63b7dSRichard Lowe 			cond_chain = conditional_targets->next;
303710d63b7dSRichard Lowe 			retmem_mb((caddr_t) conditional_targets);
303810d63b7dSRichard Lowe 			conditional_targets = cond_chain;
303910d63b7dSRichard Lowe 		}
304010d63b7dSRichard Lowe 	}
304110d63b7dSRichard Lowe 	get_prop(conditional->body.conditional.name->prop,
304210d63b7dSRichard Lowe 		 macro_prop)->body.macro = old_locals[index].body.macro;
304310d63b7dSRichard Lowe 	if (conditional->body.conditional.name == virtual_root) {
304410d63b7dSRichard Lowe 		(void) SETVAR(virtual_root, getvar(virtual_root), false);
304510d63b7dSRichard Lowe 	}
304610d63b7dSRichard Lowe 	if (debug_level > 1) {
304710d63b7dSRichard Lowe 		if (old_locals[index].body.macro.value != NULL) {
304810d63b7dSRichard Lowe 			(void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
304910d63b7dSRichard Lowe 				      recursion_level,
305010d63b7dSRichard Lowe 				      "",
305110d63b7dSRichard Lowe 				      conditional->body.conditional.name->
305210d63b7dSRichard Lowe 				      string_mb,
305310d63b7dSRichard Lowe 				      old_locals[index].body.macro.value->
305410d63b7dSRichard Lowe 				      string_mb);
305510d63b7dSRichard Lowe 		} else {
305610d63b7dSRichard Lowe 			(void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
305710d63b7dSRichard Lowe 				      recursion_level,
305810d63b7dSRichard Lowe 				      "",
305910d63b7dSRichard Lowe 				      conditional->body.conditional.name->
306010d63b7dSRichard Lowe 				      string_mb);
306110d63b7dSRichard Lowe 		}
306210d63b7dSRichard Lowe 	}
306310d63b7dSRichard Lowe }
306410d63b7dSRichard Lowe 
306510d63b7dSRichard Lowe /*
306610d63b7dSRichard Lowe  *	check_auto_dependencies(target, auto_count, automatics)
306710d63b7dSRichard Lowe  *
306810d63b7dSRichard Lowe  *	Returns true if the target now has a dependency
306910d63b7dSRichard Lowe  *	it didn't previously have (saved on automatics).
307010d63b7dSRichard Lowe  *
307110d63b7dSRichard Lowe  *	Return value:
307210d63b7dSRichard Lowe  *				true if new dependency found
307310d63b7dSRichard Lowe  *
307410d63b7dSRichard Lowe  *	Parameters:
307510d63b7dSRichard Lowe  *		target		Target we check
307610d63b7dSRichard Lowe  *		auto_count	Number of old automatic vars
307710d63b7dSRichard Lowe  *		automatics	Saved old automatics
307810d63b7dSRichard Lowe  *
307910d63b7dSRichard Lowe  *	Global variables used:
308010d63b7dSRichard Lowe  *		keep_state	Indicates that .KEEP_STATE is on
308110d63b7dSRichard Lowe  */
308210d63b7dSRichard Lowe Boolean
check_auto_dependencies(Name target,int auto_count,Name * automatics)308310d63b7dSRichard Lowe check_auto_dependencies(Name target, int auto_count, Name *automatics)
308410d63b7dSRichard Lowe {
308510d63b7dSRichard Lowe 	Name		*p;
308610d63b7dSRichard Lowe 	int		n;
308710d63b7dSRichard Lowe 	Property	line;
308810d63b7dSRichard Lowe 	Dependency	dependency;
308910d63b7dSRichard Lowe 
309010d63b7dSRichard Lowe 	if (keep_state) {
309110d63b7dSRichard Lowe 		if ((line = get_prop(target->prop, line_prop)) == NULL) {
309210d63b7dSRichard Lowe 			return false;
309310d63b7dSRichard Lowe 		}
309410d63b7dSRichard Lowe 		/* Go thru new list of automatic depes */
309510d63b7dSRichard Lowe 		for (dependency = line->body.line.dependencies;
309610d63b7dSRichard Lowe 		     dependency != NULL;
309710d63b7dSRichard Lowe 		     dependency = dependency->next) {
309810d63b7dSRichard Lowe 			/* And make sure that each one existed before we */
309910d63b7dSRichard Lowe 			/* built the target */
310010d63b7dSRichard Lowe 			if (dependency->automatic && !dependency->stale) {
310110d63b7dSRichard Lowe 				for (n = auto_count, p = automatics;
310210d63b7dSRichard Lowe 				     n > 0;
310310d63b7dSRichard Lowe 				     n--) {
310410d63b7dSRichard Lowe 					if (*p++ == dependency->name) {
310510d63b7dSRichard Lowe 						/* If we can find it on the */
310610d63b7dSRichard Lowe 						/* saved list of autos we */
310710d63b7dSRichard Lowe 						/* are OK  */
310810d63b7dSRichard Lowe 						goto not_new;
310910d63b7dSRichard Lowe 					}
311010d63b7dSRichard Lowe 				}
311110d63b7dSRichard Lowe 				/* But if we scan over the old list */
311210d63b7dSRichard Lowe 				/* of auto. without finding it it is */
311310d63b7dSRichard Lowe 				/* new and we must check it */
311410d63b7dSRichard Lowe 				return true;
311510d63b7dSRichard Lowe 			}
311610d63b7dSRichard Lowe 		not_new:;
311710d63b7dSRichard Lowe 		}
311810d63b7dSRichard Lowe 		return false;
311910d63b7dSRichard Lowe 	} else {
312010d63b7dSRichard Lowe 		return false;
312110d63b7dSRichard Lowe 	}
312210d63b7dSRichard Lowe }
312310d63b7dSRichard Lowe 
312410d63b7dSRichard Lowe 
312510d63b7dSRichard Lowe // Recursively delete each of the Chain struct on the chain.
312610d63b7dSRichard Lowe 
312710d63b7dSRichard Lowe static void
delete_query_chain(Chain ch)312810d63b7dSRichard Lowe delete_query_chain(Chain ch)
312910d63b7dSRichard Lowe {
313010d63b7dSRichard Lowe 	if (ch == NULL) {
313110d63b7dSRichard Lowe 		return;
313210d63b7dSRichard Lowe 	} else {
313310d63b7dSRichard Lowe 		delete_query_chain(ch->next);
313410d63b7dSRichard Lowe 		retmem_mb((char *) ch);
313510d63b7dSRichard Lowe 	}
313610d63b7dSRichard Lowe }
313710d63b7dSRichard Lowe 
313810d63b7dSRichard Lowe Doname
target_can_be_built(Name target)3139*e7afc443SToomas Soome target_can_be_built(Name target) {
314010d63b7dSRichard Lowe 	Doname		result = build_dont_know;
314110d63b7dSRichard Lowe 	Name		true_target = target;
314210d63b7dSRichard Lowe 	Property	line;
314310d63b7dSRichard Lowe 
314410d63b7dSRichard Lowe 	if (target == wait_name) {
314510d63b7dSRichard Lowe 		return(build_ok);
314610d63b7dSRichard Lowe 	}
314710d63b7dSRichard Lowe 	/*
314810d63b7dSRichard Lowe 	 * If the target is a constructed one for a "::" target,
314910d63b7dSRichard Lowe 	 * we need to consider that.
315010d63b7dSRichard Lowe 	 */
315110d63b7dSRichard Lowe 	if (target->has_target_prop) {
315210d63b7dSRichard Lowe 		true_target = get_prop(target->prop,
315310d63b7dSRichard Lowe 				       target_prop)->body.target.target;
315410d63b7dSRichard Lowe 	}
315510d63b7dSRichard Lowe 
315610d63b7dSRichard Lowe 	(void) exists(true_target);
315710d63b7dSRichard Lowe 
315810d63b7dSRichard Lowe 	if (true_target->state == build_running) {
315910d63b7dSRichard Lowe 		return(build_running);
316010d63b7dSRichard Lowe 	}
316110d63b7dSRichard Lowe 	if (true_target->stat.time != file_doesnt_exist) {
316210d63b7dSRichard Lowe 		result = build_ok;
316310d63b7dSRichard Lowe 	}
316410d63b7dSRichard Lowe 
316510d63b7dSRichard Lowe 	/* get line property for the target */
316610d63b7dSRichard Lowe 	line = get_prop(true_target->prop, line_prop);
316710d63b7dSRichard Lowe 
316810d63b7dSRichard Lowe 	/* first check for explicit rule */
316910d63b7dSRichard Lowe 	if (line != NULL && line->body.line.command_template != NULL) {
317010d63b7dSRichard Lowe 		result = build_ok;
317110d63b7dSRichard Lowe 	}
317210d63b7dSRichard Lowe 	/* try to find pattern rule */
317310d63b7dSRichard Lowe 	if (result == build_dont_know) {
317410d63b7dSRichard Lowe 		result = find_percent_rule(target, NULL, false);
317510d63b7dSRichard Lowe 	}
317648bbca81SDaniel Hoffman 
317710d63b7dSRichard Lowe 	/* try to find double suffix rule */
317810d63b7dSRichard Lowe 	if (result == build_dont_know) {
317910d63b7dSRichard Lowe 		if (target->is_member) {
318010d63b7dSRichard Lowe 			Property member = get_prop(target->prop, member_prop);
318110d63b7dSRichard Lowe 			if (member != NULL && member->body.member.member != NULL) {
318210d63b7dSRichard Lowe 				result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
318310d63b7dSRichard Lowe 			} else {
318410d63b7dSRichard Lowe 				result = find_double_suffix_rule(target, NULL, false);
318510d63b7dSRichard Lowe 			}
318610d63b7dSRichard Lowe 		} else {
318710d63b7dSRichard Lowe 			result = find_double_suffix_rule(target, NULL, false);
318810d63b7dSRichard Lowe 		}
318910d63b7dSRichard Lowe 	}
319048bbca81SDaniel Hoffman 
319110d63b7dSRichard Lowe 	/* try to find suffix rule */
319210d63b7dSRichard Lowe 	if ((result == build_dont_know) && second_pass) {
319310d63b7dSRichard Lowe 		result = find_suffix_rule(target, target, empty_name, NULL, false);
319410d63b7dSRichard Lowe 	}
319548bbca81SDaniel Hoffman 
319610d63b7dSRichard Lowe 	/* check for sccs */
319710d63b7dSRichard Lowe 	if (result == build_dont_know) {
319810d63b7dSRichard Lowe 		result = sccs_get(target, NULL);
319910d63b7dSRichard Lowe 	}
320048bbca81SDaniel Hoffman 
320110d63b7dSRichard Lowe 	/* try to find dyn target */
320210d63b7dSRichard Lowe 	if (result == build_dont_know) {
320310d63b7dSRichard Lowe 		Name dtarg = find_dyntarget(target);
320410d63b7dSRichard Lowe 		if (dtarg != NULL) {
320510d63b7dSRichard Lowe 			result = target_can_be_built(dtarg);
320610d63b7dSRichard Lowe 		}
320710d63b7dSRichard Lowe 	}
320848bbca81SDaniel Hoffman 
320910d63b7dSRichard Lowe 	/* check whether target was mentioned in makefile */
321010d63b7dSRichard Lowe 	if (result == build_dont_know) {
321110d63b7dSRichard Lowe 		if (target->colons != no_colon) {
321210d63b7dSRichard Lowe 			result = build_ok;
321310d63b7dSRichard Lowe 		}
321410d63b7dSRichard Lowe 	}
321510d63b7dSRichard Lowe 
321610d63b7dSRichard Lowe 	/* result */
321710d63b7dSRichard Lowe 	return result;
321810d63b7dSRichard Lowe }
3219