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 extern int printf (const char *, ...);
48 extern int _flsbuf (unsigned int, FILE *);
49
50 /*
51 * print_dependencies(target, line)
52 *
53 * Print all the dependencies of a target. First print all the Makefiles.
54 * Then print all the dependencies. Finally, print all the .INIT
55 * dependencies.
56 *
57 * Parameters:
58 * target The target we print dependencies for
59 * line We get the dependency list from here
60 *
61 * Global variables used:
62 * done The Name ".DONE"
63 * init The Name ".INIT"
64 * makefiles_used List of all makefiles read
65 */
66 void
67 print_dependencies(register Name target, register Property line)
68 {
69 Dependency dp;
70 static Boolean makefiles_printed = false;
71
72 #ifdef SUNOS4_AND_AFTER
73 if (target_variants) {
74 #else
75 if (is_true(flag.target_variants)) {
76 #endif
77 depvar_print_results();
78 }
79
80 if (!makefiles_printed) {
81 /*
82 * Search the makefile list for the primary makefile,
83 * then print it and its inclusions. After that go back
84 * and print the default.mk file and its inclusions.
85 */
86 for (dp = makefiles_used; dp != NULL; dp = dp->next) {
87 if (dp->name == primary_makefile) {
88 break;
89 }
90 }
91 if (dp) {
92 print_deplist(dp);
93 for (dp = makefiles_used; dp != NULL; dp = dp->next) {
94 if (dp->name == primary_makefile) {
95 break;
96 }
97 (void)printf(" %s", dp->name->string_mb);
98 }
99 }
100 (void) printf("\n");
101 makefiles_printed = true;
102 }
103 print_deps(target, line);
104 #ifdef SUNOS4_AND_AFTER
105 /*
106 print_more_deps(target, init);
107 print_more_deps(target, done);
108 */
109 if (target_variants) {
110 #else
111 print_more_deps(target, cached_names.init);
112 print_more_deps(target, cached_names.done);
113 if (is_true(flag.target_variants)) {
114 #endif
115 print_forest(target);
116 }
117 }
118
119 /*
120 * print_more_deps(target, name)
121 *
122 * Print some special dependencies.
123 * These are the dependencies for the .INIT and .DONE targets.
124 *
125 * Parameters:
126 * target Target built during make run
127 * name Special target to print dependencies for
128 *
129 * Global variables used:
130 */
131 static void
132 print_more_deps(Name target, Name name)
133 {
134 Property line;
135 register Dependency dependencies;
136
137 line = get_prop(name->prop, line_prop);
138 if (line != NULL && line->body.line.dependencies != NULL) {
139 (void) printf("%s:\t", target->string_mb);
140 print_deplist(line->body.line.dependencies);
141 (void) printf("\n");
142 for (dependencies= line->body.line.dependencies;
143 dependencies != NULL;
144 dependencies= dependencies->next) {
145 print_deps(dependencies->name,
146 get_prop(dependencies->name->prop, line_prop));
147 }
148 }
149 }
150
151 /*
152 * print_deps(target, line, go_recursive)
153 *
154 * Print a regular dependency list. Append to this information which
155 * indicates whether or not the target is recursive.
156 *
157 * Parameters:
158 * target target to print dependencies for
159 * line We get the dependency list from here
160 * go_recursive Should we show all dependencies recursively?
161 *
162 * Global variables used:
163 * recursive_name The Name ".RECURSIVE", printed
164 */
165 static void
166 print_deps(register Name target, register Property line)
167 {
168 register Dependency dep;
169
170 #ifdef SUNOS4_AND_AFTER
171 if ((target->dependency_printed) ||
172 (target == force)) {
173 #else
174 if (is_true(target->dependency_printed)) {
175 #endif
176 return;
177 }
178 target->dependency_printed = true;
179
180 /* only print entries that are actually derived and are not leaf
181 * files and are not the result of sccs get.
182 */
183 if (should_print_dep(line)) {
184 #ifdef NSE
185 nse_check_no_deps_no_rule(target, line, line);
186 #endif
187 if ((report_dependencies_level == 2) ||
188 (report_dependencies_level == 4)) {
189 if (is_out_of_date(line)) {
190 (void) printf("1 ");
191 } else {
192 (void) printf("0 ");
193 }
194 }
195 print_filename(target);
196 (void) printf(":\t");
197 print_deplist(line->body.line.dependencies);
198 print_rec_info(target);
199 (void) printf("\n");
200 for (dep = line->body.line.dependencies;
201 dep != NULL;
202 dep = dep->next) {
203 print_deps(dep->name,
204 get_prop(dep->name->prop, line_prop));
205 }
206 }
207 }
208
209 static Boolean
210 is_out_of_date(Property line)
211 {
212 Dependency dep;
213 Property line2;
214
215 if (line == NULL) {
216 return false;
217 }
218 if (line->body.line.is_out_of_date) {
219 return true;
220 }
221 for (dep = line->body.line.dependencies;
222 dep != NULL;
223 dep = dep->next) {
224 line2 = get_prop(dep->name->prop, line_prop);
225 if (is_out_of_date(line2)) {
226 line->body.line.is_out_of_date = true;
227 return true;
228 }
229 }
230 return false;
231 }
232
233 /*
234 * Given a dependency print it and all its siblings.
235 */
236 static void
237 print_deplist(Dependency head)
238 {
239 Dependency dp;
240
241 for (dp = head; dp != NULL; dp = dp->next) {
242 if ((report_dependencies_level != 2) ||
243 ((!dp->automatic) ||
244 (dp->name->is_double_colon))) {
245 if (dp->name != force) {
246 putwchar(' ');
247 print_filename(dp->name);
248 }
249 }
250 }
251 }
252
253 /*
254 * Print the name of a file for the -P option.
255 * If the file is a directory put on a trailing slash.
256 */
257 static void
258 print_filename(Name name)
259 {
260 (void) printf("%s", name->string_mb);
261 /*
262 if (name->stat.is_dir) {
263 putwchar('/');
264 }
265 */
266 }
267
268 /*
269 * should_print_dep(line)
270 *
271 * Test if we should print the dependencies of this target.
272 * The line must exist and either have children dependencies
273 * or have a command that is not an SCCS command.
274 *
275 * Return value:
276 * true if the dependencies should be printed
277 *
278 * Parameters:
279 * line We get the dependency list from here
280 *
281 * Global variables used:
282 */
283 static Boolean
284 should_print_dep(Property line)
285 {
286 if (line == NULL) {
287 return false;
288 }
289 if (line->body.line.dependencies != NULL) {
290 return true;
291 }
292 #ifdef SUNOS4_AND_AFTER
293 if (line->body.line.sccs_command) {
294 #else
295 if (is_true(line->body.line.sccs_command)) {
296 #endif
297 return false;
298 }
299 return true;
300 }
301
302 /*
303 * Print out the root nodes of all the dependency trees
304 * in this makefile.
305 */
306 static void
307 print_forest(Name target)
308 {
309 Name_set::iterator np, e;
310 Property line;
311
312 for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) {
313 #ifdef SUNOS4_AND_AFTER
314 if (np->is_target && !np->has_parent && np != target) {
315 #else
316 if (is_true(np->is_target) &&
317 is_false(np->has_parent) &&
318 np != target) {
319 #endif
320 (void) doname_check(np, true, false, false);
321 line = get_prop(np->prop, line_prop);
322 printf("-\n");
323 print_deps(np, line);
324 }
325 }
326 }
327
328 #ifndef SUNOS4_AND_AFTER
329 printdesc()
330 {
331 Name_set::iterator p, e;
332 register Property prop;
333 register Dependency dep;
334 register Cmd_line rule;
335 Percent percent, percent_depe;
336
337 /* Default target */
338 if (default_target_to_build != NULL) {
339 print_rule(default_target_to_build);
340 default_target_to_build->dependency_printed= true;
341 };
342 (void)printf("\n");
343
344 /* .AR_REPLACE */
345 if (ar_replace_rule != NULL) {
346 (void)printf("%s:\n", cached_names.ar_replace->string_mb);
347 for (rule= ar_replace_rule; rule != NULL; rule= rule->next)
348 (void)printf("\t%s\n", rule->command_line->string_mb);
349 };
350
351 /* .DEFAULT */
352 if (default_rule != NULL) {
353 (void)printf("%s:\n", cached_names.default_rule->string_mb);
354 for (rule= default_rule; rule != NULL; rule= rule->next)
355 (void)printf("\t%s\n", rule->command_line->string_mb);
356 };
357
358 /* .IGNORE */
359 if (is_true(flag.ignore_errors))
360 (void)printf("%s:\n", cached_names.ignore->string_mb);
361
362 /* .KEEP_STATE: */
363 if (is_true(flag.keep_state))
364 (void)printf("%s:\n\n", cached_names.dot_keep_state->string_mb);
365
366 /* .PRECIOUS */
367 (void)printf("%s: ", cached_names.precious->string_mb);
368 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++)
369 if (is_true(p->stat.is_precious | all_precious))
370 (void)printf("%s ", p->string_mb);
371 (void)printf("\n");
372
373 /* .SCCS_GET */
374 if (sccs_get_rule != NULL) {
375 (void)printf("%s:\n", cached_names.sccs_get->string_mb);
376 for (rule= sccs_get_rule; rule != NULL; rule= rule->next)
377 (void)printf("\t%s\n", rule->command_line->string_mb);
378 };
379
380 /* .SILENT */
381 if (is_true(flag.silent))
382 (void)printf("%s:\n", cached_names.silent->string_mb);
383
384 /* .SUFFIXES: */
385 (void)printf("%s: ", cached_names.suffixes->string_mb);
386 for (dep= suffixes; dep != NULL; dep= dep->next) {
387 (void)printf("%s ", dep->name->string_mb);
388 build_suffix_list(dep->name);
389 };
390 (void)printf("\n\n");
391
392 /* % rules */
393 for (percent= percent_list; percent != NULL; percent= percent->next) {
394 (void) printf("%s:", percent->name->string_mb);
395
396 for (percent_depe= percent->dependencies; percent_depe != NULL; percent_depe = percent_depe->next)
397 (void) printf(" %s", percent_depe->name->string_mb);
398
399 (void) printf("\n");
400
401 for (rule= percent->command_template; rule != NULL; rule= rule->next)
402 (void)printf("\t%s\n", rule->command_line->string_mb);
403 };
404
405 /* Suffix rules */
406 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++)
407 if (is_false(p->dependency_printed) && (p->string[0] == PERIOD)) {
408 print_rule(p);
409 p->dependency_printed= true;
410 };
411
412 /* Macro assignments */
413 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++)
414 if (((prop= get_prop(p->prop, macro_prop)) != NULL) &&
415 (prop->body.macro.value != NULL)) {
416 (void)printf("%s", p->string_mb);
417 print_value(prop->body.macro.value,
418 prop->body.macro.daemon);
419 };
420 (void)printf("\n");
421
422 /* Delays */
423 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++)
424 for (prop= get_prop(p->prop, conditional_prop);
425 prop != NULL;
426 prop= get_prop(prop->next, conditional_prop)) {
427 (void)printf("%s := %s",
428 p->string_mb,
429 prop->body.conditional.name->string_mb);
430 print_value(prop->body.conditional.value, no_daemon);
431 };
432 (void)printf("\n");
433
434 /* All other dependencies */
435 for (p = hashtab.begin(), e = hashtab.end(); p != e; p++)
436 if (is_false(p->dependency_printed) && (p->colons != no_colon))
437 print_rule(p);
438 (void)printf("\n");
439 exit(0);
440 }
441 #endif
442
443 /*
444 * This is a set of routines for dumping the internal make state
445 * Used for the -p option
446 */
447 void
448 print_value(register Name value, Daemon daemon)
449
450 #ifdef SUNOS4_AND_AFTER
451
452 #else
453
454 #endif
455 {
456 Chain cp;
457
458 if (value == NULL)
459 (void)printf("=\n");
460 else
461 switch (daemon) {
462 case no_daemon:
463 (void)printf("= %s\n", value->string_mb);
464 break;
465 case chain_daemon:
466 for (cp= (Chain) value; cp != NULL; cp= cp->next)
467 (void)printf(cp->next == NULL ? "%s" : "%s ",
468 cp->name->string_mb);
469 (void)printf("\n");
470 break;
471 };
472 }
473
474 static void
475 print_rule(register Name target)
476 {
477 register Cmd_line rule;
478 register Property line;
479
480 if (((line= get_prop(target->prop, line_prop)) == NULL) ||
481 ((line->body.line.command_template == NULL) &&
482 (line->body.line.dependencies == NULL)))
483 return;
484 print_dependencies(target, line);
485 for (rule= line->body.line.command_template; rule != NULL; rule= rule->next)
486 (void)printf("\t%s\n", rule->command_line->string_mb);
487 }
488
489
490 /*
491 * If target is recursive, print the following to standard out:
492 * .RECURSIVE subdir targ Makefile
493 */
494 static void
495 print_rec_info(Name target)
496 {
497 Recursive_make rp;
498 wchar_t *colon;
499
500 report_recursive_init();
501
502 rp = find_recursive_target(target);
503
504 if (rp) {
505 /*
506 * if found, print starting with the space after the ':'
507 */
508 colon = (wchar_t *) wschr(rp->oldline, (int) colon_char);
509 (void) printf("%s", colon + 1);
510 }
511 }
512