[BACK]Return to targ.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/targ.c between version 1.30 and 1.31

version 1.30, 2001/03/02 16:57:26 version 1.31, 2001/05/03 13:41:12
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenPackages$ */
   /*      $OpenBSD$ */
 /*      $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $       */  /*      $NetBSD: targ.c,v 1.11 1997/02/20 16:51:50 christos Exp $       */
   
 /*  /*
    * Copyright (c) 1999 Marc Espie.
    *
    * Extensive code changes for the OpenBSD project.
    *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    *
    * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS
    * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENBSD
    * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
   /*
  * Copyright (c) 1988, 1989, 1990, 1993   * Copyright (c) 1988, 1989, 1990, 1993
  *      The Regents of the University of California.  All rights reserved.   *      The Regents of the University of California.  All rights reserved.
  * Copyright (c) 1989 by Berkeley Softworks   * Copyright (c) 1989 by Berkeley Softworks
Line 44 
Line 71 
  *              Target nodes are kept into a hash table.   *              Target nodes are kept into a hash table.
  *   *
  * Interface:   * Interface:
  *      Targ_Init               Initialization procedure.   *      Targ_Init               Initialization procedure.
  *   *
  *      Targ_End                Cleanup the module   *      Targ_End                Cleanup the module
  *   *
  *      Targ_NewGN              Create a new GNode for the passed target   *      Targ_NewGN              Create a new GNode for the passed target
  *                              (string). The node is *not* placed in the   *                              (string). The node is *not* placed in the
  *                              hash table, though all its fields are   *                              hash table, though all its fields are
  *                              initialized.   *                              initialized.
  *   *
  *      Targ_FindNode           Find the node for a given target, creating   *      Targ_FindNode           Find the node for a given target, creating
  *                              and storing it if it doesn't exist and the   *                              and storing it if it doesn't exist and the
  *                              flags are right (TARG_CREATE)   *                              flags are right (TARG_CREATE)
  *   *
  *      Targ_FindList           Given a list of names, find nodes for all   *      Targ_FindList           Given a list of names, find nodes for all
  *                              of them, creating nodes if needed.   *                              of them, creating nodes if needed.
  *   *
  *      Targ_Ignore             Return TRUE if errors should be ignored when   *      Targ_Ignore             Return TRUE if errors should be ignored when
  *                              creating the given target.   *                              creating the given target.
  *   *
  *      Targ_Silent             Return TRUE if we should be silent when   *      Targ_Silent             Return TRUE if we should be silent when
  *                              creating the given target.   *                              creating the given target.
  *   *
  *      Targ_Precious           Return TRUE if the target is precious and   *      Targ_Precious           Return TRUE if the target is precious and
  *                              should not be removed if we are interrupted.   *                              should not be removed if we are interrupted.
  *   *
  * Debugging:   * Debugging:
  *      Targ_PrintGraph         Print out the entire graphm all variables   *      Targ_PrintGraph         Print out the entire graphm all variables
  *                              and statistics for the directory cache. Should   *                              and statistics for the directory cache. Should
  *                              print something for suffixes, too, but...   *                              print something for suffixes, too, but...
  */   */
   
 #include          <stddef.h>  #include          <stddef.h>
Line 81 
Line 108 
 #include          "make.h"  #include          "make.h"
 #include          "ohash.h"  #include          "ohash.h"
 #include          "dir.h"  #include          "dir.h"
   #include          "stats.h"
   
 #ifndef lint  #ifndef lint
 #if 0  #if 0
Line 91 
Line 119 
 #endif  #endif
 #endif /* not lint */  #endif /* not lint */
   
 #ifdef CLEANUP  
 static LIST       allGNs;       /* List of all the GNodes */  static struct ohash targets;    /* a hash table of same */
 #endif  static struct ohash_info gnode_info = {
 static struct ohash targets;    /* a hash table of same */          offsetof(GNode, name),
 static struct ohash_info gnode_info = {  
         offsetof(GNode, name),  
     NULL, hash_alloc, hash_free, element_alloc };      NULL, hash_alloc, hash_free, element_alloc };
   
 static void TargPrintOnlySrc __P((GNode *));  static void TargPrintOnlySrc(GNode *);
 static void TargPrintName __P((void *));  static void TargPrintName(void *);
 static void TargPrintNode __P((GNode *, int));  static void TargPrintNode(GNode *, int);
 #ifdef CLEANUP  #ifdef CLEANUP
 static void TargFreeGN __P((void *));  static void TargFreeGN(void *);
 #endif  #endif
   
 /*-  /*-
Line 111 
Line 137 
  * Targ_Init --   * Targ_Init --
  *      Initialize this module   *      Initialize this module
  *   *
 * Side Effects:   * Side Effects:
  *      The targets hash table is initialized   *      The targets hash table is initialized
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Targ_Init()  Targ_Init()
 {  {
 #ifdef CLEANUP  
     Lst_Init(&allGNs);  
 #endif  
     /* A small make file already creates 200 targets.  */      /* A small make file already creates 200 targets.  */
     ohash_init(&targets, 10, &gnode_info);      ohash_init(&targets, 10, &gnode_info);
 }  }
