2014-08-27 12:50:38 +04:00
|
|
|
/* $NetBSD: suff.c,v 1.72 2014/08/27 08:50:38 christos Exp $ */
|
1995-06-14 19:18:37 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
1996-11-06 20:58:58 +03:00
|
|
|
* Copyright (c) 1988, 1989, 1990, 1993
|
|
|
|
* The Regents of the University of California. All rights reserved.
|
2003-08-07 15:13:06 +04:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2004-05-07 04:04:38 +04:00
|
|
|
#ifndef MAKE_NATIVE
|
2014-08-27 12:50:38 +04:00
|
|
|
static char rcsid[] = "$NetBSD: suff.c,v 1.72 2014/08/27 08:50:38 christos Exp $";
|
1997-09-28 07:30:58 +04:00
|
|
|
#else
|
1997-07-02 01:17:00 +04:00
|
|
|
#include <sys/cdefs.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#ifndef lint
|
1995-06-14 19:18:37 +04:00
|
|
|
#if 0
|
1996-11-06 20:58:58 +03:00
|
|
|
static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
|
1995-06-14 19:18:37 +04:00
|
|
|
#else
|
2014-08-27 12:50:38 +04:00
|
|
|
__RCSID("$NetBSD: suff.c,v 1.72 2014/08/27 08:50:38 christos Exp $");
|
1995-06-14 19:18:37 +04:00
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
#endif /* not lint */
|
1997-09-28 07:30:58 +04:00
|
|
|
#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.
|
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Suff_End Clean up the module. Must be called after
|
|
|
|
* Targ_End() so suffix references in nodes
|
|
|
|
* have been dealt with.
|
|
|
|
*
|
|
|
|
* Suff_UnsetSuffix Helper for Targ_End() to unset node's suffix
|
|
|
|
* so as to not mess up reference counting.
|
1994-06-07 02:45:17 +04:00
|
|
|
*
|
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_FindDeps Find implicit sources for and the location of
|
|
|
|
* a target based on its suffix. Returns the
|
2008-12-13 18:19:29 +03:00
|
|
|
* bottom-most node added to the graph or NULL
|
1993-03-21 12:45:37 +03:00
|
|
|
* if the target had no implicit sources.
|
2004-12-29 04:55:25 +03:00
|
|
|
*
|
|
|
|
* Suff_FindPath Return the appropriate path to search in
|
|
|
|
* order to find the node.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
#include <assert.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdarg.h>
|
1993-03-21 12:45:37 +03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include "make.h"
|
1994-03-05 03:34:29 +03:00
|
|
|
#include "hash.h"
|
|
|
|
#include "dir.h"
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Currently known suffixes:
|
|
|
|
* All currently known suffixes are stored in sufflist (data: Suff *) and
|
|
|
|
* the next suffix added will get sNum as its suffix number (incremented
|
|
|
|
* after each use). Lookup is used as a lookup table for quick rejection,
|
|
|
|
* when it needs to be known if a string matches a known suffix. All indexes
|
|
|
|
* corresponding to the first character of a suffix in sufflist are true
|
|
|
|
* and others are false.
|
|
|
|
*/
|
|
|
|
static int sNum = 0;
|
|
|
|
static Lst sufflist;
|
|
|
|
#define LOOKUP_SIZE 256
|
|
|
|
static int lookup[LOOKUP_SIZE] = { 0 };
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Currently known transformations:
|
|
|
|
* References to nodes of currently active transformation rules (i.e. all
|
|
|
|
* which have OP_TRANSFORM set). It is used to remove the need to iterate
|
|
|
|
* through all targets when a transformation node needs to be accessed.
|
|
|
|
* (data: GNode *)
|
|
|
|
*/
|
|
|
|
static Lst transforms;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Structure describing an individual suffix.
|
2014-08-23 19:05:40 +04:00
|
|
|
*
|
|
|
|
* When a target has a known suffix, a reference is stored in the suffix
|
|
|
|
* field of its node. The same field is also used in OP_TRANSFORM nodes to
|
|
|
|
* store the /target/ of the transformation. This enables SuffScanTargets()
|
|
|
|
* to recognize single suffix transformations by the fact that the field
|
|
|
|
* references emptySuff. This also happens to be the known suffix of
|
|
|
|
* the field if the node is used as a regular target.
|
|
|
|
*
|
|
|
|
* Use the provided maintenance functions for creating, destroying and moving
|
|
|
|
* these around to keep the reference counts in order. The suffix will be
|
|
|
|
* free'd when the count reaches zero.
|
|
|
|
*
|
|
|
|
* The SUFF_NULL type flag is required for SuffAddLevelForSuffix() to
|
|
|
|
* detect when a suffix is used as a regular suffix and when as the .NULL
|
|
|
|
* suffix. This is achieved by only setting it for the duration of
|
|
|
|
* the call when the "remove a suffix" aspect of .NULL is used. When
|
|
|
|
* the .NULL feature is used in its "add a suffix" aspect, the transformation
|
|
|
|
* from a suffixless file is added after the regular transformation by
|
|
|
|
* SuffNewChildSrc() when a suffix == nullSuff is used.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
typedef struct _Suff {
|
2014-08-23 19:05:40 +04:00
|
|
|
char *name; /* The suffix itself (e.g. ".c") */
|
|
|
|
size_t nameLen; /* Length of the suffix */
|
|
|
|
|
|
|
|
short flags; /* Filetype implied by the suffix (bitfield) */
|
|
|
|
#define SUFF_INCLUDE 0x01 /* One which is #include'd.
|
|
|
|
* XXX: Not used? Remove? */
|
|
|
|
#define SUFF_LIBRARY 0x02 /* ar(1) archive */
|
|
|
|
#define SUFF_NULL 0x04 /* The .NULL suffix */
|
|
|
|
|
|
|
|
Lst searchPath; /* The path along which files of this suffix
|
1993-03-21 12:45:37 +03:00
|
|
|
* may be found */
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The suffix number. Unique for each suffix. Doubles as suffix
|
|
|
|
* priority, i.e. shows the relative .SUFFIXES ordering of suffixes:
|
|
|
|
* smaller sNums are earlier in the list.
|
|
|
|
*/
|
|
|
|
int sNum;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Reference count. Counted references are: membership in sufflist,
|
|
|
|
* membership in parents or children list of another suffix, assignment
|
|
|
|
* to GNode->suffix, assignment as emptySuff, and assignment as nullSuff.
|
|
|
|
*/
|
|
|
|
int refCount;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Suffixes we have a transformation to (parents) and from (children).
|
|
|
|
* Kept in .SUFFIXES order, as implied by sNum (data: Suff *)
|
|
|
|
* XXX: renaming these to "to" and "from" or "targets" and "sources"
|
|
|
|
* could make sense as parents and children on a suffix are not very
|
|
|
|
* intuitive.
|
|
|
|
*/
|
|
|
|
Lst parents;
|
|
|
|
Lst children;
|
|
|
|
|
|
|
|
#ifdef DEBUG_SRC
|
|
|
|
/*
|
|
|
|
* Lists this suffix is referenced in. Contains sufflist for all but
|
|
|
|
* emptySuff, parents list of all suffixes referenced in own children
|
|
|
|
* list, and children list of all suffixes referenced in own parents
|
|
|
|
* list. (data: Lst)
|
|
|
|
*/
|
|
|
|
Lst ref;
|
|
|
|
#endif
|
1993-03-21 12:45:37 +03:00
|
|
|
} Suff;
|
|
|
|
|
1998-11-01 06:05:03 +03:00
|
|
|
/*
|
|
|
|
* for SuffSuffIsSuffix
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2014-08-23 19:05:40 +04:00
|
|
|
char *ename; /* The end of the name (the final '\0') */
|
|
|
|
size_t len; /* The length of the name */
|
1998-11-01 06:05:03 +03:00
|
|
|
} 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 */
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Prefix from which file was formed. In an effort to reduce
|
|
|
|
* unnecessary memory allocations, only those with parent != NULL
|
|
|
|
* own their pref, others refer to their parents'.
|
|
|
|
*/
|
|
|
|
char *pref;
|
|
|
|
|
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 */
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Steps to top of chain. Used in debug prints to show chain length
|
|
|
|
* with indentation so multi-stage transformations are more readable.
|
|
|
|
*/
|
|
|
|
int depth;
|
1993-03-21 12:45:37 +03:00
|
|
|
} Src;
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Extra arguments to SuffAddSrc() via Lst_ForEach(). */
|
1994-03-05 03:34:29 +03:00
|
|
|
typedef struct {
|
2014-08-23 19:05:40 +04:00
|
|
|
Src *target; /* get possible transformations for this target */
|
|
|
|
Lst possible; /* list of possible transformation not yet tried */
|
|
|
|
Lst cleanup; /* list of all transformations created (for freeing) */
|
1994-03-05 03:34:29 +03:00
|
|
|
} LstSrc;
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Empty suffix for implementing POSIX single-suffix transformation rules.
|
|
|
|
* It won't go in sufflist lest all targets consider it as their suffix.
|
|
|
|
* Also, single suffix rules must only be checked if the target does not
|
|
|
|
* have a known suffix. This suffix is always the first one created, but
|
|
|
|
* its sNum field is forced to INT_MAX to keep it in its proper place
|
|
|
|
* at the end of the parents list of any of its children. (Hopefully no one
|
|
|
|
* will create that many suffixes)
|
|
|
|
*/
|
|
|
|
static Suff *emptySuff = NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* XXX: replace this ugly hack of a feature with pattern rules!
|
|
|
|
*/
|
|
|
|
static Suff *nullSuff = NULL;
|
1997-05-02 18:24:27 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Flags for SuffCleanUp() */
|
|
|
|
#define SCU_CLEAR (1 << 1) /* called from Suff_ClearSuffixes() */
|
|
|
|
#define SCU_END (1 << 2) /* called from Suff_End() */
|
|
|
|
/* Flags for SuffApplyTransformation*() */
|
|
|
|
#define SAT_REGULAR (1 << 0) /* Standard behavior */
|
|
|
|
#define SAT_NO_EXPAND (1 << 1) /* Don't expand children of top node */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Definitions (and map) for local functions. */
|
1994-03-05 03:34:29 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Lst Predicates */
|
2009-01-24 00:58:27 +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 *);
|
2014-08-23 19:05:40 +04:00
|
|
|
static int SuffSuffIsPrefixP(const void *, const void *);
|
2009-01-24 00:58:27 +03:00
|
|
|
static int SuffGNHasNameP(const void *, const void *);
|
2014-08-23 19:05:40 +04:00
|
|
|
static int SuffSuffHasPriorityLEP(const void *, const void *);
|
|
|
|
|
|
|
|
/* Maintenance Functions */
|
|
|
|
static Suff *SuffNewSuff(const char *);
|
|
|
|
static void SuffFreeSuff(Suff *);
|
|
|
|
static Src *SuffNewSrc(char *, char *, Suff *, GNode *, Src *);
|
|
|
|
static Src *SuffNewTopSrc(GNode *, Suff *);
|
|
|
|
static Src *SuffNewChildSrc(Src *, Suff *, Src **);
|
|
|
|
static void SuffFreeSrc(void *);
|
|
|
|
static void SuffLinkSuffixes(Suff *, Suff *);
|
|
|
|
static int SuffUnlinkSuffixes(void *f, void *t);
|
|
|
|
static void SuffSetSuffix(GNode *, Suff *);
|
|
|
|
static void Suff_UnsetSuffix(GNode *);
|
|
|
|
static void SuffAddToList(Suff *, Lst, LstNode);
|
|
|
|
static void SuffRemoveFromList(Suff *, Lst);
|
|
|
|
static void SuffInsertIntoList(Suff *, Lst);
|
|
|
|
static void SuffUnsetOpTransform(void *);
|
|
|
|
static int SuffUnlinkChildren(void *, void *);
|
|
|
|
static void SuffFreeSuffSufflist(void *);
|
|
|
|
static void SuffCleanUp(int);
|
|
|
|
|
|
|
|
/* Parsing Helpers */
|
|
|
|
/* Suff_ClearSuffixes */
|
2002-06-15 22:24:55 +04:00
|
|
|
static Boolean SuffParseTransform(char *, Suff **, Suff **);
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Suff_IsTransform */
|
|
|
|
/* Suff_AddTransform */
|
|
|
|
/* Suff_EndTransform */
|
2009-01-24 00:26:30 +03:00
|
|
|
static int SuffScanTargets(void *, void *);
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Suff_AddSuffix */
|
|
|
|
/* Suff_GetPath */
|
|
|
|
/* Suff_DoPaths */
|
|
|
|
/* Suff_AddInclude */
|
|
|
|
/* Suff_AddLib */
|
|
|
|
|
|
|
|
/* Implicit Source Search Functions */
|
2009-01-24 00:26:30 +03:00
|
|
|
static int SuffAddSrc(void *, void *);
|
2014-08-23 19:05:40 +04:00
|
|
|
static void SuffAddLevel(Lst, Src *, Lst);
|
2002-06-15 22:24:55 +04:00
|
|
|
static Src *SuffFindThem(Lst, Lst);
|
2014-08-23 19:05:40 +04:00
|
|
|
static void SuffExpandChildren(GNode *, LstNode);
|
|
|
|
static void SuffExpandChild(LstNode, GNode *);
|
2006-10-25 23:44:10 +04:00
|
|
|
static void SuffExpandWildcards(LstNode, GNode *);
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Suff_FindPath */
|
|
|
|
static Suff *SuffApplyTransformations(Src *, GNode *);
|
|
|
|
static Boolean SuffApplyTransformation(GNode *, GNode *, Suff *, Suff *, int);
|
|
|
|
static Suff *SuffFirstKnownSuffix(char* name);
|
|
|
|
static void SuffSetPrefixLocalVar(Suff *suffix, char *name, GNode *node);
|
2002-06-15 22:24:55 +04:00
|
|
|
static void SuffFindArchiveDeps(GNode *, Lst);
|
|
|
|
static void SuffFindNormalDeps(GNode *, Lst);
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Suff_FindDeps */
|
|
|
|
/* Suff_SetNull */
|
|
|
|
/* Suff_Init */
|
|
|
|
/* Suff_End */
|
|
|
|
|
|
|
|
/* Debugging Functions */
|
|
|
|
static int SuffDebug(const char *,...) MAKE_ATTR_PRINTFLIKE(1, 2);
|
|
|
|
static void SuffDebugChain(Src *);
|
2009-01-24 00:26:30 +03:00
|
|
|
static int SuffPrintName(void *, void *);
|
|
|
|
static int SuffPrintSuff(void *, void *);
|
|
|
|
static int SuffPrintTrans(void *, void *);
|
1994-03-05 03:34:29 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Lst Predicates
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffStrIsPrefix --
|
|
|
|
* See if pref is a prefix of str.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2009-01-24 00:58:27 +03:00
|
|
|
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 --
|
1998-11-01 06:05:03 +03:00
|
|
|
* 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
|
|
|
*
|
2002-06-15 22:24:55 +04: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 *
|
2009-01-24 00:58:27 +03:00
|
|
|
SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2002-06-15 22:24:55 +04:00
|
|
|
char *p1; /* Pointer into suffix name */
|
|
|
|
char *p2; /* Pointer into string being examined */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
1998-11-01 06:05:03 +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;
|
1998-11-01 06:05:03 +03:00
|
|
|
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.
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
1994-03-05 03:34:29 +03:00
|
|
|
static int
|
2009-01-24 00:58:27 +03:00
|
|
|
SuffSuffIsSuffixP(const void *s, const void *sd)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-01-24 00:58:27 +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.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
2009-01-24 00:58:27 +03:00
|
|
|
SuffSuffHasNameP(const void *s, const void *sname)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-01-24 00:58:27 +03:00
|
|
|
return (strcmp(sname, ((const Suff *)s)->name));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffSuffIsPrefixP -- see if str starts with s->name.
|
|
|
|
*
|
|
|
|
* 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...
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffSuffIsPrefixP(const void *s, const void *str)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-01-24 00:58:27 +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
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
2009-01-24 00:58:27 +03:00
|
|
|
SuffGNHasNameP(const void *gn, const void *name)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2009-01-24 00:58:27 +03:00
|
|
|
return (strcmp(name, ((const GNode *)gn)->name));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffSuffHasPriorityLEP -- (Less Than or Equal To [Predicate])
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Check if the second suffix should preceed the first one. This is
|
|
|
|
* a predicate function for Lst_Find(), used by SuffInsertIntoList()
|
|
|
|
* for finding the insertion position of the new suffix.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* first The first suffix. (Suff *)
|
|
|
|
* second The second suffix. (Suff *)
|
|
|
|
*
|
|
|
|
* Returns:
|
|
|
|
* Return 0 if the first suffix has a priority less than or
|
|
|
|
* equal to the second one, i.e. the second one preceeds the first
|
|
|
|
* one in the .SUFFIXES list or they are in fact the same suffix.
|
|
|
|
* Otherwise non-zero is returned.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static int
|
|
|
|
SuffSuffHasPriorityLEP(const void *first, const void* second)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
return !(((const Suff *)first)->sNum >= ((const Suff *)second)->sNum);
|
|
|
|
}
|
1994-06-07 02:45:17 +04:00
|
|
|
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Maintenance Functions
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffNewSuff -- allocate and initialize a Suff structure.
|
|
|
|
*
|
|
|
|
* The contained lists are initialized and empty. No flags are set and
|
|
|
|
* the reference count is zero. The next serial number is allocated
|
|
|
|
* for this struct.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* name The suffix this structure describes (e.g. ".c"). A copy
|
|
|
|
* is made of this string.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* The allocated and initialized structure.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Suff*
|
|
|
|
SuffNewSuff(const char* name)
|
|
|
|
{
|
|
|
|
Suff *s = bmake_malloc(sizeof(Suff));
|
|
|
|
|
|
|
|
s->name = bmake_strdup(name);
|
|
|
|
s->nameLen = strlen(name);
|
|
|
|
s->flags = (strcmp(name, LIBSUFF) == 0 ? SUFF_LIBRARY : 0);
|
|
|
|
s->searchPath = Lst_Init(FALSE);
|
|
|
|
s->sNum = sNum++;
|
|
|
|
s->refCount = 0;
|
|
|
|
s->children = Lst_Init(FALSE);
|
|
|
|
s->parents = Lst_Init(FALSE);
|
|
|
|
#ifdef DEBUG_SRC
|
|
|
|
s->ref = Lst_Init(FALSE);
|
1998-07-03 03:30:18 +04:00
|
|
|
#endif
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
return s;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
1994-06-07 02:45:17 +04:00
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffFreeSuff -- release resources held by a Suff structure.
|
1994-06-07 02:45:17 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* There are no other resources than memory, which is free'd.
|
1994-06-07 02:45:17 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* s the struct to free
|
1994-06-07 02:45:17 +04:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffFreeSuff(Suff *s)
|
1994-06-07 02:45:17 +04:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Make reference counting bugs unpleasantly obvious. */
|
|
|
|
if (s->refCount != 0)
|
|
|
|
Punt("Internal error deleting suffix `%s' with reference count %d",
|
|
|
|
s->name, s->refCount);
|
|
|
|
|
|
|
|
free(s->name);
|
|
|
|
Lst_Destroy(s->searchPath, Dir_Destroy);
|
|
|
|
Lst_Destroy(s->parents, NULL);
|
|
|
|
Lst_Destroy(s->children, NULL);
|
|
|
|
#ifdef DEBUG_SRC
|
|
|
|
Lst_Destroy(s->ref, NULL);
|
|
|
|
#endif
|
|
|
|
free(s);
|
1994-06-07 02:45:17 +04:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffNewSrc -- allocate and initialize a new Src structure.
|
|
|
|
*
|
|
|
|
* The depth field is set to 0 if parent is NULL and to parent->depth + 1
|
|
|
|
* otherwise.
|
|
|
|
*
|
|
|
|
* You probably want to use the convenience functions SuffNewTopSrc() and
|
|
|
|
* SuffNewChildSrc(). These convenience functions take the relevant
|
|
|
|
* information from their parameters, making copies as needed.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* file, pref, suffix, node, parent
|
|
|
|
* Contents of the corresponding fields. No copies are
|
|
|
|
* made, they are used as they are!
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
2014-08-23 19:05:40 +04:00
|
|
|
* The allocated and initialized structure.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static Src*
|
|
|
|
SuffNewSrc(char* file, char* pref, Suff *suffix, GNode *node, Src *parent)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Src *s = bmake_malloc(sizeof(Src));
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
s->file = file;
|
|
|
|
s->pref = pref;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
s->suff = suffix;
|
|
|
|
|
|
|
|
s->parent = parent;
|
|
|
|
s->depth = 0;
|
|
|
|
if (parent != NULL)
|
|
|
|
s->depth = parent->depth + 1;
|
|
|
|
|
|
|
|
s->node = node;
|
|
|
|
|
|
|
|
return s;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffNewTopSrc -- create a new Src for node->name, using suffix.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static Src*
|
|
|
|
SuffNewTopSrc(GNode *node, Suff *suffix)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
return SuffNewSrc(
|
|
|
|
bmake_strdup(node->name),
|
|
|
|
bmake_strndup(node->name, strlen(node->name) - suffix->nameLen),
|
|
|
|
suffix,
|
|
|
|
node,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffNewTopSrc -- create a new Src for node->name, faking suffix as "".
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Src*
|
|
|
|
SuffNewTopSrcNull(GNode *node, Suff *suffix)
|
|
|
|
{
|
|
|
|
return SuffNewSrc(
|
|
|
|
bmake_strdup(node->name),
|
|
|
|
bmake_strdup(node->name),
|
|
|
|
suffix,
|
|
|
|
node,
|
|
|
|
NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffNewChildSrc -- create a new Src for (parent->pref + suffix->name).
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* nullChild for storing the .NULL child
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* If suffix == nullSuff, a possible source is created for parent->pref
|
|
|
|
* also and stored into nullChild. Otherwise nullChild is set to NULL.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static Src*
|
|
|
|
SuffNewChildSrc(Src *parent, Suff *suffix, Src **nullChild)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
if (suffix == nullSuff)
|
|
|
|
*nullChild = SuffNewSrc(
|
|
|
|
bmake_strdup(parent->pref),
|
|
|
|
parent->pref,
|
|
|
|
suffix,
|
|
|
|
NULL,
|
|
|
|
parent);
|
|
|
|
else
|
|
|
|
*nullChild = NULL;
|
|
|
|
|
|
|
|
return SuffNewSrc(
|
|
|
|
str_concat(parent->pref, suffix->name, 0),
|
|
|
|
parent->pref,
|
|
|
|
suffix,
|
|
|
|
NULL,
|
|
|
|
parent);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffFreeSrc -- release resources held by an Src structure.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* There are no other resources than memory, which is free'd. The signature
|
|
|
|
* is chosen so as to be able to call this from Lst_Destroy().
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* sp the struct to free
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
SuffFreeSrc(void *sp)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Src *s = (Src *)sp;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
free(s->file);
|
|
|
|
if (s->parent == NULL)
|
|
|
|
free(s->pref);
|
|
|
|
free(s);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffLinkSuffixes -- relate two suffixes.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Makes "from" aware that "to" is a possible target and "to" aware that
|
|
|
|
* "from" is a possible source. Proper .SUFFIXES ordering is maintained.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Pre-condition:
|
|
|
|
* The suffixes are not already linked.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* from source file suffix
|
|
|
|
* to target file suffix
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
SuffLinkSuffixes(Suff *from, Suff *to)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("Defining a transformation from `%s' to `%s'.\n",
|
|
|
|
from->name, to->name);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffInsertIntoList(to, from->parents);
|
|
|
|
SuffInsertIntoList(from, to->children);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffUnlinkSuffixes -- undo what SuffLinkSuffixes() did.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
SuffUnlinkSuffixes(void *f, void *t)
|
|
|
|
{
|
|
|
|
Suff *from = (Suff *)f;
|
|
|
|
Suff *to = (Suff *)t;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("Undefining a transformation from `%s' to `%s'.\n",
|
|
|
|
from->name, to->name);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffRemoveFromList(to, from->parents);
|
|
|
|
SuffRemoveFromList(from, to->children);
|
|
|
|
/* The suffixes are still in sufflist, refCount must be > 0. */
|
|
|
|
assert(to->refCount > 0);
|
|
|
|
assert(from->refCount > 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffSetSuffix -- set a new suffix for node.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* The old suffix, if any, is removed by calling Suff_UnsetSuffix().
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* node node to set the suffix for
|
|
|
|
* suffix new suffix for the node
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* OP_LIB is set / unset on node if SUFF_LIBRARY is set / unset on
|
|
|
|
* suffix.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
SuffSetSuffix(GNode *node, Suff *suffix)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff_UnsetSuffix(node);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
node->suffix = suffix;
|
2001-05-08 19:15:53 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (suffix != NULL) {
|
|
|
|
suffix->refCount++;
|
|
|
|
if (suffix->flags & SUFF_LIBRARY)
|
|
|
|
node->type |= OP_LIB;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* Suff_UnsetSuffix -- remove the current suffix of a node.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* node Node whose suffix is to be cleared.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* OP_LIB is cleared from node if it was set. The library status
|
|
|
|
* of nodes stems from their suffixes, so it can't be a library
|
|
|
|
* if it has no suffix.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
Suff_UnsetSuffix(GNode *node)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
if (node->suffix != NULL) {
|
|
|
|
--node->suffix->refCount;
|
|
|
|
/* Suffix is still in sufflist, so refCount must be > 0 */
|
|
|
|
assert(node->suffix->refCount > 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
node->type &= ~OP_LIB;
|
|
|
|
node->suffix = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1997-05-02 18:24:27 +04:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffAddToList -- add a suffix to a suffix list.
|
1997-05-02 18:24:27 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* suffix suffix to add
|
|
|
|
* list list to receive the suffix
|
|
|
|
* succ The intended successor of the suffix in the list.
|
|
|
|
* NULL means no successor, i.e. append.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffAddToList(Suff *suffix, Lst list, LstNode succ)
|
|
|
|
{
|
|
|
|
if (list != sufflist)
|
|
|
|
SuffDebug("\t`%s'(%d) ", suffix->name, suffix->sNum);
|
|
|
|
|
|
|
|
if (succ == NULL) {
|
|
|
|
(void)Lst_AtEnd(list, suffix);
|
|
|
|
if (list != sufflist)
|
|
|
|
SuffDebug("inserted at the end of the list.\n");
|
|
|
|
} else {
|
|
|
|
Suff *s = (Suff *)Lst_Datum(succ);
|
|
|
|
(void)Lst_InsertBefore(list, succ, suffix);
|
|
|
|
if (list != sufflist)
|
|
|
|
SuffDebug("inserted before `%s'(%d).\n", s->name, s->sNum);
|
|
|
|
}
|
|
|
|
++suffix->refCount;
|
|
|
|
|
|
|
|
#ifdef DEBUG_SRC
|
|
|
|
(void)Lst_AtEnd(suffix->ref, list);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffRemoveFromList -- remove a suffix from a suffix list.
|
|
|
|
*
|
|
|
|
* The reference count of the suffix might be zero afterwards. It is
|
|
|
|
* the responsibility of the caller to handle this.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* suffix suffix to remove
|
|
|
|
* list list to remove the suffix from
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffRemoveFromList(Suff *suffix, Lst list)
|
|
|
|
{
|
|
|
|
if (Lst_Remove(list, Lst_Member(list, suffix)) == SUCCESS) {
|
|
|
|
suffix->refCount--;
|
|
|
|
|
|
|
|
#ifdef DEBUG_SRC
|
|
|
|
Lst_Remove(suffix->ref, Lst_Member(suffix->ref, list));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffInsertIntoList -- insert a suffix into its proper place in a list.
|
|
|
|
*
|
|
|
|
* The suffixes in the list are kept ordered by suffix numbers (sNum).
|
|
|
|
*
|
|
|
|
* Pre-condition:
|
|
|
|
* suffix is not already in the list.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* suffix suffix to add
|
|
|
|
* list list to receive the suffix
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffInsertIntoList(Suff *suffix, Lst list)
|
|
|
|
{
|
|
|
|
LstNode successor;
|
|
|
|
|
|
|
|
successor = Lst_Find(list, suffix, SuffSuffHasPriorityLEP);
|
|
|
|
|
|
|
|
if (successor == NULL || ((Suff *)Lst_Datum(successor)) != suffix)
|
|
|
|
SuffAddToList(suffix, list, successor);
|
|
|
|
else
|
|
|
|
/*
|
|
|
|
* This function is only used by SuffLinkSuffixes(), which in turn
|
|
|
|
* should only be called to link previously unlinked suffixes.
|
|
|
|
*/
|
|
|
|
Punt("Internal error: tried to insert duplicate suffix `%s'(%d) "
|
|
|
|
"into a list.\n", suffix->name, suffix->sNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffUnsetOpTransform -- clear the OP_TRANSFORM flag from a target.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* target The target node whose type is modified. (GNode *)
|
1997-05-02 18:24:27 +04:00
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* The suffix of the node is unset.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffUnsetOpTransform(void *tp)
|
|
|
|
{
|
|
|
|
GNode *target = (GNode *)tp;
|
|
|
|
Suff_UnsetSuffix(target);
|
|
|
|
target->type &= ~OP_TRANSFORM;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffUnlinkChildren -- SuffUnlinkSuffixes(child, suffix) with all chidren.
|
|
|
|
*
|
|
|
|
* Calling this function for all suffixes undoes all links between suffixes
|
|
|
|
* and this is what Suff_ClearSuffixes() uses it for.
|
1997-05-02 18:24:27 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* suff undo links to children for this suffix (Suff *)
|
1997-05-02 18:24:27 +04:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static int
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffUnlinkChildren(void *suff, void *unused)
|
|
|
|
{
|
|
|
|
Suff *suffix = (Suff *)suff;
|
|
|
|
(void)unused;
|
|
|
|
Lst_ForEach(suffix->children, SuffUnlinkSuffixes, suffix);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffFreeSuffSufflist -- frontend to SuffFreeSuff() for destroying sufflist.
|
|
|
|
*
|
|
|
|
* Reduce the reference count of the suffix by one because it is
|
|
|
|
* no longer in sufflist, preventing SuffFreeSuff() from throwing a fit.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* suff suffix to free
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffFreeSuffSufflist(void *suff)
|
1997-05-02 18:24:27 +04:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff *suffix = (Suff *)suff;
|
|
|
|
--suffix->refCount;
|
|
|
|
SuffFreeSuff(suffix);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffCleanUp -- uninitialize the module.
|
|
|
|
*
|
|
|
|
* Clears OP_TRANSFORM from transformation rules and deletes all suffixes.
|
|
|
|
*
|
|
|
|
* This is a separate function instead of being built in to Suff_End()
|
|
|
|
* because coincidentally this exact same functionality is needed
|
|
|
|
* by Suff_ClearSuffixes().
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* flags tweak behavior
|
|
|
|
* SCU_CLEAR
|
|
|
|
* regular behavior
|
|
|
|
* SCU_END
|
|
|
|
* do not clear transforms, they've been deleted
|
|
|
|
* already by Targ_End()
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffCleanUp(int flags)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Undo all references between the suffixes before deleting them
|
|
|
|
* so SuffFreeSuff() can catch any bugs we might have with reference
|
|
|
|
* counting.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Lst_Destroy(transforms,
|
|
|
|
((flags & SCU_CLEAR) ? SuffUnsetOpTransform : NULL));
|
|
|
|
|
|
|
|
if (nullSuff != NULL) {
|
|
|
|
--nullSuff->refCount;
|
|
|
|
nullSuff = NULL;
|
1997-05-02 18:24:27 +04:00
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffUnlinkChildren(emptySuff, NULL);
|
|
|
|
--emptySuff->refCount;
|
|
|
|
SuffFreeSuff(emptySuff);
|
|
|
|
|
|
|
|
Lst_ForEach(sufflist, SuffUnlinkChildren, NULL);
|
|
|
|
Lst_Destroy(sufflist, SuffFreeSuffSufflist);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Parsing Helpers
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_ClearSuffixes -- remove all known suffixes.
|
|
|
|
*
|
|
|
|
* Effectively, the module is re-initialized.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* All OP_TRANSFORM nodes in the graph are reset to regular nodes.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
Suff_ClearSuffixes(void)
|
|
|
|
{
|
|
|
|
SuffCleanUp(SCU_CLEAR);
|
|
|
|
Suff_Init();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffParseTransform -- get component suffixes from transformation name.
|
|
|
|
*
|
|
|
|
* Double suffix rules are preferred over single suffix ones (i.e.
|
|
|
|
* transformations to the empty suffix). This only matters if any suffix
|
|
|
|
* is a catenation of two others: if .tar.gz, .tar, and .gz are known, then
|
|
|
|
* ".tar.gz" is double suffix transformation from .tar to .gz, not a single
|
|
|
|
* suffix one from .tar.gz.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* name transformation name
|
|
|
|
* sourceSuff place to store the source suffix
|
|
|
|
* targetSuff place to store the target suffix
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* TRUE if the string is a valid transformation and FALSE otherwise.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* The passed pointers are overwritten: by the actual suffixes when
|
|
|
|
* TRUE is returned, with NULLs otherwise.
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Boolean
|
|
|
|
SuffParseTransform(char *name, Suff **sourceSuff, Suff **targetSuff)
|
|
|
|
{
|
|
|
|
LstNode s; /* sufflist iterator for source */
|
|
|
|
Suff *from, *to; /* source and target suffixes */
|
|
|
|
Suff *single; /* the suffix that matches the whole name */
|
|
|
|
|
|
|
|
s = NULL;
|
|
|
|
from = to = single = NULL;
|
1997-05-02 18:24:27 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Don't bother with obviously invalid names. */
|
|
|
|
if (!lookup[(unsigned char)name[0]])
|
|
|
|
goto end;
|
1997-05-02 18:24:27 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Is it a double suffix transformation? For each suffix that matches
|
|
|
|
* the start of the name, see if another one matches the rest of it.
|
|
|
|
* The first valid pair is chosen. The first suffix that matches
|
|
|
|
* the whole name is remembered, so the suffixes need not to be checked
|
|
|
|
* again for a single suffix transformation. from and to stay as
|
|
|
|
* NULLs if no valid transformation is found.
|
|
|
|
*/
|
|
|
|
for (s = Lst_Find(sufflist, name, SuffSuffIsPrefixP); s != NULL;
|
|
|
|
s = Lst_FindFrom(sufflist, Lst_Succ(s), name, SuffSuffIsPrefixP))
|
|
|
|
{
|
|
|
|
from = (Suff *)Lst_Datum(s);
|
|
|
|
char *targetName = name + from->nameLen;
|
|
|
|
|
|
|
|
if (*targetName == '\0') {
|
|
|
|
single = from;
|
|
|
|
} else {
|
|
|
|
LstNode t = Lst_Find(sufflist, targetName, SuffSuffHasNameP);
|
|
|
|
if (t != NULL) {
|
|
|
|
to = (Suff *)Lst_Datum(t);
|
|
|
|
break;
|
|
|
|
}
|
1997-05-02 18:24:27 +04:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
from = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Use the full match for a single if it wasn't a double. */
|
|
|
|
if (from == NULL && single != NULL) {
|
|
|
|
from = single;
|
|
|
|
to = emptySuff;
|
|
|
|
}
|
|
|
|
|
|
|
|
end:
|
|
|
|
if (sourceSuff != NULL && targetSuff != NULL) {
|
|
|
|
*sourceSuff = from;
|
|
|
|
*targetSuff = to;
|
|
|
|
}
|
|
|
|
|
|
|
|
return from != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_IsTransform -- check if the given string is a transformation rule.
|
|
|
|
*
|
|
|
|
* Figuring out if the name is a transformation requires us to find
|
|
|
|
* the suffixes which would make up the transformation. The same
|
|
|
|
* information will be calculated if Suff_AddTransform() is then called
|
|
|
|
* with the same name. The information from this call can be cached by
|
|
|
|
* providing non-NULL values for fromCache and toCache and passing all
|
|
|
|
* the same parameters to Suff_AddTransform() if this function returns
|
|
|
|
* true..
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* str string to check
|
|
|
|
* fromCache opaque cache pointer
|
|
|
|
* toCache opaque cache pointer
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* TRUE if the string is a catenation of two known suffixes or
|
|
|
|
* matches one suffix exactly, FALSE otherwise
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
Boolean
|
|
|
|
Suff_IsTransform(char *str, void **fromCache, void **toCache)
|
|
|
|
{
|
|
|
|
return SuffParseTransform(str, (Suff **)fromCache, (Suff **)toCache);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_AddTransform -- record the transformation defined by name.
|
|
|
|
*
|
|
|
|
* A node is created into the graph to store the transformation, if one
|
|
|
|
* does not already exist.
|
|
|
|
*
|
|
|
|
* Pre-condition:
|
|
|
|
* If src and targ are non-NULL, they must have been parameters
|
|
|
|
* of a call to Suff_IsTransform() that returned true for the same
|
|
|
|
* set of parameters.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* name name of new transformation
|
|
|
|
* fromCache opaque cache pointer
|
|
|
|
* toCache opaque cache pointer
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* The node of the transformation.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
GNode *
|
|
|
|
Suff_AddTransform(char *name, void **fromCache, void **toCache)
|
|
|
|
{
|
|
|
|
GNode *node;
|
|
|
|
Suff *from, *to;
|
|
|
|
if (fromCache != NULL && toCache != NULL) {
|
|
|
|
from = (Suff *)*fromCache;
|
|
|
|
to = (Suff *)*toCache;
|
|
|
|
} else
|
|
|
|
from = to = NULL;
|
|
|
|
|
|
|
|
node = Targ_FindNode(name, TARG_CREATE);
|
|
|
|
|
|
|
|
if ((from != NULL || SuffParseTransform(name, &from, &to))
|
|
|
|
&& !(node->type & OP_TRANSFORM))
|
|
|
|
{
|
|
|
|
node->type |= OP_TRANSFORM;
|
|
|
|
Lst_AtEnd(transforms, node);
|
|
|
|
SuffSetSuffix(node, to);
|
|
|
|
|
|
|
|
/* Pre-cond: this did not exist before, can't be linked yet. */
|
|
|
|
SuffLinkSuffixes(from, to);
|
|
|
|
}
|
|
|
|
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* 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
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* gnp Node for transformation
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* === 0
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* If the node has no commands or children, the children and parents
|
|
|
|
* lists of the affected suffixes are altered.
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
Suff_EndTransform(void *gnp, void *unused)
|
|
|
|
{
|
|
|
|
GNode *gn = (GNode *)gnp;
|
|
|
|
|
|
|
|
(void)unused;
|
|
|
|
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
/* So it is an empty target. */
|
|
|
|
Suff *s, *t;
|
|
|
|
|
|
|
|
/* But is it a transformation? (.DEFAULT is also OP_TRANSFORM) */
|
|
|
|
if (SuffParseTransform(gn->name, &s, &t)) {
|
|
|
|
SuffDebug("Deleting a transformation with no commands.\n");
|
|
|
|
SuffUnlinkSuffixes(s, t);
|
|
|
|
gn->type |= ~OP_TRANSFORM;
|
1997-05-02 18:24:27 +04:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
} else if ((gn->type & OP_TRANSFORM))
|
|
|
|
SuffDebug("Transformation %s completed.\n", gn->name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffScanTargets --
|
|
|
|
* Called from Suff_AddSuffix via Lst_ForEach to search through the
|
|
|
|
* list of existing targets for necessary changes.
|
|
|
|
*
|
|
|
|
* Any target that was not already a transformation and according to
|
|
|
|
* SuffParseTransform() now is, is made into one. Existing
|
|
|
|
* single suffix transformations, that are now valid two suffix ones,
|
|
|
|
* are converted. There's no change in double prefix rules.
|
|
|
|
* The single suffix conversion could not happen if we were to accept
|
|
|
|
* only POSIX suffixes, but we accept everything.
|
|
|
|
*
|
|
|
|
* What is so special about single suffix transformations? Consider
|
|
|
|
* the case in which suffixes s1, s2, ..., and sN are given. Then
|
|
|
|
* any double prefix rule is sXsY such that sX is the first suffix
|
|
|
|
* in the list for which the remainder sY is also in the list.
|
|
|
|
* Thus X and Y are both at most N. No matter what suffix we add
|
|
|
|
* to the list, X and Y cannot change.
|
|
|
|
*
|
|
|
|
* For a single suffix rule the case is different. Given suffixes
|
|
|
|
* .a.b and .a, the transformation ".a.b" is a single prefix rule.
|
|
|
|
* We always give precedence for double prefix rules, so when
|
|
|
|
* .b is added as a suffix, the transformation should now be
|
|
|
|
* a double suffix rule .a -> .b.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* targetNode Current target to check.
|
|
|
|
* newSuffix The newly added suffix.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* Always 0, so Lst_ForEach() won't stop prematurely.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
SuffScanTargets(void *targetGNode, void *newSuffix)
|
|
|
|
{
|
|
|
|
GNode *target = (GNode *)targetGNode;
|
|
|
|
Suff *from, *to;
|
|
|
|
Suff *suffix = (Suff *)newSuffix;
|
|
|
|
|
|
|
|
from = to = NULL;
|
|
|
|
|
|
|
|
/* Reject obviously irrelevant targets. */
|
|
|
|
if (!(lookup[(unsigned char)target->name[0]]
|
|
|
|
&& strstr(target->name, suffix->name) != NULL))
|
|
|
|
{
|
|
|
|
goto out;
|
1997-05-02 18:24:27 +04:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
if (SuffParseTransform(target->name, &from, &to)) {
|
|
|
|
if (target->type & OP_TRANSFORM) {
|
|
|
|
if (target->suffix == emptySuff && to != emptySuff)
|
|
|
|
SuffUnlinkSuffixes(from, to); /* single to double */
|
|
|
|
else
|
|
|
|
from = to = NULL; /* still a single, or was double */
|
|
|
|
} else
|
|
|
|
target->type |= OP_TRANSFORM; /* regular to transformation */
|
|
|
|
|
|
|
|
if (from != NULL && to != NULL) {
|
|
|
|
/* Pre-cond: new double or completely new, can't be linked yet. */
|
|
|
|
SuffLinkSuffixes(from, to);
|
|
|
|
Lst_AtEnd(transforms, target);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
1997-05-02 18:24:27 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_AddSuffix --
|
2014-08-23 19:05:40 +04:00
|
|
|
* Add the named suffix to the end of the list of known suffixes.
|
|
|
|
* Existing targets are checked to see if any of them becomes
|
|
|
|
* a transformation.
|
|
|
|
*
|
|
|
|
* If the suffix is already in the list of known suffixes, nothing
|
|
|
|
* is done.
|
|
|
|
*
|
|
|
|
* After this function is called, the target list should be re-scanned
|
|
|
|
* in case the current main target was made into a transformation rule.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* name the name of the suffix to add
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
2014-08-23 19:05:40 +04:00
|
|
|
* TRUE if a new suffix was added, FALSE otherwise.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Side Effects:
|
|
|
|
* A GNode is created for the suffix and a Suff structure is created and
|
2014-08-23 19:05:40 +04:00
|
|
|
* appended to the suffixes list unless the suffix was already known.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff_AddSuffix(char *name)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff *s; /* New one for adding */
|
|
|
|
LstNode old;
|
|
|
|
|
|
|
|
old = Lst_Find(sufflist, name, SuffSuffHasNameP);
|
|
|
|
if (old == NULL) {
|
|
|
|
s = SuffNewSuff(name);
|
|
|
|
SuffAddToList(s, sufflist, NULL);
|
|
|
|
|
|
|
|
lookup[(unsigned char)s->name[0]] = 1;
|
|
|
|
|
|
|
|
Lst_ForEach(Targ_List(), SuffScanTargets, s);
|
1996-11-06 20:58:58 +03:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_GetPath --
|
|
|
|
* Return the search path for the given suffix, if it's defined.
|
|
|
|
*
|
|
|
|
* Results:
|
2008-12-13 18:19:29 +03:00
|
|
|
* 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
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_GetPath(char *sname)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
LstNode ln;
|
|
|
|
Suff *s;
|
|
|
|
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
|
2014-08-23 19:05:40 +04:00
|
|
|
if (ln != NULL)
|
2005-07-26 02:55:58 +04:00
|
|
|
s = (Suff *)Lst_Datum(ln);
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
return (ln == NULL ? NULL : 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
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_DoPaths(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff *s;
|
|
|
|
LstNode ln;
|
1994-06-07 02:45:17 +04:00
|
|
|
char *ptr;
|
1993-03-21 12:45:37 +03:00
|
|
|
Lst inIncludes; /* Cumulative .INCLUDES path */
|
|
|
|
Lst inLibs; /* Cumulative .LIBS path */
|
|
|
|
|
2005-02-16 18:11:52 +03:00
|
|
|
if (Lst_Open(sufflist) == FAILURE) {
|
1993-03-21 12:45:37 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
inIncludes = Lst_Init(FALSE);
|
|
|
|
inLibs = Lst_Init(FALSE);
|
|
|
|
|
2008-12-13 18:19:29 +03:00
|
|
|
while ((ln = Lst_Next(sufflist)) != NULL) {
|
2005-07-26 02:55:58 +04:00
|
|
|
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 {
|
2005-02-16 18:11:52 +03:00
|
|
|
Lst_Destroy(s->searchPath, Dir_Destroy);
|
1993-03-21 12:45:37 +03:00
|
|
|
s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL, 0);
|
1994-06-07 02:45:17 +04:00
|
|
|
free(ptr);
|
2001-06-13 03:36:17 +04:00
|
|
|
Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL, 0);
|
1994-06-07 02:45:17 +04:00
|
|
|
free(ptr);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
Lst_Destroy(inIncludes, Dir_Destroy);
|
|
|
|
Lst_Destroy(inLibs, Dir_Destroy);
|
|
|
|
|
2005-02-16 18:11:52 +03:00
|
|
|
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.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_AddInclude(char *sname)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
LstNode ln;
|
|
|
|
Suff *s;
|
|
|
|
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
|
2008-12-13 18:19:29 +03:00
|
|
|
if (ln != NULL) {
|
2005-07-26 02:55:58 +04:00
|
|
|
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.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* 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
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_AddLib(char *sname)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
|
|
|
LstNode ln;
|
|
|
|
Suff *s;
|
|
|
|
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(sufflist, sname, SuffSuffHasNameP);
|
2008-12-13 18:19:29 +03:00
|
|
|
if (ln != NULL) {
|
2005-07-26 02:55:58 +04:00
|
|
|
s = (Suff *)Lst_Datum(ln);
|
1993-03-21 12:45:37 +03:00
|
|
|
s->flags |= SUFF_LIBRARY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Implicit Source Search Functions
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffAddSrc -- add transformation possibility.
|
|
|
|
*
|
|
|
|
* Create an Src structure describing a transformation from a file with
|
|
|
|
* the given suffix to the given target (target.from -> target.to).
|
|
|
|
* If the suffix happens to be the .NULL suffix, create a transformation
|
|
|
|
* from target's prefix also (target -> target.to).
|
|
|
|
*
|
|
|
|
* This is callback function for Lst_ForEach().
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* suffix the source's suffix
|
|
|
|
* arguments more arguments: target, transformations not yet tried,
|
|
|
|
* cleanup list.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
2014-08-23 19:05:40 +04:00
|
|
|
* Always return 0 to prevent Lst_ForEach() from exiting prematurely.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static int
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffAddSrc(void *suffix, void *arguments)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff *fromSuffix;
|
|
|
|
LstSrc *args;
|
|
|
|
Src *from, *nullChild, *to;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
fromSuffix = (Suff *)suffix;
|
|
|
|
args = (LstSrc *)arguments;
|
|
|
|
to = args->target;
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Don't add a transformation that is already in the chain or we
|
|
|
|
* might get stuck in an infinite loop.
|
|
|
|
*/
|
|
|
|
for (to = args->target; to != NULL; to = to->parent) {
|
|
|
|
if (to->suff == fromSuffix) {
|
|
|
|
SuffDebug("\t%*.s%s%s: ignored (already tried in this chain)\n",
|
|
|
|
args->target->depth + 1, " ", to->pref, fromSuffix->name);
|
|
|
|
goto end;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
to = args->target;
|
|
|
|
|
|
|
|
from = SuffNewChildSrc(to, fromSuffix, &nullChild);
|
1994-06-07 02:45:17 +04:00
|
|
|
#ifdef DEBUG_SRC
|
2014-08-23 19:05:40 +04:00
|
|
|
fprintf(debug_file, "1 add %x %x to %x:", to, from, args->possible);
|
|
|
|
if (nullChild != NULL)
|
|
|
|
fprintf(debug_file, "2 add %x %x to %x:", to, nullChild,
|
|
|
|
args->possible);
|
|
|
|
Lst_ForEach(args->possible, PrintAddr, NULL);
|
2006-10-15 12:38:21 +04:00
|
|
|
fprintf(debug_file, "\n");
|
1994-06-07 02:45:17 +04:00
|
|
|
#endif
|
2014-08-23 19:05:40 +04:00
|
|
|
Lst_AtEnd(args->possible, from);
|
|
|
|
Lst_AtEnd(args->cleanup, from);
|
|
|
|
if (nullChild != NULL) {
|
|
|
|
Lst_AtEnd(args->possible, nullChild);
|
|
|
|
Lst_AtEnd(args->cleanup, nullChild);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
end:
|
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffAddLevelForSuffix -- get possible transformations to target node.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* A new top level Src structure (parent == NULL) is created for target
|
|
|
|
* using the provided suffix. Then Src structures describing all
|
|
|
|
* the possible ways to create the target node are appended into the list
|
|
|
|
* possible. If the target node has multiple known suffixes, this function
|
|
|
|
* should be called for each suffix separately to get all the possible ways
|
|
|
|
* to create the node.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* The top level Src and the possible transformations are added into
|
|
|
|
* cleanup.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Input:
|
|
|
|
* suffix target node's suffix
|
|
|
|
* possible list to add the possible transformations into
|
|
|
|
* (data: Src *)
|
|
|
|
* end desired transformation target
|
|
|
|
* cleanup list of all Srcs for eventual cleanup (data: Src *)
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffAddLevelForSuffix(Suff *suffix, Lst possible, GNode *end, Lst cleanup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Src *s;
|
|
|
|
if (suffix != NULL) {
|
|
|
|
if (suffix->flags & SUFF_NULL)
|
|
|
|
/* Only set when "remove a suffix" aspect of .NULL is used. */
|
|
|
|
s = SuffNewTopSrcNull(end, suffix);
|
|
|
|
else
|
|
|
|
s = SuffNewTopSrc(end, suffix);
|
|
|
|
Lst_AtEnd(cleanup, s);
|
|
|
|
|
|
|
|
SuffAddLevel(possible, s, cleanup);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
2014-08-23 19:05:40 +04:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffAddLevel -- get possible transformations to target Src.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Src structures describing all the possible ways to create target are
|
|
|
|
* appended into the list possible.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* The possible transformations are also added into cleanup.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* possible list to add the possible transformations to
|
|
|
|
* (data: Src *)
|
|
|
|
* target desired transformation target
|
|
|
|
* cleanup list of all Srcs for eventual clean-up (data: Src *)
|
|
|
|
*-----------------------------------------------------------------------
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
SuffAddLevel(Lst possible, Src *target, Lst cleanup) {
|
|
|
|
LstSrc ls;
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
ls.target = target;
|
|
|
|
ls.possible = possible;
|
|
|
|
ls.cleanup = cleanup;
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
Lst_ForEach(target->suff->children, SuffAddSrc, &ls);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffFindThem -- find a transformation chain from a list of possibilities.
|
|
|
|
*
|
|
|
|
* A valid transformation chain is one which starts from an existing
|
|
|
|
* target node or file and can be converted into the desired target by
|
|
|
|
* repeated application of transformation rules. If any such chain
|
|
|
|
* can be found, this function will return the one which is the shortest.
|
|
|
|
* If there are multiple equally short chains, the steps required are
|
|
|
|
* compared, starting from the /last/ one, and on the first differing
|
|
|
|
* step the one whose target suffix occurs first in .SUFFIXES is chosen.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* possible all possible last steps in the transformation,
|
|
|
|
* in the proper .SUFFIXES order
|
|
|
|
* chain (data: Src *)
|
|
|
|
* cleanup list of all Srcs for eventual clean-up (data: Src *)
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
2014-08-23 19:05:40 +04:00
|
|
|
* The starting point of the shortest, highest priority transformation
|
|
|
|
* chain. Taking the node described by the returned value and
|
|
|
|
* applying to it the transformations defined by the parent pointers
|
|
|
|
* will result in the initially desired target.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* If no chain terminates at an existing target or file, NULL is
|
|
|
|
* returned.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Src *
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffFindThem(Lst possible, Lst cleanup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Src *i, *result, *parent;
|
2014-08-27 12:50:38 +04:00
|
|
|
char *tf;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
result = NULL;
|
|
|
|
/*
|
|
|
|
* Parent of the current candidate. When it changes, debug print
|
|
|
|
* the chain of transformations so far.
|
|
|
|
*/
|
|
|
|
parent = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* You've been lied to. There wont be any step priority comparisons.
|
|
|
|
* Because the list initially contains the possible transformations
|
|
|
|
* in the correct order, the first existing one is the correct result.
|
|
|
|
* Each possible transformation is removed from the front of the list
|
|
|
|
* as it is checked and if it does not exist, all the ways to create
|
|
|
|
* it are appended to the list. This way the one step longer chains
|
|
|
|
* are also in the correct priority order and the item at the front
|
|
|
|
* of the list is always the correct result, should it exist. It is
|
|
|
|
* then easy to keep popping the list until the result is found or all
|
|
|
|
* possibilities are exhausted.
|
|
|
|
*/
|
|
|
|
while ((i = (Src *)Lst_DeQueue(possible)) != NULL) {
|
2014-08-27 12:50:38 +04:00
|
|
|
GNode *n;
|
2014-08-23 19:05:40 +04:00
|
|
|
if (parent != i->parent) {
|
|
|
|
SuffDebugChain(i->parent);
|
|
|
|
parent = i->parent;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug ("\t%*.s%s: ", i->depth, " ", i->file);
|
1994-06-07 02:45:17 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* XXX: should only targets with commands be accepted? The node
|
|
|
|
* exists even if it only has had extra dependencies added.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-27 12:50:38 +04:00
|
|
|
if ((n = Targ_FindNode(i->file, TARG_NOCREATE)) != NULL) {
|
1994-06-07 02:45:17 +04:00
|
|
|
#ifdef DEBUG_SRC
|
2014-08-23 19:05:40 +04:00
|
|
|
fprintf(debug_file, "remove %x from %x\n", i, possible);
|
1994-06-07 02:45:17 +04:00
|
|
|
#endif
|
2014-08-27 12:50:38 +04:00
|
|
|
SuffDebug(": Node %s %x: ", i->file, n->type);
|
|
|
|
if ((n->type & OP_INVISIBLE) == 0) {
|
|
|
|
result = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else if ((tf = Dir_FindFile(i->file, i->suff->searchPath)) != NULL) {
|
2014-08-23 19:05:40 +04:00
|
|
|
result = i;
|
1994-06-07 02:45:17 +04:00
|
|
|
#ifdef DEBUG_SRC
|
2014-08-23 19:05:40 +04:00
|
|
|
fprintf(debug_file, "remove %x from %x\n", i, possible);
|
1994-06-07 02:45:17 +04:00
|
|
|
#endif
|
2014-08-27 12:50:38 +04:00
|
|
|
SuffDebug(": File %s %s: ", i->file, tf);
|
|
|
|
free(tf);
|
1994-06-07 02:45:17 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("not there.\n");
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffAddLevel(possible, i, cleanup);
|
1994-06-07 02:45:17 +04:00
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (result)
|
|
|
|
SuffDebug("got it.\n");
|
|
|
|
|
|
|
|
return result;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffExpandChildren -- call SuffExpandChild() on node's children.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* parent parent node
|
|
|
|
* first child to start from
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
static void
|
|
|
|
SuffExpandChildren(GNode *parent, LstNode first)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
LstNode i, next;
|
2004-01-11 20:24:25 +03:00
|
|
|
|
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffExpandChild() replaces the curren node with the expanded values,
|
|
|
|
* so we won't try to expand the already expanded values
|
2004-01-11 20:24:25 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
for (i = first; i != NULL; i = next) {
|
|
|
|
/* SuffExpandChild() might remove i, so get the successor now. */
|
|
|
|
next = Lst_Succ(i);
|
|
|
|
SuffExpandChild(i, parent);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffExpandChild -- expand variables and wildcards in a child name.
|
|
|
|
*
|
|
|
|
* Expand variables and wildcards in a child's name and replace the child
|
|
|
|
* with the results if an expansion happened. This means that when
|
|
|
|
* expansion occurred, cln will point to free'd memory!
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* cln child to expand.
|
|
|
|
* pgn parent node being processed
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
|
|
|
* === 0 (continue)
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2006-10-25 23:44:10 +04:00
|
|
|
static void
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffExpandChild(LstNode cln, GNode *pgn)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2006-10-25 23:44:10 +04:00
|
|
|
GNode *cgn = (GNode *)Lst_Datum(cln);
|
2014-08-23 19:05:40 +04:00
|
|
|
GNode *gn; /* helper for adding expanded nodes */
|
|
|
|
char *expanded; /* expanded child name */
|
|
|
|
char *cp; /* current position in expanded value */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-11-18 01:07:39 +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.
|
|
|
|
*/
|
2006-10-25 23:44:10 +04:00
|
|
|
if (strchr(cgn->name, '$') == NULL) {
|
|
|
|
SuffExpandWildcards(cln, pgn);
|
|
|
|
return;
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("\tVariable expanding dependency `%s'\n", cgn->name);
|
|
|
|
cp = expanded = Var_Subst(NULL, cgn->name, pgn, TRUE);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2006-10-25 23:44:10 +04:00
|
|
|
if (cp != NULL) {
|
|
|
|
Lst members = Lst_Init(FALSE);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-10-25 23:44:10 +04: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...
|
2014-08-23 19:05:40 +04:00
|
|
|
* XXX: what variable specs?! I thought we already expanded
|
|
|
|
* all of the variables and there shouldn't be any variable
|
|
|
|
* expansion stages left before the name is used as target!
|
2006-10-25 23:44:10 +04:00
|
|
|
*/
|
|
|
|
char *start;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2006-10-25 23:44:10 +04: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
|
|
|
/*
|
2006-10-25 23:44:10 +04:00
|
|
|
* White-space -- terminate element, find the node,
|
|
|
|
* add it, skip any further spaces.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-10-25 23:44:10 +04:00
|
|
|
*cp++ = '\0';
|
1993-03-21 12:45:37 +03:00
|
|
|
gn = Targ_FindNode(start, TARG_CREATE);
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(members, gn);
|
2006-10-25 23:44:10 +04:00
|
|
|
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;
|
2008-02-16 00:29:50 +03:00
|
|
|
int len;
|
2006-10-25 23:44:10 +04:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-10-25 23:44:10 +04:00
|
|
|
if (cp != start) {
|
|
|
|
/*
|
|
|
|
* Stuff left over -- add it to the list too
|
|
|
|
*/
|
|
|
|
gn = Targ_FindNode(start, TARG_CREATE);
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(members, gn);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-10-25 23:44:10 +04:00
|
|
|
* Add all elements of the members list to the parent node.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-10-25 23:44:10 +04:00
|
|
|
while(!Lst_IsEmpty(members)) {
|
|
|
|
gn = (GNode *)Lst_DeQueue(members);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("\t\t%s\n", gn->name);
|
2006-10-25 23:44:10 +04:00
|
|
|
/* Add gn to the parents child list before the original child */
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_InsertBefore(pgn->children, cln, gn);
|
2014-08-23 19:05:40 +04:00
|
|
|
if ((GNode *)Lst_Datum(pgn->first_local_child) == cgn)
|
|
|
|
pgn->first_local_child = Lst_Prev(cln);
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(gn->parents, pgn);
|
2006-10-25 23:44:10 +04:00
|
|
|
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
|
|
|
}
|
2008-12-13 18:19:29 +03:00
|
|
|
Lst_Destroy(members, NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
free(expanded);
|
|
|
|
expanded = NULL;
|
2006-10-25 23:44:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2006-10-25 23:44:10 +04:00
|
|
|
if (!Dir_HasWildcards(cgn->name))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Expand the word along the chosen path
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("\tWildcard expanding dependency `%s'\n", cgn->name);
|
2006-10-25 23:44:10 +04:00
|
|
|
explist = Lst_Init(FALSE);
|
|
|
|
Dir_Expand(cgn->name, Suff_FindPath(cgn), explist);
|
|
|
|
|
|
|
|
while (!Lst_IsEmpty(explist)) {
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2006-10-25 23:44:10 +04:00
|
|
|
* Fetch next expansion off the list and find its GNode
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2006-10-25 23:44:10 +04:00
|
|
|
cp = (char *)Lst_DeQueue(explist);
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("\t\t%s\n", cp);
|
2006-10-25 23:44:10 +04:00
|
|
|
gn = Targ_FindNode(cp, TARG_CREATE);
|
|
|
|
|
|
|
|
/* Add gn to the parents child list before the original child */
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_InsertBefore(pgn->children, cln, gn);
|
2014-08-23 19:05:40 +04:00
|
|
|
if ((GNode *)Lst_Datum(pgn->first_local_child) == cgn)
|
|
|
|
pgn->first_local_child = Lst_Prev(cln);
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(gn->parents, pgn);
|
2006-10-25 23:44:10 +04:00
|
|
|
pgn->unmade++;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2006-10-25 23:44:10 +04:00
|
|
|
/*
|
|
|
|
* Nuke what's left of the list
|
|
|
|
*/
|
2008-12-13 18:19:29 +03:00
|
|
|
Lst_Destroy(explist, NULL);
|
2006-10-25 23:44:10 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
|
|
}
|
|
|
|
|
2004-12-29 04:55:25 +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.
|
2004-12-29 03:43:02 +03:00
|
|
|
*
|
2004-12-29 04:55:25 +03:00
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
2004-12-29 03:43:02 +03:00
|
|
|
*/
|
|
|
|
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;
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(sufflist, &sd, SuffSuffIsSuffixP);
|
2004-12-29 03:43:02 +03:00
|
|
|
|
2008-12-13 18:19:29 +03:00
|
|
|
if (ln != NULL)
|
2004-12-29 03:43:02 +03:00
|
|
|
suff = (Suff *)Lst_Datum(ln);
|
|
|
|
/* XXX: Here we can save the suffix so we don't have to do this again */
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (suff != NULL)
|
2004-12-29 03:43:02 +03:00
|
|
|
return suff->searchPath;
|
2014-08-23 19:05:40 +04:00
|
|
|
else
|
2004-12-29 03:43:02 +03:00
|
|
|
return dirSearchPath;
|
2014-08-23 19:05:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffApplyTransformations -- apply a transformation chain.
|
|
|
|
*
|
|
|
|
* Apply transformations beginning at start, until the node end is
|
|
|
|
* reached. A node is created for each intermediate target, if one does
|
|
|
|
* not already exist and the relevant suffixes are set on the nodes.
|
|
|
|
*
|
|
|
|
* Each target except for the start and end of the chain gets TARGET
|
|
|
|
* and PREFIX set and their children expanded. The start of the chain
|
|
|
|
* cannot be expanded as it could turn out to be the result of another
|
|
|
|
* transformation chain and have a different suffix as a part of that
|
|
|
|
* chain. The end of the chain cannot be expanded because the node's
|
|
|
|
* name might be a fake one (see SuffFindArchiveDeps()).
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* start transformation chain's starting
|
|
|
|
* end transformation chain's end, i.e. the node for which we were
|
|
|
|
* initially looking dependencies for
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* The suffix that was set on end.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Suff *
|
|
|
|
SuffApplyTransformations(Src *start, GNode *end)
|
|
|
|
{
|
|
|
|
Src *target, *source;
|
|
|
|
|
|
|
|
if (start->node == NULL)
|
|
|
|
start->node = Targ_FindNode(start->file, TARG_CREATE);
|
|
|
|
|
|
|
|
for (source = start; source->parent != NULL; source = source->parent) {
|
|
|
|
target = source->parent;
|
|
|
|
|
|
|
|
SuffSetSuffix(source->node, source->suff);
|
|
|
|
|
|
|
|
if (target->node == NULL)
|
|
|
|
target->node = Targ_FindNode(target->file, TARG_CREATE);
|
|
|
|
|
|
|
|
if (target->node != end) {
|
|
|
|
/*
|
|
|
|
* Dependency search for intermediate targets is finished:
|
|
|
|
* if they had dependencies to check, they would have
|
|
|
|
* a target or an existing file and therefore wouldn't be
|
|
|
|
* intermediate targets.
|
|
|
|
*/
|
|
|
|
target->node->type |= OP_DEPS_FOUND;
|
|
|
|
Var_Set(TARGET, target->node->name, target->node, 0);
|
|
|
|
Var_Set(PREFIX, target->pref, target->node, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
SuffApplyTransformation(target->node, source->node,
|
|
|
|
target->suff, source->suff,
|
|
|
|
(target->node == end ? SAT_NO_EXPAND : SAT_REGULAR));
|
2004-12-29 03:43:02 +03:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
SuffSetSuffix(end, source->suff);
|
|
|
|
|
|
|
|
return end->suffix;
|
2004-12-29 03:43:02 +03:00
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffApplyTransformation -- apply a transformation from source to target.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* tGn Target node
|
|
|
|
* sGn Source node
|
|
|
|
* t Target suffix
|
|
|
|
* s Source suffix
|
|
|
|
* flags Request modifications for standard behavior.
|
|
|
|
* SAT_REGULAR:
|
|
|
|
* Normal behavior.
|
|
|
|
* SAT_NO_EXPAND:
|
|
|
|
* Do not expand children.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
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
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffApplyTransformation(GNode *tGn, GNode *sGn, Suff *t, Suff *s, int flags)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
LstNode ln; /* General node */
|
1993-03-21 12:45:37 +03:00
|
|
|
char *tname; /* Name of transformation rule */
|
|
|
|
GNode *gn; /* Node for same */
|
|
|
|
|
2000-06-11 11:39:52 +04:00
|
|
|
/*
|
|
|
|
* Form the proper links between the target and source.
|
|
|
|
*/
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(tGn->children, sGn);
|
|
|
|
(void)Lst_AtEnd(sGn->parents, tGn);
|
2000-06-11 11:39:52 +04:00
|
|
|
tGn->unmade += 1;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Locate the transformation rule itself
|
|
|
|
*/
|
|
|
|
tname = str_concat(s->name, t->name, 0);
|
2006-10-28 01:00:18 +04:00
|
|
|
ln = Lst_Find(transforms, tname, SuffGNHasNameP);
|
1993-03-21 12:45:37 +03:00
|
|
|
free(tname);
|
|
|
|
|
|
|
|
gn = (GNode *)Lst_Datum(ln);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("\tApplying `%s' -> `%s' to `%s'\n", s->name, t->name,
|
|
|
|
tGn->name);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/* Record last child so only the new children get expanded. */
|
1993-03-21 12:45:37 +03:00
|
|
|
ln = Lst_Last(tGn->children);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
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
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (!(flags & SAT_NO_EXPAND))
|
|
|
|
SuffExpandChildren(tGn, Lst_Succ(ln));
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Keep track of another parent to which this beast is transformed so
|
|
|
|
* the .IMPSRC variable can be set correctly for the parent.
|
|
|
|
*/
|
2006-10-28 01:00:18 +04:00
|
|
|
(void)Lst_AtEnd(sGn->iParents, tGn);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffFirstKnownSuffix -- find the first suffix that fits name.
|
|
|
|
*
|
|
|
|
* Used by SuffFindArchiveDeps() and SuffFindNormalDeps() to figure
|
|
|
|
* out suffixes for explicit rules.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* name The name to try the suffixes on.
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* The first matching suffix structure or NULL if there isn't one.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static Suff*
|
|
|
|
SuffFirstKnownSuffix(char* name)
|
|
|
|
{
|
|
|
|
LstNode ln;
|
|
|
|
SuffixCmpData sd;
|
|
|
|
|
|
|
|
sd.len = strlen(name);
|
|
|
|
sd.ename = name + sd.len;
|
|
|
|
|
|
|
|
ln = Lst_Find(sufflist, &sd, SuffSuffIsSuffixP);
|
|
|
|
return (ln == NULL ? NULL : (Suff *)Lst_Datum(ln));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffSetPrefixLocalVar -- set .PREFIX properly on target.
|
|
|
|
*
|
|
|
|
* The value of the .PREFIX variable is the node's name less suffix->name.
|
|
|
|
* Used by SuffFindArchiveDeps() and SuffFindNormalDeps().
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* suffix The suffix structure to base the prefix on. If it is NULL,
|
|
|
|
* the whole name is used.
|
|
|
|
* name The name to get the prefix from, as it is not necessarily
|
|
|
|
* the node's name.
|
|
|
|
* node The context to set the variable in.
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffSetPrefixLocalVar(Suff *suffix, char *name, GNode *node)
|
|
|
|
{
|
|
|
|
if (suffix != NULL) {
|
|
|
|
char save, *save_pos;
|
|
|
|
|
|
|
|
save_pos = name + (strlen(name) - suffix->nameLen);
|
|
|
|
save = *save_pos;
|
|
|
|
*save_pos = '\0';
|
|
|
|
Var_Set(PREFIX, name, node, 0);
|
|
|
|
*save_pos = save;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Var_Set(PREFIX, name, node, 0);
|
|
|
|
}
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* SuffFindArchiveDeps --
|
|
|
|
* Locate dependencies for an OP_ARCHV node.
|
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* target Node for which to locate dependencies
|
|
|
|
* cleanup List to add all created Srcs into, so the caller can
|
|
|
|
* destroy them.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
|
|
|
* None
|
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* Same as Suff_FindDeps. ARCHIVE and MEMBER variables are set as
|
|
|
|
* well as gn->type is modified to include OP_MEMBER
|
|
|
|
* on the relevant nodes and are so the modifications
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffFindArchiveDeps(GNode *target, Lst cleanup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Lst possible; /* Possible transformation starting points. */
|
|
|
|
Src *start; /* The start of the chain of transformations that
|
|
|
|
* results in this target being built. */
|
|
|
|
Suff *suffix; /* Suffix of the member. */
|
|
|
|
char *temp;
|
|
|
|
|
|
|
|
char *lib, *member; /* Copies of lib and member parts, */
|
|
|
|
char *libEnd, *memberEnd; /* their terminating NULs, and */
|
|
|
|
size_t libLen, memberLen; /* their lengths. */
|
|
|
|
|
|
|
|
possible = Lst_Init(FALSE);
|
|
|
|
start = NULL;
|
|
|
|
suffix = NULL;
|
|
|
|
|
|
|
|
lib = target->name;
|
|
|
|
member = strchr(lib, '(') + 1;
|
|
|
|
libLen = member - target->name - 1;
|
|
|
|
memberLen = strchr(member, ')') - member;
|
|
|
|
|
|
|
|
lib = bmake_strndup(lib, libLen);
|
|
|
|
member = bmake_strndup(member, memberLen);
|
|
|
|
libEnd = lib + libLen;
|
|
|
|
memberEnd = member + memberLen;
|
1996-11-06 20:58:58 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Explicit rules always take precedence. Explicit <=> appeared as
|
|
|
|
* a target in a rule with commands.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (!OP_NOP(target->type) && !Lst_IsEmpty(target->commands)) {
|
|
|
|
SuffDebug("\tIt has an explicit rule.\n");
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
suffix = SuffFirstKnownSuffix(member);
|
|
|
|
goto expand_children;
|
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Try with POSIX semantics first, if applicable: library rules are only
|
|
|
|
* supported for "lib(member.o)" and ".s2.a" is the transformation rule
|
|
|
|
* from "member.s2" to "lib(member.o)", regardless of the suffix, if any,
|
|
|
|
* "lib" might have. We pretend to be "member.a" and look for
|
|
|
|
* transformations.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (memberLen > 2 && strcmp(memberEnd - 2, ".o") == 0) {
|
|
|
|
LstNode ln;
|
|
|
|
SuffDebug("\tTrying POSIX \".s2.a\" transformation.\n");
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
*(memberEnd - 1) = 'a';
|
|
|
|
temp = target->name; target->name = member;
|
|
|
|
ln = Lst_Find(sufflist, ".a", SuffSuffHasNameP);
|
|
|
|
SuffAddLevelForSuffix((ln == NULL ? NULL : (Suff *)Lst_Datum(ln)),
|
|
|
|
possible, target, cleanup);
|
|
|
|
target->name = temp;
|
|
|
|
*(memberEnd - 1) = 'o';
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
start = SuffFindThem(possible, cleanup);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Given lib.s2(member.s1), if a ".s1.s2" transformation exists, try
|
|
|
|
* to find a way to make member.s1 so it could be added to lib.s2.
|
|
|
|
* The problem is, all suffixes are accepted, not just POSIX ones
|
|
|
|
* (\.[^./]+), so more than one may match either lib or member and
|
|
|
|
* not all permutations are valid.
|
|
|
|
*
|
|
|
|
* Here are a couple of examples of what has to be taken into account.
|
|
|
|
* Consider "lib.a.b(member.c)" in a case where "member.d" exists, and
|
|
|
|
* with ".SUFFIXES: .b .a.b .c .d". The transformations are ".d.c" and
|
|
|
|
* ".c.b". If one were to swap the longest suffixes and try with
|
|
|
|
* "member.a.b", the transformation would not be found. Now consider
|
|
|
|
* if the transformation ".d.a.b" also existed. If one were to try
|
|
|
|
* in order each suffix of the lib against each suffix of the member
|
|
|
|
* and take the first one that works, the chain ".d" -> ".c" -> ".b"
|
|
|
|
* would be found but traditionally transformations choose the shortest
|
|
|
|
* chain, which would be ".d" -> ".a.b".
|
|
|
|
*
|
|
|
|
* These issues mean that trying to shoehorn SuffFindNormalDeps()
|
|
|
|
* to be useful here would be more trouble than it is worth. Gladly
|
|
|
|
* that use would have mainly been as a frontend for SuffFindThem() and
|
|
|
|
* SuffApplyTransformations() and things actually become cleaner if
|
|
|
|
* they are used directly.
|
|
|
|
*
|
|
|
|
* Single suffix rules are not acceptable because they're usually used
|
|
|
|
* to create executables.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (start == NULL) {
|
|
|
|
/* One set for lib (l) and one for member (m). */
|
|
|
|
LstNode l, m; /* Suffix list iterators. */
|
|
|
|
SuffixCmpData ld, md; /* Parameters for predicates. */
|
|
|
|
Suff *ls, *ms; /* Current suffix. */
|
|
|
|
|
|
|
|
SuffDebug("\tTrying \".s1.s2\" transformation extension.\n");
|
|
|
|
|
|
|
|
ld.len = libLen;
|
|
|
|
ld.ename = libEnd;
|
|
|
|
md.len = memberLen;
|
|
|
|
md.ename = memberEnd;
|
|
|
|
|
|
|
|
/* Get all possible transformations from member to lib. */
|
|
|
|
for (l = Lst_Find(sufflist, &ld, SuffSuffIsSuffixP); l != NULL;
|
|
|
|
l = Lst_FindFrom(sufflist, Lst_Succ(l), &ld, SuffSuffIsSuffixP))
|
|
|
|
{
|
|
|
|
ls = ((Suff *)Lst_Datum(l));
|
|
|
|
|
|
|
|
for (m = Lst_Find(ls->children, &md, SuffSuffIsSuffixP);
|
|
|
|
m != NULL;
|
|
|
|
m = Lst_FindFrom(ls->children, Lst_Succ(m), &md,
|
|
|
|
SuffSuffIsSuffixP))
|
|
|
|
{
|
|
|
|
char *fakename, save, *save_pos;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
ms = (Suff *)Lst_Datum(m);
|
|
|
|
save_pos = memberEnd - ms->nameLen;
|
|
|
|
save = *save_pos;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
*save_pos = '\0';
|
|
|
|
fakename = str_concat(member, ls->name, 0);
|
|
|
|
*save_pos = save;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
temp = target->name; target->name = fakename;
|
|
|
|
SuffAddLevelForSuffix(ms, possible, target, cleanup);
|
|
|
|
target->name = temp;
|
|
|
|
free(fakename);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
|
|
|
|
start = SuffFindThem(possible, cleanup);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (start != NULL)
|
|
|
|
suffix = SuffApplyTransformations(start, target);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
expand_children:
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* POSIX: in a lib(member.o) and a .s2.a rule, the values for
|
|
|
|
* the local variables are:
|
|
|
|
* $* = member $@ = lib $? = member.s2 $% = member.o.
|
|
|
|
* Additionally, for the .s2.a inference rule:
|
|
|
|
* $< = member.s2
|
|
|
|
*
|
|
|
|
* ARCHIVE and MEMBER are used by Arch_MTime() to find the modification
|
|
|
|
* time.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
Var_Set(ARCHIVE, lib, target, 0);
|
|
|
|
Var_Set(MEMBER, member, target, 0);
|
|
|
|
Var_Set(TARGET, lib, target, 0);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (suffix == NULL && memberLen > 2 && strcmp(memberEnd - 2, ".o") == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* POSIX compatibility: in case ".o" was not a known suffix, force it.
|
|
|
|
* The target is not POSIX compliant if a suffix other than ".o" was
|
|
|
|
* already matched, so there's no need to try to force e.g. ".fo.o"
|
|
|
|
* or "o" into ".o". (Compliant suffixes start with a period
|
|
|
|
* and contain neither periods nor slashes.)
|
|
|
|
*/
|
|
|
|
*(memberEnd - 2) = '\0';
|
|
|
|
Var_Set(PREFIX, member, target, 0);
|
|
|
|
*(memberEnd - 2) = '.';
|
|
|
|
} else
|
|
|
|
SuffSetPrefixLocalVar(suffix, member, target);
|
|
|
|
|
|
|
|
SuffExpandChildren(target, Lst_First(target->children));
|
|
|
|
|
|
|
|
free(lib);
|
|
|
|
free(member);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* SuffFindNormalDeps -- locate dependencies for regular targets.
|
|
|
|
*
|
|
|
|
* If the target does not have an explicit rule a suffix transformation
|
|
|
|
* rule search is performed to see if it can be inferred.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* target Node for which to find sources.
|
|
|
|
* cleanup List to add all created Srcs into, so the caller can
|
|
|
|
* destroy them.
|
2002-06-15 22:24:55 +04:00
|
|
|
*
|
1993-03-21 12:45:37 +03:00
|
|
|
* Results:
|
|
|
|
* None.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* Same as Suff_FindDeps.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
static void
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffFindNormalDeps(GNode *target, Lst cleanup)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
Lst possible; /* List of possible transformations (Src). */
|
|
|
|
Suff *suffix; /* The suffix that applies to target. */
|
|
|
|
Src *bottom; /* Start of found transformation chain. */
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
possible = Lst_Init(FALSE);
|
|
|
|
suffix = NULL;
|
2013-05-18 17:13:34 +04:00
|
|
|
bottom = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Explicit rules always take precedence. Explicit <=> appeared as
|
|
|
|
* a target in a rule with commands.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (!OP_NOP(target->type) && !Lst_IsEmpty(target->commands)) {
|
|
|
|
SuffDebug("\tIt has an explicit rule.\n");
|
|
|
|
suffix = SuffFirstKnownSuffix(target->name);
|
|
|
|
goto expand_children;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Try transformation rules. They're used to make files from other files,
|
|
|
|
* so don't try them for .PHONY targets, which are not actual files.
|
|
|
|
* All suffixes are accepted, not just POSIX ones (\.[^./]+), so more
|
|
|
|
* than one may match. Matching ones are collected in .SUFFIXES order
|
|
|
|
* and the one to give the shortest working chain is used for creating
|
|
|
|
* the missing links and setting PREFIX. In the case that at least one
|
|
|
|
* suffix matched but none resulted in a chain, use the first one to set
|
|
|
|
* PREFIX.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
if (!(target->type & OP_PHONY)) {
|
|
|
|
LstNode ln;
|
|
|
|
SuffixCmpData sd;
|
|
|
|
|
|
|
|
sd.len = strlen(target->name);
|
|
|
|
sd.ename = target->name + sd.len;
|
|
|
|
|
|
|
|
SuffDebug("\tTrying double suffix transformations.\n");
|
|
|
|
for (ln = Lst_Find(sufflist, &sd, SuffSuffIsSuffixP); ln != NULL;
|
|
|
|
ln = Lst_FindFrom(sufflist, Lst_Succ(ln), &sd, SuffSuffIsSuffixP))
|
|
|
|
{
|
|
|
|
if (suffix == NULL)
|
|
|
|
suffix = (Suff *)Lst_Datum(ln);
|
|
|
|
SuffAddLevelForSuffix((Suff *)Lst_Datum(ln), possible, target,
|
|
|
|
cleanup);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (suffix == NULL) {
|
|
|
|
SuffDebug("\tNo known suffix, trying single suffix "
|
|
|
|
"transformations.\n");
|
|
|
|
SuffAddLevelForSuffix(emptySuff, possible, target, cleanup);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (nullSuff != NULL) {
|
|
|
|
SuffDebug("\tTrying with .NULL too.\n");
|
|
|
|
nullSuff->flags |= SUFF_NULL;
|
|
|
|
SuffAddLevelForSuffix(nullSuff, possible, target, cleanup);
|
|
|
|
nullSuff->flags &= ~SUFF_NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
bottom = SuffFindThem(possible, cleanup);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (bottom != NULL) {
|
|
|
|
suffix = SuffApplyTransformations(bottom, target);
|
|
|
|
} else {
|
|
|
|
/* If there's no transformation, try search paths. */
|
|
|
|
SuffDebug("\tNo transformations, trying path search.\n");
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if ((target->type & (OP_PHONY|OP_NOPATH)) == 0) {
|
|
|
|
free(target->path);
|
|
|
|
target->path = Dir_FindFile(target->name,
|
|
|
|
(suffix == NULL ? dirSearchPath : suffix->searchPath));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
expand_children:
|
|
|
|
SuffSetSuffix(target, suffix);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
Var_Set(TARGET, (target->path ? target->path : target->name), target, 0);
|
|
|
|
if (bottom != NULL)
|
|
|
|
/* Only because of nullSuff: use "" instead of the real suffix. */
|
|
|
|
SuffSetPrefixLocalVar(NULL, bottom->pref, target);
|
|
|
|
else
|
|
|
|
SuffSetPrefixLocalVar(target->suffix, target->name, target);
|
1994-06-07 02:45:17 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffExpandChildren(target, Lst_First(target->children));
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
1996-11-06 20:58:58 +03:00
|
|
|
|
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_FindDeps --
|
2014-08-23 19:05:40 +04:00
|
|
|
* Do suffix transformation rule search for the given target.
|
|
|
|
* Explicit rules always take precedence, so the search will not be
|
|
|
|
* done, if an explicit rule is detected.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* gn node to check inference rules for
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* Nothing.
|
|
|
|
*
|
|
|
|
* Side Effects:
|
2014-08-23 19:05:40 +04:00
|
|
|
* Nodes may be added as dependencies to the target if implied so
|
|
|
|
* by suffix search. Any newly created nodes are also added to
|
|
|
|
* the graph. The implied sources are linked via their iParents
|
|
|
|
* field to the target that uses them so the target will get its
|
|
|
|
* IMPSRC variable filled in properly later.
|
|
|
|
*
|
|
|
|
* The TARGET, PREFIX, ARCHIVE and MEMBER variables get set on
|
|
|
|
* the target and its children as needed.
|
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
|
2014-08-23 19:05:40 +04:00
|
|
|
* root suffix until a file or an existing target node 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
|
|
|
*
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
1994-06-07 02:45:17 +04:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
void
|
2014-08-23 19:05:40 +04:00
|
|
|
Suff_FindDeps(GNode *target)
|
1994-06-07 02:45:17 +04:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
* Storage for all Src structures created during the search. This is
|
|
|
|
* purely a convenience for the implementation of the helper functions.
|
|
|
|
* This way there does not need to be logic for deciding what is safe
|
|
|
|
* to remove and what is not. After the search is complete, they can
|
|
|
|
* all be safely removed.
|
|
|
|
*/
|
|
|
|
Lst cleanup = Lst_Init(FALSE);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (target->type & OP_DEPS_FOUND) {
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
|
|
|
* If dependencies already found, no need to do it again...
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
} else {
|
2014-08-23 19:05:40 +04:00
|
|
|
target->type |= OP_DEPS_FOUND;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2011-09-30 03:38:04 +04:00
|
|
|
/*
|
|
|
|
* Make sure we have these set, may get revised below.
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
Var_Set(TARGET, target->path ? target->path : target->name, target, 0);
|
|
|
|
Var_Set(PREFIX, target->name, target, 0);
|
2013-05-18 17:13:34 +04:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffDebug("SuffFindDeps (%s)\n", target->name);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
if (target->type & OP_ARCHV)
|
|
|
|
SuffFindArchiveDeps(target, cleanup);
|
|
|
|
else if (target->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).
|
2014-08-23 19:05:40 +04:00
|
|
|
* XXX: try all suffixes with SUFF_LIBRARY set?
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
|
|
|
LstNode ln;
|
|
|
|
Suff *s;
|
1996-11-06 20:58:58 +03:00
|
|
|
|
2009-01-24 00:58:27 +03:00
|
|
|
ln = Lst_Find(sufflist, LIBSUFF, SuffSuffHasNameP);
|
2014-08-23 19:05:40 +04:00
|
|
|
s = (ln == NULL ? NULL : (Suff *)Lst_Datum(ln));
|
|
|
|
SuffSetSuffix(target, s);
|
|
|
|
if (s != NULL)
|
|
|
|
Arch_FindLib(target, s->searchPath);
|
|
|
|
else
|
|
|
|
Var_Set(TARGET, target->name, target, 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...
|
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
Var_Set(PREFIX, "", target, 0);
|
|
|
|
} else
|
|
|
|
SuffFindNormalDeps(target, cleanup);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
Lst_Destroy(cleanup, SuffFreeSrc);
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* Suff_SetNull -- define which suffix is the .NULL suffix.
|
1993-03-21 12:45:37 +03:00
|
|
|
*
|
2002-06-15 22:24:55 +04:00
|
|
|
* Input:
|
2014-08-23 19:05:40 +04:00
|
|
|
* name Name of null suffix
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_SetNull(char *name)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
LstNode i;
|
|
|
|
|
|
|
|
i = Lst_Find(sufflist, name, SuffSuffHasNameP);
|
|
|
|
if (i != NULL) {
|
|
|
|
if (nullSuff != NULL)
|
|
|
|
--nullSuff->refCount;
|
|
|
|
nullSuff = (Suff *)Lst_Datum(i);
|
|
|
|
++nullSuff->refCount;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
2014-08-23 19:05:40 +04:00
|
|
|
else
|
|
|
|
Parse_Error(PARSE_WARNING,
|
|
|
|
".NULL not set because %s is not in .SUFFIXES.", name);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*-
|
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
* Suff_Init --
|
2014-08-23 19:05:40 +04:00
|
|
|
* Initialize suffixes module so all of its services can be used.
|
1993-03-21 12:45:37 +03:00
|
|
|
*-----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_Init(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-02-16 18:11:52 +03:00
|
|
|
sufflist = Lst_Init(FALSE);
|
1993-03-21 12:45:37 +03:00
|
|
|
/*
|
2014-08-23 19:05:40 +04:00
|
|
|
* Do explicit initialization for .SUFFIXES related things with static
|
|
|
|
* initialization because we get called by Suff_ClearSuffixes() too.
|
1993-03-21 12:45:37 +03:00
|
|
|
*/
|
2014-08-23 19:05:40 +04:00
|
|
|
sNum = 0;
|
|
|
|
memset(lookup, 0, sizeof(lookup[0]) * LOOKUP_SIZE);
|
|
|
|
|
|
|
|
transforms = Lst_Init(FALSE);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
emptySuff = SuffNewSuff("");
|
|
|
|
emptySuff->sNum = INT_MAX;
|
|
|
|
++emptySuff->refCount;
|
|
|
|
Dir_Concat(emptySuff->searchPath, dirSearchPath);
|
|
|
|
|
|
|
|
nullSuff = NULL;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-03-23 03:52:13 +03:00
|
|
|
|
|
|
|
/*-
|
1994-06-07 02:45:17 +04:00
|
|
|
*----------------------------------------------------------------------
|
2014-08-23 19:05:40 +04:00
|
|
|
* Suff_End -- release resources used by the module.
|
1994-03-23 03:52:13 +03:00
|
|
|
*
|
2014-08-23 19:05:40 +04:00
|
|
|
* It is not safe to call functions from this module after calling this.
|
1994-06-07 02:45:17 +04:00
|
|
|
*----------------------------------------------------------------------
|
1994-03-23 03:52:13 +03:00
|
|
|
*/
|
1994-06-07 02:45:17 +04:00
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_End(void)
|
1994-03-23 03:52:13 +03:00
|
|
|
{
|
1999-09-15 12:43:21 +04:00
|
|
|
#ifdef CLEANUP
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffCleanUp(SCU_END);
|
1999-09-15 12:43:21 +04:00
|
|
|
#endif
|
1994-03-23 03:52:13 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Debugging Functions
|
|
|
|
******************************************************************************
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
* SuffDebug -- print a message to debug_file if debugging is enabled.
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* fmt printf format specification
|
|
|
|
* ... print arguments
|
|
|
|
*
|
|
|
|
* Results:
|
|
|
|
* See vfprintf().
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
SuffDebug(const char * fmt, ...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = 0;
|
|
|
|
if (DEBUG(SUFF)) {
|
|
|
|
va_start(ap, fmt);
|
|
|
|
rv = vfprintf(debug_file, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
* SuffDebugChain -- print transformation chain to debug_file.
|
|
|
|
*
|
|
|
|
* Print the transformation chain that begins with start in reverse
|
|
|
|
* order (end result first). Each suffix in the chain is printed
|
|
|
|
* on one line separated by " <- ".
|
|
|
|
*
|
|
|
|
* Input:
|
|
|
|
* start chain's first transformation
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
SuffDebugChain(Src *start)
|
|
|
|
{
|
|
|
|
if (DEBUG(SUFF)){
|
|
|
|
Lst tmp = Lst_Init(FALSE);
|
|
|
|
Src *i;
|
|
|
|
LstNode j;
|
|
|
|
|
|
|
|
for (i = start; i != NULL; i = i->parent)
|
|
|
|
Lst_AtFront(tmp, i);
|
|
|
|
fprintf(debug_file, "\t");
|
|
|
|
for (j = Lst_First(tmp); j != NULL; j = Lst_Succ(j)) {
|
|
|
|
i = (Src *)Lst_Datum(j);
|
|
|
|
fprintf(debug_file, "`%s' <- ", i->suff->name);
|
|
|
|
}
|
|
|
|
fprintf(debug_file, "\n");
|
|
|
|
|
|
|
|
Lst_Destroy(tmp, NULL);
|
|
|
|
}
|
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
static int SuffPrintName(void *s, void *unused)
|
1994-06-07 02:45:17 +04:00
|
|
|
{
|
2014-08-23 19:05:40 +04:00
|
|
|
(void)unused;
|
|
|
|
fprintf(debug_file, "`%s' ", ((Suff *)s)->name);
|
|
|
|
return 0;
|
1994-06-07 02:45:17 +04:00
|
|
|
}
|
1993-03-21 12:45:37 +03:00
|
|
|
|
|
|
|
static int
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffPrintSuff(void *sp, void *unused)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-08-08 20:42:54 +04:00
|
|
|
Suff *s = (Suff *)sp;
|
1993-03-21 12:45:37 +03:00
|
|
|
int flags;
|
|
|
|
int flag;
|
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
(void)unused;
|
|
|
|
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount);
|
1996-11-06 20:58:58 +03:00
|
|
|
|
1993-03-21 12:45:37 +03:00
|
|
|
flags = s->flags;
|
|
|
|
if (flags) {
|
2008-02-16 00:29:50 +03:00
|
|
|
fputs(" (", debug_file);
|
1993-03-21 12:45:37 +03:00
|
|
|
while (flags) {
|
|
|
|
flag = 1 << (ffs(flags) - 1);
|
|
|
|
flags &= ~flag;
|
|
|
|
switch (flag) {
|
|
|
|
case SUFF_INCLUDE:
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "INCLUDE");
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
case SUFF_LIBRARY:
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "LIBRARY");
|
1993-03-21 12:45:37 +03:00
|
|
|
break;
|
|
|
|
}
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc(flags ? '|' : ')', debug_file);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
}
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
|
|
|
fprintf(debug_file, "#\tTo: ");
|
2006-10-28 01:00:18 +04:00
|
|
|
Lst_ForEach(s->parents, SuffPrintName, NULL);
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
|
|
|
fprintf(debug_file, "#\tFrom: ");
|
2006-10-28 01:00:18 +04:00
|
|
|
Lst_ForEach(s->children, SuffPrintName, NULL);
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
|
|
|
fprintf(debug_file, "#\tSearch Path: ");
|
2005-02-16 18:11:52 +03:00
|
|
|
Dir_PrintPath(s->searchPath);
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
2014-08-23 19:05:40 +04:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffPrintTrans(void *tp, void *unused)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2005-08-08 20:42:54 +04:00
|
|
|
GNode *t = (GNode *)tp;
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2014-08-23 19:05:40 +04:00
|
|
|
(void)unused;
|
|
|
|
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "%-16s: ", t->name);
|
2005-02-16 18:11:52 +03:00
|
|
|
Targ_PrintType(t->type);
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
2006-10-28 01:00:18 +04:00
|
|
|
Lst_ForEach(t->commands, Targ_PrintCmd, NULL);
|
2008-02-16 00:29:50 +03:00
|
|
|
fputc('\n', debug_file);
|
2014-08-23 19:05:40 +04:00
|
|
|
return 0;
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|
|
|
|
|
1994-03-05 03:34:29 +03:00
|
|
|
void
|
2002-06-15 22:24:55 +04:00
|
|
|
Suff_PrintAll(void)
|
1993-03-21 12:45:37 +03:00
|
|
|
{
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "#*** Suffixes:\n");
|
2006-10-28 01:00:18 +04:00
|
|
|
Lst_ForEach(sufflist, SuffPrintSuff, NULL);
|
2014-08-23 19:05:40 +04:00
|
|
|
SuffPrintSuff(emptySuff, NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
|
2008-02-16 00:29:50 +03:00
|
|
|
fprintf(debug_file, "#*** Transformations:\n");
|
2006-10-28 01:00:18 +04:00
|
|
|
Lst_ForEach(transforms, SuffPrintTrans, NULL);
|
1993-03-21 12:45:37 +03:00
|
|
|
}
|