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