Line 135 
Line 158 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Targ_End ()  Targ_End()
 {  {
 #ifdef CLEANUP  #ifdef CLEANUP
     Lst_Destroy(&allGNs, TargFreeGN);      unsigned int i;
       GNode *n;
   
        for (n = ohash_first(&targets, &i); n != NULL; n = ohash_next(&targets, &i))
           TargFreeGN(n);
   
     ohash_delete(&targets);      ohash_delete(&targets);
 #endif  #endif
 }  }
Line 153 
Line 181 
  *      of the passed name   *      of the passed name
  *   *
  * Side Effects:   * Side Effects:
  *      The gnode is added to the set of all gnodes.   *      The gnode is added to the list of all gnodes.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 GNode *  GNode *
 Targ_NewGN(name, end)  Targ_NewGN(name, end)
     const char          *name;  /* the name to stick in the new node */      const char  *name;  /* the name to stick in the new node */
     const char          *end;      const char  *end;
 {  {
     GNode               *gn;      GNode *gn;
   
     gn = ohash_create_entry(&gnode_info, name, &end);      gn = ohash_create_entry(&gnode_info, name, &end);
     gn->path = NULL;      gn->path = NULL;
Line 170 
Line 198 
     } else {      } else {
         gn->type = 0;          gn->type = 0;
     }      }
     gn->unmade =        0;      gn->unmade =        0;
     gn->make =          FALSE;      gn->make =          FALSE;
     gn->made =          UNMADE;      gn->made =          UNMADE;
     gn->childMade =     FALSE;      gn->childMade =     FALSE;
     gn->order =         0;      gn->order =         0;
     set_out_of_date(gn->mtime);      set_out_of_date(gn->mtime);
     set_out_of_date(gn->cmtime);      set_out_of_date(gn->cmtime);
     Lst_Init(&gn->iParents);      Lst_Init(&gn->iParents);
Line 189 
Line 217 
     Lst_Init(&gn->commands);      Lst_Init(&gn->commands);
     gn->suffix =        NULL;      gn->suffix =        NULL;
   
 #ifdef CLEANUP  #ifdef STATS_GN_CREATION
     Lst_AtEnd(&allGNs, gn);      STAT_GN_COUNT++;
 #endif  #endif
   
     return gn;      return gn;
Line 201 
Line 229 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * TargFreeGN  --   * TargFreeGN  --
  *      Destroy a GNode   *      Destroy a GNode
  *  
  * Results:  
  *      None.  
  *  
  * Side Effects:  
  *      None.  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 TargFreeGN(gnp)  TargFreeGN(gnp)
     void *gnp;      void *gnp;
 {  {
     GNode *gn = (GNode *) gnp;      GNode *gn = (GNode *)gnp;
   
     efree(gn->path);      efree(gn->path);
     Lst_Destroy(&gn->iParents, NOFREE);      Lst_Destroy(&gn->iParents, NOFREE);
Line 222 
Line 244 
     Lst_Destroy(&gn->children, NOFREE);      Lst_Destroy(&gn->children, NOFREE);
     Lst_Destroy(&gn->successors, NOFREE);      Lst_Destroy(&gn->successors, NOFREE);
     Lst_Destroy(&gn->preds, NOFREE);      Lst_Destroy(&gn->preds, NOFREE);
     SymTable_Destroy(&gn->context);  
     Lst_Destroy(&gn->commands, NOFREE);      Lst_Destroy(&gn->commands, NOFREE);
       SymTable_Destroy(&gn->context);
     free(gn);      free(gn);
 }  }
 #endif  #endif
