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
308 {
309 Chain cp;
310
311 if (value == NULL)
312 (void)printf("=\n");
313 else
314 switch (daemon) {
315 case no_daemon:
316 (void)printf("= %s\n", value->string_mb);
317 break;
318 case chain_daemon:
319 for (cp= (Chain) value; cp != NULL; cp= cp->next)
320 (void)printf(cp->next == NULL ? "%s" : "%s ",
321 cp->name->string_mb);
322 (void)printf("\n");
323 break;
324 };
325 }
326
327 static void
print_rule(register Name target)328 print_rule(register Name target)
329 {
330 register Cmd_line rule;
331 register Property line;
332
333 if (((line= get_prop(target->prop, line_prop)) == NULL) ||
334 ((line->body.line.command_template == NULL) &&
335 (line->body.line.dependencies == NULL)))
336 return;
337 print_dependencies(target, line);
338 for (rule= line->body.line.command_template; rule != NULL; rule= rule->next)
339 (void)printf("\t%s\n", rule->command_line->string_mb);
340 }
341
342
343 /*
344 * If target is recursive, print the following to standard out:
345 * .RECURSIVE subdir targ Makefile
346 */
347 static void
print_rec_info(Name target)348 print_rec_info(Name target)
349 {
350 Recursive_make rp;
351 wchar_t *colon;
352
353 report_recursive_init();
354
355 rp = find_recursive_target(target);
356
357 if (rp) {
358 /*
359 * if found, print starting with the space after the ':'
360 */
361 colon = (wchar_t *) wcschr(rp->oldline, (int) colon_char);
362 (void) printf("%s", colon + 1);
363 }
364 }
365
366