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