1250837Ssjg/* $NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $ */ 2236769Sobrien 3236769Sobrien/* 4236769Sobrien * Copyright (c) 1988, 1989, 1990, 1993 5236769Sobrien * The Regents of the University of California. All rights reserved. 6236769Sobrien * 7236769Sobrien * This code is derived from software contributed to Berkeley by 8236769Sobrien * Adam de Boor. 9236769Sobrien * 10236769Sobrien * Redistribution and use in source and binary forms, with or without 11236769Sobrien * modification, are permitted provided that the following conditions 12236769Sobrien * are met: 13236769Sobrien * 1. Redistributions of source code must retain the above copyright 14236769Sobrien * notice, this list of conditions and the following disclaimer. 15236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 16236769Sobrien * notice, this list of conditions and the following disclaimer in the 17236769Sobrien * documentation and/or other materials provided with the distribution. 18236769Sobrien * 3. Neither the name of the University nor the names of its contributors 19236769Sobrien * may be used to endorse or promote products derived from this software 20236769Sobrien * without specific prior written permission. 21236769Sobrien * 22236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25236769Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32236769Sobrien * SUCH DAMAGE. 33236769Sobrien */ 34236769Sobrien 35236769Sobrien/* 36236769Sobrien * Copyright (c) 1989 by Berkeley Softworks 37236769Sobrien * All rights reserved. 38236769Sobrien * 39236769Sobrien * This code is derived from software contributed to Berkeley by 40236769Sobrien * Adam de Boor. 41236769Sobrien * 42236769Sobrien * Redistribution and use in source and binary forms, with or without 43236769Sobrien * modification, are permitted provided that the following conditions 44236769Sobrien * are met: 45236769Sobrien * 1. Redistributions of source code must retain the above copyright 46236769Sobrien * notice, this list of conditions and the following disclaimer. 47236769Sobrien * 2. Redistributions in binary form must reproduce the above copyright 48236769Sobrien * notice, this list of conditions and the following disclaimer in the 49236769Sobrien * documentation and/or other materials provided with the distribution. 50236769Sobrien * 3. All advertising materials mentioning features or use of this software 51236769Sobrien * must display the following acknowledgement: 52236769Sobrien * This product includes software developed by the University of 53236769Sobrien * California, Berkeley and its contributors. 54236769Sobrien * 4. Neither the name of the University nor the names of its contributors 55236769Sobrien * may be used to endorse or promote products derived from this software 56236769Sobrien * without specific prior written permission. 57236769Sobrien * 58236769Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59236769Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60236769Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61236769Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62236769Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63236769Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64236769Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65236769Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66236769Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67236769Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68236769Sobrien * SUCH DAMAGE. 69236769Sobrien */ 70236769Sobrien 71236769Sobrien#ifndef MAKE_NATIVE 72250837Ssjgstatic char rcsid[] = "$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $"; 73236769Sobrien#else 74236769Sobrien#include <sys/cdefs.h> 75236769Sobrien#ifndef lint 76236769Sobrien#if 0 77236769Sobrienstatic char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; 78236769Sobrien#else 79250837Ssjg__RCSID("$NetBSD: suff.c,v 1.70 2013/05/18 13:13:34 sjg Exp $"); 80236769Sobrien#endif 81236769Sobrien#endif /* not lint */ 82236769Sobrien#endif 83236769Sobrien 84236769Sobrien/*- 85236769Sobrien * suff.c -- 86236769Sobrien * Functions to maintain suffix lists and find implicit dependents 87236769Sobrien * using suffix transformation rules 88236769Sobrien * 89236769Sobrien * Interface: 90236769Sobrien * Suff_Init Initialize all things to do with suffixes. 91236769Sobrien * 92236769Sobrien * Suff_End Cleanup the module 93236769Sobrien * 94236769Sobrien * Suff_DoPaths This function is used to make life easier 95236769Sobrien * when searching for a file according to its 96236769Sobrien * suffix. It takes the global search path, 97236769Sobrien * as defined using the .PATH: target, and appends 98236769Sobrien * its directories to the path of each of the 99236769Sobrien * defined suffixes, as specified using 100236769Sobrien * .PATH<suffix>: targets. In addition, all 101236769Sobrien * directories given for suffixes labeled as 102236769Sobrien * include files or libraries, using the .INCLUDES 103236769Sobrien * or .LIBS targets, are played with using 104236769Sobrien * Dir_MakeFlags to create the .INCLUDES and 105236769Sobrien * .LIBS global variables. 106236769Sobrien * 107236769Sobrien * Suff_ClearSuffixes Clear out all the suffixes and defined 108236769Sobrien * transformations. 109236769Sobrien * 110236769Sobrien * Suff_IsTransform Return TRUE if the passed string is the lhs 111236769Sobrien * of a transformation rule. 112236769Sobrien * 113236769Sobrien * Suff_AddSuffix Add the passed string as another known suffix. 114236769Sobrien * 115236769Sobrien * Suff_GetPath Return the search path for the given suffix. 116236769Sobrien * 117236769Sobrien * Suff_AddInclude Mark the given suffix as denoting an include 118236769Sobrien * file. 119236769Sobrien * 120236769Sobrien * Suff_AddLib Mark the given suffix as denoting a library. 121236769Sobrien * 122236769Sobrien * Suff_AddTransform Add another transformation to the suffix 123236769Sobrien * graph. Returns GNode suitable for framing, I 124236769Sobrien * mean, tacking commands, attributes, etc. on. 125236769Sobrien * 126236769Sobrien * Suff_SetNull Define the suffix to consider the suffix of 127236769Sobrien * any file that doesn't have a known one. 128236769Sobrien * 129236769Sobrien * Suff_FindDeps Find implicit sources for and the location of 130236769Sobrien * a target based on its suffix. Returns the 131236769Sobrien * bottom-most node added to the graph or NULL 132236769Sobrien * if the target had no implicit sources. 133236769Sobrien * 134236769Sobrien * Suff_FindPath Return the appropriate path to search in 135236769Sobrien * order to find the node. 136236769Sobrien */ 137236769Sobrien 138236769Sobrien#include <stdio.h> 139236769Sobrien#include "make.h" 140236769Sobrien#include "hash.h" 141236769Sobrien#include "dir.h" 142236769Sobrien 143236769Sobrienstatic Lst sufflist; /* Lst of suffixes */ 144236769Sobrien#ifdef CLEANUP 145236769Sobrienstatic Lst suffClean; /* Lst of suffixes to be cleaned */ 146236769Sobrien#endif 147236769Sobrienstatic Lst srclist; /* Lst of sources */ 148236769Sobrienstatic Lst transforms; /* Lst of transformation rules */ 149236769Sobrien 150236769Sobrienstatic int sNum = 0; /* Counter for assigning suffix numbers */ 151236769Sobrien 152236769Sobrien/* 153236769Sobrien * Structure describing an individual suffix. 154236769Sobrien */ 155236769Sobrientypedef struct _Suff { 156236769Sobrien char *name; /* The suffix itself */ 157236769Sobrien int nameLen; /* Length of the suffix */ 158236769Sobrien short flags; /* Type of suffix */ 159236769Sobrien#define SUFF_INCLUDE 0x01 /* One which is #include'd */ 160236769Sobrien#define SUFF_LIBRARY 0x02 /* One which contains a library */ 161236769Sobrien#define SUFF_NULL 0x04 /* The empty suffix */ 162236769Sobrien Lst searchPath; /* The path along which files of this suffix 163236769Sobrien * may be found */ 164236769Sobrien int sNum; /* The suffix number */ 165236769Sobrien int refCount; /* Reference count of list membership */ 166236769Sobrien Lst parents; /* Suffixes we have a transformation to */ 167236769Sobrien Lst children; /* Suffixes we have a transformation from */ 168236769Sobrien Lst ref; /* List of lists this suffix is referenced */ 169236769Sobrien} Suff; 170236769Sobrien 171236769Sobrien/* 172236769Sobrien * for SuffSuffIsSuffix 173236769Sobrien */ 174236769Sobrientypedef struct { 175236769Sobrien char *ename; /* The end of the name */ 176236769Sobrien int len; /* Length of the name */ 177236769Sobrien} SuffixCmpData; 178236769Sobrien 179236769Sobrien/* 180236769Sobrien * Structure used in the search for implied sources. 181236769Sobrien */ 182236769Sobrientypedef struct _Src { 183236769Sobrien char *file; /* The file to look for */ 184236769Sobrien char *pref; /* Prefix from which file was formed */ 185236769Sobrien Suff *suff; /* The suffix on the file */ 186236769Sobrien struct _Src *parent; /* The Src for which this is a source */ 187236769Sobrien GNode *node; /* The node describing the file */ 188236769Sobrien int children; /* Count of existing children (so we don't free 189236769Sobrien * this thing too early or never nuke it) */ 190236769Sobrien#ifdef DEBUG_SRC 191236769Sobrien Lst cp; /* Debug; children list */ 192236769Sobrien#endif 193236769Sobrien} Src; 194236769Sobrien 195236769Sobrien/* 196236769Sobrien * A structure for passing more than one argument to the Lst-library-invoked 197236769Sobrien * function... 198236769Sobrien */ 199236769Sobrientypedef struct { 200236769Sobrien Lst l; 201236769Sobrien Src *s; 202236769Sobrien} LstSrc; 203236769Sobrien 204236769Sobrientypedef struct { 205236769Sobrien GNode **gn; 206236769Sobrien Suff *s; 207236769Sobrien Boolean r; 208236769Sobrien} GNodeSuff; 209236769Sobrien 210236769Sobrienstatic Suff *suffNull; /* The NULL suffix for this run */ 211236769Sobrienstatic Suff *emptySuff; /* The empty suffix required for POSIX 212236769Sobrien * single-suffix transformation rules */ 213236769Sobrien 214236769Sobrien 215236769Sobrienstatic const char *SuffStrIsPrefix(const char *, const char *); 216236769Sobrienstatic char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *); 217236769Sobrienstatic int SuffSuffIsSuffixP(const void *, const void *); 218236769Sobrienstatic int SuffSuffHasNameP(const void *, const void *); 219236769Sobrienstatic int SuffSuffIsPrefix(const void *, const void *); 220236769Sobrienstatic int SuffGNHasNameP(const void *, const void *); 221236769Sobrienstatic void SuffUnRef(void *, void *); 222236769Sobrienstatic void SuffFree(void *); 223236769Sobrienstatic void SuffInsert(Lst, Suff *); 224236769Sobrienstatic void SuffRemove(Lst, Suff *); 225236769Sobrienstatic Boolean SuffParseTransform(char *, Suff **, Suff **); 226236769Sobrienstatic int SuffRebuildGraph(void *, void *); 227236769Sobrienstatic int SuffScanTargets(void *, void *); 228236769Sobrienstatic int SuffAddSrc(void *, void *); 229236769Sobrienstatic int SuffRemoveSrc(Lst); 230236769Sobrienstatic void SuffAddLevel(Lst, Src *); 231236769Sobrienstatic Src *SuffFindThem(Lst, Lst); 232236769Sobrienstatic Src *SuffFindCmds(Src *, Lst); 233236769Sobrienstatic void SuffExpandChildren(LstNode, GNode *); 234236769Sobrienstatic void SuffExpandWildcards(LstNode, GNode *); 235236769Sobrienstatic Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); 236236769Sobrienstatic void SuffFindDeps(GNode *, Lst); 237236769Sobrienstatic void SuffFindArchiveDeps(GNode *, Lst); 238236769Sobrienstatic void SuffFindNormalDeps(GNode *, Lst); 239236769Sobrienstatic int SuffPrintName(void *, void *); 240236769Sobrienstatic int SuffPrintSuff(void *, void *); 241236769Sobrienstatic int SuffPrintTrans(void *, void *); 242236769Sobrien 243236769Sobrien /*************** Lst Predicates ****************/ 244236769Sobrien/*- 245236769Sobrien *----------------------------------------------------------------------- 246236769Sobrien * SuffStrIsPrefix -- 247236769Sobrien * See if pref is a prefix of str. 248236769Sobrien * 249236769Sobrien * Input: 250236769Sobrien * pref possible prefix 251236769Sobrien * str string to check 252236769Sobrien * 253236769Sobrien * Results: 254236769Sobrien * NULL if it ain't, pointer to character in str after prefix if so 255236769Sobrien * 256236769Sobrien * Side Effects: 257236769Sobrien * None 258236769Sobrien *----------------------------------------------------------------------- 259236769Sobrien */ 260236769Sobrienstatic const char * 261236769SobrienSuffStrIsPrefix(const char *pref, const char *str) 262236769Sobrien{ 263236769Sobrien while (*str && *pref == *str) { 264236769Sobrien pref++; 265236769Sobrien str++; 266236769Sobrien } 267236769Sobrien 268236769Sobrien return (*pref ? NULL : str); 269236769Sobrien} 270236769Sobrien 271236769Sobrien/*- 272236769Sobrien *----------------------------------------------------------------------- 273236769Sobrien * SuffSuffIsSuffix -- 274236769Sobrien * See if suff is a suffix of str. sd->ename should point to THE END 275236769Sobrien * of the string to check. (THE END == the null byte) 276236769Sobrien * 277236769Sobrien * Input: 278236769Sobrien * s possible suffix 279236769Sobrien * sd string to examine 280236769Sobrien * 281236769Sobrien * Results: 282236769Sobrien * NULL if it ain't, pointer to character in str before suffix if 283236769Sobrien * it is. 284236769Sobrien * 285236769Sobrien * Side Effects: 286236769Sobrien * None 287236769Sobrien *----------------------------------------------------------------------- 288236769Sobrien */ 289236769Sobrienstatic char * 290236769SobrienSuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd) 291236769Sobrien{ 292236769Sobrien char *p1; /* Pointer into suffix name */ 293236769Sobrien char *p2; /* Pointer into string being examined */ 294236769Sobrien 295236769Sobrien if (sd->len < s->nameLen) 296236769Sobrien return NULL; /* this string is shorter than the suffix */ 297236769Sobrien 298236769Sobrien p1 = s->name + s->nameLen; 299236769Sobrien p2 = sd->ename; 300236769Sobrien 301236769Sobrien while (p1 >= s->name && *p1 == *p2) { 302236769Sobrien p1--; 303236769Sobrien p2--; 304236769Sobrien } 305236769Sobrien 306236769Sobrien return (p1 == s->name - 1 ? p2 : NULL); 307236769Sobrien} 308236769Sobrien 309236769Sobrien/*- 310236769Sobrien *----------------------------------------------------------------------- 311236769Sobrien * SuffSuffIsSuffixP -- 312236769Sobrien * Predicate form of SuffSuffIsSuffix. Passed as the callback function 313236769Sobrien * to Lst_Find. 314236769Sobrien * 315236769Sobrien * Results: 316236769Sobrien * 0 if the suffix is the one desired, non-zero if not. 317236769Sobrien * 318236769Sobrien * Side Effects: 319236769Sobrien * None. 320236769Sobrien * 321236769Sobrien *----------------------------------------------------------------------- 322236769Sobrien */ 323236769Sobrienstatic int 324236769SobrienSuffSuffIsSuffixP(const void *s, const void *sd) 325236769Sobrien{ 326236769Sobrien return(!SuffSuffIsSuffix(s, sd)); 327236769Sobrien} 328236769Sobrien 329236769Sobrien/*- 330236769Sobrien *----------------------------------------------------------------------- 331236769Sobrien * SuffSuffHasNameP -- 332236769Sobrien * Callback procedure for finding a suffix based on its name. Used by 333236769Sobrien * Suff_GetPath. 334236769Sobrien * 335236769Sobrien * Input: 336236769Sobrien * s Suffix to check 337236769Sobrien * sd Desired name 338236769Sobrien * 339236769Sobrien * Results: 340236769Sobrien * 0 if the suffix is of the given name. non-zero otherwise. 341236769Sobrien * 342236769Sobrien * Side Effects: 343236769Sobrien * None 344236769Sobrien *----------------------------------------------------------------------- 345236769Sobrien */ 346236769Sobrienstatic int 347236769SobrienSuffSuffHasNameP(const void *s, const void *sname) 348236769Sobrien{ 349236769Sobrien return (strcmp(sname, ((const Suff *)s)->name)); 350236769Sobrien} 351236769Sobrien 352236769Sobrien/*- 353236769Sobrien *----------------------------------------------------------------------- 354236769Sobrien * SuffSuffIsPrefix -- 355236769Sobrien * See if the suffix described by s is a prefix of the string. Care 356236769Sobrien * must be taken when using this to search for transformations and 357236769Sobrien * what-not, since there could well be two suffixes, one of which 358236769Sobrien * is a prefix of the other... 359236769Sobrien * 360236769Sobrien * Input: 361236769Sobrien * s suffix to compare 362236769Sobrien * str string to examine 363236769Sobrien * 364236769Sobrien * Results: 365236769Sobrien * 0 if s is a prefix of str. non-zero otherwise 366236769Sobrien * 367236769Sobrien * Side Effects: 368236769Sobrien * None 369236769Sobrien *----------------------------------------------------------------------- 370236769Sobrien */ 371236769Sobrienstatic int 372236769SobrienSuffSuffIsPrefix(const void *s, const void *str) 373236769Sobrien{ 374236769Sobrien return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL; 375236769Sobrien} 376236769Sobrien 377236769Sobrien/*- 378236769Sobrien *----------------------------------------------------------------------- 379236769Sobrien * SuffGNHasNameP -- 380236769Sobrien * See if the graph node has the desired name 381236769Sobrien * 382236769Sobrien * Input: 383236769Sobrien * gn current node we're looking at 384236769Sobrien * name name we're looking for 385236769Sobrien * 386236769Sobrien * Results: 387236769Sobrien * 0 if it does. non-zero if it doesn't 388236769Sobrien * 389236769Sobrien * Side Effects: 390236769Sobrien * None 391236769Sobrien *----------------------------------------------------------------------- 392236769Sobrien */ 393236769Sobrienstatic int 394236769SobrienSuffGNHasNameP(const void *gn, const void *name) 395236769Sobrien{ 396236769Sobrien return (strcmp(name, ((const GNode *)gn)->name)); 397236769Sobrien} 398236769Sobrien 399236769Sobrien /*********** Maintenance Functions ************/ 400236769Sobrien 401236769Sobrienstatic void 402236769SobrienSuffUnRef(void *lp, void *sp) 403236769Sobrien{ 404236769Sobrien Lst l = (Lst) lp; 405236769Sobrien 406236769Sobrien LstNode ln = Lst_Member(l, sp); 407236769Sobrien if (ln != NULL) { 408236769Sobrien Lst_Remove(l, ln); 409236769Sobrien ((Suff *)sp)->refCount--; 410236769Sobrien } 411236769Sobrien} 412236769Sobrien 413236769Sobrien/*- 414236769Sobrien *----------------------------------------------------------------------- 415236769Sobrien * SuffFree -- 416236769Sobrien * Free up all memory associated with the given suffix structure. 417236769Sobrien * 418236769Sobrien * Results: 419236769Sobrien * none 420236769Sobrien * 421236769Sobrien * Side Effects: 422236769Sobrien * the suffix entry is detroyed 423236769Sobrien *----------------------------------------------------------------------- 424236769Sobrien */ 425236769Sobrienstatic void 426236769SobrienSuffFree(void *sp) 427236769Sobrien{ 428236769Sobrien Suff *s = (Suff *)sp; 429236769Sobrien 430236769Sobrien if (s == suffNull) 431236769Sobrien suffNull = NULL; 432236769Sobrien 433236769Sobrien if (s == emptySuff) 434236769Sobrien emptySuff = NULL; 435236769Sobrien 436236769Sobrien#ifdef notdef 437236769Sobrien /* We don't delete suffixes in order, so we cannot use this */ 438236769Sobrien if (s->refCount) 439236769Sobrien Punt("Internal error deleting suffix `%s' with refcount = %d", s->name, 440236769Sobrien s->refCount); 441236769Sobrien#endif 442236769Sobrien 443236769Sobrien Lst_Destroy(s->ref, NULL); 444236769Sobrien Lst_Destroy(s->children, NULL); 445236769Sobrien Lst_Destroy(s->parents, NULL); 446236769Sobrien Lst_Destroy(s->searchPath, Dir_Destroy); 447236769Sobrien 448236769Sobrien free(s->name); 449236769Sobrien free(s); 450236769Sobrien} 451236769Sobrien 452236769Sobrien/*- 453236769Sobrien *----------------------------------------------------------------------- 454236769Sobrien * SuffRemove -- 455236769Sobrien * Remove the suffix into the list 456236769Sobrien * 457236769Sobrien * Results: 458236769Sobrien * None 459236769Sobrien * 460236769Sobrien * Side Effects: 461236769Sobrien * The reference count for the suffix is decremented and the 462236769Sobrien * suffix is possibly freed 463236769Sobrien *----------------------------------------------------------------------- 464236769Sobrien */ 465236769Sobrienstatic void 466236769SobrienSuffRemove(Lst l, Suff *s) 467236769Sobrien{ 468236769Sobrien SuffUnRef(l, s); 469236769Sobrien if (s->refCount == 0) { 470236769Sobrien SuffUnRef(sufflist, s); 471236769Sobrien SuffFree(s); 472236769Sobrien } 473236769Sobrien} 474236769Sobrien 475236769Sobrien/*- 476236769Sobrien *----------------------------------------------------------------------- 477236769Sobrien * SuffInsert -- 478236769Sobrien * Insert the suffix into the list keeping the list ordered by suffix 479236769Sobrien * numbers. 480236769Sobrien * 481236769Sobrien * Input: 482236769Sobrien * l the list where in s should be inserted 483236769Sobrien * s the suffix to insert 484236769Sobrien * 485236769Sobrien * Results: 486236769Sobrien * None 487236769Sobrien * 488236769Sobrien * Side Effects: 489236769Sobrien * The reference count of the suffix is incremented 490236769Sobrien *----------------------------------------------------------------------- 491236769Sobrien */ 492236769Sobrienstatic void 493236769SobrienSuffInsert(Lst l, Suff *s) 494236769Sobrien{ 495236769Sobrien LstNode ln; /* current element in l we're examining */ 496236769Sobrien Suff *s2 = NULL; /* the suffix descriptor in this element */ 497236769Sobrien 498236769Sobrien if (Lst_Open(l) == FAILURE) { 499236769Sobrien return; 500236769Sobrien } 501236769Sobrien while ((ln = Lst_Next(l)) != NULL) { 502236769Sobrien s2 = (Suff *)Lst_Datum(ln); 503236769Sobrien if (s2->sNum >= s->sNum) { 504236769Sobrien break; 505236769Sobrien } 506236769Sobrien } 507236769Sobrien 508236769Sobrien Lst_Close(l); 509236769Sobrien if (DEBUG(SUFF)) { 510236769Sobrien fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum); 511236769Sobrien } 512236769Sobrien if (ln == NULL) { 513236769Sobrien if (DEBUG(SUFF)) { 514236769Sobrien fprintf(debug_file, "at end of list\n"); 515236769Sobrien } 516236769Sobrien (void)Lst_AtEnd(l, s); 517236769Sobrien s->refCount++; 518236769Sobrien (void)Lst_AtEnd(s->ref, l); 519236769Sobrien } else if (s2->sNum != s->sNum) { 520236769Sobrien if (DEBUG(SUFF)) { 521236769Sobrien fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum); 522236769Sobrien } 523236769Sobrien (void)Lst_InsertBefore(l, ln, s); 524236769Sobrien s->refCount++; 525236769Sobrien (void)Lst_AtEnd(s->ref, l); 526236769Sobrien } else if (DEBUG(SUFF)) { 527236769Sobrien fprintf(debug_file, "already there\n"); 528236769Sobrien } 529236769Sobrien} 530236769Sobrien 531236769Sobrien/*- 532236769Sobrien *----------------------------------------------------------------------- 533236769Sobrien * Suff_ClearSuffixes -- 534236769Sobrien * This is gross. Nuke the list of suffixes but keep all transformation 535236769Sobrien * rules around. The transformation graph is destroyed in this process, 536236769Sobrien * but we leave the list of rules so when a new graph is formed the rules 537236769Sobrien * will remain. 538236769Sobrien * This function is called from the parse module when a 539236769Sobrien * .SUFFIXES:\n line is encountered. 540236769Sobrien * 541236769Sobrien * Results: 542236769Sobrien * none 543236769Sobrien * 544236769Sobrien * Side Effects: 545236769Sobrien * the sufflist and its graph nodes are destroyed 546236769Sobrien *----------------------------------------------------------------------- 547236769Sobrien */ 548236769Sobrienvoid 549236769SobrienSuff_ClearSuffixes(void) 550236769Sobrien{ 551236769Sobrien#ifdef CLEANUP 552236769Sobrien Lst_Concat(suffClean, sufflist, LST_CONCLINK); 553236769Sobrien#endif 554236769Sobrien sufflist = Lst_Init(FALSE); 555236769Sobrien sNum = 0; 556236769Sobrien suffNull = emptySuff; 557236769Sobrien} 558236769Sobrien 559236769Sobrien/*- 560236769Sobrien *----------------------------------------------------------------------- 561236769Sobrien * SuffParseTransform -- 562236769Sobrien * Parse a transformation string to find its two component suffixes. 563236769Sobrien * 564236769Sobrien * Input: 565236769Sobrien * str String being parsed 566236769Sobrien * srcPtr Place to store source of trans. 567236769Sobrien * targPtr Place to store target of trans. 568236769Sobrien * 569236769Sobrien * Results: 570236769Sobrien * TRUE if the string is a valid transformation and FALSE otherwise. 571236769Sobrien * 572236769Sobrien * Side Effects: 573236769Sobrien * The passed pointers are overwritten. 574236769Sobrien * 575236769Sobrien *----------------------------------------------------------------------- 576236769Sobrien */ 577236769Sobrienstatic Boolean 578236769SobrienSuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr) 579236769Sobrien{ 580236769Sobrien LstNode srcLn; /* element in suffix list of trans source*/ 581236769Sobrien Suff *src; /* Source of transformation */ 582236769Sobrien LstNode targLn; /* element in suffix list of trans target*/ 583236769Sobrien char *str2; /* Extra pointer (maybe target suffix) */ 584236769Sobrien LstNode singleLn; /* element in suffix list of any suffix 585236769Sobrien * that exactly matches str */ 586236769Sobrien Suff *single = NULL;/* Source of possible transformation to 587236769Sobrien * null suffix */ 588236769Sobrien 589236769Sobrien srcLn = NULL; 590236769Sobrien singleLn = NULL; 591236769Sobrien 592236769Sobrien /* 593236769Sobrien * Loop looking first for a suffix that matches the start of the 594236769Sobrien * string and then for one that exactly matches the rest of it. If 595236769Sobrien * we can find two that meet these criteria, we've successfully 596236769Sobrien * parsed the string. 597236769Sobrien */ 598236769Sobrien for (;;) { 599236769Sobrien if (srcLn == NULL) { 600236769Sobrien srcLn = Lst_Find(sufflist, str, SuffSuffIsPrefix); 601236769Sobrien } else { 602236769Sobrien srcLn = Lst_FindFrom(sufflist, Lst_Succ(srcLn), str, 603236769Sobrien SuffSuffIsPrefix); 604236769Sobrien } 605236769Sobrien if (srcLn == NULL) { 606236769Sobrien /* 607236769Sobrien * Ran out of source suffixes -- no such rule 608236769Sobrien */ 609236769Sobrien if (singleLn != NULL) { 610236769Sobrien /* 611236769Sobrien * Not so fast Mr. Smith! There was a suffix that encompassed 612236769Sobrien * the entire string, so we assume it was a transformation 613236769Sobrien * to the null suffix (thank you POSIX). We still prefer to 614236769Sobrien * find a double rule over a singleton, hence we leave this 615236769Sobrien * check until the end. 616236769Sobrien * 617236769Sobrien * XXX: Use emptySuff over suffNull? 618236769Sobrien */ 619236769Sobrien *srcPtr = single; 620236769Sobrien *targPtr = suffNull; 621236769Sobrien return(TRUE); 622236769Sobrien } 623236769Sobrien return (FALSE); 624236769Sobrien } 625236769Sobrien src = (Suff *)Lst_Datum(srcLn); 626236769Sobrien str2 = str + src->nameLen; 627236769Sobrien if (*str2 == '\0') { 628236769Sobrien single = src; 629236769Sobrien singleLn = srcLn; 630236769Sobrien } else { 631236769Sobrien targLn = Lst_Find(sufflist, str2, SuffSuffHasNameP); 632236769Sobrien if (targLn != NULL) { 633236769Sobrien *srcPtr = src; 634236769Sobrien *targPtr = (Suff *)Lst_Datum(targLn); 635236769Sobrien return (TRUE); 636236769Sobrien } 637236769Sobrien } 638236769Sobrien } 639236769Sobrien} 640236769Sobrien 641236769Sobrien/*- 642236769Sobrien *----------------------------------------------------------------------- 643236769Sobrien * Suff_IsTransform -- 644236769Sobrien * Return TRUE if the given string is a transformation rule 645236769Sobrien * 646236769Sobrien * 647236769Sobrien * Input: 648236769Sobrien * str string to check 649236769Sobrien * 650236769Sobrien * Results: 651236769Sobrien * TRUE if the string is a concatenation of two known suffixes. 652236769Sobrien * FALSE otherwise 653236769Sobrien * 654236769Sobrien * Side Effects: 655236769Sobrien * None 656236769Sobrien *----------------------------------------------------------------------- 657236769Sobrien */ 658236769SobrienBoolean 659236769SobrienSuff_IsTransform(char *str) 660236769Sobrien{ 661236769Sobrien Suff *src, *targ; 662236769Sobrien 663236769Sobrien return (SuffParseTransform(str, &src, &targ)); 664236769Sobrien} 665236769Sobrien 666236769Sobrien/*- 667236769Sobrien *----------------------------------------------------------------------- 668236769Sobrien * Suff_AddTransform -- 669236769Sobrien * Add the transformation rule described by the line to the 670236769Sobrien * list of rules and place the transformation itself in the graph 671236769Sobrien * 672236769Sobrien * Input: 673236769Sobrien * line name of transformation to add 674236769Sobrien * 675236769Sobrien * Results: 676236769Sobrien * The node created for the transformation in the transforms list 677236769Sobrien * 678236769Sobrien * Side Effects: 679236769Sobrien * The node is placed on the end of the transforms Lst and links are 680236769Sobrien * made between the two suffixes mentioned in the target name 681236769Sobrien *----------------------------------------------------------------------- 682236769Sobrien */ 683236769SobrienGNode * 684236769SobrienSuff_AddTransform(char *line) 685236769Sobrien{ 686236769Sobrien GNode *gn; /* GNode of transformation rule */ 687236769Sobrien Suff *s, /* source suffix */ 688236769Sobrien *t; /* target suffix */ 689236769Sobrien LstNode ln; /* Node for existing transformation */ 690236769Sobrien 691236769Sobrien ln = Lst_Find(transforms, line, SuffGNHasNameP); 692236769Sobrien if (ln == NULL) { 693236769Sobrien /* 694236769Sobrien * Make a new graph node for the transformation. It will be filled in 695236769Sobrien * by the Parse module. 696236769Sobrien */ 697236769Sobrien gn = Targ_NewGN(line); 698236769Sobrien (void)Lst_AtEnd(transforms, gn); 699236769Sobrien } else { 700236769Sobrien /* 701236769Sobrien * New specification for transformation rule. Just nuke the old list 702236769Sobrien * of commands so they can be filled in again... We don't actually 703236769Sobrien * free the commands themselves, because a given command can be 704236769Sobrien * attached to several different transformations. 705236769Sobrien */ 706236769Sobrien gn = (GNode *)Lst_Datum(ln); 707236769Sobrien Lst_Destroy(gn->commands, NULL); 708236769Sobrien Lst_Destroy(gn->children, NULL); 709236769Sobrien gn->commands = Lst_Init(FALSE); 710236769Sobrien gn->children = Lst_Init(FALSE); 711236769Sobrien } 712236769Sobrien 713236769Sobrien gn->type = OP_TRANSFORM; 714236769Sobrien 715236769Sobrien (void)SuffParseTransform(line, &s, &t); 716236769Sobrien 717236769Sobrien /* 718236769Sobrien * link the two together in the proper relationship and order 719236769Sobrien */ 720236769Sobrien if (DEBUG(SUFF)) { 721236769Sobrien fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 722236769Sobrien s->name, t->name); 723236769Sobrien } 724236769Sobrien SuffInsert(t->children, s); 725236769Sobrien SuffInsert(s->parents, t); 726236769Sobrien 727236769Sobrien return (gn); 728236769Sobrien} 729236769Sobrien 730236769Sobrien/*- 731236769Sobrien *----------------------------------------------------------------------- 732236769Sobrien * Suff_EndTransform -- 733236769Sobrien * Handle the finish of a transformation definition, removing the 734236769Sobrien * transformation from the graph if it has neither commands nor 735236769Sobrien * sources. This is a callback procedure for the Parse module via 736236769Sobrien * Lst_ForEach 737236769Sobrien * 738236769Sobrien * Input: 739236769Sobrien * gnp Node for transformation 740236769Sobrien * dummy Node for transformation 741236769Sobrien * 742236769Sobrien * Results: 743236769Sobrien * === 0 744236769Sobrien * 745236769Sobrien * Side Effects: 746236769Sobrien * If the node has no commands or children, the children and parents 747236769Sobrien * lists of the affected suffixes are altered. 748236769Sobrien * 749236769Sobrien *----------------------------------------------------------------------- 750236769Sobrien */ 751236769Sobrienint 752236769SobrienSuff_EndTransform(void *gnp, void *dummy) 753236769Sobrien{ 754236769Sobrien GNode *gn = (GNode *)gnp; 755236769Sobrien 756236769Sobrien if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts)) 757236769Sobrien gn = (GNode *)Lst_Datum(Lst_Last(gn->cohorts)); 758236769Sobrien if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) && 759236769Sobrien Lst_IsEmpty(gn->children)) 760236769Sobrien { 761236769Sobrien Suff *s, *t; 762236769Sobrien 763236769Sobrien /* 764236769Sobrien * SuffParseTransform() may fail for special rules which are not 765236769Sobrien * actual transformation rules. (e.g. .DEFAULT) 766236769Sobrien */ 767236769Sobrien if (SuffParseTransform(gn->name, &s, &t)) { 768236769Sobrien Lst p; 769236769Sobrien 770236769Sobrien if (DEBUG(SUFF)) { 771236769Sobrien fprintf(debug_file, "deleting transformation from `%s' to `%s'\n", 772236769Sobrien s->name, t->name); 773236769Sobrien } 774236769Sobrien 775236769Sobrien /* 776236769Sobrien * Store s->parents because s could be deleted in SuffRemove 777236769Sobrien */ 778236769Sobrien p = s->parents; 779236769Sobrien 780236769Sobrien /* 781236769Sobrien * Remove the source from the target's children list. We check for a 782236769Sobrien * nil return to handle a beanhead saying something like 783236769Sobrien * .c.o .c.o: 784236769Sobrien * 785236769Sobrien * We'll be called twice when the next target is seen, but .c and .o 786236769Sobrien * are only linked once... 787236769Sobrien */ 788236769Sobrien SuffRemove(t->children, s); 789236769Sobrien 790236769Sobrien /* 791236769Sobrien * Remove the target from the source's parents list 792236769Sobrien */ 793236769Sobrien SuffRemove(p, t); 794236769Sobrien } 795236769Sobrien } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) { 796236769Sobrien fprintf(debug_file, "transformation %s complete\n", gn->name); 797236769Sobrien } 798236769Sobrien 799236769Sobrien return(dummy ? 0 : 0); 800236769Sobrien} 801236769Sobrien 802236769Sobrien/*- 803236769Sobrien *----------------------------------------------------------------------- 804236769Sobrien * SuffRebuildGraph -- 805236769Sobrien * Called from Suff_AddSuffix via Lst_ForEach to search through the 806236769Sobrien * list of existing transformation rules and rebuild the transformation 807236769Sobrien * graph when it has been destroyed by Suff_ClearSuffixes. If the 808236769Sobrien * given rule is a transformation involving this suffix and another, 809236769Sobrien * existing suffix, the proper relationship is established between 810236769Sobrien * the two. 811236769Sobrien * 812236769Sobrien * Input: 813236769Sobrien * transformp Transformation to test 814236769Sobrien * sp Suffix to rebuild 815236769Sobrien * 816236769Sobrien * Results: 817236769Sobrien * Always 0. 818236769Sobrien * 819236769Sobrien * Side Effects: 820236769Sobrien * The appropriate links will be made between this suffix and 821236769Sobrien * others if transformation rules exist for it. 822236769Sobrien * 823236769Sobrien *----------------------------------------------------------------------- 824236769Sobrien */ 825236769Sobrienstatic int 826236769SobrienSuffRebuildGraph(void *transformp, void *sp) 827236769Sobrien{ 828236769Sobrien GNode *transform = (GNode *)transformp; 829236769Sobrien Suff *s = (Suff *)sp; 830236769Sobrien char *cp; 831236769Sobrien LstNode ln; 832236769Sobrien Suff *s2; 833236769Sobrien SuffixCmpData sd; 834236769Sobrien 835236769Sobrien /* 836236769Sobrien * First see if it is a transformation from this suffix. 837236769Sobrien */ 838236769Sobrien cp = UNCONST(SuffStrIsPrefix(s->name, transform->name)); 839236769Sobrien if (cp != NULL) { 840236769Sobrien ln = Lst_Find(sufflist, cp, SuffSuffHasNameP); 841236769Sobrien if (ln != NULL) { 842236769Sobrien /* 843236769Sobrien * Found target. Link in and return, since it can't be anything 844236769Sobrien * else. 845236769Sobrien */ 846236769Sobrien s2 = (Suff *)Lst_Datum(ln); 847236769Sobrien SuffInsert(s2->children, s); 848236769Sobrien SuffInsert(s->parents, s2); 849236769Sobrien return(0); 850236769Sobrien } 851236769Sobrien } 852236769Sobrien 853236769Sobrien /* 854236769Sobrien * Not from, maybe to? 855236769Sobrien */ 856236769Sobrien sd.len = strlen(transform->name); 857236769Sobrien sd.ename = transform->name + sd.len; 858236769Sobrien cp = SuffSuffIsSuffix(s, &sd); 859236769Sobrien if (cp != NULL) { 860236769Sobrien /* 861236769Sobrien * Null-terminate the source suffix in order to find it. 862236769Sobrien */ 863236769Sobrien cp[1] = '\0'; 864236769Sobrien ln = Lst_Find(sufflist, transform->name, SuffSuffHasNameP); 865236769Sobrien /* 866236769Sobrien * Replace the start of the target suffix 867236769Sobrien */ 868236769Sobrien cp[1] = s->name[0]; 869236769Sobrien if (ln != NULL) { 870236769Sobrien /* 871236769Sobrien * Found it -- establish the proper relationship 872236769Sobrien */ 873236769Sobrien s2 = (Suff *)Lst_Datum(ln); 874236769Sobrien SuffInsert(s->children, s2); 875236769Sobrien SuffInsert(s2->parents, s); 876236769Sobrien } 877236769Sobrien } 878236769Sobrien return(0); 879236769Sobrien} 880236769Sobrien 881236769Sobrien/*- 882236769Sobrien *----------------------------------------------------------------------- 883236769Sobrien * SuffScanTargets -- 884236769Sobrien * Called from Suff_AddSuffix via Lst_ForEach to search through the 885236769Sobrien * list of existing targets and find if any of the existing targets 886236769Sobrien * can be turned into a transformation rule. 887236769Sobrien * 888236769Sobrien * Results: 889236769Sobrien * 1 if a new main target has been selected, 0 otherwise. 890236769Sobrien * 891236769Sobrien * Side Effects: 892236769Sobrien * If such a target is found and the target is the current main 893236769Sobrien * target, the main target is set to NULL and the next target 894236769Sobrien * examined (if that exists) becomes the main target. 895236769Sobrien * 896236769Sobrien *----------------------------------------------------------------------- 897236769Sobrien */ 898236769Sobrienstatic int 899236769SobrienSuffScanTargets(void *targetp, void *gsp) 900236769Sobrien{ 901236769Sobrien GNode *target = (GNode *)targetp; 902236769Sobrien GNodeSuff *gs = (GNodeSuff *)gsp; 903236769Sobrien Suff *s, *t; 904236769Sobrien char *ptr; 905236769Sobrien 906236769Sobrien if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) { 907236769Sobrien *gs->gn = target; 908236769Sobrien Targ_SetMain(target); 909236769Sobrien return 1; 910236769Sobrien } 911236769Sobrien 912236769Sobrien if ((unsigned int)target->type == OP_TRANSFORM) 913236769Sobrien return 0; 914236769Sobrien 915236769Sobrien if ((ptr = strstr(target->name, gs->s->name)) == NULL || 916236769Sobrien ptr == target->name) 917236769Sobrien return 0; 918236769Sobrien 919236769Sobrien if (SuffParseTransform(target->name, &s, &t)) { 920236769Sobrien if (*gs->gn == target) { 921236769Sobrien gs->r = TRUE; 922236769Sobrien *gs->gn = NULL; 923236769Sobrien Targ_SetMain(NULL); 924236769Sobrien } 925236769Sobrien Lst_Destroy(target->children, NULL); 926236769Sobrien target->children = Lst_Init(FALSE); 927236769Sobrien target->type = OP_TRANSFORM; 928236769Sobrien /* 929236769Sobrien * link the two together in the proper relationship and order 930236769Sobrien */ 931236769Sobrien if (DEBUG(SUFF)) { 932236769Sobrien fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 933236769Sobrien s->name, t->name); 934236769Sobrien } 935236769Sobrien SuffInsert(t->children, s); 936236769Sobrien SuffInsert(s->parents, t); 937236769Sobrien } 938236769Sobrien return 0; 939236769Sobrien} 940236769Sobrien 941236769Sobrien/*- 942236769Sobrien *----------------------------------------------------------------------- 943236769Sobrien * Suff_AddSuffix -- 944236769Sobrien * Add the suffix in string to the end of the list of known suffixes. 945236769Sobrien * Should we restructure the suffix graph? Make doesn't... 946236769Sobrien * 947236769Sobrien * Input: 948236769Sobrien * str the name of the suffix to add 949236769Sobrien * 950236769Sobrien * Results: 951236769Sobrien * None 952236769Sobrien * 953236769Sobrien * Side Effects: 954236769Sobrien * A GNode is created for the suffix and a Suff structure is created and 955236769Sobrien * added to the suffixes list unless the suffix was already known. 956236769Sobrien * The mainNode passed can be modified if a target mutated into a 957236769Sobrien * transform and that target happened to be the main target. 958236769Sobrien *----------------------------------------------------------------------- 959236769Sobrien */ 960236769Sobrienvoid 961236769SobrienSuff_AddSuffix(char *str, GNode **gn) 962236769Sobrien{ 963236769Sobrien Suff *s; /* new suffix descriptor */ 964236769Sobrien LstNode ln; 965236769Sobrien GNodeSuff gs; 966236769Sobrien 967236769Sobrien ln = Lst_Find(sufflist, str, SuffSuffHasNameP); 968236769Sobrien if (ln == NULL) { 969236769Sobrien s = bmake_malloc(sizeof(Suff)); 970236769Sobrien 971236769Sobrien s->name = bmake_strdup(str); 972236769Sobrien s->nameLen = strlen(s->name); 973236769Sobrien s->searchPath = Lst_Init(FALSE); 974236769Sobrien s->children = Lst_Init(FALSE); 975236769Sobrien s->parents = Lst_Init(FALSE); 976236769Sobrien s->ref = Lst_Init(FALSE); 977236769Sobrien s->sNum = sNum++; 978236769Sobrien s->flags = 0; 979236769Sobrien s->refCount = 1; 980236769Sobrien 981236769Sobrien (void)Lst_AtEnd(sufflist, s); 982236769Sobrien /* 983236769Sobrien * We also look at our existing targets list to see if adding 984236769Sobrien * this suffix will make one of our current targets mutate into 985236769Sobrien * a suffix rule. This is ugly, but other makes treat all targets 986236769Sobrien * that start with a . as suffix rules. 987236769Sobrien */ 988236769Sobrien gs.gn = gn; 989236769Sobrien gs.s = s; 990236769Sobrien gs.r = FALSE; 991236769Sobrien Lst_ForEach(Targ_List(), SuffScanTargets, &gs); 992236769Sobrien /* 993236769Sobrien * Look for any existing transformations from or to this suffix. 994236769Sobrien * XXX: Only do this after a Suff_ClearSuffixes? 995236769Sobrien */ 996236769Sobrien Lst_ForEach(transforms, SuffRebuildGraph, s); 997236769Sobrien } 998236769Sobrien} 999236769Sobrien 1000236769Sobrien/*- 1001236769Sobrien *----------------------------------------------------------------------- 1002236769Sobrien * Suff_GetPath -- 1003236769Sobrien * Return the search path for the given suffix, if it's defined. 1004236769Sobrien * 1005236769Sobrien * Results: 1006236769Sobrien * The searchPath for the desired suffix or NULL if the suffix isn't 1007236769Sobrien * defined. 1008236769Sobrien * 1009236769Sobrien * Side Effects: 1010236769Sobrien * None 1011236769Sobrien *----------------------------------------------------------------------- 1012236769Sobrien */ 1013236769SobrienLst 1014236769SobrienSuff_GetPath(char *sname) 1015236769Sobrien{ 1016236769Sobrien LstNode ln; 1017236769Sobrien Suff *s; 1018236769Sobrien 1019236769Sobrien ln = Lst_Find(sufflist, sname, SuffSuffHasNameP); 1020236769Sobrien if (ln == NULL) { 1021236769Sobrien return NULL; 1022236769Sobrien } else { 1023236769Sobrien s = (Suff *)Lst_Datum(ln); 1024236769Sobrien return (s->searchPath); 1025236769Sobrien } 1026236769Sobrien} 1027236769Sobrien 1028236769Sobrien/*- 1029236769Sobrien *----------------------------------------------------------------------- 1030236769Sobrien * Suff_DoPaths -- 1031236769Sobrien * Extend the search paths for all suffixes to include the default 1032236769Sobrien * search path. 1033236769Sobrien * 1034236769Sobrien * Results: 1035236769Sobrien * None. 1036236769Sobrien * 1037236769Sobrien * Side Effects: 1038236769Sobrien * The searchPath field of all the suffixes is extended by the 1039236769Sobrien * directories in dirSearchPath. If paths were specified for the 1040236769Sobrien * ".h" suffix, the directories are stuffed into a global variable 1041236769Sobrien * called ".INCLUDES" with each directory preceded by a -I. The same 1042236769Sobrien * is done for the ".a" suffix, except the variable is called 1043236769Sobrien * ".LIBS" and the flag is -L. 1044236769Sobrien *----------------------------------------------------------------------- 1045236769Sobrien */ 1046236769Sobrienvoid 1047236769SobrienSuff_DoPaths(void) 1048236769Sobrien{ 1049236769Sobrien Suff *s; 1050236769Sobrien LstNode ln; 1051236769Sobrien char *ptr; 1052236769Sobrien Lst inIncludes; /* Cumulative .INCLUDES path */ 1053236769Sobrien Lst inLibs; /* Cumulative .LIBS path */ 1054236769Sobrien 1055236769Sobrien if (Lst_Open(sufflist) == FAILURE) { 1056236769Sobrien return; 1057236769Sobrien } 1058236769Sobrien 1059236769Sobrien inIncludes = Lst_Init(FALSE); 1060236769Sobrien inLibs = Lst_Init(FALSE); 1061236769Sobrien 1062236769Sobrien while ((ln = Lst_Next(sufflist)) != NULL) { 1063236769Sobrien s = (Suff *)Lst_Datum(ln); 1064236769Sobrien if (!Lst_IsEmpty (s->searchPath)) { 1065236769Sobrien#ifdef INCLUDES 1066236769Sobrien if (s->flags & SUFF_INCLUDE) { 1067236769Sobrien Dir_Concat(inIncludes, s->searchPath); 1068236769Sobrien } 1069236769Sobrien#endif /* INCLUDES */ 1070236769Sobrien#ifdef LIBRARIES 1071236769Sobrien if (s->flags & SUFF_LIBRARY) { 1072236769Sobrien Dir_Concat(inLibs, s->searchPath); 1073236769Sobrien } 1074236769Sobrien#endif /* LIBRARIES */ 1075236769Sobrien Dir_Concat(s->searchPath, dirSearchPath); 1076236769Sobrien } else { 1077236769Sobrien Lst_Destroy(s->searchPath, Dir_Destroy); 1078236769Sobrien s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir); 1079236769Sobrien } 1080236769Sobrien } 1081236769Sobrien 1082236769Sobrien Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL, 0); 1083236769Sobrien free(ptr); 1084236769Sobrien Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL, 0); 1085236769Sobrien free(ptr); 1086236769Sobrien 1087236769Sobrien Lst_Destroy(inIncludes, Dir_Destroy); 1088236769Sobrien Lst_Destroy(inLibs, Dir_Destroy); 1089236769Sobrien 1090236769Sobrien Lst_Close(sufflist); 1091236769Sobrien} 1092236769Sobrien 1093236769Sobrien/*- 1094236769Sobrien *----------------------------------------------------------------------- 1095236769Sobrien * Suff_AddInclude -- 1096236769Sobrien * Add the given suffix as a type of file which gets included. 1097236769Sobrien * Called from the parse module when a .INCLUDES line is parsed. 1098236769Sobrien * The suffix must have already been defined. 1099236769Sobrien * 1100236769Sobrien * Input: 1101236769Sobrien * sname Name of the suffix to mark 1102236769Sobrien * 1103236769Sobrien * Results: 1104236769Sobrien * None. 1105236769Sobrien * 1106236769Sobrien * Side Effects: 1107236769Sobrien * The SUFF_INCLUDE bit is set in the suffix's flags field 1108236769Sobrien * 1109236769Sobrien *----------------------------------------------------------------------- 1110236769Sobrien */ 1111236769Sobrienvoid 1112236769SobrienSuff_AddInclude(char *sname) 1113236769Sobrien{ 1114236769Sobrien LstNode ln; 1115236769Sobrien Suff *s; 1116236769Sobrien 1117236769Sobrien ln = Lst_Find(sufflist, sname, SuffSuffHasNameP); 1118236769Sobrien if (ln != NULL) { 1119236769Sobrien s = (Suff *)Lst_Datum(ln); 1120236769Sobrien s->flags |= SUFF_INCLUDE; 1121236769Sobrien } 1122236769Sobrien} 1123236769Sobrien 1124236769Sobrien/*- 1125236769Sobrien *----------------------------------------------------------------------- 1126236769Sobrien * Suff_AddLib -- 1127236769Sobrien * Add the given suffix as a type of file which is a library. 1128236769Sobrien * Called from the parse module when parsing a .LIBS line. The 1129236769Sobrien * suffix must have been defined via .SUFFIXES before this is 1130236769Sobrien * called. 1131236769Sobrien * 1132236769Sobrien * Input: 1133236769Sobrien * sname Name of the suffix to mark 1134236769Sobrien * 1135236769Sobrien * Results: 1136236769Sobrien * None. 1137236769Sobrien * 1138236769Sobrien * Side Effects: 1139236769Sobrien * The SUFF_LIBRARY bit is set in the suffix's flags field 1140236769Sobrien * 1141236769Sobrien *----------------------------------------------------------------------- 1142236769Sobrien */ 1143236769Sobrienvoid 1144236769SobrienSuff_AddLib(char *sname) 1145236769Sobrien{ 1146236769Sobrien LstNode ln; 1147236769Sobrien Suff *s; 1148236769Sobrien 1149236769Sobrien ln = Lst_Find(sufflist, sname, SuffSuffHasNameP); 1150236769Sobrien if (ln != NULL) { 1151236769Sobrien s = (Suff *)Lst_Datum(ln); 1152236769Sobrien s->flags |= SUFF_LIBRARY; 1153236769Sobrien } 1154236769Sobrien} 1155236769Sobrien 1156236769Sobrien /********** Implicit Source Search Functions *********/ 1157236769Sobrien 1158236769Sobrien/*- 1159236769Sobrien *----------------------------------------------------------------------- 1160236769Sobrien * SuffAddSrc -- 1161236769Sobrien * Add a suffix as a Src structure to the given list with its parent 1162236769Sobrien * being the given Src structure. If the suffix is the null suffix, 1163236769Sobrien * the prefix is used unaltered as the file name in the Src structure. 1164236769Sobrien * 1165236769Sobrien * Input: 1166236769Sobrien * sp suffix for which to create a Src structure 1167236769Sobrien * lsp list and parent for the new Src 1168236769Sobrien * 1169236769Sobrien * Results: 1170236769Sobrien * always returns 0 1171236769Sobrien * 1172236769Sobrien * Side Effects: 1173236769Sobrien * A Src structure is created and tacked onto the end of the list 1174236769Sobrien *----------------------------------------------------------------------- 1175236769Sobrien */ 1176236769Sobrienstatic int 1177236769SobrienSuffAddSrc(void *sp, void *lsp) 1178236769Sobrien{ 1179236769Sobrien Suff *s = (Suff *)sp; 1180236769Sobrien LstSrc *ls = (LstSrc *)lsp; 1181236769Sobrien Src *s2; /* new Src structure */ 1182236769Sobrien Src *targ; /* Target structure */ 1183236769Sobrien 1184236769Sobrien targ = ls->s; 1185236769Sobrien 1186236769Sobrien if ((s->flags & SUFF_NULL) && (*s->name != '\0')) { 1187236769Sobrien /* 1188236769Sobrien * If the suffix has been marked as the NULL suffix, also create a Src 1189236769Sobrien * structure for a file with no suffix attached. Two birds, and all 1190236769Sobrien * that... 1191236769Sobrien */ 1192236769Sobrien s2 = bmake_malloc(sizeof(Src)); 1193236769Sobrien s2->file = bmake_strdup(targ->pref); 1194236769Sobrien s2->pref = targ->pref; 1195236769Sobrien s2->parent = targ; 1196236769Sobrien s2->node = NULL; 1197236769Sobrien s2->suff = s; 1198236769Sobrien s->refCount++; 1199236769Sobrien s2->children = 0; 1200236769Sobrien targ->children += 1; 1201236769Sobrien (void)Lst_AtEnd(ls->l, s2); 1202236769Sobrien#ifdef DEBUG_SRC 1203236769Sobrien s2->cp = Lst_Init(FALSE); 1204236769Sobrien Lst_AtEnd(targ->cp, s2); 1205236769Sobrien fprintf(debug_file, "1 add %x %x to %x:", targ, s2, ls->l); 1206236769Sobrien Lst_ForEach(ls->l, PrintAddr, NULL); 1207236769Sobrien fprintf(debug_file, "\n"); 1208236769Sobrien#endif 1209236769Sobrien } 1210236769Sobrien s2 = bmake_malloc(sizeof(Src)); 1211236769Sobrien s2->file = str_concat(targ->pref, s->name, 0); 1212236769Sobrien s2->pref = targ->pref; 1213236769Sobrien s2->parent = targ; 1214236769Sobrien s2->node = NULL; 1215236769Sobrien s2->suff = s; 1216236769Sobrien s->refCount++; 1217236769Sobrien s2->children = 0; 1218236769Sobrien targ->children += 1; 1219236769Sobrien (void)Lst_AtEnd(ls->l, s2); 1220236769Sobrien#ifdef DEBUG_SRC 1221236769Sobrien s2->cp = Lst_Init(FALSE); 1222236769Sobrien Lst_AtEnd(targ->cp, s2); 1223236769Sobrien fprintf(debug_file, "2 add %x %x to %x:", targ, s2, ls->l); 1224236769Sobrien Lst_ForEach(ls->l, PrintAddr, NULL); 1225236769Sobrien fprintf(debug_file, "\n"); 1226236769Sobrien#endif 1227236769Sobrien 1228236769Sobrien return(0); 1229236769Sobrien} 1230236769Sobrien 1231236769Sobrien/*- 1232236769Sobrien *----------------------------------------------------------------------- 1233236769Sobrien * SuffAddLevel -- 1234236769Sobrien * Add all the children of targ as Src structures to the given list 1235236769Sobrien * 1236236769Sobrien * Input: 1237236769Sobrien * l list to which to add the new level 1238236769Sobrien * targ Src structure to use as the parent 1239236769Sobrien * 1240236769Sobrien * Results: 1241236769Sobrien * None 1242236769Sobrien * 1243236769Sobrien * Side Effects: 1244236769Sobrien * Lots of structures are created and added to the list 1245236769Sobrien *----------------------------------------------------------------------- 1246236769Sobrien */ 1247236769Sobrienstatic void 1248236769SobrienSuffAddLevel(Lst l, Src *targ) 1249236769Sobrien{ 1250236769Sobrien LstSrc ls; 1251236769Sobrien 1252236769Sobrien ls.s = targ; 1253236769Sobrien ls.l = l; 1254236769Sobrien 1255236769Sobrien Lst_ForEach(targ->suff->children, SuffAddSrc, &ls); 1256236769Sobrien} 1257236769Sobrien 1258236769Sobrien/*- 1259236769Sobrien *---------------------------------------------------------------------- 1260236769Sobrien * SuffRemoveSrc -- 1261236769Sobrien * Free all src structures in list that don't have a reference count 1262236769Sobrien * 1263236769Sobrien * Results: 1264236769Sobrien * Ture if an src was removed 1265236769Sobrien * 1266236769Sobrien * Side Effects: 1267236769Sobrien * The memory is free'd. 1268236769Sobrien *---------------------------------------------------------------------- 1269236769Sobrien */ 1270236769Sobrienstatic int 1271236769SobrienSuffRemoveSrc(Lst l) 1272236769Sobrien{ 1273236769Sobrien LstNode ln; 1274236769Sobrien Src *s; 1275236769Sobrien int t = 0; 1276236769Sobrien 1277236769Sobrien if (Lst_Open(l) == FAILURE) { 1278236769Sobrien return 0; 1279236769Sobrien } 1280236769Sobrien#ifdef DEBUG_SRC 1281236769Sobrien fprintf(debug_file, "cleaning %lx: ", (unsigned long) l); 1282236769Sobrien Lst_ForEach(l, PrintAddr, NULL); 1283236769Sobrien fprintf(debug_file, "\n"); 1284236769Sobrien#endif 1285236769Sobrien 1286236769Sobrien 1287236769Sobrien while ((ln = Lst_Next(l)) != NULL) { 1288236769Sobrien s = (Src *)Lst_Datum(ln); 1289236769Sobrien if (s->children == 0) { 1290236769Sobrien free(s->file); 1291236769Sobrien if (!s->parent) 1292236769Sobrien free(s->pref); 1293236769Sobrien else { 1294236769Sobrien#ifdef DEBUG_SRC 1295236769Sobrien LstNode ln = Lst_Member(s->parent->cp, s); 1296236769Sobrien if (ln != NULL) 1297236769Sobrien Lst_Remove(s->parent->cp, ln); 1298236769Sobrien#endif 1299236769Sobrien --s->parent->children; 1300236769Sobrien } 1301236769Sobrien#ifdef DEBUG_SRC 1302236769Sobrien fprintf(debug_file, "free: [l=%x] p=%x %d\n", l, s, s->children); 1303236769Sobrien Lst_Destroy(s->cp, NULL); 1304236769Sobrien#endif 1305236769Sobrien Lst_Remove(l, ln); 1306236769Sobrien free(s); 1307236769Sobrien t |= 1; 1308236769Sobrien Lst_Close(l); 1309236769Sobrien return TRUE; 1310236769Sobrien } 1311236769Sobrien#ifdef DEBUG_SRC 1312236769Sobrien else { 1313236769Sobrien fprintf(debug_file, "keep: [l=%x] p=%x %d: ", l, s, s->children); 1314236769Sobrien Lst_ForEach(s->cp, PrintAddr, NULL); 1315236769Sobrien fprintf(debug_file, "\n"); 1316236769Sobrien } 1317236769Sobrien#endif 1318236769Sobrien } 1319236769Sobrien 1320236769Sobrien Lst_Close(l); 1321236769Sobrien 1322236769Sobrien return t; 1323236769Sobrien} 1324236769Sobrien 1325236769Sobrien/*- 1326236769Sobrien *----------------------------------------------------------------------- 1327236769Sobrien * SuffFindThem -- 1328236769Sobrien * Find the first existing file/target in the list srcs 1329236769Sobrien * 1330236769Sobrien * Input: 1331236769Sobrien * srcs list of Src structures to search through 1332236769Sobrien * 1333236769Sobrien * Results: 1334236769Sobrien * The lowest structure in the chain of transformations 1335236769Sobrien * 1336236769Sobrien * Side Effects: 1337236769Sobrien * None 1338236769Sobrien *----------------------------------------------------------------------- 1339236769Sobrien */ 1340236769Sobrienstatic Src * 1341236769SobrienSuffFindThem(Lst srcs, Lst slst) 1342236769Sobrien{ 1343236769Sobrien Src *s; /* current Src */ 1344236769Sobrien Src *rs; /* returned Src */ 1345236769Sobrien char *ptr; 1346236769Sobrien 1347236769Sobrien rs = NULL; 1348236769Sobrien 1349236769Sobrien while (!Lst_IsEmpty (srcs)) { 1350236769Sobrien s = (Src *)Lst_DeQueue(srcs); 1351236769Sobrien 1352236769Sobrien if (DEBUG(SUFF)) { 1353236769Sobrien fprintf(debug_file, "\ttrying %s...", s->file); 1354236769Sobrien } 1355236769Sobrien 1356236769Sobrien /* 1357236769Sobrien * A file is considered to exist if either a node exists in the 1358236769Sobrien * graph for it or the file actually exists. 1359236769Sobrien */ 1360236769Sobrien if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { 1361236769Sobrien#ifdef DEBUG_SRC 1362236769Sobrien fprintf(debug_file, "remove %x from %x\n", s, srcs); 1363236769Sobrien#endif 1364236769Sobrien rs = s; 1365236769Sobrien break; 1366236769Sobrien } 1367236769Sobrien 1368236769Sobrien if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) { 1369236769Sobrien rs = s; 1370236769Sobrien#ifdef DEBUG_SRC 1371236769Sobrien fprintf(debug_file, "remove %x from %x\n", s, srcs); 1372236769Sobrien#endif 1373236769Sobrien free(ptr); 1374236769Sobrien break; 1375236769Sobrien } 1376236769Sobrien 1377236769Sobrien if (DEBUG(SUFF)) { 1378236769Sobrien fprintf(debug_file, "not there\n"); 1379236769Sobrien } 1380236769Sobrien 1381236769Sobrien SuffAddLevel(srcs, s); 1382236769Sobrien Lst_AtEnd(slst, s); 1383236769Sobrien } 1384236769Sobrien 1385236769Sobrien if (DEBUG(SUFF) && rs) { 1386236769Sobrien fprintf(debug_file, "got it\n"); 1387236769Sobrien } 1388236769Sobrien return (rs); 1389236769Sobrien} 1390236769Sobrien 1391236769Sobrien/*- 1392236769Sobrien *----------------------------------------------------------------------- 1393236769Sobrien * SuffFindCmds -- 1394236769Sobrien * See if any of the children of the target in the Src structure is 1395236769Sobrien * one from which the target can be transformed. If there is one, 1396236769Sobrien * a Src structure is put together for it and returned. 1397236769Sobrien * 1398236769Sobrien * Input: 1399236769Sobrien * targ Src structure to play with 1400236769Sobrien * 1401236769Sobrien * Results: 1402236769Sobrien * The Src structure of the "winning" child, or NULL if no such beast. 1403236769Sobrien * 1404236769Sobrien * Side Effects: 1405236769Sobrien * A Src structure may be allocated. 1406236769Sobrien * 1407236769Sobrien *----------------------------------------------------------------------- 1408236769Sobrien */ 1409236769Sobrienstatic Src * 1410236769SobrienSuffFindCmds(Src *targ, Lst slst) 1411236769Sobrien{ 1412236769Sobrien LstNode ln; /* General-purpose list node */ 1413236769Sobrien GNode *t, /* Target GNode */ 1414236769Sobrien *s; /* Source GNode */ 1415236769Sobrien int prefLen;/* The length of the defined prefix */ 1416236769Sobrien Suff *suff; /* Suffix on matching beastie */ 1417236769Sobrien Src *ret; /* Return value */ 1418236769Sobrien char *cp; 1419236769Sobrien 1420236769Sobrien t = targ->node; 1421236769Sobrien (void)Lst_Open(t->children); 1422236769Sobrien prefLen = strlen(targ->pref); 1423236769Sobrien 1424236769Sobrien for (;;) { 1425236769Sobrien ln = Lst_Next(t->children); 1426236769Sobrien if (ln == NULL) { 1427236769Sobrien Lst_Close(t->children); 1428236769Sobrien return NULL; 1429236769Sobrien } 1430236769Sobrien s = (GNode *)Lst_Datum(ln); 1431236769Sobrien 1432236769Sobrien if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->commands)) { 1433236769Sobrien /* 1434236769Sobrien * We haven't looked to see if .OPTIONAL files exist yet, so 1435236769Sobrien * don't use one as the implicit source. 1436236769Sobrien * This allows us to use .OPTIONAL in .depend files so make won't 1437236769Sobrien * complain "don't know how to make xxx.h' when a dependent file 1438236769Sobrien * has been moved/deleted. 1439236769Sobrien */ 1440236769Sobrien continue; 1441236769Sobrien } 1442236769Sobrien 1443236769Sobrien cp = strrchr(s->name, '/'); 1444236769Sobrien if (cp == NULL) { 1445236769Sobrien cp = s->name; 1446236769Sobrien } else { 1447236769Sobrien cp++; 1448236769Sobrien } 1449236769Sobrien if (strncmp(cp, targ->pref, prefLen) != 0) 1450236769Sobrien continue; 1451236769Sobrien /* 1452236769Sobrien * The node matches the prefix ok, see if it has a known 1453236769Sobrien * suffix. 1454236769Sobrien */ 1455236769Sobrien ln = Lst_Find(sufflist, &cp[prefLen], SuffSuffHasNameP); 1456236769Sobrien if (ln == NULL) 1457236769Sobrien continue; 1458236769Sobrien /* 1459236769Sobrien * It even has a known suffix, see if there's a transformation 1460236769Sobrien * defined between the node's suffix and the target's suffix. 1461236769Sobrien * 1462236769Sobrien * XXX: Handle multi-stage transformations here, too. 1463236769Sobrien */ 1464236769Sobrien suff = (Suff *)Lst_Datum(ln); 1465236769Sobrien 1466236769Sobrien if (Lst_Member(suff->parents, targ->suff) != NULL) 1467236769Sobrien break; 1468236769Sobrien } 1469236769Sobrien 1470236769Sobrien /* 1471236769Sobrien * Hot Damn! Create a new Src structure to describe 1472236769Sobrien * this transformation (making sure to duplicate the 1473236769Sobrien * source node's name so Suff_FindDeps can free it 1474236769Sobrien * again (ick)), and return the new structure. 1475236769Sobrien */ 1476236769Sobrien ret = bmake_malloc(sizeof(Src)); 1477236769Sobrien ret->file = bmake_strdup(s->name); 1478236769Sobrien ret->pref = targ->pref; 1479236769Sobrien ret->suff = suff; 1480236769Sobrien suff->refCount++; 1481236769Sobrien ret->parent = targ; 1482236769Sobrien ret->node = s; 1483236769Sobrien ret->children = 0; 1484236769Sobrien targ->children += 1; 1485236769Sobrien#ifdef DEBUG_SRC 1486236769Sobrien ret->cp = Lst_Init(FALSE); 1487236769Sobrien fprintf(debug_file, "3 add %x %x\n", targ, ret); 1488236769Sobrien Lst_AtEnd(targ->cp, ret); 1489236769Sobrien#endif 1490236769Sobrien Lst_AtEnd(slst, ret); 1491236769Sobrien if (DEBUG(SUFF)) { 1492236769Sobrien fprintf(debug_file, "\tusing existing source %s\n", s->name); 1493236769Sobrien } 1494236769Sobrien return (ret); 1495236769Sobrien} 1496236769Sobrien 1497236769Sobrien/*- 1498236769Sobrien *----------------------------------------------------------------------- 1499236769Sobrien * SuffExpandChildren -- 1500236769Sobrien * Expand the names of any children of a given node that contain 1501236769Sobrien * variable invocations or file wildcards into actual targets. 1502236769Sobrien * 1503236769Sobrien * Input: 1504236769Sobrien * cln Child to examine 1505236769Sobrien * pgn Parent node being processed 1506236769Sobrien * 1507236769Sobrien * Results: 1508236769Sobrien * === 0 (continue) 1509236769Sobrien * 1510236769Sobrien * Side Effects: 1511236769Sobrien * The expanded node is removed from the parent's list of children, 1512236769Sobrien * and the parent's unmade counter is decremented, but other nodes 1513236769Sobrien * may be added. 1514236769Sobrien * 1515236769Sobrien *----------------------------------------------------------------------- 1516236769Sobrien */ 1517236769Sobrienstatic void 1518236769SobrienSuffExpandChildren(LstNode cln, GNode *pgn) 1519236769Sobrien{ 1520236769Sobrien GNode *cgn = (GNode *)Lst_Datum(cln); 1521236769Sobrien GNode *gn; /* New source 8) */ 1522236769Sobrien char *cp; /* Expanded value */ 1523236769Sobrien 1524236769Sobrien if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ)) 1525236769Sobrien /* It is all too hard to process the result of .ORDER */ 1526236769Sobrien return; 1527236769Sobrien 1528236769Sobrien if (cgn->type & OP_WAIT) 1529236769Sobrien /* Ignore these (& OP_PHONY ?) */ 1530236769Sobrien return; 1531236769Sobrien 1532236769Sobrien /* 1533236769Sobrien * First do variable expansion -- this takes precedence over 1534236769Sobrien * wildcard expansion. If the result contains wildcards, they'll be gotten 1535236769Sobrien * to later since the resulting words are tacked on to the end of 1536236769Sobrien * the children list. 1537236769Sobrien */ 1538236769Sobrien if (strchr(cgn->name, '$') == NULL) { 1539236769Sobrien SuffExpandWildcards(cln, pgn); 1540236769Sobrien return; 1541236769Sobrien } 1542236769Sobrien 1543236769Sobrien if (DEBUG(SUFF)) { 1544236769Sobrien fprintf(debug_file, "Expanding \"%s\"...", cgn->name); 1545236769Sobrien } 1546236769Sobrien cp = Var_Subst(NULL, cgn->name, pgn, TRUE); 1547236769Sobrien 1548236769Sobrien if (cp != NULL) { 1549236769Sobrien Lst members = Lst_Init(FALSE); 1550236769Sobrien 1551236769Sobrien if (cgn->type & OP_ARCHV) { 1552236769Sobrien /* 1553236769Sobrien * Node was an archive(member) target, so we want to call 1554236769Sobrien * on the Arch module to find the nodes for us, expanding 1555236769Sobrien * variables in the parent's context. 1556236769Sobrien */ 1557236769Sobrien char *sacrifice = cp; 1558236769Sobrien 1559236769Sobrien (void)Arch_ParseArchive(&sacrifice, members, pgn); 1560236769Sobrien } else { 1561236769Sobrien /* 1562236769Sobrien * Break the result into a vector of strings whose nodes 1563236769Sobrien * we can find, then add those nodes to the members list. 1564236769Sobrien * Unfortunately, we can't use brk_string b/c it 1565236769Sobrien * doesn't understand about variable specifications with 1566236769Sobrien * spaces in them... 1567236769Sobrien */ 1568236769Sobrien char *start; 1569236769Sobrien char *initcp = cp; /* For freeing... */ 1570236769Sobrien 1571236769Sobrien for (start = cp; *start == ' ' || *start == '\t'; start++) 1572236769Sobrien continue; 1573236769Sobrien for (cp = start; *cp != '\0'; cp++) { 1574236769Sobrien if (*cp == ' ' || *cp == '\t') { 1575236769Sobrien /* 1576236769Sobrien * White-space -- terminate element, find the node, 1577236769Sobrien * add it, skip any further spaces. 1578236769Sobrien */ 1579236769Sobrien *cp++ = '\0'; 1580236769Sobrien gn = Targ_FindNode(start, TARG_CREATE); 1581236769Sobrien (void)Lst_AtEnd(members, gn); 1582236769Sobrien while (*cp == ' ' || *cp == '\t') { 1583236769Sobrien cp++; 1584236769Sobrien } 1585236769Sobrien /* 1586236769Sobrien * Adjust cp for increment at start of loop, but 1587236769Sobrien * set start to first non-space. 1588236769Sobrien */ 1589236769Sobrien start = cp--; 1590236769Sobrien } else if (*cp == '$') { 1591236769Sobrien /* 1592236769Sobrien * Start of a variable spec -- contact variable module 1593236769Sobrien * to find the end so we can skip over it. 1594236769Sobrien */ 1595236769Sobrien char *junk; 1596236769Sobrien int len; 1597236769Sobrien void *freeIt; 1598236769Sobrien 1599236769Sobrien junk = Var_Parse(cp, pgn, TRUE, &len, &freeIt); 1600236769Sobrien if (junk != var_Error) { 1601236769Sobrien cp += len - 1; 1602236769Sobrien } 1603236769Sobrien 1604236769Sobrien if (freeIt) 1605236769Sobrien free(freeIt); 1606236769Sobrien } else if (*cp == '\\' && *cp != '\0') { 1607236769Sobrien /* 1608236769Sobrien * Escaped something -- skip over it 1609236769Sobrien */ 1610236769Sobrien cp++; 1611236769Sobrien } 1612236769Sobrien } 1613236769Sobrien 1614236769Sobrien if (cp != start) { 1615236769Sobrien /* 1616236769Sobrien * Stuff left over -- add it to the list too 1617236769Sobrien */ 1618236769Sobrien gn = Targ_FindNode(start, TARG_CREATE); 1619236769Sobrien (void)Lst_AtEnd(members, gn); 1620236769Sobrien } 1621236769Sobrien /* 1622236769Sobrien * Point cp back at the beginning again so the variable value 1623236769Sobrien * can be freed. 1624236769Sobrien */ 1625236769Sobrien cp = initcp; 1626236769Sobrien } 1627236769Sobrien 1628236769Sobrien /* 1629236769Sobrien * Add all elements of the members list to the parent node. 1630236769Sobrien */ 1631236769Sobrien while(!Lst_IsEmpty(members)) { 1632236769Sobrien gn = (GNode *)Lst_DeQueue(members); 1633236769Sobrien 1634236769Sobrien if (DEBUG(SUFF)) { 1635236769Sobrien fprintf(debug_file, "%s...", gn->name); 1636236769Sobrien } 1637236769Sobrien /* Add gn to the parents child list before the original child */ 1638236769Sobrien (void)Lst_InsertBefore(pgn->children, cln, gn); 1639236769Sobrien (void)Lst_AtEnd(gn->parents, pgn); 1640236769Sobrien pgn->unmade++; 1641236769Sobrien /* Expand wildcards on new node */ 1642236769Sobrien SuffExpandWildcards(Lst_Prev(cln), pgn); 1643236769Sobrien } 1644236769Sobrien Lst_Destroy(members, NULL); 1645236769Sobrien 1646236769Sobrien /* 1647236769Sobrien * Free the result 1648236769Sobrien */ 1649236769Sobrien free(cp); 1650236769Sobrien } 1651236769Sobrien if (DEBUG(SUFF)) { 1652236769Sobrien fprintf(debug_file, "\n"); 1653236769Sobrien } 1654236769Sobrien 1655236769Sobrien /* 1656236769Sobrien * Now the source is expanded, remove it from the list of children to 1657236769Sobrien * keep it from being processed. 1658236769Sobrien */ 1659236769Sobrien pgn->unmade--; 1660236769Sobrien Lst_Remove(pgn->children, cln); 1661236769Sobrien Lst_Remove(cgn->parents, Lst_Member(cgn->parents, pgn)); 1662236769Sobrien} 1663236769Sobrien 1664236769Sobrienstatic void 1665236769SobrienSuffExpandWildcards(LstNode cln, GNode *pgn) 1666236769Sobrien{ 1667236769Sobrien GNode *cgn = (GNode *)Lst_Datum(cln); 1668236769Sobrien GNode *gn; /* New source 8) */ 1669236769Sobrien char *cp; /* Expanded value */ 1670236769Sobrien Lst explist; /* List of expansions */ 1671236769Sobrien 1672236769Sobrien if (!Dir_HasWildcards(cgn->name)) 1673236769Sobrien return; 1674236769Sobrien 1675236769Sobrien /* 1676236769Sobrien * Expand the word along the chosen path 1677236769Sobrien */ 1678236769Sobrien explist = Lst_Init(FALSE); 1679236769Sobrien Dir_Expand(cgn->name, Suff_FindPath(cgn), explist); 1680236769Sobrien 1681236769Sobrien while (!Lst_IsEmpty(explist)) { 1682236769Sobrien /* 1683236769Sobrien * Fetch next expansion off the list and find its GNode 1684236769Sobrien */ 1685236769Sobrien cp = (char *)Lst_DeQueue(explist); 1686236769Sobrien 1687236769Sobrien if (DEBUG(SUFF)) { 1688236769Sobrien fprintf(debug_file, "%s...", cp); 1689236769Sobrien } 1690236769Sobrien gn = Targ_FindNode(cp, TARG_CREATE); 1691236769Sobrien 1692236769Sobrien /* Add gn to the parents child list before the original child */ 1693236769Sobrien (void)Lst_InsertBefore(pgn->children, cln, gn); 1694236769Sobrien (void)Lst_AtEnd(gn->parents, pgn); 1695236769Sobrien pgn->unmade++; 1696236769Sobrien } 1697236769Sobrien 1698236769Sobrien /* 1699236769Sobrien * Nuke what's left of the list 1700236769Sobrien */ 1701236769Sobrien Lst_Destroy(explist, NULL); 1702236769Sobrien 1703236769Sobrien if (DEBUG(SUFF)) { 1704236769Sobrien fprintf(debug_file, "\n"); 1705236769Sobrien } 1706236769Sobrien 1707236769Sobrien /* 1708236769Sobrien * Now the source is expanded, remove it from the list of children to 1709236769Sobrien * keep it from being processed. 1710236769Sobrien */ 1711236769Sobrien pgn->unmade--; 1712236769Sobrien Lst_Remove(pgn->children, cln); 1713236769Sobrien Lst_Remove(cgn->parents, Lst_Member(cgn->parents, pgn)); 1714236769Sobrien} 1715236769Sobrien 1716236769Sobrien/*- 1717236769Sobrien *----------------------------------------------------------------------- 1718236769Sobrien * Suff_FindPath -- 1719236769Sobrien * Find a path along which to expand the node. 1720236769Sobrien * 1721236769Sobrien * If the word has a known suffix, use that path. 1722236769Sobrien * If it has no known suffix, use the default system search path. 1723236769Sobrien * 1724236769Sobrien * Input: 1725236769Sobrien * gn Node being examined 1726236769Sobrien * 1727236769Sobrien * Results: 1728236769Sobrien * The appropriate path to search for the GNode. 1729236769Sobrien * 1730236769Sobrien * Side Effects: 1731236769Sobrien * XXX: We could set the suffix here so that we don't have to scan 1732236769Sobrien * again. 1733236769Sobrien * 1734236769Sobrien *----------------------------------------------------------------------- 1735236769Sobrien */ 1736236769SobrienLst 1737236769SobrienSuff_FindPath(GNode* gn) 1738236769Sobrien{ 1739236769Sobrien Suff *suff = gn->suffix; 1740236769Sobrien 1741236769Sobrien if (suff == NULL) { 1742236769Sobrien SuffixCmpData sd; /* Search string data */ 1743236769Sobrien LstNode ln; 1744236769Sobrien sd.len = strlen(gn->name); 1745236769Sobrien sd.ename = gn->name + sd.len; 1746236769Sobrien ln = Lst_Find(sufflist, &sd, SuffSuffIsSuffixP); 1747236769Sobrien 1748236769Sobrien if (DEBUG(SUFF)) { 1749236769Sobrien fprintf(debug_file, "Wildcard expanding \"%s\"...", gn->name); 1750236769Sobrien } 1751236769Sobrien if (ln != NULL) 1752236769Sobrien suff = (Suff *)Lst_Datum(ln); 1753236769Sobrien /* XXX: Here we can save the suffix so we don't have to do this again */ 1754236769Sobrien } 1755236769Sobrien 1756236769Sobrien if (suff != NULL) { 1757236769Sobrien if (DEBUG(SUFF)) { 1758236769Sobrien fprintf(debug_file, "suffix is \"%s\"...", suff->name); 1759236769Sobrien } 1760236769Sobrien return suff->searchPath; 1761236769Sobrien } else { 1762236769Sobrien /* 1763236769Sobrien * Use default search path 1764236769Sobrien */ 1765236769Sobrien return dirSearchPath; 1766236769Sobrien } 1767236769Sobrien} 1768236769Sobrien 1769236769Sobrien/*- 1770236769Sobrien *----------------------------------------------------------------------- 1771236769Sobrien * SuffApplyTransform -- 1772236769Sobrien * Apply a transformation rule, given the source and target nodes 1773236769Sobrien * and suffixes. 1774236769Sobrien * 1775236769Sobrien * Input: 1776236769Sobrien * tGn Target node 1777236769Sobrien * sGn Source node 1778236769Sobrien * t Target suffix 1779236769Sobrien * s Source suffix 1780236769Sobrien * 1781236769Sobrien * Results: 1782236769Sobrien * TRUE if successful, FALSE if not. 1783236769Sobrien * 1784236769Sobrien * Side Effects: 1785236769Sobrien * The source and target are linked and the commands from the 1786236769Sobrien * transformation are added to the target node's commands list. 1787236769Sobrien * All attributes but OP_DEPMASK and OP_TRANSFORM are applied 1788236769Sobrien * to the target. The target also inherits all the sources for 1789236769Sobrien * the transformation rule. 1790236769Sobrien * 1791236769Sobrien *----------------------------------------------------------------------- 1792236769Sobrien */ 1793236769Sobrienstatic Boolean 1794236769SobrienSuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) 1795236769Sobrien{ 1796236769Sobrien LstNode ln, nln; /* General node */ 1797236769Sobrien char *tname; /* Name of transformation rule */ 1798236769Sobrien GNode *gn; /* Node for same */ 1799236769Sobrien 1800236769Sobrien /* 1801236769Sobrien * Form the proper links between the target and source. 1802236769Sobrien */ 1803236769Sobrien (void)Lst_AtEnd(tGn->children, sGn); 1804236769Sobrien (void)Lst_AtEnd(sGn->parents, tGn); 1805236769Sobrien tGn->unmade += 1; 1806236769Sobrien 1807236769Sobrien /* 1808236769Sobrien * Locate the transformation rule itself 1809236769Sobrien */ 1810236769Sobrien tname = str_concat(s->name, t->name, 0); 1811236769Sobrien ln = Lst_Find(transforms, tname, SuffGNHasNameP); 1812236769Sobrien free(tname); 1813236769Sobrien 1814236769Sobrien if (ln == NULL) { 1815236769Sobrien /* 1816236769Sobrien * Not really such a transformation rule (can happen when we're 1817236769Sobrien * called to link an OP_MEMBER and OP_ARCHV node), so return 1818236769Sobrien * FALSE. 1819236769Sobrien */ 1820236769Sobrien return(FALSE); 1821236769Sobrien } 1822236769Sobrien 1823236769Sobrien gn = (GNode *)Lst_Datum(ln); 1824236769Sobrien 1825236769Sobrien if (DEBUG(SUFF)) { 1826236769Sobrien fprintf(debug_file, "\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); 1827236769Sobrien } 1828236769Sobrien 1829236769Sobrien /* 1830236769Sobrien * Record last child for expansion purposes 1831236769Sobrien */ 1832236769Sobrien ln = Lst_Last(tGn->children); 1833236769Sobrien 1834236769Sobrien /* 1835236769Sobrien * Pass the buck to Make_HandleUse to apply the rule 1836236769Sobrien */ 1837236769Sobrien (void)Make_HandleUse(gn, tGn); 1838236769Sobrien 1839236769Sobrien /* 1840236769Sobrien * Deal with wildcards and variables in any acquired sources 1841236769Sobrien */ 1842236769Sobrien for (ln = Lst_Succ(ln); ln != NULL; ln = nln) { 1843236769Sobrien nln = Lst_Succ(ln); 1844236769Sobrien SuffExpandChildren(ln, tGn); 1845236769Sobrien } 1846236769Sobrien 1847236769Sobrien /* 1848236769Sobrien * Keep track of another parent to which this beast is transformed so 1849236769Sobrien * the .IMPSRC variable can be set correctly for the parent. 1850236769Sobrien */ 1851236769Sobrien (void)Lst_AtEnd(sGn->iParents, tGn); 1852236769Sobrien 1853236769Sobrien return(TRUE); 1854236769Sobrien} 1855236769Sobrien 1856236769Sobrien 1857236769Sobrien/*- 1858236769Sobrien *----------------------------------------------------------------------- 1859236769Sobrien * SuffFindArchiveDeps -- 1860236769Sobrien * Locate dependencies for an OP_ARCHV node. 1861236769Sobrien * 1862236769Sobrien * Input: 1863236769Sobrien * gn Node for which to locate dependencies 1864236769Sobrien * 1865236769Sobrien * Results: 1866236769Sobrien * None 1867236769Sobrien * 1868236769Sobrien * Side Effects: 1869236769Sobrien * Same as Suff_FindDeps 1870236769Sobrien * 1871236769Sobrien *----------------------------------------------------------------------- 1872236769Sobrien */ 1873236769Sobrienstatic void 1874236769SobrienSuffFindArchiveDeps(GNode *gn, Lst slst) 1875236769Sobrien{ 1876236769Sobrien char *eoarch; /* End of archive portion */ 1877236769Sobrien char *eoname; /* End of member portion */ 1878236769Sobrien GNode *mem; /* Node for member */ 1879236769Sobrien static const char *copy[] = { 1880236769Sobrien /* Variables to be copied from the member node */ 1881236769Sobrien TARGET, /* Must be first */ 1882236769Sobrien PREFIX, /* Must be second */ 1883236769Sobrien }; 1884236769Sobrien int i; /* Index into copy and vals */ 1885236769Sobrien Suff *ms; /* Suffix descriptor for member */ 1886236769Sobrien char *name; /* Start of member's name */ 1887236769Sobrien 1888236769Sobrien /* 1889236769Sobrien * The node is an archive(member) pair. so we must find a 1890236769Sobrien * suffix for both of them. 1891236769Sobrien */ 1892236769Sobrien eoarch = strchr(gn->name, '('); 1893236769Sobrien eoname = strchr(eoarch, ')'); 1894236769Sobrien 1895236769Sobrien *eoname = '\0'; /* Nuke parentheses during suffix search */ 1896236769Sobrien *eoarch = '\0'; /* So a suffix can be found */ 1897236769Sobrien 1898236769Sobrien name = eoarch + 1; 1899236769Sobrien 1900236769Sobrien /* 1901236769Sobrien * To simplify things, call Suff_FindDeps recursively on the member now, 1902236769Sobrien * so we can simply compare the member's .PREFIX and .TARGET variables 1903236769Sobrien * to locate its suffix. This allows us to figure out the suffix to 1904236769Sobrien * use for the archive without having to do a quadratic search over the 1905236769Sobrien * suffix list, backtracking for each one... 1906236769Sobrien */ 1907236769Sobrien mem = Targ_FindNode(name, TARG_CREATE); 1908236769Sobrien SuffFindDeps(mem, slst); 1909236769Sobrien 1910236769Sobrien /* 1911236769Sobrien * Create the link between the two nodes right off 1912236769Sobrien */ 1913236769Sobrien (void)Lst_AtEnd(gn->children, mem); 1914236769Sobrien (void)Lst_AtEnd(mem->parents, gn); 1915236769Sobrien gn->unmade += 1; 1916236769Sobrien 1917236769Sobrien /* 1918236769Sobrien * Copy in the variables from the member node to this one. 1919236769Sobrien */ 1920236769Sobrien for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) { 1921236769Sobrien char *p1; 1922236769Sobrien Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn, 0); 1923236769Sobrien if (p1) 1924236769Sobrien free(p1); 1925236769Sobrien 1926236769Sobrien } 1927236769Sobrien 1928236769Sobrien ms = mem->suffix; 1929236769Sobrien if (ms == NULL) { 1930236769Sobrien /* 1931236769Sobrien * Didn't know what it was -- use .NULL suffix if not in make mode 1932236769Sobrien */ 1933236769Sobrien if (DEBUG(SUFF)) { 1934236769Sobrien fprintf(debug_file, "using null suffix\n"); 1935236769Sobrien } 1936236769Sobrien ms = suffNull; 1937236769Sobrien } 1938236769Sobrien 1939236769Sobrien 1940236769Sobrien /* 1941236769Sobrien * Set the other two local variables required for this target. 1942236769Sobrien */ 1943236769Sobrien Var_Set(MEMBER, name, gn, 0); 1944236769Sobrien Var_Set(ARCHIVE, gn->name, gn, 0); 1945236769Sobrien 1946236769Sobrien if (ms != NULL) { 1947236769Sobrien /* 1948236769Sobrien * Member has a known suffix, so look for a transformation rule from 1949236769Sobrien * it to a possible suffix of the archive. Rather than searching 1950236769Sobrien * through the entire list, we just look at suffixes to which the 1951236769Sobrien * member's suffix may be transformed... 1952236769Sobrien */ 1953236769Sobrien LstNode ln; 1954236769Sobrien SuffixCmpData sd; /* Search string data */ 1955236769Sobrien 1956236769Sobrien /* 1957236769Sobrien * Use first matching suffix... 1958236769Sobrien */ 1959236769Sobrien sd.len = eoarch - gn->name; 1960236769Sobrien sd.ename = eoarch; 1961236769Sobrien ln = Lst_Find(ms->parents, &sd, SuffSuffIsSuffixP); 1962236769Sobrien 1963236769Sobrien if (ln != NULL) { 1964236769Sobrien /* 1965236769Sobrien * Got one -- apply it 1966236769Sobrien */ 1967236769Sobrien if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) && 1968236769Sobrien DEBUG(SUFF)) 1969236769Sobrien { 1970236769Sobrien fprintf(debug_file, "\tNo transformation from %s -> %s\n", 1971236769Sobrien ms->name, ((Suff *)Lst_Datum(ln))->name); 1972236769Sobrien } 1973236769Sobrien } 1974236769Sobrien } 1975236769Sobrien 1976236769Sobrien /* 1977236769Sobrien * Replace the opening and closing parens now we've no need of the separate 1978236769Sobrien * pieces. 1979236769Sobrien */ 1980236769Sobrien *eoarch = '('; *eoname = ')'; 1981236769Sobrien 1982236769Sobrien /* 1983236769Sobrien * Pretend gn appeared to the left of a dependency operator so 1984236769Sobrien * the user needn't provide a transformation from the member to the 1985236769Sobrien * archive. 1986236769Sobrien */ 1987236769Sobrien if (OP_NOP(gn->type)) { 1988236769Sobrien gn->type |= OP_DEPENDS; 1989236769Sobrien } 1990236769Sobrien 1991236769Sobrien /* 1992236769Sobrien * Flag the member as such so we remember to look in the archive for 1993236769Sobrien * its modification time. 1994236769Sobrien */ 1995236769Sobrien mem->type |= OP_MEMBER; 1996236769Sobrien} 1997236769Sobrien 1998236769Sobrien/*- 1999236769Sobrien *----------------------------------------------------------------------- 2000236769Sobrien * SuffFindNormalDeps -- 2001236769Sobrien * Locate implicit dependencies for regular targets. 2002236769Sobrien * 2003236769Sobrien * Input: 2004236769Sobrien * gn Node for which to find sources 2005236769Sobrien * 2006236769Sobrien * Results: 2007236769Sobrien * None. 2008236769Sobrien * 2009236769Sobrien * Side Effects: 2010236769Sobrien * Same as Suff_FindDeps... 2011236769Sobrien * 2012236769Sobrien *----------------------------------------------------------------------- 2013236769Sobrien */ 2014236769Sobrienstatic void 2015236769SobrienSuffFindNormalDeps(GNode *gn, Lst slst) 2016236769Sobrien{ 2017236769Sobrien char *eoname; /* End of name */ 2018236769Sobrien char *sopref; /* Start of prefix */ 2019236769Sobrien LstNode ln, nln; /* Next suffix node to check */ 2020236769Sobrien Lst srcs; /* List of sources at which to look */ 2021236769Sobrien Lst targs; /* List of targets to which things can be 2022236769Sobrien * transformed. They all have the same file, 2023236769Sobrien * but different suff and pref fields */ 2024236769Sobrien Src *bottom; /* Start of found transformation path */ 2025236769Sobrien Src *src; /* General Src pointer */ 2026236769Sobrien char *pref; /* Prefix to use */ 2027236769Sobrien Src *targ; /* General Src target pointer */ 2028236769Sobrien SuffixCmpData sd; /* Search string data */ 2029236769Sobrien 2030236769Sobrien 2031236769Sobrien sd.len = strlen(gn->name); 2032236769Sobrien sd.ename = eoname = gn->name + sd.len; 2033236769Sobrien 2034236769Sobrien sopref = gn->name; 2035236769Sobrien 2036236769Sobrien /* 2037236769Sobrien * Begin at the beginning... 2038236769Sobrien */ 2039236769Sobrien ln = Lst_First(sufflist); 2040236769Sobrien srcs = Lst_Init(FALSE); 2041236769Sobrien targs = Lst_Init(FALSE); 2042236769Sobrien 2043236769Sobrien /* 2044236769Sobrien * We're caught in a catch-22 here. On the one hand, we want to use any 2045236769Sobrien * transformation implied by the target's sources, but we can't examine 2046236769Sobrien * the sources until we've expanded any variables/wildcards they may hold, 2047236769Sobrien * and we can't do that until we've set up the target's local variables 2048236769Sobrien * and we can't do that until we know what the proper suffix for the 2049236769Sobrien * target is (in case there are two suffixes one of which is a suffix of 2050236769Sobrien * the other) and we can't know that until we've found its implied 2051236769Sobrien * source, which we may not want to use if there's an existing source 2052236769Sobrien * that implies a different transformation. 2053236769Sobrien * 2054236769Sobrien * In an attempt to get around this, which may not work all the time, 2055236769Sobrien * but should work most of the time, we look for implied sources first, 2056236769Sobrien * checking transformations to all possible suffixes of the target, 2057236769Sobrien * use what we find to set the target's local variables, expand the 2058236769Sobrien * children, then look for any overriding transformations they imply. 2059236769Sobrien * Should we find one, we discard the one we found before. 2060236769Sobrien */ 2061250773Ssjg bottom = NULL; 2062250773Ssjg targ = NULL; 2063236769Sobrien 2064250773Ssjg if (!(gn->type & OP_PHONY)) { 2065250773Ssjg 2066250837Ssjg while (ln != NULL) { 2067250837Ssjg /* 2068250837Ssjg * Look for next possible suffix... 2069250837Ssjg */ 2070250837Ssjg ln = Lst_FindFrom(sufflist, ln, &sd, SuffSuffIsSuffixP); 2071250837Ssjg 2072250837Ssjg if (ln != NULL) { 2073250837Ssjg int prefLen; /* Length of the prefix */ 2074250837Ssjg 2075250837Ssjg /* 2076250837Ssjg * Allocate a Src structure to which things can be transformed 2077250837Ssjg */ 2078250837Ssjg targ = bmake_malloc(sizeof(Src)); 2079250837Ssjg targ->file = bmake_strdup(gn->name); 2080250837Ssjg targ->suff = (Suff *)Lst_Datum(ln); 2081250837Ssjg targ->suff->refCount++; 2082250837Ssjg targ->node = gn; 2083250837Ssjg targ->parent = NULL; 2084250837Ssjg targ->children = 0; 2085250837Ssjg#ifdef DEBUG_SRC 2086250837Ssjg targ->cp = Lst_Init(FALSE); 2087250837Ssjg#endif 2088250837Ssjg 2089250837Ssjg /* 2090250837Ssjg * Allocate room for the prefix, whose end is found by 2091250837Ssjg * subtracting the length of the suffix from 2092250837Ssjg * the end of the name. 2093250837Ssjg */ 2094250837Ssjg prefLen = (eoname - targ->suff->nameLen) - sopref; 2095250837Ssjg targ->pref = bmake_malloc(prefLen + 1); 2096250837Ssjg memcpy(targ->pref, sopref, prefLen); 2097250837Ssjg targ->pref[prefLen] = '\0'; 2098250837Ssjg 2099250837Ssjg /* 2100250837Ssjg * Add nodes from which the target can be made 2101250837Ssjg */ 2102250837Ssjg SuffAddLevel(srcs, targ); 2103250837Ssjg 2104250837Ssjg /* 2105250837Ssjg * Record the target so we can nuke it 2106250837Ssjg */ 2107250837Ssjg (void)Lst_AtEnd(targs, targ); 2108250837Ssjg 2109250837Ssjg /* 2110250837Ssjg * Search from this suffix's successor... 2111250837Ssjg */ 2112250837Ssjg ln = Lst_Succ(ln); 2113250837Ssjg } 2114250837Ssjg } 2115250837Ssjg 2116236769Sobrien /* 2117250837Ssjg * Handle target of unknown suffix... 2118236769Sobrien */ 2119250837Ssjg if (Lst_IsEmpty(targs) && suffNull != NULL) { 2120250837Ssjg if (DEBUG(SUFF)) { 2121250837Ssjg fprintf(debug_file, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name); 2122250837Ssjg } 2123236769Sobrien 2124236769Sobrien targ = bmake_malloc(sizeof(Src)); 2125236769Sobrien targ->file = bmake_strdup(gn->name); 2126250837Ssjg targ->suff = suffNull; 2127236769Sobrien targ->suff->refCount++; 2128236769Sobrien targ->node = gn; 2129236769Sobrien targ->parent = NULL; 2130236769Sobrien targ->children = 0; 2131250837Ssjg targ->pref = bmake_strdup(sopref); 2132236769Sobrien#ifdef DEBUG_SRC 2133236769Sobrien targ->cp = Lst_Init(FALSE); 2134236769Sobrien#endif 2135236769Sobrien 2136236769Sobrien /* 2137250837Ssjg * Only use the default suffix rules if we don't have commands 2138250837Ssjg * defined for this gnode; traditional make programs used to 2139250837Ssjg * not define suffix rules if the gnode had children but we 2140250837Ssjg * don't do this anymore. 2141236769Sobrien */ 2142250837Ssjg if (Lst_IsEmpty(gn->commands)) 2143250837Ssjg SuffAddLevel(srcs, targ); 2144250837Ssjg else { 2145250837Ssjg if (DEBUG(SUFF)) 2146250837Ssjg fprintf(debug_file, "not "); 2147250837Ssjg } 2148236769Sobrien 2149250837Ssjg if (DEBUG(SUFF)) 2150250837Ssjg fprintf(debug_file, "adding suffix rules\n"); 2151236769Sobrien 2152236769Sobrien (void)Lst_AtEnd(targs, targ); 2153236769Sobrien } 2154236769Sobrien 2155236769Sobrien /* 2156250837Ssjg * Using the list of possible sources built up from the target 2157250837Ssjg * suffix(es), try and find an existing file/target that matches. 2158236769Sobrien */ 2159250837Ssjg bottom = SuffFindThem(srcs, slst); 2160236769Sobrien 2161250837Ssjg if (bottom == NULL) { 2162250837Ssjg /* 2163250837Ssjg * No known transformations -- use the first suffix found 2164250837Ssjg * for setting the local variables. 2165250837Ssjg */ 2166250837Ssjg if (!Lst_IsEmpty(targs)) { 2167250837Ssjg targ = (Src *)Lst_Datum(Lst_First(targs)); 2168250837Ssjg } else { 2169250837Ssjg targ = NULL; 2170250837Ssjg } 2171236769Sobrien } else { 2172250837Ssjg /* 2173250837Ssjg * Work up the transformation path to find the suffix of the 2174250837Ssjg * target to which the transformation was made. 2175250837Ssjg */ 2176250837Ssjg for (targ = bottom; targ->parent != NULL; targ = targ->parent) 2177250837Ssjg continue; 2178236769Sobrien } 2179236769Sobrien } 2180236769Sobrien 2181236769Sobrien Var_Set(TARGET, gn->path ? gn->path : gn->name, gn, 0); 2182236769Sobrien 2183236769Sobrien pref = (targ != NULL) ? targ->pref : gn->name; 2184236769Sobrien Var_Set(PREFIX, pref, gn, 0); 2185236769Sobrien 2186236769Sobrien /* 2187236769Sobrien * Now we've got the important local variables set, expand any sources 2188236769Sobrien * that still contain variables or wildcards in their names. 2189236769Sobrien */ 2190236769Sobrien for (ln = Lst_First(gn->children); ln != NULL; ln = nln) { 2191236769Sobrien nln = Lst_Succ(ln); 2192236769Sobrien SuffExpandChildren(ln, gn); 2193236769Sobrien } 2194236769Sobrien 2195236769Sobrien if (targ == NULL) { 2196236769Sobrien if (DEBUG(SUFF)) { 2197236769Sobrien fprintf(debug_file, "\tNo valid suffix on %s\n", gn->name); 2198236769Sobrien } 2199236769Sobrien 2200236769Sobriensfnd_abort: 2201236769Sobrien /* 2202236769Sobrien * Deal with finding the thing on the default search path. We 2203236769Sobrien * always do that, not only if the node is only a source (not 2204236769Sobrien * on the lhs of a dependency operator or [XXX] it has neither 2205236769Sobrien * children or commands) as the old pmake did. 2206236769Sobrien */ 2207236769Sobrien if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) { 2208236769Sobrien free(gn->path); 2209236769Sobrien gn->path = Dir_FindFile(gn->name, 2210236769Sobrien (targ == NULL ? dirSearchPath : 2211236769Sobrien targ->suff->searchPath)); 2212236769Sobrien if (gn->path != NULL) { 2213236769Sobrien char *ptr; 2214236769Sobrien Var_Set(TARGET, gn->path, gn, 0); 2215236769Sobrien 2216236769Sobrien if (targ != NULL) { 2217236769Sobrien /* 2218236769Sobrien * Suffix known for the thing -- trim the suffix off 2219236769Sobrien * the path to form the proper .PREFIX variable. 2220236769Sobrien */ 2221236769Sobrien int savep = strlen(gn->path) - targ->suff->nameLen; 2222236769Sobrien char savec; 2223236769Sobrien 2224236769Sobrien if (gn->suffix) 2225236769Sobrien gn->suffix->refCount--; 2226236769Sobrien gn->suffix = targ->suff; 2227236769Sobrien gn->suffix->refCount++; 2228236769Sobrien 2229236769Sobrien savec = gn->path[savep]; 2230236769Sobrien gn->path[savep] = '\0'; 2231236769Sobrien 2232236769Sobrien if ((ptr = strrchr(gn->path, '/')) != NULL) 2233236769Sobrien ptr++; 2234236769Sobrien else 2235236769Sobrien ptr = gn->path; 2236236769Sobrien 2237236769Sobrien Var_Set(PREFIX, ptr, gn, 0); 2238236769Sobrien 2239236769Sobrien gn->path[savep] = savec; 2240236769Sobrien } else { 2241236769Sobrien /* 2242236769Sobrien * The .PREFIX gets the full path if the target has 2243236769Sobrien * no known suffix. 2244236769Sobrien */ 2245236769Sobrien if (gn->suffix) 2246236769Sobrien gn->suffix->refCount--; 2247236769Sobrien gn->suffix = NULL; 2248236769Sobrien 2249236769Sobrien if ((ptr = strrchr(gn->path, '/')) != NULL) 2250236769Sobrien ptr++; 2251236769Sobrien else 2252236769Sobrien ptr = gn->path; 2253236769Sobrien 2254236769Sobrien Var_Set(PREFIX, ptr, gn, 0); 2255236769Sobrien } 2256236769Sobrien } 2257236769Sobrien } 2258236769Sobrien 2259236769Sobrien goto sfnd_return; 2260236769Sobrien } 2261236769Sobrien 2262236769Sobrien /* 2263236769Sobrien * If the suffix indicates that the target is a library, mark that in 2264236769Sobrien * the node's type field. 2265236769Sobrien */ 2266236769Sobrien if (targ->suff->flags & SUFF_LIBRARY) { 2267236769Sobrien gn->type |= OP_LIB; 2268236769Sobrien } 2269236769Sobrien 2270236769Sobrien /* 2271236769Sobrien * Check for overriding transformation rule implied by sources 2272236769Sobrien */ 2273236769Sobrien if (!Lst_IsEmpty(gn->children)) { 2274236769Sobrien src = SuffFindCmds(targ, slst); 2275236769Sobrien 2276236769Sobrien if (src != NULL) { 2277236769Sobrien /* 2278236769Sobrien * Free up all the Src structures in the transformation path 2279236769Sobrien * up to, but not including, the parent node. 2280236769Sobrien */ 2281236769Sobrien while (bottom && bottom->parent != NULL) { 2282236769Sobrien if (Lst_Member(slst, bottom) == NULL) { 2283236769Sobrien Lst_AtEnd(slst, bottom); 2284236769Sobrien } 2285236769Sobrien bottom = bottom->parent; 2286236769Sobrien } 2287236769Sobrien bottom = src; 2288236769Sobrien } 2289236769Sobrien } 2290236769Sobrien 2291236769Sobrien if (bottom == NULL) { 2292236769Sobrien /* 2293236769Sobrien * No idea from where it can come -- return now. 2294236769Sobrien */ 2295236769Sobrien goto sfnd_abort; 2296236769Sobrien } 2297236769Sobrien 2298236769Sobrien /* 2299236769Sobrien * We now have a list of Src structures headed by 'bottom' and linked via 2300236769Sobrien * their 'parent' pointers. What we do next is create links between 2301236769Sobrien * source and target nodes (which may or may not have been created) 2302236769Sobrien * and set the necessary local variables in each target. The 2303236769Sobrien * commands for each target are set from the commands of the 2304236769Sobrien * transformation rule used to get from the src suffix to the targ 2305236769Sobrien * suffix. Note that this causes the commands list of the original 2306236769Sobrien * node, gn, to be replaced by the commands of the final 2307236769Sobrien * transformation rule. Also, the unmade field of gn is incremented. 2308236769Sobrien * Etc. 2309236769Sobrien */ 2310236769Sobrien if (bottom->node == NULL) { 2311236769Sobrien bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); 2312236769Sobrien } 2313236769Sobrien 2314236769Sobrien for (src = bottom; src->parent != NULL; src = src->parent) { 2315236769Sobrien targ = src->parent; 2316236769Sobrien 2317236769Sobrien if (src->node->suffix) 2318236769Sobrien src->node->suffix->refCount--; 2319236769Sobrien src->node->suffix = src->suff; 2320236769Sobrien src->node->suffix->refCount++; 2321236769Sobrien 2322236769Sobrien if (targ->node == NULL) { 2323236769Sobrien targ->node = Targ_FindNode(targ->file, TARG_CREATE); 2324236769Sobrien } 2325236769Sobrien 2326236769Sobrien SuffApplyTransform(targ->node, src->node, 2327236769Sobrien targ->suff, src->suff); 2328236769Sobrien 2329236769Sobrien if (targ->node != gn) { 2330236769Sobrien /* 2331236769Sobrien * Finish off the dependency-search process for any nodes 2332236769Sobrien * between bottom and gn (no point in questing around the 2333236769Sobrien * filesystem for their implicit source when it's already 2334236769Sobrien * known). Note that the node can't have any sources that 2335236769Sobrien * need expanding, since SuffFindThem will stop on an existing 2336236769Sobrien * node, so all we need to do is set the standard and System V 2337236769Sobrien * variables. 2338236769Sobrien */ 2339236769Sobrien targ->node->type |= OP_DEPS_FOUND; 2340236769Sobrien 2341236769Sobrien Var_Set(PREFIX, targ->pref, targ->node, 0); 2342236769Sobrien 2343236769Sobrien Var_Set(TARGET, targ->node->name, targ->node, 0); 2344236769Sobrien } 2345236769Sobrien } 2346236769Sobrien 2347236769Sobrien if (gn->suffix) 2348236769Sobrien gn->suffix->refCount--; 2349236769Sobrien gn->suffix = src->suff; 2350236769Sobrien gn->suffix->refCount++; 2351236769Sobrien 2352236769Sobrien /* 2353236769Sobrien * Nuke the transformation path and the Src structures left over in the 2354236769Sobrien * two lists. 2355236769Sobrien */ 2356236769Sobriensfnd_return: 2357236769Sobrien if (bottom) 2358236769Sobrien if (Lst_Member(slst, bottom) == NULL) 2359236769Sobrien Lst_AtEnd(slst, bottom); 2360236769Sobrien 2361236769Sobrien while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs)) 2362236769Sobrien continue; 2363236769Sobrien 2364236769Sobrien Lst_Concat(slst, srcs, LST_CONCLINK); 2365236769Sobrien Lst_Concat(slst, targs, LST_CONCLINK); 2366236769Sobrien} 2367236769Sobrien 2368236769Sobrien 2369236769Sobrien/*- 2370236769Sobrien *----------------------------------------------------------------------- 2371236769Sobrien * Suff_FindDeps -- 2372236769Sobrien * Find implicit sources for the target described by the graph node 2373236769Sobrien * gn 2374236769Sobrien * 2375236769Sobrien * Results: 2376236769Sobrien * Nothing. 2377236769Sobrien * 2378236769Sobrien * Side Effects: 2379236769Sobrien * Nodes are added to the graph below the passed-in node. The nodes 2380236769Sobrien * are marked to have their IMPSRC variable filled in. The 2381236769Sobrien * PREFIX variable is set for the given node and all its 2382236769Sobrien * implied children. 2383236769Sobrien * 2384236769Sobrien * Notes: 2385236769Sobrien * The path found by this target is the shortest path in the 2386236769Sobrien * transformation graph, which may pass through non-existent targets, 2387236769Sobrien * to an existing target. The search continues on all paths from the 2388236769Sobrien * root suffix until a file is found. I.e. if there's a path 2389236769Sobrien * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but 2390236769Sobrien * the .c and .l files don't, the search will branch out in 2391236769Sobrien * all directions from .o and again from all the nodes on the 2392236769Sobrien * next level until the .l,v node is encountered. 2393236769Sobrien * 2394236769Sobrien *----------------------------------------------------------------------- 2395236769Sobrien */ 2396236769Sobrien 2397236769Sobrienvoid 2398236769SobrienSuff_FindDeps(GNode *gn) 2399236769Sobrien{ 2400236769Sobrien 2401236769Sobrien SuffFindDeps(gn, srclist); 2402236769Sobrien while (SuffRemoveSrc(srclist)) 2403236769Sobrien continue; 2404236769Sobrien} 2405236769Sobrien 2406236769Sobrien 2407236769Sobrien/* 2408236769Sobrien * Input: 2409236769Sobrien * gn node we're dealing with 2410236769Sobrien * 2411236769Sobrien */ 2412236769Sobrienstatic void 2413236769SobrienSuffFindDeps(GNode *gn, Lst slst) 2414236769Sobrien{ 2415236769Sobrien if (gn->type & OP_DEPS_FOUND) { 2416236769Sobrien /* 2417236769Sobrien * If dependencies already found, no need to do it again... 2418236769Sobrien */ 2419236769Sobrien return; 2420236769Sobrien } else { 2421236769Sobrien gn->type |= OP_DEPS_FOUND; 2422236769Sobrien } 2423236769Sobrien /* 2424236769Sobrien * Make sure we have these set, may get revised below. 2425236769Sobrien */ 2426236769Sobrien Var_Set(TARGET, gn->path ? gn->path : gn->name, gn, 0); 2427236769Sobrien Var_Set(PREFIX, gn->name, gn, 0); 2428250773Ssjg 2429236769Sobrien if (DEBUG(SUFF)) { 2430236769Sobrien fprintf(debug_file, "SuffFindDeps (%s)\n", gn->name); 2431236769Sobrien } 2432236769Sobrien 2433236769Sobrien if (gn->type & OP_ARCHV) { 2434236769Sobrien SuffFindArchiveDeps(gn, slst); 2435236769Sobrien } else if (gn->type & OP_LIB) { 2436236769Sobrien /* 2437236769Sobrien * If the node is a library, it is the arch module's job to find it 2438236769Sobrien * and set the TARGET variable accordingly. We merely provide the 2439236769Sobrien * search path, assuming all libraries end in ".a" (if the suffix 2440236769Sobrien * hasn't been defined, there's nothing we can do for it, so we just 2441236769Sobrien * set the TARGET variable to the node's name in order to give it a 2442236769Sobrien * value). 2443236769Sobrien */ 2444236769Sobrien LstNode ln; 2445236769Sobrien Suff *s; 2446236769Sobrien 2447236769Sobrien ln = Lst_Find(sufflist, LIBSUFF, SuffSuffHasNameP); 2448236769Sobrien if (gn->suffix) 2449236769Sobrien gn->suffix->refCount--; 2450236769Sobrien if (ln != NULL) { 2451236769Sobrien gn->suffix = s = (Suff *)Lst_Datum(ln); 2452236769Sobrien gn->suffix->refCount++; 2453236769Sobrien Arch_FindLib(gn, s->searchPath); 2454236769Sobrien } else { 2455236769Sobrien gn->suffix = NULL; 2456236769Sobrien Var_Set(TARGET, gn->name, gn, 0); 2457236769Sobrien } 2458236769Sobrien /* 2459236769Sobrien * Because a library (-lfoo) target doesn't follow the standard 2460236769Sobrien * filesystem conventions, we don't set the regular variables for 2461236769Sobrien * the thing. .PREFIX is simply made empty... 2462236769Sobrien */ 2463236769Sobrien Var_Set(PREFIX, "", gn, 0); 2464236769Sobrien } else { 2465236769Sobrien SuffFindNormalDeps(gn, slst); 2466236769Sobrien } 2467236769Sobrien} 2468236769Sobrien 2469236769Sobrien/*- 2470236769Sobrien *----------------------------------------------------------------------- 2471236769Sobrien * Suff_SetNull -- 2472236769Sobrien * Define which suffix is the null suffix. 2473236769Sobrien * 2474236769Sobrien * Input: 2475236769Sobrien * name Name of null suffix 2476236769Sobrien * 2477236769Sobrien * Results: 2478236769Sobrien * None. 2479236769Sobrien * 2480236769Sobrien * Side Effects: 2481236769Sobrien * 'suffNull' is altered. 2482236769Sobrien * 2483236769Sobrien * Notes: 2484236769Sobrien * Need to handle the changing of the null suffix gracefully so the 2485236769Sobrien * old transformation rules don't just go away. 2486236769Sobrien * 2487236769Sobrien *----------------------------------------------------------------------- 2488236769Sobrien */ 2489236769Sobrienvoid 2490236769SobrienSuff_SetNull(char *name) 2491236769Sobrien{ 2492236769Sobrien Suff *s; 2493236769Sobrien LstNode ln; 2494236769Sobrien 2495236769Sobrien ln = Lst_Find(sufflist, name, SuffSuffHasNameP); 2496236769Sobrien if (ln != NULL) { 2497236769Sobrien s = (Suff *)Lst_Datum(ln); 2498236769Sobrien if (suffNull != NULL) { 2499236769Sobrien suffNull->flags &= ~SUFF_NULL; 2500236769Sobrien } 2501236769Sobrien s->flags |= SUFF_NULL; 2502236769Sobrien /* 2503236769Sobrien * XXX: Here's where the transformation mangling would take place 2504236769Sobrien */ 2505236769Sobrien suffNull = s; 2506236769Sobrien } else { 2507236769Sobrien Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", 2508236769Sobrien name); 2509236769Sobrien } 2510236769Sobrien} 2511236769Sobrien 2512236769Sobrien/*- 2513236769Sobrien *----------------------------------------------------------------------- 2514236769Sobrien * Suff_Init -- 2515236769Sobrien * Initialize suffixes module 2516236769Sobrien * 2517236769Sobrien * Results: 2518236769Sobrien * None 2519236769Sobrien * 2520236769Sobrien * Side Effects: 2521236769Sobrien * Many 2522236769Sobrien *----------------------------------------------------------------------- 2523236769Sobrien */ 2524236769Sobrienvoid 2525236769SobrienSuff_Init(void) 2526236769Sobrien{ 2527236769Sobrien sufflist = Lst_Init(FALSE); 2528236769Sobrien#ifdef CLEANUP 2529236769Sobrien suffClean = Lst_Init(FALSE); 2530236769Sobrien#endif 2531236769Sobrien srclist = Lst_Init(FALSE); 2532236769Sobrien transforms = Lst_Init(FALSE); 2533236769Sobrien 2534236769Sobrien sNum = 0; 2535236769Sobrien /* 2536236769Sobrien * Create null suffix for single-suffix rules (POSIX). The thing doesn't 2537236769Sobrien * actually go on the suffix list or everyone will think that's its 2538236769Sobrien * suffix. 2539236769Sobrien */ 2540236769Sobrien emptySuff = suffNull = bmake_malloc(sizeof(Suff)); 2541236769Sobrien 2542236769Sobrien suffNull->name = bmake_strdup(""); 2543236769Sobrien suffNull->nameLen = 0; 2544236769Sobrien suffNull->searchPath = Lst_Init(FALSE); 2545236769Sobrien Dir_Concat(suffNull->searchPath, dirSearchPath); 2546236769Sobrien suffNull->children = Lst_Init(FALSE); 2547236769Sobrien suffNull->parents = Lst_Init(FALSE); 2548236769Sobrien suffNull->ref = Lst_Init(FALSE); 2549236769Sobrien suffNull->sNum = sNum++; 2550236769Sobrien suffNull->flags = SUFF_NULL; 2551236769Sobrien suffNull->refCount = 1; 2552236769Sobrien 2553236769Sobrien} 2554236769Sobrien 2555236769Sobrien 2556236769Sobrien/*- 2557236769Sobrien *---------------------------------------------------------------------- 2558236769Sobrien * Suff_End -- 2559236769Sobrien * Cleanup the this module 2560236769Sobrien * 2561236769Sobrien * Results: 2562236769Sobrien * None 2563236769Sobrien * 2564236769Sobrien * Side Effects: 2565236769Sobrien * The memory is free'd. 2566236769Sobrien *---------------------------------------------------------------------- 2567236769Sobrien */ 2568236769Sobrien 2569236769Sobrienvoid 2570236769SobrienSuff_End(void) 2571236769Sobrien{ 2572236769Sobrien#ifdef CLEANUP 2573236769Sobrien Lst_Destroy(sufflist, SuffFree); 2574236769Sobrien Lst_Destroy(suffClean, SuffFree); 2575236769Sobrien if (suffNull) 2576236769Sobrien SuffFree(suffNull); 2577236769Sobrien Lst_Destroy(srclist, NULL); 2578236769Sobrien Lst_Destroy(transforms, NULL); 2579236769Sobrien#endif 2580236769Sobrien} 2581236769Sobrien 2582236769Sobrien 2583236769Sobrien/********************* DEBUGGING FUNCTIONS **********************/ 2584236769Sobrien 2585236769Sobrienstatic int SuffPrintName(void *s, void *dummy) 2586236769Sobrien{ 2587236769Sobrien fprintf(debug_file, "%s ", ((Suff *)s)->name); 2588236769Sobrien return (dummy ? 0 : 0); 2589236769Sobrien} 2590236769Sobrien 2591236769Sobrienstatic int 2592236769SobrienSuffPrintSuff(void *sp, void *dummy) 2593236769Sobrien{ 2594236769Sobrien Suff *s = (Suff *)sp; 2595236769Sobrien int flags; 2596236769Sobrien int flag; 2597236769Sobrien 2598236769Sobrien fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount); 2599236769Sobrien 2600236769Sobrien flags = s->flags; 2601236769Sobrien if (flags) { 2602236769Sobrien fputs(" (", debug_file); 2603236769Sobrien while (flags) { 2604236769Sobrien flag = 1 << (ffs(flags) - 1); 2605236769Sobrien flags &= ~flag; 2606236769Sobrien switch (flag) { 2607236769Sobrien case SUFF_NULL: 2608236769Sobrien fprintf(debug_file, "NULL"); 2609236769Sobrien break; 2610236769Sobrien case SUFF_INCLUDE: 2611236769Sobrien fprintf(debug_file, "INCLUDE"); 2612236769Sobrien break; 2613236769Sobrien case SUFF_LIBRARY: 2614236769Sobrien fprintf(debug_file, "LIBRARY"); 2615236769Sobrien break; 2616236769Sobrien } 2617236769Sobrien fputc(flags ? '|' : ')', debug_file); 2618236769Sobrien } 2619236769Sobrien } 2620236769Sobrien fputc('\n', debug_file); 2621236769Sobrien fprintf(debug_file, "#\tTo: "); 2622236769Sobrien Lst_ForEach(s->parents, SuffPrintName, NULL); 2623236769Sobrien fputc('\n', debug_file); 2624236769Sobrien fprintf(debug_file, "#\tFrom: "); 2625236769Sobrien Lst_ForEach(s->children, SuffPrintName, NULL); 2626236769Sobrien fputc('\n', debug_file); 2627236769Sobrien fprintf(debug_file, "#\tSearch Path: "); 2628236769Sobrien Dir_PrintPath(s->searchPath); 2629236769Sobrien fputc('\n', debug_file); 2630236769Sobrien return (dummy ? 0 : 0); 2631236769Sobrien} 2632236769Sobrien 2633236769Sobrienstatic int 2634236769SobrienSuffPrintTrans(void *tp, void *dummy) 2635236769Sobrien{ 2636236769Sobrien GNode *t = (GNode *)tp; 2637236769Sobrien 2638236769Sobrien fprintf(debug_file, "%-16s: ", t->name); 2639236769Sobrien Targ_PrintType(t->type); 2640236769Sobrien fputc('\n', debug_file); 2641236769Sobrien Lst_ForEach(t->commands, Targ_PrintCmd, NULL); 2642236769Sobrien fputc('\n', debug_file); 2643236769Sobrien return(dummy ? 0 : 0); 2644236769Sobrien} 2645236769Sobrien 2646236769Sobrienvoid 2647236769SobrienSuff_PrintAll(void) 2648236769Sobrien{ 2649236769Sobrien fprintf(debug_file, "#*** Suffixes:\n"); 2650236769Sobrien Lst_ForEach(sufflist, SuffPrintSuff, NULL); 2651236769Sobrien 2652236769Sobrien fprintf(debug_file, "#*** Transformations:\n"); 2653236769Sobrien Lst_ForEach(transforms, SuffPrintTrans, NULL); 2654236769Sobrien} 2655