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