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 #ifdef NSE 171 nse_check_no_deps_no_rule(target, line, line); 172 #endif 173 if ((report_dependencies_level == 2) || 174 (report_dependencies_level == 4)) { 175 if (is_out_of_date(line)) { 176 (void) printf("1 "); 177 } else { 178 (void) printf("0 "); 179 } 180 } 181 print_filename(target); 182 (void) printf(":\t"); 183 print_deplist(line->body.line.dependencies); 184 print_rec_info(target); 185 (void) printf("\n"); 186 for (dep = line->body.line.dependencies; 187 dep != NULL; 188 dep = dep->next) { 189 print_deps(dep->name, 190 get_prop(dep->name->prop, line_prop)); 191 } 192 } 193 } 194 195 static Boolean 196 is_out_of_date(Property line) 197 { 198 Dependency dep; 199 Property line2; 200 201 if (line == NULL) { 202 return false; 203 } 204 if (line->body.line.is_out_of_date) { 205 return true; 206 } 207 for (dep = line->body.line.dependencies; 208 dep != NULL; 209 dep = dep->next) { 210 line2 = get_prop(dep->name->prop, line_prop); 211 if (is_out_of_date(line2)) { 212 line->body.line.is_out_of_date = true; 213 return true; 214 } 215 } 216 return false; 217 } 218 219 /* 220 * Given a dependency print it and all its siblings. 221 */ 222 static void 223 print_deplist(Dependency head) 224 { 225 Dependency dp; 226 227 for (dp = head; dp != NULL; dp = dp->next) { 228 if ((report_dependencies_level != 2) || 229 ((!dp->automatic) || 230 (dp->name->is_double_colon))) { 231 if (dp->name != force) { 232 putwchar(' '); 233 print_filename(dp->name); 234 } 235 } 236 } 237 } 238 239 /* 240 * Print the name of a file for the -P option. 241 * If the file is a directory put on a trailing slash. 242 */ 243 static void 244 print_filename(Name name) 245 { 246 (void) printf("%s", name->string_mb); 247 /* 248 if (name->stat.is_dir) { 249 putwchar('/'); 250 } 251 */ 252 } 253 254 /* 255 * should_print_dep(line) 256 * 257 * Test if we should print the dependencies of this target. 258 * The line must exist and either have children dependencies 259 * or have a command that is not an SCCS command. 260 * 261 * Return value: 262 * true if the dependencies should be printed 263 * 264 * Parameters: 265 * line We get the dependency list from here 266 * 267 * Global variables used: 268 */ 269 static Boolean 270 should_print_dep(Property line) 271 { 272 if (line == NULL) { 273 return false; 274 } 275 if (line->body.line.dependencies != NULL) { 276 return true; 277 } 278 if (line->body.line.sccs_command) { 279 return false; 280 } 281 return true; 282 } 283 284 /* 285 * Print out the root nodes of all the dependency trees 286 * in this makefile. 287 */ 288 static void 289 print_forest(Name target) 290 { 291 Name_set::iterator np, e; 292 Property line; 293 294 for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) { 295 if (np->is_target && !np->has_parent && np != target) { 296 (void) doname_check(np, true, false, false); 297 line = get_prop(np->prop, line_prop); 298 printf("-\n"); 299 print_deps(np, line); 300 } 301 } 302 } 303 304 305 /* 306 * This is a set of routines for dumping the internal make state 307 * Used for the -p option 308 */ 309 void 310 print_value(register Name value, Daemon daemon) 311 312 313 { 314 Chain cp; 315 316 if (value == NULL) 317 (void)printf("=\n"); 318 else 319 switch (daemon) { 320 case no_daemon: 321 (void)printf("= %s\n", value->string_mb); 322 break; 323 case chain_daemon: 324 for (cp= (Chain) value; cp != NULL; cp= cp->next) 325 (void)printf(cp->next == NULL ? "%s" : "%s ", 326 cp->name->string_mb); 327 (void)printf("\n"); 328 break; 329 }; 330 } 331 332 static void 333 print_rule(register Name target) 334 { 335 register Cmd_line rule; 336 register Property line; 337 338 if (((line= get_prop(target->prop, line_prop)) == NULL) || 339 ((line->body.line.command_template == NULL) && 340 (line->body.line.dependencies == NULL))) 341 return; 342 print_dependencies(target, line); 343 for (rule= line->body.line.command_template; rule != NULL; rule= rule->next) 344 (void)printf("\t%s\n", rule->command_line->string_mb); 345 } 346 347 348 /* 349 * If target is recursive, print the following to standard out: 350 * .RECURSIVE subdir targ Makefile 351 */ 352 static void 353 print_rec_info(Name target) 354 { 355 Recursive_make rp; 356 wchar_t *colon; 357 358 report_recursive_init(); 359 360 rp = find_recursive_target(target); 361 362 if (rp) { 363 /* 364 * if found, print starting with the space after the ':' 365 */ 366 colon = (wchar_t *) wschr(rp->oldline, (int) colon_char); 367 (void) printf("%s", colon + 1); 368 } 369 } 370