1*2c3632d1SSimon J. Gerraty /* $NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 rillig Exp $ */ 23955d011SMarcel Moolenaar 33955d011SMarcel Moolenaar /* 43955d011SMarcel Moolenaar * Copyright (c) 1988, 1989, 1990, 1993 53955d011SMarcel Moolenaar * The Regents of the University of California. All rights reserved. 63955d011SMarcel Moolenaar * 73955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 83955d011SMarcel Moolenaar * Adam de Boor. 93955d011SMarcel Moolenaar * 103955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 113955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 123955d011SMarcel Moolenaar * are met: 133955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 143955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 153955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 163955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 173955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 183955d011SMarcel Moolenaar * 3. Neither the name of the University nor the names of its contributors 193955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 203955d011SMarcel Moolenaar * without specific prior written permission. 213955d011SMarcel Moolenaar * 223955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 233955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 243955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 253955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 263955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 273955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 283955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 293955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 303955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 313955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 323955d011SMarcel Moolenaar * SUCH DAMAGE. 333955d011SMarcel Moolenaar */ 343955d011SMarcel Moolenaar 353955d011SMarcel Moolenaar /* 363955d011SMarcel Moolenaar * Copyright (c) 1989 by Berkeley Softworks 373955d011SMarcel Moolenaar * All rights reserved. 383955d011SMarcel Moolenaar * 393955d011SMarcel Moolenaar * This code is derived from software contributed to Berkeley by 403955d011SMarcel Moolenaar * Adam de Boor. 413955d011SMarcel Moolenaar * 423955d011SMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 433955d011SMarcel Moolenaar * modification, are permitted provided that the following conditions 443955d011SMarcel Moolenaar * are met: 453955d011SMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 463955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer. 473955d011SMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 483955d011SMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 493955d011SMarcel Moolenaar * documentation and/or other materials provided with the distribution. 503955d011SMarcel Moolenaar * 3. All advertising materials mentioning features or use of this software 513955d011SMarcel Moolenaar * must display the following acknowledgement: 523955d011SMarcel Moolenaar * This product includes software developed by the University of 533955d011SMarcel Moolenaar * California, Berkeley and its contributors. 543955d011SMarcel Moolenaar * 4. Neither the name of the University nor the names of its contributors 553955d011SMarcel Moolenaar * may be used to endorse or promote products derived from this software 563955d011SMarcel Moolenaar * without specific prior written permission. 573955d011SMarcel Moolenaar * 583955d011SMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 593955d011SMarcel Moolenaar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 603955d011SMarcel Moolenaar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 613955d011SMarcel Moolenaar * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 623955d011SMarcel Moolenaar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 633955d011SMarcel Moolenaar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 643955d011SMarcel Moolenaar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 653955d011SMarcel Moolenaar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 663955d011SMarcel Moolenaar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 673955d011SMarcel Moolenaar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 683955d011SMarcel Moolenaar * SUCH DAMAGE. 693955d011SMarcel Moolenaar */ 703955d011SMarcel Moolenaar 713955d011SMarcel Moolenaar #ifndef MAKE_NATIVE 72*2c3632d1SSimon J. Gerraty static char rcsid[] = "$NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 rillig Exp $"; 733955d011SMarcel Moolenaar #else 743955d011SMarcel Moolenaar #include <sys/cdefs.h> 753955d011SMarcel Moolenaar #ifndef lint 763955d011SMarcel Moolenaar #if 0 773955d011SMarcel Moolenaar static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; 783955d011SMarcel Moolenaar #else 79*2c3632d1SSimon J. Gerraty __RCSID("$NetBSD: suff.c,v 1.142 2020/08/31 16:44:25 rillig Exp $"); 803955d011SMarcel Moolenaar #endif 813955d011SMarcel Moolenaar #endif /* not lint */ 823955d011SMarcel Moolenaar #endif 833955d011SMarcel Moolenaar 843955d011SMarcel Moolenaar /*- 853955d011SMarcel Moolenaar * suff.c -- 863955d011SMarcel Moolenaar * Functions to maintain suffix lists and find implicit dependents 873955d011SMarcel Moolenaar * using suffix transformation rules 883955d011SMarcel Moolenaar * 893955d011SMarcel Moolenaar * Interface: 903955d011SMarcel Moolenaar * Suff_Init Initialize all things to do with suffixes. 913955d011SMarcel Moolenaar * 923955d011SMarcel Moolenaar * Suff_End Cleanup the module 933955d011SMarcel Moolenaar * 943955d011SMarcel Moolenaar * Suff_DoPaths This function is used to make life easier 953955d011SMarcel Moolenaar * when searching for a file according to its 963955d011SMarcel Moolenaar * suffix. It takes the global search path, 973955d011SMarcel Moolenaar * as defined using the .PATH: target, and appends 983955d011SMarcel Moolenaar * its directories to the path of each of the 993955d011SMarcel Moolenaar * defined suffixes, as specified using 1003955d011SMarcel Moolenaar * .PATH<suffix>: targets. In addition, all 1013955d011SMarcel Moolenaar * directories given for suffixes labeled as 1023955d011SMarcel Moolenaar * include files or libraries, using the .INCLUDES 1033955d011SMarcel Moolenaar * or .LIBS targets, are played with using 1043955d011SMarcel Moolenaar * Dir_MakeFlags to create the .INCLUDES and 1053955d011SMarcel Moolenaar * .LIBS global variables. 1063955d011SMarcel Moolenaar * 1073955d011SMarcel Moolenaar * Suff_ClearSuffixes Clear out all the suffixes and defined 1083955d011SMarcel Moolenaar * transformations. 1093955d011SMarcel Moolenaar * 1103955d011SMarcel Moolenaar * Suff_IsTransform Return TRUE if the passed string is the lhs 1113955d011SMarcel Moolenaar * of a transformation rule. 1123955d011SMarcel Moolenaar * 1133955d011SMarcel Moolenaar * Suff_AddSuffix Add the passed string as another known suffix. 1143955d011SMarcel Moolenaar * 1153955d011SMarcel Moolenaar * Suff_GetPath Return the search path for the given suffix. 1163955d011SMarcel Moolenaar * 1173955d011SMarcel Moolenaar * Suff_AddInclude Mark the given suffix as denoting an include 1183955d011SMarcel Moolenaar * file. 1193955d011SMarcel Moolenaar * 1203955d011SMarcel Moolenaar * Suff_AddLib Mark the given suffix as denoting a library. 1213955d011SMarcel Moolenaar * 1223955d011SMarcel Moolenaar * Suff_AddTransform Add another transformation to the suffix 1233955d011SMarcel Moolenaar * graph. Returns GNode suitable for framing, I 1243955d011SMarcel Moolenaar * mean, tacking commands, attributes, etc. on. 1253955d011SMarcel Moolenaar * 1263955d011SMarcel Moolenaar * Suff_SetNull Define the suffix to consider the suffix of 1273955d011SMarcel Moolenaar * any file that doesn't have a known one. 1283955d011SMarcel Moolenaar * 1293955d011SMarcel Moolenaar * Suff_FindDeps Find implicit sources for and the location of 1303955d011SMarcel Moolenaar * a target based on its suffix. Returns the 1313955d011SMarcel Moolenaar * bottom-most node added to the graph or NULL 1323955d011SMarcel Moolenaar * if the target had no implicit sources. 1333955d011SMarcel Moolenaar * 1343955d011SMarcel Moolenaar * Suff_FindPath Return the appropriate path to search in 1353955d011SMarcel Moolenaar * order to find the node. 1363955d011SMarcel Moolenaar */ 1373955d011SMarcel Moolenaar 1383955d011SMarcel Moolenaar #include "make.h" 1393955d011SMarcel Moolenaar #include "dir.h" 1403955d011SMarcel Moolenaar 141*2c3632d1SSimon J. Gerraty #define SUFF_DEBUG0(fmt) \ 142*2c3632d1SSimon J. Gerraty if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt) 143*2c3632d1SSimon J. Gerraty 144*2c3632d1SSimon J. Gerraty #define SUFF_DEBUG1(fmt, arg1) \ 145*2c3632d1SSimon J. Gerraty if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1) 146*2c3632d1SSimon J. Gerraty 147*2c3632d1SSimon J. Gerraty #define SUFF_DEBUG2(fmt, arg1, arg2) \ 148*2c3632d1SSimon J. Gerraty if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2) 149*2c3632d1SSimon J. Gerraty 150*2c3632d1SSimon J. Gerraty #define SUFF_DEBUG3(fmt, arg1, arg2, arg3) \ 151*2c3632d1SSimon J. Gerraty if (!DEBUG(SUFF)) (void) 0; else fprintf(debug_file, fmt, arg1, arg2, arg3) 152*2c3632d1SSimon J. Gerraty 1533955d011SMarcel Moolenaar static Lst sufflist; /* Lst of suffixes */ 1543955d011SMarcel Moolenaar #ifdef CLEANUP 1553955d011SMarcel Moolenaar static Lst suffClean; /* Lst of suffixes to be cleaned */ 1563955d011SMarcel Moolenaar #endif 1573955d011SMarcel Moolenaar static Lst srclist; /* Lst of sources */ 1583955d011SMarcel Moolenaar static Lst transforms; /* Lst of transformation rules */ 1593955d011SMarcel Moolenaar 1603955d011SMarcel Moolenaar static int sNum = 0; /* Counter for assigning suffix numbers */ 1613955d011SMarcel Moolenaar 162*2c3632d1SSimon J. Gerraty typedef enum { 163*2c3632d1SSimon J. Gerraty SUFF_INCLUDE = 0x01, /* One which is #include'd */ 164*2c3632d1SSimon J. Gerraty SUFF_LIBRARY = 0x02, /* One which contains a library */ 165*2c3632d1SSimon J. Gerraty SUFF_NULL = 0x04 /* The empty suffix */ 166*2c3632d1SSimon J. Gerraty /* XXX: Why is SUFF_NULL needed? Wouldn't nameLen == 0 mean the same? */ 167*2c3632d1SSimon J. Gerraty } SuffFlags; 168*2c3632d1SSimon J. Gerraty 169*2c3632d1SSimon J. Gerraty ENUM_FLAGS_RTTI_3(SuffFlags, 170*2c3632d1SSimon J. Gerraty SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL); 171*2c3632d1SSimon J. Gerraty 1723955d011SMarcel Moolenaar /* 1733955d011SMarcel Moolenaar * Structure describing an individual suffix. 1743955d011SMarcel Moolenaar */ 175*2c3632d1SSimon J. Gerraty typedef struct Suff { 176*2c3632d1SSimon J. Gerraty char *name; /* The suffix itself, such as ".c" */ 177*2c3632d1SSimon J. Gerraty int nameLen; /* Length of the name, to avoid strlen calls */ 178*2c3632d1SSimon J. Gerraty SuffFlags flags; /* Type of suffix */ 1793955d011SMarcel Moolenaar Lst searchPath; /* The path along which files of this suffix 1803955d011SMarcel Moolenaar * may be found */ 1813955d011SMarcel Moolenaar int sNum; /* The suffix number */ 1823955d011SMarcel Moolenaar int refCount; /* Reference count of list membership */ 1833955d011SMarcel Moolenaar Lst parents; /* Suffixes we have a transformation to */ 1843955d011SMarcel Moolenaar Lst children; /* Suffixes we have a transformation from */ 1853955d011SMarcel Moolenaar Lst ref; /* List of lists this suffix is referenced */ 1863955d011SMarcel Moolenaar } Suff; 1873955d011SMarcel Moolenaar 1883955d011SMarcel Moolenaar /* 1893955d011SMarcel Moolenaar * Structure used in the search for implied sources. 1903955d011SMarcel Moolenaar */ 1913955d011SMarcel Moolenaar typedef struct _Src { 1923955d011SMarcel Moolenaar char *file; /* The file to look for */ 1933955d011SMarcel Moolenaar char *pref; /* Prefix from which file was formed */ 1943955d011SMarcel Moolenaar Suff *suff; /* The suffix on the file */ 1953955d011SMarcel Moolenaar struct _Src *parent; /* The Src for which this is a source */ 1963955d011SMarcel Moolenaar GNode *node; /* The node describing the file */ 1973955d011SMarcel Moolenaar int children; /* Count of existing children (so we don't free 1983955d011SMarcel Moolenaar * this thing too early or never nuke it) */ 1993955d011SMarcel Moolenaar #ifdef DEBUG_SRC 2003955d011SMarcel Moolenaar Lst cp; /* Debug; children list */ 2013955d011SMarcel Moolenaar #endif 2023955d011SMarcel Moolenaar } Src; 2033955d011SMarcel Moolenaar 2043955d011SMarcel Moolenaar /* 2053955d011SMarcel Moolenaar * A structure for passing more than one argument to the Lst-library-invoked 2063955d011SMarcel Moolenaar * function... 2073955d011SMarcel Moolenaar */ 2083955d011SMarcel Moolenaar typedef struct { 2093955d011SMarcel Moolenaar Lst l; 2103955d011SMarcel Moolenaar Src *s; 2113955d011SMarcel Moolenaar } LstSrc; 2123955d011SMarcel Moolenaar 2133955d011SMarcel Moolenaar typedef struct { 2143955d011SMarcel Moolenaar GNode **gn; 2153955d011SMarcel Moolenaar Suff *s; 2163955d011SMarcel Moolenaar Boolean r; 2173955d011SMarcel Moolenaar } GNodeSuff; 2183955d011SMarcel Moolenaar 2193955d011SMarcel Moolenaar static Suff *suffNull; /* The NULL suffix for this run */ 2203955d011SMarcel Moolenaar static Suff *emptySuff; /* The empty suffix required for POSIX 2213955d011SMarcel Moolenaar * single-suffix transformation rules */ 2223955d011SMarcel Moolenaar 2233955d011SMarcel Moolenaar 2243955d011SMarcel Moolenaar static void SuffUnRef(void *, void *); 2253955d011SMarcel Moolenaar static void SuffFree(void *); 2263955d011SMarcel Moolenaar static void SuffInsert(Lst, Suff *); 2273955d011SMarcel Moolenaar static void SuffRemove(Lst, Suff *); 2283955d011SMarcel Moolenaar static Boolean SuffParseTransform(char *, Suff **, Suff **); 2293955d011SMarcel Moolenaar static int SuffRebuildGraph(void *, void *); 2303955d011SMarcel Moolenaar static int SuffScanTargets(void *, void *); 2313955d011SMarcel Moolenaar static int SuffAddSrc(void *, void *); 2323955d011SMarcel Moolenaar static void SuffAddLevel(Lst, Src *); 2333955d011SMarcel Moolenaar static void SuffExpandChildren(LstNode, GNode *); 2343955d011SMarcel Moolenaar static void SuffExpandWildcards(LstNode, GNode *); 2353955d011SMarcel Moolenaar static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); 2363955d011SMarcel Moolenaar static void SuffFindDeps(GNode *, Lst); 2373955d011SMarcel Moolenaar static void SuffFindArchiveDeps(GNode *, Lst); 2383955d011SMarcel Moolenaar static void SuffFindNormalDeps(GNode *, Lst); 2393955d011SMarcel Moolenaar static int SuffPrintName(void *, void *); 2403955d011SMarcel Moolenaar static int SuffPrintSuff(void *, void *); 2413955d011SMarcel Moolenaar static int SuffPrintTrans(void *, void *); 2423955d011SMarcel Moolenaar 2433955d011SMarcel Moolenaar /*************** Lst Predicates ****************/ 2443955d011SMarcel Moolenaar /*- 2453955d011SMarcel Moolenaar *----------------------------------------------------------------------- 2463955d011SMarcel Moolenaar * SuffStrIsPrefix -- 2473955d011SMarcel Moolenaar * See if pref is a prefix of str. 2483955d011SMarcel Moolenaar * 2493955d011SMarcel Moolenaar * Input: 2503955d011SMarcel Moolenaar * pref possible prefix 2513955d011SMarcel Moolenaar * str string to check 2523955d011SMarcel Moolenaar * 2533955d011SMarcel Moolenaar * Results: 2543955d011SMarcel Moolenaar * NULL if it ain't, pointer to character in str after prefix if so 2553955d011SMarcel Moolenaar * 2563955d011SMarcel Moolenaar * Side Effects: 2573955d011SMarcel Moolenaar * None 2583955d011SMarcel Moolenaar *----------------------------------------------------------------------- 2593955d011SMarcel Moolenaar */ 2603955d011SMarcel Moolenaar static const char * 2613955d011SMarcel Moolenaar SuffStrIsPrefix(const char *pref, const char *str) 2623955d011SMarcel Moolenaar { 2633955d011SMarcel Moolenaar while (*str && *pref == *str) { 2643955d011SMarcel Moolenaar pref++; 2653955d011SMarcel Moolenaar str++; 2663955d011SMarcel Moolenaar } 2673955d011SMarcel Moolenaar 2683841c287SSimon J. Gerraty return *pref ? NULL : str; 2693955d011SMarcel Moolenaar } 2703955d011SMarcel Moolenaar 271*2c3632d1SSimon J. Gerraty typedef struct { 272*2c3632d1SSimon J. Gerraty char *ename; /* The end of the name */ 273*2c3632d1SSimon J. Gerraty int len; /* Length of the name */ 274*2c3632d1SSimon J. Gerraty } SuffSuffGetSuffixArgs; 275*2c3632d1SSimon J. Gerraty 276*2c3632d1SSimon J. Gerraty /* See if suff is a suffix of str. str->ename should point to THE END 2773955d011SMarcel Moolenaar * of the string to check. (THE END == the null byte) 2783955d011SMarcel Moolenaar * 2793955d011SMarcel Moolenaar * Input: 2803955d011SMarcel Moolenaar * s possible suffix 281*2c3632d1SSimon J. Gerraty * str string to examine 2823955d011SMarcel Moolenaar * 2833955d011SMarcel Moolenaar * Results: 2843955d011SMarcel Moolenaar * NULL if it ain't, pointer to character in str before suffix if 2853955d011SMarcel Moolenaar * it is. 2863955d011SMarcel Moolenaar */ 2873955d011SMarcel Moolenaar static char * 288*2c3632d1SSimon J. Gerraty SuffSuffGetSuffix(const Suff *s, const SuffSuffGetSuffixArgs *str) 2893955d011SMarcel Moolenaar { 2903955d011SMarcel Moolenaar char *p1; /* Pointer into suffix name */ 2913955d011SMarcel Moolenaar char *p2; /* Pointer into string being examined */ 2923955d011SMarcel Moolenaar 293*2c3632d1SSimon J. Gerraty if (str->len < s->nameLen) 2943955d011SMarcel Moolenaar return NULL; /* this string is shorter than the suffix */ 2953955d011SMarcel Moolenaar 2963955d011SMarcel Moolenaar p1 = s->name + s->nameLen; 297*2c3632d1SSimon J. Gerraty p2 = str->ename; 2983955d011SMarcel Moolenaar 2993955d011SMarcel Moolenaar while (p1 >= s->name && *p1 == *p2) { 3003955d011SMarcel Moolenaar p1--; 3013955d011SMarcel Moolenaar p2--; 3023955d011SMarcel Moolenaar } 3033955d011SMarcel Moolenaar 3043841c287SSimon J. Gerraty return p1 == s->name - 1 ? p2 : NULL; 3053955d011SMarcel Moolenaar } 3063955d011SMarcel Moolenaar 307*2c3632d1SSimon J. Gerraty /* Predicate form of SuffSuffGetSuffix, for Lst_Find. */ 308*2c3632d1SSimon J. Gerraty static Boolean 309*2c3632d1SSimon J. Gerraty SuffSuffIsSuffix(const void *s, const void *sd) 3103955d011SMarcel Moolenaar { 311*2c3632d1SSimon J. Gerraty return SuffSuffGetSuffix(s, sd) != NULL; 3123955d011SMarcel Moolenaar } 3133955d011SMarcel Moolenaar 314*2c3632d1SSimon J. Gerraty /* See if the suffix has the desired name. */ 315*2c3632d1SSimon J. Gerraty static Boolean 316*2c3632d1SSimon J. Gerraty SuffSuffHasName(const void *s, const void *desiredName) 3173955d011SMarcel Moolenaar { 318*2c3632d1SSimon J. Gerraty return strcmp(((const Suff *)s)->name, desiredName) == 0; 3193955d011SMarcel Moolenaar } 3203955d011SMarcel Moolenaar 321*2c3632d1SSimon J. Gerraty /* See if the suffix name is a prefix of the string. Care must be taken when 322*2c3632d1SSimon J. Gerraty * using this to search for transformations and what-not, since there could 323*2c3632d1SSimon J. Gerraty * well be two suffixes, one of which is a prefix of the other... */ 324*2c3632d1SSimon J. Gerraty static Boolean 3253955d011SMarcel Moolenaar SuffSuffIsPrefix(const void *s, const void *str) 3263955d011SMarcel Moolenaar { 327*2c3632d1SSimon J. Gerraty return SuffStrIsPrefix(((const Suff *)s)->name, str) != NULL; 3283955d011SMarcel Moolenaar } 3293955d011SMarcel Moolenaar 330*2c3632d1SSimon J. Gerraty /* See if the graph node has the desired name. */ 331*2c3632d1SSimon J. Gerraty static Boolean 332*2c3632d1SSimon J. Gerraty SuffGNHasName(const void *gn, const void *desiredName) 3333955d011SMarcel Moolenaar { 334*2c3632d1SSimon J. Gerraty return strcmp(((const GNode *)gn)->name, desiredName) == 0; 3353955d011SMarcel Moolenaar } 3363955d011SMarcel Moolenaar 3373955d011SMarcel Moolenaar /*********** Maintenance Functions ************/ 3383955d011SMarcel Moolenaar 3393955d011SMarcel Moolenaar static void 3403955d011SMarcel Moolenaar SuffUnRef(void *lp, void *sp) 3413955d011SMarcel Moolenaar { 3423955d011SMarcel Moolenaar Lst l = (Lst) lp; 3433955d011SMarcel Moolenaar 344*2c3632d1SSimon J. Gerraty LstNode ln = Lst_FindDatum(l, sp); 3453955d011SMarcel Moolenaar if (ln != NULL) { 3463955d011SMarcel Moolenaar Lst_Remove(l, ln); 3473955d011SMarcel Moolenaar ((Suff *)sp)->refCount--; 3483955d011SMarcel Moolenaar } 3493955d011SMarcel Moolenaar } 3503955d011SMarcel Moolenaar 351*2c3632d1SSimon J. Gerraty /* Free up all memory associated with the given suffix structure. */ 3523955d011SMarcel Moolenaar static void 3533955d011SMarcel Moolenaar SuffFree(void *sp) 3543955d011SMarcel Moolenaar { 3553955d011SMarcel Moolenaar Suff *s = (Suff *)sp; 3563955d011SMarcel Moolenaar 3573955d011SMarcel Moolenaar if (s == suffNull) 3583955d011SMarcel Moolenaar suffNull = NULL; 3593955d011SMarcel Moolenaar 3603955d011SMarcel Moolenaar if (s == emptySuff) 3613955d011SMarcel Moolenaar emptySuff = NULL; 3623955d011SMarcel Moolenaar 3633955d011SMarcel Moolenaar #ifdef notdef 3643955d011SMarcel Moolenaar /* We don't delete suffixes in order, so we cannot use this */ 3653955d011SMarcel Moolenaar if (s->refCount) 3663955d011SMarcel Moolenaar Punt("Internal error deleting suffix `%s' with refcount = %d", s->name, 3673955d011SMarcel Moolenaar s->refCount); 3683955d011SMarcel Moolenaar #endif 3693955d011SMarcel Moolenaar 370*2c3632d1SSimon J. Gerraty Lst_Free(s->ref); 371*2c3632d1SSimon J. Gerraty Lst_Free(s->children); 372*2c3632d1SSimon J. Gerraty Lst_Free(s->parents); 3733955d011SMarcel Moolenaar Lst_Destroy(s->searchPath, Dir_Destroy); 3743955d011SMarcel Moolenaar 3753955d011SMarcel Moolenaar free(s->name); 3763955d011SMarcel Moolenaar free(s); 3773955d011SMarcel Moolenaar } 3783955d011SMarcel Moolenaar 379*2c3632d1SSimon J. Gerraty /* Remove the suffix from the list, and free if it is otherwise unused. */ 3803955d011SMarcel Moolenaar static void 3813955d011SMarcel Moolenaar SuffRemove(Lst l, Suff *s) 3823955d011SMarcel Moolenaar { 3833955d011SMarcel Moolenaar SuffUnRef(l, s); 3843955d011SMarcel Moolenaar if (s->refCount == 0) { 3853955d011SMarcel Moolenaar SuffUnRef(sufflist, s); 3863955d011SMarcel Moolenaar SuffFree(s); 3873955d011SMarcel Moolenaar } 3883955d011SMarcel Moolenaar } 389*2c3632d1SSimon J. Gerraty 390*2c3632d1SSimon J. Gerraty /* Insert the suffix into the list keeping the list ordered by suffix numbers. 3913955d011SMarcel Moolenaar * 3923955d011SMarcel Moolenaar * Input: 3933955d011SMarcel Moolenaar * l the list where in s should be inserted 3943955d011SMarcel Moolenaar * s the suffix to insert 3953955d011SMarcel Moolenaar */ 3963955d011SMarcel Moolenaar static void 3973955d011SMarcel Moolenaar SuffInsert(Lst l, Suff *s) 3983955d011SMarcel Moolenaar { 3993955d011SMarcel Moolenaar LstNode ln; /* current element in l we're examining */ 4003955d011SMarcel Moolenaar Suff *s2 = NULL; /* the suffix descriptor in this element */ 4013955d011SMarcel Moolenaar 402*2c3632d1SSimon J. Gerraty Lst_Open(l); 4033955d011SMarcel Moolenaar while ((ln = Lst_Next(l)) != NULL) { 404*2c3632d1SSimon J. Gerraty s2 = LstNode_Datum(ln); 4053955d011SMarcel Moolenaar if (s2->sNum >= s->sNum) { 4063955d011SMarcel Moolenaar break; 4073955d011SMarcel Moolenaar } 4083955d011SMarcel Moolenaar } 4093955d011SMarcel Moolenaar Lst_Close(l); 410*2c3632d1SSimon J. Gerraty 411*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("inserting %s(%d)...", s->name, s->sNum); 412*2c3632d1SSimon J. Gerraty 4133955d011SMarcel Moolenaar if (ln == NULL) { 414*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("at end of list\n"); 415*2c3632d1SSimon J. Gerraty Lst_Append(l, s); 4163955d011SMarcel Moolenaar s->refCount++; 417*2c3632d1SSimon J. Gerraty Lst_Append(s->ref, l); 4183955d011SMarcel Moolenaar } else if (s2->sNum != s->sNum) { 419*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("before %s(%d)\n", s2->name, s2->sNum); 420*2c3632d1SSimon J. Gerraty Lst_InsertBefore(l, ln, s); 4213955d011SMarcel Moolenaar s->refCount++; 422*2c3632d1SSimon J. Gerraty Lst_Append(s->ref, l); 423*2c3632d1SSimon J. Gerraty } else { 424*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("already there\n"); 4253955d011SMarcel Moolenaar } 4263955d011SMarcel Moolenaar } 4273955d011SMarcel Moolenaar 428*2c3632d1SSimon J. Gerraty static Suff * 429*2c3632d1SSimon J. Gerraty SuffNew(const char *name) 430*2c3632d1SSimon J. Gerraty { 431*2c3632d1SSimon J. Gerraty Suff *s = bmake_malloc(sizeof(Suff)); 432*2c3632d1SSimon J. Gerraty 433*2c3632d1SSimon J. Gerraty s->name = bmake_strdup(name); 434*2c3632d1SSimon J. Gerraty s->nameLen = strlen(s->name); 435*2c3632d1SSimon J. Gerraty s->searchPath = Lst_Init(); 436*2c3632d1SSimon J. Gerraty s->children = Lst_Init(); 437*2c3632d1SSimon J. Gerraty s->parents = Lst_Init(); 438*2c3632d1SSimon J. Gerraty s->ref = Lst_Init(); 439*2c3632d1SSimon J. Gerraty s->sNum = sNum++; 440*2c3632d1SSimon J. Gerraty s->flags = 0; 441*2c3632d1SSimon J. Gerraty s->refCount = 1; 442*2c3632d1SSimon J. Gerraty 443*2c3632d1SSimon J. Gerraty return s; 444*2c3632d1SSimon J. Gerraty } 445*2c3632d1SSimon J. Gerraty 446*2c3632d1SSimon J. Gerraty /* This is gross. Nuke the list of suffixes but keep all transformation 447*2c3632d1SSimon J. Gerraty * rules around. The transformation graph is destroyed in this process, but 448*2c3632d1SSimon J. Gerraty * we leave the list of rules so when a new graph is formed the rules will 449*2c3632d1SSimon J. Gerraty * remain. This function is called from the parse module when a .SUFFIXES:\n 450*2c3632d1SSimon J. Gerraty * line is encountered. */ 4513955d011SMarcel Moolenaar void 4523955d011SMarcel Moolenaar Suff_ClearSuffixes(void) 4533955d011SMarcel Moolenaar { 4543955d011SMarcel Moolenaar #ifdef CLEANUP 455*2c3632d1SSimon J. Gerraty Lst_MoveAll(suffClean, sufflist); 4563955d011SMarcel Moolenaar #endif 457*2c3632d1SSimon J. Gerraty sufflist = Lst_Init(); 4583955d011SMarcel Moolenaar sNum = 0; 4596e050540SSimon J. Gerraty if (suffNull) 4606e050540SSimon J. Gerraty SuffFree(suffNull); 461*2c3632d1SSimon J. Gerraty emptySuff = suffNull = SuffNew(""); 4626e050540SSimon J. Gerraty 4636e050540SSimon J. Gerraty Dir_Concat(suffNull->searchPath, dirSearchPath); 4646e050540SSimon J. Gerraty suffNull->flags = SUFF_NULL; 4653955d011SMarcel Moolenaar } 4663955d011SMarcel Moolenaar 467*2c3632d1SSimon J. Gerraty /* Parse a transformation string to find its two component suffixes. 4683955d011SMarcel Moolenaar * 4693955d011SMarcel Moolenaar * Input: 4703955d011SMarcel Moolenaar * str String being parsed 471*2c3632d1SSimon J. Gerraty * out_src Place to store source of trans. 472*2c3632d1SSimon J. Gerraty * out_targ Place to store target of trans. 4733955d011SMarcel Moolenaar * 4743955d011SMarcel Moolenaar * Results: 475*2c3632d1SSimon J. Gerraty * TRUE if the string is a valid transformation, FALSE otherwise. 4763955d011SMarcel Moolenaar */ 4773955d011SMarcel Moolenaar static Boolean 478*2c3632d1SSimon J. Gerraty SuffParseTransform(char *str, Suff **out_src, Suff **out_targ) 4793955d011SMarcel Moolenaar { 4803955d011SMarcel Moolenaar LstNode srcLn; /* element in suffix list of trans source*/ 4813955d011SMarcel Moolenaar Suff *src; /* Source of transformation */ 4823955d011SMarcel Moolenaar LstNode targLn; /* element in suffix list of trans target*/ 4833955d011SMarcel Moolenaar char *str2; /* Extra pointer (maybe target suffix) */ 4843955d011SMarcel Moolenaar LstNode singleLn; /* element in suffix list of any suffix 4853955d011SMarcel Moolenaar * that exactly matches str */ 4863955d011SMarcel Moolenaar Suff *single = NULL;/* Source of possible transformation to 4873955d011SMarcel Moolenaar * null suffix */ 4883955d011SMarcel Moolenaar 4893955d011SMarcel Moolenaar srcLn = NULL; 4903955d011SMarcel Moolenaar singleLn = NULL; 4913955d011SMarcel Moolenaar 4923955d011SMarcel Moolenaar /* 4933955d011SMarcel Moolenaar * Loop looking first for a suffix that matches the start of the 4943955d011SMarcel Moolenaar * string and then for one that exactly matches the rest of it. If 4953955d011SMarcel Moolenaar * we can find two that meet these criteria, we've successfully 4963955d011SMarcel Moolenaar * parsed the string. 4973955d011SMarcel Moolenaar */ 4983955d011SMarcel Moolenaar for (;;) { 4993955d011SMarcel Moolenaar if (srcLn == NULL) { 500*2c3632d1SSimon J. Gerraty srcLn = Lst_Find(sufflist, SuffSuffIsPrefix, str); 5013955d011SMarcel Moolenaar } else { 502*2c3632d1SSimon J. Gerraty srcLn = Lst_FindFrom(sufflist, LstNode_Next(srcLn), 503*2c3632d1SSimon J. Gerraty SuffSuffIsPrefix, str); 5043955d011SMarcel Moolenaar } 5053955d011SMarcel Moolenaar if (srcLn == NULL) { 5063955d011SMarcel Moolenaar /* 5073955d011SMarcel Moolenaar * Ran out of source suffixes -- no such rule 5083955d011SMarcel Moolenaar */ 5093955d011SMarcel Moolenaar if (singleLn != NULL) { 5103955d011SMarcel Moolenaar /* 5113955d011SMarcel Moolenaar * Not so fast Mr. Smith! There was a suffix that encompassed 5123955d011SMarcel Moolenaar * the entire string, so we assume it was a transformation 5133955d011SMarcel Moolenaar * to the null suffix (thank you POSIX). We still prefer to 5143955d011SMarcel Moolenaar * find a double rule over a singleton, hence we leave this 5153955d011SMarcel Moolenaar * check until the end. 5163955d011SMarcel Moolenaar * 5173955d011SMarcel Moolenaar * XXX: Use emptySuff over suffNull? 5183955d011SMarcel Moolenaar */ 519*2c3632d1SSimon J. Gerraty *out_src = single; 520*2c3632d1SSimon J. Gerraty *out_targ = suffNull; 5213841c287SSimon J. Gerraty return TRUE; 5223955d011SMarcel Moolenaar } 5233841c287SSimon J. Gerraty return FALSE; 5243955d011SMarcel Moolenaar } 525*2c3632d1SSimon J. Gerraty src = LstNode_Datum(srcLn); 5263955d011SMarcel Moolenaar str2 = str + src->nameLen; 5273955d011SMarcel Moolenaar if (*str2 == '\0') { 5283955d011SMarcel Moolenaar single = src; 5293955d011SMarcel Moolenaar singleLn = srcLn; 5303955d011SMarcel Moolenaar } else { 531*2c3632d1SSimon J. Gerraty targLn = Lst_Find(sufflist, SuffSuffHasName, str2); 5323955d011SMarcel Moolenaar if (targLn != NULL) { 533*2c3632d1SSimon J. Gerraty *out_src = src; 534*2c3632d1SSimon J. Gerraty *out_targ = LstNode_Datum(targLn); 5353841c287SSimon J. Gerraty return TRUE; 5363955d011SMarcel Moolenaar } 5373955d011SMarcel Moolenaar } 5383955d011SMarcel Moolenaar } 5393955d011SMarcel Moolenaar } 5403955d011SMarcel Moolenaar 541*2c3632d1SSimon J. Gerraty /* Return TRUE if the given string is a transformation rule, that is, a 542*2c3632d1SSimon J. Gerraty * concatenation of two known suffixes. */ 5433955d011SMarcel Moolenaar Boolean 5443955d011SMarcel Moolenaar Suff_IsTransform(char *str) 5453955d011SMarcel Moolenaar { 5463955d011SMarcel Moolenaar Suff *src, *targ; 5473955d011SMarcel Moolenaar 5483841c287SSimon J. Gerraty return SuffParseTransform(str, &src, &targ); 5493955d011SMarcel Moolenaar } 5503955d011SMarcel Moolenaar 551*2c3632d1SSimon J. Gerraty /* Add the transformation rule described by the line to the list of rules 552*2c3632d1SSimon J. Gerraty * and place the transformation itself in the graph. 5533955d011SMarcel Moolenaar * 554*2c3632d1SSimon J. Gerraty * The node is placed on the end of the transforms Lst and links are made 555*2c3632d1SSimon J. Gerraty * between the two suffixes mentioned in the target name. 556*2c3632d1SSimon J. Gerraty 5573955d011SMarcel Moolenaar * Input: 5583955d011SMarcel Moolenaar * line name of transformation to add 5593955d011SMarcel Moolenaar * 5603955d011SMarcel Moolenaar * Results: 5613955d011SMarcel Moolenaar * The node created for the transformation in the transforms list 5623955d011SMarcel Moolenaar */ 5633955d011SMarcel Moolenaar GNode * 5643955d011SMarcel Moolenaar Suff_AddTransform(char *line) 5653955d011SMarcel Moolenaar { 5663955d011SMarcel Moolenaar GNode *gn; /* GNode of transformation rule */ 5673955d011SMarcel Moolenaar Suff *s, /* source suffix */ 5683955d011SMarcel Moolenaar *t; /* target suffix */ 5693955d011SMarcel Moolenaar LstNode ln; /* Node for existing transformation */ 570*2c3632d1SSimon J. Gerraty Boolean ok; 5713955d011SMarcel Moolenaar 572*2c3632d1SSimon J. Gerraty ln = Lst_Find(transforms, SuffGNHasName, line); 5733955d011SMarcel Moolenaar if (ln == NULL) { 5743955d011SMarcel Moolenaar /* 5753955d011SMarcel Moolenaar * Make a new graph node for the transformation. It will be filled in 5763955d011SMarcel Moolenaar * by the Parse module. 5773955d011SMarcel Moolenaar */ 5783955d011SMarcel Moolenaar gn = Targ_NewGN(line); 579*2c3632d1SSimon J. Gerraty Lst_Append(transforms, gn); 5803955d011SMarcel Moolenaar } else { 5813955d011SMarcel Moolenaar /* 5823955d011SMarcel Moolenaar * New specification for transformation rule. Just nuke the old list 5833955d011SMarcel Moolenaar * of commands so they can be filled in again... We don't actually 5843955d011SMarcel Moolenaar * free the commands themselves, because a given command can be 5853955d011SMarcel Moolenaar * attached to several different transformations. 5863955d011SMarcel Moolenaar */ 587*2c3632d1SSimon J. Gerraty gn = LstNode_Datum(ln); 588*2c3632d1SSimon J. Gerraty Lst_Free(gn->commands); 589*2c3632d1SSimon J. Gerraty Lst_Free(gn->children); 590*2c3632d1SSimon J. Gerraty gn->commands = Lst_Init(); 591*2c3632d1SSimon J. Gerraty gn->children = Lst_Init(); 5923955d011SMarcel Moolenaar } 5933955d011SMarcel Moolenaar 5943955d011SMarcel Moolenaar gn->type = OP_TRANSFORM; 5953955d011SMarcel Moolenaar 596*2c3632d1SSimon J. Gerraty ok = SuffParseTransform(line, &s, &t); 597*2c3632d1SSimon J. Gerraty assert(ok); 598*2c3632d1SSimon J. Gerraty (void)ok; 5993955d011SMarcel Moolenaar 6003955d011SMarcel Moolenaar /* 6013955d011SMarcel Moolenaar * link the two together in the proper relationship and order 6023955d011SMarcel Moolenaar */ 603*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("defining transformation from `%s' to `%s'\n", 6043955d011SMarcel Moolenaar s->name, t->name); 6053955d011SMarcel Moolenaar SuffInsert(t->children, s); 6063955d011SMarcel Moolenaar SuffInsert(s->parents, t); 6073955d011SMarcel Moolenaar 6083841c287SSimon J. Gerraty return gn; 6093955d011SMarcel Moolenaar } 6103955d011SMarcel Moolenaar 611*2c3632d1SSimon J. Gerraty /* Handle the finish of a transformation definition, removing the 612*2c3632d1SSimon J. Gerraty * transformation from the graph if it has neither commands nor sources. 613*2c3632d1SSimon J. Gerraty * This is a callback procedure for the Parse module via Lst_ForEach. 614*2c3632d1SSimon J. Gerraty * 615*2c3632d1SSimon J. Gerraty * If the node has no commands or children, the children and parents lists 616*2c3632d1SSimon J. Gerraty * of the affected suffixes are altered. 6173955d011SMarcel Moolenaar * 6183955d011SMarcel Moolenaar * Input: 6193955d011SMarcel Moolenaar * gnp Node for transformation 6203955d011SMarcel Moolenaar * 6213955d011SMarcel Moolenaar * Results: 622*2c3632d1SSimon J. Gerraty * 0, so that Lst_ForEach continues 6233955d011SMarcel Moolenaar */ 6243955d011SMarcel Moolenaar int 625e1cee40dSSimon J. Gerraty Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED) 6263955d011SMarcel Moolenaar { 6273955d011SMarcel Moolenaar GNode *gn = (GNode *)gnp; 6283955d011SMarcel Moolenaar 6293955d011SMarcel Moolenaar if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts)) 630*2c3632d1SSimon J. Gerraty gn = LstNode_Datum(Lst_Last(gn->cohorts)); 6313955d011SMarcel Moolenaar if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) && 6323955d011SMarcel Moolenaar Lst_IsEmpty(gn->children)) 6333955d011SMarcel Moolenaar { 6343955d011SMarcel Moolenaar Suff *s, *t; 6353955d011SMarcel Moolenaar 6363955d011SMarcel Moolenaar /* 6373955d011SMarcel Moolenaar * SuffParseTransform() may fail for special rules which are not 6383955d011SMarcel Moolenaar * actual transformation rules. (e.g. .DEFAULT) 6393955d011SMarcel Moolenaar */ 6403955d011SMarcel Moolenaar if (SuffParseTransform(gn->name, &s, &t)) { 6413955d011SMarcel Moolenaar Lst p; 6423955d011SMarcel Moolenaar 643*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("deleting transformation from `%s' to `%s'\n", 6443955d011SMarcel Moolenaar s->name, t->name); 6453955d011SMarcel Moolenaar 6463955d011SMarcel Moolenaar /* 6473955d011SMarcel Moolenaar * Store s->parents because s could be deleted in SuffRemove 6483955d011SMarcel Moolenaar */ 6493955d011SMarcel Moolenaar p = s->parents; 6503955d011SMarcel Moolenaar 6513955d011SMarcel Moolenaar /* 6523955d011SMarcel Moolenaar * Remove the source from the target's children list. We check for a 6533955d011SMarcel Moolenaar * nil return to handle a beanhead saying something like 6543955d011SMarcel Moolenaar * .c.o .c.o: 6553955d011SMarcel Moolenaar * 6563955d011SMarcel Moolenaar * We'll be called twice when the next target is seen, but .c and .o 6573955d011SMarcel Moolenaar * are only linked once... 6583955d011SMarcel Moolenaar */ 6593955d011SMarcel Moolenaar SuffRemove(t->children, s); 6603955d011SMarcel Moolenaar 6613955d011SMarcel Moolenaar /* 6623955d011SMarcel Moolenaar * Remove the target from the source's parents list 6633955d011SMarcel Moolenaar */ 6643955d011SMarcel Moolenaar SuffRemove(p, t); 6653955d011SMarcel Moolenaar } 666*2c3632d1SSimon J. Gerraty } else if (gn->type & OP_TRANSFORM) { 667*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("transformation %s complete\n", gn->name); 6683955d011SMarcel Moolenaar } 6693955d011SMarcel Moolenaar 67095e3ed2cSSimon J. Gerraty return 0; 6713955d011SMarcel Moolenaar } 6723955d011SMarcel Moolenaar 673*2c3632d1SSimon J. Gerraty /* Called from Suff_AddSuffix via Lst_ForEach to search through the list of 674*2c3632d1SSimon J. Gerraty * existing transformation rules and rebuild the transformation graph when 675*2c3632d1SSimon J. Gerraty * it has been destroyed by Suff_ClearSuffixes. If the given rule is a 676*2c3632d1SSimon J. Gerraty * transformation involving this suffix and another, existing suffix, the 677*2c3632d1SSimon J. Gerraty * proper relationship is established between the two. 678*2c3632d1SSimon J. Gerraty * 679*2c3632d1SSimon J. Gerraty * The appropriate links will be made between this suffix and others if 680*2c3632d1SSimon J. Gerraty * transformation rules exist for it. 6813955d011SMarcel Moolenaar * 6823955d011SMarcel Moolenaar * Input: 6833955d011SMarcel Moolenaar * transformp Transformation to test 6843955d011SMarcel Moolenaar * sp Suffix to rebuild 6853955d011SMarcel Moolenaar * 6863955d011SMarcel Moolenaar * Results: 687*2c3632d1SSimon J. Gerraty * 0, so that Lst_ForEach continues 6883955d011SMarcel Moolenaar */ 6893955d011SMarcel Moolenaar static int 6903955d011SMarcel Moolenaar SuffRebuildGraph(void *transformp, void *sp) 6913955d011SMarcel Moolenaar { 6923955d011SMarcel Moolenaar GNode *transform = (GNode *)transformp; 6933955d011SMarcel Moolenaar Suff *s = (Suff *)sp; 6943955d011SMarcel Moolenaar char *cp; 6953955d011SMarcel Moolenaar LstNode ln; 6963955d011SMarcel Moolenaar Suff *s2; 697*2c3632d1SSimon J. Gerraty SuffSuffGetSuffixArgs sd; 6983955d011SMarcel Moolenaar 6993955d011SMarcel Moolenaar /* 7003955d011SMarcel Moolenaar * First see if it is a transformation from this suffix. 7013955d011SMarcel Moolenaar */ 7023955d011SMarcel Moolenaar cp = UNCONST(SuffStrIsPrefix(s->name, transform->name)); 7033955d011SMarcel Moolenaar if (cp != NULL) { 704*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, cp); 7053955d011SMarcel Moolenaar if (ln != NULL) { 7063955d011SMarcel Moolenaar /* 7073955d011SMarcel Moolenaar * Found target. Link in and return, since it can't be anything 7083955d011SMarcel Moolenaar * else. 7093955d011SMarcel Moolenaar */ 710*2c3632d1SSimon J. Gerraty s2 = LstNode_Datum(ln); 7113955d011SMarcel Moolenaar SuffInsert(s2->children, s); 7123955d011SMarcel Moolenaar SuffInsert(s->parents, s2); 7133841c287SSimon J. Gerraty return 0; 7143955d011SMarcel Moolenaar } 7153955d011SMarcel Moolenaar } 7163955d011SMarcel Moolenaar 7173955d011SMarcel Moolenaar /* 7183955d011SMarcel Moolenaar * Not from, maybe to? 7193955d011SMarcel Moolenaar */ 7203955d011SMarcel Moolenaar sd.len = strlen(transform->name); 7213955d011SMarcel Moolenaar sd.ename = transform->name + sd.len; 722*2c3632d1SSimon J. Gerraty cp = SuffSuffGetSuffix(s, &sd); 7233955d011SMarcel Moolenaar if (cp != NULL) { 7243955d011SMarcel Moolenaar /* 7253955d011SMarcel Moolenaar * Null-terminate the source suffix in order to find it. 7263955d011SMarcel Moolenaar */ 7273955d011SMarcel Moolenaar cp[1] = '\0'; 728*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, transform->name); 7293955d011SMarcel Moolenaar /* 7303955d011SMarcel Moolenaar * Replace the start of the target suffix 7313955d011SMarcel Moolenaar */ 7323955d011SMarcel Moolenaar cp[1] = s->name[0]; 7333955d011SMarcel Moolenaar if (ln != NULL) { 7343955d011SMarcel Moolenaar /* 7353955d011SMarcel Moolenaar * Found it -- establish the proper relationship 7363955d011SMarcel Moolenaar */ 737*2c3632d1SSimon J. Gerraty s2 = LstNode_Datum(ln); 7383955d011SMarcel Moolenaar SuffInsert(s->children, s2); 7393955d011SMarcel Moolenaar SuffInsert(s2->parents, s); 7403955d011SMarcel Moolenaar } 7413955d011SMarcel Moolenaar } 7423841c287SSimon J. Gerraty return 0; 7433955d011SMarcel Moolenaar } 7443955d011SMarcel Moolenaar 745*2c3632d1SSimon J. Gerraty /* Called from Suff_AddSuffix via Lst_ForEach to search through the list of 746*2c3632d1SSimon J. Gerraty * existing targets and find if any of the existing targets can be turned 747*2c3632d1SSimon J. Gerraty * into a transformation rule. 748*2c3632d1SSimon J. Gerraty * 749*2c3632d1SSimon J. Gerraty * If such a target is found and the target is the current main target, the 750*2c3632d1SSimon J. Gerraty * main target is set to NULL and the next target examined (if that exists) 751*2c3632d1SSimon J. Gerraty * becomes the main target. 7523955d011SMarcel Moolenaar * 7533955d011SMarcel Moolenaar * Results: 7543955d011SMarcel Moolenaar * 1 if a new main target has been selected, 0 otherwise. 7553955d011SMarcel Moolenaar */ 7563955d011SMarcel Moolenaar static int 7573955d011SMarcel Moolenaar SuffScanTargets(void *targetp, void *gsp) 7583955d011SMarcel Moolenaar { 7593955d011SMarcel Moolenaar GNode *target = (GNode *)targetp; 7603955d011SMarcel Moolenaar GNodeSuff *gs = (GNodeSuff *)gsp; 7613955d011SMarcel Moolenaar Suff *s, *t; 7623955d011SMarcel Moolenaar char *ptr; 7633955d011SMarcel Moolenaar 7643955d011SMarcel Moolenaar if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) { 7653955d011SMarcel Moolenaar *gs->gn = target; 7663955d011SMarcel Moolenaar Targ_SetMain(target); 7673955d011SMarcel Moolenaar return 1; 7683955d011SMarcel Moolenaar } 7693955d011SMarcel Moolenaar 770*2c3632d1SSimon J. Gerraty if (target->type == OP_TRANSFORM) 7713955d011SMarcel Moolenaar return 0; 7723955d011SMarcel Moolenaar 7733955d011SMarcel Moolenaar if ((ptr = strstr(target->name, gs->s->name)) == NULL || 7743955d011SMarcel Moolenaar ptr == target->name) 7753955d011SMarcel Moolenaar return 0; 7763955d011SMarcel Moolenaar 7773955d011SMarcel Moolenaar if (SuffParseTransform(target->name, &s, &t)) { 7783955d011SMarcel Moolenaar if (*gs->gn == target) { 7793955d011SMarcel Moolenaar gs->r = TRUE; 7803955d011SMarcel Moolenaar *gs->gn = NULL; 7813955d011SMarcel Moolenaar Targ_SetMain(NULL); 7823955d011SMarcel Moolenaar } 783*2c3632d1SSimon J. Gerraty Lst_Free(target->children); 784*2c3632d1SSimon J. Gerraty target->children = Lst_Init(); 7853955d011SMarcel Moolenaar target->type = OP_TRANSFORM; 7863955d011SMarcel Moolenaar /* 7873955d011SMarcel Moolenaar * link the two together in the proper relationship and order 7883955d011SMarcel Moolenaar */ 789*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("defining transformation from `%s' to `%s'\n", 7903955d011SMarcel Moolenaar s->name, t->name); 7913955d011SMarcel Moolenaar SuffInsert(t->children, s); 7923955d011SMarcel Moolenaar SuffInsert(s->parents, t); 7933955d011SMarcel Moolenaar } 7943955d011SMarcel Moolenaar return 0; 7953955d011SMarcel Moolenaar } 7963955d011SMarcel Moolenaar 797*2c3632d1SSimon J. Gerraty /* Add the suffix to the end of the list of known suffixes. 7983955d011SMarcel Moolenaar * Should we restructure the suffix graph? Make doesn't... 7993955d011SMarcel Moolenaar * 8003955d011SMarcel Moolenaar * A GNode is created for the suffix and a Suff structure is created and 8013955d011SMarcel Moolenaar * added to the suffixes list unless the suffix was already known. 8023955d011SMarcel Moolenaar * The mainNode passed can be modified if a target mutated into a 8033955d011SMarcel Moolenaar * transform and that target happened to be the main target. 804*2c3632d1SSimon J. Gerraty * 805*2c3632d1SSimon J. Gerraty * Input: 806*2c3632d1SSimon J. Gerraty * name the name of the suffix to add 8073955d011SMarcel Moolenaar */ 8083955d011SMarcel Moolenaar void 809*2c3632d1SSimon J. Gerraty Suff_AddSuffix(const char *name, GNode **gn) 8103955d011SMarcel Moolenaar { 8113955d011SMarcel Moolenaar Suff *s; /* new suffix descriptor */ 8123955d011SMarcel Moolenaar LstNode ln; 8133955d011SMarcel Moolenaar GNodeSuff gs; 8143955d011SMarcel Moolenaar 815*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, name); 8163955d011SMarcel Moolenaar if (ln == NULL) { 817*2c3632d1SSimon J. Gerraty s = SuffNew(name); 8183955d011SMarcel Moolenaar 819*2c3632d1SSimon J. Gerraty Lst_Append(sufflist, s); 8203955d011SMarcel Moolenaar /* 8213955d011SMarcel Moolenaar * We also look at our existing targets list to see if adding 8223955d011SMarcel Moolenaar * this suffix will make one of our current targets mutate into 8233955d011SMarcel Moolenaar * a suffix rule. This is ugly, but other makes treat all targets 8243955d011SMarcel Moolenaar * that start with a . as suffix rules. 8253955d011SMarcel Moolenaar */ 8263955d011SMarcel Moolenaar gs.gn = gn; 8273955d011SMarcel Moolenaar gs.s = s; 8283955d011SMarcel Moolenaar gs.r = FALSE; 8293955d011SMarcel Moolenaar Lst_ForEach(Targ_List(), SuffScanTargets, &gs); 8303955d011SMarcel Moolenaar /* 8313955d011SMarcel Moolenaar * Look for any existing transformations from or to this suffix. 8323955d011SMarcel Moolenaar * XXX: Only do this after a Suff_ClearSuffixes? 8333955d011SMarcel Moolenaar */ 8343955d011SMarcel Moolenaar Lst_ForEach(transforms, SuffRebuildGraph, s); 8353955d011SMarcel Moolenaar } 8363955d011SMarcel Moolenaar } 8373955d011SMarcel Moolenaar 838*2c3632d1SSimon J. Gerraty /* Return the search path for the given suffix, or NULL. */ 8393955d011SMarcel Moolenaar Lst 8403955d011SMarcel Moolenaar Suff_GetPath(char *sname) 8413955d011SMarcel Moolenaar { 8423955d011SMarcel Moolenaar LstNode ln; 8433955d011SMarcel Moolenaar Suff *s; 8443955d011SMarcel Moolenaar 845*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, sname); 8463955d011SMarcel Moolenaar if (ln == NULL) { 8473955d011SMarcel Moolenaar return NULL; 8483955d011SMarcel Moolenaar } else { 849*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 8503841c287SSimon J. Gerraty return s->searchPath; 8513955d011SMarcel Moolenaar } 8523955d011SMarcel Moolenaar } 8533955d011SMarcel Moolenaar 854*2c3632d1SSimon J. Gerraty /* Extend the search paths for all suffixes to include the default search 855*2c3632d1SSimon J. Gerraty * path. 8563955d011SMarcel Moolenaar * 857*2c3632d1SSimon J. Gerraty * The searchPath field of all the suffixes is extended by the directories 858*2c3632d1SSimon J. Gerraty * in dirSearchPath. If paths were specified for the ".h" suffix, the 859*2c3632d1SSimon J. Gerraty * directories are stuffed into a global variable called ".INCLUDES" with 860*2c3632d1SSimon J. Gerraty * each directory preceded by a -I. The same is done for the ".a" suffix, 861*2c3632d1SSimon J. Gerraty * except the variable is called ".LIBS" and the flag is -L. 8623955d011SMarcel Moolenaar */ 8633955d011SMarcel Moolenaar void 8643955d011SMarcel Moolenaar Suff_DoPaths(void) 8653955d011SMarcel Moolenaar { 8663955d011SMarcel Moolenaar Suff *s; 8673955d011SMarcel Moolenaar LstNode ln; 8683955d011SMarcel Moolenaar char *ptr; 8693955d011SMarcel Moolenaar Lst inIncludes; /* Cumulative .INCLUDES path */ 8703955d011SMarcel Moolenaar Lst inLibs; /* Cumulative .LIBS path */ 8713955d011SMarcel Moolenaar 8723955d011SMarcel Moolenaar 873*2c3632d1SSimon J. Gerraty inIncludes = Lst_Init(); 874*2c3632d1SSimon J. Gerraty inLibs = Lst_Init(); 8753955d011SMarcel Moolenaar 876*2c3632d1SSimon J. Gerraty Lst_Open(sufflist); 8773955d011SMarcel Moolenaar while ((ln = Lst_Next(sufflist)) != NULL) { 878*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 8793955d011SMarcel Moolenaar if (!Lst_IsEmpty(s->searchPath)) { 8803955d011SMarcel Moolenaar #ifdef INCLUDES 8813955d011SMarcel Moolenaar if (s->flags & SUFF_INCLUDE) { 8823955d011SMarcel Moolenaar Dir_Concat(inIncludes, s->searchPath); 8833955d011SMarcel Moolenaar } 8843955d011SMarcel Moolenaar #endif /* INCLUDES */ 8853955d011SMarcel Moolenaar #ifdef LIBRARIES 8863955d011SMarcel Moolenaar if (s->flags & SUFF_LIBRARY) { 8873955d011SMarcel Moolenaar Dir_Concat(inLibs, s->searchPath); 8883955d011SMarcel Moolenaar } 8893955d011SMarcel Moolenaar #endif /* LIBRARIES */ 8903955d011SMarcel Moolenaar Dir_Concat(s->searchPath, dirSearchPath); 8913955d011SMarcel Moolenaar } else { 8923955d011SMarcel Moolenaar Lst_Destroy(s->searchPath, Dir_Destroy); 893*2c3632d1SSimon J. Gerraty s->searchPath = Lst_Copy(dirSearchPath, Dir_CopyDir); 8943955d011SMarcel Moolenaar } 8953955d011SMarcel Moolenaar } 896*2c3632d1SSimon J. Gerraty Lst_Close(sufflist); 8973955d011SMarcel Moolenaar 8983841c287SSimon J. Gerraty Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL); 8993955d011SMarcel Moolenaar free(ptr); 9003841c287SSimon J. Gerraty Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL); 9013955d011SMarcel Moolenaar free(ptr); 9023955d011SMarcel Moolenaar 9033955d011SMarcel Moolenaar Lst_Destroy(inIncludes, Dir_Destroy); 9043955d011SMarcel Moolenaar Lst_Destroy(inLibs, Dir_Destroy); 9053955d011SMarcel Moolenaar } 9063955d011SMarcel Moolenaar 907*2c3632d1SSimon J. Gerraty /* Add the given suffix as a type of file which gets included. 9083955d011SMarcel Moolenaar * Called from the parse module when a .INCLUDES line is parsed. 9093955d011SMarcel Moolenaar * The suffix must have already been defined. 910*2c3632d1SSimon J. Gerraty * The SUFF_INCLUDE bit is set in the suffix's flags field. 9113955d011SMarcel Moolenaar * 9123955d011SMarcel Moolenaar * Input: 9133955d011SMarcel Moolenaar * sname Name of the suffix to mark 9143955d011SMarcel Moolenaar */ 9153955d011SMarcel Moolenaar void 9163955d011SMarcel Moolenaar Suff_AddInclude(char *sname) 9173955d011SMarcel Moolenaar { 9183955d011SMarcel Moolenaar LstNode ln; 9193955d011SMarcel Moolenaar Suff *s; 9203955d011SMarcel Moolenaar 921*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, sname); 9223955d011SMarcel Moolenaar if (ln != NULL) { 923*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 9243955d011SMarcel Moolenaar s->flags |= SUFF_INCLUDE; 9253955d011SMarcel Moolenaar } 9263955d011SMarcel Moolenaar } 9273955d011SMarcel Moolenaar 928*2c3632d1SSimon J. Gerraty /* Add the given suffix as a type of file which is a library. 929*2c3632d1SSimon J. Gerraty * Called from the parse module when parsing a .LIBS line. 930*2c3632d1SSimon J. Gerraty * The suffix must have been defined via .SUFFIXES before this is called. 931*2c3632d1SSimon J. Gerraty * The SUFF_LIBRARY bit is set in the suffix's flags field. 9323955d011SMarcel Moolenaar * 9333955d011SMarcel Moolenaar * Input: 9343955d011SMarcel Moolenaar * sname Name of the suffix to mark 9353955d011SMarcel Moolenaar */ 9363955d011SMarcel Moolenaar void 937*2c3632d1SSimon J. Gerraty Suff_AddLib(const char *sname) 9383955d011SMarcel Moolenaar { 9393955d011SMarcel Moolenaar LstNode ln; 9403955d011SMarcel Moolenaar Suff *s; 9413955d011SMarcel Moolenaar 942*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, sname); 9433955d011SMarcel Moolenaar if (ln != NULL) { 944*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 9453955d011SMarcel Moolenaar s->flags |= SUFF_LIBRARY; 9463955d011SMarcel Moolenaar } 9473955d011SMarcel Moolenaar } 9483955d011SMarcel Moolenaar 9493955d011SMarcel Moolenaar /********** Implicit Source Search Functions *********/ 9503955d011SMarcel Moolenaar 951*2c3632d1SSimon J. Gerraty /* Add a suffix as a Src structure to the given list with its parent 9523955d011SMarcel Moolenaar * being the given Src structure. If the suffix is the null suffix, 9533955d011SMarcel Moolenaar * the prefix is used unaltered as the file name in the Src structure. 9543955d011SMarcel Moolenaar * 9553955d011SMarcel Moolenaar * Input: 9563955d011SMarcel Moolenaar * sp suffix for which to create a Src structure 9573955d011SMarcel Moolenaar * lsp list and parent for the new Src 9583955d011SMarcel Moolenaar * 9593955d011SMarcel Moolenaar * Results: 960*2c3632d1SSimon J. Gerraty * 0, so that Lst_ForEach continues 9613955d011SMarcel Moolenaar */ 9623955d011SMarcel Moolenaar static int 9633955d011SMarcel Moolenaar SuffAddSrc(void *sp, void *lsp) 9643955d011SMarcel Moolenaar { 9653955d011SMarcel Moolenaar Suff *s = (Suff *)sp; 9663955d011SMarcel Moolenaar LstSrc *ls = (LstSrc *)lsp; 9673955d011SMarcel Moolenaar Src *s2; /* new Src structure */ 9683955d011SMarcel Moolenaar Src *targ; /* Target structure */ 9693955d011SMarcel Moolenaar 9703955d011SMarcel Moolenaar targ = ls->s; 9713955d011SMarcel Moolenaar 9723955d011SMarcel Moolenaar if ((s->flags & SUFF_NULL) && (*s->name != '\0')) { 9733955d011SMarcel Moolenaar /* 9743955d011SMarcel Moolenaar * If the suffix has been marked as the NULL suffix, also create a Src 9753955d011SMarcel Moolenaar * structure for a file with no suffix attached. Two birds, and all 9763955d011SMarcel Moolenaar * that... 9773955d011SMarcel Moolenaar */ 9783955d011SMarcel Moolenaar s2 = bmake_malloc(sizeof(Src)); 9793955d011SMarcel Moolenaar s2->file = bmake_strdup(targ->pref); 9803955d011SMarcel Moolenaar s2->pref = targ->pref; 9813955d011SMarcel Moolenaar s2->parent = targ; 9823955d011SMarcel Moolenaar s2->node = NULL; 9833955d011SMarcel Moolenaar s2->suff = s; 9843955d011SMarcel Moolenaar s->refCount++; 9853955d011SMarcel Moolenaar s2->children = 0; 9863955d011SMarcel Moolenaar targ->children += 1; 987*2c3632d1SSimon J. Gerraty Lst_Append(ls->l, s2); 9883955d011SMarcel Moolenaar #ifdef DEBUG_SRC 989*2c3632d1SSimon J. Gerraty s2->cp = Lst_Init(); 990*2c3632d1SSimon J. Gerraty Lst_Append(targ->cp, s2); 99195e3ed2cSSimon J. Gerraty fprintf(debug_file, "1 add %p %p to %p:", targ, s2, ls->l); 9923955d011SMarcel Moolenaar Lst_ForEach(ls->l, PrintAddr, NULL); 9933955d011SMarcel Moolenaar fprintf(debug_file, "\n"); 9943955d011SMarcel Moolenaar #endif 9953955d011SMarcel Moolenaar } 9963955d011SMarcel Moolenaar s2 = bmake_malloc(sizeof(Src)); 997*2c3632d1SSimon J. Gerraty s2->file = str_concat2(targ->pref, s->name); 9983955d011SMarcel Moolenaar s2->pref = targ->pref; 9993955d011SMarcel Moolenaar s2->parent = targ; 10003955d011SMarcel Moolenaar s2->node = NULL; 10013955d011SMarcel Moolenaar s2->suff = s; 10023955d011SMarcel Moolenaar s->refCount++; 10033955d011SMarcel Moolenaar s2->children = 0; 10043955d011SMarcel Moolenaar targ->children += 1; 1005*2c3632d1SSimon J. Gerraty Lst_Append(ls->l, s2); 10063955d011SMarcel Moolenaar #ifdef DEBUG_SRC 1007*2c3632d1SSimon J. Gerraty s2->cp = Lst_Init(); 1008*2c3632d1SSimon J. Gerraty Lst_Append(targ->cp, s2); 100995e3ed2cSSimon J. Gerraty fprintf(debug_file, "2 add %p %p to %p:", targ, s2, ls->l); 10103955d011SMarcel Moolenaar Lst_ForEach(ls->l, PrintAddr, NULL); 10113955d011SMarcel Moolenaar fprintf(debug_file, "\n"); 10123955d011SMarcel Moolenaar #endif 10133955d011SMarcel Moolenaar 10143841c287SSimon J. Gerraty return 0; 10153955d011SMarcel Moolenaar } 10163955d011SMarcel Moolenaar 1017*2c3632d1SSimon J. Gerraty /* Add all the children of targ as Src structures to the given list. 10183955d011SMarcel Moolenaar * 10193955d011SMarcel Moolenaar * Input: 10203955d011SMarcel Moolenaar * l list to which to add the new level 10213955d011SMarcel Moolenaar * targ Src structure to use as the parent 10223955d011SMarcel Moolenaar */ 10233955d011SMarcel Moolenaar static void 10243955d011SMarcel Moolenaar SuffAddLevel(Lst l, Src *targ) 10253955d011SMarcel Moolenaar { 10263955d011SMarcel Moolenaar LstSrc ls; 10273955d011SMarcel Moolenaar 10283955d011SMarcel Moolenaar ls.s = targ; 10293955d011SMarcel Moolenaar ls.l = l; 10303955d011SMarcel Moolenaar 10313955d011SMarcel Moolenaar Lst_ForEach(targ->suff->children, SuffAddSrc, &ls); 10323955d011SMarcel Moolenaar } 10333955d011SMarcel Moolenaar 1034*2c3632d1SSimon J. Gerraty /* Free the first Src in the list that doesn't have a reference count. 1035*2c3632d1SSimon J. Gerraty * Return whether a Src was removed. */ 1036*2c3632d1SSimon J. Gerraty static Boolean 10373955d011SMarcel Moolenaar SuffRemoveSrc(Lst l) 10383955d011SMarcel Moolenaar { 10393955d011SMarcel Moolenaar LstNode ln; 10403955d011SMarcel Moolenaar Src *s; 10413955d011SMarcel Moolenaar 1042*2c3632d1SSimon J. Gerraty Lst_Open(l); 1043*2c3632d1SSimon J. Gerraty 10443955d011SMarcel Moolenaar #ifdef DEBUG_SRC 10453955d011SMarcel Moolenaar fprintf(debug_file, "cleaning %lx: ", (unsigned long) l); 10463955d011SMarcel Moolenaar Lst_ForEach(l, PrintAddr, NULL); 10473955d011SMarcel Moolenaar fprintf(debug_file, "\n"); 10483955d011SMarcel Moolenaar #endif 10493955d011SMarcel Moolenaar 10503955d011SMarcel Moolenaar while ((ln = Lst_Next(l)) != NULL) { 1051*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 10523955d011SMarcel Moolenaar if (s->children == 0) { 10533955d011SMarcel Moolenaar free(s->file); 10543955d011SMarcel Moolenaar if (!s->parent) 10553955d011SMarcel Moolenaar free(s->pref); 10563955d011SMarcel Moolenaar else { 10573955d011SMarcel Moolenaar #ifdef DEBUG_SRC 1058*2c3632d1SSimon J. Gerraty LstNode ln2 = Lst_FindDatum(s->parent->cp, s); 105995e3ed2cSSimon J. Gerraty if (ln2 != NULL) 106095e3ed2cSSimon J. Gerraty Lst_Remove(s->parent->cp, ln2); 10613955d011SMarcel Moolenaar #endif 10623955d011SMarcel Moolenaar --s->parent->children; 10633955d011SMarcel Moolenaar } 10643955d011SMarcel Moolenaar #ifdef DEBUG_SRC 106595e3ed2cSSimon J. Gerraty fprintf(debug_file, "free: [l=%p] p=%p %d\n", l, s, s->children); 1066*2c3632d1SSimon J. Gerraty Lst_Free(s->cp); 10673955d011SMarcel Moolenaar #endif 10683955d011SMarcel Moolenaar Lst_Remove(l, ln); 10693955d011SMarcel Moolenaar free(s); 10703955d011SMarcel Moolenaar Lst_Close(l); 10713955d011SMarcel Moolenaar return TRUE; 10723955d011SMarcel Moolenaar } 10733955d011SMarcel Moolenaar #ifdef DEBUG_SRC 10743955d011SMarcel Moolenaar else { 107595e3ed2cSSimon J. Gerraty fprintf(debug_file, "keep: [l=%p] p=%p %d: ", l, s, s->children); 10763955d011SMarcel Moolenaar Lst_ForEach(s->cp, PrintAddr, NULL); 10773955d011SMarcel Moolenaar fprintf(debug_file, "\n"); 10783955d011SMarcel Moolenaar } 10793955d011SMarcel Moolenaar #endif 10803955d011SMarcel Moolenaar } 10813955d011SMarcel Moolenaar 10823955d011SMarcel Moolenaar Lst_Close(l); 10833955d011SMarcel Moolenaar 1084*2c3632d1SSimon J. Gerraty return FALSE; 10853955d011SMarcel Moolenaar } 10863955d011SMarcel Moolenaar 1087*2c3632d1SSimon J. Gerraty /* Find the first existing file/target in the list srcs. 10883955d011SMarcel Moolenaar * 10893955d011SMarcel Moolenaar * Input: 10903955d011SMarcel Moolenaar * srcs list of Src structures to search through 10913955d011SMarcel Moolenaar * 10923955d011SMarcel Moolenaar * Results: 1093*2c3632d1SSimon J. Gerraty * The lowest structure in the chain of transformations, or NULL. 10943955d011SMarcel Moolenaar */ 10953955d011SMarcel Moolenaar static Src * 10963955d011SMarcel Moolenaar SuffFindThem(Lst srcs, Lst slst) 10973955d011SMarcel Moolenaar { 10983955d011SMarcel Moolenaar Src *s; /* current Src */ 10993955d011SMarcel Moolenaar Src *rs; /* returned Src */ 11003955d011SMarcel Moolenaar char *ptr; 11013955d011SMarcel Moolenaar 11023955d011SMarcel Moolenaar rs = NULL; 11033955d011SMarcel Moolenaar 11043955d011SMarcel Moolenaar while (!Lst_IsEmpty(srcs)) { 1105*2c3632d1SSimon J. Gerraty s = Lst_Dequeue(srcs); 11063955d011SMarcel Moolenaar 1107*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("\ttrying %s...", s->file); 11083955d011SMarcel Moolenaar 11093955d011SMarcel Moolenaar /* 11103955d011SMarcel Moolenaar * A file is considered to exist if either a node exists in the 11113955d011SMarcel Moolenaar * graph for it or the file actually exists. 11123955d011SMarcel Moolenaar */ 11133955d011SMarcel Moolenaar if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { 11143955d011SMarcel Moolenaar #ifdef DEBUG_SRC 111595e3ed2cSSimon J. Gerraty fprintf(debug_file, "remove %p from %p\n", s, srcs); 11163955d011SMarcel Moolenaar #endif 11173955d011SMarcel Moolenaar rs = s; 11183955d011SMarcel Moolenaar break; 11193955d011SMarcel Moolenaar } 11203955d011SMarcel Moolenaar 11213955d011SMarcel Moolenaar if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) { 11223955d011SMarcel Moolenaar rs = s; 11233955d011SMarcel Moolenaar #ifdef DEBUG_SRC 112495e3ed2cSSimon J. Gerraty fprintf(debug_file, "remove %p from %p\n", s, srcs); 11253955d011SMarcel Moolenaar #endif 11263955d011SMarcel Moolenaar free(ptr); 11273955d011SMarcel Moolenaar break; 11283955d011SMarcel Moolenaar } 11293955d011SMarcel Moolenaar 1130*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("not there\n"); 11313955d011SMarcel Moolenaar 11323955d011SMarcel Moolenaar SuffAddLevel(srcs, s); 1133*2c3632d1SSimon J. Gerraty Lst_Append(slst, s); 11343955d011SMarcel Moolenaar } 11353955d011SMarcel Moolenaar 1136*2c3632d1SSimon J. Gerraty if (rs) { 1137*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("got it\n"); 11383955d011SMarcel Moolenaar } 11393841c287SSimon J. Gerraty return rs; 11403955d011SMarcel Moolenaar } 11413955d011SMarcel Moolenaar 1142*2c3632d1SSimon J. Gerraty /* See if any of the children of the target in the Src structure is one from 1143*2c3632d1SSimon J. Gerraty * which the target can be transformed. If there is one, a Src structure is 1144*2c3632d1SSimon J. Gerraty * put together for it and returned. 11453955d011SMarcel Moolenaar * 11463955d011SMarcel Moolenaar * Input: 1147*2c3632d1SSimon J. Gerraty * targ Src to play with 11483955d011SMarcel Moolenaar * 11493955d011SMarcel Moolenaar * Results: 1150*2c3632d1SSimon J. Gerraty * The Src of the "winning" child, or NULL. 11513955d011SMarcel Moolenaar */ 11523955d011SMarcel Moolenaar static Src * 11533955d011SMarcel Moolenaar SuffFindCmds(Src *targ, Lst slst) 11543955d011SMarcel Moolenaar { 11553955d011SMarcel Moolenaar LstNode ln; /* General-purpose list node */ 11563955d011SMarcel Moolenaar GNode *t, /* Target GNode */ 11573955d011SMarcel Moolenaar *s; /* Source GNode */ 11583955d011SMarcel Moolenaar int prefLen;/* The length of the defined prefix */ 11593955d011SMarcel Moolenaar Suff *suff; /* Suffix on matching beastie */ 11603955d011SMarcel Moolenaar Src *ret; /* Return value */ 11613955d011SMarcel Moolenaar char *cp; 11623955d011SMarcel Moolenaar 11633955d011SMarcel Moolenaar t = targ->node; 1164*2c3632d1SSimon J. Gerraty Lst_Open(t->children); 11653955d011SMarcel Moolenaar prefLen = strlen(targ->pref); 11663955d011SMarcel Moolenaar 11673955d011SMarcel Moolenaar for (;;) { 11683955d011SMarcel Moolenaar ln = Lst_Next(t->children); 11693955d011SMarcel Moolenaar if (ln == NULL) { 11703955d011SMarcel Moolenaar Lst_Close(t->children); 11713955d011SMarcel Moolenaar return NULL; 11723955d011SMarcel Moolenaar } 1173*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 11743955d011SMarcel Moolenaar 11753955d011SMarcel Moolenaar if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->commands)) { 11763955d011SMarcel Moolenaar /* 11773955d011SMarcel Moolenaar * We haven't looked to see if .OPTIONAL files exist yet, so 11783955d011SMarcel Moolenaar * don't use one as the implicit source. 11793955d011SMarcel Moolenaar * This allows us to use .OPTIONAL in .depend files so make won't 11803955d011SMarcel Moolenaar * complain "don't know how to make xxx.h' when a dependent file 11813955d011SMarcel Moolenaar * has been moved/deleted. 11823955d011SMarcel Moolenaar */ 11833955d011SMarcel Moolenaar continue; 11843955d011SMarcel Moolenaar } 11853955d011SMarcel Moolenaar 11863955d011SMarcel Moolenaar cp = strrchr(s->name, '/'); 11873955d011SMarcel Moolenaar if (cp == NULL) { 11883955d011SMarcel Moolenaar cp = s->name; 11893955d011SMarcel Moolenaar } else { 11903955d011SMarcel Moolenaar cp++; 11913955d011SMarcel Moolenaar } 11923955d011SMarcel Moolenaar if (strncmp(cp, targ->pref, prefLen) != 0) 11933955d011SMarcel Moolenaar continue; 11943955d011SMarcel Moolenaar /* 11953955d011SMarcel Moolenaar * The node matches the prefix ok, see if it has a known 11963955d011SMarcel Moolenaar * suffix. 11973955d011SMarcel Moolenaar */ 1198*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, &cp[prefLen]); 11993955d011SMarcel Moolenaar if (ln == NULL) 12003955d011SMarcel Moolenaar continue; 12013955d011SMarcel Moolenaar /* 12023955d011SMarcel Moolenaar * It even has a known suffix, see if there's a transformation 12033955d011SMarcel Moolenaar * defined between the node's suffix and the target's suffix. 12043955d011SMarcel Moolenaar * 12053955d011SMarcel Moolenaar * XXX: Handle multi-stage transformations here, too. 12063955d011SMarcel Moolenaar */ 1207*2c3632d1SSimon J. Gerraty suff = LstNode_Datum(ln); 12083955d011SMarcel Moolenaar 1209*2c3632d1SSimon J. Gerraty /* XXX: Can targ->suff be NULL here? */ 1210*2c3632d1SSimon J. Gerraty if (targ->suff != NULL && 1211*2c3632d1SSimon J. Gerraty Lst_FindDatum(suff->parents, targ->suff) != NULL) 12123955d011SMarcel Moolenaar break; 12133955d011SMarcel Moolenaar } 12143955d011SMarcel Moolenaar 12153955d011SMarcel Moolenaar /* 12163955d011SMarcel Moolenaar * Hot Damn! Create a new Src structure to describe 12173955d011SMarcel Moolenaar * this transformation (making sure to duplicate the 12183955d011SMarcel Moolenaar * source node's name so Suff_FindDeps can free it 12193955d011SMarcel Moolenaar * again (ick)), and return the new structure. 12203955d011SMarcel Moolenaar */ 12213955d011SMarcel Moolenaar ret = bmake_malloc(sizeof(Src)); 12223955d011SMarcel Moolenaar ret->file = bmake_strdup(s->name); 12233955d011SMarcel Moolenaar ret->pref = targ->pref; 12243955d011SMarcel Moolenaar ret->suff = suff; 12253955d011SMarcel Moolenaar suff->refCount++; 12263955d011SMarcel Moolenaar ret->parent = targ; 12273955d011SMarcel Moolenaar ret->node = s; 12283955d011SMarcel Moolenaar ret->children = 0; 12293955d011SMarcel Moolenaar targ->children += 1; 12303955d011SMarcel Moolenaar #ifdef DEBUG_SRC 1231*2c3632d1SSimon J. Gerraty ret->cp = Lst_Init(); 123295e3ed2cSSimon J. Gerraty fprintf(debug_file, "3 add %p %p\n", targ, ret); 1233*2c3632d1SSimon J. Gerraty Lst_Append(targ->cp, ret); 12343955d011SMarcel Moolenaar #endif 1235*2c3632d1SSimon J. Gerraty Lst_Append(slst, ret); 1236*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("\tusing existing source %s\n", s->name); 1237*2c3632d1SSimon J. Gerraty Lst_Close(t->children); 12383841c287SSimon J. Gerraty return ret; 12393955d011SMarcel Moolenaar } 12403955d011SMarcel Moolenaar 1241*2c3632d1SSimon J. Gerraty /* Expand the names of any children of a given node that contain variable 1242*2c3632d1SSimon J. Gerraty * invocations or file wildcards into actual targets. 1243*2c3632d1SSimon J. Gerraty * 1244*2c3632d1SSimon J. Gerraty * The expanded node is removed from the parent's list of children, and the 1245*2c3632d1SSimon J. Gerraty * parent's unmade counter is decremented, but other nodes may be added. 12463955d011SMarcel Moolenaar * 12473955d011SMarcel Moolenaar * Input: 12483955d011SMarcel Moolenaar * cln Child to examine 12493955d011SMarcel Moolenaar * pgn Parent node being processed 12503955d011SMarcel Moolenaar */ 12513955d011SMarcel Moolenaar static void 12523955d011SMarcel Moolenaar SuffExpandChildren(LstNode cln, GNode *pgn) 12533955d011SMarcel Moolenaar { 1254*2c3632d1SSimon J. Gerraty GNode *cgn = LstNode_Datum(cln); 12553955d011SMarcel Moolenaar GNode *gn; /* New source 8) */ 12563955d011SMarcel Moolenaar char *cp; /* Expanded value */ 12573955d011SMarcel Moolenaar 12583955d011SMarcel Moolenaar if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ)) 12593955d011SMarcel Moolenaar /* It is all too hard to process the result of .ORDER */ 12603955d011SMarcel Moolenaar return; 12613955d011SMarcel Moolenaar 12623955d011SMarcel Moolenaar if (cgn->type & OP_WAIT) 12633955d011SMarcel Moolenaar /* Ignore these (& OP_PHONY ?) */ 12643955d011SMarcel Moolenaar return; 12653955d011SMarcel Moolenaar 12663955d011SMarcel Moolenaar /* 12673955d011SMarcel Moolenaar * First do variable expansion -- this takes precedence over 12683955d011SMarcel Moolenaar * wildcard expansion. If the result contains wildcards, they'll be gotten 12693955d011SMarcel Moolenaar * to later since the resulting words are tacked on to the end of 12703955d011SMarcel Moolenaar * the children list. 12713955d011SMarcel Moolenaar */ 12723955d011SMarcel Moolenaar if (strchr(cgn->name, '$') == NULL) { 12733955d011SMarcel Moolenaar SuffExpandWildcards(cln, pgn); 12743955d011SMarcel Moolenaar return; 12753955d011SMarcel Moolenaar } 12763955d011SMarcel Moolenaar 1277*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("Expanding \"%s\"...", cgn->name); 1278*2c3632d1SSimon J. Gerraty cp = Var_Subst(cgn->name, pgn, VARE_UNDEFERR|VARE_WANTRES); 12793955d011SMarcel Moolenaar 1280*2c3632d1SSimon J. Gerraty { 1281*2c3632d1SSimon J. Gerraty Lst members = Lst_Init(); 12823955d011SMarcel Moolenaar 12833955d011SMarcel Moolenaar if (cgn->type & OP_ARCHV) { 12843955d011SMarcel Moolenaar /* 12853955d011SMarcel Moolenaar * Node was an archive(member) target, so we want to call 12863955d011SMarcel Moolenaar * on the Arch module to find the nodes for us, expanding 12873955d011SMarcel Moolenaar * variables in the parent's context. 12883955d011SMarcel Moolenaar */ 12893955d011SMarcel Moolenaar char *sacrifice = cp; 12903955d011SMarcel Moolenaar 12913955d011SMarcel Moolenaar (void)Arch_ParseArchive(&sacrifice, members, pgn); 12923955d011SMarcel Moolenaar } else { 12933955d011SMarcel Moolenaar /* 12943955d011SMarcel Moolenaar * Break the result into a vector of strings whose nodes 12953955d011SMarcel Moolenaar * we can find, then add those nodes to the members list. 12963955d011SMarcel Moolenaar * Unfortunately, we can't use brk_string b/c it 12973955d011SMarcel Moolenaar * doesn't understand about variable specifications with 12983955d011SMarcel Moolenaar * spaces in them... 12993955d011SMarcel Moolenaar */ 13003955d011SMarcel Moolenaar char *start; 13013955d011SMarcel Moolenaar char *initcp = cp; /* For freeing... */ 13023955d011SMarcel Moolenaar 13033955d011SMarcel Moolenaar for (start = cp; *start == ' ' || *start == '\t'; start++) 13043955d011SMarcel Moolenaar continue; 13053955d011SMarcel Moolenaar for (cp = start; *cp != '\0'; cp++) { 13063955d011SMarcel Moolenaar if (*cp == ' ' || *cp == '\t') { 13073955d011SMarcel Moolenaar /* 13083955d011SMarcel Moolenaar * White-space -- terminate element, find the node, 13093955d011SMarcel Moolenaar * add it, skip any further spaces. 13103955d011SMarcel Moolenaar */ 13113955d011SMarcel Moolenaar *cp++ = '\0'; 13123955d011SMarcel Moolenaar gn = Targ_FindNode(start, TARG_CREATE); 1313*2c3632d1SSimon J. Gerraty Lst_Append(members, gn); 13143955d011SMarcel Moolenaar while (*cp == ' ' || *cp == '\t') { 13153955d011SMarcel Moolenaar cp++; 13163955d011SMarcel Moolenaar } 13173955d011SMarcel Moolenaar /* 13183955d011SMarcel Moolenaar * Adjust cp for increment at start of loop, but 13193955d011SMarcel Moolenaar * set start to first non-space. 13203955d011SMarcel Moolenaar */ 13213955d011SMarcel Moolenaar start = cp--; 13223955d011SMarcel Moolenaar } else if (*cp == '$') { 13233955d011SMarcel Moolenaar /* 13243955d011SMarcel Moolenaar * Start of a variable spec -- contact variable module 13253955d011SMarcel Moolenaar * to find the end so we can skip over it. 13263955d011SMarcel Moolenaar */ 1327*2c3632d1SSimon J. Gerraty const char *junk; 13283955d011SMarcel Moolenaar int len; 13293955d011SMarcel Moolenaar void *freeIt; 13303955d011SMarcel Moolenaar 1331*2c3632d1SSimon J. Gerraty junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES, 1332be19d90bSSimon J. Gerraty &len, &freeIt); 13333955d011SMarcel Moolenaar if (junk != var_Error) { 13343955d011SMarcel Moolenaar cp += len - 1; 13353955d011SMarcel Moolenaar } 13363955d011SMarcel Moolenaar 13373955d011SMarcel Moolenaar free(freeIt); 133895e3ed2cSSimon J. Gerraty } else if (*cp == '\\' && cp[1] != '\0') { 13393955d011SMarcel Moolenaar /* 13403955d011SMarcel Moolenaar * Escaped something -- skip over it 13413955d011SMarcel Moolenaar */ 13423955d011SMarcel Moolenaar cp++; 13433955d011SMarcel Moolenaar } 13443955d011SMarcel Moolenaar } 13453955d011SMarcel Moolenaar 13463955d011SMarcel Moolenaar if (cp != start) { 13473955d011SMarcel Moolenaar /* 13483955d011SMarcel Moolenaar * Stuff left over -- add it to the list too 13493955d011SMarcel Moolenaar */ 13503955d011SMarcel Moolenaar gn = Targ_FindNode(start, TARG_CREATE); 1351*2c3632d1SSimon J. Gerraty Lst_Append(members, gn); 13523955d011SMarcel Moolenaar } 13533955d011SMarcel Moolenaar /* 13543955d011SMarcel Moolenaar * Point cp back at the beginning again so the variable value 13553955d011SMarcel Moolenaar * can be freed. 13563955d011SMarcel Moolenaar */ 13573955d011SMarcel Moolenaar cp = initcp; 13583955d011SMarcel Moolenaar } 13593955d011SMarcel Moolenaar 13603955d011SMarcel Moolenaar /* 13613955d011SMarcel Moolenaar * Add all elements of the members list to the parent node. 13623955d011SMarcel Moolenaar */ 13633955d011SMarcel Moolenaar while(!Lst_IsEmpty(members)) { 1364*2c3632d1SSimon J. Gerraty gn = Lst_Dequeue(members); 13653955d011SMarcel Moolenaar 1366*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("%s...", gn->name); 13673955d011SMarcel Moolenaar /* Add gn to the parents child list before the original child */ 1368*2c3632d1SSimon J. Gerraty Lst_InsertBefore(pgn->children, cln, gn); 1369*2c3632d1SSimon J. Gerraty Lst_Append(gn->parents, pgn); 13703955d011SMarcel Moolenaar pgn->unmade++; 13713955d011SMarcel Moolenaar /* Expand wildcards on new node */ 1372*2c3632d1SSimon J. Gerraty SuffExpandWildcards(LstNode_Prev(cln), pgn); 13733955d011SMarcel Moolenaar } 1374*2c3632d1SSimon J. Gerraty Lst_Free(members); 13753955d011SMarcel Moolenaar 13763955d011SMarcel Moolenaar /* 13773955d011SMarcel Moolenaar * Free the result 13783955d011SMarcel Moolenaar */ 13793955d011SMarcel Moolenaar free(cp); 13803955d011SMarcel Moolenaar } 1381*2c3632d1SSimon J. Gerraty 1382*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("\n"); 13833955d011SMarcel Moolenaar 13843955d011SMarcel Moolenaar /* 13853955d011SMarcel Moolenaar * Now the source is expanded, remove it from the list of children to 13863955d011SMarcel Moolenaar * keep it from being processed. 13873955d011SMarcel Moolenaar */ 13883955d011SMarcel Moolenaar pgn->unmade--; 13893955d011SMarcel Moolenaar Lst_Remove(pgn->children, cln); 1390*2c3632d1SSimon J. Gerraty Lst_Remove(cgn->parents, Lst_FindDatum(cgn->parents, pgn)); 13913955d011SMarcel Moolenaar } 13923955d011SMarcel Moolenaar 13933955d011SMarcel Moolenaar static void 13943955d011SMarcel Moolenaar SuffExpandWildcards(LstNode cln, GNode *pgn) 13953955d011SMarcel Moolenaar { 1396*2c3632d1SSimon J. Gerraty GNode *cgn = LstNode_Datum(cln); 13973955d011SMarcel Moolenaar GNode *gn; /* New source 8) */ 13983955d011SMarcel Moolenaar char *cp; /* Expanded value */ 13993955d011SMarcel Moolenaar Lst explist; /* List of expansions */ 14003955d011SMarcel Moolenaar 14013955d011SMarcel Moolenaar if (!Dir_HasWildcards(cgn->name)) 14023955d011SMarcel Moolenaar return; 14033955d011SMarcel Moolenaar 14043955d011SMarcel Moolenaar /* 14053955d011SMarcel Moolenaar * Expand the word along the chosen path 14063955d011SMarcel Moolenaar */ 1407*2c3632d1SSimon J. Gerraty explist = Lst_Init(); 14083955d011SMarcel Moolenaar Dir_Expand(cgn->name, Suff_FindPath(cgn), explist); 14093955d011SMarcel Moolenaar 14103955d011SMarcel Moolenaar while (!Lst_IsEmpty(explist)) { 14113955d011SMarcel Moolenaar /* 14123955d011SMarcel Moolenaar * Fetch next expansion off the list and find its GNode 14133955d011SMarcel Moolenaar */ 1414*2c3632d1SSimon J. Gerraty cp = Lst_Dequeue(explist); 14153955d011SMarcel Moolenaar 1416*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("%s...", cp); 14173955d011SMarcel Moolenaar gn = Targ_FindNode(cp, TARG_CREATE); 14183955d011SMarcel Moolenaar 14193955d011SMarcel Moolenaar /* Add gn to the parents child list before the original child */ 1420*2c3632d1SSimon J. Gerraty Lst_InsertBefore(pgn->children, cln, gn); 1421*2c3632d1SSimon J. Gerraty Lst_Append(gn->parents, pgn); 14223955d011SMarcel Moolenaar pgn->unmade++; 14233955d011SMarcel Moolenaar } 14243955d011SMarcel Moolenaar 1425*2c3632d1SSimon J. Gerraty Lst_Free(explist); 14263955d011SMarcel Moolenaar 1427*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("\n"); 14283955d011SMarcel Moolenaar 14293955d011SMarcel Moolenaar /* 14303955d011SMarcel Moolenaar * Now the source is expanded, remove it from the list of children to 14313955d011SMarcel Moolenaar * keep it from being processed. 14323955d011SMarcel Moolenaar */ 14333955d011SMarcel Moolenaar pgn->unmade--; 14343955d011SMarcel Moolenaar Lst_Remove(pgn->children, cln); 1435*2c3632d1SSimon J. Gerraty Lst_Remove(cgn->parents, Lst_FindDatum(cgn->parents, pgn)); 14363955d011SMarcel Moolenaar } 14373955d011SMarcel Moolenaar 1438*2c3632d1SSimon J. Gerraty /* Find a path along which to expand the node. 14393955d011SMarcel Moolenaar * 14403955d011SMarcel Moolenaar * If the word has a known suffix, use that path. 14413955d011SMarcel Moolenaar * If it has no known suffix, use the default system search path. 14423955d011SMarcel Moolenaar * 14433955d011SMarcel Moolenaar * Input: 14443955d011SMarcel Moolenaar * gn Node being examined 14453955d011SMarcel Moolenaar * 14463955d011SMarcel Moolenaar * Results: 14473955d011SMarcel Moolenaar * The appropriate path to search for the GNode. 14483955d011SMarcel Moolenaar */ 14493955d011SMarcel Moolenaar Lst 14503955d011SMarcel Moolenaar Suff_FindPath(GNode* gn) 14513955d011SMarcel Moolenaar { 14523955d011SMarcel Moolenaar Suff *suff = gn->suffix; 14533955d011SMarcel Moolenaar 14543955d011SMarcel Moolenaar if (suff == NULL) { 1455*2c3632d1SSimon J. Gerraty SuffSuffGetSuffixArgs sd; /* Search string data */ 14563955d011SMarcel Moolenaar LstNode ln; 14573955d011SMarcel Moolenaar sd.len = strlen(gn->name); 14583955d011SMarcel Moolenaar sd.ename = gn->name + sd.len; 1459*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffIsSuffix, &sd); 14603955d011SMarcel Moolenaar 1461*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("Wildcard expanding \"%s\"...", gn->name); 14623955d011SMarcel Moolenaar if (ln != NULL) 1463*2c3632d1SSimon J. Gerraty suff = LstNode_Datum(ln); 14643955d011SMarcel Moolenaar /* XXX: Here we can save the suffix so we don't have to do this again */ 14653955d011SMarcel Moolenaar } 14663955d011SMarcel Moolenaar 14673955d011SMarcel Moolenaar if (suff != NULL) { 1468*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("suffix is \"%s\"...", suff->name); 14693955d011SMarcel Moolenaar return suff->searchPath; 14703955d011SMarcel Moolenaar } else { 14713955d011SMarcel Moolenaar /* 14723955d011SMarcel Moolenaar * Use default search path 14733955d011SMarcel Moolenaar */ 14743955d011SMarcel Moolenaar return dirSearchPath; 14753955d011SMarcel Moolenaar } 14763955d011SMarcel Moolenaar } 14773955d011SMarcel Moolenaar 1478*2c3632d1SSimon J. Gerraty /* Apply a transformation rule, given the source and target nodes and 1479*2c3632d1SSimon J. Gerraty * suffixes. 14803955d011SMarcel Moolenaar * 14813955d011SMarcel Moolenaar * Input: 14823955d011SMarcel Moolenaar * tGn Target node 14833955d011SMarcel Moolenaar * sGn Source node 14843955d011SMarcel Moolenaar * t Target suffix 14853955d011SMarcel Moolenaar * s Source suffix 14863955d011SMarcel Moolenaar * 14873955d011SMarcel Moolenaar * Results: 14883955d011SMarcel Moolenaar * TRUE if successful, FALSE if not. 14893955d011SMarcel Moolenaar * 14903955d011SMarcel Moolenaar * Side Effects: 14913955d011SMarcel Moolenaar * The source and target are linked and the commands from the 14923955d011SMarcel Moolenaar * transformation are added to the target node's commands list. 14933955d011SMarcel Moolenaar * All attributes but OP_DEPMASK and OP_TRANSFORM are applied 14943955d011SMarcel Moolenaar * to the target. The target also inherits all the sources for 14953955d011SMarcel Moolenaar * the transformation rule. 14963955d011SMarcel Moolenaar */ 14973955d011SMarcel Moolenaar static Boolean 14983955d011SMarcel Moolenaar SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) 14993955d011SMarcel Moolenaar { 15003955d011SMarcel Moolenaar LstNode ln, nln; /* General node */ 15013955d011SMarcel Moolenaar char *tname; /* Name of transformation rule */ 15023955d011SMarcel Moolenaar GNode *gn; /* Node for same */ 15033955d011SMarcel Moolenaar 15043955d011SMarcel Moolenaar /* 15053955d011SMarcel Moolenaar * Form the proper links between the target and source. 15063955d011SMarcel Moolenaar */ 1507*2c3632d1SSimon J. Gerraty Lst_Append(tGn->children, sGn); 1508*2c3632d1SSimon J. Gerraty Lst_Append(sGn->parents, tGn); 15093955d011SMarcel Moolenaar tGn->unmade += 1; 15103955d011SMarcel Moolenaar 15113955d011SMarcel Moolenaar /* 15123955d011SMarcel Moolenaar * Locate the transformation rule itself 15133955d011SMarcel Moolenaar */ 1514*2c3632d1SSimon J. Gerraty tname = str_concat2(s->name, t->name); 1515*2c3632d1SSimon J. Gerraty ln = Lst_Find(transforms, SuffGNHasName, tname); 15163955d011SMarcel Moolenaar free(tname); 15173955d011SMarcel Moolenaar 15183955d011SMarcel Moolenaar if (ln == NULL) { 15193955d011SMarcel Moolenaar /* 15203955d011SMarcel Moolenaar * Not really such a transformation rule (can happen when we're 15213955d011SMarcel Moolenaar * called to link an OP_MEMBER and OP_ARCHV node), so return 15223955d011SMarcel Moolenaar * FALSE. 15233955d011SMarcel Moolenaar */ 15243841c287SSimon J. Gerraty return FALSE; 15253955d011SMarcel Moolenaar } 15263955d011SMarcel Moolenaar 1527*2c3632d1SSimon J. Gerraty gn = LstNode_Datum(ln); 15283955d011SMarcel Moolenaar 1529*2c3632d1SSimon J. Gerraty SUFF_DEBUG3("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); 15303955d011SMarcel Moolenaar 15313955d011SMarcel Moolenaar /* 15323955d011SMarcel Moolenaar * Record last child for expansion purposes 15333955d011SMarcel Moolenaar */ 15343955d011SMarcel Moolenaar ln = Lst_Last(tGn->children); 15353955d011SMarcel Moolenaar 15363955d011SMarcel Moolenaar /* 15373955d011SMarcel Moolenaar * Pass the buck to Make_HandleUse to apply the rule 15383955d011SMarcel Moolenaar */ 15393955d011SMarcel Moolenaar (void)Make_HandleUse(gn, tGn); 15403955d011SMarcel Moolenaar 15413955d011SMarcel Moolenaar /* 15423955d011SMarcel Moolenaar * Deal with wildcards and variables in any acquired sources 15433955d011SMarcel Moolenaar */ 1544*2c3632d1SSimon J. Gerraty for (ln = ln != NULL ? LstNode_Next(ln) : NULL; ln != NULL; ln = nln) { 1545*2c3632d1SSimon J. Gerraty nln = LstNode_Next(ln); 15463955d011SMarcel Moolenaar SuffExpandChildren(ln, tGn); 15473955d011SMarcel Moolenaar } 15483955d011SMarcel Moolenaar 15493955d011SMarcel Moolenaar /* 15503955d011SMarcel Moolenaar * Keep track of another parent to which this beast is transformed so 15513955d011SMarcel Moolenaar * the .IMPSRC variable can be set correctly for the parent. 15523955d011SMarcel Moolenaar */ 1553*2c3632d1SSimon J. Gerraty Lst_Append(sGn->implicitParents, tGn); 15543955d011SMarcel Moolenaar 15553841c287SSimon J. Gerraty return TRUE; 15563955d011SMarcel Moolenaar } 15573955d011SMarcel Moolenaar 15583955d011SMarcel Moolenaar 1559*2c3632d1SSimon J. Gerraty /* Locate dependencies for an OP_ARCHV node. 15603955d011SMarcel Moolenaar * 15613955d011SMarcel Moolenaar * Input: 15623955d011SMarcel Moolenaar * gn Node for which to locate dependencies 15633955d011SMarcel Moolenaar * 15643955d011SMarcel Moolenaar * Side Effects: 15653955d011SMarcel Moolenaar * Same as Suff_FindDeps 15663955d011SMarcel Moolenaar */ 15673955d011SMarcel Moolenaar static void 15683955d011SMarcel Moolenaar SuffFindArchiveDeps(GNode *gn, Lst slst) 15693955d011SMarcel Moolenaar { 15703955d011SMarcel Moolenaar char *eoarch; /* End of archive portion */ 15713955d011SMarcel Moolenaar char *eoname; /* End of member portion */ 15723955d011SMarcel Moolenaar GNode *mem; /* Node for member */ 15733bebe729SSimon J. Gerraty LstNode ln, nln; /* Next suffix node to check */ 15743955d011SMarcel Moolenaar Suff *ms; /* Suffix descriptor for member */ 15753955d011SMarcel Moolenaar char *name; /* Start of member's name */ 15763955d011SMarcel Moolenaar 15773955d011SMarcel Moolenaar /* 15783955d011SMarcel Moolenaar * The node is an archive(member) pair. so we must find a 15793955d011SMarcel Moolenaar * suffix for both of them. 15803955d011SMarcel Moolenaar */ 15813955d011SMarcel Moolenaar eoarch = strchr(gn->name, '('); 15823955d011SMarcel Moolenaar eoname = strchr(eoarch, ')'); 15833955d011SMarcel Moolenaar 1584e1cee40dSSimon J. Gerraty /* 1585e1cee40dSSimon J. Gerraty * Caller guarantees the format `libname(member)', via 1586e1cee40dSSimon J. Gerraty * Arch_ParseArchive. 1587e1cee40dSSimon J. Gerraty */ 1588e1cee40dSSimon J. Gerraty assert(eoarch != NULL); 1589e1cee40dSSimon J. Gerraty assert(eoname != NULL); 1590e1cee40dSSimon J. Gerraty 15913955d011SMarcel Moolenaar *eoname = '\0'; /* Nuke parentheses during suffix search */ 15923955d011SMarcel Moolenaar *eoarch = '\0'; /* So a suffix can be found */ 15933955d011SMarcel Moolenaar 15943955d011SMarcel Moolenaar name = eoarch + 1; 15953955d011SMarcel Moolenaar 15963955d011SMarcel Moolenaar /* 15973955d011SMarcel Moolenaar * To simplify things, call Suff_FindDeps recursively on the member now, 15983955d011SMarcel Moolenaar * so we can simply compare the member's .PREFIX and .TARGET variables 15993955d011SMarcel Moolenaar * to locate its suffix. This allows us to figure out the suffix to 16003955d011SMarcel Moolenaar * use for the archive without having to do a quadratic search over the 16013955d011SMarcel Moolenaar * suffix list, backtracking for each one... 16023955d011SMarcel Moolenaar */ 16033955d011SMarcel Moolenaar mem = Targ_FindNode(name, TARG_CREATE); 16043955d011SMarcel Moolenaar SuffFindDeps(mem, slst); 16053955d011SMarcel Moolenaar 16063955d011SMarcel Moolenaar /* 16073955d011SMarcel Moolenaar * Create the link between the two nodes right off 16083955d011SMarcel Moolenaar */ 1609*2c3632d1SSimon J. Gerraty Lst_Append(gn->children, mem); 1610*2c3632d1SSimon J. Gerraty Lst_Append(mem->parents, gn); 16113955d011SMarcel Moolenaar gn->unmade += 1; 16123955d011SMarcel Moolenaar 16133955d011SMarcel Moolenaar /* 16143955d011SMarcel Moolenaar * Copy in the variables from the member node to this one. 16153955d011SMarcel Moolenaar */ 1616*2c3632d1SSimon J. Gerraty { 1617*2c3632d1SSimon J. Gerraty char *freeIt; 1618*2c3632d1SSimon J. Gerraty Var_Set(PREFIX, Var_Value(PREFIX, mem, &freeIt), gn); 1619*2c3632d1SSimon J. Gerraty bmake_free(freeIt); 1620*2c3632d1SSimon J. Gerraty Var_Set(TARGET, Var_Value(TARGET, mem, &freeIt), gn); 1621*2c3632d1SSimon J. Gerraty bmake_free(freeIt); 16223955d011SMarcel Moolenaar } 16233955d011SMarcel Moolenaar 16243955d011SMarcel Moolenaar ms = mem->suffix; 16253955d011SMarcel Moolenaar if (ms == NULL) { 16263955d011SMarcel Moolenaar /* 16273955d011SMarcel Moolenaar * Didn't know what it was -- use .NULL suffix if not in make mode 16283955d011SMarcel Moolenaar */ 1629*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("using null suffix\n"); 16303955d011SMarcel Moolenaar ms = suffNull; 16313955d011SMarcel Moolenaar } 16323955d011SMarcel Moolenaar 16333955d011SMarcel Moolenaar 16343955d011SMarcel Moolenaar /* 16353955d011SMarcel Moolenaar * Set the other two local variables required for this target. 16363955d011SMarcel Moolenaar */ 16373841c287SSimon J. Gerraty Var_Set(MEMBER, name, gn); 16383841c287SSimon J. Gerraty Var_Set(ARCHIVE, gn->name, gn); 16393955d011SMarcel Moolenaar 16403bebe729SSimon J. Gerraty /* 16413bebe729SSimon J. Gerraty * Set $@ for compatibility with other makes 16423bebe729SSimon J. Gerraty */ 16433841c287SSimon J. Gerraty Var_Set(TARGET, gn->name, gn); 16443bebe729SSimon J. Gerraty 16453bebe729SSimon J. Gerraty /* 16463bebe729SSimon J. Gerraty * Now we've got the important local variables set, expand any sources 16473bebe729SSimon J. Gerraty * that still contain variables or wildcards in their names. 16483bebe729SSimon J. Gerraty */ 16493bebe729SSimon J. Gerraty for (ln = Lst_First(gn->children); ln != NULL; ln = nln) { 1650*2c3632d1SSimon J. Gerraty nln = LstNode_Next(ln); 16513bebe729SSimon J. Gerraty SuffExpandChildren(ln, gn); 16523bebe729SSimon J. Gerraty } 16533bebe729SSimon J. Gerraty 16543955d011SMarcel Moolenaar if (ms != NULL) { 16553955d011SMarcel Moolenaar /* 16563955d011SMarcel Moolenaar * Member has a known suffix, so look for a transformation rule from 16573955d011SMarcel Moolenaar * it to a possible suffix of the archive. Rather than searching 16583955d011SMarcel Moolenaar * through the entire list, we just look at suffixes to which the 16593955d011SMarcel Moolenaar * member's suffix may be transformed... 16603955d011SMarcel Moolenaar */ 1661*2c3632d1SSimon J. Gerraty SuffSuffGetSuffixArgs sd; /* Search string data */ 16623955d011SMarcel Moolenaar 16633955d011SMarcel Moolenaar /* 16643955d011SMarcel Moolenaar * Use first matching suffix... 16653955d011SMarcel Moolenaar */ 16663955d011SMarcel Moolenaar sd.len = eoarch - gn->name; 16673955d011SMarcel Moolenaar sd.ename = eoarch; 1668*2c3632d1SSimon J. Gerraty ln = Lst_Find(ms->parents, SuffSuffIsSuffix, &sd); 16693955d011SMarcel Moolenaar 16703955d011SMarcel Moolenaar if (ln != NULL) { 16713955d011SMarcel Moolenaar /* 16723955d011SMarcel Moolenaar * Got one -- apply it 16733955d011SMarcel Moolenaar */ 1674*2c3632d1SSimon J. Gerraty Suff *suff = LstNode_Datum(ln); 1675*2c3632d1SSimon J. Gerraty if (!SuffApplyTransform(gn, mem, suff, ms)) { 1676*2c3632d1SSimon J. Gerraty SUFF_DEBUG2("\tNo transformation from %s -> %s\n", 1677*2c3632d1SSimon J. Gerraty ms->name, suff->name); 16783955d011SMarcel Moolenaar } 16793955d011SMarcel Moolenaar } 16803955d011SMarcel Moolenaar } 16813955d011SMarcel Moolenaar 16823955d011SMarcel Moolenaar /* 16833955d011SMarcel Moolenaar * Replace the opening and closing parens now we've no need of the separate 16843955d011SMarcel Moolenaar * pieces. 16853955d011SMarcel Moolenaar */ 16863955d011SMarcel Moolenaar *eoarch = '('; *eoname = ')'; 16873955d011SMarcel Moolenaar 16883955d011SMarcel Moolenaar /* 16893955d011SMarcel Moolenaar * Pretend gn appeared to the left of a dependency operator so 16903955d011SMarcel Moolenaar * the user needn't provide a transformation from the member to the 16913955d011SMarcel Moolenaar * archive. 16923955d011SMarcel Moolenaar */ 16933955d011SMarcel Moolenaar if (OP_NOP(gn->type)) { 16943955d011SMarcel Moolenaar gn->type |= OP_DEPENDS; 16953955d011SMarcel Moolenaar } 16963955d011SMarcel Moolenaar 16973955d011SMarcel Moolenaar /* 16983955d011SMarcel Moolenaar * Flag the member as such so we remember to look in the archive for 16993bebe729SSimon J. Gerraty * its modification time. The OP_JOIN | OP_MADE is needed because this 17003bebe729SSimon J. Gerraty * target should never get made. 17013955d011SMarcel Moolenaar */ 17023bebe729SSimon J. Gerraty mem->type |= OP_MEMBER | OP_JOIN | OP_MADE; 17033955d011SMarcel Moolenaar } 17043955d011SMarcel Moolenaar 1705*2c3632d1SSimon J. Gerraty /* Locate implicit dependencies for regular targets. 17063955d011SMarcel Moolenaar * 17073955d011SMarcel Moolenaar * Input: 17083955d011SMarcel Moolenaar * gn Node for which to find sources 17093955d011SMarcel Moolenaar * 17103955d011SMarcel Moolenaar * Side Effects: 1711*2c3632d1SSimon J. Gerraty * Same as Suff_FindDeps 17123955d011SMarcel Moolenaar */ 17133955d011SMarcel Moolenaar static void 17143955d011SMarcel Moolenaar SuffFindNormalDeps(GNode *gn, Lst slst) 17153955d011SMarcel Moolenaar { 17163955d011SMarcel Moolenaar char *eoname; /* End of name */ 17173955d011SMarcel Moolenaar char *sopref; /* Start of prefix */ 17183955d011SMarcel Moolenaar LstNode ln, nln; /* Next suffix node to check */ 17193955d011SMarcel Moolenaar Lst srcs; /* List of sources at which to look */ 17203955d011SMarcel Moolenaar Lst targs; /* List of targets to which things can be 17213955d011SMarcel Moolenaar * transformed. They all have the same file, 17223955d011SMarcel Moolenaar * but different suff and pref fields */ 17233955d011SMarcel Moolenaar Src *bottom; /* Start of found transformation path */ 17243955d011SMarcel Moolenaar Src *src; /* General Src pointer */ 17253955d011SMarcel Moolenaar char *pref; /* Prefix to use */ 17263955d011SMarcel Moolenaar Src *targ; /* General Src target pointer */ 1727*2c3632d1SSimon J. Gerraty SuffSuffGetSuffixArgs sd; /* Search string data */ 17283955d011SMarcel Moolenaar 17293955d011SMarcel Moolenaar 17303955d011SMarcel Moolenaar sd.len = strlen(gn->name); 17313955d011SMarcel Moolenaar sd.ename = eoname = gn->name + sd.len; 17323955d011SMarcel Moolenaar 17333955d011SMarcel Moolenaar sopref = gn->name; 17343955d011SMarcel Moolenaar 17353955d011SMarcel Moolenaar /* 17363955d011SMarcel Moolenaar * Begin at the beginning... 17373955d011SMarcel Moolenaar */ 17383955d011SMarcel Moolenaar ln = Lst_First(sufflist); 1739*2c3632d1SSimon J. Gerraty srcs = Lst_Init(); 1740*2c3632d1SSimon J. Gerraty targs = Lst_Init(); 17413955d011SMarcel Moolenaar 17423955d011SMarcel Moolenaar /* 17433955d011SMarcel Moolenaar * We're caught in a catch-22 here. On the one hand, we want to use any 17443955d011SMarcel Moolenaar * transformation implied by the target's sources, but we can't examine 17453955d011SMarcel Moolenaar * the sources until we've expanded any variables/wildcards they may hold, 17463955d011SMarcel Moolenaar * and we can't do that until we've set up the target's local variables 17473955d011SMarcel Moolenaar * and we can't do that until we know what the proper suffix for the 17483955d011SMarcel Moolenaar * target is (in case there are two suffixes one of which is a suffix of 17493955d011SMarcel Moolenaar * the other) and we can't know that until we've found its implied 17503955d011SMarcel Moolenaar * source, which we may not want to use if there's an existing source 17513955d011SMarcel Moolenaar * that implies a different transformation. 17523955d011SMarcel Moolenaar * 17533955d011SMarcel Moolenaar * In an attempt to get around this, which may not work all the time, 17543955d011SMarcel Moolenaar * but should work most of the time, we look for implied sources first, 17553955d011SMarcel Moolenaar * checking transformations to all possible suffixes of the target, 17563955d011SMarcel Moolenaar * use what we find to set the target's local variables, expand the 17573955d011SMarcel Moolenaar * children, then look for any overriding transformations they imply. 17583955d011SMarcel Moolenaar * Should we find one, we discard the one we found before. 17593955d011SMarcel Moolenaar */ 17604fc82fe4SSimon J. Gerraty bottom = NULL; 17614fc82fe4SSimon J. Gerraty targ = NULL; 17624fc82fe4SSimon J. Gerraty 17634fc82fe4SSimon J. Gerraty if (!(gn->type & OP_PHONY)) { 17643955d011SMarcel Moolenaar 17653955d011SMarcel Moolenaar while (ln != NULL) { 17663955d011SMarcel Moolenaar /* 17673955d011SMarcel Moolenaar * Look for next possible suffix... 17683955d011SMarcel Moolenaar */ 1769*2c3632d1SSimon J. Gerraty ln = Lst_FindFrom(sufflist, ln, SuffSuffIsSuffix, &sd); 17703955d011SMarcel Moolenaar 17713955d011SMarcel Moolenaar if (ln != NULL) { 1772*2c3632d1SSimon J. Gerraty const char *eopref; 17733955d011SMarcel Moolenaar 17743955d011SMarcel Moolenaar /* 17753955d011SMarcel Moolenaar * Allocate a Src structure to which things can be transformed 17763955d011SMarcel Moolenaar */ 17773955d011SMarcel Moolenaar targ = bmake_malloc(sizeof(Src)); 17783955d011SMarcel Moolenaar targ->file = bmake_strdup(gn->name); 1779*2c3632d1SSimon J. Gerraty targ->suff = LstNode_Datum(ln); 17803955d011SMarcel Moolenaar targ->suff->refCount++; 17813955d011SMarcel Moolenaar targ->node = gn; 17823955d011SMarcel Moolenaar targ->parent = NULL; 17833955d011SMarcel Moolenaar targ->children = 0; 17843955d011SMarcel Moolenaar #ifdef DEBUG_SRC 1785*2c3632d1SSimon J. Gerraty targ->cp = Lst_Init(); 17863955d011SMarcel Moolenaar #endif 17873955d011SMarcel Moolenaar 1788*2c3632d1SSimon J. Gerraty eopref = eoname - targ->suff->nameLen; 1789*2c3632d1SSimon J. Gerraty targ->pref = bmake_strsedup(sopref, eopref); 17903955d011SMarcel Moolenaar 17913955d011SMarcel Moolenaar /* 17923955d011SMarcel Moolenaar * Add nodes from which the target can be made 17933955d011SMarcel Moolenaar */ 17943955d011SMarcel Moolenaar SuffAddLevel(srcs, targ); 17953955d011SMarcel Moolenaar 17963955d011SMarcel Moolenaar /* 17973955d011SMarcel Moolenaar * Record the target so we can nuke it 17983955d011SMarcel Moolenaar */ 1799*2c3632d1SSimon J. Gerraty Lst_Append(targs, targ); 18003955d011SMarcel Moolenaar 18013955d011SMarcel Moolenaar /* 18023955d011SMarcel Moolenaar * Search from this suffix's successor... 18033955d011SMarcel Moolenaar */ 1804*2c3632d1SSimon J. Gerraty ln = LstNode_Next(ln); 18053955d011SMarcel Moolenaar } 18063955d011SMarcel Moolenaar } 18073955d011SMarcel Moolenaar 18083955d011SMarcel Moolenaar /* 18093955d011SMarcel Moolenaar * Handle target of unknown suffix... 18103955d011SMarcel Moolenaar */ 18113955d011SMarcel Moolenaar if (Lst_IsEmpty(targs) && suffNull != NULL) { 1812*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("\tNo known suffix on %s. Using .NULL suffix\n", 1813*2c3632d1SSimon J. Gerraty gn->name); 18143955d011SMarcel Moolenaar 18153955d011SMarcel Moolenaar targ = bmake_malloc(sizeof(Src)); 18163955d011SMarcel Moolenaar targ->file = bmake_strdup(gn->name); 18173955d011SMarcel Moolenaar targ->suff = suffNull; 18183955d011SMarcel Moolenaar targ->suff->refCount++; 18193955d011SMarcel Moolenaar targ->node = gn; 18203955d011SMarcel Moolenaar targ->parent = NULL; 18213955d011SMarcel Moolenaar targ->children = 0; 18223955d011SMarcel Moolenaar targ->pref = bmake_strdup(sopref); 18233955d011SMarcel Moolenaar #ifdef DEBUG_SRC 1824*2c3632d1SSimon J. Gerraty targ->cp = Lst_Init(); 18253955d011SMarcel Moolenaar #endif 18263955d011SMarcel Moolenaar 18273955d011SMarcel Moolenaar /* 18283955d011SMarcel Moolenaar * Only use the default suffix rules if we don't have commands 18293955d011SMarcel Moolenaar * defined for this gnode; traditional make programs used to 18303955d011SMarcel Moolenaar * not define suffix rules if the gnode had children but we 18313955d011SMarcel Moolenaar * don't do this anymore. 18323955d011SMarcel Moolenaar */ 18333955d011SMarcel Moolenaar if (Lst_IsEmpty(gn->commands)) 18343955d011SMarcel Moolenaar SuffAddLevel(srcs, targ); 18353955d011SMarcel Moolenaar else { 1836*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("not "); 18373955d011SMarcel Moolenaar } 18383955d011SMarcel Moolenaar 1839*2c3632d1SSimon J. Gerraty SUFF_DEBUG0("adding suffix rules\n"); 18403955d011SMarcel Moolenaar 1841*2c3632d1SSimon J. Gerraty Lst_Append(targs, targ); 18423955d011SMarcel Moolenaar } 18433955d011SMarcel Moolenaar 18443955d011SMarcel Moolenaar /* 184552d86256SSimon J. Gerraty * Using the list of possible sources built up from the target 184652d86256SSimon J. Gerraty * suffix(es), try and find an existing file/target that matches. 18473955d011SMarcel Moolenaar */ 18483955d011SMarcel Moolenaar bottom = SuffFindThem(srcs, slst); 18493955d011SMarcel Moolenaar 18503955d011SMarcel Moolenaar if (bottom == NULL) { 18513955d011SMarcel Moolenaar /* 185252d86256SSimon J. Gerraty * No known transformations -- use the first suffix found 185352d86256SSimon J. Gerraty * for setting the local variables. 18543955d011SMarcel Moolenaar */ 18553955d011SMarcel Moolenaar if (!Lst_IsEmpty(targs)) { 1856*2c3632d1SSimon J. Gerraty targ = LstNode_Datum(Lst_First(targs)); 18573955d011SMarcel Moolenaar } else { 18583955d011SMarcel Moolenaar targ = NULL; 18593955d011SMarcel Moolenaar } 18603955d011SMarcel Moolenaar } else { 18613955d011SMarcel Moolenaar /* 18623955d011SMarcel Moolenaar * Work up the transformation path to find the suffix of the 18633955d011SMarcel Moolenaar * target to which the transformation was made. 18643955d011SMarcel Moolenaar */ 18653955d011SMarcel Moolenaar for (targ = bottom; targ->parent != NULL; targ = targ->parent) 18663955d011SMarcel Moolenaar continue; 18673955d011SMarcel Moolenaar } 18684fc82fe4SSimon J. Gerraty } 18693955d011SMarcel Moolenaar 18703841c287SSimon J. Gerraty Var_Set(TARGET, gn->path ? gn->path : gn->name, gn); 18713955d011SMarcel Moolenaar 18723955d011SMarcel Moolenaar pref = (targ != NULL) ? targ->pref : gn->name; 18733841c287SSimon J. Gerraty Var_Set(PREFIX, pref, gn); 18743955d011SMarcel Moolenaar 18753955d011SMarcel Moolenaar /* 18763955d011SMarcel Moolenaar * Now we've got the important local variables set, expand any sources 18773955d011SMarcel Moolenaar * that still contain variables or wildcards in their names. 18783955d011SMarcel Moolenaar */ 18793955d011SMarcel Moolenaar for (ln = Lst_First(gn->children); ln != NULL; ln = nln) { 1880*2c3632d1SSimon J. Gerraty nln = LstNode_Next(ln); 18813955d011SMarcel Moolenaar SuffExpandChildren(ln, gn); 18823955d011SMarcel Moolenaar } 18833955d011SMarcel Moolenaar 18843955d011SMarcel Moolenaar if (targ == NULL) { 1885*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("\tNo valid suffix on %s\n", gn->name); 18863955d011SMarcel Moolenaar 18873955d011SMarcel Moolenaar sfnd_abort: 18883955d011SMarcel Moolenaar /* 18893955d011SMarcel Moolenaar * Deal with finding the thing on the default search path. We 18903955d011SMarcel Moolenaar * always do that, not only if the node is only a source (not 18913955d011SMarcel Moolenaar * on the lhs of a dependency operator or [XXX] it has neither 18923955d011SMarcel Moolenaar * children or commands) as the old pmake did. 18933955d011SMarcel Moolenaar */ 18943955d011SMarcel Moolenaar if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) { 18953955d011SMarcel Moolenaar free(gn->path); 18963955d011SMarcel Moolenaar gn->path = Dir_FindFile(gn->name, 18973955d011SMarcel Moolenaar (targ == NULL ? dirSearchPath : 18983955d011SMarcel Moolenaar targ->suff->searchPath)); 18993955d011SMarcel Moolenaar if (gn->path != NULL) { 19003955d011SMarcel Moolenaar char *ptr; 19013841c287SSimon J. Gerraty Var_Set(TARGET, gn->path, gn); 19023955d011SMarcel Moolenaar 19033955d011SMarcel Moolenaar if (targ != NULL) { 19043955d011SMarcel Moolenaar /* 19053955d011SMarcel Moolenaar * Suffix known for the thing -- trim the suffix off 19063955d011SMarcel Moolenaar * the path to form the proper .PREFIX variable. 19073955d011SMarcel Moolenaar */ 19083955d011SMarcel Moolenaar int savep = strlen(gn->path) - targ->suff->nameLen; 19093955d011SMarcel Moolenaar char savec; 19103955d011SMarcel Moolenaar 19113955d011SMarcel Moolenaar if (gn->suffix) 19123955d011SMarcel Moolenaar gn->suffix->refCount--; 19133955d011SMarcel Moolenaar gn->suffix = targ->suff; 19143955d011SMarcel Moolenaar gn->suffix->refCount++; 19153955d011SMarcel Moolenaar 19163955d011SMarcel Moolenaar savec = gn->path[savep]; 19173955d011SMarcel Moolenaar gn->path[savep] = '\0'; 19183955d011SMarcel Moolenaar 19193955d011SMarcel Moolenaar if ((ptr = strrchr(gn->path, '/')) != NULL) 19203955d011SMarcel Moolenaar ptr++; 19213955d011SMarcel Moolenaar else 19223955d011SMarcel Moolenaar ptr = gn->path; 19233955d011SMarcel Moolenaar 19243841c287SSimon J. Gerraty Var_Set(PREFIX, ptr, gn); 19253955d011SMarcel Moolenaar 19263955d011SMarcel Moolenaar gn->path[savep] = savec; 19273955d011SMarcel Moolenaar } else { 19283955d011SMarcel Moolenaar /* 19293955d011SMarcel Moolenaar * The .PREFIX gets the full path if the target has 19303955d011SMarcel Moolenaar * no known suffix. 19313955d011SMarcel Moolenaar */ 19323955d011SMarcel Moolenaar if (gn->suffix) 19333955d011SMarcel Moolenaar gn->suffix->refCount--; 19343955d011SMarcel Moolenaar gn->suffix = NULL; 19353955d011SMarcel Moolenaar 19363955d011SMarcel Moolenaar if ((ptr = strrchr(gn->path, '/')) != NULL) 19373955d011SMarcel Moolenaar ptr++; 19383955d011SMarcel Moolenaar else 19393955d011SMarcel Moolenaar ptr = gn->path; 19403955d011SMarcel Moolenaar 19413841c287SSimon J. Gerraty Var_Set(PREFIX, ptr, gn); 19423955d011SMarcel Moolenaar } 19433955d011SMarcel Moolenaar } 19443955d011SMarcel Moolenaar } 19453955d011SMarcel Moolenaar 19463955d011SMarcel Moolenaar goto sfnd_return; 19473955d011SMarcel Moolenaar } 19483955d011SMarcel Moolenaar 19493955d011SMarcel Moolenaar /* 19503955d011SMarcel Moolenaar * If the suffix indicates that the target is a library, mark that in 19513955d011SMarcel Moolenaar * the node's type field. 19523955d011SMarcel Moolenaar */ 19533955d011SMarcel Moolenaar if (targ->suff->flags & SUFF_LIBRARY) { 19543955d011SMarcel Moolenaar gn->type |= OP_LIB; 19553955d011SMarcel Moolenaar } 19563955d011SMarcel Moolenaar 19573955d011SMarcel Moolenaar /* 19583955d011SMarcel Moolenaar * Check for overriding transformation rule implied by sources 19593955d011SMarcel Moolenaar */ 19603955d011SMarcel Moolenaar if (!Lst_IsEmpty(gn->children)) { 19613955d011SMarcel Moolenaar src = SuffFindCmds(targ, slst); 19623955d011SMarcel Moolenaar 19633955d011SMarcel Moolenaar if (src != NULL) { 19643955d011SMarcel Moolenaar /* 19653955d011SMarcel Moolenaar * Free up all the Src structures in the transformation path 19663955d011SMarcel Moolenaar * up to, but not including, the parent node. 19673955d011SMarcel Moolenaar */ 19683955d011SMarcel Moolenaar while (bottom && bottom->parent != NULL) { 1969*2c3632d1SSimon J. Gerraty if (Lst_FindDatum(slst, bottom) == NULL) { 1970*2c3632d1SSimon J. Gerraty Lst_Append(slst, bottom); 19713955d011SMarcel Moolenaar } 19723955d011SMarcel Moolenaar bottom = bottom->parent; 19733955d011SMarcel Moolenaar } 19743955d011SMarcel Moolenaar bottom = src; 19753955d011SMarcel Moolenaar } 19763955d011SMarcel Moolenaar } 19773955d011SMarcel Moolenaar 19783955d011SMarcel Moolenaar if (bottom == NULL) { 19793955d011SMarcel Moolenaar /* 19803955d011SMarcel Moolenaar * No idea from where it can come -- return now. 19813955d011SMarcel Moolenaar */ 19823955d011SMarcel Moolenaar goto sfnd_abort; 19833955d011SMarcel Moolenaar } 19843955d011SMarcel Moolenaar 19853955d011SMarcel Moolenaar /* 19863955d011SMarcel Moolenaar * We now have a list of Src structures headed by 'bottom' and linked via 19873955d011SMarcel Moolenaar * their 'parent' pointers. What we do next is create links between 19883955d011SMarcel Moolenaar * source and target nodes (which may or may not have been created) 19893955d011SMarcel Moolenaar * and set the necessary local variables in each target. The 19903955d011SMarcel Moolenaar * commands for each target are set from the commands of the 19913955d011SMarcel Moolenaar * transformation rule used to get from the src suffix to the targ 19923955d011SMarcel Moolenaar * suffix. Note that this causes the commands list of the original 19933955d011SMarcel Moolenaar * node, gn, to be replaced by the commands of the final 19943955d011SMarcel Moolenaar * transformation rule. Also, the unmade field of gn is incremented. 19953955d011SMarcel Moolenaar * Etc. 19963955d011SMarcel Moolenaar */ 19973955d011SMarcel Moolenaar if (bottom->node == NULL) { 19983955d011SMarcel Moolenaar bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); 19993955d011SMarcel Moolenaar } 20003955d011SMarcel Moolenaar 20013955d011SMarcel Moolenaar for (src = bottom; src->parent != NULL; src = src->parent) { 20023955d011SMarcel Moolenaar targ = src->parent; 20033955d011SMarcel Moolenaar 20043955d011SMarcel Moolenaar if (src->node->suffix) 20053955d011SMarcel Moolenaar src->node->suffix->refCount--; 20063955d011SMarcel Moolenaar src->node->suffix = src->suff; 20073955d011SMarcel Moolenaar src->node->suffix->refCount++; 20083955d011SMarcel Moolenaar 20093955d011SMarcel Moolenaar if (targ->node == NULL) { 20103955d011SMarcel Moolenaar targ->node = Targ_FindNode(targ->file, TARG_CREATE); 20113955d011SMarcel Moolenaar } 20123955d011SMarcel Moolenaar 20133955d011SMarcel Moolenaar SuffApplyTransform(targ->node, src->node, 20143955d011SMarcel Moolenaar targ->suff, src->suff); 20153955d011SMarcel Moolenaar 20163955d011SMarcel Moolenaar if (targ->node != gn) { 20173955d011SMarcel Moolenaar /* 20183955d011SMarcel Moolenaar * Finish off the dependency-search process for any nodes 20193955d011SMarcel Moolenaar * between bottom and gn (no point in questing around the 20203955d011SMarcel Moolenaar * filesystem for their implicit source when it's already 20213955d011SMarcel Moolenaar * known). Note that the node can't have any sources that 20223955d011SMarcel Moolenaar * need expanding, since SuffFindThem will stop on an existing 20233955d011SMarcel Moolenaar * node, so all we need to do is set the standard and System V 20243955d011SMarcel Moolenaar * variables. 20253955d011SMarcel Moolenaar */ 20263955d011SMarcel Moolenaar targ->node->type |= OP_DEPS_FOUND; 20273955d011SMarcel Moolenaar 20283841c287SSimon J. Gerraty Var_Set(PREFIX, targ->pref, targ->node); 20293955d011SMarcel Moolenaar 20303841c287SSimon J. Gerraty Var_Set(TARGET, targ->node->name, targ->node); 20313955d011SMarcel Moolenaar } 20323955d011SMarcel Moolenaar } 20333955d011SMarcel Moolenaar 20343955d011SMarcel Moolenaar if (gn->suffix) 20353955d011SMarcel Moolenaar gn->suffix->refCount--; 20363955d011SMarcel Moolenaar gn->suffix = src->suff; 20373955d011SMarcel Moolenaar gn->suffix->refCount++; 20383955d011SMarcel Moolenaar 20393955d011SMarcel Moolenaar /* 20403955d011SMarcel Moolenaar * Nuke the transformation path and the Src structures left over in the 20413955d011SMarcel Moolenaar * two lists. 20423955d011SMarcel Moolenaar */ 20433955d011SMarcel Moolenaar sfnd_return: 20443955d011SMarcel Moolenaar if (bottom) 2045*2c3632d1SSimon J. Gerraty if (Lst_FindDatum(slst, bottom) == NULL) 2046*2c3632d1SSimon J. Gerraty Lst_Append(slst, bottom); 20473955d011SMarcel Moolenaar 20483955d011SMarcel Moolenaar while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs)) 20493955d011SMarcel Moolenaar continue; 20503955d011SMarcel Moolenaar 2051*2c3632d1SSimon J. Gerraty Lst_MoveAll(slst, srcs); 2052*2c3632d1SSimon J. Gerraty Lst_MoveAll(slst, targs); 20533955d011SMarcel Moolenaar } 20543955d011SMarcel Moolenaar 20553955d011SMarcel Moolenaar 2056*2c3632d1SSimon J. Gerraty /* Find implicit sources for the target described by the graph node. 20573955d011SMarcel Moolenaar * 2058*2c3632d1SSimon J. Gerraty * Nodes are added to the graph below the passed-in node. The nodes are 2059*2c3632d1SSimon J. Gerraty * marked to have their IMPSRC variable filled in. The PREFIX variable is set 2060*2c3632d1SSimon J. Gerraty * for the given node and all its implied children. 20613955d011SMarcel Moolenaar * 2062*2c3632d1SSimon J. Gerraty * The path found by this target is the shortest path in the transformation 2063*2c3632d1SSimon J. Gerraty * graph, which may pass through non-existent targets, to an existing target. 2064*2c3632d1SSimon J. Gerraty * The search continues on all paths from the root suffix until a file is 2065*2c3632d1SSimon J. Gerraty * found. I.e. if there's a path .o -> .c -> .l -> .l,v from the root and the 2066*2c3632d1SSimon J. Gerraty * .l,v file exists but the .c and .l files don't, the search will branch out 2067*2c3632d1SSimon J. Gerraty * in all directions from .o and again from all the nodes on the next level 2068*2c3632d1SSimon J. Gerraty * until the .l,v node is encountered. 20693955d011SMarcel Moolenaar */ 20703955d011SMarcel Moolenaar void 20713955d011SMarcel Moolenaar Suff_FindDeps(GNode *gn) 20723955d011SMarcel Moolenaar { 20733955d011SMarcel Moolenaar 20743955d011SMarcel Moolenaar SuffFindDeps(gn, srclist); 20753955d011SMarcel Moolenaar while (SuffRemoveSrc(srclist)) 20763955d011SMarcel Moolenaar continue; 20773955d011SMarcel Moolenaar } 20783955d011SMarcel Moolenaar 20793955d011SMarcel Moolenaar static void 20803955d011SMarcel Moolenaar SuffFindDeps(GNode *gn, Lst slst) 20813955d011SMarcel Moolenaar { 2082*2c3632d1SSimon J. Gerraty if (gn->type & OP_DEPS_FOUND) 20833955d011SMarcel Moolenaar return; 20843955d011SMarcel Moolenaar gn->type |= OP_DEPS_FOUND; 2085*2c3632d1SSimon J. Gerraty 20863955d011SMarcel Moolenaar /* 20873955d011SMarcel Moolenaar * Make sure we have these set, may get revised below. 20883955d011SMarcel Moolenaar */ 20893841c287SSimon J. Gerraty Var_Set(TARGET, gn->path ? gn->path : gn->name, gn); 20903841c287SSimon J. Gerraty Var_Set(PREFIX, gn->name, gn); 20914fc82fe4SSimon J. Gerraty 2092*2c3632d1SSimon J. Gerraty SUFF_DEBUG1("SuffFindDeps (%s)\n", gn->name); 20933955d011SMarcel Moolenaar 20943955d011SMarcel Moolenaar if (gn->type & OP_ARCHV) { 20953955d011SMarcel Moolenaar SuffFindArchiveDeps(gn, slst); 20963955d011SMarcel Moolenaar } else if (gn->type & OP_LIB) { 20973955d011SMarcel Moolenaar /* 20983955d011SMarcel Moolenaar * If the node is a library, it is the arch module's job to find it 20993955d011SMarcel Moolenaar * and set the TARGET variable accordingly. We merely provide the 21003955d011SMarcel Moolenaar * search path, assuming all libraries end in ".a" (if the suffix 21013955d011SMarcel Moolenaar * hasn't been defined, there's nothing we can do for it, so we just 21023955d011SMarcel Moolenaar * set the TARGET variable to the node's name in order to give it a 21033955d011SMarcel Moolenaar * value). 21043955d011SMarcel Moolenaar */ 21053955d011SMarcel Moolenaar LstNode ln; 21063955d011SMarcel Moolenaar Suff *s; 21073955d011SMarcel Moolenaar 2108*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, LIBSUFF); 21093955d011SMarcel Moolenaar if (gn->suffix) 21103955d011SMarcel Moolenaar gn->suffix->refCount--; 21113955d011SMarcel Moolenaar if (ln != NULL) { 2112*2c3632d1SSimon J. Gerraty gn->suffix = s = LstNode_Datum(ln); 21133955d011SMarcel Moolenaar gn->suffix->refCount++; 21143955d011SMarcel Moolenaar Arch_FindLib(gn, s->searchPath); 21153955d011SMarcel Moolenaar } else { 21163955d011SMarcel Moolenaar gn->suffix = NULL; 21173841c287SSimon J. Gerraty Var_Set(TARGET, gn->name, gn); 21183955d011SMarcel Moolenaar } 21193955d011SMarcel Moolenaar /* 21203955d011SMarcel Moolenaar * Because a library (-lfoo) target doesn't follow the standard 21213955d011SMarcel Moolenaar * filesystem conventions, we don't set the regular variables for 21223955d011SMarcel Moolenaar * the thing. .PREFIX is simply made empty... 21233955d011SMarcel Moolenaar */ 21243841c287SSimon J. Gerraty Var_Set(PREFIX, "", gn); 21253955d011SMarcel Moolenaar } else { 21263955d011SMarcel Moolenaar SuffFindNormalDeps(gn, slst); 21273955d011SMarcel Moolenaar } 21283955d011SMarcel Moolenaar } 21293955d011SMarcel Moolenaar 2130*2c3632d1SSimon J. Gerraty /* Define which suffix is the null suffix. 2131*2c3632d1SSimon J. Gerraty * 2132*2c3632d1SSimon J. Gerraty * Need to handle the changing of the null suffix gracefully so the old 2133*2c3632d1SSimon J. Gerraty * transformation rules don't just go away. 21343955d011SMarcel Moolenaar * 21353955d011SMarcel Moolenaar * Input: 21363955d011SMarcel Moolenaar * name Name of null suffix 21373955d011SMarcel Moolenaar */ 21383955d011SMarcel Moolenaar void 21393955d011SMarcel Moolenaar Suff_SetNull(char *name) 21403955d011SMarcel Moolenaar { 21413955d011SMarcel Moolenaar Suff *s; 21423955d011SMarcel Moolenaar LstNode ln; 21433955d011SMarcel Moolenaar 2144*2c3632d1SSimon J. Gerraty ln = Lst_Find(sufflist, SuffSuffHasName, name); 21453955d011SMarcel Moolenaar if (ln != NULL) { 2146*2c3632d1SSimon J. Gerraty s = LstNode_Datum(ln); 21473955d011SMarcel Moolenaar if (suffNull != NULL) { 21483955d011SMarcel Moolenaar suffNull->flags &= ~SUFF_NULL; 21493955d011SMarcel Moolenaar } 21503955d011SMarcel Moolenaar s->flags |= SUFF_NULL; 21513955d011SMarcel Moolenaar /* 21523955d011SMarcel Moolenaar * XXX: Here's where the transformation mangling would take place 21533955d011SMarcel Moolenaar */ 21543955d011SMarcel Moolenaar suffNull = s; 21553955d011SMarcel Moolenaar } else { 21563955d011SMarcel Moolenaar Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", 21573955d011SMarcel Moolenaar name); 21583955d011SMarcel Moolenaar } 21593955d011SMarcel Moolenaar } 21603955d011SMarcel Moolenaar 2161*2c3632d1SSimon J. Gerraty /* Initialize the suffixes module. */ 21623955d011SMarcel Moolenaar void 21633955d011SMarcel Moolenaar Suff_Init(void) 21643955d011SMarcel Moolenaar { 21653955d011SMarcel Moolenaar #ifdef CLEANUP 2166*2c3632d1SSimon J. Gerraty suffClean = Lst_Init(); 2167*2c3632d1SSimon J. Gerraty sufflist = Lst_Init(); 21683955d011SMarcel Moolenaar #endif 2169*2c3632d1SSimon J. Gerraty srclist = Lst_Init(); 2170*2c3632d1SSimon J. Gerraty transforms = Lst_Init(); 21713955d011SMarcel Moolenaar 21723955d011SMarcel Moolenaar /* 21733955d011SMarcel Moolenaar * Create null suffix for single-suffix rules (POSIX). The thing doesn't 21743955d011SMarcel Moolenaar * actually go on the suffix list or everyone will think that's its 21753955d011SMarcel Moolenaar * suffix. 21763955d011SMarcel Moolenaar */ 21776e050540SSimon J. Gerraty Suff_ClearSuffixes(); 21783955d011SMarcel Moolenaar } 21793955d011SMarcel Moolenaar 21803955d011SMarcel Moolenaar 2181*2c3632d1SSimon J. Gerraty /* Clean up the suffixes module. */ 21823955d011SMarcel Moolenaar void 21833955d011SMarcel Moolenaar Suff_End(void) 21843955d011SMarcel Moolenaar { 21853955d011SMarcel Moolenaar #ifdef CLEANUP 21863955d011SMarcel Moolenaar Lst_Destroy(sufflist, SuffFree); 21873955d011SMarcel Moolenaar Lst_Destroy(suffClean, SuffFree); 21883955d011SMarcel Moolenaar if (suffNull) 21893955d011SMarcel Moolenaar SuffFree(suffNull); 2190*2c3632d1SSimon J. Gerraty Lst_Free(srclist); 2191*2c3632d1SSimon J. Gerraty Lst_Free(transforms); 21923955d011SMarcel Moolenaar #endif 21933955d011SMarcel Moolenaar } 21943955d011SMarcel Moolenaar 21953955d011SMarcel Moolenaar 21963955d011SMarcel Moolenaar /********************* DEBUGGING FUNCTIONS **********************/ 21973955d011SMarcel Moolenaar 2198e1cee40dSSimon J. Gerraty static int SuffPrintName(void *s, void *dummy MAKE_ATTR_UNUSED) 21993955d011SMarcel Moolenaar { 220095e3ed2cSSimon J. Gerraty 22013955d011SMarcel Moolenaar fprintf(debug_file, "%s ", ((Suff *)s)->name); 220295e3ed2cSSimon J. Gerraty return 0; 22033955d011SMarcel Moolenaar } 22043955d011SMarcel Moolenaar 22053955d011SMarcel Moolenaar static int 2206e1cee40dSSimon J. Gerraty SuffPrintSuff(void *sp, void *dummy MAKE_ATTR_UNUSED) 22073955d011SMarcel Moolenaar { 22083955d011SMarcel Moolenaar Suff *s = (Suff *)sp; 22093955d011SMarcel Moolenaar 22103955d011SMarcel Moolenaar fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount); 22113955d011SMarcel Moolenaar 2212*2c3632d1SSimon J. Gerraty if (s->flags != 0) { 2213*2c3632d1SSimon J. Gerraty char flags_buf[SuffFlags_ToStringSize]; 2214*2c3632d1SSimon J. Gerraty 2215*2c3632d1SSimon J. Gerraty fprintf(debug_file, " (%s)", 2216*2c3632d1SSimon J. Gerraty Enum_FlagsToString(flags_buf, sizeof flags_buf, 2217*2c3632d1SSimon J. Gerraty s->flags, SuffFlags_ToStringSpecs)); 22183955d011SMarcel Moolenaar } 22193955d011SMarcel Moolenaar fputc('\n', debug_file); 22203955d011SMarcel Moolenaar fprintf(debug_file, "#\tTo: "); 22213955d011SMarcel Moolenaar Lst_ForEach(s->parents, SuffPrintName, NULL); 22223955d011SMarcel Moolenaar fputc('\n', debug_file); 22233955d011SMarcel Moolenaar fprintf(debug_file, "#\tFrom: "); 22243955d011SMarcel Moolenaar Lst_ForEach(s->children, SuffPrintName, NULL); 22253955d011SMarcel Moolenaar fputc('\n', debug_file); 22263955d011SMarcel Moolenaar fprintf(debug_file, "#\tSearch Path: "); 22273955d011SMarcel Moolenaar Dir_PrintPath(s->searchPath); 22283955d011SMarcel Moolenaar fputc('\n', debug_file); 222995e3ed2cSSimon J. Gerraty return 0; 22303955d011SMarcel Moolenaar } 22313955d011SMarcel Moolenaar 22323955d011SMarcel Moolenaar static int 2233e1cee40dSSimon J. Gerraty SuffPrintTrans(void *tp, void *dummy MAKE_ATTR_UNUSED) 22343955d011SMarcel Moolenaar { 22353955d011SMarcel Moolenaar GNode *t = (GNode *)tp; 22363955d011SMarcel Moolenaar 22373955d011SMarcel Moolenaar fprintf(debug_file, "%-16s: ", t->name); 22383955d011SMarcel Moolenaar Targ_PrintType(t->type); 22393955d011SMarcel Moolenaar fputc('\n', debug_file); 22403955d011SMarcel Moolenaar Lst_ForEach(t->commands, Targ_PrintCmd, NULL); 22413955d011SMarcel Moolenaar fputc('\n', debug_file); 224295e3ed2cSSimon J. Gerraty return 0; 22433955d011SMarcel Moolenaar } 22443955d011SMarcel Moolenaar 22453955d011SMarcel Moolenaar void 22463955d011SMarcel Moolenaar Suff_PrintAll(void) 22473955d011SMarcel Moolenaar { 22483955d011SMarcel Moolenaar fprintf(debug_file, "#*** Suffixes:\n"); 22493955d011SMarcel Moolenaar Lst_ForEach(sufflist, SuffPrintSuff, NULL); 22503955d011SMarcel Moolenaar 22513955d011SMarcel Moolenaar fprintf(debug_file, "#*** Transformations:\n"); 22523955d011SMarcel Moolenaar Lst_ForEach(transforms, SuffPrintTrans, NULL); 22533955d011SMarcel Moolenaar } 2254