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