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

Diff for /src/usr.bin/make/suff.c between version 1.40 and 1.41

version 1.40, 2000/11/24 14:27:20 version 1.41, 2001/05/03 13:41:11
Line 1 
Line 1 
 /*      $OpenBSD$       */  /*      $OpenPackages$ */
   /*      $OpenBSD$ */
 /*      $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $       */  /*      $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $       */
   
 /*  /*
Line 45 
Line 46 
  *      using suffix transformation rules   *      using suffix transformation rules
  *   *
  * Interface:   * Interface:
  *      Suff_Init               Initialize all things to do with suffixes.   *      Suff_Init               Initialize all things to do with suffixes.
  *   *
  *      Suff_End                Cleanup the module   *      Suff_End                Cleanup the module
  *   *
  *      Suff_DoPaths            This function is used to make life easier   *      Suff_DoPaths            This function is used to make life easier
  *                              when searching for a file according to its   *                              when searching for a file according to its
  *                              suffix. It takes the global search path,   *                              suffix. It takes the global search path,
  *                              as defined using the .PATH: target, and appends   *                              as defined using the .PATH: target, and appends
  *                              its directories to the path of each of the   *                              its directories to the path of each of the
  *                              defined suffixes, as specified using   *                              defined suffixes, as specified using
  *                              .PATH<suffix>: targets. In addition, all   *                              .PATH<suffix>: targets. In addition, all
  *                              directories given for suffixes labeled as   *                              directories given for suffixes labeled as
  *                              include files or libraries, using the .INCLUDES   *                              include files or libraries, using the .INCLUDES
  *                              or .LIBS targets, are played with using   *                              or .LIBS targets, are played with using
  *                              Dir_MakeFlags to create the .INCLUDES and   *                              Dir_MakeFlags to create the .INCLUDES and
  *                              .LIBS global variables.   *                              .LIBS global variables.
  *   *
  *      Suff_ClearSuffixes      Clear out all the suffixes and defined   *      Suff_ClearSuffixes      Clear out all the suffixes and defined
  *                              transformations.   *                              transformations.
  *   *
  *      Suff_IsTransform        Return TRUE if the passed string is the lhs   *      Suff_IsTransform        Return TRUE if the passed string is the lhs
  *                              of a transformation rule.   *                              of a transformation rule.
  *   *
  *      Suff_AddSuffix          Add the passed string as another known suffix.   *      Suff_AddSuffix          Add the passed string as another known suffix.
  *   *
  *      Suff_GetPath            Return the search path for the given suffix.   *      Suff_GetPath            Return the search path for the given suffix.
  *   *
  *      Suff_AddInclude         Mark the given suffix as denoting an include   *      Suff_AddInclude         Mark the given suffix as denoting an include
  *                              file.   *                              file.
  *   *
  *      Suff_AddLib             Mark the given suffix as denoting a library.   *      Suff_AddLib             Mark the given suffix as denoting a library.
  *   *
  *      Suff_AddTransform       Add another transformation to the suffix   *      Suff_AddTransform       Add another transformation to the suffix
  *                              graph. Returns  GNode suitable for framing, I   *                              graph. Returns  GNode suitable for framing, I
  *                              mean, tacking commands, attributes, etc. on.   *                              mean, tacking commands, attributes, etc. on.
  *   *
  *      Suff_SetNull            Define the suffix to consider the suffix of   *      Suff_SetNull            Define the suffix to consider the suffix of
  *                              any file that doesn't have a known one.   *                              any file that doesn't have a known one.
  *   *
  *      Suff_FindDeps           Find implicit sources for and the location of   *      Suff_FindDeps           Find implicit sources for and the location of
  *                              a target based on its suffix. Returns the   *                              a target based on its suffix. Returns the
  *                              bottom-most node added to the graph or NULL   *                              bottom-most node added to the graph or NULL
  *                              if the target had no implicit sources.   *                              if the target had no implicit sources.
  */   */
   
 #include          <stddef.h>  #include          <stddef.h>
 #include          <stdio.h>  #include          <stdio.h>
 #include          "make.h"  #include          "make.h"
 #include          "ohash.h"  #include          "ohash.h"
 #include          "dir.h"  #include          "dir.h"
Line 105 
Line 106 
 #endif  #endif
 #endif /* not lint */  #endif /* not lint */
   
 static LIST      sufflist;      /* Lst of suffixes */  static LIST      sufflist;      /* Lst of suffixes */
 #ifdef CLEANUP  #ifdef CLEANUP
 static LIST      suffClean;     /* Lst of suffixes to be cleaned */  static LIST      suffClean;     /* Lst of suffixes to be cleaned */
 #endif  #endif
 static LIST      srclist;       /* Lst of sources */  static LIST      srclist;       /* Lst of sources */
 static LIST      transforms;    /* Lst of transformation rules */  static LIST      transforms;    /* Lst of transformation rules */
   
 static int        sNum = 0;     /* Counter for assigning suffix numbers */  static int        sNum = 0;     /* Counter for assigning suffix numbers */
   
 /*  /*
  * Structure describing an individual suffix.   * Structure describing an individual suffix.
  */   */
 typedef struct Suff_ {  typedef struct Suff_ {
     char         *name;         /* The suffix itself */      char         *name;         /* The suffix itself */
     int          nameLen;       /* Length of the suffix */      int          nameLen;       /* Length of the suffix */
     short        flags;         /* Type of suffix */      short        flags;         /* Type of suffix */
 #define SUFF_INCLUDE      0x01      /* One which is #include'd */  #define SUFF_INCLUDE      0x01      /* One which is #include'd */
 #define SUFF_LIBRARY      0x02      /* One which contains a library */  #define SUFF_LIBRARY      0x02      /* One which contains a library */
 #define SUFF_NULL         0x04      /* The empty suffix */  #define SUFF_NULL         0x04      /* The empty suffix */
     LIST         searchPath;    /* The path along which files of this suffix      LIST         searchPath;    /* The path along which files of this suffix
                                  * may be found */                                   * may be found */
     int          sNum;          /* The suffix number */      int          sNum;          /* The suffix number */
     LIST         parents;       /* Suffixes we have a transformation to */      LIST         parents;       /* Suffixes we have a transformation to */
     LIST         children;      /* Suffixes we have a transformation from */      LIST         children;      /* Suffixes we have a transformation from */
     LIST         ref;           /* List of lists this suffix is referenced */      LIST         ref;           /* List of lists this suffix is referenced */
 } Suff;  } Suff;
   
Line 136 
Line 137 
  * Structure used in the search for implied sources.   * Structure used in the search for implied sources.
  */   */
 typedef struct Src_ {  typedef struct Src_ {
     char            *file;      /* The file to look for */      char            *file;      /* The file to look for */
     char            *pref;      /* Prefix from which file was formed */      char            *pref;      /* Prefix from which file was formed */
     Suff            *suff;      /* The suffix on the file */      Suff            *suff;      /* The suffix on the file */
     struct Src_     *parent;    /* The Src for which this is a source */      struct Src_     *parent;    /* The Src for which this is a source */
     GNode           *node;      /* The node describing the file */      GNode           *node;      /* The node describing the file */
     int             children;   /* Count of existing children (so we don't free      int             children;   /* Count of existing children (so we don't free
                                  * this thing too early or never nuke it) */                                   * this thing too early or never nuke it) */
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
     LIST            cp;         /* Debug; children list */      LIST            cp;         /* Debug; children list */
 #endif  #endif
 } Src;  } Src;
   
