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