1141104Sharti/*- 21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This code is derived from software contributed to Berkeley by 81590Srgrimes * Adam de Boor. 91590Srgrimes * 101590Srgrimes * Redistribution and use in source and binary forms, with or without 111590Srgrimes * modification, are permitted provided that the following conditions 121590Srgrimes * are met: 131590Srgrimes * 1. Redistributions of source code must retain the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer. 151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer in the 171590Srgrimes * documentation and/or other materials provided with the distribution. 181590Srgrimes * 3. All advertising materials mentioning features or use of this software 191590Srgrimes * must display the following acknowledgement: 201590Srgrimes * This product includes software developed by the University of 211590Srgrimes * California, Berkeley and its contributors. 221590Srgrimes * 4. Neither the name of the University nor the names of its contributors 231590Srgrimes * may be used to endorse or promote products derived from this software 241590Srgrimes * without specific prior written permission. 251590Srgrimes * 261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361590Srgrimes * SUCH DAMAGE. 3762833Swsanchez * 3862833Swsanchez * @(#)suff.c 8.4 (Berkeley) 3/21/94 391590Srgrimes */ 401590Srgrimes 4162833Swsanchez#include <sys/cdefs.h> 4294587Sobrien__FBSDID("$FreeBSD$"); 431590Srgrimes 441590Srgrimes/*- 451590Srgrimes * suff.c -- 461590Srgrimes * Functions to maintain suffix lists and find implicit dependents 471590Srgrimes * using suffix transformation rules 481590Srgrimes * 491590Srgrimes * Interface: 501590Srgrimes * Suff_Init Initialize all things to do with suffixes. 511590Srgrimes * 521590Srgrimes * Suff_DoPaths This function is used to make life easier 531590Srgrimes * when searching for a file according to its 541590Srgrimes * suffix. It takes the global search path, 551590Srgrimes * as defined using the .PATH: target, and appends 561590Srgrimes * its directories to the path of each of the 571590Srgrimes * defined suffixes, as specified using 581590Srgrimes * .PATH<suffix>: targets. In addition, all 591590Srgrimes * directories given for suffixes labeled as 601590Srgrimes * include files or libraries, using the .INCLUDES 611590Srgrimes * or .LIBS targets, are played with using 621590Srgrimes * Dir_MakeFlags to create the .INCLUDES and 631590Srgrimes * .LIBS global variables. 641590Srgrimes * 651590Srgrimes * Suff_ClearSuffixes Clear out all the suffixes and defined 661590Srgrimes * transformations. 671590Srgrimes * 681590Srgrimes * Suff_IsTransform Return TRUE if the passed string is the lhs 691590Srgrimes * of a transformation rule. 701590Srgrimes * 711590Srgrimes * Suff_AddSuffix Add the passed string as another known suffix. 721590Srgrimes * 731590Srgrimes * Suff_GetPath Return the search path for the given suffix. 741590Srgrimes * 751590Srgrimes * Suff_AddInclude Mark the given suffix as denoting an include 761590Srgrimes * file. 771590Srgrimes * 781590Srgrimes * Suff_AddLib Mark the given suffix as denoting a library. 791590Srgrimes * 801590Srgrimes * Suff_AddTransform Add another transformation to the suffix 811590Srgrimes * graph. Returns GNode suitable for framing, I 821590Srgrimes * mean, tacking commands, attributes, etc. on. 831590Srgrimes * 841590Srgrimes * Suff_SetNull Define the suffix to consider the suffix of 851590Srgrimes * any file that doesn't have a known one. 861590Srgrimes * 871590Srgrimes * Suff_FindDeps Find implicit sources for and the location of 881590Srgrimes * a target based on its suffix. Returns the 8969527Swill * bottom-most node added to the graph or NULL 901590Srgrimes * if the target had no implicit sources. 911590Srgrimes */ 921590Srgrimes 93144020Sharti#include <sys/queue.h> 94143807Sharti#include <assert.h> 95141104Sharti#include <string.h> 96141104Sharti#include <stdlib.h> 971590Srgrimes 98141104Sharti#include "arch.h" 99142457Sharti#include "buf.h" 100141104Sharti#include "config.h" 101141104Sharti#include "dir.h" 102141104Sharti#include "globals.h" 103141104Sharti#include "GNode.h" 104141104Sharti#include "lst.h" 105141104Sharti#include "make.h" 106141104Sharti#include "parse.h" 107141104Sharti#include "str.h" 108141104Sharti#include "suff.h" 109141104Sharti#include "targ.h" 110141104Sharti#include "util.h" 111141104Sharti#include "var.h" 112141104Sharti 113138916Sharti/* Lst of suffixes */ 114138916Shartistatic Lst sufflist = Lst_Initializer(sufflist); 1151590Srgrimes 116138916Sharti/* Lst of suffixes to be cleaned */ 117138916Shartistatic Lst suffClean = Lst_Initializer(suffClean); 118138916Sharti 119138916Sharti/* Lst of sources */ 120138916Shartistatic Lst srclist = Lst_Initializer(srclist); 121138916Sharti 122138916Sharti/* Lst of transformation rules */ 123138916Shartistatic Lst transforms = Lst_Initializer(transforms); 124138916Sharti 125143407Sharti/* Counter for assigning suffix numbers */ 126143407Shartistatic int sNum = 0; 1271590Srgrimes 1281590Srgrimes/* 1291590Srgrimes * Structure describing an individual suffix. 1301590Srgrimes */ 131143411Shartitypedef struct Suff { 132143407Sharti char *name; /* The suffix itself */ 133143407Sharti int nameLen; /* Length of the suffix */ 134143407Sharti short flags; /* Type of suffix */ 135143407Sharti#define SUFF_INCLUDE 0x01 /* One which is #include'd */ 136143407Sharti#define SUFF_LIBRARY 0x02 /* One which contains a library */ 137143407Sharti#define SUFF_NULL 0x04 /* The empty suffix */ 138144020Sharti struct Path searchPath; /* Path for files with this suffix */ 139143407Sharti int sNum; /* The suffix number */ 140143407Sharti int refCount; /* Reference count of list membership */ 141143407Sharti Lst parents; /* Suffixes we have a transformation to */ 142143407Sharti Lst children; /* Suffixes we have a transformation from */ 143143407Sharti Lst ref; /* List of lists this suffix is referenced */ 1441590Srgrimes} Suff; 1451590Srgrimes 1461590Srgrimes/* 1471590Srgrimes * Structure used in the search for implied sources. 1481590Srgrimes */ 149143411Shartitypedef struct Src { 150143407Sharti char *file; /* The file to look for */ 151143407Sharti char *pref; /* Prefix from which file was formed */ 152143407Sharti Suff *suff; /* The suffix on the file */ 153143411Sharti struct Src *parent; /* The Src for which this is a source */ 154143407Sharti GNode *node; /* The node describing the file */ 155143407Sharti int children; /* Count of existing children (so we don't free 1561590Srgrimes * this thing too early or never nuke it) */ 1575814Sjkh#ifdef DEBUG_SRC 158143407Sharti Lst cp; /* Debug; children list */ 1595814Sjkh#endif 1601590Srgrimes} Src; 1611590Srgrimes 162143407Sharti/* The NULL suffix for this run */ 163143407Shartistatic Suff *suffNull; 1641590Srgrimes 165143407Sharti/* The empty suffix required for POSIX single-suffix transformation rules */ 166143407Shartistatic Suff *emptySuff; 1671590Srgrimes 168138512Shartistatic void SuffFindDeps(GNode *, Lst *); 1691590Srgrimes 170141271Sharti 1711590Srgrimes/*- 1721590Srgrimes *----------------------------------------------------------------------- 1731590Srgrimes * SuffSuffIsSuffix -- 174143807Sharti * See if suff is a suffix of str. 1751590Srgrimes * 1761590Srgrimes * Results: 1771590Srgrimes * NULL if it ain't, pointer to character in str before suffix if 1781590Srgrimes * it is. 1791590Srgrimes * 1801590Srgrimes * Side Effects: 1811590Srgrimes * None 1821590Srgrimes *----------------------------------------------------------------------- 1831590Srgrimes */ 1841590Srgrimesstatic char * 185138561ShartiSuffSuffIsSuffix(const Suff *s, char *str) 1861590Srgrimes{ 187143407Sharti const char *p1; /* Pointer into suffix name */ 188143407Sharti char *p2; /* Pointer into string being examined */ 189143807Sharti size_t len; 1901590Srgrimes 191143807Sharti len = strlen(str); 192143407Sharti p1 = s->name + s->nameLen; 193143807Sharti p2 = str + len; 1941590Srgrimes 195143807Sharti while (p1 >= s->name && len > 0 && *p1 == *p2) { 196143407Sharti p1--; 197143407Sharti p2--; 198143807Sharti len--; 199143407Sharti } 2001590Srgrimes 201143407Sharti return (p1 == s->name - 1 ? p2 : NULL); 2021590Srgrimes} 2031590Srgrimes 2041590Srgrimes/*- 2051590Srgrimes *----------------------------------------------------------------------- 206143911Sharti * SuffSuffFind -- 207143911Sharti * Find a suffix given its name. 2081590Srgrimes * 2091590Srgrimes * Results: 210143911Sharti * The suffix or NULL. 2111590Srgrimes * 2121590Srgrimes * Side Effects: 2131590Srgrimes * None 2141590Srgrimes *----------------------------------------------------------------------- 2151590Srgrimes */ 216143911Shartistatic Suff * 217143911ShartiSuffSuffFind(const char *s) 2181590Srgrimes{ 219143911Sharti LstNode *ln; 220138232Sharti 221143911Sharti LST_FOREACH(ln, &sufflist) { 222143911Sharti if (strcmp(s, ((const Suff *)Lst_Datum(ln))->name) == 0) 223143911Sharti return (Lst_Datum(ln)); 224143911Sharti } 225143911Sharti return (NULL); 2261590Srgrimes} 2271590Srgrimes 2281590Srgrimes/*- 2291590Srgrimes *----------------------------------------------------------------------- 230143911Sharti * SuffTransFind 231143911Sharti * Find a transform. 2321590Srgrimes * 2331590Srgrimes * Results: 234143911Sharti * transform or NULL. 2351590Srgrimes * 2361590Srgrimes * Side Effects: 2371590Srgrimes * None 2381590Srgrimes *----------------------------------------------------------------------- 2391590Srgrimes */ 240143911Shartistatic GNode * 241143911ShartiSuffTransFind(const char *name) 2421590Srgrimes{ 243143911Sharti LstNode *ln; 244138232Sharti 245143911Sharti LST_FOREACH(ln, &transforms) { 246143911Sharti if (strcmp(name, ((const GNode *)Lst_Datum(ln))->name) == 0) 247143911Sharti return (Lst_Datum(ln)); 248138561Sharti } 249143911Sharti return (NULL); 2501590Srgrimes} 2511590Srgrimes 2521590Srgrimes /*********** Maintenance Functions ************/ 2535814Sjkh 254138972Sharti#if 0 255138972Sharti/* 256138972Sharti * Keep this function for now until it is clear why a .SUFFIXES: doesn't 257138972Sharti * actually delete the suffixes but just puts them on the suffClean list. 258138972Sharti */ 2591590Srgrimes/*- 2601590Srgrimes *----------------------------------------------------------------------- 2611590Srgrimes * SuffFree -- 2621590Srgrimes * Free up all memory associated with the given suffix structure. 2631590Srgrimes * 2641590Srgrimes * Results: 2651590Srgrimes * none 2661590Srgrimes * 2671590Srgrimes * Side Effects: 2681590Srgrimes * the suffix entry is detroyed 2691590Srgrimes *----------------------------------------------------------------------- 2701590Srgrimes */ 2711590Srgrimesstatic void 272138232ShartiSuffFree(void *sp) 2731590Srgrimes{ 274143407Sharti Suff *s = sp; 2755814Sjkh 276143407Sharti if (s == suffNull) 277143407Sharti suffNull = NULL; 2785814Sjkh 279143407Sharti if (s == emptySuff) 280143407Sharti emptySuff = NULL; 2815814Sjkh 282143407Sharti Lst_Destroy(&s->ref, NOFREE); 283143407Sharti Lst_Destroy(&s->children, NOFREE); 284143407Sharti Lst_Destroy(&s->parents, NOFREE); 285143407Sharti Lst_Destroy(&s->searchPath, Dir_Destroy); 2865814Sjkh 287143407Sharti free(s->name); 288143407Sharti free(s); 2891590Srgrimes} 290138972Sharti#endif 2911590Srgrimes 2921590Srgrimes/*- 2931590Srgrimes *----------------------------------------------------------------------- 2945814Sjkh * SuffRemove -- 2955814Sjkh * Remove the suffix into the list 2965814Sjkh * 2975814Sjkh * Results: 2985814Sjkh * None 2995814Sjkh * 3005814Sjkh * Side Effects: 30135464Sphk * The reference count for the suffix is decremented 3025814Sjkh *----------------------------------------------------------------------- 3035814Sjkh */ 3045814Sjkhstatic void 305138512ShartiSuffRemove(Lst *l, Suff *s) 3065814Sjkh{ 307143407Sharti LstNode *ln = Lst_Member(l, s); 308138264Sharti 309143407Sharti if (ln != NULL) { 310143407Sharti Lst_Remove(l, ln); 311143407Sharti s->refCount--; 312143407Sharti } 3135814Sjkh} 314138232Sharti 3155814Sjkh/*- 3165814Sjkh *----------------------------------------------------------------------- 3171590Srgrimes * SuffInsert -- 3181590Srgrimes * Insert the suffix into the list keeping the list ordered by suffix 3191590Srgrimes * numbers. 3201590Srgrimes * 3211590Srgrimes * Results: 3221590Srgrimes * None 3231590Srgrimes * 3241590Srgrimes * Side Effects: 3255814Sjkh * The reference count of the suffix is incremented 3261590Srgrimes *----------------------------------------------------------------------- 3271590Srgrimes */ 3281590Srgrimesstatic void 329138512ShartiSuffInsert(Lst *l, Suff *s) 3301590Srgrimes{ 331143407Sharti LstNode *ln; /* current element in l we're examining */ 332143407Sharti Suff *s2; /* the suffix descriptor in this element */ 3331590Srgrimes 334143407Sharti s2 = NULL; 335143407Sharti for (ln = Lst_First(l); ln != NULL; ln = Lst_Succ(ln)) { 336143407Sharti s2 = Lst_Datum(ln); 337143407Sharti if (s2->sNum >= s->sNum) 338143407Sharti break; 339143407Sharti } 340143407Sharti if (s2 == NULL) { 341143407Sharti DEBUGF(SUFF, ("inserting an empty list?...")); 342143407Sharti } 3431590Srgrimes 344143407Sharti DEBUGF(SUFF, ("inserting %s(%d)...", s->name, s->sNum)); 345143407Sharti if (ln == NULL) { 346143407Sharti DEBUGF(SUFF, ("at end of list\n")); 347143407Sharti Lst_AtEnd(l, s); 348143407Sharti s->refCount++; 349143407Sharti Lst_AtEnd(&s->ref, l); 350143407Sharti } else if (s2->sNum != s->sNum) { 351143407Sharti DEBUGF(SUFF, ("before %s(%d)\n", s2->name, s2->sNum)); 352143407Sharti Lst_Insert(l, ln, s); 353143407Sharti s->refCount++; 354143407Sharti Lst_AtEnd(&s->ref, l); 355143407Sharti } else { 356143407Sharti DEBUGF(SUFF, ("already there\n")); 357143407Sharti } 3581590Srgrimes} 3591590Srgrimes 3601590Srgrimes/*- 3611590Srgrimes *----------------------------------------------------------------------- 3621590Srgrimes * Suff_ClearSuffixes -- 3631590Srgrimes * This is gross. Nuke the list of suffixes but keep all transformation 3641590Srgrimes * rules around. The transformation graph is destroyed in this process, 3651590Srgrimes * but we leave the list of rules so when a new graph is formed the rules 3661590Srgrimes * will remain. 3671590Srgrimes * This function is called from the parse module when a 3681590Srgrimes * .SUFFIXES:\n line is encountered. 3691590Srgrimes * 3701590Srgrimes * Results: 3711590Srgrimes * none 3721590Srgrimes * 3731590Srgrimes * Side Effects: 3741590Srgrimes * the sufflist and its graph nodes are destroyed 3751590Srgrimes *----------------------------------------------------------------------- 3761590Srgrimes */ 3771590Srgrimesvoid 378138232ShartiSuff_ClearSuffixes(void) 3791590Srgrimes{ 380138232Sharti 381143407Sharti Lst_Concat(&suffClean, &sufflist, LST_CONCLINK); 382138916Sharti 383143407Sharti sNum = 1; 384143407Sharti suffNull = emptySuff; 385143407Sharti /* 386143407Sharti * Clear suffNull's children list (the other suffixes are built new, but 387143407Sharti * suffNull is used as is). 388143407Sharti * NOFREE is used because all suffixes are are on the suffClean list. 389143407Sharti * suffNull should not have parents. 390143407Sharti */ 391143407Sharti Lst_Destroy(&suffNull->children, NOFREE); 3921590Srgrimes} 3931590Srgrimes 3941590Srgrimes/*- 3951590Srgrimes *----------------------------------------------------------------------- 3961590Srgrimes * SuffParseTransform -- 3971590Srgrimes * Parse a transformation string to find its two component suffixes. 3981590Srgrimes * 3991590Srgrimes * Results: 4001590Srgrimes * TRUE if the string is a valid transformation and FALSE otherwise. 4011590Srgrimes * 4021590Srgrimes * Side Effects: 4031590Srgrimes * The passed pointers are overwritten. 4041590Srgrimes * 4051590Srgrimes *----------------------------------------------------------------------- 4061590Srgrimes */ 4071590Srgrimesstatic Boolean 408104696SjmallettSuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr) 4091590Srgrimes{ 410143407Sharti LstNode *srcLn; /* element in suffix list of trans source*/ 411143407Sharti Suff *src; /* Source of transformation */ 412143407Sharti char *str2; /* Extra pointer (maybe target suffix) */ 413143407Sharti LstNode *singleLn; /* element in suffix list of any suffix 414143407Sharti * that exactly matches str */ 415143407Sharti Suff *single = NULL; /* Source of possible transformation to 416143407Sharti * null suffix */ 4171590Srgrimes 418143407Sharti singleLn = NULL; 4198874Srgrimes 420143407Sharti /* 421143407Sharti * Loop looking first for a suffix that matches the start of the 422143407Sharti * string and then for one that exactly matches the rest of it. If 423143407Sharti * we can find two that meet these criteria, we've successfully 424143407Sharti * parsed the string. 425143407Sharti */ 426143911Sharti srcLn = Lst_First(&sufflist); 427143407Sharti for (;;) { 428143911Sharti /* advance to next possible suffix */ 429143911Sharti while (srcLn != NULL) { 430143911Sharti src = Lst_Datum(srcLn); 431143911Sharti if (strncmp(str, src->name, strlen(src->name)) == 0) 432143911Sharti break; 433143911Sharti srcLn = LST_NEXT(srcLn); 434143407Sharti } 435143911Sharti 436143407Sharti if (srcLn == NULL) { 437143407Sharti /* 438143407Sharti * Ran out of source suffixes -- no such rule 439143407Sharti */ 440143407Sharti if (singleLn != NULL) { 441143407Sharti /* 442143407Sharti * Not so fast Mr. Smith! There was a suffix 443143407Sharti * that encompassed the entire string, so we 444143407Sharti * assume it was a transformation to the null 445143407Sharti * suffix (thank you POSIX). We still prefer to 446143407Sharti * find a double rule over a singleton, hence we 447143407Sharti * leave this check until the end. 448143407Sharti * 449143407Sharti * XXX: Use emptySuff over suffNull? 450143407Sharti */ 451143407Sharti *srcPtr = single; 452143407Sharti *targPtr = suffNull; 453143407Sharti return (TRUE); 454143407Sharti } 455143407Sharti return (FALSE); 456143407Sharti } 457143407Sharti str2 = str + src->nameLen; 458143407Sharti if (*str2 == '\0') { 459143407Sharti single = src; 460143407Sharti singleLn = srcLn; 461143407Sharti } else { 462143911Sharti 463143911Sharti *targPtr = SuffSuffFind(str2); 464143911Sharti if (*targPtr != NULL) { 465143407Sharti *srcPtr = src; 466143407Sharti return (TRUE); 467143407Sharti } 468143407Sharti } 469143911Sharti /* next one */ 470143911Sharti srcLn = LST_NEXT(srcLn); 4711590Srgrimes } 4721590Srgrimes} 4731590Srgrimes 4741590Srgrimes/*- 4751590Srgrimes *----------------------------------------------------------------------- 4761590Srgrimes * Suff_IsTransform -- 4771590Srgrimes * Return TRUE if the given string is a transformation rule 4781590Srgrimes * 4791590Srgrimes * 4801590Srgrimes * Results: 4811590Srgrimes * TRUE if the string is a concatenation of two known suffixes. 4821590Srgrimes * FALSE otherwise 4831590Srgrimes * 4841590Srgrimes * Side Effects: 4851590Srgrimes * None 4861590Srgrimes *----------------------------------------------------------------------- 4871590Srgrimes */ 4881590SrgrimesBoolean 489138232ShartiSuff_IsTransform(char *str) 4901590Srgrimes{ 491143407Sharti Suff *src, *targ; 4921590Srgrimes 493143407Sharti return (SuffParseTransform(str, &src, &targ)); 4941590Srgrimes} 4951590Srgrimes 4961590Srgrimes/*- 4971590Srgrimes *----------------------------------------------------------------------- 4981590Srgrimes * Suff_AddTransform -- 4991590Srgrimes * Add the transformation rule described by the line to the 5001590Srgrimes * list of rules and place the transformation itself in the graph 5011590Srgrimes * 5021590Srgrimes * Results: 5031590Srgrimes * The node created for the transformation in the transforms list 5041590Srgrimes * 5051590Srgrimes * Side Effects: 5061590Srgrimes * The node is placed on the end of the transforms Lst and links are 5071590Srgrimes * made between the two suffixes mentioned in the target name 5081590Srgrimes *----------------------------------------------------------------------- 5091590Srgrimes */ 5101590SrgrimesGNode * 511138232ShartiSuff_AddTransform(char *line) 5121590Srgrimes{ 513143407Sharti GNode *gn; /* GNode of transformation rule */ 514143407Sharti Suff *s; /* source suffix */ 515143407Sharti Suff *t; /* target suffix */ 5161590Srgrimes 517187475Srdivacky s = t = NULL; /* silence gcc */ 518143911Sharti gn = SuffTransFind(line); 519143911Sharti if (gn == NULL) { 520143407Sharti /* 521143407Sharti * Make a new graph node for the transformation. 522143407Sharti * It will be filled in by the Parse module. 523143407Sharti */ 524143407Sharti gn = Targ_NewGN(line); 525143407Sharti Lst_AtEnd(&transforms, gn); 526143407Sharti } else { 527143407Sharti /* 528143407Sharti * New specification for transformation rule. Just nuke the 529143407Sharti * old list of commands so they can be filled in again... 530143407Sharti * We don't actually free the commands themselves, because a 531143407Sharti * given command can be attached to several different 532143407Sharti * transformations. 533143407Sharti */ 534143407Sharti Lst_Destroy(&gn->commands, NOFREE); 535143407Sharti Lst_Destroy(&gn->children, NOFREE); 536143407Sharti } 5371590Srgrimes 538143407Sharti gn->type = OP_TRANSFORM; 5391590Srgrimes 540143407Sharti SuffParseTransform(line, &s, &t); 5411590Srgrimes 542143407Sharti /* 543143407Sharti * link the two together in the proper relationship and order 544143407Sharti */ 545143407Sharti DEBUGF(SUFF, ("defining transformation from `%s' to `%s'\n", 546143407Sharti s->name, t->name)); 547143407Sharti SuffInsert(&t->children, s); 548143407Sharti SuffInsert(&s->parents, t); 5491590Srgrimes 550143407Sharti return (gn); 5511590Srgrimes} 5521590Srgrimes 5531590Srgrimes/*- 5541590Srgrimes *----------------------------------------------------------------------- 5551590Srgrimes * Suff_EndTransform -- 5561590Srgrimes * Handle the finish of a transformation definition, removing the 5571590Srgrimes * transformation from the graph if it has neither commands nor 558143372Sharti * sources. This is called from the Parse module at the end of 559143372Sharti * a dependency block. 5601590Srgrimes * 5611590Srgrimes * Side Effects: 5621590Srgrimes * If the node has no commands or children, the children and parents 5631590Srgrimes * lists of the affected suffices are altered. 5641590Srgrimes * 5651590Srgrimes *----------------------------------------------------------------------- 5661590Srgrimes */ 567143372Shartivoid 568143372ShartiSuff_EndTransform(const GNode *gn) 5691590Srgrimes{ 570143372Sharti Suff *s, *t; 5718874Srgrimes 572143372Sharti if (!Lst_IsEmpty(&gn->commands) || !Lst_IsEmpty(&gn->children)) { 573143372Sharti DEBUGF(SUFF, ("transformation %s complete\n", gn->name)); 574143372Sharti return; 575143372Sharti } 5761590Srgrimes 577143372Sharti /* 578143372Sharti * SuffParseTransform() may fail for special rules which are not 579143372Sharti * actual transformation rules (e.g., .DEFAULT). 580143372Sharti */ 581143372Sharti if (!SuffParseTransform(gn->name, &s, &t)) 582143372Sharti return; 5831590Srgrimes 584143372Sharti DEBUGF(SUFF, ("deleting transformation from `%s' to `%s'\n", 585143372Sharti s->name, t->name)); 5861590Srgrimes 587143372Sharti /* 588143372Sharti * Remove the source from the target's children list. We check 589143372Sharti * for a NULL return to handle a beanhead saying something like 590143372Sharti * .c.o .c.o: 591143372Sharti * 592143372Sharti * We'll be called twice when the next target is seen, but .c 593143372Sharti * and .o are only linked once... 594143372Sharti */ 595143372Sharti SuffRemove(&t->children, s); 5961590Srgrimes 597143372Sharti /* 598143372Sharti * Remove the target from the source's parents list 599143372Sharti */ 600143372Sharti SuffRemove(&s->parents, t); 6011590Srgrimes} 6021590Srgrimes 6031590Srgrimes/*- 6041590Srgrimes *----------------------------------------------------------------------- 6051590Srgrimes * SuffRebuildGraph -- 606143556Sharti * Called from Suff_AddSuffix via LST_FOREACH to search through the 6071590Srgrimes * list of existing transformation rules and rebuild the transformation 6081590Srgrimes * graph when it has been destroyed by Suff_ClearSuffixes. If the 6091590Srgrimes * given rule is a transformation involving this suffix and another, 6101590Srgrimes * existing suffix, the proper relationship is established between 6111590Srgrimes * the two. 6121590Srgrimes * 6131590Srgrimes * Side Effects: 6141590Srgrimes * The appropriate links will be made between this suffix and 6151590Srgrimes * others if transformation rules exist for it. 6161590Srgrimes * 6171590Srgrimes *----------------------------------------------------------------------- 6181590Srgrimes */ 619143556Shartistatic void 620143556ShartiSuffRebuildGraph(const GNode *transform, Suff *s) 6211590Srgrimes{ 622143407Sharti char *cp; 623143407Sharti Suff *s2 = NULL; 6241590Srgrimes 625143407Sharti /* 626143407Sharti * First see if it is a transformation from this suffix. 627143407Sharti */ 628143911Sharti if (strncmp(transform->name, s->name, strlen(s->name)) == 0) { 629143911Sharti cp = transform->name + strlen(s->name); 630143911Sharti 631143407Sharti if (cp[0] == '\0') /* null rule */ 632143407Sharti s2 = suffNull; 633143911Sharti else 634143911Sharti s2 = SuffSuffFind(cp); 635143407Sharti if (s2 != NULL) { 636143407Sharti /* 637143407Sharti * Found target. Link in and return, since it can't be 638143407Sharti * anything else. 639143407Sharti */ 640143407Sharti SuffInsert(&s2->children, s); 641143407Sharti SuffInsert(&s->parents, s2); 642143556Sharti return; 643143407Sharti } 64473970Stmm } 6451590Srgrimes 6461590Srgrimes /* 647143807Sharti * Not from, maybe to? 648143807Sharti */ 649143807Sharti cp = SuffSuffIsSuffix(s, transform->name); 650143407Sharti if (cp != NULL) { 651143407Sharti /* 652143407Sharti * Null-terminate the source suffix in order to find it. 653143407Sharti */ 654143407Sharti cp[1] = '\0'; 655143911Sharti s2 = SuffSuffFind(transform->name); 656143911Sharti 657143407Sharti /* 658143407Sharti * Replace the start of the target suffix 659143407Sharti */ 660143407Sharti cp[1] = s->name[0]; 661143911Sharti if (s2 != NULL) { 662143407Sharti /* 663143407Sharti * Found it -- establish the proper relationship 664143407Sharti */ 665143407Sharti SuffInsert(&s->children, s2); 666143407Sharti SuffInsert(&s2->parents, s); 667143407Sharti } 6681590Srgrimes } 6691590Srgrimes} 6701590Srgrimes 6711590Srgrimes/*- 6721590Srgrimes *----------------------------------------------------------------------- 6731590Srgrimes * Suff_AddSuffix -- 6741590Srgrimes * Add the suffix in string to the end of the list of known suffixes. 6751590Srgrimes * Should we restructure the suffix graph? Make doesn't... 6761590Srgrimes * 6771590Srgrimes * Results: 6781590Srgrimes * None 6791590Srgrimes * 6801590Srgrimes * Side Effects: 6811590Srgrimes * A GNode is created for the suffix and a Suff structure is created and 6821590Srgrimes * added to the suffixes list unless the suffix was already known. 6831590Srgrimes *----------------------------------------------------------------------- 6841590Srgrimes */ 6851590Srgrimesvoid 686138232ShartiSuff_AddSuffix(char *str) 6871590Srgrimes{ 688143407Sharti Suff *s; /* new suffix descriptor */ 689143407Sharti LstNode *ln; 6901590Srgrimes 691143911Sharti if (SuffSuffFind(str) != NULL) 692143556Sharti /* 693143556Sharti * Already known 694143556Sharti */ 695143556Sharti return; 6961590Srgrimes 697143556Sharti s = emalloc(sizeof(Suff)); 6981590Srgrimes 699143556Sharti s->name = estrdup(str); 700143556Sharti s->nameLen = strlen(s->name); 701144020Sharti TAILQ_INIT(&s->searchPath); 702143556Sharti Lst_Init(&s->children); 703143556Sharti Lst_Init(&s->parents); 704143556Sharti Lst_Init(&s->ref); 705143556Sharti s->sNum = sNum++; 706143556Sharti s->flags = 0; 707143556Sharti s->refCount = 0; 708138264Sharti 709143556Sharti Lst_AtEnd(&sufflist, s); 710143556Sharti 711143556Sharti /* 712143556Sharti * Look for any existing transformations from or to this suffix. 713143556Sharti * XXX: Only do this after a Suff_ClearSuffixes? 714143556Sharti */ 715143556Sharti LST_FOREACH(ln, &transforms) 716143556Sharti SuffRebuildGraph(Lst_Datum(ln), s); 7171590Srgrimes} 7181590Srgrimes 7191590Srgrimes/*- 7201590Srgrimes *----------------------------------------------------------------------- 7211590Srgrimes * Suff_GetPath -- 7221590Srgrimes * Return the search path for the given suffix, if it's defined. 7231590Srgrimes * 7241590Srgrimes * Results: 72569527Swill * The searchPath for the desired suffix or NULL if the suffix isn't 7261590Srgrimes * defined. 7271590Srgrimes * 7281590Srgrimes * Side Effects: 7291590Srgrimes * None 7301590Srgrimes *----------------------------------------------------------------------- 7311590Srgrimes */ 732144020Shartistruct Path * 733138232ShartiSuff_GetPath(char *sname) 7341590Srgrimes{ 735143407Sharti Suff *s; 7361590Srgrimes 737143911Sharti s = SuffSuffFind(sname); 738143911Sharti if (s == NULL) 739143407Sharti return (NULL); 740143911Sharti return (&s->searchPath); 7411590Srgrimes} 7421590Srgrimes 7431590Srgrimes/*- 7441590Srgrimes *----------------------------------------------------------------------- 7451590Srgrimes * Suff_DoPaths -- 7461590Srgrimes * Extend the search paths for all suffixes to include the default 7471590Srgrimes * search path. 7481590Srgrimes * 7491590Srgrimes * Results: 7501590Srgrimes * None. 7511590Srgrimes * 7521590Srgrimes * Side Effects: 7531590Srgrimes * The searchPath field of all the suffixes is extended by the 7541590Srgrimes * directories in dirSearchPath. If paths were specified for the 7551590Srgrimes * ".h" suffix, the directories are stuffed into a global variable 75672645Sasmodai * called ".INCLUDES" with each directory preceded by a -I. The same 7571590Srgrimes * is done for the ".a" suffix, except the variable is called 7581590Srgrimes * ".LIBS" and the flag is -L. 7591590Srgrimes *----------------------------------------------------------------------- 7601590Srgrimes */ 7611590Srgrimesvoid 762104696SjmallettSuff_DoPaths(void) 7631590Srgrimes{ 764143407Sharti Suff *s; 765143407Sharti LstNode *ln; 766143407Sharti char *ptr; 767144020Sharti struct Path inIncludes; /* Cumulative .INCLUDES path */ 768144020Sharti struct Path inLibs; /* Cumulative .LIBS path */ 7691590Srgrimes 770144020Sharti TAILQ_INIT(&inIncludes); 771144020Sharti TAILQ_INIT(&inLibs); 7721590Srgrimes 773143407Sharti for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Succ(ln)) { 774143407Sharti s = Lst_Datum(ln); 7751590Srgrimes#ifdef INCLUDES 776144020Sharti if (s->flags & SUFF_INCLUDE) { 777144020Sharti Path_Concat(&inIncludes, &s->searchPath); 778144020Sharti } 7791590Srgrimes#endif /* INCLUDES */ 7801590Srgrimes#ifdef LIBRARIES 781144020Sharti if (s->flags & SUFF_LIBRARY) { 782144020Sharti Path_Concat(&inLibs, &s->searchPath); 783144020Sharti } 7841590Srgrimes#endif /* LIBRARIES */ 785144020Sharti Path_Concat(&s->searchPath, &dirSearchPath); 7861590Srgrimes } 7871590Srgrimes 788144020Sharti ptr = Path_MakeFlags("-I", &inIncludes); 789186558Sobrien Var_SetGlobal(".INCLUDES", ptr); 790143407Sharti free(ptr); 791144020Sharti 792144020Sharti ptr = Path_MakeFlags("-L", &inLibs); 793186558Sobrien Var_SetGlobal(".LIBS", ptr); 794143407Sharti free(ptr); 7951590Srgrimes 796144020Sharti Path_Clear(&inIncludes); 797144020Sharti Path_Clear(&inLibs); 7981590Srgrimes} 7991590Srgrimes 8001590Srgrimes/*- 8011590Srgrimes *----------------------------------------------------------------------- 8021590Srgrimes * Suff_AddInclude -- 8031590Srgrimes * Add the given suffix as a type of file which gets included. 8041590Srgrimes * Called from the parse module when a .INCLUDES line is parsed. 8051590Srgrimes * The suffix must have already been defined. 8061590Srgrimes * 8071590Srgrimes * Results: 8081590Srgrimes * None. 8091590Srgrimes * 8101590Srgrimes * Side Effects: 8111590Srgrimes * The SUFF_INCLUDE bit is set in the suffix's flags field 8121590Srgrimes * 8131590Srgrimes *----------------------------------------------------------------------- 8141590Srgrimes */ 8151590Srgrimesvoid 816138232ShartiSuff_AddInclude(char *sname) 8171590Srgrimes{ 818143407Sharti Suff *s; 8191590Srgrimes 820143911Sharti if ((s = SuffSuffFind(sname)) != NULL) 821143407Sharti s->flags |= SUFF_INCLUDE; 8221590Srgrimes} 8231590Srgrimes 8241590Srgrimes/*- 8251590Srgrimes *----------------------------------------------------------------------- 8261590Srgrimes * Suff_AddLib -- 8271590Srgrimes * Add the given suffix as a type of file which is a library. 8281590Srgrimes * Called from the parse module when parsing a .LIBS line. The 8291590Srgrimes * suffix must have been defined via .SUFFIXES before this is 8301590Srgrimes * called. 8311590Srgrimes * 8321590Srgrimes * Results: 8331590Srgrimes * None. 8341590Srgrimes * 8351590Srgrimes * Side Effects: 8361590Srgrimes * The SUFF_LIBRARY bit is set in the suffix's flags field 8371590Srgrimes * 8381590Srgrimes *----------------------------------------------------------------------- 8391590Srgrimes */ 8401590Srgrimesvoid 841138232ShartiSuff_AddLib(char *sname) 8421590Srgrimes{ 843143407Sharti Suff *s; 8441590Srgrimes 845143911Sharti if ((s = SuffSuffFind(sname)) != NULL) 846143407Sharti s->flags |= SUFF_LIBRARY; 8471590Srgrimes} 8481590Srgrimes 849143567Sharti/* 850143567Sharti * Create a new Src structure 851143567Sharti */ 852143567Shartistatic Src * 853143567ShartiSuffSrcCreate(char *file, char *prefix, Suff *suff, Src *parent, GNode *node) 854143567Sharti{ 855143567Sharti Src *s; 856143567Sharti 857143567Sharti s = emalloc(sizeof(*s)); 858143567Sharti s->file = file; 859143567Sharti s->pref = prefix; 860143567Sharti s->suff = suff; 861143567Sharti s->parent = parent; 862143567Sharti s->node = node; 863143567Sharti s->children = 0; 864143567Sharti 865143567Sharti#ifdef DEBUG_SRC 866143567Sharti Lst_Init(&s->cp); 867143567Sharti#endif 868143567Sharti 869143567Sharti return (s); 870143567Sharti} 871143567Sharti 8721590Srgrimes /********** Implicit Source Search Functions *********/ 8731590Srgrimes 8741590Srgrimes/*- 8751590Srgrimes *----------------------------------------------------------------------- 876143600Sharti * SuffAddLevel -- 877143600Sharti * Add all the children of targ as Src structures to the given list: 8781590Srgrimes * Add a suffix as a Src structure to the given list with its parent 8791590Srgrimes * being the given Src structure. If the suffix is the null suffix, 8801590Srgrimes * the prefix is used unaltered as the file name in the Src structure. 8811590Srgrimes * 8821590Srgrimes * Results: 883143600Sharti * None 8841590Srgrimes * 8851590Srgrimes * Side Effects: 886143600Sharti * Lots of structures are created and added to the list 8871590Srgrimes *----------------------------------------------------------------------- 8881590Srgrimes */ 889143600Shartistatic void 890143600ShartiSuffAddLevel(Lst *l, Src *targ) 8911590Srgrimes{ 892143600Sharti LstNode *ln; 893143600Sharti Suff *suff; 894143600Sharti Src *s2; 895143556Sharti#ifdef DEBUG_SRC 896143600Sharti const LstNode *ln1; 897143556Sharti#endif 8981590Srgrimes 899143600Sharti LST_FOREACH(ln, &targ->suff->children) { 900143600Sharti suff = Lst_Datum(ln); 9018874Srgrimes 902143600Sharti if ((suff->flags & SUFF_NULL) && *suff->name != '\0') { 903143600Sharti /* 904143600Sharti * If the suffix has been marked as the NULL suffix, 905143600Sharti * also create a Src structure for a file with no suffix 906143600Sharti * attached. Two birds, and all that... 907143600Sharti */ 908143600Sharti s2 = SuffSrcCreate(estrdup(targ->pref), targ->pref, 909143600Sharti suff, targ, NULL); 910143600Sharti suff->refCount++; 911143600Sharti targ->children += 1; 912143600Sharti Lst_AtEnd(l, s2); 913143600Sharti#ifdef DEBUG_SRC 914143600Sharti Lst_AtEnd(&targ->cp, s2); 915143600Sharti printf("1 add %p %p to %p:", targ, s2, l); 916143600Sharti LST_FOREACH(ln1, l) 917143600Sharti printf("%p ", (const void *)Lst_Datum(ln1)); 918143600Sharti printf("\n"); 919143600Sharti#endif 920143600Sharti } 921143600Sharti s2 = SuffSrcCreate(str_concat(targ->pref, suff->name, 0), 922143600Sharti targ->pref, suff, targ, NULL); 923143600Sharti suff->refCount++; 924143407Sharti targ->children += 1; 925143600Sharti Lst_AtEnd(l, s2); 926143407Sharti#ifdef DEBUG_SRC 927143407Sharti Lst_AtEnd(&targ->cp, s2); 928143600Sharti printf("2 add %p %p to %p:", targ, s2, l); 929143600Sharti LST_FOREACH(ln1, l) 930143600Sharti printf("%p ", (const void *)Lst_Datum(ln1)); 931143407Sharti printf("\n"); 932143407Sharti#endif 933143407Sharti } 9341590Srgrimes} 9351590Srgrimes 9361590Srgrimes/*- 9371590Srgrimes *---------------------------------------------------------------------- 9385814Sjkh * SuffRemoveSrc -- 9395814Sjkh * Free all src structures in list that don't have a reference count 940138564Sharti * XXX this actually frees only the first of these. 9411590Srgrimes * 9421590Srgrimes * Results: 943108470Sschweikh * True if a src was removed 9441590Srgrimes * 9451590Srgrimes * Side Effects: 9461590Srgrimes * The memory is free'd. 9471590Srgrimes *---------------------------------------------------------------------- 9481590Srgrimes */ 9495814Sjkhstatic int 950138512ShartiSuffRemoveSrc(Lst *l) 9511590Srgrimes{ 952143407Sharti LstNode *ln, *ln1; 953143407Sharti Src *s; 954143407Sharti int t = 0; 9555814Sjkh 9565814Sjkh#ifdef DEBUG_SRC 957143407Sharti printf("cleaning %lx: ", (unsigned long) l); 958143556Sharti LST_FOREACH(ln, l) 959143556Sharti printf("%p ", (const void *)Lst_Datum(ln)); 960143407Sharti printf("\n"); 9615814Sjkh#endif 9625814Sjkh 963143407Sharti for (ln = Lst_First(l); ln != NULL; ln = ln1) { 964143407Sharti ln1 = Lst_Succ(ln); 9655814Sjkh 966143407Sharti s = (Src *)Lst_Datum(ln); 967143407Sharti if (s->children == 0) { 968143407Sharti free(s->file); 969143407Sharti if (!s->parent) 970143407Sharti free(s->pref); 971143407Sharti else { 9725814Sjkh#ifdef DEBUG_SRC 973143407Sharti LstNode *ln = Lst_Member(&s->parent->cp, s); 974143407Sharti if (ln != NULL) 975143407Sharti Lst_Remove(&s->parent->cp, ln); 9765814Sjkh#endif 977143407Sharti --s->parent->children; 978143407Sharti } 9795814Sjkh#ifdef DEBUG_SRC 980143407Sharti printf("free: [l=%p] p=%p %d\n", l, s, s->children); 981143407Sharti Lst_Destroy(&s->cp, NOFREE); 9825814Sjkh#endif 983143407Sharti Lst_Remove(l, ln); 984143407Sharti free(s); 985143407Sharti t |= 1; 986143407Sharti return (TRUE); 987143407Sharti } 9885814Sjkh#ifdef DEBUG_SRC 989143407Sharti else { 990143556Sharti const LstNode *tln; 991143556Sharti 992143407Sharti printf("keep: [l=%p] p=%p %d: ", l, s, s->children); 993143556Sharti LST_FOREACH(tln, &s->cp) 994143556Sharti printf("%p ", (const void *)Lst_Datum(tln)); 995143407Sharti printf("\n"); 996143407Sharti } 997143407Sharti#endif 9985814Sjkh } 9995814Sjkh 1000143407Sharti return (t); 10011590Srgrimes} 10021590Srgrimes 10031590Srgrimes/*- 10041590Srgrimes *----------------------------------------------------------------------- 10051590Srgrimes * SuffFindThem -- 10061590Srgrimes * Find the first existing file/target in the list srcs 10071590Srgrimes * 10081590Srgrimes * Results: 10091590Srgrimes * The lowest structure in the chain of transformations 10101590Srgrimes * 10111590Srgrimes * Side Effects: 10121590Srgrimes * None 10131590Srgrimes *----------------------------------------------------------------------- 10141590Srgrimes */ 10151590Srgrimesstatic Src * 1016138512ShartiSuffFindThem(Lst *srcs, Lst *slst) 10171590Srgrimes{ 1018143407Sharti Src *s; /* current Src */ 1019143407Sharti Src *rs; /* returned Src */ 1020143407Sharti char *ptr; 10211590Srgrimes 1022143407Sharti rs = NULL; 10231590Srgrimes 1024143407Sharti while (!Lst_IsEmpty (srcs)) { 1025143407Sharti s = Lst_DeQueue(srcs); 10261590Srgrimes 1027143407Sharti DEBUGF(SUFF, ("\ttrying %s...", s->file)); 10285814Sjkh 1029143407Sharti /* 1030143407Sharti * A file is considered to exist if either a node exists in the 1031143407Sharti * graph for it or the file actually exists. 1032143407Sharti */ 1033143407Sharti if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { 10345814Sjkh#ifdef DEBUG_SRC 1035143407Sharti printf("remove %p from %p\n", s, srcs); 10365814Sjkh#endif 1037143407Sharti rs = s; 1038143407Sharti break; 1039143407Sharti } 10405814Sjkh 1041144020Sharti if ((ptr = Path_FindFile(s->file, 1042143407Sharti &s->suff->searchPath)) != NULL) { 1043143407Sharti rs = s; 10445814Sjkh#ifdef DEBUG_SRC 1045143407Sharti printf("remove %p from %p\n", s, srcs); 10465814Sjkh#endif 1047143407Sharti free(ptr); 1048143407Sharti break; 1049143407Sharti } 10505814Sjkh 1051143407Sharti DEBUGF(SUFF, ("not there\n")); 10525814Sjkh 1053143407Sharti SuffAddLevel(srcs, s); 1054143407Sharti Lst_AtEnd(slst, s); 1055143407Sharti } 10565814Sjkh 1057143407Sharti if (rs) { 1058143407Sharti DEBUGF(SUFF, ("got it\n")); 1059143407Sharti } 1060143407Sharti return (rs); 10611590Srgrimes} 10621590Srgrimes 10631590Srgrimes/*- 10641590Srgrimes *----------------------------------------------------------------------- 10651590Srgrimes * SuffFindCmds -- 10661590Srgrimes * See if any of the children of the target in the Src structure is 10671590Srgrimes * one from which the target can be transformed. If there is one, 10681590Srgrimes * a Src structure is put together for it and returned. 10691590Srgrimes * 10701590Srgrimes * Results: 107169527Swill * The Src structure of the "winning" child, or NULL if no such beast. 10721590Srgrimes * 10731590Srgrimes * Side Effects: 10741590Srgrimes * A Src structure may be allocated. 10751590Srgrimes * 10761590Srgrimes *----------------------------------------------------------------------- 10771590Srgrimes */ 10781590Srgrimesstatic Src * 1079141270ShartiSuffFindCmds(Src *targ, Lst *slst) 10801590Srgrimes{ 1081143407Sharti LstNode *ln; /* General-purpose list node */ 1082143407Sharti GNode *t; /* Target GNode */ 1083143407Sharti GNode *s; /* Source GNode */ 1084143407Sharti int prefLen;/* The length of the defined prefix */ 1085143407Sharti Suff *suff; /* Suffix on matching beastie */ 1086143407Sharti Src *ret; /* Return value */ 1087143407Sharti char *cp; 10881590Srgrimes 1089143407Sharti t = targ->node; 1090143407Sharti prefLen = strlen(targ->pref); 10911590Srgrimes 1092143407Sharti for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Succ(ln)) { 1093143407Sharti s = Lst_Datum(ln); 10941590Srgrimes 1095143407Sharti cp = strrchr(s->name, '/'); 1096143407Sharti if (cp == NULL) { 1097143407Sharti cp = s->name; 1098143407Sharti } else { 1099143407Sharti cp++; 1100143407Sharti } 1101143407Sharti if (strncmp(cp, targ->pref, prefLen) == 0) { 1102143407Sharti /* 1103143407Sharti * The node matches the prefix ok, see if it has 1104143911Sharti * a known suffix. 1105143407Sharti */ 1106143911Sharti suff = SuffSuffFind(&cp[prefLen]); 1107143911Sharti if (suff != NULL) { 1108143407Sharti /* 1109143407Sharti * It even has a known suffix, see if there's 1110143407Sharti * a transformation defined between the node's 1111143407Sharti * suffix and the target's suffix. 1112143407Sharti * 1113143407Sharti * XXX: Handle multi-stage transformations 1114143407Sharti * here, too. 1115143407Sharti */ 1116143407Sharti if (Lst_Member(&suff->parents, 1117143407Sharti targ->suff) != NULL) { 1118143407Sharti /* 1119143407Sharti * Hot Damn! Create a new Src structure 1120143407Sharti * to describe this transformation 1121143407Sharti * (making sure to duplicate the 1122143407Sharti * source node's name so Suff_FindDeps 1123143407Sharti * can free it again (ick)), and return 1124143407Sharti * the new structure. 1125143407Sharti */ 1126143567Sharti ret = SuffSrcCreate(estrdup(s->name), 1127143567Sharti targ->pref, suff, targ, s); 1128143407Sharti suff->refCount++; 1129143407Sharti targ->children += 1; 11305814Sjkh#ifdef DEBUG_SRC 1131143407Sharti printf("3 add %p %p\n", &targ, ret); 1132143407Sharti Lst_AtEnd(&targ->cp, ret); 11335814Sjkh#endif 1134143407Sharti Lst_AtEnd(slst, ret); 1135143407Sharti DEBUGF(SUFF, ("\tusing existing source " 1136143407Sharti "%s\n", s->name)); 1137143407Sharti return (ret); 1138143407Sharti } 1139143407Sharti } 11401590Srgrimes } 11411590Srgrimes } 1142143407Sharti return (NULL); 11431590Srgrimes} 11441590Srgrimes 11451590Srgrimes/*- 1146143327Sharti * The child node contains variable references. Expand them and return 1147143327Sharti * a list of expansions. 11481590Srgrimes */ 1149143327Shartistatic void 1150143327ShartiSuffExpandVariables(GNode *parent, GNode *child, Lst *members) 11511590Srgrimes{ 1152143327Sharti Buffer *buf; 1153143327Sharti char *cp; 1154143327Sharti char *start; 11551590Srgrimes 1156143327Sharti Lst_Init(members); 11578874Srgrimes 1158143327Sharti DEBUGF(SUFF, ("Expanding \"%s\"...", child->name)); 1159146027Sharti buf = Var_Subst(child->name, parent, TRUE); 1160143959Sharti cp = Buf_Data(buf); 1161143327Sharti 1162143327Sharti if (child->type & OP_ARCHV) { 1163143327Sharti /* 1164143327Sharti * Node was an archive(member) target, so we 1165143327Sharti * want to call on the Arch module to find the 1166143327Sharti * nodes for us, expanding variables in the 1167143327Sharti * parent's context. 1168143327Sharti */ 1169143327Sharti Arch_ParseArchive(&cp, members, parent); 1170143327Sharti Buf_Destroy(buf, TRUE); 1171143327Sharti return; 1172143327Sharti } 1173143297Sharti /* 1174143327Sharti * Break the result into a vector of strings whose nodes we can find, 1175143327Sharti * then add those nodes to the members list. Unfortunately, we can't use 1176143327Sharti * brk_string b/c it doesn't understand about variable specifications 1177143327Sharti * with spaces in them... XXX 1178143297Sharti */ 1179143327Sharti for (start = cp; *start == ' ' || *start == '\t'; start++) 1180143327Sharti ; 1181143312Sharti 1182143327Sharti for (cp = start; *cp != '\0'; cp++) { 1183143327Sharti if (*cp == ' ' || *cp == '\t') { 1184143327Sharti /* 1185143327Sharti * White-space -- terminate element, find the node, 1186143327Sharti * add it, skip any further spaces. 1187143327Sharti */ 1188143327Sharti *cp++ = '\0'; 1189143327Sharti Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE)); 11901590Srgrimes 1191143327Sharti while (*cp == ' ' || *cp == '\t') { 1192143327Sharti cp++; 1193143327Sharti } 1194143312Sharti /* 1195143327Sharti * Adjust cp for increment at 1196143327Sharti * start of loop, but set start 1197143327Sharti * to first non-space. 1198143312Sharti */ 1199143327Sharti start = cp--; 1200143327Sharti 1201143327Sharti } else if (*cp == '$') { 1202143312Sharti /* 1203143327Sharti * Start of a variable spec -- contact variable module 1204143327Sharti * to find the end so we can skip over it. 1205143312Sharti */ 1206143327Sharti char *junk; 1207143327Sharti size_t len = 0; 1208143327Sharti Boolean doFree; 12091590Srgrimes 1210143327Sharti junk = Var_Parse(cp, parent, TRUE, &len, &doFree); 1211143327Sharti if (junk != var_Error) { 1212143327Sharti cp += len - 1; 1213143312Sharti } 1214143327Sharti if (doFree) { 1215143327Sharti free(junk); 1216143327Sharti } 1217143312Sharti 1218143327Sharti } else if (*cp == '\\' && *cp != '\0') { 1219143327Sharti /* 1220143327Sharti * Escaped something -- skip over it 1221143327Sharti */ 1222143327Sharti cp++; 1223143312Sharti } 1224143327Sharti } 12251590Srgrimes 1226143327Sharti if (cp != start) { 1227143312Sharti /* 1228143327Sharti * Stuff left over -- add it to the 1229143327Sharti * list too 1230143312Sharti */ 1231143327Sharti Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE)); 1232143327Sharti } 1233143312Sharti 1234143327Sharti Buf_Destroy(buf, TRUE); 1235143327Sharti} 1236143327Sharti 1237143327Sharti/*- 1238143327Sharti * The child node contains wildcards. Expand them and return a list of 1239143327Sharti * expansions. 1240143327Sharti */ 1241143327Shartistatic void 1242143327ShartiSuffExpandWildcards(GNode *child, Lst *members) 1243143327Sharti{ 1244143327Sharti char *cp; 1245143327Sharti Lst exp; /* List of expansions */ 1246143327Sharti LstNode *ln; 1247144020Sharti struct Path *path; /* Search path along which to expand */ 1248143327Sharti 1249143327Sharti Lst_Init(members); 1250143327Sharti 1251143327Sharti /* 1252143327Sharti * Find a path along which to expand the word. 1253143327Sharti * 1254143327Sharti * If the word has a known suffix, use that path. 1255143327Sharti * If it has no known suffix and we're allowed to use the null 1256143327Sharti * suffix, use its path. 1257143327Sharti * Else use the default system search path. 1258143327Sharti */ 1259143807Sharti LST_FOREACH(ln, &sufflist) { 1260143807Sharti if (SuffSuffIsSuffix(Lst_Datum(ln), child->name) != NULL) 1261143807Sharti break; 1262143807Sharti } 1263143327Sharti 1264143327Sharti DEBUGF(SUFF, ("Wildcard expanding \"%s\"...", child->name)); 1265143327Sharti 1266143327Sharti if (ln != NULL) { 1267143327Sharti Suff *s = Lst_Datum(ln); 1268143327Sharti 1269143327Sharti DEBUGF(SUFF, ("suffix is \"%s\"...", s->name)); 1270143327Sharti path = &s->searchPath; 1271143327Sharti } else { 1272143312Sharti /* 1273143327Sharti * Use default search path 1274143312Sharti */ 1275143327Sharti path = &dirSearchPath; 1276143327Sharti } 1277143312Sharti 1278143327Sharti /* 1279143327Sharti * Expand the word along the chosen path 1280143327Sharti */ 1281143327Sharti Lst_Init(&exp); 1282144020Sharti Path_Expand(child->name, path, &exp); 12831590Srgrimes 1284143327Sharti while (!Lst_IsEmpty(&exp)) { 12851590Srgrimes /* 1286143327Sharti * Fetch next expansion off the list and find its GNode 12871590Srgrimes */ 1288143327Sharti cp = Lst_DeQueue(&exp); 12891590Srgrimes 1290143327Sharti DEBUGF(SUFF, ("%s...", cp)); 1291143327Sharti Lst_AtEnd(members, Targ_FindNode(cp, TARG_CREATE)); 1292143327Sharti } 1293143327Sharti} 1294138916Sharti 1295143327Sharti/*- 1296143327Sharti *----------------------------------------------------------------------- 1297143327Sharti * SuffExpandChildren -- 1298143327Sharti * Expand the names of any children of a given node that contain 1299143327Sharti * variable invocations or file wildcards into actual targets. 1300143327Sharti * 1301143327Sharti * Results: 1302143327Sharti * == 0 (continue) 1303143327Sharti * 1304143327Sharti * Side Effects: 1305143327Sharti * The expanded node is removed from the parent's list of children, 1306143327Sharti * and the parent's unmade counter is decremented, but other nodes 1307143327Sharti * may be added. 1308143327Sharti * 1309143327Sharti *----------------------------------------------------------------------- 1310143327Sharti */ 1311143327Shartistatic void 1312143327ShartiSuffExpandChildren(GNode *parent, LstNode *current) 1313143327Sharti{ 1314143327Sharti GNode *cchild; /* current child */ 1315143327Sharti GNode *gn; 1316143327Sharti LstNode *prev; /* node after which to append new source */ 1317143327Sharti Lst members; /* expanded nodes */ 1318143327Sharti 1319143327Sharti if (current == NULL) { 1320143327Sharti /* start from begin of parent's children list */ 1321143327Sharti current = Lst_First(&parent->children); 1322143327Sharti } 1323143327Sharti 1324143327Sharti while (current != NULL) { 1325143327Sharti cchild = Lst_Datum(current); 1326143327Sharti 1327143297Sharti /* 1328143327Sharti * First do variable expansion -- this takes precedence over 1329143327Sharti * wildcard expansion. If the result contains wildcards, they'll 1330143327Sharti * be gotten to later since the resulting words are tacked 1331143327Sharti * instead of the current child onto the children list. 1332143297Sharti * 1333143327Sharti * XXXHB what if cchild contains lib.a(t1.o t2.o t3.o) but 1334143327Sharti * no $? 1335143297Sharti */ 1336143327Sharti if (strchr(cchild->name, '$') != NULL) { 1337143327Sharti SuffExpandVariables(parent, cchild, &members); 13381590Srgrimes 1339143327Sharti } else if (Dir_HasWildcards(cchild->name)) { 1340143327Sharti SuffExpandWildcards(cchild, &members); 13411590Srgrimes 1342143297Sharti } else { 1343143327Sharti /* nothing special just advance to next child */ 1344143327Sharti current = LST_NEXT(current); 1345143327Sharti continue; 1346143297Sharti } 13471590Srgrimes 1348143297Sharti /* 1349143327Sharti * New nodes effectively take the place of the child, 1350143327Sharti * so place them after the child 1351143297Sharti */ 1352143327Sharti prev = current; 13531590Srgrimes 1354143327Sharti /* 1355143327Sharti * Add all new elements to the parent node if they aren't 1356143327Sharti * already children of it. 1357143327Sharti */ 1358143327Sharti while(!Lst_IsEmpty(&members)) { 1359143327Sharti gn = Lst_DeQueue(&members); 13601590Srgrimes 1361143327Sharti DEBUGF(SUFF, ("%s...", gn->name)); 1362143327Sharti if (Lst_Member(&parent->children, gn) == NULL) { 1363143327Sharti Lst_Append(&parent->children, prev, gn); 1364143327Sharti prev = Lst_Succ(prev); 1365143327Sharti Lst_AtEnd(&gn->parents, parent); 1366143327Sharti parent->unmade++; 1367143297Sharti } 1368143297Sharti } 13691590Srgrimes 1370143297Sharti /* 1371143327Sharti * Now the source is expanded, remove it from the list 1372143327Sharti * of children to keep it from being processed. 1373143327Sharti * Advance to the next child. 1374143297Sharti */ 1375143327Sharti prev = current; 1376143327Sharti current = LST_NEXT(current); 1377143327Sharti 1378143327Sharti parent->unmade--; 1379143327Sharti Lst_Remove(&parent->children, prev); 1380143297Sharti DEBUGF(SUFF, ("\n")); 13811590Srgrimes } 13821590Srgrimes} 13831590Srgrimes 13841590Srgrimes/*- 13851590Srgrimes *----------------------------------------------------------------------- 13861590Srgrimes * SuffApplyTransform -- 13871590Srgrimes * Apply a transformation rule, given the source and target nodes 13881590Srgrimes * and suffixes. 13891590Srgrimes * 13901590Srgrimes * Results: 13911590Srgrimes * TRUE if successful, FALSE if not. 13921590Srgrimes * 13931590Srgrimes * Side Effects: 13941590Srgrimes * The source and target are linked and the commands from the 13951590Srgrimes * transformation are added to the target node's commands list. 13961590Srgrimes * All attributes but OP_DEPMASK and OP_TRANSFORM are applied 13971590Srgrimes * to the target. The target also inherits all the sources for 13981590Srgrimes * the transformation rule. 13991590Srgrimes * 14001590Srgrimes *----------------------------------------------------------------------- 14011590Srgrimes */ 14021590Srgrimesstatic Boolean 1403104696SjmallettSuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) 14041590Srgrimes{ 1405143407Sharti LstNode *ln; /* General node */ 1406143407Sharti char *tname; /* Name of transformation rule */ 1407143407Sharti GNode *gn; /* Node for same */ 14081590Srgrimes 1409143407Sharti if (Lst_Member(&tGn->children, sGn) == NULL) { 14101590Srgrimes /* 14111590Srgrimes * Not already linked, so form the proper links between the 14121590Srgrimes * target and source. 14131590Srgrimes */ 1414143407Sharti Lst_AtEnd(&tGn->children, sGn); 1415143407Sharti Lst_AtEnd(&sGn->parents, tGn); 14161590Srgrimes tGn->unmade += 1; 14171590Srgrimes } 14181590Srgrimes 1419143407Sharti if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) { 1420143407Sharti /* 1421143407Sharti * When a :: node is used as the implied source of a node, 1422143407Sharti * we have to link all its cohorts in as sources as well. Only 1423143407Sharti * the initial sGn gets the target in its iParents list, however 1424143407Sharti * as that will be sufficient to get the .IMPSRC variable set 1425143407Sharti * for tGn 1426143407Sharti */ 1427143407Sharti for (ln = Lst_First(&sGn->cohorts); ln != NULL; 1428143407Sharti ln = Lst_Succ(ln)) { 1429143407Sharti gn = Lst_Datum(ln); 1430143407Sharti 1431143407Sharti if (Lst_Member(&tGn->children, gn) == NULL) { 1432143407Sharti /* 1433143407Sharti * Not already linked, so form the proper 1434143407Sharti * links between the target and source. 1435143407Sharti */ 1436143407Sharti Lst_AtEnd(&tGn->children, gn); 1437143407Sharti Lst_AtEnd(&gn->parents, tGn); 1438143407Sharti tGn->unmade += 1; 1439143407Sharti } 1440143407Sharti } 1441143407Sharti } 14421590Srgrimes /* 1443143407Sharti * Locate the transformation rule itself 14441590Srgrimes */ 1445143407Sharti tname = str_concat(s->name, t->name, 0); 1446143911Sharti gn = SuffTransFind(tname); 1447143407Sharti free(tname); 14481590Srgrimes 1449143911Sharti if (gn == NULL) { 1450143407Sharti /* 1451143407Sharti * Not really such a transformation rule (can happen when we're 1452143407Sharti * called to link an OP_MEMBER and OP_ARCHV node), so return 1453143407Sharti * FALSE. 1454143407Sharti */ 1455143407Sharti return (FALSE); 1456143407Sharti } 14578874Srgrimes 1458143407Sharti DEBUGF(SUFF, ("\tapplying %s -> %s to \"%s\"\n", 1459143407Sharti s->name, t->name, tGn->name)); 14608874Srgrimes 1461143407Sharti /* 1462143407Sharti * Record last child for expansion purposes 1463143407Sharti */ 1464143407Sharti ln = Lst_Last(&tGn->children); 14651590Srgrimes 1466143407Sharti /* 1467143407Sharti * Pass the buck to Make_HandleUse to apply the rule 1468143407Sharti */ 1469143407Sharti Make_HandleUse(gn, tGn); 14701590Srgrimes 1471143407Sharti /* 1472143407Sharti * Deal with wildcards and variables in any acquired sources 1473143407Sharti */ 1474143407Sharti ln = Lst_Succ(ln); 1475143407Sharti if (ln != NULL) { 1476143407Sharti SuffExpandChildren(tGn, ln); 1477143407Sharti } 14781590Srgrimes 1479143407Sharti /* 1480143407Sharti * Keep track of another parent to which this beast is transformed so 1481143407Sharti * the .IMPSRC variable can be set correctly for the parent. 1482143407Sharti */ 1483143407Sharti Lst_AtEnd(&sGn->iParents, tGn); 1484143407Sharti 1485143407Sharti return (TRUE); 14861590Srgrimes} 14871590Srgrimes 14881590Srgrimes 14891590Srgrimes/*- 14901590Srgrimes *----------------------------------------------------------------------- 14911590Srgrimes * SuffFindArchiveDeps -- 14921590Srgrimes * Locate dependencies for an OP_ARCHV node. 14931590Srgrimes * 14941590Srgrimes * Results: 14951590Srgrimes * None 14961590Srgrimes * 14971590Srgrimes * Side Effects: 14981590Srgrimes * Same as Suff_FindDeps 14991590Srgrimes * 15001590Srgrimes *----------------------------------------------------------------------- 15011590Srgrimes */ 15021590Srgrimesstatic void 1503138512ShartiSuffFindArchiveDeps(GNode *gn, Lst *slst) 15041590Srgrimes{ 1505143407Sharti char *eoarch; /* End of archive portion */ 1506143407Sharti char *eoname; /* End of member portion */ 1507146149Sharti char *name; /* Start of member's name */ 1508143407Sharti GNode *mem; /* Node for member */ 1509146149Sharti Suff *ms; /* Suffix descriptor for member */ 1510146149Sharti 1511146149Sharti static const char *copy[] = { 1512143407Sharti TARGET, /* Must be first */ 1513143407Sharti PREFIX, /* Must be second */ 1514143407Sharti }; 15158874Srgrimes 1516143407Sharti /* 1517143407Sharti * The node is an archive(member) pair. so we must find a 1518143407Sharti * suffix for both of them. 1519143407Sharti */ 1520143407Sharti eoarch = strchr(gn->name, '('); 1521143407Sharti eoname = strchr(eoarch, ')'); 15221590Srgrimes 1523143407Sharti *eoname = '\0'; /* Nuke parentheses during suffix search */ 1524143407Sharti *eoarch = '\0'; /* So a suffix can be found */ 15251590Srgrimes 1526143407Sharti name = eoarch + 1; 15278874Srgrimes 1528143407Sharti /* 1529143407Sharti * To simplify things, call Suff_FindDeps recursively on the member now, 1530143407Sharti * so we can simply compare the member's .PREFIX and .TARGET variables 1531143407Sharti * to locate its suffix. This allows us to figure out the suffix to 1532143407Sharti * use for the archive without having to do a quadratic search over the 1533143407Sharti * suffix list, backtracking for each one... 1534143407Sharti */ 1535143407Sharti mem = Targ_FindNode(name, TARG_CREATE); 1536143407Sharti SuffFindDeps(mem, slst); 15371590Srgrimes 1538143407Sharti /* 1539143407Sharti * Create the link between the two nodes right off 1540143407Sharti */ 1541143407Sharti if (Lst_Member(&gn->children, mem) == NULL) { 1542143407Sharti Lst_AtEnd(&gn->children, mem); 1543143407Sharti Lst_AtEnd(&mem->parents, gn); 1544143407Sharti gn->unmade += 1; 1545143407Sharti } 15468874Srgrimes 1547143407Sharti /* 1548143407Sharti * Copy in the variables from the member node to this one. 1549143407Sharti */ 1550146580Sharti Var_Set(copy[1], Var_Value(copy[1], mem), gn); 1551146580Sharti Var_Set(copy[0], Var_Value(copy[0], mem), gn); 15525814Sjkh 1553143407Sharti ms = mem->suffix; 1554143407Sharti if (ms == NULL) { 1555143407Sharti /* 1556143407Sharti * Didn't know what it was -- use .NULL suffix if not in 1557143407Sharti * make mode 1558143407Sharti */ 1559143407Sharti DEBUGF(SUFF, ("using null suffix\n")); 1560143407Sharti ms = suffNull; 1561143407Sharti } 15621590Srgrimes 15631590Srgrimes /* 1564143407Sharti * Set the other two local variables required for this target. 1565143407Sharti */ 1566143407Sharti Var_Set(MEMBER, name, gn); 1567143407Sharti Var_Set(ARCHIVE, gn->name, gn); 15681590Srgrimes 1569143407Sharti if (ms != NULL) { 1570143407Sharti /* 1571143407Sharti * Member has a known suffix, so look for a transformation rule 1572143407Sharti * from it to a possible suffix of the archive. Rather than 1573143407Sharti * searching through the entire list, we just look at suffixes 1574143407Sharti * to which the member's suffix may be transformed... 1575143407Sharti */ 1576143407Sharti LstNode *ln; 15771590Srgrimes 1578143407Sharti /* 1579143407Sharti * Use first matching suffix... 1580143407Sharti */ 1581143807Sharti LST_FOREACH(ln, &ms->parents) { 1582143807Sharti if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL) 1583143807Sharti break; 1584143807Sharti } 15851590Srgrimes 1586143407Sharti if (ln != NULL) { 1587143407Sharti /* 1588143407Sharti * Got one -- apply it 1589143407Sharti */ 1590143407Sharti if (!SuffApplyTransform(gn, mem, Lst_Datum(ln), ms)) { 1591143407Sharti DEBUGF(SUFF, ("\tNo transformation from " 1592143407Sharti "%s -> %s\n", ms->name, 1593143407Sharti ((Suff *)Lst_Datum(ln))->name)); 1594143407Sharti } 1595143407Sharti } 1596143407Sharti } 1597143407Sharti 15981590Srgrimes /* 1599143407Sharti * Replace the opening and closing parens now we've no need 1600143407Sharti * of the separate pieces. 16011590Srgrimes */ 1602143407Sharti *eoarch = '('; 1603143407Sharti *eoname = ')'; 16041590Srgrimes 16051590Srgrimes /* 1606143407Sharti * Pretend gn appeared to the left of a dependency operator so 1607143407Sharti * the user needn't provide a transformation from the member to the 1608143407Sharti * archive. 16091590Srgrimes */ 1610143407Sharti if (OP_NOP(gn->type)) { 1611143407Sharti gn->type |= OP_DEPENDS; 16121590Srgrimes } 16131590Srgrimes 1614143407Sharti /* 1615143407Sharti * Flag the member as such so we remember to look in the archive for 1616143407Sharti * its modification time. 1617143407Sharti */ 1618143407Sharti mem->type |= OP_MEMBER; 16191590Srgrimes} 16201590Srgrimes 16211590Srgrimes/*- 16221590Srgrimes *----------------------------------------------------------------------- 16231590Srgrimes * SuffFindNormalDeps -- 16241590Srgrimes * Locate implicit dependencies for regular targets. 16251590Srgrimes * 16261590Srgrimes * Results: 16271590Srgrimes * None. 16281590Srgrimes * 16291590Srgrimes * Side Effects: 16301590Srgrimes * Same as Suff_FindDeps... 16311590Srgrimes * 16321590Srgrimes *----------------------------------------------------------------------- 16331590Srgrimes */ 16341590Srgrimesstatic void 1635138512ShartiSuffFindNormalDeps(GNode *gn, Lst *slst) 16361590Srgrimes{ 1637143407Sharti char *eoname; /* End of name */ 1638143407Sharti char *sopref; /* Start of prefix */ 1639143407Sharti LstNode *ln; /* Next suffix node to check */ 1640143407Sharti Lst srcs; /* List of sources at which to look */ 1641143407Sharti Lst targs; /* List of targets to which things can be 1642143407Sharti * transformed. They all have the same file, 1643143407Sharti * but different suff and pref fields */ 1644143407Sharti Src *bottom; /* Start of found transformation path */ 1645143407Sharti Src *src; /* General Src pointer */ 1646143407Sharti char *pref; /* Prefix to use */ 1647143407Sharti Src *targ; /* General Src target pointer */ 16481590Srgrimes 1649143407Sharti eoname = gn->name + strlen(gn->name); 1650143407Sharti sopref = gn->name; 16511590Srgrimes 1652143407Sharti /* 1653143407Sharti * Begin at the beginning... 1654143407Sharti */ 1655143407Sharti ln = Lst_First(&sufflist); 1656143407Sharti Lst_Init(&srcs); 1657143407Sharti Lst_Init(&targs); 16581590Srgrimes 16591590Srgrimes /* 1660143407Sharti * We're caught in a catch-22 here. On the one hand, we want to use any 1661143407Sharti * transformation implied by the target's sources, but we can't examine 1662143407Sharti * the sources until we've expanded any variables/wildcards they may 1663143407Sharti * hold, and we can't do that until we've set up the target's local 1664143407Sharti * variables and we can't do that until we know what the proper suffix 1665143407Sharti * for the target is (in case there are two suffixes one of which is a 1666143407Sharti * suffix of the other) and we can't know that until we've found its 1667143407Sharti * implied source, which we may not want to use if there's an existing 1668143407Sharti * source that implies a different transformation. 1669143407Sharti * 1670143407Sharti * In an attempt to get around this, which may not work all the time, 1671143407Sharti * but should work most of the time, we look for implied sources first, 1672143407Sharti * checking transformations to all possible suffixes of the target, 1673143407Sharti * use what we find to set the target's local variables, expand the 1674143407Sharti * children, then look for any overriding transformations they imply. 1675143407Sharti * Should we find one, we discard the one we found before. 16761590Srgrimes */ 16771590Srgrimes 1678143407Sharti while (ln != NULL) { 1679143407Sharti /* 1680143407Sharti * Look for next possible suffix... 1681143407Sharti */ 1682143807Sharti while (ln != NULL) { 1683143807Sharti if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL) 1684143807Sharti break; 1685143807Sharti ln = LST_NEXT(ln); 1686143807Sharti } 1687143807Sharti 1688143407Sharti if (ln != NULL) { 1689143407Sharti int prefLen; /* Length of the prefix */ 1690143407Sharti Src *target; 1691143407Sharti 1692143407Sharti /* 1693143407Sharti * Allocate a Src structure to which things can be 1694143407Sharti * transformed 1695143407Sharti */ 1696143567Sharti target = SuffSrcCreate(estrdup(gn->name), NULL, 1697143567Sharti Lst_Datum(ln), NULL, gn); 1698143407Sharti target->suff->refCount++; 16998874Srgrimes 1700143407Sharti /* 1701143407Sharti * Allocate room for the prefix, whose end is found 1702143407Sharti * by subtracting the length of the suffix from 1703143407Sharti * the end of the name. 1704143407Sharti */ 1705143407Sharti prefLen = (eoname - target->suff->nameLen) - sopref; 1706143807Sharti assert(prefLen >= 0); 1707143407Sharti target->pref = emalloc(prefLen + 1); 1708143407Sharti memcpy(target->pref, sopref, prefLen); 1709143407Sharti target->pref[prefLen] = '\0'; 17101590Srgrimes 1711143407Sharti /* 1712143407Sharti * Add nodes from which the target can be made 1713143407Sharti */ 1714143407Sharti SuffAddLevel(&srcs, target); 17151590Srgrimes 1716143407Sharti /* 1717143407Sharti * Record the target so we can nuke it 1718143407Sharti */ 1719143407Sharti Lst_AtEnd(&targs, target); 17201590Srgrimes 1721143407Sharti /* 1722143407Sharti * Search from this suffix's successor... 1723143407Sharti */ 1724143407Sharti ln = Lst_Succ(ln); 1725143407Sharti } 17261590Srgrimes } 17271590Srgrimes 1728143407Sharti /* 1729143407Sharti * Handle target of unknown suffix... 1730143407Sharti */ 1731143407Sharti if (Lst_IsEmpty(&targs) && suffNull != NULL) { 1732143407Sharti DEBUGF(SUFF, ("\tNo known suffix on %s. Using .NULL suffix\n", 1733143407Sharti gn->name)); 17348874Srgrimes 1735143567Sharti targ = SuffSrcCreate(estrdup(gn->name), estrdup(sopref), 1736143567Sharti suffNull, NULL, gn); 1737143407Sharti targ->suff->refCount++; 17381590Srgrimes 1739143407Sharti /* 1740143407Sharti * Only use the default suffix rules if we don't have commands 1741143407Sharti * or dependencies defined for this gnode 1742143407Sharti */ 1743143407Sharti if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children)) 1744143407Sharti SuffAddLevel(&srcs, targ); 1745143407Sharti else { 1746143407Sharti DEBUGF(SUFF, ("not ")); 1747143407Sharti } 17489254Sache 1749143407Sharti DEBUGF(SUFF, ("adding suffix rules\n")); 17509254Sache 1751143407Sharti Lst_AtEnd(&targs, targ); 1752143407Sharti } 17538874Srgrimes 17541590Srgrimes /* 1755143407Sharti * Using the list of possible sources built up from the target 1756143407Sharti * suffix(es), try and find an existing file/target that matches. 17571590Srgrimes */ 1758143407Sharti bottom = SuffFindThem(&srcs, slst); 1759143407Sharti 1760143407Sharti if (bottom == NULL) { 1761143407Sharti /* 1762143407Sharti * No known transformations -- use the first suffix found for 1763143407Sharti * setting the local variables. 1764143407Sharti */ 1765143407Sharti if (!Lst_IsEmpty(&targs)) { 1766143407Sharti targ = Lst_Datum(Lst_First(&targs)); 1767143407Sharti } else { 1768143407Sharti targ = NULL; 1769143407Sharti } 17701590Srgrimes } else { 1771143407Sharti /* 1772143407Sharti * Work up the transformation path to find the suffix of the 1773143407Sharti * target to which the transformation was made. 1774143407Sharti */ 1775143407Sharti for (targ = bottom; targ->parent != NULL; targ = targ->parent) 1776143407Sharti continue; 17771590Srgrimes } 1778143407Sharti 17791590Srgrimes /* 1780143407Sharti * The .TARGET variable we always set to be the name at this point, 1781143407Sharti * since it's only set to the path if the thing is only a source and 1782143407Sharti * if it's only a source, it doesn't matter what we put here as far 1783143407Sharti * as expanding sources is concerned, since it has none... 17841590Srgrimes */ 1785143407Sharti Var_Set(TARGET, gn->name, gn); 17861590Srgrimes 1787143407Sharti pref = (targ != NULL) ? targ->pref : gn->name; 1788143407Sharti Var_Set(PREFIX, pref, gn); 17891590Srgrimes 1790143407Sharti /* 1791143407Sharti * Now we've got the important local variables set, expand any sources 1792143407Sharti * that still contain variables or wildcards in their names. 1793143407Sharti */ 1794143407Sharti SuffExpandChildren(gn, NULL); 17951590Srgrimes 1796143407Sharti if (targ == NULL) { 1797143407Sharti DEBUGF(SUFF, ("\tNo valid suffix on %s\n", gn->name)); 17988874Srgrimes 1799143407Sharti sfnd_abort: 1800143407Sharti /* 1801143407Sharti * Deal with finding the thing on the default search path if the 1802143407Sharti * node is only a source (not on the lhs of a dependency 1803143407Sharti * operator or [XXX] it has neither children or commands). 1804143407Sharti */ 1805143407Sharti if (OP_NOP(gn->type) || (Lst_IsEmpty(&gn->children) && 1806143407Sharti Lst_IsEmpty(&gn->commands))) { 1807144020Sharti gn->path = Path_FindFile(gn->name, 1808143407Sharti (targ == NULL ? &dirSearchPath : 1809143407Sharti &targ->suff->searchPath)); 1810143407Sharti if (gn->path != NULL) { 1811143407Sharti char *ptr; 1812143407Sharti Var_Set(TARGET, gn->path, gn); 18131590Srgrimes 1814143407Sharti if (targ != NULL) { 1815143407Sharti /* 1816143407Sharti * Suffix known for the thing -- trim 1817143407Sharti * the suffix off the path to form the 1818143407Sharti * proper .PREFIX variable. 1819143407Sharti */ 1820143407Sharti int savep = strlen(gn->path) - 1821143407Sharti targ->suff->nameLen; 1822143407Sharti char savec; 18231590Srgrimes 1824143407Sharti if (gn->suffix) 1825143407Sharti gn->suffix->refCount--; 1826143407Sharti gn->suffix = targ->suff; 1827143407Sharti gn->suffix->refCount++; 18281590Srgrimes 1829143407Sharti savec = gn->path[savep]; 1830143407Sharti gn->path[savep] = '\0'; 18311590Srgrimes 1832143407Sharti if ((ptr = strrchr(gn->path, '/')) != NULL) 1833143407Sharti ptr++; 1834143407Sharti else 1835143407Sharti ptr = gn->path; 18361590Srgrimes 1837143407Sharti Var_Set(PREFIX, ptr, gn); 18381590Srgrimes 1839143407Sharti gn->path[savep] = savec; 1840143407Sharti } else { 1841143407Sharti /* 1842143407Sharti * The .PREFIX gets the full path if 1843143407Sharti * the target has no known suffix. 1844143407Sharti */ 1845143407Sharti if (gn->suffix) 1846143407Sharti gn->suffix->refCount--; 1847143407Sharti gn->suffix = NULL; 184818730Ssteve 1849143407Sharti if ((ptr = strrchr(gn->path, '/')) != NULL) 1850143407Sharti ptr++; 1851143407Sharti else 1852143407Sharti ptr = gn->path; 1853143407Sharti 1854143407Sharti Var_Set(PREFIX, ptr, gn); 1855143407Sharti } 1856143407Sharti } 18571590Srgrimes } else { 1858143407Sharti /* 1859143407Sharti * Not appropriate to search for the thing -- set the 1860143407Sharti * path to be the name so Dir_MTime won't go 1861143407Sharti * grovelling for it. 1862143407Sharti */ 1863143407Sharti if (gn->suffix) 1864143407Sharti gn->suffix->refCount--; 1865143407Sharti gn->suffix = (targ == NULL) ? NULL : targ->suff; 1866143407Sharti if (gn->suffix) 1867143407Sharti gn->suffix->refCount++; 1868143407Sharti free(gn->path); 1869143407Sharti gn->path = estrdup(gn->name); 1870143407Sharti } 18711590Srgrimes 1872143407Sharti goto sfnd_return; 1873143407Sharti } 187418730Ssteve 1875143407Sharti /* 1876143407Sharti * If the suffix indicates that the target is a library, mark that in 1877143407Sharti * the node's type field. 1878143407Sharti */ 1879143407Sharti if (targ->suff->flags & SUFF_LIBRARY) { 1880143407Sharti gn->type |= OP_LIB; 18811590Srgrimes } 18828874Srgrimes 1883143407Sharti /* 1884143407Sharti * Check for overriding transformation rule implied by sources 1885143407Sharti */ 1886143407Sharti if (!Lst_IsEmpty(&gn->children)) { 1887143407Sharti src = SuffFindCmds(targ, slst); 18881590Srgrimes 1889143407Sharti if (src != NULL) { 1890143407Sharti /* 1891143407Sharti * Free up all the Src structures in the 1892143407Sharti * transformation path up to, but not including, 1893143407Sharti * the parent node. 1894143407Sharti */ 1895143407Sharti while (bottom && bottom->parent != NULL) { 1896143407Sharti if (Lst_Member(slst, bottom) == NULL) { 1897143407Sharti Lst_AtEnd(slst, bottom); 1898143407Sharti } 1899143407Sharti bottom = bottom->parent; 1900143407Sharti } 1901143407Sharti bottom = src; 19025814Sjkh } 19031590Srgrimes } 19041590Srgrimes 1905143407Sharti if (bottom == NULL) { 1906143407Sharti /* 1907143407Sharti * No idea from where it can come -- return now. 1908143407Sharti */ 1909143407Sharti goto sfnd_abort; 1910143407Sharti } 1911143407Sharti 19121590Srgrimes /* 1913143407Sharti * We now have a list of Src structures headed by 'bottom' and linked 1914143407Sharti * via their 'parent' pointers. What we do next is create links between 1915143407Sharti * source and target nodes (which may or may not have been created) 1916143407Sharti * and set the necessary local variables in each target. The 1917143407Sharti * commands for each target are set from the commands of the 1918143407Sharti * transformation rule used to get from the src suffix to the targ 1919143407Sharti * suffix. Note that this causes the commands list of the original 1920143407Sharti * node, gn, to be replaced by the commands of the final 1921143407Sharti * transformation rule. Also, the unmade field of gn is incremented. 1922143407Sharti * Etc. 19231590Srgrimes */ 1924143407Sharti if (bottom->node == NULL) { 1925143407Sharti bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); 1926143407Sharti } 19271590Srgrimes 1928143407Sharti for (src = bottom; src->parent != NULL; src = src->parent) { 1929143407Sharti targ = src->parent; 19308874Srgrimes 1931143407Sharti if (src->node->suffix) 1932143407Sharti src->node->suffix->refCount--; 1933143407Sharti src->node->suffix = src->suff; 1934143407Sharti src->node->suffix->refCount++; 19351590Srgrimes 1936143407Sharti if (targ->node == NULL) { 1937143407Sharti targ->node = Targ_FindNode(targ->file, TARG_CREATE); 1938143407Sharti } 19391590Srgrimes 1940143407Sharti SuffApplyTransform(targ->node, src->node, 1941143407Sharti targ->suff, src->suff); 19421590Srgrimes 1943143407Sharti if (targ->node != gn) { 1944143407Sharti /* 1945143407Sharti * Finish off the dependency-search process for any 1946143407Sharti * nodes between bottom and gn (no point in questing 1947143407Sharti * around the filesystem for their implicit source 1948143407Sharti * when it's already known). Note that the node can't 1949143407Sharti * have any sources that need expanding, since 1950143407Sharti * SuffFindThem will stop on an existing 1951143407Sharti * node, so all we need to do is set the standard and 1952143407Sharti * System V variables. 1953143407Sharti */ 1954143407Sharti targ->node->type |= OP_DEPS_FOUND; 19551590Srgrimes 1956143407Sharti Var_Set(PREFIX, targ->pref, targ->node); 1957143407Sharti Var_Set(TARGET, targ->node->name, targ->node); 1958143407Sharti } 19591590Srgrimes } 19601590Srgrimes 1961143407Sharti if (gn->suffix) 1962143407Sharti gn->suffix->refCount--; 1963143407Sharti gn->suffix = src->suff; 1964143407Sharti gn->suffix->refCount++; 19651590Srgrimes 1966143407Sharti /* 1967143407Sharti * So Dir_MTime doesn't go questing for it... 1968143407Sharti */ 1969143407Sharti free(gn->path); 1970143407Sharti gn->path = estrdup(gn->name); 19711590Srgrimes 1972143407Sharti /* 1973143407Sharti * Nuke the transformation path and the Src structures left over in the 1974143407Sharti * two lists. 1975143407Sharti */ 1976143407Sharti sfnd_return: 1977143407Sharti if (bottom) 1978143407Sharti if (Lst_Member(slst, bottom) == NULL) 1979143407Sharti Lst_AtEnd(slst, bottom); 19801590Srgrimes 1981143407Sharti while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs)) 1982143407Sharti continue; 19835814Sjkh 1984143407Sharti Lst_Concat(slst, &srcs, LST_CONCLINK); 1985143407Sharti Lst_Concat(slst, &targs, LST_CONCLINK); 19861590Srgrimes} 19878874Srgrimes 19881590Srgrimes/*- 19891590Srgrimes *----------------------------------------------------------------------- 19901590Srgrimes * Suff_FindDeps -- 19911590Srgrimes * Find implicit sources for the target described by the graph node 19921590Srgrimes * gn 19931590Srgrimes * 19941590Srgrimes * Results: 19951590Srgrimes * Nothing. 19961590Srgrimes * 19971590Srgrimes * Side Effects: 19981590Srgrimes * Nodes are added to the graph below the passed-in node. The nodes 19991590Srgrimes * are marked to have their IMPSRC variable filled in. The 20001590Srgrimes * PREFIX variable is set for the given node and all its 20011590Srgrimes * implied children. 20021590Srgrimes * 20031590Srgrimes * Notes: 20041590Srgrimes * The path found by this target is the shortest path in the 20051590Srgrimes * transformation graph, which may pass through non-existent targets, 20061590Srgrimes * to an existing target. The search continues on all paths from the 20071590Srgrimes * root suffix until a file is found. I.e. if there's a path 20081590Srgrimes * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but 20091590Srgrimes * the .c and .l files don't, the search will branch out in 20101590Srgrimes * all directions from .o and again from all the nodes on the 20111590Srgrimes * next level until the .l,v node is encountered. 20121590Srgrimes * 20131590Srgrimes *----------------------------------------------------------------------- 20141590Srgrimes */ 20151590Srgrimesvoid 2016104696SjmallettSuff_FindDeps(GNode *gn) 20175814Sjkh{ 20188874Srgrimes 2019143407Sharti SuffFindDeps(gn, &srclist); 2020143407Sharti while (SuffRemoveSrc(&srclist)) 2021143407Sharti continue; 20225814Sjkh} 20235814Sjkh 20245814Sjkh 20255814Sjkhstatic void 2026138512ShartiSuffFindDeps(GNode *gn, Lst *slst) 20271590Srgrimes{ 2028138232Sharti 2029143407Sharti if (gn->type & OP_DEPS_FOUND) { 2030143407Sharti /* 2031143407Sharti * If dependencies already found, no need to do it again... 2032143407Sharti */ 2033143407Sharti return; 2034143407Sharti } else { 2035143407Sharti gn->type |= OP_DEPS_FOUND; 2036143407Sharti } 20378874Srgrimes 2038143407Sharti DEBUGF(SUFF, ("SuffFindDeps (%s)\n", gn->name)); 20398874Srgrimes 2040143407Sharti if (gn->type & OP_ARCHV) { 2041143407Sharti SuffFindArchiveDeps(gn, slst); 20428874Srgrimes 2043143407Sharti } else if (gn->type & OP_LIB) { 2044143407Sharti /* 2045143407Sharti * If the node is a library, it is the arch module's job to find 2046143407Sharti * it and set the TARGET variable accordingly. We merely provide 2047143407Sharti * the search path, assuming all libraries end in ".a" (if the 2048143407Sharti * suffix hasn't been defined, there's nothing we can do for it, 2049143407Sharti * so we just set the TARGET variable to the node's name in order 2050143407Sharti * to give it a value). 2051143407Sharti */ 2052143407Sharti Suff *s; 2053143407Sharti 2054143911Sharti s = SuffSuffFind(LIBSUFF); 2055143407Sharti if (gn->suffix) 2056143407Sharti gn->suffix->refCount--; 2057143911Sharti if (s != NULL) { 2058143911Sharti gn->suffix = s; 2059143407Sharti gn->suffix->refCount++; 2060143407Sharti Arch_FindLib(gn, &s->searchPath); 2061143407Sharti } else { 2062143407Sharti gn->suffix = NULL; 2063143407Sharti Var_Set(TARGET, gn->name, gn); 2064143407Sharti } 2065143407Sharti 2066143407Sharti /* 2067143407Sharti * Because a library (-lfoo) target doesn't follow the standard 2068143407Sharti * filesystem conventions, we don't set the regular variables for 2069143407Sharti * the thing. .PREFIX is simply made empty... 2070143407Sharti */ 2071143407Sharti Var_Set(PREFIX, "", gn); 2072143407Sharti 20731590Srgrimes } else { 2074143407Sharti SuffFindNormalDeps(gn, slst); 20751590Srgrimes } 20761590Srgrimes} 20771590Srgrimes 20781590Srgrimes/*- 20791590Srgrimes *----------------------------------------------------------------------- 20801590Srgrimes * Suff_SetNull -- 20811590Srgrimes * Define which suffix is the null suffix. 20821590Srgrimes * 20831590Srgrimes * Results: 20841590Srgrimes * None. 20851590Srgrimes * 20861590Srgrimes * Side Effects: 20871590Srgrimes * 'suffNull' is altered. 20881590Srgrimes * 20891590Srgrimes * Notes: 20901590Srgrimes * Need to handle the changing of the null suffix gracefully so the 20911590Srgrimes * old transformation rules don't just go away. 20921590Srgrimes * 20931590Srgrimes *----------------------------------------------------------------------- 20941590Srgrimes */ 20951590Srgrimesvoid 2096104696SjmallettSuff_SetNull(char *name) 20971590Srgrimes{ 2098143407Sharti Suff *s; 20991590Srgrimes 2100143911Sharti if ((s = SuffSuffFind(name)) == NULL) { 2101143407Sharti Parse_Error(PARSE_WARNING, "Desired null suffix %s " 2102143407Sharti "not defined.", name); 2103143911Sharti return; 21041590Srgrimes } 2105143911Sharti 2106143911Sharti if (suffNull != NULL) { 2107143911Sharti suffNull->flags &= ~SUFF_NULL; 2108143911Sharti } 2109143911Sharti s->flags |= SUFF_NULL; 2110143911Sharti 2111143911Sharti /* 2112143911Sharti * XXX: Here's where the transformation mangling 2113143911Sharti * would take place 2114143911Sharti */ 2115143911Sharti suffNull = s; 21161590Srgrimes} 21171590Srgrimes 21181590Srgrimes/*- 21191590Srgrimes *----------------------------------------------------------------------- 21201590Srgrimes * Suff_Init -- 21211590Srgrimes * Initialize suffixes module 21221590Srgrimes * 21231590Srgrimes * Results: 21241590Srgrimes * None 21251590Srgrimes * 21261590Srgrimes * Side Effects: 21271590Srgrimes * Many 21281590Srgrimes *----------------------------------------------------------------------- 21291590Srgrimes */ 21301590Srgrimesvoid 2131138232ShartiSuff_Init(void) 21321590Srgrimes{ 2133138232Sharti 2134143407Sharti sNum = 0; 2135143407Sharti /* 2136143407Sharti * Create null suffix for single-suffix rules (POSIX). The thing doesn't 2137143407Sharti * actually go on the suffix list or everyone will think that's its 2138143407Sharti * suffix. 2139143407Sharti */ 2140143407Sharti emptySuff = suffNull = emalloc(sizeof(Suff)); 21411590Srgrimes 2142143407Sharti suffNull->name = estrdup(""); 2143143407Sharti suffNull->nameLen = 0; 2144144020Sharti TAILQ_INIT(&suffNull->searchPath); 2145144020Sharti Path_Concat(&suffNull->searchPath, &dirSearchPath); 2146143407Sharti Lst_Init(&suffNull->children); 2147143407Sharti Lst_Init(&suffNull->parents); 2148143407Sharti Lst_Init(&suffNull->ref); 2149143407Sharti suffNull->sNum = sNum++; 2150143407Sharti suffNull->flags = SUFF_NULL; 2151143407Sharti suffNull->refCount = 1; 21521590Srgrimes} 21531590Srgrimes 21541590Srgrimes/********************* DEBUGGING FUNCTIONS **********************/ 21551590Srgrimes 2156143414Shartivoid 2157143414ShartiSuff_PrintAll(void) 21585814Sjkh{ 2159143414Sharti const LstNode *ln; 2160143414Sharti const LstNode *tln; 2161143414Sharti const GNode *gn; 2162143414Sharti const Suff *s; 2163138232Sharti 2164143414Sharti static const struct flag2str suff_flags[] = { 2165143414Sharti { SUFF_INCLUDE, "INCLUDE" }, 2166143414Sharti { SUFF_LIBRARY, "LIBRARY" }, 2167143414Sharti { SUFF_NULL, "NULL" }, 2168143414Sharti { 0, NULL } 2169143414Sharti }; 21701590Srgrimes 2171143414Sharti printf("#*** Suffixes:\n"); 2172143414Sharti LST_FOREACH(ln, &sufflist) { 2173143414Sharti s = Lst_Datum(ln); 2174143414Sharti printf("# `%s' [%d] ", s->name, s->refCount); 21751590Srgrimes 2176143414Sharti if (s->flags != 0) { 2177143414Sharti printf(" "); 2178146184Sharti print_flags(stdout, suff_flags, s->flags, 1); 2179143407Sharti } 21801590Srgrimes 2181143414Sharti printf("\n#\tTo: "); 2182143414Sharti LST_FOREACH(tln, &s->parents) 2183143414Sharti printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name); 21841590Srgrimes 2185143414Sharti printf("\n#\tFrom: "); 2186143414Sharti LST_FOREACH(tln, &s->children) 2187143414Sharti printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name); 21881590Srgrimes 2189143414Sharti printf("\n#\tSearch Path: "); 2190144020Sharti Path_Print(&s->searchPath); 21911590Srgrimes 2192143414Sharti printf("\n"); 2193143414Sharti } 2194138232Sharti 2195143407Sharti printf("#*** Transformations:\n"); 2196143414Sharti LST_FOREACH(ln, &transforms) { 2197143414Sharti gn = Lst_Datum(ln); 2198143414Sharti printf("%-16s: ", gn->name); 2199143414Sharti Targ_PrintType(gn->type); 2200143414Sharti printf("\n"); 2201143414Sharti LST_FOREACH(tln, &gn->commands) 2202143414Sharti printf("\t%s\n", (const char *)Lst_Datum(tln)); 2203143414Sharti printf("\n"); 2204143414Sharti } 22051590Srgrimes} 2206