Line 153 
Line 154 
  * function...   * function...
  */   */
 typedef struct {  typedef struct {
     Lst            l;      Lst            l;
     Src            *s;      Src            *s;
 } LstSrc;  } LstSrc;
   
 static Suff         *suffNull;  /* The NULL suffix for this run */  static Suff         *suffNull;  /* The NULL suffix for this run */
 static Suff         *emptySuff; /* The empty suffix required for POSIX  static Suff         *emptySuff; /* The empty suffix required for POSIX
                                  * single-suffix transformation rules */                                   * single-suffix transformation rules */
   
   
 static char *SuffStrIsPrefix __P((char *, char *));  static char *SuffStrIsPrefix(const char *, const char *);
 static char *SuffSuffIsSuffix __P((Suff *, char *));  static char *SuffSuffIsSuffix(Suff *, const char *);
 static int SuffSuffIsSuffixP __P((void *, void *));  static int SuffSuffIsSuffixP(void *, const void *);
 static int SuffSuffHasNameP __P((void *, void *));  static int SuffSuffHasNameP(void *, const void *);
 static int SuffSuffIsPrefix __P((void *, void *));  static int SuffSuffIsPrefix(void *, const void *);
 static int SuffGNHasNameP __P((void *, void *));  static int SuffGNHasNameP(void *, const void *);
 static void SuffUnRef __P((Lst, Suff *));  static void SuffUnRef(Lst, Suff *);
 static void SuffInsert __P((Lst, Suff *));  #ifdef CLEANUP
 static void SuffRemove __P((Lst, Suff *));  static void SuffFree(void *);
 static Boolean SuffParseTransform __P((char *, Suff **, Suff **));  #endif
 static void SuffRebuildGraph __P((void *, void *));  static void SuffInsert(Lst, Suff *);
 static void SuffAddSrc __P((void *, void *));  static Boolean SuffParseTransform(const char *, Suff **, Suff **);
 static int SuffRemoveSrc __P((Lst));  static void SuffRebuildGraph(void *, void *);
 static void SuffAddLevel __P((Lst, Src *));  static void SuffAddSrc(void *, void *);
 static Src *SuffFindThem __P((Lst, Lst));  static int SuffRemoveSrc(Lst);
 static Src *SuffFindCmds __P((Src *, Lst));  static void SuffAddLevel(Lst, Src *);
 static void SuffExpandChildren __P((void *, void *));  static Src *SuffFindThem(Lst, Lst);
 static Boolean SuffApplyTransform __P((GNode *, GNode *, Suff *, Suff *));  static Src *SuffFindCmds(Src *, Lst);
 static void SuffFindDeps __P((GNode *, Lst));  static void SuffExpandChildren(void *, void *);
 static void SuffFindArchiveDeps __P((GNode *, Lst));  static void SuffExpandVarChildren(LstNode, GNode *, GNode *);
 static void SuffFindNormalDeps __P((GNode *, Lst));  static void SuffExpandWildChildren(LstNode, GNode *, GNode *);
 static void SuffPrintName __P((void *));  static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
 static void SuffPrintSuff __P((void *));  static void SuffFindDeps(GNode *, Lst);
 static void SuffPrintTrans __P((void *));  static void SuffFindArchiveDeps(GNode *, Lst);
   static void SuffFindNormalDeps(GNode *, Lst);
   static void SuffPrintName(void *);
   static void SuffPrintSuff(void *);
   static void SuffPrintTrans(void *);
   
         /*************** Lst Predicates ****************/          /*************** Lst Predicates ****************/
 /*-  /*-
Line 195 
Line 200 
  *   *
  * Results:   * Results:
  *      NULL if it ain't, pointer to character in str after prefix if so   *      NULL if it ain't, pointer to character in str after prefix if so
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static char    *  static char    *
 SuffStrIsPrefix (pref, str)  SuffStrIsPrefix(pref, str)
     register char  *pref;       /* possible prefix */      const char  *pref;  /* possible prefix */
     register char  *str;        /* string to check */      const char  *str;   /* string to check */
 {  {
     while (*str && *pref == *str) {      while (*str && *pref == *str) {
         pref++;          pref++;
         str++;          str++;
     }      }
   
     return (*pref ? NULL : str);      return *pref ? NULL : (char *)str;
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * SuffSuffIsSuffix  --   * SuffSuffIsSuffix  --
  *      See if suff is a suffix of str. Str should point to THE END of the   *      See if suff is a suffix of str. str should point to the end of the
  *      string to check. (THE END == the null byte)   *      string to check.
  *   *
  * Results:   * Results:
  *      NULL if it ain't, pointer to character in str before suffix if   *      NULL if it ain't, pointer to first character of suffix in str if
  *      it is.   *      it is.
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static char *  static char *
 SuffSuffIsSuffix (s, str)  SuffSuffIsSuffix(s, str)
     register Suff  *s;          /* possible suffix */      Suff           *s;          /* possible suffix */
     char           *str;        /* string to examine */      const char     *str;        /* string to examine */
 {  {
     register char  *p1;         /* Pointer into suffix name */      const char     *p1;         /* Pointer into suffix name */
     register char  *p2;         /* Pointer into string being examined */      const char     *p2;         /* Pointer into string being examined */
   
     p1 = s->name + s->nameLen;      p1 = s->name + s->nameLen;
     p2 = str;      p2 = str;
   
     while (p1 >= s->name && *p1 == *p2) {      while (p1 != s->name) {
         p1--;          p1--;
         p2--;          p2--;
           if (*p1 != *p2)
                   return NULL;
     }      }
   
     return (p1 == s->name - 1 ? p2 : NULL);      return (char *)p2;
 }  }
   
 /*-  /*-
Line 254 
Line 255 
  *   *
  * Results:   * Results:
  *      0 if the suffix is the one desired, non-zero if not.   *      0 if the suffix is the one desired, non-zero if not.
  *  
  * Side Effects:  
  *      None.  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 SuffSuffIsSuffixP(s, str)  SuffSuffIsSuffixP(s, str)
     void *s;      void        *s;
     void *str;      const void  *str;
 {  {
     return !SuffSuffIsSuffix((Suff *)s, (char *)str);      return !SuffSuffIsSuffix((Suff *)s, (const char *)str);
 }  }
   
 /*-  /*-
Line 276 
Line 273 
  *   *
  * Results:   * Results:
  *      0 if the suffix is of the given name. non-zero otherwise.   *      0 if the suffix is of the given name. non-zero otherwise.
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 SuffSuffHasNameP (s, sname)  SuffSuffHasNameP(s, sname)
     void *s;                /* Suffix to check */      void        *s;                 /* Suffix to check */
     void *sname;            /* Desired name */      const void  *sname;             /* Desired name */
 {  {
     return (strcmp ((char *) sname, ((Suff *) s)->name));      return strcmp((const char *)sname, ((Suff *)s)->name);
 }  }
   
 /*-  /*-
Line 299 
Line 293 
  *   *
  * Results:   * Results:
  *      0 if s is a prefix of str. non-zero otherwise   *      0 if s is a prefix of str. non-zero otherwise
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 SuffSuffIsPrefix(s, str)  SuffSuffIsPrefix(s, str)
     void *s;    /* suffix to compare */      void        *s;             /* suffix to compare */
     void *str;  /* string to examine */      const void  *str;   /* string to examine */
 {  {
     return SuffStrIsPrefix (((Suff *)s)->name, (char *)str) == NULL ? 1 : 0;      return SuffStrIsPrefix(((Suff *)s)->name, (const char *)str) == NULL ? 1 : 0;
 }  }
   
 /*-  /*-
Line 319 
Line 310 
  *   *
  * Results:   * Results:
  *      0 if it does. non-zero if it doesn't   *      0 if it does. non-zero if it doesn't
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 SuffGNHasNameP(gn, name)  SuffGNHasNameP(gn, name)
     void *gn;           /* current node we're looking at */      void        *gn;            /* current node we're looking at */
     void *name;         /* name we're looking for */      const void  *name;          /* name we're looking for */
 {  {
     return strcmp((char *)name, ((GNode *)gn)->name);      return strcmp((const char *)name, ((GNode *)gn)->name);
 }  }
   
             /*********** Maintenance Functions ************/              /*********** Maintenance Functions ************/
   
 static void  static void
 SuffUnRef(l, s)  SuffUnRef(l, sp)
     Lst l;      Lst         l;
     Suff *s;      Suff        *sp;
 {  {
     LstNode ln = Lst_Member(l, s);      LstNode ln = Lst_Member(l, sp);
     if (ln != NULL)      if (ln != NULL)
         Lst_Remove(l, ln);          Lst_Remove(l, ln);
 }  }
   
   #ifdef CLEANUP
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * SuffRemove  --   * SuffFree  --
  *      Remove the suffix from the list   *      Free up all memory associated with the given suffix structure.
    *
    * Side Effects:
    *      the suffix entry is detroyed
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffRemove(l, s)  SuffFree(sp)
     Lst l;      void        *sp;
     Suff *s;  
 {  {
     SuffUnRef(l, s);      Suff        *s = (Suff *)sp;
   
       if (s == suffNull)
           suffNull = NULL;
   
       if (s == emptySuff)
           emptySuff = NULL;
   
       Lst_Destroy(&s->ref, NOFREE);
       Lst_Destroy(&s->children, NOFREE);
       Lst_Destroy(&s->parents, NOFREE);
       Lst_Destroy(&s->searchPath, Dir_Destroy);
   
       free(s->name);
       free(s);
 }  }
   #endif
   
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * SuffInsert  --   * SuffInsert  --
  *      Insert the suffix into the list keeping the list ordered by suffix   *      Insert the suffix into the list keeping the list ordered by suffix
  *      numbers.   *      numbers.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      The reference count of the suffix is incremented   *      The reference count of the suffix is incremented
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffInsert (l, s)  SuffInsert(l, s)
     Lst           l;            /* the list where in s should be inserted */      Lst           l;            /* the list where in s should be inserted */
     Suff          *s;           /* the suffix to insert */      Suff          *s;           /* the suffix to insert */
 {  {
     LstNode       ln;           /* current element in l we're examining */      LstNode       ln;           /* current element in l we're examining */
     Suff          *s2 = NULL;   /* the suffix descriptor in this element */      Suff          *s2 = NULL;   /* the suffix descriptor in this element */
   
     Lst_Open(l);      for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
     while ((ln = Lst_Next(l)) != NULL) {  
         s2 = (Suff *)Lst_Datum(ln);          s2 = (Suff *)Lst_Datum(ln);
         if (s2->sNum >= s->sNum) {          if (s2->sNum >= s->sNum)
             break;              break;
         }  
     }      }
   
     Lst_Close (l);  
     if (DEBUG(SUFF)) {      if (DEBUG(SUFF)) {
         printf("inserting %s(%d)...", s->name, s->sNum);          printf("inserting %s(%d)...", s->name, s->sNum);
     }      }
Line 418 
Line 419 
  *      This function is called from the parse module when a   *      This function is called from the parse module when a
  *      .SUFFIXES:\n line is encountered.   *      .SUFFIXES:\n line is encountered.
  *   *
  * Results:  
  *      none  
  *  
  * Side Effects:   * Side Effects:
  *      the sufflist and its graph nodes are destroyed   *      the sufflist and its graph nodes are destroyed
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_ClearSuffixes ()  Suff_ClearSuffixes()
 {  {
 #ifdef CLEANUP  #ifdef CLEANUP
     Lst_ConcatDestroy(&suffClean, &sufflist);      Lst_ConcatDestroy(&suffClean, &sufflist);
Line 446 
Line 444 
  *   *
  * Side Effects:   * Side Effects:
  *      The passed pointers are overwritten.   *      The passed pointers are overwritten.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Boolean  static Boolean
 SuffParseTransform(str, srcPtr, targPtr)  SuffParseTransform(str, srcPtr, targPtr)
     char                *str;           /* String being parsed */      const char          *str;           /* String being parsed */
     Suff                **srcPtr;       /* Place to store source of trans. */      Suff                **srcPtr;       /* Place to store source of trans. */
     Suff                **targPtr;      /* Place to store target of trans. */      Suff                **targPtr;      /* Place to store target of trans. */
 {  {
     register LstNode    srcLn;      /* element in suffix list of trans source*/      LstNode             srcLn;      /* element in suffix list of trans source*/
     register Suff       *src;       /* Source of transformation */      Suff                *src;       /* Source of transformation */
     register LstNode    targLn;     /* element in suffix list of trans target*/      LstNode             targLn;     /* element in suffix list of trans target*/
     register char       *str2;      /* Extra pointer (maybe target suffix) */      const char          *str2;      /* Extra pointer (maybe target suffix) */
     LstNode             singleLn;   /* element in suffix list of any suffix      LstNode             singleLn;   /* element in suffix list of any suffix
                                      * that exactly matches str */                                       * that exactly matches str */
     Suff                *single = NULL;/* Source of possible transformation to      Suff                *single = NULL;/* Source of possible transformation to
                                      * null suffix */                                       * null suffix */
   
     srcLn = NULL;      srcLn = NULL;
Line 474 
Line 471 
      * parsed the string.       * parsed the string.
      */       */
     for (;;) {      for (;;) {
           if (srcLn == NULL)
               srcLn = Lst_FindConst(&sufflist, SuffSuffIsPrefix, str);
           else
               srcLn = Lst_FindFromConst(Lst_Succ(srcLn), SuffSuffIsPrefix, str);
         if (srcLn == NULL) {          if (srcLn == NULL) {
             srcLn = Lst_Find(&sufflist, SuffSuffIsPrefix, str);  
         } else {  
             srcLn = Lst_FindFrom(Lst_Succ(srcLn),  
                                   SuffSuffIsPrefix, str);  
         }  
         if (srcLn == NULL) {  
             /*              /*
              * Ran out of source suffixes -- no such rule               * Ran out of source suffixes -- no such rule
              */               */
Line 496 
Line 491 
                  */                   */
                 *srcPtr = single;                  *srcPtr = single;
                 *targPtr = suffNull;                  *targPtr = suffNull;
                 return(TRUE);                  return TRUE;
             }              }
             return (FALSE);              return FALSE;
         }          }
         src = (Suff *)Lst_Datum(srcLn);          src = (Suff *)Lst_Datum(srcLn);
         str2 = str + src->nameLen;          str2 = str + src->nameLen;
Line 506 
Line 501 
             single = src;              single = src;
             singleLn = srcLn;              singleLn = srcLn;
         } else {          } else {
             targLn = Lst_Find(&sufflist, SuffSuffHasNameP, str2);              targLn = Lst_FindConst(&sufflist, SuffSuffHasNameP, str2);
             if (targLn != NULL) {              if (targLn != NULL) {
                 *srcPtr = src;                  *srcPtr = src;
                 *targPtr = (Suff *)Lst_Datum(targLn);                  *targPtr = (Suff *)Lst_Datum(targLn);
                 return (TRUE);                  return TRUE;
             }              }
         }          }
     }      }
Line 521 
Line 516 
  * Suff_IsTransform  --   * Suff_IsTransform  --
  *      Return TRUE if the given string is a transformation rule   *      Return TRUE if the given string is a transformation rule
  *   *
  *  
  * Results:   * Results:
  *      TRUE if the string is a concatenation of two known suffixes.   *      TRUE if the string is a concatenation of two known suffixes.
  *      FALSE otherwise   *      FALSE otherwise
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 Boolean  Boolean
 Suff_IsTransform (str)  Suff_IsTransform(str)
     char          *str;         /* string to check */      const char    *str;         /* string to check */
 {  {
     Suff          *src, *targ;      Suff          *src, *targ;
   
     return (SuffParseTransform(str, &src, &targ));      return SuffParseTransform(str, &src, &targ);
 }  }
   
 /*-  /*-
Line 554 
Line 545 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 GNode *  GNode *
 Suff_AddTransform (line)  Suff_AddTransform(line)
     char          *line;        /* name of transformation to add */      const char    *line;        /* name of transformation to add */
 {  {
     GNode         *gn;          /* GNode of transformation rule */      GNode         *gn;          /* GNode of transformation rule */
     Suff          *s,           /* source suffix */      Suff          *s,           /* source suffix */
                   *t;           /* target suffix */                    *t;           /* target suffix */
     LstNode       ln;           /* Node for existing transformation */      LstNode       ln;           /* Node for existing transformation */
   
     ln = Lst_Find(&transforms, SuffGNHasNameP, line);      ln = Lst_FindConst(&transforms, SuffGNHasNameP, line);
     if (ln == NULL) {      if (ln == NULL) {
         /*          /*
          * Make a new graph node for the transformation. It will be filled in           * Make a new graph node for the transformation. It will be filled in
Line 579 
Line 570 
          */           */
         gn = (GNode *)Lst_Datum(ln);          gn = (GNode *)Lst_Datum(ln);
         Lst_Destroy(&gn->commands, NOFREE);          Lst_Destroy(&gn->commands, NOFREE);
         Lst_Destroy(&gn->children, NOFREE);  
         Lst_Init(&gn->commands);          Lst_Init(&gn->commands);
           Lst_Destroy(&gn->children, NOFREE);
         Lst_Init(&gn->children);          Lst_Init(&gn->children);
     }      }
   
Line 598 
Line 589 
     SuffInsert(&t->children, s);      SuffInsert(&t->children, s);
     SuffInsert(&s->parents, t);      SuffInsert(&s->parents, t);
   
     return (gn);      return gn;
 }  }
   
 /*-  /*-
Line 612 
Line 603 
  * Side Effects:   * Side Effects:
  *      If the node has no commands or children, the children and parents   *      If the node has no commands or children, the children and parents
  *      lists of the affected suffices are altered.   *      lists of the affected suffices are altered.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_EndTransform(gnp)  Suff_EndTransform(gnp)
     void *gnp;          /* Node for transformation */      void *gnp;          /* Node for transformation */
 {  {
     GNode *gn = (GNode *)gnp;      GNode *gn = (GNode *)gnp;
   
Line 634 
Line 624 
         }          }
   
         /*          /*
          * Remove the source from the target's children list.           * Remove the source from the target's children list.
          *           *
          * We'll be called twice when the next target is seen, but .c and .o           * We'll be called twice when the next target is seen, but .c and .o
          * are only linked once...           * are only linked once...
          */           */
         SuffRemove(&t->children, s);          SuffUnRef(&t->children, s);
   
         /*          /*
          * Remove the target from the source's parents list           * Remove the target from the source's parents list
          */           */
         SuffRemove(&s->parents, t);          if (s != NULL)
               SuffUnRef(&s->parents, t);
     } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {      } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
         printf("transformation %s complete\n", gn->name);          printf("transformation %s complete\n", gn->name);
     }      }
