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