1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright (c) 2016 by Delphix. All rights reserved.
26 * Copyright 2019 RackTop Systems.
27 */
28
29/*
30 *	doname.c
31 *
32 *	Figure out which targets are out of date and rebuild them
33 */
34
35/*
36 * Included files
37 */
38#include <alloca.h>		/* alloca() */
39#include <fcntl.h>
40#include <mk/defs.h>
41#include <mksh/i18n.h>		/* get_char_semantics_value() */
42#include <mksh/macro.h>		/* getvar(), expand_value() */
43#include <mksh/misc.h>		/* getmem() */
44#include <poll.h>
45#include <libintl.h>
46#include <signal.h>
47#include <stropts.h>
48#include <sys/errno.h>
49#include <sys/stat.h>
50#include <sys/types.h>
51#include <sys/utsname.h>	/* uname() */
52#include <sys/wait.h>
53#include <unistd.h>		/* close() */
54
55/*
56 * Defined macros
57 */
58#	define LOCALHOST "localhost"
59
60#define MAXRULES 100
61
62// Sleep for .1 seconds between stat()'s
63const int	STAT_RETRY_SLEEP_TIME = 100000;
64
65/*
66 * typedefs & structs
67 */
68
69/*
70 * Static variables
71 */
72static char	hostName[MAXNAMELEN] = "";
73static char	userName[MAXNAMELEN] = "";
74
75
76static int	second_pass = 0;
77
78/*
79 * File table of contents
80 */
81extern	Doname		doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
82extern	Doname		doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic);
83static	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);
84void		dynamic_dependencies(Name target);
85static	Doname		run_command(register Property line, Boolean print_machine);
86extern	Doname		execute_serial(Property line);
87extern	Name		vpath_translation(register Name cmd);
88extern	void		check_state(Name temp_file_name);
89static	void		read_dependency_file(register Name filename);
90static	void		check_read_state_file(void);
91static	void		do_assign(register Name line, register Name target);
92static	void		build_command_strings(Name target, register Property line);
93static	Doname		touch_command(register Property line, register Name target, Doname result);
94extern	void		update_target(Property line, Doname result);
95static	Doname		sccs_get(register Name target, register Property *command);
96extern	void		read_directory_of_file(register Name file);
97static	void		add_pattern_conditionals(register Name target);
98extern	void		set_locals(register Name target, register Property old_locals);
99extern	void		reset_locals(register Name target, register Property old_locals, register Property conditional, register int index);
100extern	Boolean		check_auto_dependencies(Name target, int auto_count, Name *automatics);
101static	void		delete_query_chain(Chain ch);
102
103// From read2.cc
104extern	Name		normalize_name(register wchar_t *name_string, register int length);
105
106
107
108/*
109 * DONE.
110 *
111 *	doname_check(target, do_get, implicit, automatic)
112 *
113 *	Will call doname() and then inspect the return value
114 *
115 *	Return value:
116 *				Indication if the build failed or not
117 *
118 *	Parameters:
119 *		target		The target to build
120 *		do_get		Passed thru to doname()
121 *		implicit	Passed thru to doname()
122 *		automatic	Are we building a hidden dependency?
123 *
124 *	Global variables used:
125 *		build_failed_seen	Set if -k is on and error occurs
126 *		continue_after_error	Indicates that -k is on
127 *		report_dependencies	No error msg if -P is on
128 */
129Doname
130doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
131{
132	int first_time = 1;
133	Doname rv = build_failed;
134
135	(void) fflush(stdout);
136try_again:
137	switch (doname(target, do_get, implicit, automatic)) {
138	case build_ok:
139		second_pass = 0;
140		rv = build_ok;
141		break;
142	case build_running:
143		second_pass = 0;
144		rv = build_running;
145		break;
146	case build_failed:
147		if (!continue_after_error) {
148			fatal(
149			    gettext("Target `%s' not remade because of errors"),
150			    target->string_mb);
151		}
152		build_failed_seen = true;
153		second_pass = 0;
154		rv = build_failed;
155		break;
156	case build_dont_know:
157		/*
158		 * If we can't figure out how to build an automatic
159		 * (hidden) dependency, we just ignore it.
160		 * We later declare the target to be out of date just in
161		 * case something changed.
162		 * Also, don't complain if just reporting the dependencies
163		 * and not building anything.
164		 */
165		if (automatic || (report_dependencies_level > 0)) {
166			second_pass = 0;
167			rv = build_dont_know;
168			break;
169		}
170		if(first_time) {
171			first_time = 0;
172			second_pass = 1;
173			goto try_again;
174		}
175		second_pass = 0;
176		if (continue_after_error && !svr4) {
177			warning(gettext("Don't know how to make target `%s'"),
178				target->string_mb);
179			build_failed_seen = true;
180			rv = build_failed;
181			break;
182		}
183		fatal(gettext("Don't know how to make target `%s'"),
184		    target->string_mb);
185		break;
186	}
187	return (rv);
188}
189
190
191void
192enter_explicit_rule_from_dynamic_rule(Name target, Name source)
193{
194	Property line, source_line;
195	Dependency dependency;
196
197	source_line = get_prop(source->prop, line_prop);
198	line = maybe_append_prop(target, line_prop);
199	line->body.line.sccs_command = false;
200	line->body.line.target = target;
201	if (line->body.line.command_template == NULL) {
202		line->body.line.command_template = source_line->body.line.command_template;
203		for (dependency = source_line->body.line.dependencies;
204		     dependency != NULL;
205		     dependency = dependency->next) {
206			enter_dependency(line, dependency->name, false);
207		}
208		line->body.line.less = target;
209	}
210	line->body.line.percent = NULL;
211}
212
213
214
215Name
216find_dyntarget(Name target)
217{
218	Dyntarget		p;
219	int			i;
220	String_rec		string;
221	wchar_t			buffer[STRING_BUFFER_LENGTH];
222	wchar_t			*pp, * bufend;
223	wchar_t			tbuffer[MAXPATHLEN];
224	Wstring			wcb(target);
225
226	for (p = dyntarget_list; p != NULL; p = p->next) {
227		INIT_STRING_FROM_STACK(string, buffer);
228		expand_value(p->name, &string, false);
229		i = 0;
230		pp = string.buffer.start;
231		bufend = pp + STRING_BUFFER_LENGTH;
232		while((*pp != nul_char) && (pp < bufend)) {
233			if(iswspace(*pp)) {
234				tbuffer[i] = nul_char;
235				if(i > 0) {
236					if (wcb.equal(tbuffer)) {
237						enter_explicit_rule_from_dynamic_rule(target, p->name);
238						return(target);
239					}
240				}
241				pp++;
242				i = 0;
243				continue;
244			}
245			tbuffer[i] = *pp;
246			i++;
247			pp++;
248			if(*pp == nul_char) {
249				tbuffer[i] = nul_char;
250				if(i > 0) {
251					if (wcb.equal(tbuffer)) {
252						enter_explicit_rule_from_dynamic_rule(target, p->name);
253						return(target);
254					}
255				}
256				break;
257			}
258		}
259	}
260	return(NULL);
261}
262
263/*
264 * DONE.
265 *
266 *	doname(target, do_get, implicit)
267 *
268 *	Chases all files the target depends on and builds any that
269 *	are out of date. If the target is out of date it is then rebuilt.
270 *
271 *	Return value:
272 *				Indiates if build failed or nt
273 *
274 *	Parameters:
275 *		target		Target to build
276 *		do_get		Run sccs get is nessecary
277 *		implicit	doname is trying to find an implicit rule
278 *
279 *	Global variables used:
280 *		assign_done	True if command line assgnment has happened
281 *		commands_done	Preserved for the case that we need local value
282 *		debug_level	Should we trace make's actions?
283 *		default_rule	The rule for ".DEFAULT", used as last resort
284 *		empty_name	The Name "", used when looking for single sfx
285 *		keep_state	Indicates that .KEEP_STATE is on
286 *		parallel	True if building in parallel
287 *		recursion_level	Used for tracing
288 *		report_dependencies make -P is on
289 */
290Doname
291doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic)
292{
293	Doname			result = build_dont_know;
294	Chain			out_of_date_list = NULL;
295	Chain			target_group;
296	Property		old_locals = NULL;
297	register Property	line;
298	Property		command = NULL;
299	register Dependency	dependency;
300	Name			less = NULL;
301	Name			true_target = target;
302	Name			*automatics = NULL;
303	register int		auto_count;
304	Boolean			rechecking_target = false;
305	Boolean			saved_commands_done;
306	Boolean			restart = false;
307	Boolean			save_parallel = parallel;
308	Boolean			doing_subtree = false;
309
310	Boolean			recheck_conditionals = false;
311
312	if (target->state == build_running) {
313		return build_running;
314	}
315	line = get_prop(target->prop, line_prop);
316	if (line != NULL) {
317		/*
318		 * If this target is a member of target group and one of the
319		 * other members of the group is running, mark this target
320		 * as running.
321		 */
322		for (target_group = line->body.line.target_group;
323		     target_group != NULL;
324		     target_group = target_group->next) {
325			if (is_running(target_group->name)) {
326				target->state = build_running;
327				add_pending(target,
328					    recursion_level,
329					    do_get,
330					    implicit,
331					    false);
332				return build_running;
333			}
334		}
335	}
336	/*
337	 * If the target is a constructed one for a "::" target,
338	 * we need to consider that.
339	 */
340	if (target->has_target_prop) {
341		true_target = get_prop(target->prop,
342				       target_prop)->body.target.target;
343		if (true_target->colon_splits > 0) {
344			/* Make sure we have a valid time for :: targets */
345			Property        time;
346
347			time = get_prop(true_target->prop, time_prop);
348			if (time != NULL) {
349				true_target->stat.time = time->body.time.time;
350			}
351		}
352	}
353	(void) exists(true_target);
354	/*
355	 * If the target has been processed, we don't need to do it again,
356	 * unless it depends on conditional macros or a delayed assignment,
357	 * or it has been done when KEEP_STATE is on.
358	 */
359	if (target->state == build_ok) {
360		if((!keep_state || (!target->depends_on_conditional && !assign_done))) {
361			return build_ok;
362		} else {
363			recheck_conditionals = true;
364		}
365	}
366	if (target->state == build_subtree) {
367		/* A dynamic macro subtree is being built */
368		target->state = build_dont_know;
369		doing_subtree = true;
370		if (!target->checking_subtree) {
371			/*
372			 * This target has been started before and therefore
373			 * not all dependencies have to be built.
374			 */
375			restart = true;
376		}
377	} else if (target->state == build_pending) {
378		target->state = build_dont_know;
379		restart = true;
380/*
381	} else if (parallel &&
382		   keep_state &&
383		   (target->conditional_cnt > 0)) {
384	    if (!parallel_ok(target, false)) {
385		add_subtree(target, recursion_level, do_get, implicit);
386		target->state = build_running;
387		return build_running;
388	    }
389 */
390	}
391	/*
392	 * If KEEP_STATE is on, we have to rebuild the target if the
393	 * building of it caused new automatic dependencies to be reported.
394	 * This is where we restart the build.
395	 */
396	if (line != NULL) {
397		line->body.line.percent = NULL;
398	}
399recheck_target:
400	/* Init all local variables */
401	result = build_dont_know;
402	out_of_date_list = NULL;
403	command = NULL;
404	less = NULL;
405	auto_count = 0;
406	if (!restart && line != NULL) {
407		/*
408		 * If this target has never been built before, mark all
409		 * of the dependencies as never built.
410		 */
411		for (dependency = line->body.line.dependencies;
412		     dependency != NULL;
413		     dependency = dependency->next) {
414			dependency->built = false;
415		}
416	}
417	/* Save the set of automatic depes defined for this target */
418	if (keep_state &&
419	    (line != NULL) &&
420	    (line->body.line.dependencies != NULL)) {
421		Name *p;
422
423		/*
424		 * First run thru the dependency list to see how many
425		 * autos there are.
426		 */
427		for (dependency = line->body.line.dependencies;
428		     dependency != NULL;
429		     dependency = dependency->next) {
430			if (dependency->automatic && !dependency->stale) {
431				auto_count++;
432			}
433		}
434		/* Create vector to hold the current autos */
435		automatics =
436		  (Name *) alloca((int) (auto_count * sizeof (Name)));
437		/* Copy them */
438		for (p = automatics, dependency = line->body.line.dependencies;
439		     dependency != NULL;
440		     dependency = dependency->next) {
441			if (dependency->automatic && !dependency->stale) {
442				*p++ = dependency->name;
443			}
444		}
445	}
446	if (debug_level > 1) {
447		(void) printf("%*sdoname(%s)\n",
448			      recursion_level,
449			      "",
450			      target->string_mb);
451	}
452	recursion_level++;
453	/* Avoid infinite loops */
454	if (target->state == build_in_progress) {
455		warning(gettext("Infinite loop: Target `%s' depends on itself"),
456			target->string_mb);
457		return build_ok;
458	}
459	target->state = build_in_progress;
460
461	/* Activate conditional macros for the target */
462	if (!target->added_pattern_conditionals) {
463		add_pattern_conditionals(target);
464		target->added_pattern_conditionals = true;
465	}
466	if (target->conditional_cnt > 0) {
467		old_locals = (Property) alloca(target->conditional_cnt *
468					       sizeof (Property_rec));
469		set_locals(target, old_locals);
470	}
471
472/*
473 * after making the call to dynamic_dependecies unconditional we can handle
474 * target names that are same as file name. In this case $$@ in the
475 * dependencies did not mean anything. WIth this change it expands it
476 * as expected.
477 */
478	if (!target->has_depe_list_expanded)
479	{
480		dynamic_dependencies(target);
481	}
482
483/*
484 *	FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT
485 *	COMMANDS TO RUN
486 */
487	if ((line = get_prop(target->prop, line_prop)) != NULL) {
488		if (check_dependencies(&result,
489				       line,
490				       do_get,
491				       target,
492				       true_target,
493				       doing_subtree,
494				       &out_of_date_list,
495				       old_locals,
496				       implicit,
497				       &command,
498				       less,
499				       rechecking_target,
500				       recheck_conditionals)) {
501			return build_running;
502		}
503		if (line->body.line.query != NULL) {
504			delete_query_chain(line->body.line.query);
505		}
506		line->body.line.query = out_of_date_list;
507	}
508
509
510/*
511 * If the target is a :: type, do not try to find the rule for the target,
512 * all actions will be taken by separate branches.
513 * Else, we try to find an implicit rule using various methods,
514 * we quit as soon as one is found.
515 *
516 * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target
517 * being rechecked - the target is being rechecked means that it already
518 * has explicit dependencies derived from an implicit rule found
519 * in previous step.
520 */
521	if (target->colon_splits == 0 && !rechecking_target) {
522		/* Look for percent matched rule */
523		if ((result == build_dont_know) &&
524		    (command == NULL)) {
525			switch (find_percent_rule(
526					target,
527					&command,
528					recheck_conditionals)) {
529			case build_failed:
530				result = build_failed;
531				break;
532			case build_running:
533				target->state = build_running;
534				add_pending(target,
535					    --recursion_level,
536					    do_get,
537					    implicit,
538					    false);
539				if (target->conditional_cnt > 0) {
540					reset_locals(target,
541						     old_locals,
542						     get_prop(target->prop,
543							     conditional_prop),
544						     0);
545				}
546				return build_running;
547			case build_ok:
548				result = build_ok;
549				break;
550			}
551		}
552		/* Look for double suffix rule */
553		if (result == build_dont_know) {
554			Property member;
555
556			if (target->is_member &&
557			    ((member = get_prop(target->prop, member_prop)) !=
558			     NULL)) {
559			        switch (find_ar_suffix_rule(target,
560						member->body.
561						member.member,
562						&command,
563						recheck_conditionals)) {
564				case build_failed:
565					result = build_failed;
566					break;
567				case build_running:
568					target->state = build_running;
569					add_pending(target,
570						    --recursion_level,
571						    do_get,
572						    implicit,
573						    false);
574				    if (target->conditional_cnt > 0) {
575					    reset_locals(target,
576							 old_locals,
577							 get_prop(target->prop,
578							     conditional_prop),
579							 0);
580				    }
581					return build_running;
582				default:
583					/* ALWAYS bind $% for old style */
584					/* ar rules */
585					if (line == NULL) {
586						line =
587						  maybe_append_prop(target,
588								    line_prop);
589					}
590					line->body.line.percent =
591					  member->body.member.member;
592					break;
593				}
594			} else {
595				switch (find_double_suffix_rule(target,
596						&command,
597						recheck_conditionals)) {
598				case build_failed:
599					result = build_failed;
600					break;
601				case build_running:
602					target->state = build_running;
603					add_pending(target,
604						    --recursion_level,
605						    do_get,
606						    implicit,
607						    false);
608					if (target->conditional_cnt > 0) {
609						reset_locals(target,
610							     old_locals,
611							     get_prop(target->
612								      prop,
613								      conditional_prop),
614							     0);
615					}
616					return build_running;
617				}
618			}
619		}
620		/* Look for single suffix rule */
621
622/* /tolik/
623 * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules.
624 * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc"
625 */
626/* /tolik, 06.21.96/
627 * Regression! See BugId 1255360
628 * If more than one percent rules are defined for the same target then
629 * the behaviour of 'make' with my previous fix may be different from one
630 * of the 'old make'.
631 * The global variable second_pass (maybe it should be an argument to doname())
632 * is intended to avoid this regression. It is set in doname_check().
633 * First, 'make' will work as it worked before. Only when it is
634 * going to say "don't know how to make target" it sets second_pass to true and
635 * run 'doname' again but now trying to use Single Suffix Rules.
636 */
637		if ((result == build_dont_know) && !automatic && (!implicit || second_pass) &&
638		    ((line == NULL) ||
639		     ((line->body.line.target != NULL) &&
640		      !line->body.line.target->has_regular_dependency))) {
641			switch (find_suffix_rule(target,
642						 target,
643						 empty_name,
644						 &command,
645						 recheck_conditionals)) {
646			case build_failed:
647				result = build_failed;
648				break;
649			case build_running:
650				target->state = build_running;
651				add_pending(target,
652					    --recursion_level,
653					    do_get,
654					    implicit,
655					    false);
656				if (target->conditional_cnt > 0) {
657					reset_locals(target,
658						     old_locals,
659						     get_prop(target->prop,
660							     conditional_prop),
661						     0);
662				}
663				return build_running;
664			}
665		}
666		/* Try to sccs get */
667		if ((command == NULL) &&
668		    (result == build_dont_know) &&
669		    do_get) {
670			result = sccs_get(target, &command);
671		}
672
673		/* Use .DEFAULT rule if it is defined. */
674		if ((command == NULL) &&
675		    (result == build_dont_know) &&
676		    (true_target->colons == no_colon) &&
677		    default_rule &&
678		    !implicit) {
679			/* Make sure we have a line prop */
680			line = maybe_append_prop(target, line_prop);
681			command = line;
682			Boolean out_of_date;
683			if (true_target->is_member) {
684				out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
685									line->body.line.dependency_time);
686			} else {
687				out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
688								    line->body.line.dependency_time);
689			}
690			if (build_unconditional || out_of_date) {
691				line->body.line.is_out_of_date = true;
692				if (debug_level > 0) {
693					(void) printf(gettext("%*sBuilding %s using .DEFAULT because it is out of date\n"),
694						      recursion_level,
695						      "",
696						      true_target->string_mb);
697				}
698			}
699			line->body.line.sccs_command = false;
700			line->body.line.command_template = default_rule;
701			line->body.line.target = true_target;
702			line->body.line.star = NULL;
703			line->body.line.less = true_target;
704			line->body.line.percent = NULL;
705		}
706	}
707
708	/* We say "target up to date" if no cmd were executed for the target */
709	if (!target->is_double_colon_parent) {
710		commands_done = false;
711	}
712
713	silent = silent_all;
714	ignore_errors = ignore_errors_all;
715	if  (posix)
716	{
717	  if  (!silent)
718	  {
719            silent = (Boolean) target->silent_mode;
720	  }
721	  if  (!ignore_errors)
722	  {
723            ignore_errors = (Boolean) target->ignore_error_mode;
724	  }
725	}
726
727	int doname_dyntarget = 0;
728r_command:
729	/* Run commands if any. */
730	if ((command != NULL) &&
731	    (command->body.line.command_template != NULL)) {
732		if (result != build_failed) {
733			result = run_command(command,
734					     (Boolean) ((parallel || save_parallel) && !silent));
735		}
736		switch (result) {
737		case build_running:
738			add_running(target,
739				    true_target,
740				    command,
741				    --recursion_level,
742				    auto_count,
743				    automatics,
744				    do_get,
745				    implicit);
746			target->state = build_running;
747			if ((line = get_prop(target->prop,
748					     line_prop)) != NULL) {
749				if (line->body.line.query != NULL) {
750					delete_query_chain(line->body.line.query);
751				}
752				line->body.line.query = NULL;
753			}
754			if (target->conditional_cnt > 0) {
755				reset_locals(target,
756					     old_locals,
757					     get_prop(target->prop,
758						     conditional_prop),
759					     0);
760			}
761			return build_running;
762		case build_serial:
763			add_serial(target,
764				   --recursion_level,
765				   do_get,
766				   implicit);
767			target->state = build_running;
768			line = get_prop(target->prop, line_prop);
769			if (line != NULL) {
770				if (line->body.line.query != NULL) {
771					delete_query_chain(line->body.line.query);
772				}
773				line->body.line.query = NULL;
774			}
775			if (target->conditional_cnt > 0) {
776				reset_locals(target,
777					     old_locals,
778					     get_prop(target->prop,
779						     conditional_prop),
780					     0);
781			}
782			return build_running;
783		case build_ok:
784			/* If all went OK set a nice timestamp */
785			if (true_target->stat.time == file_doesnt_exist) {
786				true_target->stat.time = file_max_time;
787			}
788			break;
789		}
790	} else {
791		/*
792		 * If no command was found for the target, and it doesn't
793		 * exist, and it is mentioned as a target in the makefile,
794		 * we say it is extremely new and that it is OK.
795		 */
796		if (target->colons != no_colon) {
797			if (true_target->stat.time == file_doesnt_exist){
798				true_target->stat.time = file_max_time;
799			}
800			result = build_ok;
801		}
802		/*
803		 * Trying dynamic targets.
804		 */
805		if(!doname_dyntarget) {
806			doname_dyntarget = 1;
807			Name dtarg = find_dyntarget(target);
808			if(dtarg!=NULL) {
809				if (!target->has_depe_list_expanded) {
810					dynamic_dependencies(target);
811				}
812				if ((line = get_prop(target->prop, line_prop)) != NULL) {
813					if (check_dependencies(&result,
814					                       line,
815					                       do_get,
816					                       target,
817					                       true_target,
818					                       doing_subtree,
819					                       &out_of_date_list,
820					                       old_locals,
821					                       implicit,
822					                       &command,
823					                       less,
824					                       rechecking_target,
825					                       recheck_conditionals))
826					{
827						return build_running;
828					}
829					if (line->body.line.query != NULL) {
830						delete_query_chain(line->body.line.query);
831					}
832					line->body.line.query = out_of_date_list;
833				}
834				goto r_command;
835			}
836		}
837		/*
838		 * If the file exists, it is OK that we couldnt figure
839		 * out how to build it.
840		 */
841		(void) exists(target);
842		if ((target->stat.time != file_doesnt_exist) &&
843		    (result == build_dont_know)) {
844			result = build_ok;
845		}
846	}
847
848	/*
849	 * Some of the following is duplicated in the function finish_doname.
850	 * If anything is changed here, check to see if it needs to be
851	 * changed there.
852	 */
853	if ((line = get_prop(target->prop, line_prop)) != NULL) {
854		if (line->body.line.query != NULL) {
855			delete_query_chain(line->body.line.query);
856		}
857		line->body.line.query = NULL;
858	}
859	target->state = result;
860	parallel = save_parallel;
861	if (target->conditional_cnt > 0) {
862		reset_locals(target,
863			     old_locals,
864			     get_prop(target->prop, conditional_prop),
865			     0);
866	}
867	recursion_level--;
868	if (target->is_member) {
869		Property member;
870
871		/* Propagate the timestamp from the member file to the member*/
872		if ((target->stat.time != file_max_time) &&
873		    ((member = get_prop(target->prop, member_prop)) != NULL) &&
874		    (exists(member->body.member.member) > file_doesnt_exist)) {
875			target->stat.time =
876			  member->body.member.member->stat.time;
877		}
878	}
879	/*
880	 * Check if we found any new auto dependencies when we
881	 * built the target.
882	 */
883	if ((result == build_ok) && check_auto_dependencies(target,
884							    auto_count,
885							    automatics)) {
886		if (debug_level > 0) {
887			(void) printf(gettext("%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"),
888				      recursion_level,
889				      "",
890				      true_target->string_mb);
891		}
892		rechecking_target = true;
893		saved_commands_done = commands_done;
894		goto recheck_target;
895	}
896
897	if (rechecking_target && !commands_done) {
898		commands_done = saved_commands_done;
899	}
900
901	return result;
902}
903
904/*
905 * DONE.
906 *
907 *	check_dependencies(result, line, do_get,
908 *			target, true_target, doing_subtree, out_of_date_tail,
909 *			old_locals, implicit, command, less, rechecking_target)
910 *
911 *	Return value:
912 *				True returned if some dependencies left running
913 *
914 *	Parameters:
915 *		result		Pointer to cell we update if build failed
916 *		line		We get the dependencies from here
917 *		do_get		Allow use of sccs get in recursive doname()
918 *		target		The target to chase dependencies for
919 *		true_target	The real one for :: and lib(member)
920 *		doing_subtree	True if building a conditional macro subtree
921 *		out_of_date_tail Used to set the $? list
922 *		old_locals	Used for resetting the local macros
923 *		implicit	Called when scanning for implicit rules?
924 *		command		Place to stuff command
925 *		less		Set to $< value
926 *
927 *	Global variables used:
928 *		command_changed	Set if we suspect .make.state needs rewrite
929 *		debug_level	Should we trace actions?
930 *		force		The Name " FORCE", compared against
931 *		recursion_level	Used for tracing
932 *		rewrite_statefile Set if .make.state needs rewriting
933 *		wait_name	The Name ".WAIT", compared against
934 */
935static Boolean
936check_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)
937{
938	Boolean			dependencies_running;
939	register Dependency	dependency;
940	Doname			dep_result;
941	Boolean			dependency_changed = false;
942
943	line->body.line.dependency_time = file_doesnt_exist;
944	if (line->body.line.query != NULL) {
945		delete_query_chain(line->body.line.query);
946	}
947	line->body.line.query = NULL;
948	line->body.line.is_out_of_date = false;
949	dependencies_running = false;
950	/*
951	 * Run thru all the dependencies and call doname() recursively
952	 * on each of them.
953	 */
954	for (dependency = line->body.line.dependencies;
955	     dependency != NULL;
956	     dependency = dependency->next) {
957		Boolean this_dependency_changed = false;
958
959		if (!dependency->automatic &&
960		    (rechecking_target || target->rechecking_target)) {
961			/*
962			 * We only bother with the autos when rechecking
963			 */
964			continue;
965		}
966
967		if (dependency->name == wait_name) {
968			/*
969			 * The special target .WAIT means finish all of
970			 * the prior dependencies before continuing.
971			 */
972			if (dependencies_running) {
973				break;
974			}
975		} else if ((!parallel_ok(dependency->name, false)) &&
976			   (dependencies_running)) {
977			/*
978			 * If we can't execute the current dependency in
979			 * parallel, hold off the dependency processing
980			 * to preserve the order of the dependencies.
981			 */
982			break;
983		} else {
984			timestruc_t	depe_time = file_doesnt_exist;
985
986
987			if (true_target->is_member) {
988				depe_time = exists(dependency->name);
989			}
990			if (dependency->built ||
991			    (dependency->name->state == build_failed)) {
992				dep_result = (Doname) dependency->name->state;
993			} else {
994				dep_result = doname_check(dependency->name,
995							  do_get,
996							  false,
997							  (Boolean) dependency->automatic);
998			}
999			if (true_target->is_member || dependency->name->is_member) {
1000				/* should compare only secs, cause lib members does not have nsec time resolution */
1001				if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) {
1002					this_dependency_changed =
1003					  dependency_changed =
1004					    true;
1005				}
1006			} else {
1007				if (depe_time != dependency->name->stat.time) {
1008					this_dependency_changed =
1009					  dependency_changed =
1010					    true;
1011				}
1012			}
1013			dependency->built = true;
1014			switch (dep_result) {
1015			case build_running:
1016				dependencies_running = true;
1017				continue;
1018			case build_failed:
1019				*result = build_failed;
1020				break;
1021			case build_dont_know:
1022/*
1023 * If make can't figure out how to make a dependency, maybe the dependency
1024 * is out of date. In this case, we just declare the target out of date
1025 * and go on. If we really need the dependency, the make'ing of the target
1026 * will fail. This will only happen for automatic (hidden) dependencies.
1027 */
1028				if(!recheck_conditionals) {
1029					line->body.line.is_out_of_date = true;
1030				}
1031				/*
1032				 * Make sure the dependency is not saved
1033				 * in the state file.
1034				 */
1035				dependency->stale = true;
1036				rewrite_statefile =
1037				  command_changed =
1038				    true;
1039				if (debug_level > 0) {
1040					(void) printf(gettext("Target %s rebuilt because dependency %s does not exist\n"),
1041						     true_target->string_mb,
1042						     dependency->name->string_mb);
1043				}
1044				break;
1045			}
1046			if (dependency->name->depends_on_conditional) {
1047				target->depends_on_conditional = true;
1048			}
1049			if (dependency->name == force) {
1050				target->stat.time =
1051				  dependency->name->stat.time;
1052			}
1053			/*
1054			 * Propagate new timestamp from "member" to
1055			 * "lib.a(member)".
1056			 */
1057			(void) exists(dependency->name);
1058
1059			/* Collect the timestamp of the youngest dependency */
1060			line->body.line.dependency_time =
1061			  MAX(dependency->name->stat.time,
1062			      line->body.line.dependency_time);
1063
1064			/* Correction: do not consider nanosecs for members */
1065			if(true_target->is_member || dependency->name->is_member) {
1066				line->body.line.dependency_time.tv_nsec = 0;
1067			}
1068
1069			if (debug_level > 1) {
1070				(void) printf(gettext("%*sDate(%s)=%s \n"),
1071					      recursion_level,
1072					      "",
1073					      dependency->name->string_mb,
1074					      time_to_string(dependency->name->
1075							     stat.time));
1076				if (dependency->name->stat.time > line->body.line.dependency_time) {
1077					(void) printf(gettext("%*sDate-dependencies(%s) set to %s\n"),
1078						      recursion_level,
1079						      "",
1080						      true_target->string_mb,
1081						      time_to_string(line->body.line.
1082								     dependency_time));
1083				}
1084			}
1085
1086			/* Build the $? list */
1087			if (true_target->is_member) {
1088				if (this_dependency_changed == true) {
1089					true_target->stat.time = dependency->name->stat.time;
1090					true_target->stat.time.tv_sec--;
1091				} else {
1092					/* Dina:
1093					 * The next statement is commented
1094					 * out as a fix for bug #1051032.
1095					 * if dependency hasn't changed
1096					 * then there's no need to invalidate
1097					 * true_target. This statemnt causes
1098					 * make to take much longer to process
1099					 * an already-built archive. Soren
1100					 * said it was a quick fix for some
1101					 * problem he doesn't remember.
1102					true_target->stat.time = file_no_time;
1103					 */
1104					(void) exists(true_target);
1105				}
1106			} else {
1107				(void) exists(true_target);
1108			}
1109			Boolean out_of_date;
1110			if (true_target->is_member || dependency->name->is_member) {
1111				out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1112							                dependency->name->stat.time);
1113			} else {
1114				out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1115							            dependency->name->stat.time);
1116			}
1117			if ((build_unconditional || out_of_date) &&
1118			    (dependency->name != force) &&
1119			    (dependency->stale == false)) {
1120				*out_of_date_tail = ALLOC(Chain);
1121				if (dependency->name->is_member &&
1122				    (get_prop(dependency->name->prop,
1123					      member_prop) != NULL)) {
1124					(*out_of_date_tail)->name =
1125					  get_prop(dependency->name->prop,
1126						   member_prop)->
1127						     body.member.member;
1128				} else {
1129					(*out_of_date_tail)->name =
1130					  dependency->name;
1131				}
1132				(*out_of_date_tail)->next = NULL;
1133				out_of_date_tail = &(*out_of_date_tail)->next;
1134				if (debug_level > 0) {
1135					if (dependency->name->stat.time == file_max_time) {
1136						(void) printf(gettext("%*sBuilding %s because %s does not exist\n"),
1137							      recursion_level,
1138							      "",
1139							      true_target->string_mb,
1140							      dependency->name->string_mb);
1141					} else {
1142						(void) printf(gettext("%*sBuilding %s because it is out of date relative to %s\n"),
1143							      recursion_level,
1144							      "",
1145							      true_target->string_mb,
1146							      dependency->name->string_mb);
1147					}
1148				}
1149			}
1150			if (dependency->name == force) {
1151				force->stat.time =
1152				  file_max_time;
1153				force->state = build_dont_know;
1154			}
1155		}
1156	}
1157	if (dependencies_running) {
1158		if (doing_subtree) {
1159			if (target->conditional_cnt > 0) {
1160				reset_locals(target,
1161					     old_locals,
1162					     get_prop(target->prop,
1163						      conditional_prop),
1164					     0);
1165			}
1166			return true;
1167		} else {
1168			target->state = build_running;
1169			add_pending(target,
1170				    --recursion_level,
1171				    do_get,
1172				    implicit,
1173				    false);
1174			if (target->conditional_cnt > 0) {
1175				reset_locals(target,
1176					     old_locals,
1177					     get_prop(target->prop,
1178						      conditional_prop),
1179					     0);
1180			}
1181			return true;
1182		}
1183	}
1184	/*
1185	 * Collect the timestamp of the youngest double colon target
1186	 * dependency.
1187	 */
1188	if (target->is_double_colon_parent) {
1189		for (dependency = line->body.line.dependencies;
1190		     dependency != NULL;
1191		     dependency = dependency->next) {
1192			Property        tmp_line;
1193
1194			if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) {
1195				if(tmp_line->body.line.dependency_time != file_max_time) {
1196					target->stat.time =
1197					  MAX(tmp_line->body.line.dependency_time,
1198					      target->stat.time);
1199				}
1200			}
1201		}
1202	}
1203	if ((true_target->is_member) && (dependency_changed == true)) {
1204		true_target->stat.time = file_no_time;
1205	}
1206	/*
1207	 * After scanning all the dependencies, we check the rule
1208	 * if we found one.
1209	 */
1210	if (line->body.line.command_template != NULL) {
1211		if (line->body.line.command_template_redefined) {
1212			warning(gettext("Too many rules defined for target %s"),
1213				target->string_mb);
1214		}
1215		*command = line;
1216		/* Check if the target is out of date */
1217		Boolean out_of_date;
1218		if (true_target->is_member) {
1219			out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time,
1220				                                line->body.line.dependency_time);
1221		} else {
1222			out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time,
1223				                            line->body.line.dependency_time);
1224		}
1225		if (build_unconditional || out_of_date){
1226			if(!recheck_conditionals) {
1227				line->body.line.is_out_of_date = true;
1228			}
1229		}
1230		line->body.line.sccs_command = false;
1231		line->body.line.target = true_target;
1232		if(gnu_style) {
1233
1234			// set $< for explicit rule
1235			if(line->body.line.dependencies != NULL) {
1236				less = line->body.line.dependencies->name;
1237			}
1238
1239			// set $* for explicit rule
1240			Name			target_body;
1241			Name			tt = true_target;
1242			Property		member;
1243			register wchar_t	*target_end;
1244			register Dependency	suffix;
1245			register int		suffix_length;
1246			Wstring			targ_string;
1247			Wstring			suf_string;
1248
1249			if (true_target->is_member &&
1250			    ((member = get_prop(target->prop, member_prop)) !=
1251			     NULL)) {
1252				tt = member->body.member.member;
1253			}
1254			targ_string.init(tt);
1255			target_end = targ_string.get_string() + tt->hash.length;
1256			for (suffix = suffixes; suffix != NULL; suffix = suffix->next) {
1257				suffix_length = suffix->name->hash.length;
1258				suf_string.init(suffix->name);
1259				if (tt->hash.length < suffix_length) {
1260					continue;
1261				} else if (!IS_WEQUALN(suf_string.get_string(),
1262						(target_end - suffix_length),
1263						suffix_length)) {
1264					continue;
1265				}
1266				target_body = GETNAME(
1267					targ_string.get_string(),
1268					(int)(tt->hash.length - suffix_length)
1269				);
1270				line->body.line.star = target_body;
1271			}
1272
1273			// set result = build_ok so that implicit rules are not used.
1274			if(*result == build_dont_know) {
1275				*result = build_ok;
1276			}
1277		}
1278		if (less != NULL) {
1279			line->body.line.less = less;
1280		}
1281	}
1282
1283	return false;
1284}
1285
1286/*
1287 *	dynamic_dependencies(target)
1288 *
1289 *	Checks if any dependency contains a macro ref
1290 *	If so, it replaces the dependency with the expanded version.
1291 *	Here, "$@" gets translated to target->string. That is
1292 *	the current name on the left of the colon in the
1293 *	makefile.  Thus,
1294 *		xyz:	s.$@.c
1295 *	translates into
1296 *		xyz:	s.xyz.c
1297 *
1298 *	Also, "$(@F)" translates to the same thing without a preceeding
1299 *	directory path (if one exists).
1300 *	Note, to enter "$@" on a dependency line in a makefile
1301 *	"$$@" must be typed. This is because make expands
1302 *	macros in dependency lists upon reading them.
1303 *	dynamic_dependencies() also expands file wildcards.
1304 *	If there are any Shell meta characters in the name,
1305 *	search the directory, and replace the dependency
1306 *	with the set of files the pattern matches
1307 *
1308 *	Parameters:
1309 *		target		Target to sanitize dependencies for
1310 *
1311 *	Global variables used:
1312 *		c_at		The Name "@", used to set macro value
1313 *		debug_level	Should we trace actions?
1314 *		dot		The Name ".", used to read directory
1315 *		recursion_level	Used for tracing
1316 */
1317void
1318dynamic_dependencies(Name target)
1319{
1320	wchar_t			pattern[MAXPATHLEN];
1321	register wchar_t	*p;
1322	Property		line;
1323	register Dependency	dependency;
1324	register Dependency	*remove;
1325	String_rec		string;
1326	wchar_t			buffer[MAXPATHLEN];
1327	register Boolean	set_at = false;
1328	register wchar_t	*start;
1329	Dependency		new_depe;
1330	register Boolean	reuse_cell;
1331	Dependency		first_member;
1332	Name			directory;
1333	Name			lib;
1334	Name			member;
1335	Property		prop;
1336	Name			true_target = target;
1337	wchar_t			*library;
1338
1339	if ((line = get_prop(target->prop, line_prop)) == NULL) {
1340		return;
1341	}
1342	/* If the target is constructed from a "::" target we consider that */
1343	if (target->has_target_prop) {
1344		true_target = get_prop(target->prop,
1345				       target_prop)->body.target.target;
1346	}
1347	/* Scan all dependencies and process the ones that contain "$" chars */
1348	for (dependency = line->body.line.dependencies;
1349	     dependency != NULL;
1350	     dependency = dependency->next) {
1351		if (!dependency->name->dollar) {
1352			continue;
1353		}
1354		target->has_depe_list_expanded = true;
1355
1356		/* The make macro $@ is bound to the target name once per */
1357		/* invocation of dynamic_dependencies() */
1358		if (!set_at) {
1359			(void) SETVAR(c_at, true_target, false);
1360			set_at = true;
1361		}
1362		/* Expand this dependency string */
1363		INIT_STRING_FROM_STACK(string, buffer);
1364		expand_value(dependency->name, &string, false);
1365		/* Scan the expanded string. It could contain whitespace */
1366		/* which mean it expands to several dependencies */
1367		start = string.buffer.start;
1368		while (iswspace(*start)) {
1369			start++;
1370		}
1371		/* Remove the cell (later) if the macro was empty */
1372		if (start[0] == (int) nul_char) {
1373			dependency->name = NULL;
1374		}
1375
1376/* azv 10/26/95 to fix bug BID_1170218 */
1377		if ((start[0] == (int) period_char) &&
1378		    (start[1] == (int) slash_char)) {
1379			start += 2;
1380		}
1381/* azv */
1382
1383		first_member = NULL;
1384		/* We use the original dependency cell for the first */
1385		/* dependency from the expansion */
1386		reuse_cell = true;
1387		/* We also have to deal with dependencies that expand to */
1388		/* lib.a(members) notation */
1389		for (p = start; *p != (int) nul_char; p++) {
1390			if ((*p == (int) parenleft_char)) {
1391				lib = GETNAME(start, p - start);
1392				lib->is_member = true;
1393				first_member = dependency;
1394				start = p + 1;
1395				while (iswspace(*start)) {
1396					start++;
1397				}
1398				break;
1399			}
1400		}
1401		do {
1402		    /* First skip whitespace */
1403			for (p = start; *p != (int) nul_char; p++) {
1404				if ((*p == (int) nul_char) ||
1405				    iswspace(*p) ||
1406				    (*p == (int) parenright_char)) {
1407					break;
1408				}
1409			}
1410			/* Enter dependency from expansion */
1411			if (p != start) {
1412				/* Create new dependency cell if */
1413				/* this is not the first dependency */
1414				/* picked from the expansion */
1415				if (!reuse_cell) {
1416					new_depe = ALLOC(Dependency);
1417					new_depe->next = dependency->next;
1418					new_depe->automatic = false;
1419					new_depe->stale = false;
1420					new_depe->built = false;
1421					dependency->next = new_depe;
1422					dependency = new_depe;
1423				}
1424				reuse_cell = false;
1425				/* Internalize the dependency name */
1426				// tolik. Fix for bug 4110429: inconsistent expansion for macros that
1427				// include "//" and "/./"
1428				//dependency->name = GETNAME(start, p - start);
1429				dependency->name = normalize_name(start, p - start);
1430				if ((debug_level > 0) &&
1431				    (first_member == NULL)) {
1432					(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1433						      recursion_level,
1434						      "",
1435						      dependency->name->string_mb,
1436						      true_target->string_mb);
1437				}
1438				for (start = p; iswspace(*start); start++);
1439				p = start;
1440			}
1441		} while ((*p != (int) nul_char) &&
1442			 (*p != (int) parenright_char));
1443		/* If the expansion was of lib.a(members) format we now */
1444		/* enter the proper member cells */
1445		if (first_member != NULL) {
1446			/* Scan the new dependencies and transform them from */
1447			/* "foo" to "lib.a(foo)" */
1448			for (; 1; first_member = first_member->next) {
1449				/* Build "lib.a(foo)" name */
1450				INIT_STRING_FROM_STACK(string, buffer);
1451				APPEND_NAME(lib,
1452					      &string,
1453					      (int) lib->hash.length);
1454				append_char((int) parenleft_char, &string);
1455				APPEND_NAME(first_member->name,
1456					      &string,
1457					      FIND_LENGTH);
1458				append_char((int) parenright_char, &string);
1459				member = first_member->name;
1460				/* Replace "foo" with "lib.a(foo)" */
1461				first_member->name =
1462				  GETNAME(string.buffer.start, FIND_LENGTH);
1463				if (string.free_after_use) {
1464					retmem(string.buffer.start);
1465				}
1466				if (debug_level > 0) {
1467					(void) printf(gettext("%*sDynamic dependency `%s' for target `%s'\n"),
1468						      recursion_level,
1469						      "",
1470						      first_member->name->
1471						      string_mb,
1472						      true_target->string_mb);
1473				}
1474				first_member->name->is_member = lib->is_member;
1475				/* Add member property to member */
1476				prop = maybe_append_prop(first_member->name,
1477							 member_prop);
1478				prop->body.member.library = lib;
1479				prop->body.member.entry = NULL;
1480				prop->body.member.member = member;
1481				if (first_member == dependency) {
1482					break;
1483				}
1484			}
1485		}
1486	}
1487	Wstring wcb;
1488	/* Then scan all the dependencies again. This time we want to expand */
1489	/* shell file wildcards */
1490	for (remove = &line->body.line.dependencies, dependency = *remove;
1491	     dependency != NULL;
1492	     dependency = *remove) {
1493		if (dependency->name == NULL) {
1494			dependency = *remove = (*remove)->next;
1495			continue;
1496		}
1497		/* If dependency name string contains shell wildcards */
1498		/* replace the name with the expansion */
1499		if (dependency->name->wildcard) {
1500			wcb.init(dependency->name);
1501			if ((start = (wchar_t *) wcschr(wcb.get_string(),
1502					   (int) parenleft_char)) != NULL) {
1503				/* lib(*) type pattern */
1504				library = buffer;
1505				(void) wcsncpy(buffer,
1506					      wcb.get_string(),
1507					      start - wcb.get_string());
1508				buffer[start-wcb.get_string()] =
1509				  (int) nul_char;
1510				(void) wcsncpy(pattern,
1511					      start + 1,
1512(int) (dependency->name->hash.length-(start-wcb.get_string())-2));
1513				pattern[dependency->name->hash.length -
1514					(start-wcb.get_string()) - 2] =
1515					  (int) nul_char;
1516			} else {
1517				library = NULL;
1518				(void) wcsncpy(pattern,
1519					      wcb.get_string(),
1520					      (int) dependency->name->hash.length);
1521				pattern[dependency->name->hash.length] =
1522				  (int) nul_char;
1523			}
1524			start = (wchar_t *) wcsrchr(pattern, (int) slash_char);
1525			if (start == NULL) {
1526				directory = dot;
1527				p = pattern;
1528			} else {
1529				directory = GETNAME(pattern, start-pattern);
1530				p = start+1;
1531			}
1532			/* The expansion is handled by the read_dir() routine*/
1533			if (read_dir(directory, p, line, library)) {
1534				*remove = (*remove)->next;
1535			} else {
1536				remove = &dependency->next;
1537			}
1538		} else {
1539			remove = &dependency->next;
1540		}
1541        }
1542
1543	/* Then unbind $@ */
1544	(void) SETVAR(c_at, (Name) NULL, false);
1545}
1546
1547/*
1548 * DONE.
1549 *
1550 *	run_command(line)
1551 *
1552 *	Takes one Cmd_line and runs the commands from it.
1553 *
1554 *	Return value:
1555 *				Indicates if the command failed or not
1556 *
1557 *	Parameters:
1558 *		line		The command line to run
1559 *
1560 *	Global variables used:
1561 *		commands_done	Set if we do run command
1562 *		current_line	Set to the line we run a command from
1563 *		current_target	Set to the target we run a command for
1564 *		file_number	Used to form temp file name
1565 *		keep_state	Indicates that .KEEP_STATE is on
1566 *		make_state	The Name ".make.state", used to check timestamp
1567 *		parallel	True if currently building in parallel
1568 *		parallel_process_cnt Count of parallel processes running
1569 *		quest		Indicates that make -q is on
1570 *		rewrite_statefile Set if we do run a command
1571 *		sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value
1572 *		temp_file_directory Used to form temp fie name
1573 *		temp_file_name	Set to the name of the temp file
1574 *		touch		Indicates that make -t is on
1575 */
1576static Doname
1577run_command(register Property line, Boolean)
1578{
1579	register Doname		result = build_ok;
1580	register Boolean	remember_only = false;
1581	register Name		target = line->body.line.target;
1582	wchar_t			*string;
1583	char			tmp_file_path[MAXPATHLEN];
1584
1585	if (!line->body.line.is_out_of_date && target->rechecking_target) {
1586		target->rechecking_target = false;
1587		return build_ok;
1588	}
1589
1590	/*
1591	 * Build the command if we know the target is out of date,
1592	 * or if we want to check cmd consistency.
1593	 */
1594	if (line->body.line.is_out_of_date || keep_state) {
1595		/* Hack for handling conditional macros in DMake. */
1596		if (!line->body.line.dont_rebuild_command_used) {
1597			build_command_strings(target, line);
1598		}
1599	}
1600	/* Never mind */
1601	if (!line->body.line.is_out_of_date) {
1602		return build_ok;
1603	}
1604	/* If quest, then exit(1) because the target is out of date */
1605	if (quest) {
1606		if (posix) {
1607			result = execute_parallel(line, true);
1608		}
1609		exit_status = 1;
1610		exit(1);
1611	}
1612	/* We actually had to do something this time */
1613	rewrite_statefile = commands_done = true;
1614	/*
1615	 * If this is an sccs command, we have to do some extra checking
1616	 * and possibly complain. If the file can't be gotten because it's
1617	 * checked out, we complain and behave as if the command was
1618	 * executed eventhough we ignored the command.
1619	 */
1620	if (!touch &&
1621	    line->body.line.sccs_command &&
1622	    (target->stat.time != file_doesnt_exist) &&
1623	    ((target->stat.mode & 0222) != 0)) {
1624		fatal(gettext("%s is writable so it cannot be sccs gotten"),
1625		      target->string_mb);
1626		target->has_complained = remember_only = true;
1627	}
1628	/*
1629	 * If KEEP_STATE is on, we make sure we have the timestamp for
1630	 * .make.state. If .make.state changes during the command run,
1631	 * we reread .make.state after the command. We also setup the
1632	 * environment variable that asks utilities to report dependencies.
1633	 */
1634	if (!touch &&
1635	    keep_state &&
1636	    !remember_only) {
1637		(void) exists(make_state);
1638		if((strlen(temp_file_directory) == 1) &&
1639			(temp_file_directory[0] == '/')) {
1640		   tmp_file_path[0] = '\0';
1641		} else {
1642		   strcpy(tmp_file_path, temp_file_directory);
1643		}
1644		sprintf(mbs_buffer,
1645				"%s/.make.dependency.%08x.%d.%d",
1646			        tmp_file_path,
1647			        hostid,
1648			        getpid(),
1649			        file_number++);
1650		MBSTOWCS(wcs_buffer, mbs_buffer);
1651		Boolean fnd;
1652		temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd);
1653		temp_file_name->stat.is_file = true;
1654		int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2;
1655		wchar_t *to = string = ALLOC_WC(len);
1656		for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) {
1657			if (*from == (int) space_char) {
1658				*to++ = (int) backslash_char;
1659			}
1660			*to++ = *from++;
1661		}
1662		*to++ = (int) space_char;
1663		MBSTOWCS(to, target->string_mb);
1664		Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd);
1665		(void) SETVAR(sunpro_dependencies,
1666			      sprodep_name,
1667			      false);
1668		retmem(string);
1669	} else {
1670		temp_file_name = NULL;
1671	}
1672
1673	/*
1674	 * In case we are interrupted, we need to know what was going on.
1675	 */
1676	current_target = target;
1677	/*
1678	 * We also need to be able to save an empty command instead of the
1679	 * interrupted one in .make.state.
1680	 */
1681	current_line = line;
1682	if (remember_only) {
1683		/* Empty block!!! */
1684	} else if (touch) {
1685		result = touch_command(line, target, result);
1686		if (posix) {
1687			result = execute_parallel(line, true);
1688		}
1689	} else {
1690		/*
1691		 * If this is not a touch run, we need to execute the
1692		 * proper command(s) for the target.
1693		 */
1694		if (parallel) {
1695			if (!parallel_ok(target, true)) {
1696				/*
1697				 * We are building in parallel, but
1698				 * this target must be built in serial.
1699				 */
1700				/*
1701				 * If nothing else is building,
1702				 * do this one, else wait.
1703				 */
1704				if (parallel_process_cnt == 0) {
1705					result = execute_parallel(line, true, target->localhost);
1706				} else {
1707					current_target = NULL;
1708					current_line = NULL;
1709/*
1710					line->body.line.command_used = NULL;
1711 */
1712					line->body.line.dont_rebuild_command_used = true;
1713					return build_serial;
1714				}
1715			} else {
1716				result = execute_parallel(line, false);
1717				switch (result) {
1718				case build_running:
1719					return build_running;
1720				case build_serial:
1721					if (parallel_process_cnt == 0) {
1722						result = execute_parallel(line, true, target->localhost);
1723					} else {
1724						current_target = NULL;
1725						current_line = NULL;
1726						target->parallel = false;
1727						line->body.line.command_used =
1728						    NULL;
1729						return build_serial;
1730					}
1731				}
1732			}
1733		} else {
1734			result = execute_parallel(line, true, target->localhost);
1735		}
1736	}
1737	temp_file_name = NULL;
1738	if (report_dependencies_level == 0){
1739		update_target(line, result);
1740	}
1741	current_target = NULL;
1742	current_line = NULL;
1743	return result;
1744}
1745
1746/*
1747 *	execute_serial(line)
1748 *
1749 *	Runs thru the command line for the target and
1750 *	executes the rules one by one.
1751 *
1752 *	Return value:
1753 *				The result of the command build
1754 *
1755 *	Parameters:
1756 *		line		The command to execute
1757 *
1758 *	Static variables used:
1759 *
1760 *	Global variables used:
1761 *		continue_after_error -k flag
1762 *		do_not_exec_rule -n flag
1763 *		report_dependencies -P flag
1764 *		silent		Don't echo commands before executing
1765 *		temp_file_name	Temp file for auto dependencies
1766 *		vpath_defined	If true, translate path for command
1767 */
1768Doname
1769execute_serial(Property line)
1770{
1771	int			child_pid = 0;
1772	Boolean			printed_serial;
1773	Doname			result = build_ok;
1774	Cmd_line		rule, cmd_tail, command = NULL;
1775	char			mbstring[MAXPATHLEN];
1776	int			filed;
1777	Name			target = line->body.line.target;
1778
1779	target->has_recursive_dependency = false;
1780	// We have to create a copy of the rules chain for processing because
1781	// the original one can be destroyed during .make.state file rereading.
1782	for (rule = line->body.line.command_used;
1783	     rule != NULL;
1784	     rule = rule->next) {
1785		if (command == NULL) {
1786			command = cmd_tail = ALLOC(Cmd_line);
1787		} else {
1788			cmd_tail->next = ALLOC(Cmd_line);
1789			cmd_tail = cmd_tail->next;
1790		}
1791		*cmd_tail = *rule;
1792	}
1793	if (command) {
1794		cmd_tail->next = NULL;
1795	}
1796	for (rule = command; rule != NULL; rule = rule->next) {
1797		if (posix && (touch || quest) && !rule->always_exec) {
1798			continue;
1799		}
1800		if (vpath_defined) {
1801			rule->command_line =
1802			  vpath_translation(rule->command_line);
1803		}
1804		/* Echo command line, maybe. */
1805		if ((rule->command_line->hash.length > 0) &&
1806		    !silent &&
1807		    (!rule->silent || do_not_exec_rule) &&
1808		    (report_dependencies_level == 0)) {
1809			(void) printf("%s\n", rule->command_line->string_mb);
1810		}
1811		if (rule->command_line->hash.length > 0) {
1812			/* Do assignment if command line prefixed with "=" */
1813			if (rule->assign) {
1814				result = build_ok;
1815				do_assign(rule->command_line, target);
1816			} else if (report_dependencies_level == 0) {
1817				/* Execute command line. */
1818				setvar_envvar();
1819				result = dosys(rule->command_line,
1820				               (Boolean) rule->ignore_error,
1821				               (Boolean) rule->make_refd,
1822				               /* ds 98.04.23 bug #4085164. make should always show error messages */
1823				               false,
1824				               /* BOOLEAN(rule->silent &&
1825				                       rule->ignore_error), */
1826				               (Boolean) rule->always_exec,
1827				               target);
1828				check_state(temp_file_name);
1829			}
1830		} else {
1831			result = build_ok;
1832		}
1833		if (result == build_failed) {
1834			if (silent || rule->silent) {
1835				(void) printf(gettext("The following command caused the error:\n%s\n"),
1836				              rule->command_line->string_mb);
1837			}
1838			if (!rule->ignore_error && !ignore_errors) {
1839				if (!continue_after_error) {
1840					fatal(gettext("Command failed for target `%s'"),
1841					      target->string_mb);
1842				}
1843				/*
1844				 * Make sure a failing command is not
1845				 * saved in .make.state.
1846				 */
1847				line->body.line.command_used = NULL;
1848				break;
1849			} else {
1850				result = build_ok;
1851			}
1852		}
1853	}
1854	for (rule = command; rule != NULL; rule = cmd_tail) {
1855		cmd_tail = rule->next;
1856		free(rule);
1857	}
1858	command = NULL;
1859	if (temp_file_name != NULL) {
1860		free_name(temp_file_name);
1861	}
1862        temp_file_name = NULL;
1863
1864	Property spro = get_prop(sunpro_dependencies->prop, macro_prop);
1865	if(spro != NULL) {
1866		Name val = spro->body.macro.value;
1867		if(val != NULL) {
1868			free_name(val);
1869			spro->body.macro.value = NULL;
1870		}
1871	}
1872	spro = get_prop(sunpro_dependencies->prop, env_mem_prop);
1873	if(spro) {
1874		char *val = spro->body.env_mem.value;
1875		if(val != NULL) {
1876			/*
1877			 * Do not return memory allocated for SUNPRO_DEPENDENCIES
1878			 * It will be returned in setvar_daemon() in macro.cc
1879			 */
1880			//	retmem_mb(val);
1881			spro->body.env_mem.value = NULL;
1882		}
1883	}
1884
1885        return result;
1886}
1887
1888
1889
1890/*
1891 *	vpath_translation(cmd)
1892 *
1893 *	Translates one command line by
1894 *	checking each word. If the word has an alias it is translated.
1895 *
1896 *	Return value:
1897 *				The translated command
1898 *
1899 *	Parameters:
1900 *		cmd		Command to translate
1901 *
1902 *	Global variables used:
1903 */
1904Name
1905vpath_translation(register Name cmd)
1906{
1907	wchar_t			buffer[STRING_BUFFER_LENGTH];
1908	String_rec		new_cmd;
1909	wchar_t			*p;
1910	wchar_t			*start;
1911
1912	if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) {
1913		return cmd;
1914	}
1915	INIT_STRING_FROM_STACK(new_cmd, buffer);
1916
1917	Wstring wcb(cmd);
1918	p = wcb.get_string();
1919
1920	while (*p != (int) nul_char) {
1921		while (iswspace(*p) && (*p != (int) nul_char)) {
1922			append_char(*p++, &new_cmd);
1923		}
1924		start = p;
1925		while (!iswspace(*p) && (*p != (int) nul_char)) {
1926			p++;
1927		}
1928		cmd = GETNAME(start, p - start);
1929		if (cmd->has_vpath_alias_prop) {
1930			cmd = get_prop(cmd->prop, vpath_alias_prop)->
1931						body.vpath_alias.alias;
1932			APPEND_NAME(cmd,
1933				      &new_cmd,
1934				      (int) cmd->hash.length);
1935		} else {
1936			append_string(start, &new_cmd, p - start);
1937		}
1938	}
1939	cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH);
1940	if (new_cmd.free_after_use) {
1941		retmem(new_cmd.buffer.start);
1942	}
1943	return cmd;
1944}
1945
1946/*
1947 *	check_state(temp_file_name)
1948 *
1949 *	Reads and checks the state changed by the previously executed command.
1950 *
1951 *	Parameters:
1952 *		temp_file_name	The auto dependency temp file
1953 *
1954 *	Global variables used:
1955 */
1956void
1957check_state(Name temp_file_name)
1958{
1959	if (!keep_state) {
1960		return;
1961	}
1962
1963	/*
1964	 * Then read the temp file that now might
1965	 * contain dependency reports from utilities
1966	 */
1967	read_dependency_file(temp_file_name);
1968
1969	/*
1970	 * And reread .make.state if it
1971	 * changed (the command ran recursive makes)
1972	 */
1973	check_read_state_file();
1974	if (temp_file_name != NULL) {
1975		(void) unlink(temp_file_name->string_mb);
1976	}
1977}
1978
1979/*
1980 *	read_dependency_file(filename)
1981 *
1982 *	Read the temp file used for reporting dependencies to make
1983 *
1984 *	Parameters:
1985 *		filename	The name of the file with the state info
1986 *
1987 *	Global variables used:
1988 *		makefile_type	The type of makefile being read
1989 *		read_trace_level Debug flag
1990 *		temp_file_number The always increasing number for unique files
1991 *		trace_reader	Debug flag
1992 */
1993static void
1994read_dependency_file(register Name filename)
1995{
1996	register Makefile_type	save_makefile_type;
1997
1998	if (filename == NULL) {
1999		return;
2000	}
2001	filename->stat.time = file_no_time;
2002	if (exists(filename) > file_doesnt_exist) {
2003		save_makefile_type = makefile_type;
2004		makefile_type = reading_cpp_file;
2005		if (read_trace_level > 1) {
2006			trace_reader = true;
2007		}
2008		temp_file_number++;
2009		(void) read_simple_file(filename,
2010					false,
2011					false,
2012					false,
2013					false,
2014					false,
2015					false);
2016		trace_reader = false;
2017		makefile_type = save_makefile_type;
2018	}
2019}
2020
2021/*
2022 *	check_read_state_file()
2023 *
2024 *	Check if .make.state has changed
2025 *	If it has we reread it
2026 *
2027 *	Parameters:
2028 *
2029 *	Global variables used:
2030 *		make_state	Make state file name
2031 *		makefile_type	Type of makefile being read
2032 *		read_trace_level Debug flag
2033 *		trace_reader	Debug flag
2034 */
2035static void
2036check_read_state_file(void)
2037{
2038	timestruc_t		previous = make_state->stat.time;
2039	register Makefile_type	save_makefile_type;
2040	register Property	makefile;
2041
2042	make_state->stat.time = file_no_time;
2043	if ((exists(make_state) == file_doesnt_exist) ||
2044	    (make_state->stat.time == previous)) {
2045		return;
2046	}
2047	save_makefile_type = makefile_type;
2048	makefile_type = rereading_statefile;
2049	/* Make sure we clear the old cached contents of .make.state */
2050	makefile = maybe_append_prop(make_state, makefile_prop);
2051	if (makefile->body.makefile.contents != NULL) {
2052		retmem(makefile->body.makefile.contents);
2053		makefile->body.makefile.contents = NULL;
2054	}
2055	if (read_trace_level > 1) {
2056		trace_reader = true;
2057	}
2058	temp_file_number++;
2059	(void) read_simple_file(make_state,
2060				false,
2061				false,
2062				false,
2063				false,
2064				false,
2065				true);
2066	trace_reader = false;
2067	makefile_type = save_makefile_type;
2068}
2069
2070/*
2071 *	do_assign(line, target)
2072 *
2073 *	Handles runtime assignments for command lines prefixed with "=".
2074 *
2075 *	Parameters:
2076 *		line		The command that contains an assignment
2077 *		target		The Name of the target, used for error reports
2078 *
2079 *	Global variables used:
2080 *		assign_done	Set to indicate doname needs to reprocess
2081 */
2082static void
2083do_assign(register Name line, register Name target)
2084{
2085	Wstring wcb(line);
2086	register wchar_t	*string = wcb.get_string();
2087	register wchar_t	*equal;
2088	register Name		name;
2089	register Boolean	append = false;
2090
2091	/*
2092	 * If any runtime assignments are done, doname() must reprocess all
2093	 * targets in the future since the macro values used to build the
2094	 * command lines for the targets might have changed.
2095	 */
2096	assign_done = true;
2097	/* Skip white space. */
2098	while (iswspace(*string)) {
2099		string++;
2100	}
2101	equal = string;
2102	/* Find "+=" or "=". */
2103	while (!iswspace(*equal) &&
2104	       (*equal != (int) plus_char) &&
2105	       (*equal != (int) equal_char)) {
2106		equal++;
2107	}
2108	/* Internalize macro name. */
2109	name = GETNAME(string, equal - string);
2110	/* Skip over "+=" "=". */
2111	while (!((*equal == (int) nul_char) ||
2112		 (*equal == (int) equal_char) ||
2113		 (*equal == (int) plus_char))) {
2114		equal++;
2115	}
2116	switch (*equal) {
2117	case nul_char:
2118		fatal(gettext("= expected in rule `%s' for target `%s'"),
2119		      line->string_mb,
2120		      target->string_mb);
2121	case plus_char:
2122		append = true;
2123		equal++;
2124		break;
2125	}
2126	equal++;
2127	/* Skip over whitespace in front of value. */
2128	while (iswspace(*equal)) {
2129		equal++;
2130	}
2131	/* Enter new macro value. */
2132	enter_equal(name,
2133		    GETNAME(equal, wcb.get_string() + line->hash.length - equal),
2134		    append);
2135}
2136
2137/*
2138 *	build_command_strings(target, line)
2139 *
2140 *	Builds the command string to used when
2141 *	building a target. If the string is different from the previous one
2142 *	is_out_of_date is set.
2143 *
2144 *	Parameters:
2145 *		target		Target to build commands for
2146 *		line		Where to stuff result
2147 *
2148 *	Global variables used:
2149 *		c_at		The Name "@", used to set macro value
2150 *		command_changed	Set if command is different from old
2151 *		debug_level	Should we trace activities?
2152 *		do_not_exec_rule Always echo when running -n
2153 *		empty_name	The Name "", used for empty rule
2154 *		funny		Semantics of characters
2155 *		ignore_errors	Used to init field for line
2156 *		is_conditional	Set to false befor evaling macro, checked
2157 *				after expanding macros
2158 *		keep_state	Indicates that .KEEP_STATE is on
2159 *		make_word_mentioned Set by macro eval, inits field for cmd
2160 *		query		The Name "?", used to set macro value
2161 *		query_mentioned	Set by macro eval, inits field for cmd
2162 *		recursion_level	Used for tracing
2163 *		silent		Used to init field for line
2164 */
2165static void
2166build_command_strings(Name target, register Property line)
2167{
2168	String_rec		command_line;
2169	register Cmd_line	command_template = line->body.line.command_template;
2170	register Cmd_line	*insert = &line->body.line.command_used;
2171	register Cmd_line	used = *insert;
2172	wchar_t			buffer[STRING_BUFFER_LENGTH];
2173	wchar_t			*start;
2174	Name			new_command_line;
2175	register Boolean	new_command_longer = false;
2176	register Boolean	ignore_all_command_dependency = true;
2177	Property		member;
2178	static Name		less_name;
2179	static Name		percent_name;
2180	static Name		star;
2181	Name			tmp_name;
2182
2183	if (less_name == NULL) {
2184		MBSTOWCS(wcs_buffer, "<");
2185		less_name = GETNAME(wcs_buffer, FIND_LENGTH);
2186		MBSTOWCS(wcs_buffer, "%");
2187		percent_name = GETNAME(wcs_buffer, FIND_LENGTH);
2188		MBSTOWCS(wcs_buffer, "*");
2189		star = GETNAME(wcs_buffer, FIND_LENGTH);
2190	}
2191
2192	/* We have to check if a target depends on conditional macros */
2193	/* Targets that do must be reprocessed by doname() each time around */
2194	/* since the macro values used when building the target might have */
2195	/* changed */
2196	conditional_macro_used = false;
2197	/* If we are building a lib.a(member) target $@ should be bound */
2198	/* to lib.a */
2199	if (target->is_member &&
2200	    ((member = get_prop(target->prop, member_prop)) != NULL)) {
2201		target = member->body.member.library;
2202	}
2203	/* If we are building a "::" help target $@ should be bound to */
2204	/* the real target name */
2205	/* A lib.a(member) target is never :: */
2206	if (target->has_target_prop) {
2207		target = get_prop(target->prop, target_prop)->
2208		  body.target.target;
2209	}
2210	/* Bind the magic macros that make supplies */
2211	tmp_name = target;
2212	if(tmp_name != NULL) {
2213		if (tmp_name->has_vpath_alias_prop) {
2214			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2215					body.vpath_alias.alias;
2216		}
2217	}
2218	(void) SETVAR(c_at, tmp_name, false);
2219
2220	tmp_name = line->body.line.star;
2221	if(tmp_name != NULL) {
2222		if (tmp_name->has_vpath_alias_prop) {
2223			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2224					body.vpath_alias.alias;
2225		}
2226	}
2227	(void) SETVAR(star, tmp_name, false);
2228
2229	tmp_name = line->body.line.less;
2230	if(tmp_name != NULL) {
2231		if (tmp_name->has_vpath_alias_prop) {
2232			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2233					body.vpath_alias.alias;
2234		}
2235	}
2236	(void) SETVAR(less_name, tmp_name, false);
2237
2238	tmp_name = line->body.line.percent;
2239	if(tmp_name != NULL) {
2240		if (tmp_name->has_vpath_alias_prop) {
2241			tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)->
2242					body.vpath_alias.alias;
2243		}
2244	}
2245	(void) SETVAR(percent_name, tmp_name, false);
2246
2247	/* $? is seldom used and it is expensive to build */
2248	/* so we store the list form and build the string on demand */
2249	Chain query_list = NULL;
2250	Chain *query_list_tail = &query_list;
2251
2252	for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) {
2253		*query_list_tail = ALLOC(Chain);
2254		(*query_list_tail)->name = ch->name;
2255		if ((*query_list_tail)->name->has_vpath_alias_prop) {
2256			(*query_list_tail)->name =
2257				get_prop((*query_list_tail)->name->prop,
2258					vpath_alias_prop)->body.vpath_alias.alias;
2259		}
2260		(*query_list_tail)->next = NULL;
2261		query_list_tail = &(*query_list_tail)->next;
2262	}
2263	(void) setvar_daemon(query,
2264			     (Name) query_list,
2265			     false,
2266			     chain_daemon,
2267                             false,
2268                             debug_level);
2269
2270	/* build $^ */
2271	Chain hat_list = NULL;
2272	Chain *hat_list_tail = &hat_list;
2273
2274	for (Dependency dependency = line->body.line.dependencies;
2275		dependency != NULL;
2276		dependency = dependency->next) {
2277		/* skip automatic dependencies */
2278		if (!dependency->automatic) {
2279			if ((dependency->name != force) &&
2280				(dependency->stale == false)) {
2281				*hat_list_tail = ALLOC(Chain);
2282
2283				if (dependency->name->is_member &&
2284					(get_prop(dependency->name->prop, member_prop) != NULL)) {
2285					(*hat_list_tail)->name =
2286							get_prop(dependency->name->prop,
2287								member_prop)->body.member.member;
2288				} else {
2289					(*hat_list_tail)->name = dependency->name;
2290				}
2291
2292				if((*hat_list_tail)->name != NULL) {
2293					if ((*hat_list_tail)->name->has_vpath_alias_prop) {
2294						(*hat_list_tail)->name =
2295							get_prop((*hat_list_tail)->name->prop,
2296								vpath_alias_prop)->body.vpath_alias.alias;
2297					}
2298				}
2299
2300				(*hat_list_tail)->next = NULL;
2301				hat_list_tail = &(*hat_list_tail)->next;
2302			}
2303		}
2304	}
2305	(void) setvar_daemon(hat,
2306			     (Name) hat_list,
2307			     false,
2308			     chain_daemon,
2309                             false,
2310                             debug_level);
2311
2312/* We have two command sequences we need to handle */
2313/* The old one that we probably read from .make.state */
2314/* and the new one we are building that will replace the old one */
2315/* Even when KEEP_STATE is not on we build a new command sequence and store */
2316/* it in the line prop. This command sequence is then executed by */
2317/* run_command(). If KEEP_STATE is on it is also later written to */
2318/* .make.state. The routine replaces the old command line by line with the */
2319/* new one trying to reuse Cmd_lines */
2320
2321	/* If there is no old command_used we have to start creating */
2322	/* Cmd_lines to keep the new cmd in */
2323	if (used == NULL) {
2324		new_command_longer = true;
2325		*insert = used = ALLOC(Cmd_line);
2326		used->next = NULL;
2327		used->command_line = NULL;
2328		insert = &used->next;
2329	}
2330	/* Run thru the template for the new command and build the expanded */
2331	/* new command lines */
2332	for (;
2333	     command_template != NULL;
2334	     command_template = command_template->next, insert = &used->next, used = *insert) {
2335		/* If there is no old command_used Cmd_line we need to */
2336		/* create one and say that cmd consistency failed */
2337		if (used == NULL) {
2338			new_command_longer = true;
2339			*insert = used = ALLOC(Cmd_line);
2340			used->next = NULL;
2341			used->command_line = empty_name;
2342		}
2343		/* Prepare the Cmd_line for the processing */
2344		/* The command line prefixes "@-=?" are stripped and that */
2345		/* information is saved in the Cmd_line */
2346		used->assign = false;
2347		used->ignore_error = ignore_errors;
2348		used->silent = silent;
2349		used->always_exec = false;
2350		/* Expand the macros in the command line */
2351		INIT_STRING_FROM_STACK(command_line, buffer);
2352		make_word_mentioned =
2353		  query_mentioned =
2354		    false;
2355		expand_value(command_template->command_line, &command_line, true);
2356		/* If the macro $(MAKE) is mentioned in the command */
2357		/* "make -n" runs actually execute the command */
2358		used->make_refd = make_word_mentioned;
2359		used->ignore_command_dependency = query_mentioned;
2360		/* Strip the prefixes */
2361		start = command_line.buffer.start;
2362		for (;
2363		     iswspace(*start) ||
2364		     (get_char_semantics_value(*start) & (int) command_prefix_sem);
2365		     start++) {
2366			switch (*start) {
2367			case question_char:
2368				used->ignore_command_dependency = true;
2369				break;
2370			case exclam_char:
2371				used->ignore_command_dependency = false;
2372				break;
2373			case equal_char:
2374				used->assign = true;
2375				break;
2376			case hyphen_char:
2377				used->ignore_error = true;
2378				break;
2379			case at_char:
2380				if (!do_not_exec_rule) {
2381					used->silent = true;
2382				}
2383				break;
2384			case plus_char:
2385				if(posix) {
2386				  used->always_exec  = true;
2387				}
2388				break;
2389			}
2390		}
2391		/* If all command lines of the template are prefixed with "?"*/
2392		/* the VIRTUAL_ROOT is not used for cmd consistency checks */
2393		if (!used->ignore_command_dependency) {
2394			ignore_all_command_dependency = false;
2395		}
2396		/* Internalize the expanded and stripped command line */
2397		new_command_line = GETNAME(start, FIND_LENGTH);
2398		if ((used->command_line == NULL) &&
2399		    (line->body.line.sccs_command)) {
2400			used->command_line = new_command_line;
2401			new_command_longer = false;
2402		}
2403		/* Compare it with the old one for command consistency */
2404		if (used->command_line != new_command_line) {
2405			Name vpath_translated = vpath_translation(new_command_line);
2406			if (keep_state &&
2407			    !used->ignore_command_dependency && (vpath_translated != used->command_line)) {
2408				if (debug_level > 0) {
2409					if (used->command_line != NULL
2410					    && *used->command_line->string_mb !=
2411					    '\0') {
2412						(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"),
2413							      recursion_level,
2414							      "",
2415							      target->string_mb,
2416							      vpath_translated->string_mb,
2417							      recursion_level,
2418							      "",
2419							      used->
2420							      command_line->
2421							      string_mb);
2422					} else {
2423						(void) printf(gettext("%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"),
2424							      recursion_level,
2425							      "",
2426							      target->string_mb,
2427							      vpath_translated->string_mb,
2428							      recursion_level,
2429							      "");
2430					}
2431				}
2432				command_changed = true;
2433                                line->body.line.is_out_of_date = true;
2434			}
2435			used->command_line = new_command_line;
2436		}
2437		if (command_line.free_after_use) {
2438			retmem(command_line.buffer.start);
2439		}
2440	}
2441	/* Check if the old command is longer than the new for */
2442	/* command consistency */
2443	if (used != NULL) {
2444		*insert = NULL;
2445		if (keep_state &&
2446		    !ignore_all_command_dependency) {
2447			if (debug_level > 0) {
2448				(void) printf(gettext("%*sBuilding %s because new command shorter than old\n"),
2449					      recursion_level,
2450					      "",
2451					      target->string_mb);
2452			}
2453			command_changed = true;
2454                        line->body.line.is_out_of_date = true;
2455		}
2456	}
2457	/* Check if the new command is longer than the old command for */
2458	/* command consistency */
2459	if (new_command_longer &&
2460	    !ignore_all_command_dependency &&
2461	    keep_state) {
2462		if (debug_level > 0) {
2463			(void) printf(gettext("%*sBuilding %s because new command longer than old\n"),
2464				      recursion_level,
2465				      "",
2466				      target->string_mb);
2467		}
2468		command_changed = true;
2469                line->body.line.is_out_of_date = true;
2470	}
2471	/* Unbind the magic macros */
2472	(void) SETVAR(c_at, (Name) NULL, false);
2473	(void) SETVAR(star, (Name) NULL, false);
2474	(void) SETVAR(less_name, (Name) NULL, false);
2475	(void) SETVAR(percent_name, (Name) NULL, false);
2476	(void) SETVAR(query, (Name) NULL, false);
2477        if (query_list != NULL) {
2478		delete_query_chain(query_list);
2479        }
2480	(void) SETVAR(hat, (Name) NULL, false);
2481        if (hat_list != NULL) {
2482		delete_query_chain(hat_list);
2483        }
2484
2485	if (conditional_macro_used) {
2486		target->conditional_macro_list = cond_macro_list;
2487		cond_macro_list = NULL;
2488		target->depends_on_conditional = true;
2489	}
2490}
2491
2492/*
2493 *	touch_command(line, target, result)
2494 *
2495 *	If this is an "make -t" run we do this.
2496 *	We touch all targets in the target group ("foo + fie:") if any.
2497 *
2498 *	Return value:
2499 *				Indicates if the command failed or not
2500 *
2501 *	Parameters:
2502 *		line		The command line to update
2503 *		target		The target we are touching
2504 *		result		Initial value for the result we return
2505 *
2506 *	Global variables used:
2507 *		do_not_exec_rule Indicates that -n is on
2508 *		silent		Do not echo commands
2509 */
2510static Doname
2511touch_command(register Property line, register Name target, Doname result)
2512{
2513	Name			name;
2514	register Chain		target_group;
2515	String_rec		touch_string;
2516	wchar_t			buffer[MAXPATHLEN];
2517	Name			touch_cmd;
2518	Cmd_line		rule;
2519
2520	for (name = target, target_group = NULL; name != NULL;) {
2521		if (!name->is_member) {
2522			/*
2523			 * Build a touch command that can be passed
2524			 * to dosys(). If KEEP_STATE is on, "make -t"
2525			 * will save the proper command, not the
2526			 * "touch" in .make.state.
2527			 */
2528			INIT_STRING_FROM_STACK(touch_string, buffer);
2529			MBSTOWCS(wcs_buffer, "touch ");
2530			append_string(wcs_buffer, &touch_string, FIND_LENGTH);
2531			touch_cmd = name;
2532			if (name->has_vpath_alias_prop) {
2533				touch_cmd = get_prop(name->prop,
2534						 vpath_alias_prop)->
2535						   body.vpath_alias.alias;
2536			}
2537			APPEND_NAME(touch_cmd,
2538				      &touch_string,
2539				      FIND_LENGTH);
2540			touch_cmd = GETNAME(touch_string.buffer.start,
2541					    FIND_LENGTH);
2542			if (touch_string.free_after_use) {
2543				retmem(touch_string.buffer.start);
2544			}
2545			if (!silent ||
2546			    do_not_exec_rule &&
2547			    (target_group == NULL)) {
2548				(void) printf("%s\n", touch_cmd->string_mb);
2549			}
2550			/* Run the touch command, or simulate it */
2551			if (!do_not_exec_rule) {
2552				result = dosys(touch_cmd,
2553					       false,
2554					       false,
2555					       false,
2556					       false,
2557					       name);
2558			} else {
2559				result = build_ok;
2560			}
2561		} else {
2562			result = build_ok;
2563		}
2564		if (target_group == NULL) {
2565			target_group = line->body.line.target_group;
2566		} else {
2567			target_group = target_group->next;
2568		}
2569		if (target_group != NULL) {
2570			name = target_group->name;
2571		} else {
2572			name = NULL;
2573		}
2574	}
2575	return result;
2576}
2577
2578/*
2579 *	update_target(line, result)
2580 *
2581 *	updates the status of a target after executing its commands.
2582 *
2583 *	Parameters:
2584 *		line		The command line block to update
2585 *		result		Indicates that build is OK so can update
2586 *
2587 *	Global variables used:
2588 *		do_not_exec_rule Indicates that -n is on
2589 *		touch		Fake the new timestamp if we are just touching
2590 */
2591void
2592update_target(Property line, Doname result)
2593{
2594	Name			target;
2595	Chain			target_group;
2596	Property		line2;
2597	timestruc_t		old_stat_time;
2598	Property		member;
2599
2600	/*
2601	 * [tolik] Additional fix for bug 1063790. It was fixed
2602	 * for serial make long ago, but DMake dumps core when
2603	 * target is a symlink and sccs file is newer then target.
2604	 * In this case, finish_children() calls update_target()
2605	 * with line==NULL.
2606	 */
2607	if(line == NULL) {
2608		/* XXX. Should we do anything here? */
2609		return;
2610	}
2611
2612	target = line->body.line.target;
2613
2614	if ((result == build_ok) && (line->body.line.command_used != NULL)) {
2615		if (do_not_exec_rule ||
2616		    touch ||
2617		    (target->is_member &&
2618		     (line->body.line.command_template != NULL) &&
2619		     (line->body.line.command_template->command_line->string_mb[0] == 0) &&
2620		     (line->body.line.command_template->next == NULL))) {
2621			/* If we are simulating execution we need to fake a */
2622			/* new timestamp for the target we didnt build */
2623			target->stat.time = file_max_time;
2624		} else {
2625			/*
2626			 * If we really built the target we read the new
2627			 * timestamp.
2628			 * Fix for bug #1110906: if .c file is newer than
2629			 * the corresponding .o file which is in an archive
2630			 * file, make will compile the .c file but it won't
2631			 * update the object in the .a file.
2632			 */
2633			old_stat_time = target->stat.time;
2634			target->stat.time = file_no_time;
2635			(void) exists(target);
2636			if ((target->is_member) &&
2637			    (target->stat.time == old_stat_time)) {
2638				member = get_prop(target->prop, member_prop);
2639				if (member != NULL) {
2640					target->stat.time = member->body.member.library->stat.time;
2641					target->stat.time.tv_sec++;
2642				}
2643			}
2644		}
2645		/* If the target is part of a group we need to propagate the */
2646		/* result of the run to all members */
2647		for (target_group = line->body.line.target_group;
2648		     target_group != NULL;
2649		     target_group = target_group->next) {
2650			target_group->name->stat.time = target->stat.time;
2651			line2 = maybe_append_prop(target_group->name,
2652						  line_prop);
2653			line2->body.line.command_used =
2654			  line->body.line.command_used;
2655			line2->body.line.target = target_group->name;
2656		}
2657	}
2658	target->has_built = true;
2659}
2660
2661/*
2662 *	sccs_get(target, command)
2663 *
2664 *	Figures out if it possible to sccs get a file
2665 *	and builds the command to do it if it is.
2666 *
2667 *	Return value:
2668 *				Indicates if sccs get failed or not
2669 *
2670 *	Parameters:
2671 *		target		Target to get
2672 *		command		Where to deposit command to use
2673 *
2674 *	Global variables used:
2675 *		debug_level	Should we trace activities?
2676 *		recursion_level	Used for tracing
2677 *		sccs_get_rule	The rule to used for sccs getting
2678 */
2679static Doname
2680sccs_get(register Name target, register Property *command)
2681{
2682	register int		result;
2683	char			link[MAXPATHLEN];
2684	String_rec		string;
2685	wchar_t			name[MAXPATHLEN];
2686	register wchar_t	*p;
2687	timestruc_t		sccs_time;
2688	register Property	line;
2689	int			sym_link_depth = 0;
2690
2691	/* For sccs, we need to chase symlinks. */
2692        while (target->stat.is_sym_link) {
2693		if (sym_link_depth++ > 90) {
2694			fatal(gettext("Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."),
2695			      target->string_mb);
2696		}
2697                /* Read the value of the link. */
2698                result = readlink_vroot(target->string_mb,
2699					link,
2700					sizeof(link),
2701					NULL,
2702					VROOT_DEFAULT);
2703                if (result == -1) {
2704                        fatal(gettext("Can't read symbolic link `%s': %s"),
2705                              target->string_mb, errmsg(errno));
2706		}
2707		link[result] = 0;
2708                /* Use the value to build the proper filename. */
2709                INIT_STRING_FROM_STACK(string, name);
2710
2711		Wstring wcb(target);
2712                if ((link[0] != slash_char) &&
2713                    ((p = (wchar_t *) wcsrchr(wcb.get_string(), slash_char)) != NULL)) {
2714                        append_string(wcb.get_string(), &string, p - wcb.get_string() + 1);
2715		}
2716                append_string(link, &string, result);
2717                /* Replace the old name with the translated name. */
2718		target = normalize_name(string.buffer.start, string.text.p - string.buffer.start);
2719                (void) exists(target);
2720                if (string.free_after_use) {
2721                        retmem(string.buffer.start);
2722		}
2723        }
2724
2725	/*
2726	 * read_dir() also reads the ?/SCCS dir and saves information
2727	 * about which files have SCSC/s. files.
2728	 */
2729	if (target->stat.has_sccs == DONT_KNOW_SCCS) {
2730		read_directory_of_file(target);
2731	}
2732	switch (target->stat.has_sccs) {
2733	case DONT_KNOW_SCCS:
2734		/* We dont know by now there is no SCCS/s.* */
2735		target->stat.has_sccs = NO_SCCS;
2736		/* FALLTHROUGH */
2737	case NO_SCCS:
2738		/*
2739		 * If there is no SCCS/s.* but the plain file exists,
2740		 * we say things are OK.
2741		 */
2742		if (target->stat.time > file_doesnt_exist) {
2743			return build_ok;
2744		}
2745		/* If we cant find the plain file, we give up. */
2746		return build_dont_know;
2747	case HAS_SCCS:
2748		/*
2749		 * Pay dirt. We now need to figure out if the plain file
2750		 * is out of date relative to the SCCS/s.* file.
2751		 */
2752		sccs_time = exists(get_prop(target->prop,
2753					    sccs_prop)->body.sccs.file);
2754		break;
2755	}
2756
2757	if ((!target->has_complained &&
2758	    (sccs_time != file_doesnt_exist) &&
2759	    (sccs_get_rule != NULL))) {
2760		/* only checking */
2761		if (command == NULL) {
2762			return build_ok;
2763		}
2764		/*
2765		 * We provide a command line for the target. The line is a
2766		 * "sccs get" command from default.mk.
2767		 */
2768		line = maybe_append_prop(target, line_prop);
2769		*command = line;
2770		if (sccs_time > target->stat.time) {
2771			/*
2772			 * And only if the plain file is out of date do we
2773			 * request execution of the command.
2774			 */
2775			line->body.line.is_out_of_date = true;
2776			if (debug_level > 0) {
2777				(void) printf(gettext("%*sSccs getting %s because s. file is younger than source file\n"),
2778					      recursion_level,
2779					      "",
2780					      target->string_mb);
2781			}
2782		}
2783		line->body.line.sccs_command = true;
2784		line->body.line.command_template = sccs_get_rule;
2785		if(!svr4 && (!allrules_read || posix)) {
2786		   if((target->prop) &&
2787		      (target->prop->body.sccs.file) &&
2788		      (target->prop->body.sccs.file->string_mb)) {
2789		      if((strlen(target->prop->body.sccs.file->string_mb) ==
2790			strlen(target->string_mb) + 2) &&
2791		        (target->prop->body.sccs.file->string_mb[0] == 's') &&
2792		        (target->prop->body.sccs.file->string_mb[1] == '.')) {
2793
2794		         line->body.line.command_template = get_posix_rule;
2795		      }
2796		   }
2797		}
2798		line->body.line.target = target;
2799		/*
2800		 * Also make sure the rule is build with $* and $<
2801		 * bound properly.
2802		 */
2803		line->body.line.star = NULL;
2804		line->body.line.less = NULL;
2805		line->body.line.percent = NULL;
2806		return build_ok;
2807	}
2808	return build_dont_know;
2809}
2810
2811/*
2812 *	read_directory_of_file(file)
2813 *
2814 *	Reads the directory the specified file lives in.
2815 *
2816 *	Parameters:
2817 *		file		The file we need to read dir for
2818 *
2819 *	Global variables used:
2820 *		dot		The Name ".", used as the default dir
2821 */
2822void
2823read_directory_of_file(register Name file)
2824{
2825
2826	Wstring file_string(file);
2827	wchar_t * wcb = file_string.get_string();
2828	wchar_t usr_include_buf[MAXPATHLEN];
2829	wchar_t usr_include_sys_buf[MAXPATHLEN];
2830
2831	register Name		directory = dot;
2832	register wchar_t	*p = (wchar_t *) wcsrchr(wcb,
2833							(int) slash_char);
2834	register int		length = p - wcb;
2835	static Name		usr_include;
2836	static Name		usr_include_sys;
2837
2838	if (usr_include == NULL) {
2839		MBSTOWCS(usr_include_buf, "/usr/include");
2840		usr_include = GETNAME(usr_include_buf, FIND_LENGTH);
2841		MBSTOWCS(usr_include_sys_buf, "/usr/include/sys");
2842		usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH);
2843	}
2844
2845	/*
2846	 * If the filename contains a "/" we have to extract the path
2847	 * Else the path defaults to ".".
2848	 */
2849	if (p != NULL) {
2850		/*
2851		 * Check some popular directories first to possibly
2852		 * save time. Compare string length first to gain speed.
2853		 */
2854		if ((usr_include->hash.length == length) &&
2855		    IS_WEQUALN(usr_include_buf,
2856			       wcb,
2857			       length)) {
2858			directory = usr_include;
2859		} else if ((usr_include_sys->hash.length == length) &&
2860		           IS_WEQUALN(usr_include_sys_buf,
2861		                      wcb,
2862		                      length)) {
2863			directory = usr_include_sys;
2864		} else {
2865			directory = GETNAME(wcb, length);
2866		}
2867	}
2868	(void) read_dir(directory,
2869			(wchar_t *) NULL,
2870			(Property) NULL,
2871			(wchar_t *) NULL);
2872}
2873
2874/*
2875 *	add_pattern_conditionals(target)
2876 *
2877 *	Scan the list of conditionals defined for pattern targets and add any
2878 *	that match this target to its list of conditionals.
2879 *
2880 *	Parameters:
2881 *		target		The target we should add conditionals for
2882 *
2883 *	Global variables used:
2884 *		conditionals	The list of pattern conditionals
2885 */
2886static void
2887add_pattern_conditionals(register Name target)
2888{
2889	register Property	conditional;
2890	Property		new_prop;
2891	Property		*previous;
2892	Name_rec		dummy;
2893	wchar_t			*pattern;
2894	wchar_t			*percent;
2895	int			length;
2896
2897	Wstring wcb(target);
2898	Wstring wcb1;
2899
2900	for (conditional = get_prop(conditionals->prop, conditional_prop);
2901	     conditional != NULL;
2902	     conditional = get_prop(conditional->next, conditional_prop)) {
2903		wcb1.init(conditional->body.conditional.target);
2904		pattern = wcb1.get_string();
2905		if (pattern[1] != 0) {
2906			percent = (wchar_t *) wcschr(pattern, (int) percent_char);
2907			/* Check for possible buffer under-read */
2908			if ((length = wcb.length()-wcslen(percent+1)) <= 0) {
2909				continue;
2910			}
2911			if (!wcb.equaln(pattern, percent-pattern) ||
2912			    !IS_WEQUAL(wcb.get_string(length), percent+1)) {
2913				continue;
2914			}
2915		}
2916		for (previous = &target->prop;
2917		     *previous != NULL;
2918		     previous = &(*previous)->next) {
2919			if (((*previous)->type == conditional_prop) &&
2920			    ((*previous)->body.conditional.sequence >
2921			     conditional->body.conditional.sequence)) {
2922				break;
2923			}
2924		}
2925		if (*previous == NULL) {
2926			new_prop = append_prop(target, conditional_prop);
2927		} else {
2928			dummy.prop = NULL;
2929			new_prop = append_prop(&dummy, conditional_prop);
2930			new_prop->next = *previous;
2931			*previous = new_prop;
2932		}
2933		target->conditional_cnt++;
2934		new_prop->body.conditional = conditional->body.conditional;
2935	}
2936}
2937
2938/*
2939 *	set_locals(target, old_locals)
2940 *
2941 *	Sets any conditional macros for the target.
2942 *	Each target carries a possibly empty set of conditional properties.
2943 *
2944 *	Parameters:
2945 *		target		The target to set conditional macros for
2946 *		old_locals	Space to store old values in
2947 *
2948 *	Global variables used:
2949 *		debug_level	Should we trace activity?
2950 *		is_conditional	We need to preserve this value
2951 *		recursion_level	Used for tracing
2952 */
2953void
2954set_locals(register Name target, register Property old_locals)
2955{
2956	register Property	conditional;
2957	register int		i;
2958	register Boolean	saved_conditional_macro_used;
2959	Chain			cond_name;
2960	Chain			cond_chain;
2961
2962	if (target->dont_activate_cond_values) {
2963		return;
2964	}
2965
2966	saved_conditional_macro_used = conditional_macro_used;
2967
2968	/* Scan the list of conditional properties and apply each one */
2969	for (conditional = get_prop(target->prop, conditional_prop), i = 0;
2970	     conditional != NULL;
2971	     conditional = get_prop(conditional->next, conditional_prop),
2972	     i++) {
2973		/* Save the old value */
2974		old_locals[i].body.macro =
2975		  maybe_append_prop(conditional->body.conditional.name,
2976				    macro_prop)->body.macro;
2977		if (debug_level > 1) {
2978			(void) printf(gettext("%*sActivating conditional value: "),
2979				      recursion_level,
2980				      "");
2981		}
2982		/* Set the conditional value. Macros are expanded when the */
2983		/* macro is refd as usual */
2984		if ((conditional->body.conditional.name != virtual_root) ||
2985		    (conditional->body.conditional.value != virtual_root)) {
2986			(void) SETVAR(conditional->body.conditional.name,
2987				      conditional->body.conditional.value,
2988				      (Boolean) conditional->body.conditional.append);
2989		}
2990		cond_name = ALLOC(Chain);
2991		cond_name->name = conditional->body.conditional.name;
2992	}
2993	/* Put this target on the front of the chain of conditional targets */
2994	cond_chain = ALLOC(Chain);
2995	cond_chain->name = target;
2996	cond_chain->next = conditional_targets;
2997	conditional_targets = cond_chain;
2998	conditional_macro_used = saved_conditional_macro_used;
2999}
3000
3001/*
3002 *	reset_locals(target, old_locals, conditional, index)
3003 *
3004 *	Removes any conditional macros for the target.
3005 *
3006 *	Parameters:
3007 *		target		The target we are retoring values for
3008 *		old_locals	The values to restore
3009 *		conditional	The first conditional block for the target
3010 *		index		into the old_locals vector
3011 *	Global variables used:
3012 *		debug_level	Should we trace activities?
3013 *		recursion_level	Used for tracing
3014 */
3015void
3016reset_locals(register Name target, register Property old_locals, register Property conditional, register int index)
3017{
3018	register Property	this_conditional;
3019	Chain			cond_chain;
3020
3021	if (target->dont_activate_cond_values) {
3022		return;
3023	}
3024
3025	/* Scan the list of conditional properties and restore the old value */
3026	/* to each one Reverse the order relative to when we assigned macros */
3027	this_conditional = get_prop(conditional->next, conditional_prop);
3028	if (this_conditional != NULL) {
3029		reset_locals(target, old_locals, this_conditional, index+1);
3030	} else {
3031		/* Remove conditional target from chain */
3032		if (conditional_targets == NULL ||
3033		    conditional_targets->name != target) {
3034			warning(gettext("Internal error: reset target not at head of condtional_targets chain"));
3035		} else {
3036			cond_chain = conditional_targets->next;
3037			retmem_mb((caddr_t) conditional_targets);
3038			conditional_targets = cond_chain;
3039		}
3040	}
3041	get_prop(conditional->body.conditional.name->prop,
3042		 macro_prop)->body.macro = old_locals[index].body.macro;
3043	if (conditional->body.conditional.name == virtual_root) {
3044		(void) SETVAR(virtual_root, getvar(virtual_root), false);
3045	}
3046	if (debug_level > 1) {
3047		if (old_locals[index].body.macro.value != NULL) {
3048			(void) printf(gettext("%*sdeactivating conditional value: %s= %s\n"),
3049				      recursion_level,
3050				      "",
3051				      conditional->body.conditional.name->
3052				      string_mb,
3053				      old_locals[index].body.macro.value->
3054				      string_mb);
3055		} else {
3056			(void) printf(gettext("%*sdeactivating conditional value: %s =\n"),
3057				      recursion_level,
3058				      "",
3059				      conditional->body.conditional.name->
3060				      string_mb);
3061		}
3062	}
3063}
3064
3065/*
3066 *	check_auto_dependencies(target, auto_count, automatics)
3067 *
3068 *	Returns true if the target now has a dependency
3069 *	it didn't previously have (saved on automatics).
3070 *
3071 *	Return value:
3072 *				true if new dependency found
3073 *
3074 *	Parameters:
3075 *		target		Target we check
3076 *		auto_count	Number of old automatic vars
3077 *		automatics	Saved old automatics
3078 *
3079 *	Global variables used:
3080 *		keep_state	Indicates that .KEEP_STATE is on
3081 */
3082Boolean
3083check_auto_dependencies(Name target, int auto_count, Name *automatics)
3084{
3085	Name		*p;
3086	int		n;
3087	Property	line;
3088	Dependency	dependency;
3089
3090	if (keep_state) {
3091		if ((line = get_prop(target->prop, line_prop)) == NULL) {
3092			return false;
3093		}
3094		/* Go thru new list of automatic depes */
3095		for (dependency = line->body.line.dependencies;
3096		     dependency != NULL;
3097		     dependency = dependency->next) {
3098			/* And make sure that each one existed before we */
3099			/* built the target */
3100			if (dependency->automatic && !dependency->stale) {
3101				for (n = auto_count, p = automatics;
3102				     n > 0;
3103				     n--) {
3104					if (*p++ == dependency->name) {
3105						/* If we can find it on the */
3106						/* saved list of autos we */
3107						/* are OK  */
3108						goto not_new;
3109					}
3110				}
3111				/* But if we scan over the old list */
3112				/* of auto. without finding it it is */
3113				/* new and we must check it */
3114				return true;
3115			}
3116		not_new:;
3117		}
3118		return false;
3119	} else {
3120		return false;
3121	}
3122}
3123
3124
3125// Recursively delete each of the Chain struct on the chain.
3126
3127static void
3128delete_query_chain(Chain ch)
3129{
3130	if (ch == NULL) {
3131		return;
3132	} else {
3133		delete_query_chain(ch->next);
3134		retmem_mb((char *) ch);
3135	}
3136}
3137
3138Doname
3139target_can_be_built(register Name target) {
3140	Doname		result = build_dont_know;
3141	Name		true_target = target;
3142	Property	line;
3143
3144	if (target == wait_name) {
3145		return(build_ok);
3146	}
3147	/*
3148	 * If the target is a constructed one for a "::" target,
3149	 * we need to consider that.
3150	 */
3151	if (target->has_target_prop) {
3152		true_target = get_prop(target->prop,
3153				       target_prop)->body.target.target;
3154	}
3155
3156	(void) exists(true_target);
3157
3158	if (true_target->state == build_running) {
3159		return(build_running);
3160	}
3161	if (true_target->stat.time != file_doesnt_exist) {
3162		result = build_ok;
3163	}
3164
3165	/* get line property for the target */
3166	line = get_prop(true_target->prop, line_prop);
3167
3168	/* first check for explicit rule */
3169	if (line != NULL && line->body.line.command_template != NULL) {
3170		result = build_ok;
3171	}
3172	/* try to find pattern rule */
3173	if (result == build_dont_know) {
3174		result = find_percent_rule(target, NULL, false);
3175	}
3176
3177	/* try to find double suffix rule */
3178	if (result == build_dont_know) {
3179		if (target->is_member) {
3180			Property member = get_prop(target->prop, member_prop);
3181			if (member != NULL && member->body.member.member != NULL) {
3182				result = find_ar_suffix_rule(target, member->body.member.member, NULL, false);
3183			} else {
3184				result = find_double_suffix_rule(target, NULL, false);
3185			}
3186		} else {
3187			result = find_double_suffix_rule(target, NULL, false);
3188		}
3189	}
3190
3191	/* try to find suffix rule */
3192	if ((result == build_dont_know) && second_pass) {
3193		result = find_suffix_rule(target, target, empty_name, NULL, false);
3194	}
3195
3196	/* check for sccs */
3197	if (result == build_dont_know) {
3198		result = sccs_get(target, NULL);
3199	}
3200
3201	/* try to find dyn target */
3202	if (result == build_dont_know) {
3203		Name dtarg = find_dyntarget(target);
3204		if (dtarg != NULL) {
3205			result = target_can_be_built(dtarg);
3206		}
3207	}
3208
3209	/* check whether target was mentioned in makefile */
3210	if (result == build_dont_know) {
3211		if (target->colons != no_colon) {
3212			result = build_ok;
3213		}
3214	}
3215
3216	/* result */
3217	return result;
3218}
3219