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