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