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