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