Line 235 
Line 257 
  *      Find a node in the list using the given name for matching   *      Find a node in the list using the given name for matching
  *   *
  * Results:   * Results:
  *      The node in the list if it was. If it wasn't, return NULL of   *      The node in the list if it was. If it wasn't, return NULL if
  *      flags was TARG_NOCREATE or the newly created and initialized node   *      flags was TARG_NOCREATE or the newly created and initialized node
  *      if it was TARG_CREATE   *      if flags was TARG_CREATE
  *   *
  * Side Effects:   * Side Effects:
  *      Sometimes a node is created and added to the list   *      Sometimes a node is created and added to the list
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 GNode *  GNode *
 Targ_FindNode(name, flags)  Targ_FindNode(name, end, flags)
     const char          *name;  /* the name to find */      const char          *name;  /* the name to find */
     int                 flags;  /* flags governing events when target not      const char          *end;
       int                 flags;  /* flags governing events when target not
                                  * found */                                   * found */
 {  {
     const char          *end = NULL;      GNode               *gn;    /* node in that element */
     GNode               *gn;    /* node in that element */  
     unsigned int        slot;      unsigned int        slot;
   
     slot = ohash_qlookupi(&targets, name, &end);      slot = ohash_qlookupi(&targets, name, &end);
   
     gn = ohash_find(&targets, slot);      gn = ohash_find(&targets, slot);
   
     if (gn == NULL && (flags & TARG_CREATE)) {      if (gn == NULL && (flags & TARG_CREATE)) {
         gn = Targ_NewGN(name, end);          gn = Targ_NewGN(name, end);
         ohash_insert(&targets, slot, gn);          ohash_insert(&targets, slot, gn);
     }      }
   
Line 271 
Line 293 
  *      Make a complete list of GNodes from the given list of names   *      Make a complete list of GNodes from the given list of names
  *   *
  * Side Effects:   * Side Effects:
  *      Nodes will be created for all names which do not yet have graph   *      Nodes will be created for all names in names which do not yet have graph
  *      nodes.   *      nodes.
  *   *
  *      A complete list of graph nodes corresponding to all instances of   *      A complete list of graph nodes corresponding to all instances of all
  *      all names is added to nodes.   *      the names in names is added to nodes.
  * -----------------------------------------------------------------------   * -----------------------------------------------------------------------
  */   */
 void  void
 Targ_FindList(nodes, names)  Targ_FindList(nodes, names)
     Lst         nodes;          /* result list */      Lst            nodes;       /* result list */
     Lst         names;          /* list of names to find */      Lst            names;       /* list of names to find */
 {  {
     LstNode     ln;             /* name list element */      LstNode        ln;          /* name list element */
     GNode       *gn;            /* node in tLn */      GNode         *gn;          /* node in tLn */
     char        *name;      char          *name;
   
     for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {      for (ln = Lst_First(names); ln != NULL; ln = Lst_Adv(ln)) {
         name = (char *)Lst_Datum(ln);          name = (char *)Lst_Datum(ln);
         gn = Targ_FindNode(name, TARG_CREATE);          gn = Targ_FindNode(name, NULL, TARG_CREATE);
         /*              /* Note: Lst_AtEnd must come before the Lst_Concat so the nodes
          * Note: Lst_AtEnd must come before the Lst_Concat so the nodes               * are added to the list in the order in which they were
          * are added to the list in the order in which they were               * encountered in the makefile.  */
          * encountered in the makefile.  
          */  
         Lst_AtEnd(nodes, gn);          Lst_AtEnd(nodes, gn);
         if (gn->type & OP_DOUBLEDEP)          if (gn->type & OP_DOUBLEDEP)
             Lst_Concat(nodes, &gn->cohorts);              Lst_Concat(nodes, &gn->cohorts);
Line 303 
Line 323 
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Targ_Ignore  --   * Targ_Ignore  --
  *      Return true if should ignore errors when creating gn   *      Return true if should ignore errors when creating gn
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 Boolean  Boolean
 Targ_Ignore(gn)  Targ_Ignore(gn)
     GNode          *gn;         /* node to check for */      GNode          *gn;         /* node to check for */
 {  {
     if (ignoreErrors || gn->type & OP_IGNORE)      if (ignoreErrors || gn->type & OP_IGNORE)
         return TRUE;          return TRUE;
Line 319 
Line 339 
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Targ_Silent  --   * Targ_Silent  --
  *      Return true if be silent when creating gn   *      Return true if be silent when creating gn
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 Boolean  Boolean
 Targ_Silent(gn)  Targ_Silent(gn)
     GNode          *gn;         /* node to check for */      GNode          *gn;         /* node to check for */
 {  {
     if (beSilent || gn->type & OP_SILENT)      if (beSilent || gn->type & OP_SILENT)
         return TRUE;          return TRUE;
Line 340 
Line 360 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 Boolean  Boolean
 Targ_Precious (gn)  Targ_Precious(gn)
     GNode          *gn;         /* the node to check */      GNode          *gn;         /* the node to check */
 {  {
     if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP)))      if (allPrecious || (gn->type & (OP_PRECIOUS|OP_DOUBLEDEP)))
         return TRUE;          return TRUE;
Line 364 
Line 384 
  */   */
 void  void
 Targ_SetMain(gn)  Targ_SetMain(gn)
     GNode   *gn;        /* The main target we'll create */      GNode   *gn;        /* The main target we'll create */
 {  {
     mainTarg = gn;      mainTarg = gn;
 }  }
Line 374 
Line 394 
     void *gnp;      void *gnp;
 {  {
     GNode *gn = (GNode *)gnp;      GNode *gn = (GNode *)gnp;
   
     printf("%s ", gn->name);      printf("%s ", gn->name);
 }  }
   
Line 397 
Line 416 
  * Side Effects:   * Side Effects:
  *      The time is placed in a static area, so it is overwritten   *      The time is placed in a static area, so it is overwritten
  *      with each call.   *      with each call.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 char *  char *
 Targ_FmtTime(time)  Targ_FmtTime(time)
     TIMESTAMP           time;      TIMESTAMP    time;
 {  {
     struct tm           *parts;      struct tm           *parts;
     static char         buf[128];      static char         buf[128];
     time_t t;      time_t t;
   
     t = timestamp2time_t(time);      t = timestamp2time_t(time);
   
     parts = localtime(&t);      parts = localtime(&t);
     strftime(buf, sizeof buf, "%k:%M:%S %b %d, %Y", parts);      strftime(buf, sizeof buf, "%H:%M:%S %b %d, %Y", parts);
     buf[sizeof(buf) - 1] = '\0';      buf[sizeof(buf) - 1] = '\0';
     return(buf);      return buf;
 }  }
   
 /*-  /*-
Line 433 
Line 451 
 #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf("." #attr " "); break  #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf("." #attr " "); break
 #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break  #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf("." #attr " "); break
 #else  #else
 #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf(".attr "); break  #define PRINTBIT(attr)  case CONCAT(OP_,attr): printf(".attr "); break
 #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break  #define PRINTDBIT(attr) case CONCAT(OP_,attr): if (DEBUG(TARG)) printf(".attr "); break
 #endif /* __STDC__ */  #endif /* __STDC__ */
   
     type &= ~OP_OPMASK;      type &= ~OP_OPMASK;
Line 443 
Line 461 
         tbit = 1 << (ffs(type) - 1);          tbit = 1 << (ffs(type) - 1);
         type &= ~tbit;          type &= ~tbit;
   
         switch(tbit) {          switch (tbit) {
             PRINTBIT(OPTIONAL);              PRINTBIT(OPTIONAL);
             PRINTBIT(USE);              PRINTBIT(USE);
             PRINTBIT(EXEC);              PRINTBIT(EXEC);
Line 470 
Line 488 
  */   */
 static void  static void
 TargPrintNode(gn, pass)  TargPrintNode(gn, pass)
     GNode       *gn;      GNode         *gn;
     int         pass;      int           pass;
 {  {
     if (!OP_NOP(gn->type)) {      if (!OP_NOP(gn->type)) {
         printf("#\n");          printf("#\n");
         if (gn == mainTarg)          if (gn == mainTarg) {
             printf("# *** MAIN TARGET ***\n");              printf("# *** MAIN TARGET ***\n");
           }
         if (pass == 2) {          if (pass == 2) {
             if (gn->unmade)              if (gn->unmade) {
                 printf("# %d unmade children\n", gn->unmade);                  printf("# %d unmade children\n", gn->unmade);
             else              } else {
                 printf("# No unmade children\n");                  printf("# No unmade children\n");
               }
             if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {              if (! (gn->type & (OP_JOIN|OP_USE|OP_EXEC))) {
                 if (!is_out_of_date(gn->mtime))                  if (!is_out_of_date(gn->mtime)) {
                     printf("# last modified %s: %s\n",                      printf("# last modified %s: %s\n",
                               Targ_FmtTime(gn->mtime),                                Targ_FmtTime(gn->mtime),
                               (gn->made == UNMADE ? "unmade" :                                (gn->made == UNMADE ? "unmade" :
                                (gn->made == MADE ? "made" :                                 (gn->made == MADE ? "made" :
                                 (gn->made == UPTODATE ? "up-to-date" :                                  (gn->made == UPTODATE ? "up-to-date" :
                                  "error when made"))));                                   "error when made"))));
                 else if (gn->made != UNMADE)                  } else if (gn->made != UNMADE) {
                     printf("# non-existent (maybe): %s\n",                      printf("# non-existent (maybe): %s\n",
                               (gn->made == MADE ? "made" :                                (gn->made == MADE ? "made" :
                                (gn->made == UPTODATE ? "up-to-date" :                                 (gn->made == UPTODATE ? "up-to-date" :
                                 (gn->made == ERROR ? "error when made" :                                  (gn->made == ERROR ? "error when made" :
                                  "aborted"))));                                   "aborted"))));
                 else                  } else {
                     printf("# unmade\n");                      printf("# unmade\n");
                   }
             }              }
             if (!Lst_IsEmpty(&gn->iParents)) {              if (!Lst_IsEmpty(&gn->iParents)) {
                 printf("# implicit parents: ");                  printf("# implicit parents: ");
Line 508 
Line 529 
         if (!Lst_IsEmpty(&gn->parents)) {          if (!Lst_IsEmpty(&gn->parents)) {
             printf("# parents: ");              printf("# parents: ");
             Lst_Every(&gn->parents, TargPrintName);              Lst_Every(&gn->parents, TargPrintName);
             fputc ('\n', stdout);              fputc('\n', stdout);
         }          }
   
         printf("%-16s", gn->name);          printf("%-16s", gn->name);
Line 527 
Line 548 
         printf("\n\n");          printf("\n\n");
         if (gn->type & OP_DOUBLEDEP) {          if (gn->type & OP_DOUBLEDEP) {
             LstNode ln;              LstNode ln;
   
             for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))              for (ln = Lst_First(&gn->cohorts); ln != NULL; ln = Lst_Adv(ln))
                     TargPrintNode((GNode *)Lst_Datum(ln), pass);                      TargPrintNode((GNode *)Lst_Datum(ln), pass);
         }          }
     }      }
Line 537 
Line 558 
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * TargPrintOnlySrc --   * TargPrintOnlySrc --
  *      Print only those targets that are just a source.   *      Print targets that are just a source.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 TargPrintOnlySrc(gn)  TargPrintOnlySrc(gn)
     GNode       *gn;      GNode *gn;
 {  {
     if (OP_NOP(gn->type))      if (OP_NOP(gn->type))
         printf("#\t%s [%s]\n", gn->name, gn->path ? gn->path : gn->name);          printf("#\t%s [%s]\n", gn->name,
               gn->path != NULL ? gn->path : gn->name);
 }  }
   
 /*-  /*-
Line 556 
Line 578 
  */   */
 void  void
 Targ_PrintGraph(pass)  Targ_PrintGraph(pass)
     int                 pass;   /* Which pass this is. 1 => no processing      int                 pass;   /* Which pass this is. 1 => no processing
                                  * 2 => processing done */                                   * 2 => processing done */
 {  {
     GNode               *gn;      GNode               *gn;
     unsigned int        i;      unsigned int        i;
   
     printf("#*** Input graph:\n");      printf("#*** Input graph:\n");
     for (gn = ohash_first(&targets, &i); gn != NULL;      for (gn = ohash_first(&targets, &i); gn != NULL;
         gn = ohash_next(&targets, &i))          gn = ohash_next(&targets, &i))
             TargPrintNode(gn, pass);              TargPrintNode(gn, pass);
     printf("\n\n");      printf("\n\n");
     printf("#\n#   Files that are only sources:\n");      printf("#\n#   Files that are only sources:\n");
     for (gn = ohash_first(&targets, &i); gn != NULL;      for (gn = ohash_first(&targets, &i); gn != NULL;
         gn = ohash_next(&targets, &i))          gn = ohash_next(&targets, &i))
                 TargPrintOnlySrc(gn);                  TargPrintOnlySrc(gn);
     printf("#*** Global Variables:\n");      Var_Dump();
     Var_Dump(VAR_GLOBAL);  
     printf("#*** Command-line Variables:\n");  
     Var_Dump(VAR_CMD);  
     printf("\n");      printf("\n");
     Dir_PrintDirectories();      Dir_PrintDirectories();
     printf("\n");      printf("\n");

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31