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