Line 663 
Line 654 
  * Side Effects:   * Side Effects:
  *      The appropriate links will be made between this suffix and   *      The appropriate links will be made between this suffix and
  *      others if transformation rules exist for it.   *      others if transformation rules exist for it.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffRebuildGraph(transformp, sp)  SuffRebuildGraph(transformp, sp)
     void *transformp;   /* Transformation to test */      void        *transformp;    /* Transformation to test */
     void *sp;           /* Suffix to rebuild */      void        *sp;            /* Suffix to rebuild */
 {  {
     GNode       *transform = (GNode *)transformp;      GNode       *transform = (GNode *)transformp;
     Suff        *s = (Suff *)sp;      Suff        *s = (Suff *)sp;
     char        *cp;      char        *cp;
     LstNode     ln;      LstNode     ln;
     Suff        *s2;      Suff        *s2;
   
     /*      /* First see if it is a transformation from this suffix.  */
      * First see if it is a transformation from this suffix.  
      */  
     cp = SuffStrIsPrefix(s->name, transform->name);      cp = SuffStrIsPrefix(s->name, transform->name);
     if (cp != NULL) {      if (cp != NULL) {
         ln = Lst_Find(&sufflist, SuffSuffHasNameP, cp);          ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, cp);
         if (ln != NULL) {          if (ln != NULL) {
             /*              /* Found target. Link in and return, since it can't be anything
              * Found target. Link in and return, since it can't be anything               * else.  */
              * else.  
              */  
             s2 = (Suff *)Lst_Datum(ln);              s2 = (Suff *)Lst_Datum(ln);
             SuffInsert(&s2->children, s);              SuffInsert(&s2->children, s);
             SuffInsert(&s->parents, s2);              SuffInsert(&s->parents, s2);
Line 695 
Line 681 
         }          }
     }      }
   
     /*      /* Not from, maybe to?  */
      * Not from, maybe to?  
      */  
     cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));      cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
     if (cp != NULL) {      if (cp != NULL) {
         /*          /* Null-terminate the source suffix in order to find it.  */
          * Null-terminate the source suffix in order to find it.          *cp = '\0';
          */          ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, transform->name);
         cp[1] = '\0';          /* Replace the start of the target suffix.  */
         ln = Lst_Find(&sufflist, SuffSuffHasNameP, transform->name);          *cp = s->name[0];
         /*  
          * Replace the start of the target suffix  
          */  
         cp[1] = s->name[0];  
         if (ln != NULL) {          if (ln != NULL) {
             /*              /* Found it -- establish the proper relationship.  */
              * Found it -- establish the proper relationship  
              */  
             s2 = (Suff *)Lst_Datum(ln);              s2 = (Suff *)Lst_Datum(ln);
             SuffInsert(&s->children, s2);              SuffInsert(&s->children, s2);
             SuffInsert(&s2->parents, s);              SuffInsert(&s2->parents, s);
Line 726 
Line 704 
  *      Add the suffix in string to the end of the list of known suffixes.   *      Add the suffix in string to the end of the list of known suffixes.
  *      Should we restructure the suffix graph? Make doesn't...   *      Should we restructure the suffix graph? Make doesn't...
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      A GNode is created for the suffix and a Suff structure is created and   *      A GNode is created for the suffix and a Suff structure is created and
  *      added to the suffixes list unless the suffix was already known.   *      added to the suffixes list unless the suffix was already known.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_AddSuffix (str)  Suff_AddSuffix(str)
     char          *str;     /* the name of the suffix to add */      char          *str;     /* the name of the suffix to add */
 {  {
     Suff          *s;       /* new suffix descriptor */      Suff          *s;       /* new suffix descriptor */
     LstNode       ln;      LstNode       ln;
   
     ln = Lst_Find(&sufflist, SuffSuffHasNameP, str);      ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, str);
     if (ln == NULL) {      if (ln == NULL) {
         s = (Suff *) emalloc (sizeof (Suff));          s = emalloc(sizeof(Suff));
   
         s->name =       estrdup(str);          s->name =       estrdup(str);
         s->nameLen =    strlen(s->name);          s->nameLen =    strlen(s->name);
         Lst_Init(&s->searchPath);          Lst_Init(&s->searchPath);
         Lst_Init(&s->children);          Lst_Init(&s->children);
         Lst_Init(&s->parents);          Lst_Init(&s->parents);
         Lst_Init(&s->ref);          Lst_Init(&s->ref);
         s->sNum =       sNum++;          s->sNum =       sNum++;
         s->flags =      0;          s->flags =      0;
   
         Lst_AtEnd(&sufflist, s);          Lst_AtEnd(&sufflist, s);
         /*          /*
Line 775 
Line 750 
  */   */
 Lst  Lst
 Suff_GetPath(sname)  Suff_GetPath(sname)
     char          *sname;      char          *sname;
 {  {
     LstNode       ln;      LstNode       ln;
     Suff          *s;      Suff          *s;
   
     ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname);      ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname);
     if (ln == NULL)      if (ln == NULL) {
         return NULL;          return NULL;
     else {      } else {
         s = (Suff *)Lst_Datum(ln);          s = (Suff *)Lst_Datum(ln);
         return &s->searchPath;          return &s->searchPath;
     }      }
Line 795 
Line 770 
  *      Extend the search paths for all suffixes to include the default   *      Extend the search paths for all suffixes to include the default
  *      search path.   *      search path.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      The searchPath field of all the suffixes is extended by the   *      The searchPath field of all the suffixes is extended by the
  *      directories in dirSearchPath. If paths were specified for the   *      directories in dirSearchPath. If paths were specified for the
Line 810 
Line 782 
 void  void
 Suff_DoPaths()  Suff_DoPaths()
 {  {
     register Suff       *s;      Suff                *s;
     register LstNode    ln;      LstNode             ln;
     char                *ptr;      char                *ptr;
     LIST                inIncludes; /* Cumulative .INCLUDES path */      LIST                inIncludes; /* Cumulative .INCLUDES path */
     LIST                inLibs;     /* Cumulative .LIBS path */      LIST                inLibs;     /* Cumulative .LIBS path */
   
     Lst_Open(&sufflist);  
   
     Lst_Init(&inIncludes);      Lst_Init(&inIncludes);
     Lst_Init(&inLibs);      Lst_Init(&inLibs);
   
     while ((ln = Lst_Next(&sufflist)) != NULL) {      for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Adv(ln)) {
         s = (Suff *)Lst_Datum(ln);          s = (Suff *)Lst_Datum(ln);
         if (!Lst_IsEmpty(&s->searchPath)) {          if (!Lst_IsEmpty(&s->searchPath)) {
 #ifdef INCLUDES  #ifdef INCLUDES
Line 848 
Line 818 
   
     Lst_Destroy(&inIncludes, Dir_Destroy);      Lst_Destroy(&inIncludes, Dir_Destroy);
     Lst_Destroy(&inLibs, Dir_Destroy);      Lst_Destroy(&inLibs, Dir_Destroy);
   
     Lst_Close(&sufflist);  
 }  }
   
 /*-  /*-
Line 859 
Line 827 
  *      Called from the parse module when a .INCLUDES line is parsed.   *      Called from the parse module when a .INCLUDES line is parsed.
  *      The suffix must have already been defined.   *      The suffix must have already been defined.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      The SUFF_INCLUDE bit is set in the suffix's flags field   *      The SUFF_INCLUDE bit is set in the suffix's flags field
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_AddInclude (sname)  Suff_AddInclude(sname)
     char          *sname;     /* Name of suffix to mark */      char          *sname;     /* Name of suffix to mark */
 {  {
     LstNode       ln;      LstNode       ln;
     Suff          *s;      Suff          *s;
   
     ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname);      ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname);
     if (ln != NULL) {      if (ln != NULL) {
         s = (Suff *)Lst_Datum(ln);          s = (Suff *)Lst_Datum(ln);
         s->flags |= SUFF_INCLUDE;          s->flags |= SUFF_INCLUDE;
Line 889 
Line 853 
  *      suffix must have been defined via .SUFFIXES before this is   *      suffix must have been defined via .SUFFIXES before this is
  *      called.   *      called.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      The SUFF_LIBRARY bit is set in the suffix's flags field   *      The SUFF_LIBRARY bit is set in the suffix's flags field
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_AddLib (sname)  Suff_AddLib(sname)
     char          *sname;     /* Name of suffix to mark */      char          *sname;     /* Name of suffix to mark */
 {  {
     LstNode       ln;      LstNode       ln;
     Suff          *s;      Suff          *s;
   
     ln = Lst_Find(&sufflist, SuffSuffHasNameP, sname);      ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, sname);
     if (ln != NULL) {      if (ln != NULL) {
         s = (Suff *)Lst_Datum(ln);          s = (Suff *)Lst_Datum(ln);
         s->flags |= SUFF_LIBRARY;          s->flags |= SUFF_LIBRARY;
     }      }
 }  }
   
           /********** Implicit Source Search Functions *********/            /********** Implicit Source Search Functions *********/
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
Line 930 
Line 890 
     void *lsp;      /* list and parent for the new Src */      void *lsp;      /* list and parent for the new Src */
 {  {
     Suff        *s = (Suff *)sp;      Suff        *s = (Suff *)sp;
     LstSrc      *ls = (LstSrc *)lsp;      LstSrc      *ls = (LstSrc *)lsp;
     Src         *s2;        /* new Src structure */      Src         *s2;        /* new Src structure */
     Src         *targ;      /* Target structure */      Src         *targ;      /* Target structure */
   
     targ = ls->s;      targ = ls->s;
   
     if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {      if ((s->flags & SUFF_NULL) && *s->name != '\0') {
         /*          /*
          * If the suffix has been marked as the NULL suffix, also create a Src           * If the suffix has been marked as the NULL suffix, also create a Src
          * structure for a file with no suffix attached. Two birds, and all           * structure for a file with no suffix attached. Two birds, and all
          * that...           * that...
          */           */
         s2 = (Src *) emalloc (sizeof (Src));          s2 = emalloc(sizeof(Src));
         s2->file =      estrdup(targ->pref);          s2->file =      estrdup(targ->pref);
         s2->pref =      targ->pref;          s2->pref =      targ->pref;
         s2->parent =    targ;          s2->parent =    targ;
         s2->node =      NULL;          s2->node =      NULL;
         s2->suff =      s;          s2->suff =      s;
         s2->children =  0;          s2->children =  0;
         targ->children += 1;          targ->children += 1;
         Lst_AtEnd(ls->l, s2);          Lst_AtEnd(ls->l, s2);
Line 959 
Line 919 
         printf("\n");          printf("\n");
 #endif  #endif
     }      }
     s2 = (Src *) emalloc (sizeof (Src));      s2 = emalloc(sizeof(Src));
     s2->file =      str_concat(targ->pref, s->name, 0);      s2->file =      str_concat(targ->pref, s->name, 0);
     s2->pref =      targ->pref;      s2->pref =      targ->pref;
     s2->parent =    targ;      s2->parent =    targ;
     s2->node =      NULL;      s2->node =      NULL;
     s2->suff =      s;      s2->suff =      s;
     s2->children =  0;      s2->children =  0;
     targ->children += 1;      targ->children += 1;
     Lst_AtEnd(ls->l, s2);      Lst_AtEnd(ls->l, s2);
Line 975 
Line 935 
     Lst_Every(ls->l, PrintAddr);      Lst_Every(ls->l, PrintAddr);
     printf("\n");      printf("\n");
 #endif  #endif
   
 }  }
   
 /*-  /*-
Line 982 
Line 943 
  * SuffAddLevel  --   * SuffAddLevel  --
  *      Add all the children of targ as Src structures to the given list   *      Add all the children of targ as Src structures to the given list
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      Lots of structures are created and added to the list   *      Lots of structures are created and added to the list
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffAddLevel (l, targ)  SuffAddLevel(l, targ)
     Lst            l;           /* list to which to add the new level */      Lst            l;           /* list to which to add the new level */
     Src            *targ;       /* Src structure to use as the parent */      Src            *targ;       /* Src structure to use as the parent */
 {  {
     LstSrc         ls;      LstSrc         ls;
   
     ls.s = targ;      ls.s = targ;
     ls.l = l;      ls.l = l;
Line 1008 
Line 966 
  *      Free all src structures in list that don't have a reference count   *      Free all src structures in list that don't have a reference count
  *   *
  * Results:   * Results:
  *      True if an src was removed   *      Ture if an src was removed
  *   *
  * Side Effects:   * Side Effects:
  *      The memory is free'd.   *      The memory is free'd.
  *----------------------------------------------------------------------   *----------------------------------------------------------------------
  */   */
 static int  static int
 SuffRemoveSrc (l)  SuffRemoveSrc(l)
     Lst l;      Lst l;
 {  {
     LstNode ln;      LstNode ln;
     Src *s;      Src *s;
     int t = 0;      int t = 0;
   
     Lst_Open(l);  
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
     printf("cleaning %lx: ", (unsigned long) l);      printf("cleaning %lx: ", (unsigned long)l);
     Lst_Every(l, PrintAddr);      Lst_Every(l, PrintAddr);
     printf("\n");      printf("\n");
 #endif  #endif
   
   
     while ((ln = Lst_Next (l)) != NULL) {      for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
         s = (Src *)Lst_Datum(ln);          s = (Src *)Lst_Datum(ln);
         if (s->children == 0) {          if (s->children == 0) {
             free(s->file);              free(s->file);
Line 1038 
Line 995 
                 free(s->pref);                  free(s->pref);
             else {              else {
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
                 LstNode ln = Lst_Member(&s->parent->cp, s);                  LstNode ln2 = Lst_Member(&s->parent->cp, s);
                 if (ln != NULL)                  if (ln2 != NULL)
                     Lst_Remove(&s->parent->cp, ln);                      Lst_Remove(&s->parent->cp, ln2);
 #endif  #endif
                 --s->parent->children;                  --s->parent->children;
             }              }
Line 1051 
Line 1008 
             Lst_Remove(l, ln);              Lst_Remove(l, ln);
             free(s);              free(s);
             t |= 1;              t |= 1;
             Lst_Close(l);  
             return TRUE;              return TRUE;
         }          }
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
Line 1063 
Line 1019 
 #endif  #endif
     }      }
   
     Lst_Close(l);  
   
     return t;      return t;
 }  }
   
Line 1075 
Line 1029 
  *   *
  * Results:   * Results:
  *      The lowest structure in the chain of transformations   *      The lowest structure in the chain of transformations
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Src *  static Src *
 SuffFindThem (srcs, slst)  SuffFindThem(srcs, slst)
     Lst            srcs;        /* list of Src structures to search through */      Lst            srcs;        /* list of Src structures to search through */
     Lst            slst;      Lst            slst;
 {  {
     Src            *s;          /* current Src */      Src            *s;          /* current Src */
     Src            *rs;         /* returned Src */      Src            *rs;         /* returned Src */
     char           *ptr;      char           *ptr;
   
     rs = (Src *) NULL;      rs = NULL;
   
     while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) {      while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) {
         if (DEBUG(SUFF)) {          if (DEBUG(SUFF)) {
             printf ("\ttrying %s...", s->file);              printf("\ttrying %s...", s->file);
         }          }
   
         /*          /*
          * A file is considered to exist if either a node exists in the           * A file is considered to exist if either a node exists in the
          * graph for it or the file actually exists.           * graph for it or the file actually exists.
          */           */
         if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {          if (Targ_FindNode(s->file, NULL, TARG_NOCREATE) != NULL) {
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
             printf("remove %x from %x\n", s, srcs);              printf("remove %x from %x\n", s, srcs);
 #endif  #endif
Line 1118 
Line 1069 
         }          }
   
         if (DEBUG(SUFF)) {          if (DEBUG(SUFF)) {
             printf ("not there\n");              printf("not there\n");
         }          }
   
         SuffAddLevel (srcs, s);          SuffAddLevel(srcs, s);
         Lst_AtEnd(slst, s);          Lst_AtEnd(slst, s);
     }      }
   
     if (DEBUG(SUFF) && rs) {      if (DEBUG(SUFF) && rs) {
         printf ("got it\n");          printf("got it\n");
     }      }
     return (rs);      return rs;
 }  }
   
 /*-  /*-
Line 1143 
Line 1094 
  *   *
  * Side Effects:   * Side Effects:
  *      A Src structure may be allocated.   *      A Src structure may be allocated.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Src *  static Src *
 SuffFindCmds (targ, slst)  SuffFindCmds(targ, slst)
     Src         *targ;  /* Src structure to play with */      Src         *targ;  /* Src structure to play with */
     Lst         slst;      Lst         slst;
 {  {
     LstNode             ln;     /* General-purpose list node */      LstNode             ln;     /* General-purpose list node */
     register GNode      *t,     /* Target GNode */      GNode               *t,     /* Target GNode */
                         *s;     /* Source GNode */                          *s;     /* Source GNode */
     int                 prefLen;/* The length of the defined prefix */      int                 prefLen;/* The length of the defined prefix */
     Suff                *suff;  /* Suffix on matching beastie */      Suff                *suff;  /* Suffix on matching beastie */
     Src                 *ret;   /* Return value */      Src                 *ret;   /* Return value */
     char                *cp;      const char          *cp;
   
     t = targ->node;      t = targ->node;
     Lst_Open(&t->children);      prefLen = strlen(targ->pref);
     prefLen = strlen (targ->pref);  
   
     while ((ln = Lst_Next(&t->children)) != NULL) {      for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Adv(ln)) {
         s = (GNode *)Lst_Datum(ln);          s = (GNode *)Lst_Datum(ln);
   
         cp = strrchr (s->name, '/');          cp = strrchr(s->name, '/');
         if (cp == (char *)NULL) {          if (cp == NULL) {
             cp = s->name;              cp = s->name;
         } else {          } else {
             cp++;              cp++;
         }          }
         if (strncmp (cp, targ->pref, prefLen) == 0) {          if (strncmp(cp, targ->pref, prefLen) == 0) {
             /*              /* The node matches the prefix ok, see if it has a known
              * The node matches the prefix ok, see if it has a known               * suffix.  */
              * suffix.              LstNode ln2;
              */              ln2 = Lst_FindConst(&sufflist, SuffSuffHasNameP, &cp[prefLen]);
             ln = Lst_Find(&sufflist, SuffSuffHasNameP, &cp[prefLen]);              if (ln2 != NULL) {
             if (ln != NULL) {  
                 /*                  /*
                  * It even has a known suffix, see if there's a transformation                   * It even has a known suffix, see if there's a transformation
                  * defined between the node's suffix and the target's suffix.                   * defined between the node's suffix and the target's suffix.
                  *                   *
                  * XXX: Handle multi-stage transformations here, too.                   * XXX: Handle multi-stage transformations here, too.
                  */                   */
                 suff = (Suff *)Lst_Datum(ln);                  suff = (Suff *)Lst_Datum(ln2);
   
                 if (Lst_Member(&suff->parents, targ->suff) != NULL)                  if (Lst_Member(&suff->parents, targ->suff) != NULL) {
                 {  
                     /*                      /*
                      * Hot Damn! Create a new Src structure to describe                       * Hot Damn! Create a new Src structure to describe
                      * this transformation (making sure to duplicate the                       * this transformation (making sure to duplicate the
                      * source node's name so Suff_FindDeps can free it                       * source node's name so Suff_FindDeps can free it
                      * again (ick)), and return the new structure.                       * again (ick)), and return the new structure.
                      */                       */
                     ret = (Src *)emalloc (sizeof (Src));                      ret = emalloc(sizeof(Src));
                     ret->file = estrdup(s->name);                      ret->file = estrdup(s->name);
                     ret->pref = targ->pref;                      ret->pref = targ->pref;
                     ret->suff = suff;                      ret->suff = suff;
Line 1212 
Line 1159 
                     if (DEBUG(SUFF)) {                      if (DEBUG(SUFF)) {
                         printf ("\tusing existing source %s\n", s->name);                          printf ("\tusing existing source %s\n", s->name);
                     }                      }
                     return (ret);                      return ret;
                 }                  }
             }              }
         }          }
     }      }
     Lst_Close(&t->children);      return NULL;
     return ((Src *)NULL);  
 }  }
   
 /*-  
  *-----------------------------------------------------------------------  
  * SuffExpandChildren --  
  *      Expand the names of any children of a given node that contain  
  *      variable invocations or file wildcards into actual targets.  
  *  
  * Side Effects:  
  *      The expanded node is removed from the parent's list of children,  
  *      and the parent's unmade counter is decremented, but other nodes  
  *      may be added.  
  *  
  *-----------------------------------------------------------------------  
  */  
 static void  static void
 SuffExpandChildren(cgnp, pgnp)  SuffExpandVarChildren(after, cgn, pgn)
     void *cgnp;     /* Child to examine */      LstNode     after;
     void *pgnp;     /* Parent node being processed */      GNode       *cgn;
       GNode       *pgn;
 {  {
     GNode       *cgn = (GNode *)cgnp;      GNode       *gn;            /* New source 8) */
     GNode       *pgn = (GNode *)pgnp;      char        *cp;            /* Expanded value */
     GNode       *gn;        /* New source 8) */      LIST        members;
     LstNode     prevLN;    /* Node after which new source should be put */  
     LstNode     ln;         /* List element for old source */  
     char        *cp;        /* Expanded value */  
   
     /*  
      * New nodes effectively take the place of the child, so place them  
      * after the child  
      */  
     prevLN = Lst_Member(&pgn->children, cgn);  
   
     /*      if (DEBUG(SUFF))
      * First do variable expansion -- this takes precedence over          printf("Expanding \"%s\"...", cgn->name);
      * wildcard expansion. If the result contains wildcards, they'll be gotten  
      * to later since the resulting words are tacked on to the end of  
      * the children list.  
      */  
     if (strchr(cgn->name, '$') != NULL) {  
         if (DEBUG(SUFF))  
             printf("Expanding \"%s\"...", cgn->name);  
         cp = Var_Subst(cgn->name, &pgn->context, TRUE);  
   
         if (cp != NULL) {      cp = Var_Subst(cgn->name, &pgn->context, TRUE);
             LIST        members;      if (cp == NULL) {
           printf("Problem substituting in %s", cgn->name);
           printf("\n");
           return;
       }
   
             Lst_Init(&members);      Lst_Init(&members);
             if (cgn->type & OP_ARCHV) {  
                 /*  
                  * Node was an archive(member) target, so we want to call  
                  * on the Arch module to find the nodes for us, expanding  
                  * variables in the parent's context.  
                  */  
                 char    *sacrifice = cp;  
   
                 (void)Arch_ParseArchive(&sacrifice, &members, &pgn->context);      if (cgn->type & OP_ARCHV) {
             } else {          /*
                 /*           * Node was an archive(member) target, so we want to call
                  * Break the result into a vector of strings whose nodes           * on the Arch module to find the nodes for us, expanding
                  * we can find, then add those nodes to the members list.           * variables in the parent's context.
                  * Unfortunately, we can't use brk_string b/c it           */
                  * doesn't understand about variable specifications with          char    *sacrifice = cp;
                  * spaces in them...  
                  */  
                 char        *start;  
                 char        *initcp = cp;   /* For freeing... */  
   
                 for (start = cp; *start == ' ' || *start == '\t'; start++)          (void)Arch_ParseArchive(&sacrifice, &members, &pgn->context);
                     continue;      } else {
                 for (cp = start; *cp != '\0'; cp++) {          /* Break the result into a vector of strings whose nodes
                     if (*cp == ' ' || *cp == '\t') {           * we can find, then add those nodes to the members list.
                         /*           * Unfortunately, we can't use brk_string because it
                          * White-space -- terminate element, find the node,           * doesn't understand about variable specifications with
                          * add it, skip any further spaces.           * spaces in them...  */
                          */          char        *start, *cp2;
                         *cp++ = '\0';  
                         gn = Targ_FindNode(start, TARG_CREATE);  
                         Lst_AtEnd(&members, gn);  
                         while (*cp == ' ' || *cp == '\t') {  
                             cp++;  
                         }  
                         /*  
                          * Adjust cp for increment at start of loop, but  
                          * set start to first non-space.  
                          */  
                         start = cp--;  
                     } else if (*cp == '$') {  
                         /*  
                          * Start of a variable spec -- contact variable module  
                          * to find the end so we can skip over it.  
                          */  
                         char    *junk;  
                         size_t  len;  
                         Boolean doFree;  
   
                         junk = Var_Parse(cp, &pgn->context, TRUE, &len, &doFree);          for (start = cp; *start == ' ' || *start == '\t'; start++)
                         if (junk != var_Error)              continue;
                             cp += len - 1;          for (cp2 = start; *cp2 != '\0';) {
               if (isspace(*cp2)) {
                   /* White-space -- terminate element, find the node,
                    * add it, skip any further spaces.  */
                   gn = Targ_FindNode(start, cp2, TARG_CREATE);
                   cp2++;
                   Lst_AtEnd(&members, gn);
                   while (isspace(*cp2))
                       cp2++;
                   /* Adjust cp2 for increment at start of loop, but
                    * set start to first non-space.  */
                   start = cp2;
               } else if (*cp2 == '$')
                   /* Start of a variable spec -- contact variable module
                    * to find the end so we can skip over it.  */
                   cp2 += Var_ParseSkip(cp2, &pgn->context, NULL);
               else if (*cp2 == '\\' && cp2[1] != '\0')
                   /* Escaped something -- skip over it.  */
                   cp2+=2;
           }
   
                         if (doFree)          if (cp2 != start) {
                             free(junk);              /* Stuff left over -- add it to the list too.  */
                     } else if (*cp == '\\' && *cp != '\0') {              gn = Targ_FindNode(start, cp2, TARG_CREATE);
                         /*              Lst_AtEnd(&members, gn);
                          * Escaped something -- skip over it  
                          */  
                         cp++;  
                     }  
                 }  
   
                 if (cp != start) {  
                     /*  
                      * Stuff left over -- add it to the list too  
                      */  
                     gn = Targ_FindNode(start, TARG_CREATE);  
                     Lst_AtEnd(&members, gn);  
                 }  
                 /*  
                  * Point cp back at the beginning again so the variable value  
                  * can be freed.  
                  */  
                 cp = initcp;  
             }  
             /* Add all elements of the members list to the parent node.  */  
             while((gn = (GNode *)Lst_DeQueue(&members)) != NULL) {  
                 if (DEBUG(SUFF))  
                     printf("%s...", gn->name);  
                 if (Lst_Member(&pgn->children, gn) == NULL) {  
                     Lst_Append(&pgn->children, prevLN, gn);  
                     prevLN = Lst_Succ(prevLN);  
                     Lst_AtEnd(&gn->parents, pgn);  
                     pgn->unmade++;  
                 }  
             }  
             Lst_Destroy(&members, NOFREE);  
             /* Free the result */  
             free(cp);  
         }          }
         /*      }
          * Now the source is expanded, remove it from the list of children to      /* Add all elements of the members list to the parent node.  */
          * keep it from being processed.      while ((gn = (GNode *)Lst_DeQueue(&members)) != NULL) {
          */  
         ln = Lst_Member(&pgn->children, cgn);  
         pgn->unmade--;  
         Lst_Remove(&pgn->children, ln);  
         if (DEBUG(SUFF))          if (DEBUG(SUFF))
             printf("\n");              printf("%s...", gn->name);
     } else if (Dir_HasWildcards(cgn->name)) {          if (Lst_Member(&pgn->children, gn) == NULL) {
         LIST    exp;        /* List of expansions */              Lst_Append(&pgn->children, after, gn);
         Lst     path;       /* Search path along which to expand */              after = Lst_Adv(after);
               Lst_AtEnd(&gn->parents, pgn);
               pgn->unmade++;
           }
       }
       /* Free the result.  */
       free(cp);
       if (DEBUG(SUFF))
           printf("\n");
   }
   
         /*  static void
          * Find a path along which to expand the word.  SuffExpandWildChildren(after, cgn, pgn)
          *      LstNode     after;
          * If the word has a known suffix, use that path.      GNode       *cgn;
          * If it has no known suffix and we're allowed to use the null      GNode       *pgn;
          *   suffix, use its path.  {
          * Else use the default system search path.      LstNode     ln;             /* List element for old source */
          */      char        *cp;            /* Expanded value */
         cp = cgn->name + strlen(cgn->name);  
         ln = Lst_Find(&sufflist, SuffSuffIsSuffixP, cp);  
   
         if (DEBUG(SUFF))      LIST        exp;        /* List of expansions */
             printf("Wildcard expanding \"%s\"...", cgn->name);      Lst         path;       /* Search path along which to expand */
   
         if (ln != NULL) {      if (DEBUG(SUFF))
             Suff    *s = (Suff *)Lst_Datum(ln);          printf("Wildcard expanding \"%s\"...", cgn->name);
   
             if (DEBUG(SUFF))      /* Find a path along which to expand the word.
                 printf("suffix is \"%s\"...", s->name);       *
             path = &s->searchPath;       * If the word has a known suffix, use that path.
         } else {       * If it has no known suffix and we're allowed to use the null
             /*       *   suffix, use its path.
              * Use default search path       * Else use the default system search path.  */
              */      cp = cgn->name + strlen(cgn->name);
             path = &dirSearchPath;      ln = Lst_FindConst(&sufflist, SuffSuffIsSuffixP, cp);
         }  
   
         /* Expand the word along the chosen path */      if (ln != NULL) {
         Lst_Init(&exp);          Suff    *s = (Suff *)Lst_Datum(ln);
         Dir_Expand(cgn->name, path, &exp);  
   
         /* Fetch next expansion off the list and find its GNode.  */          if (DEBUG(SUFF))
         while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) {              printf("suffix is \"%s\"...", s->name);
             if (DEBUG(SUFF))          path = &s->searchPath;
                 printf("%s...", cp);      } else
             gn = Targ_FindNode(cp, TARG_CREATE);          /* Use default search path.  */
           path = &dirSearchPath;
   
             /*      /* Expand the word along the chosen path. */
              * If gn isn't already a child of the parent, make it so and      Lst_Init(&exp);
              * up the parent's count of unmade children.      Dir_Expand(cgn->name, path, &exp);
              */  
             if (Lst_Member(&pgn->children, gn) == NULL) {  
                 Lst_Append(&pgn->children, prevLN, gn);  
                 prevLN = Lst_Succ(prevLN);  
                 Lst_AtEnd(&gn->parents, pgn);  
                 pgn->unmade++;  
             }  
         }  
   
         /* Nuke what's left of the list.  */      /* Fetch next expansion off the list and find its GNode.  */
         Lst_Destroy(&exp, NOFREE);      while ((cp = (char *)Lst_DeQueue(&exp)) != NULL) {
           GNode           *gn;            /* New source 8) */
         /*  
          * Now the source is expanded, remove it from the list of children to  
          * keep it from being processed.  
          */  
         ln = Lst_Member(&pgn->children, cgn);  
         pgn->unmade--;  
         Lst_Remove(&pgn->children, ln);  
         if (DEBUG(SUFF))          if (DEBUG(SUFF))
             printf("\n");              printf("%s...", cp);
           gn = Targ_FindNode(cp, NULL, TARG_CREATE);
   
           /* If gn isn't already a child of the parent, make it so and
            * up the parent's count of unmade children.  */
           if (Lst_Member(&pgn->children, gn) == NULL) {
               Lst_Append(&pgn->children, after, gn);
               after = Lst_Adv(after);
               Lst_AtEnd(&gn->parents, pgn);
               pgn->unmade++;
           }
     }      }
   
       if (DEBUG(SUFF))
           printf("\n");
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
    * SuffExpandChildren --
    *      Expand the names of any children of a given node that contain
    *      variable invocations or file wildcards into actual targets.
    *
    * Side Effects:
    *      The expanded node is removed from the parent's list of children,
    *      and the parent's unmade counter is decremented, but other nodes
    *      may be added.
    *-----------------------------------------------------------------------
    */
   static void
   SuffExpandChildren(cgnp, pgnp)
       void        *cgnp;          /* Child to examine */
       void        *pgnp;          /* Parent node being processed */
   {
       GNode       *cgn = (GNode *)cgnp;
       GNode       *pgn = (GNode *)pgnp;
       LstNode     ln;
       /* New nodes effectively take the place of the child, so we place them
        * after the child.  */
       ln = Lst_Member(&pgn->children, cgn);
   
       /* First do variable expansion -- this takes precedence over
        * wildcard expansion. If the result contains wildcards, they'll be gotten
        * to later since the resulting words are tacked on to the end of
        * the children list.  */
       if (strchr(cgn->name, '$') != NULL)
           SuffExpandVarChildren(ln, cgn, pgn);
       else if (Dir_HasWildcards(cgn->name))
           SuffExpandWildChildren(ln, cgn, pgn);
       else
           /* Third case: nothing to expand.  */
           return;
   
       /* Since the source was expanded, remove it from the list of children to
        * keep it from being processed.  */
       pgn->unmade--;
       Lst_Remove(&pgn->children, ln);
   }
   
   /*-
    *-----------------------------------------------------------------------
  * SuffApplyTransform --   * SuffApplyTransform --
  *      Apply a transformation rule, given the source and target nodes   *      Apply a transformation rule, given the source and target nodes
  *      and suffixes.   *      and suffixes.
Line 1449 
Line 1369 
  *      All attributes but OP_DEPMASK and OP_TRANSFORM are applied   *      All attributes but OP_DEPMASK and OP_TRANSFORM are applied
  *      to the target. The target also inherits all the sources for   *      to the target. The target also inherits all the sources for
  *      the transformation rule.   *      the transformation rule.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Boolean  static Boolean
 SuffApplyTransform(tGn, sGn, t, s)  SuffApplyTransform(tGn, sGn, t, s)
     GNode       *tGn;       /* Target node */      GNode       *tGn;   /* Target node */
     GNode       *sGn;       /* Source node */      GNode       *sGn;   /* Source node */
     Suff        *t;         /* Target suffix */      Suff        *t;     /* Target suffix */
     Suff        *s;         /* Source suffix */      Suff        *s;     /* Source suffix */
 {  {
     LstNode     ln;         /* General node */      LstNode     ln;     /* General node */
     LstNode     np;         /* Next node for loop */      LstNode     np;         /* Next node for loop */
     char        *tname;     /* Name of transformation rule */      char        *tname; /* Name of transformation rule */
     GNode       *gn;        /* Node for same */      GNode       *gn;    /* Node for same */
   
     if (Lst_Member(&tGn->children, sGn) == NULL) {      if (Lst_AddNew(&tGn->children, sGn) == SUCCESS) {
         /*          /* Not already linked, so form the proper links between the
          * Not already linked, so form the proper links between the           * target and source.  */
          * target and source.  
          */  
         Lst_AtEnd(&tGn->children, sGn);  
         Lst_AtEnd(&sGn->parents, tGn);          Lst_AtEnd(&sGn->parents, tGn);
         tGn->unmade += 1;          tGn->unmade++;
     }      }
   
     if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {      if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
         /*          /* When a :: node is used as the implied source of a node, we have
          * When a :: node is used as the implied source of a node, we have  
          * to link all its cohorts in as sources as well. Only the initial           * to link all its cohorts in as sources as well. Only the initial
          * sGn gets the target in its iParents list, however, as that           * sGn gets the target in its iParents list, however, as that
          * will be sufficient to get the .IMPSRC variable set for tGn           * will be sufficient to get the .IMPSRC variable set for tGn.  */
          */  
         for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) {          for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) {
             gn = (GNode *)Lst_Datum(ln);              gn = (GNode *)Lst_Datum(ln);
   
             if (Lst_Member(&tGn->children, gn) == NULL) {              if (Lst_AddNew(&tGn->children, gn) == SUCCESS) {
                 /*                  /* Not already linked, so form the proper links between the
                  * Not already linked, so form the proper links between the                   * target and source.  */
                  * target and source.  
                  */  
                 Lst_AtEnd(&tGn->children, gn);  
                 Lst_AtEnd(&gn->parents, tGn);                  Lst_AtEnd(&gn->parents, tGn);
                 tGn->unmade += 1;                  tGn->unmade++;
             }              }
         }          }
     }      }
     /*      /* Locate the transformation rule itself.  */
      * Locate the transformation rule itself  
      */  
     tname = str_concat(s->name, t->name, 0);      tname = str_concat(s->name, t->name, 0);
     ln = Lst_Find(&transforms, SuffGNHasNameP, tname);      ln = Lst_FindConst(&transforms, SuffGNHasNameP, tname);
     free(tname);      free(tname);
   
     if (ln == NULL) {      if (ln == NULL)
         /*          /*
          * Not really such a transformation rule (can happen when we're           * Not really such a transformation rule (can happen when we're
          * called to link an OP_MEMBER and OP_ARCHV node), so return           * called to link an OP_MEMBER and OP_ARCHV node), so return
          * FALSE.           * FALSE.
          */           */
         return(FALSE);          return FALSE;
     }  
   
     gn = (GNode *)Lst_Datum(ln);      gn = (GNode *)Lst_Datum(ln);
   
     if (DEBUG(SUFF)) {      if (DEBUG(SUFF))
         printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);          printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
     }  
   
     /*      /* Record last child for expansion purposes.  */
      * Record last child for expansion purposes  
      */  
     ln = Lst_Last(&tGn->children);      ln = Lst_Last(&tGn->children);
   
     /*      /* Pass the buck to Make_HandleUse to apply the rule.  */
      * Pass the buck to Make_HandleUse to apply the rule      Make_HandleUse(gn, tGn);
      */  
     (void)Make_HandleUse(gn, tGn);  
   
     /*      /* Deal with wildcards and variables in any acquired sources.  */
      * Deal with wildcards and variables in any acquired sources  
      */  
     for (ln = Lst_Succ(ln); ln != NULL; ln = np) {      for (ln = Lst_Succ(ln); ln != NULL; ln = np) {
         np = Lst_Adv(ln);          np = Lst_Adv(ln);
         SuffExpandChildren(Lst_Datum(ln), tGn);          SuffExpandChildren(Lst_Datum(ln), tGn);
     }      }
   
     /*      /* Keep track of another parent to which this beast is transformed so
      * Keep track of another parent to which this beast is transformed so       * the .IMPSRC variable can be set correctly for the parent.  */
      * the .IMPSRC variable can be set correctly for the parent.  
      */  
     Lst_AtEnd(&sGn->iParents, tGn);      Lst_AtEnd(&sGn->iParents, tGn);
   
     return(TRUE);      return TRUE;
 }  }
   
   
Line 1550 
Line 1449 
  * SuffFindArchiveDeps --   * SuffFindArchiveDeps --
  *      Locate dependencies for an OP_ARCHV node.   *      Locate dependencies for an OP_ARCHV node.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      Same as Suff_FindDeps   *      Same as Suff_FindDeps
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffFindArchiveDeps(gn, slst)  SuffFindArchiveDeps(gn, slst)
     GNode       *gn;        /* Node for which to locate dependencies */      GNode       *gn;        /* Node for which to locate dependencies */
     Lst         slst;      Lst         slst;
 {  {
     char        *eoarch;    /* End of archive portion */      char        *eoarch;    /* End of archive portion */
     char        *eoname;    /* End of member portion */      char        *eoname;    /* End of member portion */
     GNode       *mem;       /* Node for member */      GNode       *mem;       /* Node for member */
     Suff        *ms;        /* Suffix descriptor for member */      Suff        *ms;        /* Suffix descriptor for member */
     char        *name;      /* Start of member's name */      char        *name;      /* Start of member's name */
   
     /*      /* The node is an archive(member) pair. so we must find a suffix
      * The node is an archive(member) pair. so we must find a       * for both of them.  */
      * suffix for both of them.      eoarch = strchr(gn->name, '(');
      */      if (eoarch == NULL)
     eoarch = strchr (gn->name, '(');  
     eoname = strchr (eoarch, ')');  
     if (eoarch == NULL || eoname == NULL)  
         return;          return;
   
     *eoname = '\0';       /* Nuke parentheses during suffix search */  
     *eoarch = '\0';       /* So a suffix can be found */  
   
     name = eoarch + 1;      name = eoarch + 1;
   
     /*      eoname = strchr(name, ')');
      * To simplify things, call Suff_FindDeps recursively on the member now,      if (eoname == NULL)
           return;
   
       /* To simplify things, call Suff_FindDeps recursively on the member now,
      * so we can simply compare the member's .PREFIX and .TARGET variables       * so we can simply compare the member's .PREFIX and .TARGET variables
      * to locate its suffix. This allows us to figure out the suffix to       * to locate its suffix. This allows us to figure out the suffix to
      * use for the archive without having to do a quadratic search over the       * use for the archive without having to do a quadratic search over the
      * suffix list, backtracking for each one...       * suffix list, backtracking for each one...  */
      */      mem = Targ_FindNode(name, eoname, TARG_CREATE);
     mem = Targ_FindNode(name, TARG_CREATE);  
     SuffFindDeps(mem, slst);      SuffFindDeps(mem, slst);
   
     /*      /* Create the link between the two nodes right off. */
      * Create the link between the two nodes right off      if (Lst_AddNew(&gn->children, mem) == SUCCESS) {
      */  
     if (Lst_Member(&gn->children, mem) == NULL) {  
         Lst_AtEnd(&gn->children, mem);  
         Lst_AtEnd(&mem->parents, gn);          Lst_AtEnd(&mem->parents, gn);
         gn->unmade += 1;          gn->unmade++;
     }      }
   
     /* Copy variables from member node to this one.  */      /* Copy variables from member node to this one.  */
Line 1608 
Line 1496 
   
     ms = mem->suffix;      ms = mem->suffix;
     if (ms == NULL) {      if (ms == NULL) {
         /*          /* Didn't know what it was -- use .NULL suffix if not in make mode.  */
          * Didn't know what it was -- use .NULL suffix if not in make mode          if (DEBUG(SUFF))
          */  
         if (DEBUG(SUFF)) {  
             printf("using null suffix\n");              printf("using null suffix\n");
         }  
         ms = suffNull;          ms = suffNull;
     }      }
   
   
     /*      /* Set the other two local variables required for this target.  */
      * Set the other two local variables required for this target.      Varq_Set(MEMBER_INDEX, mem->name, gn);
      */  
     Varq_Set(MEMBER_INDEX, name, gn);  
     Varq_Set(ARCHIVE_INDEX, gn->name, gn);      Varq_Set(ARCHIVE_INDEX, gn->name, gn);
   
     if (ms != NULL) {      if (ms != NULL) {
Line 1631 
Line 1514 
          * through the entire list, we just look at suffixes to which the           * through the entire list, we just look at suffixes to which the
          * member's suffix may be transformed...           * member's suffix may be transformed...
          */           */
         LstNode     ln;          LstNode     ln;
   
         /*          /* Use first matching suffix...  */
          * Use first matching suffix...          ln = Lst_FindConst(&ms->parents, SuffSuffIsSuffixP, eoarch);
          */  
         ln = Lst_Find(&ms->parents, SuffSuffIsSuffixP, eoarch);  
   
         if (ln != NULL) {          if (ln != NULL) {
             /*              /* Got one -- apply it.  */
              * Got one -- apply it  
              */  
             if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&              if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&
                 DEBUG(SUFF))                  DEBUG(SUFF))
             {  
                 printf("\tNo transformation from %s -> %s\n",                  printf("\tNo transformation from %s -> %s\n",
                        ms->name, ((Suff *)Lst_Datum(ln))->name);                         ms->name, ((Suff *)Lst_Datum(ln))->name);
             }  
         }          }
     }      }
   
     /*      /* Pretend gn appeared to the left of a dependency operator so
      * Replace the opening and closing parens now we've no need of the separate  
      * pieces.  
      */  
     *eoarch = '('; *eoname = ')';  
   
     /*  
      * Pretend gn appeared to the left of a dependency operator so  
      * the user needn't provide a transformation from the member to the       * the user needn't provide a transformation from the member to the
      * archive.       * archive.  */
      */      if (OP_NOP(gn->type))
     if (OP_NOP(gn->type)) {  
         gn->type |= OP_DEPENDS;          gn->type |= OP_DEPENDS;
     }  
   
     /*      /* Flag the member as such so we remember to look in the archive for
      * Flag the member as such so we remember to look in the archive for       * its modification time.  */
      * its modification time.  
      */  
     mem->type |= OP_MEMBER;      mem->type |= OP_MEMBER;
 }  }
   
Line 1678 
Line 1544 
  * SuffFindNormalDeps --   * SuffFindNormalDeps --
  *      Locate implicit dependencies for regular targets.   *      Locate implicit dependencies for regular targets.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Same as Suff_FindDeps...   *      Same as Suff_FindDeps...
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 SuffFindNormalDeps(gn, slst)  SuffFindNormalDeps(gn, slst)
     GNode       *gn;        /* Node for which to find sources */      GNode       *gn;        /* Node for which to find sources */
     Lst         slst;      Lst         slst;
 {  {
     char        *eoname;    /* End of name */      char        *eoname;    /* End of name */
     char        *sopref;    /* Start of prefix */      char        *sopref;    /* Start of prefix */
     LstNode     ln;         /* Next suffix node to check */      LstNode     ln;         /* Next suffix node to check */
     LstNode     np;      LstNode     np;
     LIST        srcs;       /* List of sources at which to look */      LIST        srcs;       /* List of sources at which to look */
     LIST        targs;      /* List of targets to which things can be      LIST        targs;      /* List of targets to which things can be
                              * transformed. They all have the same file,                               * transformed. They all have the same file,
                              * but different suff and pref fields */                               * but different suff and pref fields */
     Src         *bottom;    /* Start of found transformation path */      Src         *bottom;    /* Start of found transformation path */
     Src         *src;       /* General Src pointer */      Src         *src;       /* General Src pointer */
     char        *pref;      /* Prefix to use */      char        *pref;      /* Prefix to use */
     Src         *targ;      /* General Src target pointer */      Src         *targ;      /* General Src target pointer */
   
   
     eoname = gn->name + strlen(gn->name);      eoname = gn->name + strlen(gn->name);
   
     sopref = gn->name;      sopref = gn->name;
   
     /*      /* Begin at the beginning...  */
      * Begin at the beginning...  
      */  
     ln = Lst_First(&sufflist);      ln = Lst_First(&sufflist);
     Lst_Init(&srcs);      Lst_Init(&srcs);
     Lst_Init(&targs);      Lst_Init(&targs);
   
     /*      /* We're caught in a catch-22 here. On the one hand, we want to use any
      * We're caught in a catch-22 here. On the one hand, we want to use any  
      * transformation implied by the target's sources, but we can't examine       * transformation implied by the target's sources, but we can't examine
      * the sources until we've expanded any variables/wildcards they may hold,       * the sources until we've expanded any variables/wildcards they may hold,
      * and we can't do that until we've set up the target's local variables       * and we can't do that until we've set up the target's local variables
Line 1732 
Line 1591 
      * checking transformations to all possible suffixes of the target,       * checking transformations to all possible suffixes of the target,
      * use what we find to set the target's local variables, expand the       * use what we find to set the target's local variables, expand the
      * children, then look for any overriding transformations they imply.       * children, then look for any overriding transformations they imply.
      * Should we find one, we discard the one we found before.       * Should we find one, we discard the one we found before.  */
      */  
   
     while (ln != NULL) {      while (ln != NULL) {
         /*          /* Look for next possible suffix...  */
          * Look for next possible suffix...          ln = Lst_FindFromConst(ln, SuffSuffIsSuffixP, eoname);
          */  
         ln = Lst_FindFrom(ln, SuffSuffIsSuffixP, eoname);  
   
         if (ln != NULL) {          if (ln != NULL) {
             int     prefLen;        /* Length of the prefix */              int     prefLen;        /* Length of the prefix */
             Src     *targ;              Src     *targ;
   
             /*              /* Allocate a Src structure to which things can be transformed.  */
              * Allocate a Src structure to which things can be transformed              targ = emalloc(sizeof(Src));
              */  
             targ = (Src *)emalloc(sizeof (Src));  
             targ->file = estrdup(gn->name);              targ->file = estrdup(gn->name);
             targ->suff = (Suff *)Lst_Datum(ln);              targ->suff = (Suff *)Lst_Datum(ln);
             targ->node = gn;              targ->node = gn;
             targ->parent = (Src *)NULL;              targ->parent = NULL;
             targ->children = 0;              targ->children = 0;
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
             Lst_Init(&targ->cp);              Lst_Init(&targ->cp);
 #endif  #endif
   
             /*              /* Allocate room for the prefix, whose end is found by subtracting
              * Allocate room for the prefix, whose end is found by subtracting               * the length of the suffix from the end of the name.  */
              * the length of the suffix from the end of the name.  
              */  
             prefLen = (eoname - targ->suff->nameLen) - sopref;              prefLen = (eoname - targ->suff->nameLen) - sopref;
             targ->pref = emalloc(prefLen + 1);              targ->pref = emalloc(prefLen + 1);
             memcpy(targ->pref, sopref, prefLen);              memcpy(targ->pref, sopref, prefLen);
Line 1778 
Line 1630 
         }          }
     }      }
   
     /*      /* Handle target of unknown suffix...  */
      * Handle target of unknown suffix...  
      */  
     if (Lst_IsEmpty(&targs) && suffNull != NULL) {      if (Lst_IsEmpty(&targs) && suffNull != NULL) {
         if (DEBUG(SUFF)) {          if (DEBUG(SUFF)) {
             printf("\tNo known suffix on %s. Using .NULL suffix\n", gn->name);              printf("\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
         }          }
   
         targ = (Src *)emalloc(sizeof (Src));          targ = emalloc(sizeof(Src));
         targ->file = estrdup(gn->name);          targ->file = estrdup(gn->name);
         targ->suff = suffNull;          targ->suff = suffNull;
         targ->node = gn;          targ->node = gn;
         targ->parent = (Src *)NULL;          targ->parent = NULL;
         targ->children = 0;          targ->children = 0;
         targ->pref = estrdup(sopref);          targ->pref = estrdup(sopref);
 #ifdef DEBUG_SRC  #ifdef DEBUG_SRC
         Lst_Init(&targ->cp);          Lst_Init(&targ->cp);
 #endif  #endif
   
         /*          /* Only use the default suffix rules if we don't have commands
          * Only use the default suffix rules if we don't have commands           * or dependencies defined for this gnode.  */
          * or dependencies defined for this gnode  
          */  
         if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))          if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
             SuffAddLevel(&srcs, targ);              SuffAddLevel(&srcs, targ);
         else {          else {
Line 1814 
Line 1662 
         Lst_AtEnd(&targs, targ);          Lst_AtEnd(&targs, targ);
     }      }
   
     /*      /* Using the list of possible sources built up from the target suffix(es),
      * Using the list of possible sources built up from the target suffix(es),       * try and find an existing file/target that matches.  */
      * try and find an existing file/target that matches.  
      */  
     bottom = SuffFindThem(&srcs, slst);      bottom = SuffFindThem(&srcs, slst);
   
     if (bottom == NULL) {      if (bottom == NULL) {
         /*          /* No known transformations -- use the first suffix found for setting
          * No known transformations -- use the first suffix found for setting           * the local variables.  */
          * the local variables.  
          */  
         if (!Lst_IsEmpty(&targs))          if (!Lst_IsEmpty(&targs))
             targ = (Src *)Lst_Datum(Lst_First(&targs));              targ = (Src *)Lst_Datum(Lst_First(&targs));
         else          else
             targ = NULL;              targ = NULL;
     } else {      } else {
         /*          /* Work up the transformation path to find the suffix of the
          * Work up the transformation path to find the suffix of the           * target to which the transformation was made.  */
          * target to which the transformation was made.  
          */  
         for (targ = bottom; targ->parent != NULL; targ = targ->parent)          for (targ = bottom; targ->parent != NULL; targ = targ->parent)
             continue;              continue;
     }      }
   
     /*      /* The .TARGET variable we always set to be the name at this point,
      * The .TARGET variable we always set to be the name at this point,  
      * since it's only set to the path if the thing is only a source and       * since it's only set to the path if the thing is only a source and
      * if it's only a source, it doesn't matter what we put here as far       * if it's only a source, it doesn't matter what we put here as far
      * as expanding sources is concerned, since it has none...       * as expanding sources is concerned, since it has none...  */
      */  
     Varq_Set(TARGET_INDEX, gn->name, gn);      Varq_Set(TARGET_INDEX, gn->name, gn);
   
     pref = (targ != NULL) ? targ->pref : gn->name;      pref = targ != NULL ? targ->pref : gn->name;
     Varq_Set(PREFIX_INDEX, pref, gn);      Varq_Set(PREFIX_INDEX, pref, gn);
   
     /*      /* Now we've got the important local variables set, expand any sources
      * Now we've got the important local variables set, expand any sources       * that still contain variables or wildcards in their names.  */
      * that still contain variables or wildcards in their names.  
      */  
     for (ln = Lst_First(&gn->children); ln != NULL; ln = np) {      for (ln = Lst_First(&gn->children); ln != NULL; ln = np) {
         np = Lst_Adv(ln);          np = Lst_Adv(ln);
         SuffExpandChildren(Lst_Datum(ln), gn);          SuffExpandChildren(Lst_Datum(ln), gn);
     }      }
   
     if (targ == NULL) {      if (targ == NULL) {
         if (DEBUG(SUFF)) {          if (DEBUG(SUFF))
             printf("\tNo valid suffix on %s\n", gn->name);              printf("\tNo valid suffix on %s\n", gn->name);
         }  
   
 sfnd_abort:  sfnd_abort:
         /*          /* Deal with finding the thing on the default search path if the
          * Deal with finding the thing on the default search path if the  
          * node is only a source (not on the lhs of a dependency operator           * node is only a source (not on the lhs of a dependency operator
          * or [XXX] it has neither children or commands).           * or [XXX] it has neither children or commands).  */
          */  
         if (OP_NOP(gn->type) ||          if (OP_NOP(gn->type) ||
             (Lst_IsEmpty(&gn->children) && Lst_IsEmpty(&gn->commands)))              (Lst_IsEmpty(&gn->children) && Lst_IsEmpty(&gn->commands)))
         {          {
Line 1880 
Line 1715 
                 Varq_Set(TARGET_INDEX, gn->path, gn);                  Varq_Set(TARGET_INDEX, gn->path, gn);
   
                 if (targ != NULL) {                  if (targ != NULL) {
                     /*                      /* Suffix known for the thing -- trim the suffix off
                      * Suffix known for the thing -- trim the suffix off                       * the path to form the proper .PREFIX variable.  */
                      * the path to form the proper .PREFIX variable.                      int         savep = strlen(gn->path) - targ->suff->nameLen;
                      */  
                     int         savep = strlen(gn->path) - targ->suff->nameLen;  
                     char        savec;                      char        savec;
   
                     gn->suffix = targ->suff;                      gn->suffix = targ->suff;
Line 1901 
Line 1734 
   
                     gn->path[savep] = savec;                      gn->path[savep] = savec;
                 } else {                  } else {
                     /*                      /* The .PREFIX gets the full path if the target has
                      * The .PREFIX gets the full path if the target has                       * no known suffix.  */
                      * no known suffix.  
                      */  
                     gn->suffix = NULL;                      gn->suffix = NULL;
   
                     if ((ptr = strrchr(gn->path, '/')) != NULL)                      if ((ptr = strrchr(gn->path, '/')) != NULL)
Line 1916 
Line 1747 
                 }                  }
             }              }
         } else {          } else {
             /*              /* Not appropriate to search for the thing -- set the
              * Not appropriate to search for the thing -- set the  
              * path to be the name so Dir_MTime won't go grovelling for               * path to be the name so Dir_MTime won't go grovelling for
              * it.               * it.  */
              */              gn->suffix = targ == NULL ? NULL : targ->suff;
             gn->suffix = (targ == NULL) ? NULL : targ->suff;  
             efree(gn->path);              efree(gn->path);
             gn->path = estrdup(gn->name);              gn->path = estrdup(gn->name);
         }          }
Line 1929 
Line 1758 
         goto sfnd_return;          goto sfnd_return;
     }      }
   
     /*      /* If the suffix indicates that the target is a library, mark that in
      * If the suffix indicates that the target is a library, mark that in       * the node's type field.  */
      * the node's type field.  
      */  
     if (targ->suff->flags & SUFF_LIBRARY) {      if (targ->suff->flags & SUFF_LIBRARY) {
         gn->type |= OP_LIB;          gn->type |= OP_LIB;
     }      }
   
     /*      /* Check for overriding transformation rule implied by sources.  */
      * Check for overriding transformation rule implied by sources  
      */  
     if (!Lst_IsEmpty(&gn->children)) {      if (!Lst_IsEmpty(&gn->children)) {
         src = SuffFindCmds(targ, slst);          src = SuffFindCmds(targ, slst);
   
         if (src != (Src *)NULL) {          if (src != NULL) {
             /*              /* Free up all the Src structures in the transformation path
              * Free up all the Src structures in the transformation path               * up to, but not including, the parent node.  */
              * up to, but not including, the parent node.  
              */  
             while (bottom && bottom->parent != NULL) {              while (bottom && bottom->parent != NULL) {
                 if (Lst_Member(slst, bottom) == NULL) {                  (void)Lst_AddNew(slst, bottom);
                     Lst_AtEnd(slst, bottom);  
                 }  
                 bottom = bottom->parent;                  bottom = bottom->parent;
             }              }
             bottom = src;              bottom = src;
Line 1959 
Line 1780 
     }      }
   
     if (bottom == NULL) {      if (bottom == NULL) {
         /*          /* No idea from where it can come -- return now.  */
          * No idea from where it can come -- return now.  
          */  
         goto sfnd_abort;          goto sfnd_abort;
     }      }
   
     /*      /* We now have a list of Src structures headed by 'bottom' and linked via
      * We now have a list of Src structures headed by 'bottom' and linked via  
      * their 'parent' pointers. What we do next is create links between       * their 'parent' pointers. What we do next is create links between
      * source and target nodes (which may or may not have been created)       * source and target nodes (which may or may not have been created)
      * and set the necessary local variables in each target. The       * and set the necessary local variables in each target. The
Line 1975 
Line 1793 
      * suffix. Note that this causes the commands list of the original       * suffix. Note that this causes the commands list of the original
      * node, gn, to be replaced by the commands of the final       * node, gn, to be replaced by the commands of the final
      * transformation rule. Also, the unmade field of gn is incremented.       * transformation rule. Also, the unmade field of gn is incremented.
      * Etc.       * Etc.  */
      */  
     if (bottom->node == NULL) {      if (bottom->node == NULL) {
         bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);          bottom->node = Targ_FindNode(bottom->file, NULL, TARG_CREATE);
     }      }
   
     for (src = bottom; src->parent != (Src *)NULL; src = src->parent) {      for (src = bottom; src->parent != NULL; src = src->parent) {
         targ = src->parent;          targ = src->parent;
   
         src->node->suffix = src->suff;          src->node->suffix = src->suff;
   
         if (targ->node == NULL) {          if (targ->node == NULL) {
             targ->node = Targ_FindNode(targ->file, TARG_CREATE);              targ->node = Targ_FindNode(targ->file, NULL, TARG_CREATE);
         }          }
   
         SuffApplyTransform(targ->node, src->node,          SuffApplyTransform(targ->node, src->node,
                            targ->suff, src->suff);                             targ->suff, src->suff);
   
         if (targ->node != gn) {          if (targ->node != gn) {
             /*              /* Finish off the dependency-search process for any nodes
              * Finish off the dependency-search process for any nodes  
              * between bottom and gn (no point in questing around the               * between bottom and gn (no point in questing around the
              * filesystem for their implicit source when it's already               * filesystem for their implicit source when it's already
              * known). Note that the node can't have any sources that               * known). Note that the node can't have any sources that
              * need expanding, since SuffFindThem will stop on an existing               * need expanding, since SuffFindThem will stop on an existing
              * node, so all we need to do is set the standard and System V               * node, so all we need to do is set the standard and System V
              * variables.               * variables.  */
              */  
             targ->node->type |= OP_DEPS_FOUND;              targ->node->type |= OP_DEPS_FOUND;
   
             Varq_Set(PREFIX_INDEX, targ->pref, targ->node);              Varq_Set(PREFIX_INDEX, targ->pref, targ->node);
Line 2013 
Line 1828 
   
     gn->suffix = src->suff;      gn->suffix = src->suff;
   
     /*      /* So Dir_MTime doesn't go questing for it...  */
      * So Dir_MTime doesn't go questing for it...  
      */  
     efree(gn->path);      efree(gn->path);
     gn->path = estrdup(gn->name);      gn->path = estrdup(gn->name);
   
     /*      /* Nuke the transformation path and the Src structures left over in the
      * Nuke the transformation path and the Src structures left over in the       * two lists.  */
      * two lists.  
      */  
 sfnd_return:  sfnd_return:
     if (bottom)      if (bottom)
         if (Lst_Member(slst, bottom) == NULL)          (void)Lst_AddNew(slst, bottom);
             Lst_AtEnd(slst, bottom);  
   
     while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))      while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))
         continue;          continue;
Line 2042 
Line 1852 
  *      Find implicit sources for the target described by the graph node   *      Find implicit sources for the target described by the graph node
  *      gn   *      gn
  *   *
  * Results:  
  *      Nothing.  
  *  
  * Side Effects:   * Side Effects:
  *      Nodes are added to the graph below the passed-in node. The nodes   *      Nodes are added to the graph below the passed-in node. The nodes
  *      are marked to have their IMPSRC variable filled in. The   *      are marked to have their IMPSRC variable filled in. The
Line 2060 
Line 1867 
  *      the .c and .l files don't, the search will branch out in   *      the .c and .l files don't, the search will branch out in
  *      all directions from .o and again from all the nodes on the   *      all directions from .o and again from all the nodes on the
  *      next level until the .l,v node is encountered.   *      next level until the .l,v node is encountered.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
   
Line 2076 
Line 1882 
   
   
 static void  static void
 SuffFindDeps (gn, slst)  SuffFindDeps(gn, slst)
     GNode         *gn;          /* node we're dealing with */      GNode         *gn;          /* node we're dealing with */
     Lst           slst;      Lst           slst;
 {  {
     if (gn->type & OP_DEPS_FOUND) {      if (gn->type & OP_DEPS_FOUND) {
         /*          /*
Line 2090 
Line 1896 
     }      }
   
     if (DEBUG(SUFF)) {      if (DEBUG(SUFF)) {
         printf ("SuffFindDeps (%s)\n", gn->name);          printf("SuffFindDeps (%s)\n", gn->name);
     }      }
   
     if (gn->type & OP_ARCHV) {      if (gn->type & OP_ARCHV) {
Line 2104 
Line 1910 
          * set the TARGET variable to the node's name in order to give it a           * set the TARGET variable to the node's name in order to give it a
          * value).           * value).
          */           */
         LstNode ln;          LstNode ln;
         Suff    *s;          Suff    *s;
   
         ln = Lst_Find(&sufflist, SuffSuffHasNameP, LIBSUFF);          ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, LIBSUFF);
         if (ln != NULL) {          if (ln != NULL) {
             gn->suffix = s = (Suff *)Lst_Datum(ln);              gn->suffix = s = (Suff *)Lst_Datum(ln);
             Arch_FindLib(gn, &s->searchPath);              Arch_FindLib(gn, &s->searchPath);
Line 2121 
Line 1927 
          * the thing. .PREFIX is simply made empty...           * the thing. .PREFIX is simply made empty...
          */           */
         Varq_Set(PREFIX_INDEX, "", gn);          Varq_Set(PREFIX_INDEX, "", gn);
     } else {      } else
         SuffFindNormalDeps(gn, slst);          SuffFindNormalDeps(gn, slst);
     }  
 }  }
   
 /*-  /*-
Line 2131 
Line 1936 
  * Suff_SetNull --   * Suff_SetNull --
  *      Define which suffix is the null suffix.   *      Define which suffix is the null suffix.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      'suffNull' is altered.   *      'suffNull' is altered.
  *   *
  * Notes:   * Notes:
  *      Need to handle the changing of the null suffix gracefully so the   *      Need to handle the changing of the null suffix gracefully so the
  *      old transformation rules don't just go away.   *      old transformation rules don't just go away.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
Line 2150 
Line 1951 
     Suff    *s;      Suff    *s;
     LstNode ln;      LstNode ln;
   
     ln = Lst_Find(&sufflist, SuffSuffHasNameP, name);      ln = Lst_FindConst(&sufflist, SuffSuffHasNameP, name);
     if (ln != NULL) {      if (ln != NULL) {
         s = (Suff *)Lst_Datum(ln);          s = (Suff *)Lst_Datum(ln);
         if (suffNull != (Suff *)NULL) {          if (suffNull != NULL) {
             suffNull->flags &= ~SUFF_NULL;              suffNull->flags &= ~SUFF_NULL;
         }          }
         s->flags |= SUFF_NULL;          s->flags |= SUFF_NULL;
Line 2162 
Line 1963 
          */           */
         suffNull = s;          suffNull = s;
     } else {      } else {
         Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",          Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.",
                      name);                       name);
     }      }
 }  }
