NetBSD/usr.bin/make/suff.c

2655 lines
70 KiB
C
Raw Normal View History

/* $NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $ */
1993-03-21 12:45:37 +03:00
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
1993-03-21 12:45:37 +03:00
* Copyright (c) 1989 by Berkeley Softworks
* All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Adam de Boor.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MAKE_NATIVE
static char rcsid[] = "$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $";
#else
1997-07-02 01:17:00 +04:00
#include <sys/cdefs.h>
1993-03-21 12:45:37 +03:00
#ifndef lint
#if 0
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
#else
__RCSID("$NetBSD: suff.c,v 1.73 2014/09/07 20:55:34 joerg Exp $");
#endif
1993-03-21 12:45:37 +03:00
#endif /* not lint */
#endif
1993-03-21 12:45:37 +03:00
/*-
* suff.c --
* Functions to maintain suffix lists and find implicit dependents
* using suffix transformation rules
*
* Interface:
* Suff_Init Initialize all things to do with suffixes.
*
* Suff_End Cleanup the module
*
1993-03-21 12:45:37 +03:00
* Suff_DoPaths This function is used to make life easier
* when searching for a file according to its
* suffix. It takes the global search path,
* as defined using the .PATH: target, and appends
* its directories to the path of each of the
* defined suffixes, as specified using
* .PATH<suffix>: targets. In addition, all
* directories given for suffixes labeled as
* include files or libraries, using the .INCLUDES
* or .LIBS targets, are played with using
* Dir_MakeFlags to create the .INCLUDES and
* .LIBS global variables.
*
* Suff_ClearSuffixes Clear out all the suffixes and defined
* transformations.
*
* Suff_IsTransform Return TRUE if the passed string is the lhs
* of a transformation rule.
*
* Suff_AddSuffix Add the passed string as another known suffix.
*
* Suff_GetPath Return the search path for the given suffix.
*
* Suff_AddInclude Mark the given suffix as denoting an include
* file.
*
* Suff_AddLib Mark the given suffix as denoting a library.
*
* Suff_AddTransform Add another transformation to the suffix
* graph. Returns GNode suitable for framing, I
* mean, tacking commands, attributes, etc. on.
*
* Suff_SetNull Define the suffix to consider the suffix of
* any file that doesn't have a known one.
*
1993-03-21 12:45:37 +03:00
* Suff_FindDeps Find implicit sources for and the location of
* a target based on its suffix. Returns the
* bottom-most node added to the graph or NULL
1993-03-21 12:45:37 +03:00
* if the target had no implicit sources.
*
* Suff_FindPath Return the appropriate path to search in
* order to find the node.
1993-03-21 12:45:37 +03:00
*/
#include <stdio.h>
#include "make.h"
#include "hash.h"
#include "dir.h"
1993-03-21 12:45:37 +03:00
static Lst sufflist; /* Lst of suffixes */
#ifdef CLEANUP
static Lst suffClean; /* Lst of suffixes to be cleaned */
#endif
static Lst srclist; /* Lst of sources */
static Lst transforms; /* Lst of transformation rules */
1993-03-21 12:45:37 +03:00
static int sNum = 0; /* Counter for assigning suffix numbers */
1993-03-21 12:45:37 +03:00
/*
* Structure describing an individual suffix.
*/
typedef struct _Suff {
char *name; /* The suffix itself */
int nameLen; /* Length of the suffix */
short flags; /* Type of suffix */
#define SUFF_INCLUDE 0x01 /* One which is #include'd */
#define SUFF_LIBRARY 0x02 /* One which contains a library */
#define SUFF_NULL 0x04 /* The empty suffix */
Lst searchPath; /* The path along which files of this suffix
1993-03-21 12:45:37 +03:00
* may be found */
int sNum; /* The suffix number */
int refCount; /* Reference count of list membership */
Lst parents; /* Suffixes we have a transformation to */
Lst children; /* Suffixes we have a transformation from */
Lst ref; /* List of lists this suffix is referenced */
1993-03-21 12:45:37 +03:00
} Suff;
/*
* for SuffSuffIsSuffix
*/
typedef struct {
char *ename; /* The end of the name */
int len; /* Length of the name */
} SuffixCmpData;
1993-03-21 12:45:37 +03:00
/*
* Structure used in the search for implied sources.
*/
typedef struct _Src {
char *file; /* The file to look for */
char *pref; /* Prefix from which file was formed */
1993-03-21 12:45:37 +03:00
Suff *suff; /* The suffix on the file */
struct _Src *parent; /* The Src for which this is a source */
GNode *node; /* The node describing the file */
int children; /* Count of existing children (so we don't free
* this thing too early or never nuke it) */
#ifdef DEBUG_SRC
Lst cp; /* Debug; children list */
#endif
1993-03-21 12:45:37 +03:00
} Src;
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
/*
* A structure for passing more than one argument to the Lst-library-invoked
* function...
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*/
typedef struct {
Lst l;
Src *s;
} LstSrc;
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
typedef struct {
GNode **gn;
Suff *s;
Boolean r;
} GNodeSuff;
static Suff *suffNull; /* The NULL suffix for this run */
static Suff *emptySuff; /* The empty suffix required for POSIX
* single-suffix transformation rules */
1993-03-21 12:45:37 +03:00
static const char *SuffStrIsPrefix(const char *, const char *);
static char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *);
static int SuffSuffIsSuffixP(const void *, const void *);
static int SuffSuffHasNameP(const void *, const void *);
static int SuffSuffIsPrefix(const void *, const void *);
static int SuffGNHasNameP(const void *, const void *);
static void SuffUnRef(void *, void *);
static void SuffFree(void *);
static void SuffInsert(Lst, Suff *);
static void SuffRemove(Lst, Suff *);
static Boolean SuffParseTransform(char *, Suff **, Suff **);
static int SuffRebuildGraph(void *, void *);
static int SuffScanTargets(void *, void *);
static int SuffAddSrc(void *, void *);
static int SuffRemoveSrc(Lst);
static void SuffAddLevel(Lst, Src *);
static Src *SuffFindThem(Lst, Lst);
static Src *SuffFindCmds(Src *, Lst);
static void SuffExpandChildren(LstNode, GNode *);
static void SuffExpandWildcards(LstNode, GNode *);
static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
static void SuffFindDeps(GNode *, Lst);
static void SuffFindArchiveDeps(GNode *, Lst);
static void SuffFindNormalDeps(GNode *, Lst);
static int SuffPrintName(void *, void *);
static int SuffPrintSuff(void *, void *);
static int SuffPrintTrans(void *, void *);
/*************** Lst Predicates ****************/
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffStrIsPrefix --
* See if pref is a prefix of str.
*
* Input:
* pref possible prefix
* str string to check
*
1993-03-21 12:45:37 +03:00
* Results:
* NULL if it ain't, pointer to character in str after prefix if so
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static const char *
SuffStrIsPrefix(const char *pref, const char *str)
1993-03-21 12:45:37 +03:00
{
while (*str && *pref == *str) {
pref++;
str++;
}
return (*pref ? NULL : str);
}
/*-
*-----------------------------------------------------------------------
* SuffSuffIsSuffix --
* See if suff is a suffix of str. sd->ename should point to THE END
* of the string to check. (THE END == the null byte)
1993-03-21 12:45:37 +03:00
*
* Input:
* s possible suffix
* sd string to examine
*
1993-03-21 12:45:37 +03:00
* Results:
* NULL if it ain't, pointer to character in str before suffix if
* it is.
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static char *
SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd)
1993-03-21 12:45:37 +03:00
{
char *p1; /* Pointer into suffix name */
char *p2; /* Pointer into string being examined */
1993-03-21 12:45:37 +03:00
if (sd->len < s->nameLen)
return NULL; /* this string is shorter than the suffix */
1993-03-21 12:45:37 +03:00
p1 = s->name + s->nameLen;
p2 = sd->ename;
1993-03-21 12:45:37 +03:00
while (p1 >= s->name && *p1 == *p2) {
p1--;
p2--;
}
return (p1 == s->name - 1 ? p2 : NULL);
}
/*-
*-----------------------------------------------------------------------
* SuffSuffIsSuffixP --
* Predicate form of SuffSuffIsSuffix. Passed as the callback function
* to Lst_Find.
*
* Results:
* 0 if the suffix is the one desired, non-zero if not.
*
* Side Effects:
* None.
*
*-----------------------------------------------------------------------
*/
static int
SuffSuffIsSuffixP(const void *s, const void *sd)
1993-03-21 12:45:37 +03:00
{
return(!SuffSuffIsSuffix(s, sd));
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffSuffHasNameP --
* Callback procedure for finding a suffix based on its name. Used by
* Suff_GetPath.
*
* Input:
* s Suffix to check
* sd Desired name
*
1993-03-21 12:45:37 +03:00
* Results:
* 0 if the suffix is of the given name. non-zero otherwise.
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static int
SuffSuffHasNameP(const void *s, const void *sname)
1993-03-21 12:45:37 +03:00
{
return (strcmp(sname, ((const Suff *)s)->name));
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffSuffIsPrefix --
* See if the suffix described by s is a prefix of the string. Care
* must be taken when using this to search for transformations and
1993-03-21 12:45:37 +03:00
* what-not, since there could well be two suffixes, one of which
* is a prefix of the other...
*
* Input:
* s suffix to compare
* str string to examine
*
1993-03-21 12:45:37 +03:00
* Results:
* 0 if s is a prefix of str. non-zero otherwise
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static int
SuffSuffIsPrefix(const void *s, const void *str)
1993-03-21 12:45:37 +03:00
{
return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL;
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffGNHasNameP --
* See if the graph node has the desired name
*
* Input:
* gn current node we're looking at
* name name we're looking for
*
1993-03-21 12:45:37 +03:00
* Results:
* 0 if it does. non-zero if it doesn't
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
static int
SuffGNHasNameP(const void *gn, const void *name)
1993-03-21 12:45:37 +03:00
{
return (strcmp(name, ((const GNode *)gn)->name));
1993-03-21 12:45:37 +03:00
}
/*********** Maintenance Functions ************/
static void
SuffUnRef(void *lp, void *sp)
{
Lst l = (Lst) lp;
LstNode ln = Lst_Member(l, sp);
if (ln != NULL) {
Lst_Remove(l, ln);
((Suff *)sp)->refCount--;
}
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffFree --
* Free up all memory associated with the given suffix structure.
1993-03-21 12:45:37 +03:00
*
* Results:
* none
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*
* Side Effects:
* the suffix entry is detroyed
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static void
SuffFree(void *sp)
1993-03-21 12:45:37 +03:00
{
Suff *s = (Suff *)sp;
if (s == suffNull)
suffNull = NULL;
if (s == emptySuff)
emptySuff = NULL;
#ifdef notdef
/* We don't delete suffixes in order, so we cannot use this */
if (s->refCount)
Punt("Internal error deleting suffix `%s' with refcount = %d", s->name,
s->refCount);
#endif
Lst_Destroy(s->ref, NULL);
Lst_Destroy(s->children, NULL);
Lst_Destroy(s->parents, NULL);
Lst_Destroy(s->searchPath, Dir_Destroy);
free(s->name);
free(s);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffRemove --
* Remove the suffix into the list
*
* Results:
* None
*
* Side Effects:
* The reference count for the suffix is decremented and the
* suffix is possibly freed
*-----------------------------------------------------------------------
*/
static void
SuffRemove(Lst l, Suff *s)
{
SuffUnRef(l, s);
if (s->refCount == 0) {
SuffUnRef(sufflist, s);
SuffFree(s);
}
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffInsert --
* Insert the suffix into the list keeping the list ordered by suffix
* numbers.
1993-03-21 12:45:37 +03:00
*
* Input:
* l the list where in s should be inserted
* s the suffix to insert
*
1993-03-21 12:45:37 +03:00
* Results:
* None
*
* Side Effects:
* The reference count of the suffix is incremented
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static void
SuffInsert(Lst l, Suff *s)
1993-03-21 12:45:37 +03:00
{
LstNode ln; /* current element in l we're examining */
Suff *s2 = NULL; /* the suffix descriptor in this element */
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
if (Lst_Open(l) == FAILURE) {
return;
}
while ((ln = Lst_Next(l)) != NULL) {
s2 = (Suff *)Lst_Datum(ln);
if (s2->sNum >= s->sNum) {
break;
}
}
1993-03-21 12:45:37 +03:00
Lst_Close(l);
if (DEBUG(SUFF)) {
fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum);
}
if (ln == NULL) {
if (DEBUG(SUFF)) {
fprintf(debug_file, "at end of list\n");
}
(void)Lst_AtEnd(l, s);
s->refCount++;
(void)Lst_AtEnd(s->ref, l);
} else if (s2->sNum != s->sNum) {
if (DEBUG(SUFF)) {
fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum);
}
(void)Lst_InsertBefore(l, ln, s);
s->refCount++;
(void)Lst_AtEnd(s->ref, l);
} else if (DEBUG(SUFF)) {
fprintf(debug_file, "already there\n");
}
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
/*-
*-----------------------------------------------------------------------
* Suff_ClearSuffixes --
* This is gross. Nuke the list of suffixes but keep all transformation
* rules around. The transformation graph is destroyed in this process,
* but we leave the list of rules so when a new graph is formed the rules
* will remain.
* This function is called from the parse module when a
* .SUFFIXES:\n line is encountered.
*
* Results:
* none
*
* Side Effects:
* the sufflist and its graph nodes are destroyed
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*-----------------------------------------------------------------------
*/
void
Suff_ClearSuffixes(void)
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
{
#ifdef CLEANUP
Lst_Concat(suffClean, sufflist, LST_CONCLINK);
#endif
sufflist = Lst_Init(FALSE);
sNum = 0;
suffNull = emptySuff;
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffParseTransform --
* Parse a transformation string to find its two component suffixes.
1993-03-21 12:45:37 +03:00
*
* Input:
* str String being parsed
* srcPtr Place to store source of trans.
* targPtr Place to store target of trans.
*
* Results:
* TRUE if the string is a valid transformation and FALSE otherwise.
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* The passed pointers are overwritten.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static Boolean
SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr)
1993-03-21 12:45:37 +03:00
{
LstNode srcLn; /* element in suffix list of trans source*/
Suff *src; /* Source of transformation */
LstNode targLn; /* element in suffix list of trans target*/
char *str2; /* Extra pointer (maybe target suffix) */
LstNode singleLn; /* element in suffix list of any suffix
* that exactly matches str */
Suff *single = NULL;/* Source of possible transformation to
* null suffix */
srcLn = NULL;
singleLn = NULL;
/*
* Loop looking first for a suffix that matches the start of the
* string and then for one that exactly matches the rest of it. If
* we can find two that meet these criteria, we've successfully
* parsed the string.
*/
for (;;) {
if (srcLn == NULL) {
srcLn = Lst_Find(sufflist, str, SuffSuffIsPrefix);
} else {
srcLn = Lst_FindFrom(sufflist, Lst_Succ(srcLn), str,
SuffSuffIsPrefix);
}
if (srcLn == NULL) {
/*
* Ran out of source suffixes -- no such rule
*/
if (singleLn != NULL) {
/*
* Not so fast Mr. Smith! There was a suffix that encompassed
* the entire string, so we assume it was a transformation
* to the null suffix (thank you POSIX). We still prefer to
* find a double rule over a singleton, hence we leave this
* check until the end.
*
* XXX: Use emptySuff over suffNull?
*/
*srcPtr = single;
*targPtr = suffNull;
return(TRUE);
}
return (FALSE);
}
src = (Suff *)Lst_Datum(srcLn);
str2 = str + src->nameLen;
if (*str2 == '\0') {
single = src;
singleLn = srcLn;
} else {
targLn = Lst_Find(sufflist, str2, SuffSuffHasNameP);
if (targLn != NULL) {
*srcPtr = src;
*targPtr = (Suff *)Lst_Datum(targLn);
return (TRUE);
}
}
}
1993-03-21 12:45:37 +03:00
}
/*-
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
* Suff_IsTransform --
* Return TRUE if the given string is a transformation rule
1993-03-21 12:45:37 +03:00
*
*
* Input:
* str string to check
*
* Results:
* TRUE if the string is a concatenation of two known suffixes.
* FALSE otherwise
*
* Side Effects:
* None
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
Boolean
Suff_IsTransform(char *str)
1993-03-21 12:45:37 +03:00
{
Suff *src, *targ;
1993-03-21 12:45:37 +03:00
return (SuffParseTransform(str, &src, &targ));
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_AddTransform --
* Add the transformation rule described by the line to the
* list of rules and place the transformation itself in the graph
1993-03-21 12:45:37 +03:00
*
* Input:
* line name of transformation to add
*
* Results:
* The node created for the transformation in the transforms list
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* The node is placed on the end of the transforms Lst and links are
* made between the two suffixes mentioned in the target name
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
GNode *
Suff_AddTransform(char *line)
1993-03-21 12:45:37 +03:00
{
GNode *gn; /* GNode of transformation rule */
Suff *s, /* source suffix */
*t; /* target suffix */
LstNode ln; /* Node for existing transformation */
1993-03-21 12:45:37 +03:00
ln = Lst_Find(transforms, line, SuffGNHasNameP);
if (ln == NULL) {
/*
* Make a new graph node for the transformation. It will be filled in
* by the Parse module.
*/
gn = Targ_NewGN(line);
(void)Lst_AtEnd(transforms, gn);
} else {
/*
* New specification for transformation rule. Just nuke the old list
* of commands so they can be filled in again... We don't actually
* free the commands themselves, because a given command can be
* attached to several different transformations.
*/
gn = (GNode *)Lst_Datum(ln);
Lst_Destroy(gn->commands, NULL);
Lst_Destroy(gn->children, NULL);
gn->commands = Lst_Init(FALSE);
gn->children = Lst_Init(FALSE);
}
1993-03-21 12:45:37 +03:00
gn->type = OP_TRANSFORM;
1993-03-21 12:45:37 +03:00
(void)SuffParseTransform(line, &s, &t);
1993-03-21 12:45:37 +03:00
/*
* link the two together in the proper relationship and order
*/
if (DEBUG(SUFF)) {
fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
s->name, t->name);
}
SuffInsert(t->children, s);
SuffInsert(s->parents, t);
1993-03-21 12:45:37 +03:00
return (gn);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_EndTransform --
* Handle the finish of a transformation definition, removing the
* transformation from the graph if it has neither commands nor
* sources. This is a callback procedure for the Parse module via
* Lst_ForEach
*
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
* Input:
* gnp Node for transformation
* dummy Node for transformation
*
* Results:
* === 0
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* If the node has no commands or children, the children and parents
* lists of the affected suffixes are altered.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
int
Suff_EndTransform(void *gnp, void *dummy)
1993-03-21 12:45:37 +03:00
{
GNode *gn = (GNode *)gnp;
if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts))
gn = (GNode *)Lst_Datum(Lst_Last(gn->cohorts));
if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
Lst_IsEmpty(gn->children))
{
Suff *s, *t;
/*
* SuffParseTransform() may fail for special rules which are not
* actual transformation rules. (e.g. .DEFAULT)
*/
if (SuffParseTransform(gn->name, &s, &t)) {
Lst p;
if (DEBUG(SUFF)) {
fprintf(debug_file, "deleting transformation from `%s' to `%s'\n",
s->name, t->name);
}
1993-03-21 12:45:37 +03:00
/*
* Store s->parents because s could be deleted in SuffRemove
*/
p = s->parents;
/*
* Remove the source from the target's children list. We check for a
* nil return to handle a beanhead saying something like
* .c.o .c.o:
*
* We'll be called twice when the next target is seen, but .c and .o
* are only linked once...
*/
SuffRemove(t->children, s);
/*
* Remove the target from the source's parents list
*/
SuffRemove(p, t);
}
} else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
fprintf(debug_file, "transformation %s complete\n", gn->name);
1993-03-21 12:45:37 +03:00
}
return(dummy ? 0 : 0);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffRebuildGraph --
* Called from Suff_AddSuffix via Lst_ForEach to search through the
* list of existing transformation rules and rebuild the transformation
* graph when it has been destroyed by Suff_ClearSuffixes. If the
* given rule is a transformation involving this suffix and another,
* existing suffix, the proper relationship is established between
* the two.
1993-03-21 12:45:37 +03:00
*
* Input:
* transformp Transformation to test
* sp Suffix to rebuild
*
* Results:
* Always 0.
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* The appropriate links will be made between this suffix and
* others if transformation rules exist for it.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static int
SuffRebuildGraph(void *transformp, void *sp)
1993-03-21 12:45:37 +03:00
{
GNode *transform = (GNode *)transformp;
Suff *s = (Suff *)sp;
char *cp;
LstNode ln;
Suff *s2;
SuffixCmpData sd;
/*
* First see if it is a transformation from this suffix.
*/
cp = UNCONST(SuffStrIsPrefix(s->name, transform->name));
if (cp != NULL) {
ln = Lst_Find(sufflist, cp, SuffSuffHasNameP);
if (ln != NULL) {
/*
* Found target. Link in and return, since it can't be anything
* else.
*/
s2 = (Suff *)Lst_Datum(ln);
SuffInsert(s2->children, s);
SuffInsert(s->parents, s2);
return(0);
}
}
1993-03-21 12:45:37 +03:00
/*
* Not from, maybe to?
*/
sd.len = strlen(transform->name);
sd.ename = transform->name + sd.len;
cp = SuffSuffIsSuffix(s, &sd);
if (cp != NULL) {
/*
* Null-terminate the source suffix in order to find it.
*/
cp[1] = '\0';
ln = Lst_Find(sufflist, transform->name, SuffSuffHasNameP);
/*
* Replace the start of the target suffix
*/
cp[1] = s->name[0];
if (ln != NULL) {
/*
* Found it -- establish the proper relationship
*/
s2 = (Suff *)Lst_Datum(ln);
SuffInsert(s->children, s2);
SuffInsert(s2->parents, s);
}
1993-03-21 12:45:37 +03:00
}
return(0);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffScanTargets --
* Called from Suff_AddSuffix via Lst_ForEach to search through the
* list of existing targets and find if any of the existing targets
* can be turned into a transformation rule.
*
* Results:
* 1 if a new main target has been selected, 0 otherwise.
*
* Side Effects:
* If such a target is found and the target is the current main
* target, the main target is set to NULL and the next target
* examined (if that exists) becomes the main target.
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*
*-----------------------------------------------------------------------
*/
static int
SuffScanTargets(void *targetp, void *gsp)
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
{
GNode *target = (GNode *)targetp;
GNodeSuff *gs = (GNodeSuff *)gsp;
Suff *s, *t;
char *ptr;
if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) {
*gs->gn = target;
Targ_SetMain(target);
return 1;
}
if ((unsigned int)target->type == OP_TRANSFORM)
return 0;
if ((ptr = strstr(target->name, gs->s->name)) == NULL ||
ptr == target->name)
return 0;
if (SuffParseTransform(target->name, &s, &t)) {
if (*gs->gn == target) {
gs->r = TRUE;
*gs->gn = NULL;
Targ_SetMain(NULL);
}
Lst_Destroy(target->children, NULL);
target->children = Lst_Init(FALSE);
target->type = OP_TRANSFORM;
/*
* link the two together in the proper relationship and order
*/
if (DEBUG(SUFF)) {
fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
s->name, t->name);
}
SuffInsert(t->children, s);
SuffInsert(s->parents, t);
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
return 0;
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* Suff_AddSuffix --
* Add the suffix in string to the end of the list of known suffixes.
* Should we restructure the suffix graph? Make doesn't...
1993-03-21 12:45:37 +03:00
*
* Input:
* str the name of the suffix to add
*
1993-03-21 12:45:37 +03:00
* Results:
* None
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* 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.
* The mainNode passed can be modified if a target mutated into a
* transform and that target happened to be the main target.
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
void
Suff_AddSuffix(char *str, GNode **gn)
1993-03-21 12:45:37 +03:00
{
Suff *s; /* new suffix descriptor */
LstNode ln;
GNodeSuff gs;
ln = Lst_Find(sufflist, str, SuffSuffHasNameP);
if (ln == NULL) {
s = bmake_malloc(sizeof(Suff));
s->name = bmake_strdup(str);
s->nameLen = strlen(s->name);
s->searchPath = Lst_Init(FALSE);
s->children = Lst_Init(FALSE);
s->parents = Lst_Init(FALSE);
s->ref = Lst_Init(FALSE);
s->sNum = sNum++;
s->flags = 0;
s->refCount = 1;
(void)Lst_AtEnd(sufflist, s);
/*
* We also look at our existing targets list to see if adding
* this suffix will make one of our current targets mutate into
* a suffix rule. This is ugly, but other makes treat all targets
* that start with a . as suffix rules.
*/
gs.gn = gn;
gs.s = s;
gs.r = FALSE;
Lst_ForEach(Targ_List(), SuffScanTargets, &gs);
/*
* Look for any existing transformations from or to this suffix.
* XXX: Only do this after a Suff_ClearSuffixes?
*/
Lst_ForEach(transforms, SuffRebuildGraph, s);
}
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_GetPath --
* Return the search path for the given suffix, if it's defined.
*
* Results:
* The searchPath for the desired suffix or NULL if the suffix isn't
1993-03-21 12:45:37 +03:00
* defined.
*
* Side Effects:
* None
*-----------------------------------------------------------------------
*/
Lst
Suff_GetPath(char *sname)
1993-03-21 12:45:37 +03:00
{
LstNode ln;
Suff *s;
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
if (ln == NULL) {
return NULL;
} else {
s = (Suff *)Lst_Datum(ln);
return (s->searchPath);
}
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_DoPaths --
* Extend the search paths for all suffixes to include the default
* search path.
*
* Results:
* None.
*
* Side Effects:
* The searchPath field of all the suffixes is extended by the
* directories in dirSearchPath. If paths were specified for the
* ".h" suffix, the directories are stuffed into a global variable
2001-08-20 16:00:46 +04:00
* called ".INCLUDES" with each directory preceded by a -I. The same
1993-03-21 12:45:37 +03:00
* is done for the ".a" suffix, except the variable is called
* ".LIBS" and the flag is -L.
*-----------------------------------------------------------------------
*/
void
Suff_DoPaths(void)
1993-03-21 12:45:37 +03:00
{
Suff *s;
LstNode ln;
char *ptr;
1993-03-21 12:45:37 +03:00
Lst inIncludes; /* Cumulative .INCLUDES path */
Lst inLibs; /* Cumulative .LIBS path */
if (Lst_Open(sufflist) == FAILURE) {
1993-03-21 12:45:37 +03:00
return;
}
inIncludes = Lst_Init(FALSE);
inLibs = Lst_Init(FALSE);
while ((ln = Lst_Next(sufflist)) != NULL) {
s = (Suff *)Lst_Datum(ln);
1993-03-21 12:45:37 +03:00
if (!Lst_IsEmpty (s->searchPath)) {
#ifdef INCLUDES
if (s->flags & SUFF_INCLUDE) {
Dir_Concat(inIncludes, s->searchPath);
}
#endif /* INCLUDES */
#ifdef LIBRARIES
if (s->flags & SUFF_LIBRARY) {
Dir_Concat(inLibs, s->searchPath);
}
#endif /* LIBRARIES */
Dir_Concat(s->searchPath, dirSearchPath);
} else {
Lst_Destroy(s->searchPath, Dir_Destroy);
1993-03-21 12:45:37 +03:00
s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
}
}
Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL, 0);
free(ptr);
Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL, 0);
free(ptr);
1993-03-21 12:45:37 +03:00
Lst_Destroy(inIncludes, Dir_Destroy);
Lst_Destroy(inLibs, Dir_Destroy);
Lst_Close(sufflist);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_AddInclude --
* Add the given suffix as a type of file which gets included.
* Called from the parse module when a .INCLUDES line is parsed.
* The suffix must have already been defined.
*
* Input:
* sname Name of the suffix to mark
*
1993-03-21 12:45:37 +03:00
* Results:
* None.
*
* Side Effects:
* The SUFF_INCLUDE bit is set in the suffix's flags field
*
*-----------------------------------------------------------------------
*/
void
Suff_AddInclude(char *sname)
1993-03-21 12:45:37 +03:00
{
LstNode ln;
Suff *s;
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
if (ln != NULL) {
s = (Suff *)Lst_Datum(ln);
1993-03-21 12:45:37 +03:00
s->flags |= SUFF_INCLUDE;
}
}
/*-
*-----------------------------------------------------------------------
* Suff_AddLib --
* Add the given suffix as a type of file which is a library.
* Called from the parse module when parsing a .LIBS line. The
* suffix must have been defined via .SUFFIXES before this is
* called.
*
* Input:
* sname Name of the suffix to mark
*
1993-03-21 12:45:37 +03:00
* Results:
* None.
*
* Side Effects:
* The SUFF_LIBRARY bit is set in the suffix's flags field
*
*-----------------------------------------------------------------------
*/
void
Suff_AddLib(char *sname)
1993-03-21 12:45:37 +03:00
{
LstNode ln;
Suff *s;
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
if (ln != NULL) {
s = (Suff *)Lst_Datum(ln);
1993-03-21 12:45:37 +03:00
s->flags |= SUFF_LIBRARY;
}
}
/********** Implicit Source Search Functions *********/
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffAddSrc --
* Add a suffix as a Src structure to the given list with its parent
* being the given Src structure. If the suffix is the null suffix,
* the prefix is used unaltered as the file name in the Src structure.
1993-03-21 12:45:37 +03:00
*
* Input:
* sp suffix for which to create a Src structure
* lsp list and parent for the new Src
*
1993-03-21 12:45:37 +03:00
* Results:
* always returns 0
*
* Side Effects:
* A Src structure is created and tacked onto the end of the list
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static int
SuffAddSrc(void *sp, void *lsp)
1993-03-21 12:45:37 +03:00
{
Suff *s = (Suff *)sp;
LstSrc *ls = (LstSrc *)lsp;
Src *s2; /* new Src structure */
Src *targ; /* Target structure */
1993-03-21 12:45:37 +03:00
targ = ls->s;
if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
/*
* 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
* that...
*/
s2 = bmake_malloc(sizeof(Src));
s2->file = bmake_strdup(targ->pref);
s2->pref = targ->pref;
s2->parent = targ;
s2->node = NULL;
s2->suff = s;
s->refCount++;
s2->children = 0;
targ->children += 1;
(void)Lst_AtEnd(ls->l, s2);
#ifdef DEBUG_SRC
s2->cp = Lst_Init(FALSE);
Lst_AtEnd(targ->cp, s2);
fprintf(debug_file, "1 add %x %x to %x:", targ, s2, ls->l);
Lst_ForEach(ls->l, PrintAddr, NULL);
fprintf(debug_file, "\n");
#endif
1993-03-21 12:45:37 +03:00
}
s2 = bmake_malloc(sizeof(Src));
s2->file = str_concat(targ->pref, s->name, 0);
s2->pref = targ->pref;
s2->parent = targ;
s2->node = NULL;
s2->suff = s;
s->refCount++;
s2->children = 0;
targ->children += 1;
(void)Lst_AtEnd(ls->l, s2);
#ifdef DEBUG_SRC
s2->cp = Lst_Init(FALSE);
Lst_AtEnd(targ->cp, s2);
fprintf(debug_file, "2 add %x %x to %x:", targ, s2, ls->l);
Lst_ForEach(ls->l, PrintAddr, NULL);
fprintf(debug_file, "\n");
#endif
1993-03-21 12:45:37 +03:00
return(0);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffAddLevel --
* Add all the children of targ as Src structures to the given list
1993-03-21 12:45:37 +03:00
*
* Input:
* l list to which to add the new level
* targ Src structure to use as the parent
*
* Results:
* None
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* Lots of structures are created and added to the list
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static void
SuffAddLevel(Lst l, Src *targ)
1993-03-21 12:45:37 +03:00
{
LstSrc ls;
ls.s = targ;
ls.l = l;
Lst_ForEach(targ->suff->children, SuffAddSrc, &ls);
1993-03-21 12:45:37 +03:00
}
/*-
*----------------------------------------------------------------------
* SuffRemoveSrc --
* Free all src structures in list that don't have a reference count
1993-03-21 12:45:37 +03:00
*
* Results:
* Ture if an src was removed
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*
* Side Effects:
* The memory is free'd.
*----------------------------------------------------------------------
1993-03-21 12:45:37 +03:00
*/
static int
SuffRemoveSrc(Lst l)
{
LstNode ln;
Src *s;
int t = 0;
if (Lst_Open(l) == FAILURE) {
return 0;
}
#ifdef DEBUG_SRC
fprintf(debug_file, "cleaning %lx: ", (unsigned long) l);
Lst_ForEach(l, PrintAddr, NULL);
fprintf(debug_file, "\n");
#endif
while ((ln = Lst_Next(l)) != NULL) {
s = (Src *)Lst_Datum(ln);
if (s->children == 0) {
free(s->file);
if (!s->parent)
free(s->pref);
else {
#ifdef DEBUG_SRC
LstNode ln = Lst_Member(s->parent->cp, s);
if (ln != NULL)
Lst_Remove(s->parent->cp, ln);
#endif
--s->parent->children;
}
#ifdef DEBUG_SRC
fprintf(debug_file, "free: [l=%x] p=%x %d\n", l, s, s->children);
Lst_Destroy(s->cp, NULL);
#endif
Lst_Remove(l, ln);
free(s);
t |= 1;
Lst_Close(l);
return TRUE;
}
#ifdef DEBUG_SRC
else {
fprintf(debug_file, "keep: [l=%x] p=%x %d: ", l, s, s->children);
Lst_ForEach(s->cp, PrintAddr, NULL);
fprintf(debug_file, "\n");
}
#endif
}
Lst_Close(l);
return t;
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffFindThem --
* Find the first existing file/target in the list srcs
1993-03-21 12:45:37 +03:00
*
* Input:
* srcs list of Src structures to search through
*
1993-03-21 12:45:37 +03:00
* Results:
* The lowest structure in the chain of transformations
1993-03-21 12:45:37 +03:00
*
* Side Effects:
* None
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static Src *
SuffFindThem(Lst srcs, Lst slst)
1993-03-21 12:45:37 +03:00
{
Src *s; /* current Src */
Src *rs; /* returned Src */
char *ptr;
1993-03-21 12:45:37 +03:00
rs = NULL;
1993-03-21 12:45:37 +03:00
while (!Lst_IsEmpty (srcs)) {
s = (Src *)Lst_DeQueue(srcs);
if (DEBUG(SUFF)) {
fprintf(debug_file, "\ttrying %s...", s->file);
1993-03-21 12:45:37 +03:00
}
1993-03-21 12:45:37 +03:00
/*
* A file is considered to exist if either a node exists in the
* graph for it or the file actually exists.
1993-03-21 12:45:37 +03:00
*/
if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
#ifdef DEBUG_SRC
fprintf(debug_file, "remove %x from %x\n", s, srcs);
#endif
rs = s;
break;
}
if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) {
rs = s;
#ifdef DEBUG_SRC
fprintf(debug_file, "remove %x from %x\n", s, srcs);
#endif
free(ptr);
break;
}
if (DEBUG(SUFF)) {
fprintf(debug_file, "not there\n");
}
SuffAddLevel(srcs, s);
Lst_AtEnd(slst, s);
}
if (DEBUG(SUFF) && rs) {
fprintf(debug_file, "got it\n");
}
return (rs);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffFindCmds --
* See if any of the children of the target in the Src structure is
* one from which the target can be transformed. If there is one,
* a Src structure is put together for it and returned.
1993-03-21 12:45:37 +03:00
*
* Input:
* targ Src structure to play with
*
* Results:
* The Src structure of the "winning" child, or NULL if no such beast.
*
* Side Effects:
* A Src structure may be allocated.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static Src *
SuffFindCmds(Src *targ, Lst slst)
1993-03-21 12:45:37 +03:00
{
LstNode ln; /* General-purpose list node */
GNode *t, /* Target GNode */
*s; /* Source GNode */
int prefLen;/* The length of the defined prefix */
Suff *suff; /* Suffix on matching beastie */
Src *ret; /* Return value */
char *cp;
t = targ->node;
(void)Lst_Open(t->children);
prefLen = strlen(targ->pref);
for (;;) {
ln = Lst_Next(t->children);
if (ln == NULL) {
Lst_Close(t->children);
return NULL;
}
s = (GNode *)Lst_Datum(ln);
if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->commands)) {
/*
* We haven't looked to see if .OPTIONAL files exist yet, so
* don't use one as the implicit source.
* This allows us to use .OPTIONAL in .depend files so make won't
* complain "don't know how to make xxx.h' when a dependent file
* has been moved/deleted.
*/
continue;
}
cp = strrchr(s->name, '/');
if (cp == NULL) {
cp = s->name;
} else {
cp++;
}
if (strncmp(cp, targ->pref, prefLen) != 0)
continue;
/*
* The node matches the prefix ok, see if it has a known
* suffix.
*/
ln = Lst_Find(sufflist, &cp[prefLen], SuffSuffHasNameP);
if (ln == NULL)
continue;
/*
* It even has a known suffix, see if there's a transformation
* defined between the node's suffix and the target's suffix.
*
* XXX: Handle multi-stage transformations here, too.
*/
suff = (Suff *)Lst_Datum(ln);
if (Lst_Member(suff->parents, targ->suff) != NULL)
break;
}
/*
* Hot Damn! Create a new Src structure to describe
* this transformation (making sure to duplicate the
* source node's name so Suff_FindDeps can free it
* again (ick)), and return the new structure.
*/
ret = bmake_malloc(sizeof(Src));
ret->file = bmake_strdup(s->name);
ret->pref = targ->pref;
ret->suff = suff;
suff->refCount++;
ret->parent = targ;
ret->node = s;
ret->children = 0;
targ->children += 1;
#ifdef DEBUG_SRC
ret->cp = Lst_Init(FALSE);
fprintf(debug_file, "3 add %x %x\n", targ, ret);
Lst_AtEnd(targ->cp, ret);
#endif
Lst_AtEnd(slst, ret);
if (DEBUG(SUFF)) {
fprintf(debug_file, "\tusing existing source %s\n", s->name);
1993-03-21 12:45:37 +03:00
}
return (ret);
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffExpandChildren --
* Expand the names of any children of a given node that contain
* variable invocations or file wildcards into actual targets.
1993-03-21 12:45:37 +03:00
*
* Input:
* cln Child to examine
* pgn Parent node being processed
*
1993-03-21 12:45:37 +03:00
* Results:
* === 0 (continue)
*
* 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.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static void
SuffExpandChildren(LstNode cln, GNode *pgn)
1993-03-21 12:45:37 +03:00
{
GNode *cgn = (GNode *)Lst_Datum(cln);
GNode *gn; /* New source 8) */
char *cp; /* Expanded value */
1993-03-21 12:45:37 +03:00
if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ))
/* It is all too hard to process the result of .ORDER */
return;
if (cgn->type & OP_WAIT)
/* Ignore these (& OP_PHONY ?) */
return;
1993-03-21 12:45:37 +03:00
/*
* 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) {
SuffExpandWildcards(cln, pgn);
return;
}
1993-03-21 12:45:37 +03:00
if (DEBUG(SUFF)) {
fprintf(debug_file, "Expanding \"%s\"...", cgn->name);
}
cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
if (cp != NULL) {
Lst members = Lst_Init(FALSE);
1993-03-21 12:45:37 +03:00
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);
} else {
/*
* Break the result into a vector of strings whose nodes
* we can find, then add those nodes to the members list.
* Unfortunately, we can't use brk_string b/c it
* doesn't understand about variable specifications with
* spaces in them...
*/
char *start;
char *initcp = cp; /* For freeing... */
1993-03-21 12:45:37 +03:00
for (start = cp; *start == ' ' || *start == '\t'; start++)
continue;
for (cp = start; *cp != '\0'; cp++) {
if (*cp == ' ' || *cp == '\t') {
1993-03-21 12:45:37 +03:00
/*
* White-space -- terminate element, find the node,
* add it, skip any further spaces.
1993-03-21 12:45:37 +03:00
*/
*cp++ = '\0';
1993-03-21 12:45:37 +03:00
gn = Targ_FindNode(start, TARG_CREATE);
(void)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;
int len;
void *freeIt;
junk = Var_Parse(cp, pgn, TRUE, &len, &freeIt);
if (junk != var_Error) {
cp += len - 1;
}
if (freeIt)
free(freeIt);
} else if (*cp == '\\' && *cp != '\0') {
/*
* Escaped something -- skip over it
*/
cp++;
1993-03-21 12:45:37 +03:00
}
}
if (cp != start) {
/*
* Stuff left over -- add it to the list too
*/
gn = Targ_FindNode(start, TARG_CREATE);
(void)Lst_AtEnd(members, gn);
1993-03-21 12:45:37 +03:00
}
/*
* Point cp back at the beginning again so the variable value
* can be freed.
*/
cp = initcp;
1993-03-21 12:45:37 +03:00
}
/*
* Add all elements of the members list to the parent node.
1993-03-21 12:45:37 +03:00
*/
while(!Lst_IsEmpty(members)) {
gn = (GNode *)Lst_DeQueue(members);
1993-03-21 12:45:37 +03:00
if (DEBUG(SUFF)) {
fprintf(debug_file, "%s...", gn->name);
}
/* Add gn to the parents child list before the original child */
(void)Lst_InsertBefore(pgn->children, cln, gn);
(void)Lst_AtEnd(gn->parents, pgn);
pgn->unmade++;
/* Expand wildcards on new node */
2006-10-26 00:05:59 +04:00
SuffExpandWildcards(Lst_Prev(cln), pgn);
1993-03-21 12:45:37 +03:00
}
Lst_Destroy(members, NULL);
1993-03-21 12:45:37 +03:00
/*
* Free the result
*/
free(cp);
}
if (DEBUG(SUFF)) {
fprintf(debug_file, "\n");
}
/*
* Now the source is expanded, remove it from the list of children to
* keep it from being processed.
*/
pgn->unmade--;
Lst_Remove(pgn->children, cln);
Lst_Remove(cgn->parents, Lst_Member(cgn->parents, pgn));
}
static void
SuffExpandWildcards(LstNode cln, GNode *pgn)
{
GNode *cgn = (GNode *)Lst_Datum(cln);
GNode *gn; /* New source 8) */
char *cp; /* Expanded value */
Lst explist; /* List of expansions */
if (!Dir_HasWildcards(cgn->name))
return;
/*
* Expand the word along the chosen path
*/
explist = Lst_Init(FALSE);
Dir_Expand(cgn->name, Suff_FindPath(cgn), explist);
while (!Lst_IsEmpty(explist)) {
1993-03-21 12:45:37 +03:00
/*
* Fetch next expansion off the list and find its GNode
1993-03-21 12:45:37 +03:00
*/
cp = (char *)Lst_DeQueue(explist);
if (DEBUG(SUFF)) {
fprintf(debug_file, "%s...", cp);
}
gn = Targ_FindNode(cp, TARG_CREATE);
/* Add gn to the parents child list before the original child */
(void)Lst_InsertBefore(pgn->children, cln, gn);
(void)Lst_AtEnd(gn->parents, pgn);
pgn->unmade++;
1993-03-21 12:45:37 +03:00
}
/*
* Nuke what's left of the list
*/
Lst_Destroy(explist, NULL);
if (DEBUG(SUFF)) {
fprintf(debug_file, "\n");
}
/*
* Now the source is expanded, remove it from the list of children to
* keep it from being processed.
*/
pgn->unmade--;
Lst_Remove(pgn->children, cln);
Lst_Remove(cgn->parents, Lst_Member(cgn->parents, pgn));
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* Suff_FindPath --
* Find a path along which to expand the node.
*
* If the word has a known suffix, use that path.
* If it has no known suffix, use the default system search path.
*
* Input:
* gn Node being examined
*
* Results:
* The appropriate path to search for the GNode.
*
* Side Effects:
* XXX: We could set the suffix here so that we don't have to scan
* again.
*
*-----------------------------------------------------------------------
*/
Lst
Suff_FindPath(GNode* gn)
{
Suff *suff = gn->suffix;
if (suff == NULL) {
SuffixCmpData sd; /* Search string data */
LstNode ln;
sd.len = strlen(gn->name);
sd.ename = gn->name + sd.len;
ln = Lst_Find(sufflist, &sd, SuffSuffIsSuffixP);
if (DEBUG(SUFF)) {
fprintf(debug_file, "Wildcard expanding \"%s\"...", gn->name);
}
if (ln != NULL)
suff = (Suff *)Lst_Datum(ln);
/* XXX: Here we can save the suffix so we don't have to do this again */
}
if (suff != NULL) {
if (DEBUG(SUFF)) {
fprintf(debug_file, "suffix is \"%s\"...", suff->name);
}
return suff->searchPath;
} else {
/*
* Use default search path
*/
return dirSearchPath;
}
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffApplyTransform --
* Apply a transformation rule, given the source and target nodes
* and suffixes.
1993-03-21 12:45:37 +03:00
*
* Input:
* tGn Target node
* sGn Source node
* t Target suffix
* s Source suffix
*
1993-03-21 12:45:37 +03:00
* Results:
* TRUE if successful, FALSE if not.
*
* Side Effects:
* The source and target are linked and the commands from the
* transformation are added to the target node's commands list.
* All attributes but OP_DEPMASK and OP_TRANSFORM are applied
* to the target. The target also inherits all the sources for
* the transformation rule.
*
*-----------------------------------------------------------------------
*/
static Boolean
SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s)
1993-03-21 12:45:37 +03:00
{
LstNode ln, nln; /* General node */
1993-03-21 12:45:37 +03:00
char *tname; /* Name of transformation rule */
GNode *gn; /* Node for same */
/*
* Form the proper links between the target and source.
*/
(void)Lst_AtEnd(tGn->children, sGn);
(void)Lst_AtEnd(sGn->parents, tGn);
tGn->unmade += 1;
1993-03-21 12:45:37 +03:00
/*
* Locate the transformation rule itself
*/
tname = str_concat(s->name, t->name, 0);
ln = Lst_Find(transforms, tname, SuffGNHasNameP);
1993-03-21 12:45:37 +03:00
free(tname);
if (ln == NULL) {
/*
* Not really such a transformation rule (can happen when we're
* called to link an OP_MEMBER and OP_ARCHV node), so return
* FALSE.
*/
return(FALSE);
}
1993-03-21 12:45:37 +03:00
gn = (GNode *)Lst_Datum(ln);
if (DEBUG(SUFF)) {
fprintf(debug_file, "\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
}
1993-03-21 12:45:37 +03:00
/*
* Record last child for expansion purposes
*/
1993-03-21 12:45:37 +03:00
ln = Lst_Last(tGn->children);
1993-03-21 12:45:37 +03:00
/*
* Pass the buck to Make_HandleUse to apply the rule
*/
(void)Make_HandleUse(gn, tGn);
/*
* Deal with wildcards and variables in any acquired sources
*/
for (ln = Lst_Succ(ln); ln != NULL; ln = nln) {
nln = Lst_Succ(ln);
SuffExpandChildren(ln, tGn);
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
/*
* Keep track of another parent to which this beast is transformed so
* the .IMPSRC variable can be set correctly for the parent.
*/
(void)Lst_AtEnd(sGn->iParents, tGn);
return(TRUE);
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* SuffFindArchiveDeps --
* Locate dependencies for an OP_ARCHV node.
*
* Input:
* gn Node for which to locate dependencies
*
1993-03-21 12:45:37 +03:00
* Results:
* None
*
* Side Effects:
* Same as Suff_FindDeps
1993-03-21 12:45:37 +03:00
*
*-----------------------------------------------------------------------
*/
static void
SuffFindArchiveDeps(GNode *gn, Lst slst)
1993-03-21 12:45:37 +03:00
{
char *eoarch; /* End of archive portion */
char *eoname; /* End of member portion */
GNode *mem; /* Node for member */
static const char *copy[] = {
/* Variables to be copied from the member node */
TARGET, /* Must be first */
PREFIX, /* Must be second */
};
int i; /* Index into copy and vals */
Suff *ms; /* Suffix descriptor for member */
char *name; /* Start of member's name */
1993-03-21 12:45:37 +03:00
/*
* The node is an archive(member) pair. so we must find a
* suffix for both of them.
1993-03-21 12:45:37 +03:00
*/
eoarch = strchr(gn->name, '(');
eoname = strchr(eoarch, ')');
1993-03-21 12:45:37 +03:00
*eoname = '\0'; /* Nuke parentheses during suffix search */
*eoarch = '\0'; /* So a suffix can be found */
name = eoarch + 1;
1993-03-21 12:45:37 +03:00
/*
* To simplify things, call Suff_FindDeps recursively on the member now,
* 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
* use for the archive without having to do a quadratic search over the
* suffix list, backtracking for each one...
1993-03-21 12:45:37 +03:00
*/
mem = Targ_FindNode(name, TARG_CREATE);
SuffFindDeps(mem, slst);
1993-03-21 12:45:37 +03:00
/*
* Create the link between the two nodes right off
1993-03-21 12:45:37 +03:00
*/
(void)Lst_AtEnd(gn->children, mem);
(void)Lst_AtEnd(mem->parents, gn);
gn->unmade += 1;
1993-03-21 12:45:37 +03:00
/*
* Copy in the variables from the member node to this one.
*/
for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
char *p1;
Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn, 0);
if (p1)
free(p1);
1993-03-21 12:45:37 +03:00
}
1993-03-21 12:45:37 +03:00
ms = mem->suffix;
if (ms == NULL) {
/*
* Didn't know what it was -- use .NULL suffix if not in make mode
*/
if (DEBUG(SUFF)) {
fprintf(debug_file, "using null suffix\n");
1993-03-21 12:45:37 +03:00
}
ms = suffNull;
1993-03-21 12:45:37 +03:00
}
/*
* Set the other two local variables required for this target.
1993-03-21 12:45:37 +03:00
*/
Var_Set(MEMBER, name, gn, 0);
Var_Set(ARCHIVE, gn->name, gn, 0);
if (ms != NULL) {
/*
* Member has a known suffix, so look for a transformation rule from
* it to a possible suffix of the archive. Rather than searching
* through the entire list, we just look at suffixes to which the
* member's suffix may be transformed...
*/
LstNode ln;
SuffixCmpData sd; /* Search string data */
1993-03-21 12:45:37 +03:00
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
/*
* Use first matching suffix...
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
*/
sd.len = eoarch - gn->name;
sd.ename = eoarch;
ln = Lst_Find(ms->parents, &sd, SuffSuffIsSuffixP);
if (ln != NULL) {
/*
* Got one -- apply it
*/
if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&
DEBUG(SUFF))
{
fprintf(debug_file, "\tNo transformation from %s -> %s\n",
ms->name, ((Suff *)Lst_Datum(ln))->name);
}
}
}
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
/*
* 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
* archive.
*/
if (OP_NOP(gn->type)) {
gn->type |= OP_DEPENDS;
}
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
/*
* Flag the member as such so we remember to look in the archive for
* its modification time.
*/
mem->type |= OP_MEMBER;
1993-03-21 12:45:37 +03:00
}
/*-
*-----------------------------------------------------------------------
* SuffFindNormalDeps --
* Locate implicit dependencies for regular targets.
1993-03-21 12:45:37 +03:00
*
* Input:
* gn Node for which to find sources
*
1993-03-21 12:45:37 +03:00
* Results:
* None.
*
* Side Effects:
* Same as Suff_FindDeps...
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
static void
SuffFindNormalDeps(GNode *gn, Lst slst)
1993-03-21 12:45:37 +03:00
{
char *eoname; /* End of name */
char *sopref; /* Start of prefix */
LstNode ln, nln; /* Next suffix node to check */
Lst srcs; /* List of sources at which to look */
Lst targs; /* List of targets to which things can be
* transformed. They all have the same file,
* but different suff and pref fields */
Src *bottom; /* Start of found transformation path */
Src *src; /* General Src pointer */
char *pref; /* Prefix to use */
Src *targ; /* General Src target pointer */
SuffixCmpData sd; /* Search string data */
1993-03-21 12:45:37 +03:00
sd.len = strlen(gn->name);
sd.ename = eoname = gn->name + sd.len;
sopref = gn->name;
/*
* Begin at the beginning...
*/
ln = Lst_First(sufflist);
srcs = Lst_Init(FALSE);
targs = Lst_Init(FALSE);
1993-03-21 12:45:37 +03:00
/*
* 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
* 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 know what the proper suffix for the
* target is (in case there are two suffixes one of which is a suffix of
* the other) and we can't know that until we've found its implied
* source, which we may not want to use if there's an existing source
* that implies a different transformation.
*
* In an attempt to get around this, which may not work all the time,
* but should work most of the time, we look for implied sources first,
* checking transformations to all possible suffixes of the target,
* use what we find to set the target's local variables, expand the
* children, then look for any overriding transformations they imply.
* Should we find one, we discard the one we found before.
1993-03-21 12:45:37 +03:00
*/
bottom = NULL;
targ = NULL;
if (!(gn->type & OP_PHONY)) {
while (ln != NULL) {
/*
* Look for next possible suffix...
*/
ln = Lst_FindFrom(sufflist, ln, &sd, SuffSuffIsSuffixP);
if (ln != NULL) {
int prefLen; /* Length of the prefix */
/*
* Allocate a Src structure to which things can be transformed
*/
targ = bmake_malloc(sizeof(Src));
targ->file = bmake_strdup(gn->name);
targ->suff = (Suff *)Lst_Datum(ln);
targ->suff->refCount++;
targ->node = gn;
targ->parent = NULL;
targ->children = 0;
#ifdef DEBUG_SRC
targ->cp = Lst_Init(FALSE);
#endif
/*
* Allocate room for the prefix, whose end is found by
* subtracting the length of the suffix from
* the end of the name.
*/
prefLen = (eoname - targ->suff->nameLen) - sopref;
targ->pref = bmake_malloc(prefLen + 1);
memcpy(targ->pref, sopref, prefLen);
targ->pref[prefLen] = '\0';
/*
* Add nodes from which the target can be made
*/
SuffAddLevel(srcs, targ);
/*
* Record the target so we can nuke it
*/
(void)Lst_AtEnd(targs, targ);
/*
* Search from this suffix's successor...
*/
ln = Lst_Succ(ln);
}
}
/*
* Handle target of unknown suffix...
*/
if (Lst_IsEmpty(targs) && suffNull != NULL) {
if (DEBUG(SUFF)) {
fprintf(debug_file, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
}
targ = bmake_malloc(sizeof(Src));
targ->file = bmake_strdup(gn->name);
targ->suff = suffNull;
targ->suff->refCount++;
targ->node = gn;
targ->parent = NULL;
targ->children = 0;
targ->pref = bmake_strdup(sopref);
#ifdef DEBUG_SRC
targ->cp = Lst_Init(FALSE);
#endif
/*
* Only use the default suffix rules if we don't have commands
* defined for this gnode; traditional make programs used to
* not define suffix rules if the gnode had children but we
* don't do this anymore.
*/
if (Lst_IsEmpty(gn->commands))
SuffAddLevel(srcs, targ);
else {
if (DEBUG(SUFF))
fprintf(debug_file, "not ");
}
if (DEBUG(SUFF))
fprintf(debug_file, "adding suffix rules\n");
(void)Lst_AtEnd(targs, targ);
}
/*
* Using the list of possible sources built up from the target
* suffix(es), try and find an existing file/target that matches.
*/
bottom = SuffFindThem(srcs, slst);
if (bottom == NULL) {
/*
* No known transformations -- use the first suffix found
* for setting the local variables.
*/
if (!Lst_IsEmpty(targs)) {
targ = (Src *)Lst_Datum(Lst_First(targs));
} else {
targ = NULL;
}
} else {
/*
* Work up the transformation path to find the suffix of the
* target to which the transformation was made.
*/
for (targ = bottom; targ->parent != NULL; targ = targ->parent)
continue;
}
1993-03-21 12:45:37 +03:00
}
Var_Set(TARGET, gn->path ? gn->path : gn->name, gn, 0);
pref = (targ != NULL) ? targ->pref : gn->name;
Var_Set(PREFIX, pref, gn, 0);
1993-03-21 12:45:37 +03:00
/*
* Now we've got the important local variables set, expand any sources
* that still contain variables or wildcards in their names.
1993-03-21 12:45:37 +03:00
*/
for (ln = Lst_First(gn->children); ln != NULL; ln = nln) {
nln = Lst_Succ(ln);
SuffExpandChildren(ln, gn);
}
if (targ == NULL) {
if (DEBUG(SUFF)) {
fprintf(debug_file, "\tNo valid suffix on %s\n", gn->name);
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
1993-03-21 12:45:37 +03:00
sfnd_abort:
/*
* Deal with finding the thing on the default search path. We
* always do that, not only if the node is only a source (not
* on the lhs of a dependency operator or [XXX] it has neither
* children or commands) as the old pmake did.
*/
if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) {
free(gn->path);
gn->path = Dir_FindFile(gn->name,
(targ == NULL ? dirSearchPath :
targ->suff->searchPath));
if (gn->path != NULL) {
char *ptr;
Var_Set(TARGET, gn->path, gn, 0);
if (targ != NULL) {
/*
* Suffix known for the thing -- trim the suffix off
* the path to form the proper .PREFIX variable.
*/
int savep = strlen(gn->path) - targ->suff->nameLen;
char savec;
if (gn->suffix)
gn->suffix->refCount--;
gn->suffix = targ->suff;
gn->suffix->refCount++;
savec = gn->path[savep];
gn->path[savep] = '\0';
1993-03-21 12:45:37 +03:00
if ((ptr = strrchr(gn->path, '/')) != NULL)
ptr++;
else
ptr = gn->path;
Var_Set(PREFIX, ptr, gn, 0);
gn->path[savep] = savec;
} else {
/*
* The .PREFIX gets the full path if the target has
* no known suffix.
*/
if (gn->suffix)
gn->suffix->refCount--;
gn->suffix = NULL;
if ((ptr = strrchr(gn->path, '/')) != NULL)
ptr++;
else
ptr = gn->path;
Var_Set(PREFIX, ptr, gn, 0);
}
1993-03-21 12:45:37 +03:00
}
}
goto sfnd_return;
1993-03-21 12:45:37 +03:00
}
/*
* If the suffix indicates that the target is a library, mark that in
* the node's type field.
*/
if (targ->suff->flags & SUFF_LIBRARY) {
gn->type |= OP_LIB;
}
/*
* Check for overriding transformation rule implied by sources
*/
if (!Lst_IsEmpty(gn->children)) {
src = SuffFindCmds(targ, slst);
if (src != NULL) {
/*
* Free up all the Src structures in the transformation path
* up to, but not including, the parent node.
*/
while (bottom && bottom->parent != NULL) {
if (Lst_Member(slst, bottom) == NULL) {
Lst_AtEnd(slst, bottom);
}
bottom = bottom->parent;
}
bottom = src;
}
}
if (bottom == NULL) {
/*
* No idea from where it can come -- return now.
*/
goto sfnd_abort;
}
/*
* 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
* source and target nodes (which may or may not have been created)
* and set the necessary local variables in each target. The
* commands for each target are set from the commands of the
* transformation rule used to get from the src suffix to the targ
* suffix. Note that this causes the commands list of the original
* node, gn, to be replaced by the commands of the final
* transformation rule. Also, the unmade field of gn is incremented.
* Etc.
*/
if (bottom->node == NULL) {
bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
}
for (src = bottom; src->parent != NULL; src = src->parent) {
targ = src->parent;
if (src->node->suffix)
src->node->suffix->refCount--;
src->node->suffix = src->suff;
src->node->suffix->refCount++;
if (targ->node == NULL) {
targ->node = Targ_FindNode(targ->file, TARG_CREATE);
}
SuffApplyTransform(targ->node, src->node,
targ->suff, src->suff);
if (targ->node != gn) {
/*
* Finish off the dependency-search process for any nodes
* between bottom and gn (no point in questing around the
* filesystem for their implicit source when it's already
* known). Note that the node can't have any sources that
* need expanding, since SuffFindThem will stop on an existing
* node, so all we need to do is set the standard and System V
* variables.
*/
targ->node->type |= OP_DEPS_FOUND;
Var_Set(PREFIX, targ->pref, targ->node, 0);
Var_Set(TARGET, targ->node->name, targ->node, 0);
1993-03-21 12:45:37 +03:00
}
}
if (gn->suffix)
gn->suffix->refCount--;
gn->suffix = src->suff;
gn->suffix->refCount++;
/*
* Nuke the transformation path and the Src structures left over in the
* two lists.
*/
sfnd_return:
if (bottom)
if (Lst_Member(slst, bottom) == NULL)
Lst_AtEnd(slst, bottom);
1993-03-21 12:45:37 +03:00
while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
continue;
Lst_Concat(slst, srcs, LST_CONCLINK);
Lst_Concat(slst, targs, LST_CONCLINK);
1993-03-21 12:45:37 +03:00
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* Suff_FindDeps --
* Find implicit sources for the target described by the graph node
* gn
1993-03-21 12:45:37 +03:00
*
* Results:
* Nothing.
*
* Side Effects:
* Nodes are added to the graph below the passed-in node. The nodes
* are marked to have their IMPSRC variable filled in. The
* PREFIX variable is set for the given node and all its
* implied children.
1993-03-21 12:45:37 +03:00
*
* Notes:
* The path found by this target is the shortest path in the
* transformation graph, which may pass through non-existent targets,
* to an existing target. The search continues on all paths from the
* root suffix until a file is found. I.e. if there's a path
* .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
* 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
* next level until the .l,v node is encountered.
1993-03-21 12:45:37 +03:00
*
*-----------------------------------------------------------------------
*/
1993-03-21 12:45:37 +03:00
void
Suff_FindDeps(GNode *gn)
{
SuffFindDeps(gn, srclist);
while (SuffRemoveSrc(srclist))
continue;
}
/*
* Input:
* gn node we're dealing with
*
*/
static void
SuffFindDeps(GNode *gn, Lst slst)
{
if (gn->type & OP_DEPS_FOUND) {
1993-03-21 12:45:37 +03:00
/*
* If dependencies already found, no need to do it again...
*/
return;
} else {
gn->type |= OP_DEPS_FOUND;
1993-03-21 12:45:37 +03:00
}
/*
* Make sure we have these set, may get revised below.
*/
Var_Set(TARGET, gn->path ? gn->path : gn->name, gn, 0);
Var_Set(PREFIX, gn->name, gn, 0);
if (DEBUG(SUFF)) {
fprintf(debug_file, "SuffFindDeps (%s)\n", gn->name);
}
if (gn->type & OP_ARCHV) {
SuffFindArchiveDeps(gn, slst);
} else if (gn->type & OP_LIB) {
1993-03-21 12:45:37 +03:00
/*
* If the node is a library, it is the arch module's job to find it
* and set the TARGET variable accordingly. We merely provide the
* search path, assuming all libraries end in ".a" (if the suffix
* hasn't been defined, there's nothing we can do for it, so we just
* set the TARGET variable to the node's name in order to give it a
* value).
*/
LstNode ln;
Suff *s;
ln = Lst_Find(sufflist, LIBSUFF, SuffSuffHasNameP);
if (gn->suffix)
gn->suffix->refCount--;
if (ln != NULL) {
gn->suffix = s = (Suff *)Lst_Datum(ln);
gn->suffix->refCount++;
Arch_FindLib(gn, s->searchPath);
} else {
gn->suffix = NULL;
Var_Set(TARGET, gn->name, gn, 0);
}
1993-03-21 12:45:37 +03:00
/*
* Because a library (-lfoo) target doesn't follow the standard
* filesystem conventions, we don't set the regular variables for
* the thing. .PREFIX is simply made empty...
*/
Var_Set(PREFIX, "", gn, 0);
} else {
SuffFindNormalDeps(gn, slst);
}
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
}
1993-03-21 12:45:37 +03:00
/*-
*-----------------------------------------------------------------------
* Suff_SetNull --
* Define which suffix is the null suffix.
1993-03-21 12:45:37 +03:00
*
* Input:
* name Name of null suffix
*
* Results:
* None.
*
* Side Effects:
* 'suffNull' is altered.
*
* Notes:
* Need to handle the changing of the null suffix gracefully so the
* old transformation rules don't just go away.
*
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
void
Suff_SetNull(char *name)
1993-03-21 12:45:37 +03:00
{
Suff *s;
LstNode ln;
ln = Lst_Find(sufflist, name, SuffSuffHasNameP);
if (ln != NULL) {
s = (Suff *)Lst_Datum(ln);
if (suffNull != NULL) {
suffNull->flags &= ~SUFF_NULL;
}
s->flags |= SUFF_NULL;
/*
* XXX: Here's where the transformation mangling would take place
*/
suffNull = s;
} else {
Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.",
name);
1993-03-21 12:45:37 +03:00
}
}
/*-
*-----------------------------------------------------------------------
* Suff_Init --
* Initialize suffixes module
*
* Results:
* None
*
* Side Effects:
* Many
1993-03-21 12:45:37 +03:00
*-----------------------------------------------------------------------
*/
void
Suff_Init(void)
1993-03-21 12:45:37 +03:00
{
sufflist = Lst_Init(FALSE);
#ifdef CLEANUP
suffClean = Lst_Init(FALSE);
#endif
srclist = Lst_Init(FALSE);
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
transforms = Lst_Init(FALSE);
1993-03-21 12:45:37 +03:00
sNum = 0;
/*
* Create null suffix for single-suffix rules (POSIX). The thing doesn't
* actually go on the suffix list or everyone will think that's its
* suffix.
*/
emptySuff = suffNull = bmake_malloc(sizeof(Suff));
suffNull->name = bmake_strdup("");
suffNull->nameLen = 0;
suffNull->searchPath = Lst_Init(FALSE);
Dir_Concat(suffNull->searchPath, dirSearchPath);
suffNull->children = Lst_Init(FALSE);
suffNull->parents = Lst_Init(FALSE);
suffNull->ref = Lst_Init(FALSE);
suffNull->sNum = sNum++;
suffNull->flags = SUFF_NULL;
suffNull->refCount = 1;
PR/46096: Jarmo Jaakkola: fix many problems with dependencies (PR 49086) Quite extensive rewrite of the Suff module. Some ripple effects into Parse and Targ modules too. Dependency searches in general were made to honor explicit rules so implicit and explicit sources are no longer applied on targets that do not invoke a transformation rule. Archive member dependency search was rewritten. Explicit rules now work properly and $(.TARGET) is set correctly. POSIX semantics for lib(member.o) and .s1.a rules are supported. .SUFFIXES list maintenance was rewritten so that scanning of existing rules works when suffixes are added and that clearing the suffix list removes single suffix rules too. Transformation rule nodes are now mixed with regular nodes so they are available as regular targets too if needed (especially after the known suffixes are cleared). The .NULL target was documented in the manual page, especially to warn against using it when a single suffix rule would work. A deprecation warning was also added to the manual and make also warns the user if it encounters .NULL. Search for suffix rules no longer allows the explicit dependencies to override the selected transformation rule. A check is made in the search that the transformation that would be tried does not already exist in the chain. This prevents getting stuck in an infinite loop under specific circumstances. Local variables are now set before node's children are expanded so dynamic sources work in multi-stage transformations. Make_HandleUse() no longer expands the added children for transformation nodes, preventing triple expansion and allowing the Suff module to properly postpone their expansion until proper values are set for the local variables. Directory prefix is no longer removed from $(.PREFIX) if the target is found via directory search. The last rule defined is now used instead of the first one (POSIX requirement) in case a rule is defined multiple times. Everything defined in the first instance is undone, but things added "globally" are honored. To implement this, each node tracks attribute bits which have been set by special targets (global) instead of special sources (local). They also track dependencies that were added by a rule with commands (local) instead of rule with no commands (global). New attribute, OP_FROM_SYS_MK is introduced. It is set on all targets found in system makefiles so that they are not eligible to become the main target. We cannot just set OP_NOTMAIN because it is one of the attributes inherited from transformation and .USE rules and would make any eligible target that uses a built-in inference rule ineligible. The $(.IMPSRC) local variable now works like in gmake: it is set to the first prerequisite for explicit rules. For implicit rules it is still the implied source. The manual page is improved regarding the fixed features. Test cases for the fixed problems are added. Other improvements in the Suff module include: - better debug messages for transformation rule search (length of the chain is now visualized by indentation) - Suff structures are created, destroyed and moved around by a set of maintenance functions so their reference counts are easier to track (this also gets rid of a lot of code duplication) - some unreasonably long functions were split into smaller ones - many local variables had their names changed to describe their purpose instead of their type
2014-08-23 19:05:40 +04:00
1993-03-21 12:45:37 +03:00
}
/*-
*----------------------------------------------------------------------
* Suff_End --
* Cleanup the this module
*
* Results:
* None
*
* Side Effects:
* The memory is free'd.
*----------------------------------------------------------------------
*/
void
Suff_End(void)
{
#ifdef CLEANUP
Lst_Destroy(sufflist, SuffFree);
Lst_Destroy(suffClean, SuffFree);
if (suffNull)
SuffFree(suffNull);
Lst_Destroy(srclist, NULL);
Lst_Destroy(transforms, NULL);
#endif
}
/********************* DEBUGGING FUNCTIONS **********************/
1993-03-21 12:45:37 +03:00
static int SuffPrintName(void *s, void *dummy)
{
fprintf(debug_file, "%s ", ((Suff *)s)->name);
return (dummy ? 0 : 0);
}
1993-03-21 12:45:37 +03:00
static int
SuffPrintSuff(void *sp, void *dummy)
1993-03-21 12:45:37 +03:00
{
Suff *s = (Suff *)sp;
1993-03-21 12:45:37 +03:00
int flags;
int flag;
fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount);
1993-03-21 12:45:37 +03:00
flags = s->flags;
if (flags) {
fputs(" (", debug_file);
1993-03-21 12:45:37 +03:00
while (flags) {
flag = 1 << (ffs(flags) - 1);
flags &= ~flag;
switch (flag) {
case SUFF_NULL:
fprintf(debug_file, "NULL");
break;
1993-03-21 12:45:37 +03:00
case SUFF_INCLUDE:
fprintf(debug_file, "INCLUDE");
1993-03-21 12:45:37 +03:00
break;
case SUFF_LIBRARY:
fprintf(debug_file, "LIBRARY");
1993-03-21 12:45:37 +03:00
break;
}
fputc(flags ? '|' : ')', debug_file);
1993-03-21 12:45:37 +03:00
}
}
fputc('\n', debug_file);
fprintf(debug_file, "#\tTo: ");
Lst_ForEach(s->parents, SuffPrintName, NULL);
fputc('\n', debug_file);
fprintf(debug_file, "#\tFrom: ");
Lst_ForEach(s->children, SuffPrintName, NULL);
fputc('\n', debug_file);
fprintf(debug_file, "#\tSearch Path: ");
Dir_PrintPath(s->searchPath);
fputc('\n', debug_file);
return (dummy ? 0 : 0);
1993-03-21 12:45:37 +03:00
}
static int
SuffPrintTrans(void *tp, void *dummy)
1993-03-21 12:45:37 +03:00
{
GNode *t = (GNode *)tp;
1993-03-21 12:45:37 +03:00
fprintf(debug_file, "%-16s: ", t->name);
Targ_PrintType(t->type);
fputc('\n', debug_file);
Lst_ForEach(t->commands, Targ_PrintCmd, NULL);
fputc('\n', debug_file);
return(dummy ? 0 : 0);
1993-03-21 12:45:37 +03:00
}
void
Suff_PrintAll(void)
1993-03-21 12:45:37 +03:00
{
fprintf(debug_file, "#*** Suffixes:\n");
Lst_ForEach(sufflist, SuffPrintSuff, NULL);
1993-03-21 12:45:37 +03:00
fprintf(debug_file, "#*** Transformations:\n");
Lst_ForEach(transforms, SuffPrintTrans, NULL);
1993-03-21 12:45:37 +03:00
}