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