Line 2172 
Line 1973 
  * Suff_Init --   * Suff_Init --
  *      Initialize suffixes module   *      Initialize suffixes module
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      Many   *      Many
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Suff_Init ()  Suff_Init()
 {  {
     Lst_Init(&sufflist);      Lst_Init(&sufflist);
 #ifdef CLEANUP  #ifdef CLEANUP
Line 2195 
Line 1993 
      * actually go on the suffix list or everyone will think that's its       * actually go on the suffix list or everyone will think that's its
      * suffix.       * suffix.
      */       */
     emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));      emptySuff = suffNull = emalloc(sizeof(Suff));
   
     suffNull->name =        estrdup ("");      suffNull->name =        estrdup("");
     suffNull->nameLen =     0;      suffNull->nameLen =     0;
     Lst_Init(&suffNull->searchPath);      Lst_Init(&suffNull->searchPath);
     Dir_Concat(&suffNull->searchPath, &dirSearchPath);      Dir_Concat(&suffNull->searchPath, &dirSearchPath);
     Lst_Init(&suffNull->children);      Lst_Init(&suffNull->children);
     Lst_Init(&suffNull->parents);      Lst_Init(&suffNull->parents);
     Lst_Init(&suffNull->ref);      Lst_Init(&suffNull->ref);
     suffNull->sNum =        sNum++;      suffNull->sNum =        sNum++;
     suffNull->flags =       SUFF_NULL;      suffNull->flags =       SUFF_NULL;
   
 }  }
   
