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