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 2003 Sun Microsystems, Inc. All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Included files
28  */
29 #include <mk/defs.h>
30 #include <mksh/misc.h>		/* get_prop() */
31 
32 /*
33  * File table of contents
34  */
35 void   print_dependencies(register Name target, register Property line);
36 static void	print_deps(register Name target, register Property line);
37 static void	print_more_deps(Name target, Name name);
38 static void	print_filename(Name name);
39 static Boolean	should_print_dep(Property line);
40 static void	print_forest(Name target);
41 static void	print_deplist(Dependency head);
42 void		print_value(register Name value, Daemon daemon);
43 static void	print_rule(register Name target);
44 static	void	print_rec_info(Name target);
45 static Boolean	is_out_of_date(Property line);
46 extern void depvar_print_results (void);
47 
48 /*
49  *	print_dependencies(target, line)
50  *
51  *	Print all the dependencies of a target. First print all the Makefiles.
52  *	Then print all the dependencies. Finally, print all the .INIT
53  *	dependencies.
54  *
55  *	Parameters:
56  *		target		The target we print dependencies for
57  *		line		We get the dependency list from here
58  *
59  *	Global variables used:
60  *		done		The Name ".DONE"
61  *		init		The Name ".INIT"
62  *		makefiles_used	List of all makefiles read
63  */
64 void
print_dependencies(register Name target,register Property line)65 print_dependencies(register Name target, register Property line)
66 {
67 	Dependency	dp;
68 	static Boolean	makefiles_printed = false;
69 
70 	if (target_variants) {
71 		depvar_print_results();
72 	}
73 
74 	if (!makefiles_printed) {
75 		/*
76 		 * Search the makefile list for the primary makefile,
77 		 * then print it and its inclusions.  After that go back
78 		 * and print the default.mk file and its inclusions.
79 		 */
80 		for (dp = makefiles_used; dp != NULL; dp = dp->next) {
81 			if (dp->name == primary_makefile) {
82 				break;
83 			}
84 		}
85 		if (dp) {
86 			print_deplist(dp);
87 			for (dp = makefiles_used; dp != NULL; dp = dp->next) {
88 				if (dp->name == primary_makefile) {
89 					break;
90 				}
91 				(void)printf(" %s", dp->name->string_mb);
92 			}
93 		}
94 		(void) printf("\n");
95 		makefiles_printed = true;
96 	}
97 	print_deps(target, line);
98 /*
99 	print_more_deps(target, init);
100 	print_more_deps(target, done);
101  */
102 	if (target_variants) {
103 		print_forest(target);
104 	}
105 }
106 
107 /*
108  *	print_more_deps(target, name)
109  *
110  *	Print some special dependencies.
111  *	These are the dependencies for the .INIT and .DONE targets.
112  *
113  *	Parameters:
114  *		target		Target built during make run
115  *		name		Special target to print dependencies for
116  *
117  *	Global variables used:
118  */
119 static void
print_more_deps(Name target,Name name)120 print_more_deps(Name target, Name name)
121 {
122 	Property	line;
123 	register Dependency	dependencies;
124 
125 	line = get_prop(name->prop, line_prop);
126 	if (line != NULL && line->body.line.dependencies != NULL) {
127 		(void) printf("%s:\t", target->string_mb);
128 		print_deplist(line->body.line.dependencies);
129 		(void) printf("\n");
130 		for (dependencies= line->body.line.dependencies;
131 		     dependencies != NULL;
132 		     dependencies= dependencies->next) {
133 	                 print_deps(dependencies->name,
134 				 get_prop(dependencies->name->prop, line_prop));
135 		}
136 	}
137 }
138 
139 /*
140  *	print_deps(target, line, go_recursive)
141  *
142  *	Print a regular dependency list.  Append to this information which
143  *	indicates whether or not the target is recursive.
144  *
145  *	Parameters:
146  *		target		target to print dependencies for
147  *		line		We get the dependency list from here
148  *		go_recursive	Should we show all dependencies recursively?
149  *
150  *	Global variables used:
151  *		recursive_name	The Name ".RECURSIVE", printed
152  */
153 static void
print_deps(register Name target,register Property line)154 print_deps(register Name target, register Property line)
155 {
156 	register Dependency	dep;
157 
158 	if ((target->dependency_printed) ||
159 	    (target == force)) {
160 		return;
161 	}
162 	target->dependency_printed = true;
163 
164 	/* only print entries that are actually derived and are not leaf
165 	 * files and are not the result of sccs get.
166 	 */
167 	if (should_print_dep(line)) {
168 		if ((report_dependencies_level == 2) ||
169 		    (report_dependencies_level == 4)) {
170 			if (is_out_of_date(line)) {
171 			        (void) printf("1 ");
172 			} else {
173 			        (void) printf("0 ");
174 			}
175 		}
176 		print_filename(target);
177 		(void) printf(":\t");
178 		print_deplist(line->body.line.dependencies);
179 		print_rec_info(target);
180 		(void) printf("\n");
181 		for (dep = line->body.line.dependencies;
182 		     dep != NULL;
183 		     dep = dep->next) {
184 			print_deps(dep->name,
185 			           get_prop(dep->name->prop, line_prop));
186 		}
187 	}
188 }
189 
190 static Boolean
is_out_of_date(Property line)191 is_out_of_date(Property line)
192 {
193 	Dependency	dep;
194 	Property	line2;
195 
196 	if (line == NULL) {
197 		return false;
198 	}
199 	if (line->body.line.is_out_of_date) {
200 		return true;
201 	}
202 	for (dep = line->body.line.dependencies;
203 	     dep != NULL;
204 	     dep = dep->next) {
205 		line2 = get_prop(dep->name->prop, line_prop);
206 		if (is_out_of_date(line2)) {
207 			line->body.line.is_out_of_date = true;
208 			return true;
209 		}
210 	}
211 	return false;
212 }
213 
214 /*
215  * Given a dependency print it and all its siblings.
216  */
217 static void
print_deplist(Dependency head)218 print_deplist(Dependency head)
219 {
220 	Dependency	dp;
221 
222 	for (dp = head; dp != NULL; dp = dp->next) {
223 		if ((report_dependencies_level != 2) ||
224 		    ((!dp->automatic) ||
225 		     (dp->name->is_double_colon))) {
226 			if (dp->name != force) {
227 				putwchar(' ');
228 				print_filename(dp->name);
229 			}
230 		}
231 	}
232 }
233 
234 /*
235  * Print the name of a file for the -P option.
236  * If the file is a directory put on a trailing slash.
237  */
238 static void
print_filename(Name name)239 print_filename(Name name)
240 {
241 	(void) printf("%s", name->string_mb);
242 /*
243 	if (name->stat.is_dir) {
244 		putwchar('/');
245 	}
246  */
247 }
248 
249 /*
250  *	should_print_dep(line)
251  *
252  *	Test if we should print the dependencies of this target.
253  *	The line must exist and either have children dependencies
254  *	or have a command that is not an SCCS command.
255  *
256  *	Return value:
257  *				true if the dependencies should be printed
258  *
259  *	Parameters:
260  *		line		We get the dependency list from here
261  *
262  *	Global variables used:
263  */
264 static Boolean
should_print_dep(Property line)265 should_print_dep(Property line)
266 {
267 	if (line == NULL) {
268 		return false;
269 	}
270 	if (line->body.line.dependencies != NULL) {
271 		return true;
272 	}
273 	if (line->body.line.sccs_command) {
274 		return false;
275 	}
276 	return true;
277 }
278 
279 /*
280  * Print out the root nodes of all the dependency trees
281  * in this makefile.
282  */
283 static void
print_forest(Name target)284 print_forest(Name target)
285 {
286 	Name_set::iterator np, e;
287 	Property	line;
288 
289 	for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
290 			if (np->is_target && !np->has_parent && np != target) {
291 				(void) doname_check(np, true, false, false);
292 				line = get_prop(np->prop, line_prop);
293 				printf("-\n");
294 				print_deps(np, line);
295 			}
296 	}
297 }
298 
299 
300 /*
301  *	This is a set  of routines for dumping the internal make state
302  *	Used for the -p option
303  */
304 void
print_value(register Name value,Daemon daemon)305 print_value(register Name value, Daemon daemon)
306 {
307 	Chain			cp;
308 
309 	if (value == NULL)
310 		(void)printf("=\n");
311 	else
312 		switch (daemon) {
313 		    case no_daemon:
314 			(void)printf("= %s\n", value->string_mb);
315 			break;
316 		    case chain_daemon:
317 			for (cp= (Chain) value; cp != NULL; cp= cp->next)
318 				(void)printf(cp->next == NULL ? "%s" : "%s ",
319 					cp->name->string_mb);
320 			(void)printf("\n");
321 			break;
322 		};
323 }
324 
325 static void
print_rule(register Name target)326 print_rule(register Name target)
327 {
328 	register Cmd_line	rule;
329 	register Property	line;
330 
331 	if (((line= get_prop(target->prop, line_prop)) == NULL) ||
332 	    ((line->body.line.command_template == NULL) &&
333 	     (line->body.line.dependencies == NULL)))
334 		return;
335 	print_dependencies(target, line);
336 	for (rule= line->body.line.command_template; rule != NULL; rule= rule->next)
337 		(void)printf("\t%s\n", rule->command_line->string_mb);
338 }
339 
340 
341 /*
342  *  If target is recursive,  print the following to standard out:
343  *	.RECURSIVE subdir targ Makefile
344  */
345 static void
print_rec_info(Name target)346 print_rec_info(Name target)
347 {
348 	Recursive_make	rp;
349 	wchar_t		*colon;
350 
351 	report_recursive_init();
352 
353 	rp = find_recursive_target(target);
354 
355 	if (rp) {
356 		/*
357 		 * if found,  print starting with the space after the ':'
358 		 */
359 		colon = (wchar_t *) wcschr(rp->oldline, (int) colon_char);
360 		(void) printf("%s", colon + 1);
361 	}
362 }
363 
364