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