Line 2215 
Line 2013 
  * Suff_End --   * Suff_End --
  *      Cleanup the this module   *      Cleanup the this module
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      The memory is free'd.   *      The memory is free'd.
  *----------------------------------------------------------------------   *----------------------------------------------------------------------
Line 2250 
Line 2045 
     void *sp;      void *sp;
 {  {
     Suff    *s = (Suff *)sp;      Suff    *s = (Suff *)sp;
     int     flags;      int     flags;
     int     flag;      int     flag;
   
     printf("# `%s' ", s->name);      printf("# `%s' ", s->name);
   
Line 2275 
Line 2070 
             fputc(flags ? '|' : ')', stdout);              fputc(flags ? '|' : ')', stdout);
         }          }
     }      }
     printf("\n#\tTo: ");      fputc('\n', stdout);
       printf("#\tTo: ");
     Lst_Every(&s->parents, SuffPrintName);      Lst_Every(&s->parents, SuffPrintName);
     printf("\n#\tFrom: ");      fputc('\n', stdout);
       printf("#\tFrom: ");
     Lst_Every(&s->children, SuffPrintName);      Lst_Every(&s->children, SuffPrintName);
     printf("\n#\tSearch Path: ");      fputc('\n', stdout);
       printf("#\tSearch Path: ");
     Dir_PrintPath(&s->searchPath);      Dir_PrintPath(&s->searchPath);
     fputc('\n', stdout);      fputc('\n', stdout);
 }  }

Legend:
Removed from v.1.40  
changed lines
  Added in v.1.41