Annotation of src/usr.bin/make/suff.c, Revision 1.1
1.1 ! deraadt 1: /* $NetBSD: suff.c,v 1.10 1995/09/25 02:46:30 christos Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
! 5: * Copyright (c) 1988, 1989 by Adam de Boor
! 6: * Copyright (c) 1989 by Berkeley Softworks
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to Berkeley by
! 10: * Adam de Boor.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by the University of
! 23: * California, Berkeley and its contributors.
! 24: * 4. Neither the name of the University nor the names of its contributors
! 25: * may be used to endorse or promote products derived from this software
! 26: * without specific prior written permission.
! 27: *
! 28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 38: * SUCH DAMAGE.
! 39: */
! 40:
! 41: #ifndef lint
! 42: #if 0
! 43: static char sccsid[] = "@(#)suff.c 5.6 (Berkeley) 6/1/90";
! 44: #else
! 45: static char rcsid[] = "$NetBSD: suff.c,v 1.10 1995/09/25 02:46:30 christos Exp $";
! 46: #endif
! 47: #endif /* not lint */
! 48:
! 49: /*-
! 50: * suff.c --
! 51: * Functions to maintain suffix lists and find implicit dependents
! 52: * using suffix transformation rules
! 53: *
! 54: * Interface:
! 55: * Suff_Init Initialize all things to do with suffixes.
! 56: *
! 57: * Suff_End Cleanup the module
! 58: *
! 59: * Suff_DoPaths This function is used to make life easier
! 60: * when searching for a file according to its
! 61: * suffix. It takes the global search path,
! 62: * as defined using the .PATH: target, and appends
! 63: * its directories to the path of each of the
! 64: * defined suffixes, as specified using
! 65: * .PATH<suffix>: targets. In addition, all
! 66: * directories given for suffixes labeled as
! 67: * include files or libraries, using the .INCLUDES
! 68: * or .LIBS targets, are played with using
! 69: * Dir_MakeFlags to create the .INCLUDES and
! 70: * .LIBS global variables.
! 71: *
! 72: * Suff_ClearSuffixes Clear out all the suffixes and defined
! 73: * transformations.
! 74: *
! 75: * Suff_IsTransform Return TRUE if the passed string is the lhs
! 76: * of a transformation rule.
! 77: *
! 78: * Suff_AddSuffix Add the passed string as another known suffix.
! 79: *
! 80: * Suff_GetPath Return the search path for the given suffix.
! 81: *
! 82: * Suff_AddInclude Mark the given suffix as denoting an include
! 83: * file.
! 84: *
! 85: * Suff_AddLib Mark the given suffix as denoting a library.
! 86: *
! 87: * Suff_AddTransform Add another transformation to the suffix
! 88: * graph. Returns GNode suitable for framing, I
! 89: * mean, tacking commands, attributes, etc. on.
! 90: *
! 91: * Suff_SetNull Define the suffix to consider the suffix of
! 92: * any file that doesn't have a known one.
! 93: *
! 94: * Suff_FindDeps Find implicit sources for and the location of
! 95: * a target based on its suffix. Returns the
! 96: * bottom-most node added to the graph or NILGNODE
! 97: * if the target had no implicit sources.
! 98: */
! 99:
! 100: #include <stdio.h>
! 101: #include "make.h"
! 102: #include "hash.h"
! 103: #include "dir.h"
! 104: #include "bit.h"
! 105:
! 106: static Lst sufflist; /* Lst of suffixes */
! 107: static Lst suffClean; /* Lst of suffixes to be cleaned */
! 108: static Lst srclist; /* Lst of sources */
! 109: static Lst transforms; /* Lst of transformation rules */
! 110:
! 111: static int sNum = 0; /* Counter for assigning suffix numbers */
! 112:
! 113: /*
! 114: * Structure describing an individual suffix.
! 115: */
! 116: typedef struct _Suff {
! 117: char *name; /* The suffix itself */
! 118: int nameLen; /* Length of the suffix */
! 119: short flags; /* Type of suffix */
! 120: #define SUFF_INCLUDE 0x01 /* One which is #include'd */
! 121: #define SUFF_LIBRARY 0x02 /* One which contains a library */
! 122: #define SUFF_NULL 0x04 /* The empty suffix */
! 123: Lst searchPath; /* The path along which files of this suffix
! 124: * may be found */
! 125: int sNum; /* The suffix number */
! 126: int refCount; /* Reference count of list membership */
! 127: Lst parents; /* Suffixes we have a transformation to */
! 128: Lst children; /* Suffixes we have a transformation from */
! 129: Lst ref; /* List of lists this suffix is referenced */
! 130: } Suff;
! 131:
! 132: /*
! 133: * Structure used in the search for implied sources.
! 134: */
! 135: typedef struct _Src {
! 136: char *file; /* The file to look for */
! 137: char *pref; /* Prefix from which file was formed */
! 138: Suff *suff; /* The suffix on the file */
! 139: struct _Src *parent; /* The Src for which this is a source */
! 140: GNode *node; /* The node describing the file */
! 141: int children; /* Count of existing children (so we don't free
! 142: * this thing too early or never nuke it) */
! 143: #ifdef DEBUG_SRC
! 144: Lst cp; /* Debug; children list */
! 145: #endif
! 146: } Src;
! 147:
! 148: /*
! 149: * A structure for passing more than one argument to the Lst-library-invoked
! 150: * function...
! 151: */
! 152: typedef struct {
! 153: Lst l;
! 154: Src *s;
! 155: } LstSrc;
! 156:
! 157: static Suff *suffNull; /* The NULL suffix for this run */
! 158: static Suff *emptySuff; /* The empty suffix required for POSIX
! 159: * single-suffix transformation rules */
! 160:
! 161:
! 162: static char *SuffStrIsPrefix __P((char *, char *));
! 163: static char *SuffSuffIsSuffix __P((Suff *, char *));
! 164: static int SuffSuffIsSuffixP __P((ClientData, ClientData));
! 165: static int SuffSuffHasNameP __P((ClientData, ClientData));
! 166: static int SuffSuffIsPrefix __P((ClientData, ClientData));
! 167: static int SuffGNHasNameP __P((ClientData, ClientData));
! 168: static void SuffFree __P((ClientData));
! 169: static void SuffInsert __P((Lst, Suff *));
! 170: static void SuffRemove __P((Lst, Suff *));
! 171: static Boolean SuffParseTransform __P((char *, Suff **, Suff **));
! 172: static int SuffRebuildGraph __P((ClientData, ClientData));
! 173: static int SuffAddSrc __P((ClientData, ClientData));
! 174: static int SuffRemoveSrc __P((Lst));
! 175: static void SuffAddLevel __P((Lst, Src *));
! 176: static Src *SuffFindThem __P((Lst, Lst));
! 177: static Src *SuffFindCmds __P((Src *, Lst));
! 178: static int SuffExpandChildren __P((ClientData, ClientData));
! 179: static Boolean SuffApplyTransform __P((GNode *, GNode *, Suff *, Suff *));
! 180: static void SuffFindDeps __P((GNode *, Lst));
! 181: static void SuffFindArchiveDeps __P((GNode *, Lst));
! 182: static void SuffFindNormalDeps __P((GNode *, Lst));
! 183: static int SuffPrintName __P((ClientData, ClientData));
! 184: static int SuffPrintSuff __P((ClientData, ClientData));
! 185: static int SuffPrintTrans __P((ClientData, ClientData));
! 186:
! 187: /*************** Lst Predicates ****************/
! 188: /*-
! 189: *-----------------------------------------------------------------------
! 190: * SuffStrIsPrefix --
! 191: * See if pref is a prefix of str.
! 192: *
! 193: * Results:
! 194: * NULL if it ain't, pointer to character in str after prefix if so
! 195: *
! 196: * Side Effects:
! 197: * None
! 198: *-----------------------------------------------------------------------
! 199: */
! 200: static char *
! 201: SuffStrIsPrefix (pref, str)
! 202: register char *pref; /* possible prefix */
! 203: register char *str; /* string to check */
! 204: {
! 205: while (*str && *pref == *str) {
! 206: pref++;
! 207: str++;
! 208: }
! 209:
! 210: return (*pref ? NULL : str);
! 211: }
! 212:
! 213: /*-
! 214: *-----------------------------------------------------------------------
! 215: * SuffSuffIsSuffix --
! 216: * See if suff is a suffix of str. Str should point to THE END of the
! 217: * string to check. (THE END == the null byte)
! 218: *
! 219: * Results:
! 220: * NULL if it ain't, pointer to character in str before suffix if
! 221: * it is.
! 222: *
! 223: * Side Effects:
! 224: * None
! 225: *-----------------------------------------------------------------------
! 226: */
! 227: static char *
! 228: SuffSuffIsSuffix (s, str)
! 229: register Suff *s; /* possible suffix */
! 230: char *str; /* string to examine */
! 231: {
! 232: register char *p1; /* Pointer into suffix name */
! 233: register char *p2; /* Pointer into string being examined */
! 234:
! 235: p1 = s->name + s->nameLen;
! 236: p2 = str;
! 237:
! 238: while (p1 >= s->name && *p1 == *p2) {
! 239: p1--;
! 240: p2--;
! 241: }
! 242:
! 243: return (p1 == s->name - 1 ? p2 : NULL);
! 244: }
! 245:
! 246: /*-
! 247: *-----------------------------------------------------------------------
! 248: * SuffSuffIsSuffixP --
! 249: * Predicate form of SuffSuffIsSuffix. Passed as the callback function
! 250: * to Lst_Find.
! 251: *
! 252: * Results:
! 253: * 0 if the suffix is the one desired, non-zero if not.
! 254: *
! 255: * Side Effects:
! 256: * None.
! 257: *
! 258: *-----------------------------------------------------------------------
! 259: */
! 260: static int
! 261: SuffSuffIsSuffixP(s, str)
! 262: ClientData s;
! 263: ClientData str;
! 264: {
! 265: return(!SuffSuffIsSuffix((Suff *) s, (char *) str));
! 266: }
! 267:
! 268: /*-
! 269: *-----------------------------------------------------------------------
! 270: * SuffSuffHasNameP --
! 271: * Callback procedure for finding a suffix based on its name. Used by
! 272: * Suff_GetPath.
! 273: *
! 274: * Results:
! 275: * 0 if the suffix is of the given name. non-zero otherwise.
! 276: *
! 277: * Side Effects:
! 278: * None
! 279: *-----------------------------------------------------------------------
! 280: */
! 281: static int
! 282: SuffSuffHasNameP (s, sname)
! 283: ClientData s; /* Suffix to check */
! 284: ClientData sname; /* Desired name */
! 285: {
! 286: return (strcmp ((char *) sname, ((Suff *) s)->name));
! 287: }
! 288:
! 289: /*-
! 290: *-----------------------------------------------------------------------
! 291: * SuffSuffIsPrefix --
! 292: * See if the suffix described by s is a prefix of the string. Care
! 293: * must be taken when using this to search for transformations and
! 294: * what-not, since there could well be two suffixes, one of which
! 295: * is a prefix of the other...
! 296: *
! 297: * Results:
! 298: * 0 if s is a prefix of str. non-zero otherwise
! 299: *
! 300: * Side Effects:
! 301: * None
! 302: *-----------------------------------------------------------------------
! 303: */
! 304: static int
! 305: SuffSuffIsPrefix (s, str)
! 306: ClientData s; /* suffix to compare */
! 307: ClientData str; /* string to examine */
! 308: {
! 309: return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);
! 310: }
! 311:
! 312: /*-
! 313: *-----------------------------------------------------------------------
! 314: * SuffGNHasNameP --
! 315: * See if the graph node has the desired name
! 316: *
! 317: * Results:
! 318: * 0 if it does. non-zero if it doesn't
! 319: *
! 320: * Side Effects:
! 321: * None
! 322: *-----------------------------------------------------------------------
! 323: */
! 324: static int
! 325: SuffGNHasNameP (gn, name)
! 326: ClientData gn; /* current node we're looking at */
! 327: ClientData name; /* name we're looking for */
! 328: {
! 329: return (strcmp ((char *) name, ((GNode *) gn)->name));
! 330: }
! 331:
! 332: /*********** Maintenance Functions ************/
! 333:
! 334: static void
! 335: SuffUnRef(lp, sp)
! 336: ClientData lp;
! 337: ClientData sp;
! 338: {
! 339: Lst l = (Lst) lp;
! 340:
! 341: LstNode ln = Lst_Member(l, sp);
! 342: if (ln != NILLNODE) {
! 343: Lst_Remove(l, ln);
! 344: ((Suff *) sp)->refCount--;
! 345: }
! 346: }
! 347:
! 348: /*-
! 349: *-----------------------------------------------------------------------
! 350: * SuffFree --
! 351: * Free up all memory associated with the given suffix structure.
! 352: *
! 353: * Results:
! 354: * none
! 355: *
! 356: * Side Effects:
! 357: * the suffix entry is detroyed
! 358: *-----------------------------------------------------------------------
! 359: */
! 360: static void
! 361: SuffFree (sp)
! 362: ClientData sp;
! 363: {
! 364: Suff *s = (Suff *) sp;
! 365:
! 366: if (s == suffNull)
! 367: suffNull = NULL;
! 368:
! 369: if (s == emptySuff)
! 370: emptySuff = NULL;
! 371:
! 372: Lst_Destroy (s->ref, NOFREE);
! 373: Lst_Destroy (s->children, NOFREE);
! 374: Lst_Destroy (s->parents, NOFREE);
! 375: Lst_Destroy (s->searchPath, Dir_Destroy);
! 376:
! 377: free ((Address)s->name);
! 378: free ((Address)s);
! 379: }
! 380:
! 381: /*-
! 382: *-----------------------------------------------------------------------
! 383: * SuffRemove --
! 384: * Remove the suffix into the list
! 385: *
! 386: * Results:
! 387: * None
! 388: *
! 389: * Side Effects:
! 390: * The reference count for the suffix is decremented and the
! 391: * suffix is possibly freed
! 392: *-----------------------------------------------------------------------
! 393: */
! 394: static void
! 395: SuffRemove(l, s)
! 396: Lst l;
! 397: Suff *s;
! 398: {
! 399: SuffUnRef((ClientData) l, (ClientData) s);
! 400: if (s->refCount == 0)
! 401: SuffFree((ClientData) s);
! 402: }
! 403:
! 404: /*-
! 405: *-----------------------------------------------------------------------
! 406: * SuffInsert --
! 407: * Insert the suffix into the list keeping the list ordered by suffix
! 408: * numbers.
! 409: *
! 410: * Results:
! 411: * None
! 412: *
! 413: * Side Effects:
! 414: * The reference count of the suffix is incremented
! 415: *-----------------------------------------------------------------------
! 416: */
! 417: static void
! 418: SuffInsert (l, s)
! 419: Lst l; /* the list where in s should be inserted */
! 420: Suff *s; /* the suffix to insert */
! 421: {
! 422: LstNode ln; /* current element in l we're examining */
! 423: Suff *s2 = NULL; /* the suffix descriptor in this element */
! 424:
! 425: if (Lst_Open (l) == FAILURE) {
! 426: return;
! 427: }
! 428: while ((ln = Lst_Next (l)) != NILLNODE) {
! 429: s2 = (Suff *) Lst_Datum (ln);
! 430: if (s2->sNum >= s->sNum) {
! 431: break;
! 432: }
! 433: }
! 434:
! 435: Lst_Close (l);
! 436: if (DEBUG(SUFF)) {
! 437: printf("inserting %s(%d)...", s->name, s->sNum);
! 438: }
! 439: if (ln == NILLNODE) {
! 440: if (DEBUG(SUFF)) {
! 441: printf("at end of list\n");
! 442: }
! 443: (void)Lst_AtEnd (l, (ClientData)s);
! 444: s->refCount++;
! 445: (void)Lst_AtEnd(s->ref, (ClientData) l);
! 446: } else if (s2->sNum != s->sNum) {
! 447: if (DEBUG(SUFF)) {
! 448: printf("before %s(%d)\n", s2->name, s2->sNum);
! 449: }
! 450: (void)Lst_Insert (l, ln, (ClientData)s);
! 451: s->refCount++;
! 452: (void)Lst_AtEnd(s->ref, (ClientData) l);
! 453: } else if (DEBUG(SUFF)) {
! 454: printf("already there\n");
! 455: }
! 456: }
! 457:
! 458: /*-
! 459: *-----------------------------------------------------------------------
! 460: * Suff_ClearSuffixes --
! 461: * This is gross. Nuke the list of suffixes but keep all transformation
! 462: * rules around. The transformation graph is destroyed in this process,
! 463: * but we leave the list of rules so when a new graph is formed the rules
! 464: * will remain.
! 465: * This function is called from the parse module when a
! 466: * .SUFFIXES:\n line is encountered.
! 467: *
! 468: * Results:
! 469: * none
! 470: *
! 471: * Side Effects:
! 472: * the sufflist and its graph nodes are destroyed
! 473: *-----------------------------------------------------------------------
! 474: */
! 475: void
! 476: Suff_ClearSuffixes ()
! 477: {
! 478: Lst_Concat (suffClean, sufflist, LST_CONCLINK);
! 479: sufflist = Lst_Init(FALSE);
! 480: sNum = 0;
! 481: suffNull = emptySuff;
! 482: }
! 483:
! 484: /*-
! 485: *-----------------------------------------------------------------------
! 486: * SuffParseTransform --
! 487: * Parse a transformation string to find its two component suffixes.
! 488: *
! 489: * Results:
! 490: * TRUE if the string is a valid transformation and FALSE otherwise.
! 491: *
! 492: * Side Effects:
! 493: * The passed pointers are overwritten.
! 494: *
! 495: *-----------------------------------------------------------------------
! 496: */
! 497: static Boolean
! 498: SuffParseTransform(str, srcPtr, targPtr)
! 499: char *str; /* String being parsed */
! 500: Suff **srcPtr; /* Place to store source of trans. */
! 501: Suff **targPtr; /* Place to store target of trans. */
! 502: {
! 503: register LstNode srcLn; /* element in suffix list of trans source*/
! 504: register Suff *src; /* Source of transformation */
! 505: register LstNode targLn; /* element in suffix list of trans target*/
! 506: register char *str2; /* Extra pointer (maybe target suffix) */
! 507: LstNode singleLn; /* element in suffix list of any suffix
! 508: * that exactly matches str */
! 509: Suff *single = NULL;/* Source of possible transformation to
! 510: * null suffix */
! 511:
! 512: srcLn = NILLNODE;
! 513: singleLn = NILLNODE;
! 514:
! 515: /*
! 516: * Loop looking first for a suffix that matches the start of the
! 517: * string and then for one that exactly matches the rest of it. If
! 518: * we can find two that meet these criteria, we've successfully
! 519: * parsed the string.
! 520: */
! 521: for (;;) {
! 522: if (srcLn == NILLNODE) {
! 523: srcLn = Lst_Find(sufflist, (ClientData)str, SuffSuffIsPrefix);
! 524: } else {
! 525: srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (ClientData)str,
! 526: SuffSuffIsPrefix);
! 527: }
! 528: if (srcLn == NILLNODE) {
! 529: /*
! 530: * Ran out of source suffixes -- no such rule
! 531: */
! 532: if (singleLn != NILLNODE) {
! 533: /*
! 534: * Not so fast Mr. Smith! There was a suffix that encompassed
! 535: * the entire string, so we assume it was a transformation
! 536: * to the null suffix (thank you POSIX). We still prefer to
! 537: * find a double rule over a singleton, hence we leave this
! 538: * check until the end.
! 539: *
! 540: * XXX: Use emptySuff over suffNull?
! 541: */
! 542: *srcPtr = single;
! 543: *targPtr = suffNull;
! 544: return(TRUE);
! 545: }
! 546: return (FALSE);
! 547: }
! 548: src = (Suff *) Lst_Datum (srcLn);
! 549: str2 = str + src->nameLen;
! 550: if (*str2 == '\0') {
! 551: single = src;
! 552: singleLn = srcLn;
! 553: } else {
! 554: targLn = Lst_Find(sufflist, (ClientData)str2, SuffSuffHasNameP);
! 555: if (targLn != NILLNODE) {
! 556: *srcPtr = src;
! 557: *targPtr = (Suff *)Lst_Datum(targLn);
! 558: return (TRUE);
! 559: }
! 560: }
! 561: }
! 562: }
! 563:
! 564: /*-
! 565: *-----------------------------------------------------------------------
! 566: * Suff_IsTransform --
! 567: * Return TRUE if the given string is a transformation rule
! 568: *
! 569: *
! 570: * Results:
! 571: * TRUE if the string is a concatenation of two known suffixes.
! 572: * FALSE otherwise
! 573: *
! 574: * Side Effects:
! 575: * None
! 576: *-----------------------------------------------------------------------
! 577: */
! 578: Boolean
! 579: Suff_IsTransform (str)
! 580: char *str; /* string to check */
! 581: {
! 582: Suff *src, *targ;
! 583:
! 584: return (SuffParseTransform(str, &src, &targ));
! 585: }
! 586:
! 587: /*-
! 588: *-----------------------------------------------------------------------
! 589: * Suff_AddTransform --
! 590: * Add the transformation rule described by the line to the
! 591: * list of rules and place the transformation itself in the graph
! 592: *
! 593: * Results:
! 594: * The node created for the transformation in the transforms list
! 595: *
! 596: * Side Effects:
! 597: * The node is placed on the end of the transforms Lst and links are
! 598: * made between the two suffixes mentioned in the target name
! 599: *-----------------------------------------------------------------------
! 600: */
! 601: GNode *
! 602: Suff_AddTransform (line)
! 603: char *line; /* name of transformation to add */
! 604: {
! 605: GNode *gn; /* GNode of transformation rule */
! 606: Suff *s, /* source suffix */
! 607: *t; /* target suffix */
! 608: LstNode ln; /* Node for existing transformation */
! 609:
! 610: ln = Lst_Find (transforms, (ClientData)line, SuffGNHasNameP);
! 611: if (ln == NILLNODE) {
! 612: /*
! 613: * Make a new graph node for the transformation. It will be filled in
! 614: * by the Parse module.
! 615: */
! 616: gn = Targ_NewGN (line);
! 617: (void)Lst_AtEnd (transforms, (ClientData)gn);
! 618: } else {
! 619: /*
! 620: * New specification for transformation rule. Just nuke the old list
! 621: * of commands so they can be filled in again... We don't actually
! 622: * free the commands themselves, because a given command can be
! 623: * attached to several different transformations.
! 624: */
! 625: gn = (GNode *) Lst_Datum (ln);
! 626: Lst_Destroy (gn->commands, NOFREE);
! 627: Lst_Destroy (gn->children, NOFREE);
! 628: gn->commands = Lst_Init (FALSE);
! 629: gn->children = Lst_Init (FALSE);
! 630: }
! 631:
! 632: gn->type = OP_TRANSFORM;
! 633:
! 634: (void)SuffParseTransform(line, &s, &t);
! 635:
! 636: /*
! 637: * link the two together in the proper relationship and order
! 638: */
! 639: if (DEBUG(SUFF)) {
! 640: printf("defining transformation from `%s' to `%s'\n",
! 641: s->name, t->name);
! 642: }
! 643: SuffInsert (t->children, s);
! 644: SuffInsert (s->parents, t);
! 645:
! 646: return (gn);
! 647: }
! 648:
! 649: /*-
! 650: *-----------------------------------------------------------------------
! 651: * Suff_EndTransform --
! 652: * Handle the finish of a transformation definition, removing the
! 653: * transformation from the graph if it has neither commands nor
! 654: * sources. This is a callback procedure for the Parse module via
! 655: * Lst_ForEach
! 656: *
! 657: * Results:
! 658: * === 0
! 659: *
! 660: * Side Effects:
! 661: * If the node has no commands or children, the children and parents
! 662: * lists of the affected suffices are altered.
! 663: *
! 664: *-----------------------------------------------------------------------
! 665: */
! 666: int
! 667: Suff_EndTransform(gnp, dummy)
! 668: ClientData gnp; /* Node for transformation */
! 669: ClientData dummy; /* Node for transformation */
! 670: {
! 671: GNode *gn = (GNode *) gnp;
! 672:
! 673: if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
! 674: Lst_IsEmpty(gn->children))
! 675: {
! 676: Suff *s, *t;
! 677:
! 678: (void)SuffParseTransform(gn->name, &s, &t);
! 679:
! 680: if (DEBUG(SUFF)) {
! 681: printf("deleting transformation from %s to %s\n",
! 682: s->name, t->name);
! 683: }
! 684:
! 685: /*
! 686: * Remove the source from the target's children list. We check for a
! 687: * nil return to handle a beanhead saying something like
! 688: * .c.o .c.o:
! 689: *
! 690: * We'll be called twice when the next target is seen, but .c and .o
! 691: * are only linked once...
! 692: */
! 693: SuffRemove(t->children, s);
! 694:
! 695: /*
! 696: * Remove the target from the source's parents list
! 697: */
! 698: SuffRemove(s->parents, t);
! 699: } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
! 700: printf("transformation %s complete\n", gn->name);
! 701: }
! 702:
! 703: return(dummy ? 0 : 0);
! 704: }
! 705:
! 706: /*-
! 707: *-----------------------------------------------------------------------
! 708: * SuffRebuildGraph --
! 709: * Called from Suff_AddSuffix via Lst_ForEach to search through the
! 710: * list of existing transformation rules and rebuild the transformation
! 711: * graph when it has been destroyed by Suff_ClearSuffixes. If the
! 712: * given rule is a transformation involving this suffix and another,
! 713: * existing suffix, the proper relationship is established between
! 714: * the two.
! 715: *
! 716: * Results:
! 717: * Always 0.
! 718: *
! 719: * Side Effects:
! 720: * The appropriate links will be made between this suffix and
! 721: * others if transformation rules exist for it.
! 722: *
! 723: *-----------------------------------------------------------------------
! 724: */
! 725: static int
! 726: SuffRebuildGraph(transformp, sp)
! 727: ClientData transformp; /* Transformation to test */
! 728: ClientData sp; /* Suffix to rebuild */
! 729: {
! 730: GNode *transform = (GNode *) transformp;
! 731: Suff *s = (Suff *) sp;
! 732: char *cp;
! 733: LstNode ln;
! 734: Suff *s2;
! 735:
! 736: /*
! 737: * First see if it is a transformation from this suffix.
! 738: */
! 739: cp = SuffStrIsPrefix(s->name, transform->name);
! 740: if (cp != (char *)NULL) {
! 741: ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffHasNameP);
! 742: if (ln != NILLNODE) {
! 743: /*
! 744: * Found target. Link in and return, since it can't be anything
! 745: * else.
! 746: */
! 747: s2 = (Suff *)Lst_Datum(ln);
! 748: SuffInsert(s2->children, s);
! 749: SuffInsert(s->parents, s2);
! 750: return(0);
! 751: }
! 752: }
! 753:
! 754: /*
! 755: * Not from, maybe to?
! 756: */
! 757: cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
! 758: if (cp != (char *)NULL) {
! 759: /*
! 760: * Null-terminate the source suffix in order to find it.
! 761: */
! 762: cp[1] = '\0';
! 763: ln = Lst_Find(sufflist, (ClientData)transform->name, SuffSuffHasNameP);
! 764: /*
! 765: * Replace the start of the target suffix
! 766: */
! 767: cp[1] = s->name[0];
! 768: if (ln != NILLNODE) {
! 769: /*
! 770: * Found it -- establish the proper relationship
! 771: */
! 772: s2 = (Suff *)Lst_Datum(ln);
! 773: SuffInsert(s->children, s2);
! 774: SuffInsert(s2->parents, s);
! 775: }
! 776: }
! 777: return(0);
! 778: }
! 779:
! 780: /*-
! 781: *-----------------------------------------------------------------------
! 782: * Suff_AddSuffix --
! 783: * Add the suffix in string to the end of the list of known suffixes.
! 784: * Should we restructure the suffix graph? Make doesn't...
! 785: *
! 786: * Results:
! 787: * None
! 788: *
! 789: * Side Effects:
! 790: * A GNode is created for the suffix and a Suff structure is created and
! 791: * added to the suffixes list unless the suffix was already known.
! 792: *-----------------------------------------------------------------------
! 793: */
! 794: void
! 795: Suff_AddSuffix (str)
! 796: char *str; /* the name of the suffix to add */
! 797: {
! 798: Suff *s; /* new suffix descriptor */
! 799: LstNode ln;
! 800:
! 801: ln = Lst_Find (sufflist, (ClientData)str, SuffSuffHasNameP);
! 802: if (ln == NILLNODE) {
! 803: s = (Suff *) emalloc (sizeof (Suff));
! 804:
! 805: s->name = strdup (str);
! 806: s->nameLen = strlen (s->name);
! 807: s->searchPath = Lst_Init (FALSE);
! 808: s->children = Lst_Init (FALSE);
! 809: s->parents = Lst_Init (FALSE);
! 810: s->ref = Lst_Init (FALSE);
! 811: s->sNum = sNum++;
! 812: s->flags = 0;
! 813: s->refCount = 0;
! 814:
! 815: (void)Lst_AtEnd (sufflist, (ClientData)s);
! 816: /*
! 817: * Look for any existing transformations from or to this suffix.
! 818: * XXX: Only do this after a Suff_ClearSuffixes?
! 819: */
! 820: Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s);
! 821: }
! 822: }
! 823:
! 824: /*-
! 825: *-----------------------------------------------------------------------
! 826: * Suff_GetPath --
! 827: * Return the search path for the given suffix, if it's defined.
! 828: *
! 829: * Results:
! 830: * The searchPath for the desired suffix or NILLST if the suffix isn't
! 831: * defined.
! 832: *
! 833: * Side Effects:
! 834: * None
! 835: *-----------------------------------------------------------------------
! 836: */
! 837: Lst
! 838: Suff_GetPath (sname)
! 839: char *sname;
! 840: {
! 841: LstNode ln;
! 842: Suff *s;
! 843:
! 844: ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
! 845: if (ln == NILLNODE) {
! 846: return (NILLST);
! 847: } else {
! 848: s = (Suff *) Lst_Datum (ln);
! 849: return (s->searchPath);
! 850: }
! 851: }
! 852:
! 853: /*-
! 854: *-----------------------------------------------------------------------
! 855: * Suff_DoPaths --
! 856: * Extend the search paths for all suffixes to include the default
! 857: * search path.
! 858: *
! 859: * Results:
! 860: * None.
! 861: *
! 862: * Side Effects:
! 863: * The searchPath field of all the suffixes is extended by the
! 864: * directories in dirSearchPath. If paths were specified for the
! 865: * ".h" suffix, the directories are stuffed into a global variable
! 866: * called ".INCLUDES" with each directory preceeded by a -I. The same
! 867: * is done for the ".a" suffix, except the variable is called
! 868: * ".LIBS" and the flag is -L.
! 869: *-----------------------------------------------------------------------
! 870: */
! 871: void
! 872: Suff_DoPaths()
! 873: {
! 874: register Suff *s;
! 875: register LstNode ln;
! 876: char *ptr;
! 877: Lst inIncludes; /* Cumulative .INCLUDES path */
! 878: Lst inLibs; /* Cumulative .LIBS path */
! 879:
! 880: if (Lst_Open (sufflist) == FAILURE) {
! 881: return;
! 882: }
! 883:
! 884: inIncludes = Lst_Init(FALSE);
! 885: inLibs = Lst_Init(FALSE);
! 886:
! 887: while ((ln = Lst_Next (sufflist)) != NILLNODE) {
! 888: s = (Suff *) Lst_Datum (ln);
! 889: if (!Lst_IsEmpty (s->searchPath)) {
! 890: #ifdef INCLUDES
! 891: if (s->flags & SUFF_INCLUDE) {
! 892: Dir_Concat(inIncludes, s->searchPath);
! 893: }
! 894: #endif /* INCLUDES */
! 895: #ifdef LIBRARIES
! 896: if (s->flags & SUFF_LIBRARY) {
! 897: Dir_Concat(inLibs, s->searchPath);
! 898: }
! 899: #endif /* LIBRARIES */
! 900: Dir_Concat(s->searchPath, dirSearchPath);
! 901: } else {
! 902: Lst_Destroy (s->searchPath, Dir_Destroy);
! 903: s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
! 904: }
! 905: }
! 906:
! 907: Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);
! 908: free(ptr);
! 909: Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
! 910: free(ptr);
! 911:
! 912: Lst_Destroy(inIncludes, Dir_Destroy);
! 913: Lst_Destroy(inLibs, Dir_Destroy);
! 914:
! 915: Lst_Close (sufflist);
! 916: }
! 917:
! 918: /*-
! 919: *-----------------------------------------------------------------------
! 920: * Suff_AddInclude --
! 921: * Add the given suffix as a type of file which gets included.
! 922: * Called from the parse module when a .INCLUDES line is parsed.
! 923: * The suffix must have already been defined.
! 924: *
! 925: * Results:
! 926: * None.
! 927: *
! 928: * Side Effects:
! 929: * The SUFF_INCLUDE bit is set in the suffix's flags field
! 930: *
! 931: *-----------------------------------------------------------------------
! 932: */
! 933: void
! 934: Suff_AddInclude (sname)
! 935: char *sname; /* Name of suffix to mark */
! 936: {
! 937: LstNode ln;
! 938: Suff *s;
! 939:
! 940: ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
! 941: if (ln != NILLNODE) {
! 942: s = (Suff *) Lst_Datum (ln);
! 943: s->flags |= SUFF_INCLUDE;
! 944: }
! 945: }
! 946:
! 947: /*-
! 948: *-----------------------------------------------------------------------
! 949: * Suff_AddLib --
! 950: * Add the given suffix as a type of file which is a library.
! 951: * Called from the parse module when parsing a .LIBS line. The
! 952: * suffix must have been defined via .SUFFIXES before this is
! 953: * called.
! 954: *
! 955: * Results:
! 956: * None.
! 957: *
! 958: * Side Effects:
! 959: * The SUFF_LIBRARY bit is set in the suffix's flags field
! 960: *
! 961: *-----------------------------------------------------------------------
! 962: */
! 963: void
! 964: Suff_AddLib (sname)
! 965: char *sname; /* Name of suffix to mark */
! 966: {
! 967: LstNode ln;
! 968: Suff *s;
! 969:
! 970: ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP);
! 971: if (ln != NILLNODE) {
! 972: s = (Suff *) Lst_Datum (ln);
! 973: s->flags |= SUFF_LIBRARY;
! 974: }
! 975: }
! 976:
! 977: /********** Implicit Source Search Functions *********/
! 978:
! 979: /*-
! 980: *-----------------------------------------------------------------------
! 981: * SuffAddSrc --
! 982: * Add a suffix as a Src structure to the given list with its parent
! 983: * being the given Src structure. If the suffix is the null suffix,
! 984: * the prefix is used unaltered as the file name in the Src structure.
! 985: *
! 986: * Results:
! 987: * always returns 0
! 988: *
! 989: * Side Effects:
! 990: * A Src structure is created and tacked onto the end of the list
! 991: *-----------------------------------------------------------------------
! 992: */
! 993: static int
! 994: SuffAddSrc (sp, lsp)
! 995: ClientData sp; /* suffix for which to create a Src structure */
! 996: ClientData lsp; /* list and parent for the new Src */
! 997: {
! 998: Suff *s = (Suff *) sp;
! 999: LstSrc *ls = (LstSrc *) lsp;
! 1000: Src *s2; /* new Src structure */
! 1001: Src *targ; /* Target structure */
! 1002:
! 1003: targ = ls->s;
! 1004:
! 1005: if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
! 1006: /*
! 1007: * If the suffix has been marked as the NULL suffix, also create a Src
! 1008: * structure for a file with no suffix attached. Two birds, and all
! 1009: * that...
! 1010: */
! 1011: s2 = (Src *) emalloc (sizeof (Src));
! 1012: s2->file = strdup(targ->pref);
! 1013: s2->pref = targ->pref;
! 1014: s2->parent = targ;
! 1015: s2->node = NILGNODE;
! 1016: s2->suff = s;
! 1017: s->refCount++;
! 1018: s2->children = 0;
! 1019: targ->children += 1;
! 1020: (void)Lst_AtEnd (ls->l, (ClientData)s2);
! 1021: #ifdef DEBUG_SRC
! 1022: s2->cp = Lst_Init(FALSE);
! 1023: Lst_AtEnd(targ->cp, (ClientData) s2);
! 1024: printf("1 add %x %x to %x:", targ, s2, ls->l);
! 1025: Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);
! 1026: printf("\n");
! 1027: #endif
! 1028: }
! 1029: s2 = (Src *) emalloc (sizeof (Src));
! 1030: s2->file = str_concat (targ->pref, s->name, 0);
! 1031: s2->pref = targ->pref;
! 1032: s2->parent = targ;
! 1033: s2->node = NILGNODE;
! 1034: s2->suff = s;
! 1035: s->refCount++;
! 1036: s2->children = 0;
! 1037: targ->children += 1;
! 1038: (void)Lst_AtEnd (ls->l, (ClientData)s2);
! 1039: #ifdef DEBUG_SRC
! 1040: s2->cp = Lst_Init(FALSE);
! 1041: Lst_AtEnd(targ->cp, (ClientData) s2);
! 1042: printf("2 add %x %x to %x:", targ, s2, ls->l);
! 1043: Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);
! 1044: printf("\n");
! 1045: #endif
! 1046:
! 1047: return(0);
! 1048: }
! 1049:
! 1050: /*-
! 1051: *-----------------------------------------------------------------------
! 1052: * SuffAddLevel --
! 1053: * Add all the children of targ as Src structures to the given list
! 1054: *
! 1055: * Results:
! 1056: * None
! 1057: *
! 1058: * Side Effects:
! 1059: * Lots of structures are created and added to the list
! 1060: *-----------------------------------------------------------------------
! 1061: */
! 1062: static void
! 1063: SuffAddLevel (l, targ)
! 1064: Lst l; /* list to which to add the new level */
! 1065: Src *targ; /* Src structure to use as the parent */
! 1066: {
! 1067: LstSrc ls;
! 1068:
! 1069: ls.s = targ;
! 1070: ls.l = l;
! 1071:
! 1072: Lst_ForEach (targ->suff->children, SuffAddSrc, (ClientData)&ls);
! 1073: }
! 1074:
! 1075: /*-
! 1076: *----------------------------------------------------------------------
! 1077: * SuffRemoveSrc --
! 1078: * Free all src structures in list that don't have a reference count
! 1079: *
! 1080: * Results:
! 1081: * Ture if an src was removed
! 1082: *
! 1083: * Side Effects:
! 1084: * The memory is free'd.
! 1085: *----------------------------------------------------------------------
! 1086: */
! 1087: static int
! 1088: SuffRemoveSrc (l)
! 1089: Lst l;
! 1090: {
! 1091: LstNode ln;
! 1092: Src *s;
! 1093: int t = 0;
! 1094:
! 1095: if (Lst_Open (l) == FAILURE) {
! 1096: return 0;
! 1097: }
! 1098: #ifdef DEBUG_SRC
! 1099: printf("cleaning %lx: ", (unsigned long) l);
! 1100: Lst_ForEach(l, PrintAddr, (ClientData) 0);
! 1101: printf("\n");
! 1102: #endif
! 1103:
! 1104:
! 1105: while ((ln = Lst_Next (l)) != NILLNODE) {
! 1106: s = (Src *) Lst_Datum (ln);
! 1107: if (s->children == 0) {
! 1108: free ((Address)s->file);
! 1109: if (!s->parent)
! 1110: free((Address)s->pref);
! 1111: else {
! 1112: #ifdef DEBUG_SRC
! 1113: LstNode ln = Lst_Member(s->parent->cp, (ClientData)s);
! 1114: if (ln != NILLNODE)
! 1115: Lst_Remove(s->parent->cp, ln);
! 1116: #endif
! 1117: --s->parent->children;
! 1118: }
! 1119: #ifdef DEBUG_SRC
! 1120: printf("free: [l=%x] p=%x %d\n", l, s, s->children);
! 1121: Lst_Destroy(s->cp, NOFREE);
! 1122: #endif
! 1123: Lst_Remove(l, ln);
! 1124: free ((Address)s);
! 1125: t |= 1;
! 1126: Lst_Close(l);
! 1127: return TRUE;
! 1128: }
! 1129: #ifdef DEBUG_SRC
! 1130: else {
! 1131: printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
! 1132: Lst_ForEach(s->cp, PrintAddr, (ClientData) 0);
! 1133: printf("\n");
! 1134: }
! 1135: #endif
! 1136: }
! 1137:
! 1138: Lst_Close(l);
! 1139:
! 1140: return t;
! 1141: }
! 1142:
! 1143: /*-
! 1144: *-----------------------------------------------------------------------
! 1145: * SuffFindThem --
! 1146: * Find the first existing file/target in the list srcs
! 1147: *
! 1148: * Results:
! 1149: * The lowest structure in the chain of transformations
! 1150: *
! 1151: * Side Effects:
! 1152: * None
! 1153: *-----------------------------------------------------------------------
! 1154: */
! 1155: static Src *
! 1156: SuffFindThem (srcs, slst)
! 1157: Lst srcs; /* list of Src structures to search through */
! 1158: Lst slst;
! 1159: {
! 1160: Src *s; /* current Src */
! 1161: Src *rs; /* returned Src */
! 1162: char *ptr;
! 1163:
! 1164: rs = (Src *) NULL;
! 1165:
! 1166: while (!Lst_IsEmpty (srcs)) {
! 1167: s = (Src *) Lst_DeQueue (srcs);
! 1168:
! 1169: if (DEBUG(SUFF)) {
! 1170: printf ("\ttrying %s...", s->file);
! 1171: }
! 1172:
! 1173: /*
! 1174: * A file is considered to exist if either a node exists in the
! 1175: * graph for it or the file actually exists.
! 1176: */
! 1177: if (Targ_FindNode(s->file, TARG_NOCREATE) != NILGNODE) {
! 1178: #ifdef DEBUG_SRC
! 1179: printf("remove %x from %x\n", s, srcs);
! 1180: #endif
! 1181: rs = s;
! 1182: break;
! 1183: }
! 1184:
! 1185: if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {
! 1186: rs = s;
! 1187: #ifdef DEBUG_SRC
! 1188: printf("remove %x from %x\n", s, srcs);
! 1189: #endif
! 1190: free(ptr);
! 1191: break;
! 1192: }
! 1193:
! 1194: if (DEBUG(SUFF)) {
! 1195: printf ("not there\n");
! 1196: }
! 1197:
! 1198: SuffAddLevel (srcs, s);
! 1199: Lst_AtEnd(slst, (ClientData) s);
! 1200: }
! 1201:
! 1202: if (DEBUG(SUFF) && rs) {
! 1203: printf ("got it\n");
! 1204: }
! 1205: return (rs);
! 1206: }
! 1207:
! 1208: /*-
! 1209: *-----------------------------------------------------------------------
! 1210: * SuffFindCmds --
! 1211: * See if any of the children of the target in the Src structure is
! 1212: * one from which the target can be transformed. If there is one,
! 1213: * a Src structure is put together for it and returned.
! 1214: *
! 1215: * Results:
! 1216: * The Src structure of the "winning" child, or NIL if no such beast.
! 1217: *
! 1218: * Side Effects:
! 1219: * A Src structure may be allocated.
! 1220: *
! 1221: *-----------------------------------------------------------------------
! 1222: */
! 1223: static Src *
! 1224: SuffFindCmds (targ, slst)
! 1225: Src *targ; /* Src structure to play with */
! 1226: Lst slst;
! 1227: {
! 1228: LstNode ln; /* General-purpose list node */
! 1229: register GNode *t, /* Target GNode */
! 1230: *s; /* Source GNode */
! 1231: int prefLen;/* The length of the defined prefix */
! 1232: Suff *suff; /* Suffix on matching beastie */
! 1233: Src *ret; /* Return value */
! 1234: char *cp;
! 1235:
! 1236: t = targ->node;
! 1237: (void) Lst_Open (t->children);
! 1238: prefLen = strlen (targ->pref);
! 1239:
! 1240: while ((ln = Lst_Next (t->children)) != NILLNODE) {
! 1241: s = (GNode *)Lst_Datum (ln);
! 1242:
! 1243: cp = strrchr (s->name, '/');
! 1244: if (cp == (char *)NULL) {
! 1245: cp = s->name;
! 1246: } else {
! 1247: cp++;
! 1248: }
! 1249: if (strncmp (cp, targ->pref, prefLen) == 0) {
! 1250: /*
! 1251: * The node matches the prefix ok, see if it has a known
! 1252: * suffix.
! 1253: */
! 1254: ln = Lst_Find (sufflist, (ClientData)&cp[prefLen],
! 1255: SuffSuffHasNameP);
! 1256: if (ln != NILLNODE) {
! 1257: /*
! 1258: * It even has a known suffix, see if there's a transformation
! 1259: * defined between the node's suffix and the target's suffix.
! 1260: *
! 1261: * XXX: Handle multi-stage transformations here, too.
! 1262: */
! 1263: suff = (Suff *)Lst_Datum (ln);
! 1264:
! 1265: if (Lst_Member (suff->parents,
! 1266: (ClientData)targ->suff) != NILLNODE)
! 1267: {
! 1268: /*
! 1269: * Hot Damn! Create a new Src structure to describe
! 1270: * this transformation (making sure to duplicate the
! 1271: * source node's name so Suff_FindDeps can free it
! 1272: * again (ick)), and return the new structure.
! 1273: */
! 1274: ret = (Src *)emalloc (sizeof (Src));
! 1275: ret->file = strdup(s->name);
! 1276: ret->pref = targ->pref;
! 1277: ret->suff = suff;
! 1278: suff->refCount++;
! 1279: ret->parent = targ;
! 1280: ret->node = s;
! 1281: ret->children = 0;
! 1282: targ->children += 1;
! 1283: #ifdef DEBUG_SRC
! 1284: ret->cp = Lst_Init(FALSE);
! 1285: printf("3 add %x %x\n", targ, ret);
! 1286: Lst_AtEnd(targ->cp, (ClientData) ret);
! 1287: #endif
! 1288: Lst_AtEnd(slst, (ClientData) ret);
! 1289: if (DEBUG(SUFF)) {
! 1290: printf ("\tusing existing source %s\n", s->name);
! 1291: }
! 1292: return (ret);
! 1293: }
! 1294: }
! 1295: }
! 1296: }
! 1297: Lst_Close (t->children);
! 1298: return ((Src *)NULL);
! 1299: }
! 1300:
! 1301: /*-
! 1302: *-----------------------------------------------------------------------
! 1303: * SuffExpandChildren --
! 1304: * Expand the names of any children of a given node that contain
! 1305: * variable invocations or file wildcards into actual targets.
! 1306: *
! 1307: * Results:
! 1308: * === 0 (continue)
! 1309: *
! 1310: * Side Effects:
! 1311: * The expanded node is removed from the parent's list of children,
! 1312: * and the parent's unmade counter is decremented, but other nodes
! 1313: * may be added.
! 1314: *
! 1315: *-----------------------------------------------------------------------
! 1316: */
! 1317: static int
! 1318: SuffExpandChildren(cgnp, pgnp)
! 1319: ClientData cgnp; /* Child to examine */
! 1320: ClientData pgnp; /* Parent node being processed */
! 1321: {
! 1322: GNode *cgn = (GNode *) cgnp;
! 1323: GNode *pgn = (GNode *) pgnp;
! 1324: GNode *gn; /* New source 8) */
! 1325: LstNode prevLN; /* Node after which new source should be put */
! 1326: LstNode ln; /* List element for old source */
! 1327: char *cp; /* Expanded value */
! 1328:
! 1329: /*
! 1330: * New nodes effectively take the place of the child, so place them
! 1331: * after the child
! 1332: */
! 1333: prevLN = Lst_Member(pgn->children, (ClientData)cgn);
! 1334:
! 1335: /*
! 1336: * First do variable expansion -- this takes precedence over
! 1337: * wildcard expansion. If the result contains wildcards, they'll be gotten
! 1338: * to later since the resulting words are tacked on to the end of
! 1339: * the children list.
! 1340: */
! 1341: if (strchr(cgn->name, '$') != (char *)NULL) {
! 1342: if (DEBUG(SUFF)) {
! 1343: printf("Expanding \"%s\"...", cgn->name);
! 1344: }
! 1345: cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
! 1346:
! 1347: if (cp != (char *)NULL) {
! 1348: Lst members = Lst_Init(FALSE);
! 1349:
! 1350: if (cgn->type & OP_ARCHV) {
! 1351: /*
! 1352: * Node was an archive(member) target, so we want to call
! 1353: * on the Arch module to find the nodes for us, expanding
! 1354: * variables in the parent's context.
! 1355: */
! 1356: char *sacrifice = cp;
! 1357:
! 1358: (void)Arch_ParseArchive(&sacrifice, members, pgn);
! 1359: } else {
! 1360: /*
! 1361: * Break the result into a vector of strings whose nodes
! 1362: * we can find, then add those nodes to the members list.
! 1363: * Unfortunately, we can't use brk_string b/c it
! 1364: * doesn't understand about variable specifications with
! 1365: * spaces in them...
! 1366: */
! 1367: char *start;
! 1368: char *initcp = cp; /* For freeing... */
! 1369:
! 1370: for (start = cp; *start == ' ' || *start == '\t'; start++)
! 1371: continue;
! 1372: for (cp = start; *cp != '\0'; cp++) {
! 1373: if (*cp == ' ' || *cp == '\t') {
! 1374: /*
! 1375: * White-space -- terminate element, find the node,
! 1376: * add it, skip any further spaces.
! 1377: */
! 1378: *cp++ = '\0';
! 1379: gn = Targ_FindNode(start, TARG_CREATE);
! 1380: (void)Lst_AtEnd(members, (ClientData)gn);
! 1381: while (*cp == ' ' || *cp == '\t') {
! 1382: cp++;
! 1383: }
! 1384: /*
! 1385: * Adjust cp for increment at start of loop, but
! 1386: * set start to first non-space.
! 1387: */
! 1388: start = cp--;
! 1389: } else if (*cp == '$') {
! 1390: /*
! 1391: * Start of a variable spec -- contact variable module
! 1392: * to find the end so we can skip over it.
! 1393: */
! 1394: char *junk;
! 1395: int len;
! 1396: Boolean doFree;
! 1397:
! 1398: junk = Var_Parse(cp, pgn, TRUE, &len, &doFree);
! 1399: if (junk != var_Error) {
! 1400: cp += len - 1;
! 1401: }
! 1402:
! 1403: if (doFree) {
! 1404: free(junk);
! 1405: }
! 1406: } else if (*cp == '\\' && *cp != '\0') {
! 1407: /*
! 1408: * Escaped something -- skip over it
! 1409: */
! 1410: cp++;
! 1411: }
! 1412: }
! 1413:
! 1414: if (cp != start) {
! 1415: /*
! 1416: * Stuff left over -- add it to the list too
! 1417: */
! 1418: gn = Targ_FindNode(start, TARG_CREATE);
! 1419: (void)Lst_AtEnd(members, (ClientData)gn);
! 1420: }
! 1421: /*
! 1422: * Point cp back at the beginning again so the variable value
! 1423: * can be freed.
! 1424: */
! 1425: cp = initcp;
! 1426: }
! 1427: /*
! 1428: * Add all elements of the members list to the parent node.
! 1429: */
! 1430: while (!Lst_IsEmpty(members)) {
! 1431: gn = (GNode *)Lst_DeQueue(members);
! 1432:
! 1433: if (DEBUG(SUFF)) {
! 1434: printf("%s...", gn->name);
! 1435: }
! 1436: if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
! 1437: (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
! 1438: prevLN = Lst_Succ(prevLN);
! 1439: (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
! 1440: pgn->unmade++;
! 1441: }
! 1442: }
! 1443: Lst_Destroy(members, NOFREE);
! 1444: /*
! 1445: * Free the result
! 1446: */
! 1447: free((char *)cp);
! 1448: }
! 1449: /*
! 1450: * Now the source is expanded, remove it from the list of children to
! 1451: * keep it from being processed.
! 1452: */
! 1453: ln = Lst_Member(pgn->children, (ClientData)cgn);
! 1454: pgn->unmade--;
! 1455: Lst_Remove(pgn->children, ln);
! 1456: if (DEBUG(SUFF)) {
! 1457: printf("\n");
! 1458: }
! 1459: } else if (Dir_HasWildcards(cgn->name)) {
! 1460: Lst exp; /* List of expansions */
! 1461: Lst path; /* Search path along which to expand */
! 1462:
! 1463: /*
! 1464: * Find a path along which to expand the word.
! 1465: *
! 1466: * If the word has a known suffix, use that path.
! 1467: * If it has no known suffix and we're allowed to use the null
! 1468: * suffix, use its path.
! 1469: * Else use the default system search path.
! 1470: */
! 1471: cp = cgn->name + strlen(cgn->name);
! 1472: ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffIsSuffixP);
! 1473:
! 1474: if (DEBUG(SUFF)) {
! 1475: printf("Wildcard expanding \"%s\"...", cgn->name);
! 1476: }
! 1477:
! 1478: if (ln != NILLNODE) {
! 1479: Suff *s = (Suff *)Lst_Datum(ln);
! 1480:
! 1481: if (DEBUG(SUFF)) {
! 1482: printf("suffix is \"%s\"...", s->name);
! 1483: }
! 1484: path = s->searchPath;
! 1485: } else {
! 1486: /*
! 1487: * Use default search path
! 1488: */
! 1489: path = dirSearchPath;
! 1490: }
! 1491:
! 1492: /*
! 1493: * Expand the word along the chosen path
! 1494: */
! 1495: exp = Lst_Init(FALSE);
! 1496: Dir_Expand(cgn->name, path, exp);
! 1497:
! 1498: while (!Lst_IsEmpty(exp)) {
! 1499: /*
! 1500: * Fetch next expansion off the list and find its GNode
! 1501: */
! 1502: cp = (char *)Lst_DeQueue(exp);
! 1503:
! 1504: if (DEBUG(SUFF)) {
! 1505: printf("%s...", cp);
! 1506: }
! 1507: gn = Targ_FindNode(cp, TARG_CREATE);
! 1508:
! 1509: /*
! 1510: * If gn isn't already a child of the parent, make it so and
! 1511: * up the parent's count of unmade children.
! 1512: */
! 1513: if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) {
! 1514: (void)Lst_Append(pgn->children, prevLN, (ClientData)gn);
! 1515: prevLN = Lst_Succ(prevLN);
! 1516: (void)Lst_AtEnd(gn->parents, (ClientData)pgn);
! 1517: pgn->unmade++;
! 1518: }
! 1519: }
! 1520:
! 1521: /*
! 1522: * Nuke what's left of the list
! 1523: */
! 1524: Lst_Destroy(exp, NOFREE);
! 1525:
! 1526: /*
! 1527: * Now the source is expanded, remove it from the list of children to
! 1528: * keep it from being processed.
! 1529: */
! 1530: ln = Lst_Member(pgn->children, (ClientData)cgn);
! 1531: pgn->unmade--;
! 1532: Lst_Remove(pgn->children, ln);
! 1533: if (DEBUG(SUFF)) {
! 1534: printf("\n");
! 1535: }
! 1536: }
! 1537:
! 1538: return(0);
! 1539: }
! 1540:
! 1541: /*-
! 1542: *-----------------------------------------------------------------------
! 1543: * SuffApplyTransform --
! 1544: * Apply a transformation rule, given the source and target nodes
! 1545: * and suffixes.
! 1546: *
! 1547: * Results:
! 1548: * TRUE if successful, FALSE if not.
! 1549: *
! 1550: * Side Effects:
! 1551: * The source and target are linked and the commands from the
! 1552: * transformation are added to the target node's commands list.
! 1553: * All attributes but OP_DEPMASK and OP_TRANSFORM are applied
! 1554: * to the target. The target also inherits all the sources for
! 1555: * the transformation rule.
! 1556: *
! 1557: *-----------------------------------------------------------------------
! 1558: */
! 1559: static Boolean
! 1560: SuffApplyTransform(tGn, sGn, t, s)
! 1561: GNode *tGn; /* Target node */
! 1562: GNode *sGn; /* Source node */
! 1563: Suff *t; /* Target suffix */
! 1564: Suff *s; /* Source suffix */
! 1565: {
! 1566: LstNode ln; /* General node */
! 1567: char *tname; /* Name of transformation rule */
! 1568: GNode *gn; /* Node for same */
! 1569:
! 1570: if (Lst_Member(tGn->children, (ClientData)sGn) == NILLNODE) {
! 1571: /*
! 1572: * Not already linked, so form the proper links between the
! 1573: * target and source.
! 1574: */
! 1575: (void)Lst_AtEnd(tGn->children, (ClientData)sGn);
! 1576: (void)Lst_AtEnd(sGn->parents, (ClientData)tGn);
! 1577: tGn->unmade += 1;
! 1578: }
! 1579:
! 1580: if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
! 1581: /*
! 1582: * When a :: node is used as the implied source of a node, we have
! 1583: * to link all its cohorts in as sources as well. Only the initial
! 1584: * sGn gets the target in its iParents list, however, as that
! 1585: * will be sufficient to get the .IMPSRC variable set for tGn
! 1586: */
! 1587: for (ln=Lst_First(sGn->cohorts); ln != NILLNODE; ln=Lst_Succ(ln)) {
! 1588: gn = (GNode *)Lst_Datum(ln);
! 1589:
! 1590: if (Lst_Member(tGn->children, (ClientData)gn) == NILLNODE) {
! 1591: /*
! 1592: * Not already linked, so form the proper links between the
! 1593: * target and source.
! 1594: */
! 1595: (void)Lst_AtEnd(tGn->children, (ClientData)gn);
! 1596: (void)Lst_AtEnd(gn->parents, (ClientData)tGn);
! 1597: tGn->unmade += 1;
! 1598: }
! 1599: }
! 1600: }
! 1601: /*
! 1602: * Locate the transformation rule itself
! 1603: */
! 1604: tname = str_concat(s->name, t->name, 0);
! 1605: ln = Lst_Find(transforms, (ClientData)tname, SuffGNHasNameP);
! 1606: free(tname);
! 1607:
! 1608: if (ln == NILLNODE) {
! 1609: /*
! 1610: * Not really such a transformation rule (can happen when we're
! 1611: * called to link an OP_MEMBER and OP_ARCHV node), so return
! 1612: * FALSE.
! 1613: */
! 1614: return(FALSE);
! 1615: }
! 1616:
! 1617: gn = (GNode *)Lst_Datum(ln);
! 1618:
! 1619: if (DEBUG(SUFF)) {
! 1620: printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
! 1621: }
! 1622:
! 1623: /*
! 1624: * Record last child for expansion purposes
! 1625: */
! 1626: ln = Lst_Last(tGn->children);
! 1627:
! 1628: /*
! 1629: * Pass the buck to Make_HandleUse to apply the rule
! 1630: */
! 1631: (void)Make_HandleUse(gn, tGn);
! 1632:
! 1633: /*
! 1634: * Deal with wildcards and variables in any acquired sources
! 1635: */
! 1636: ln = Lst_Succ(ln);
! 1637: if (ln != NILLNODE) {
! 1638: Lst_ForEachFrom(tGn->children, ln,
! 1639: SuffExpandChildren, (ClientData)tGn);
! 1640: }
! 1641:
! 1642: /*
! 1643: * Keep track of another parent to which this beast is transformed so
! 1644: * the .IMPSRC variable can be set correctly for the parent.
! 1645: */
! 1646: (void)Lst_AtEnd(sGn->iParents, (ClientData)tGn);
! 1647:
! 1648: return(TRUE);
! 1649: }
! 1650:
! 1651:
! 1652: /*-
! 1653: *-----------------------------------------------------------------------
! 1654: * SuffFindArchiveDeps --
! 1655: * Locate dependencies for an OP_ARCHV node.
! 1656: *
! 1657: * Results:
! 1658: * None
! 1659: *
! 1660: * Side Effects:
! 1661: * Same as Suff_FindDeps
! 1662: *
! 1663: *-----------------------------------------------------------------------
! 1664: */
! 1665: static void
! 1666: SuffFindArchiveDeps(gn, slst)
! 1667: GNode *gn; /* Node for which to locate dependencies */
! 1668: Lst slst;
! 1669: {
! 1670: char *eoarch; /* End of archive portion */
! 1671: char *eoname; /* End of member portion */
! 1672: GNode *mem; /* Node for member */
! 1673: static char *copy[] = { /* Variables to be copied from the member node */
! 1674: TARGET, /* Must be first */
! 1675: PREFIX, /* Must be second */
! 1676: };
! 1677: int i; /* Index into copy and vals */
! 1678: Suff *ms; /* Suffix descriptor for member */
! 1679: char *name; /* Start of member's name */
! 1680:
! 1681: /*
! 1682: * The node is an archive(member) pair. so we must find a
! 1683: * suffix for both of them.
! 1684: */
! 1685: eoarch = strchr (gn->name, '(');
! 1686: eoname = strchr (eoarch, ')');
! 1687:
! 1688: *eoname = '\0'; /* Nuke parentheses during suffix search */
! 1689: *eoarch = '\0'; /* So a suffix can be found */
! 1690:
! 1691: name = eoarch + 1;
! 1692:
! 1693: /*
! 1694: * To simplify things, call Suff_FindDeps recursively on the member now,
! 1695: * so we can simply compare the member's .PREFIX and .TARGET variables
! 1696: * to locate its suffix. This allows us to figure out the suffix to
! 1697: * use for the archive without having to do a quadratic search over the
! 1698: * suffix list, backtracking for each one...
! 1699: */
! 1700: mem = Targ_FindNode(name, TARG_CREATE);
! 1701: SuffFindDeps(mem, slst);
! 1702:
! 1703: /*
! 1704: * Create the link between the two nodes right off
! 1705: */
! 1706: if (Lst_Member(gn->children, (ClientData)mem) == NILLNODE) {
! 1707: (void)Lst_AtEnd(gn->children, (ClientData)mem);
! 1708: (void)Lst_AtEnd(mem->parents, (ClientData)gn);
! 1709: gn->unmade += 1;
! 1710: }
! 1711:
! 1712: /*
! 1713: * Copy in the variables from the member node to this one.
! 1714: */
! 1715: for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
! 1716: char *p1;
! 1717: Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn);
! 1718: if (p1)
! 1719: free(p1);
! 1720:
! 1721: }
! 1722:
! 1723: ms = mem->suffix;
! 1724: if (ms == NULL) {
! 1725: /*
! 1726: * Didn't know what it was -- use .NULL suffix if not in make mode
! 1727: */
! 1728: if (DEBUG(SUFF)) {
! 1729: printf("using null suffix\n");
! 1730: }
! 1731: ms = suffNull;
! 1732: }
! 1733:
! 1734:
! 1735: /*
! 1736: * Set the other two local variables required for this target.
! 1737: */
! 1738: Var_Set (MEMBER, name, gn);
! 1739: Var_Set (ARCHIVE, gn->name, gn);
! 1740:
! 1741: if (ms != NULL) {
! 1742: /*
! 1743: * Member has a known suffix, so look for a transformation rule from
! 1744: * it to a possible suffix of the archive. Rather than searching
! 1745: * through the entire list, we just look at suffixes to which the
! 1746: * member's suffix may be transformed...
! 1747: */
! 1748: LstNode ln;
! 1749:
! 1750: /*
! 1751: * Use first matching suffix...
! 1752: */
! 1753: ln = Lst_Find(ms->parents, eoarch, SuffSuffIsSuffixP);
! 1754:
! 1755: if (ln != NILLNODE) {
! 1756: /*
! 1757: * Got one -- apply it
! 1758: */
! 1759: if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms) &&
! 1760: DEBUG(SUFF))
! 1761: {
! 1762: printf("\tNo transformation from %s -> %s\n",
! 1763: ms->name, ((Suff *)Lst_Datum(ln))->name);
! 1764: }
! 1765: }
! 1766: }
! 1767:
! 1768: /*
! 1769: * Replace the opening and closing parens now we've no need of the separate
! 1770: * pieces.
! 1771: */
! 1772: *eoarch = '('; *eoname = ')';
! 1773:
! 1774: /*
! 1775: * Pretend gn appeared to the left of a dependency operator so
! 1776: * the user needn't provide a transformation from the member to the
! 1777: * archive.
! 1778: */
! 1779: if (OP_NOP(gn->type)) {
! 1780: gn->type |= OP_DEPENDS;
! 1781: }
! 1782:
! 1783: /*
! 1784: * Flag the member as such so we remember to look in the archive for
! 1785: * its modification time.
! 1786: */
! 1787: mem->type |= OP_MEMBER;
! 1788: }
! 1789:
! 1790: /*-
! 1791: *-----------------------------------------------------------------------
! 1792: * SuffFindNormalDeps --
! 1793: * Locate implicit dependencies for regular targets.
! 1794: *
! 1795: * Results:
! 1796: * None.
! 1797: *
! 1798: * Side Effects:
! 1799: * Same as Suff_FindDeps...
! 1800: *
! 1801: *-----------------------------------------------------------------------
! 1802: */
! 1803: static void
! 1804: SuffFindNormalDeps(gn, slst)
! 1805: GNode *gn; /* Node for which to find sources */
! 1806: Lst slst;
! 1807: {
! 1808: char *eoname; /* End of name */
! 1809: char *sopref; /* Start of prefix */
! 1810: LstNode ln; /* Next suffix node to check */
! 1811: Lst srcs; /* List of sources at which to look */
! 1812: Lst targs; /* List of targets to which things can be
! 1813: * transformed. They all have the same file,
! 1814: * but different suff and pref fields */
! 1815: Src *bottom; /* Start of found transformation path */
! 1816: Src *src; /* General Src pointer */
! 1817: char *pref; /* Prefix to use */
! 1818: Src *targ; /* General Src target pointer */
! 1819:
! 1820:
! 1821: eoname = gn->name + strlen(gn->name);
! 1822:
! 1823: sopref = gn->name;
! 1824:
! 1825: /*
! 1826: * Begin at the beginning...
! 1827: */
! 1828: ln = Lst_First(sufflist);
! 1829: srcs = Lst_Init(FALSE);
! 1830: targs = Lst_Init(FALSE);
! 1831:
! 1832: /*
! 1833: * We're caught in a catch-22 here. On the one hand, we want to use any
! 1834: * transformation implied by the target's sources, but we can't examine
! 1835: * the sources until we've expanded any variables/wildcards they may hold,
! 1836: * and we can't do that until we've set up the target's local variables
! 1837: * and we can't do that until we know what the proper suffix for the
! 1838: * target is (in case there are two suffixes one of which is a suffix of
! 1839: * the other) and we can't know that until we've found its implied
! 1840: * source, which we may not want to use if there's an existing source
! 1841: * that implies a different transformation.
! 1842: *
! 1843: * In an attempt to get around this, which may not work all the time,
! 1844: * but should work most of the time, we look for implied sources first,
! 1845: * checking transformations to all possible suffixes of the target,
! 1846: * use what we find to set the target's local variables, expand the
! 1847: * children, then look for any overriding transformations they imply.
! 1848: * Should we find one, we discard the one we found before.
! 1849: */
! 1850:
! 1851: while (ln != NILLNODE) {
! 1852: /*
! 1853: * Look for next possible suffix...
! 1854: */
! 1855: ln = Lst_FindFrom(sufflist, ln, eoname, SuffSuffIsSuffixP);
! 1856:
! 1857: if (ln != NILLNODE) {
! 1858: int prefLen; /* Length of the prefix */
! 1859: Src *targ;
! 1860:
! 1861: /*
! 1862: * Allocate a Src structure to which things can be transformed
! 1863: */
! 1864: targ = (Src *)emalloc(sizeof (Src));
! 1865: targ->file = strdup(gn->name);
! 1866: targ->suff = (Suff *)Lst_Datum(ln);
! 1867: targ->suff->refCount++;
! 1868: targ->node = gn;
! 1869: targ->parent = (Src *)NULL;
! 1870: targ->children = 0;
! 1871: #ifdef DEBUG_SRC
! 1872: targ->cp = Lst_Init(FALSE);
! 1873: #endif
! 1874:
! 1875: /*
! 1876: * Allocate room for the prefix, whose end is found by subtracting
! 1877: * the length of the suffix from the end of the name.
! 1878: */
! 1879: prefLen = (eoname - targ->suff->nameLen) - sopref;
! 1880: targ->pref = emalloc(prefLen + 1);
! 1881: memcpy(targ->pref, sopref, prefLen);
! 1882: targ->pref[prefLen] = '\0';
! 1883:
! 1884: /*
! 1885: * Add nodes from which the target can be made
! 1886: */
! 1887: SuffAddLevel(srcs, targ);
! 1888:
! 1889: /*
! 1890: * Record the target so we can nuke it
! 1891: */
! 1892: (void)Lst_AtEnd(targs, (ClientData)targ);
! 1893:
! 1894: /*
! 1895: * Search from this suffix's successor...
! 1896: */
! 1897: ln = Lst_Succ(ln);
! 1898: }
! 1899: }
! 1900:
! 1901: /*
! 1902: * Handle target of unknown suffix...
! 1903: */
! 1904: if (Lst_IsEmpty(targs) && suffNull != NULL) {
! 1905: if (DEBUG(SUFF)) {
! 1906: printf("\tNo known suffix on %s. Using .NULL suffix: ", gn->name);
! 1907: }
! 1908:
! 1909: targ = (Src *)emalloc(sizeof (Src));
! 1910: targ->file = strdup(gn->name);
! 1911: targ->suff = suffNull;
! 1912: targ->suff->refCount++;
! 1913: targ->node = gn;
! 1914: targ->parent = (Src *)NULL;
! 1915: targ->children = 0;
! 1916: targ->pref = strdup(sopref);
! 1917: #ifdef DEBUG_SRC
! 1918: targ->cp = Lst_Init(FALSE);
! 1919: #endif
! 1920:
! 1921: /*
! 1922: * Only use the default suffix rules if we don't have commands
! 1923: * or dependencies defined for this gnode
! 1924: */
! 1925: if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
! 1926: SuffAddLevel(srcs, targ);
! 1927: else {
! 1928: if (DEBUG(SUFF))
! 1929: printf("not ");
! 1930: }
! 1931:
! 1932: if (DEBUG(SUFF))
! 1933: printf("adding suffix rules\n");
! 1934:
! 1935: (void)Lst_AtEnd(targs, (ClientData)targ);
! 1936: }
! 1937:
! 1938: /*
! 1939: * Using the list of possible sources built up from the target suffix(es),
! 1940: * try and find an existing file/target that matches.
! 1941: */
! 1942: bottom = SuffFindThem(srcs, slst);
! 1943:
! 1944: if (bottom == (Src *)NULL) {
! 1945: /*
! 1946: * No known transformations -- use the first suffix found for setting
! 1947: * the local variables.
! 1948: */
! 1949: if (!Lst_IsEmpty(targs)) {
! 1950: targ = (Src *)Lst_Datum(Lst_First(targs));
! 1951: } else {
! 1952: targ = (Src *)NULL;
! 1953: }
! 1954: } else {
! 1955: /*
! 1956: * Work up the transformation path to find the suffix of the
! 1957: * target to which the transformation was made.
! 1958: */
! 1959: for (targ = bottom; targ->parent != NULL; targ = targ->parent)
! 1960: continue;
! 1961: }
! 1962:
! 1963: /*
! 1964: * The .TARGET variable we always set to be the name at this point,
! 1965: * since it's only set to the path if the thing is only a source and
! 1966: * if it's only a source, it doesn't matter what we put here as far
! 1967: * as expanding sources is concerned, since it has none...
! 1968: */
! 1969: Var_Set(TARGET, gn->name, gn);
! 1970:
! 1971: pref = (targ != NULL) ? targ->pref : gn->name;
! 1972: Var_Set(PREFIX, pref, gn);
! 1973:
! 1974: /*
! 1975: * Now we've got the important local variables set, expand any sources
! 1976: * that still contain variables or wildcards in their names.
! 1977: */
! 1978: Lst_ForEach(gn->children, SuffExpandChildren, (ClientData)gn);
! 1979:
! 1980: if (targ == NULL) {
! 1981: if (DEBUG(SUFF)) {
! 1982: printf("\tNo valid suffix on %s\n", gn->name);
! 1983: }
! 1984:
! 1985: sfnd_abort:
! 1986: /*
! 1987: * Deal with finding the thing on the default search path if the
! 1988: * node is only a source (not on the lhs of a dependency operator
! 1989: * or [XXX] it has neither children or commands).
! 1990: */
! 1991: if (OP_NOP(gn->type) ||
! 1992: (Lst_IsEmpty(gn->children) && Lst_IsEmpty(gn->commands)))
! 1993: {
! 1994: gn->path = Dir_FindFile(gn->name,
! 1995: (targ == NULL ? dirSearchPath :
! 1996: targ->suff->searchPath));
! 1997: if (gn->path != NULL) {
! 1998: Var_Set(TARGET, gn->path, gn);
! 1999:
! 2000: if (targ != NULL) {
! 2001: /*
! 2002: * Suffix known for the thing -- trim the suffix off
! 2003: * the path to form the proper .PREFIX variable.
! 2004: */
! 2005: int len = strlen(gn->path);
! 2006: char savec;
! 2007:
! 2008: if (gn->suffix)
! 2009: gn->suffix->refCount--;
! 2010: gn->suffix = targ->suff;
! 2011: gn->suffix->refCount++;
! 2012:
! 2013: savec = gn->path[len-targ->suff->nameLen];
! 2014: gn->path[len-targ->suff->nameLen] = '\0';
! 2015:
! 2016: Var_Set(PREFIX, gn->path, gn);
! 2017:
! 2018: gn->path[len-targ->suff->nameLen] = savec;
! 2019: } else {
! 2020: /*
! 2021: * The .PREFIX gets the full path if the target has
! 2022: * no known suffix.
! 2023: */
! 2024: if (gn->suffix)
! 2025: gn->suffix->refCount--;
! 2026: gn->suffix = NULL;
! 2027:
! 2028: Var_Set(PREFIX, gn->path, gn);
! 2029: }
! 2030: }
! 2031: } else {
! 2032: /*
! 2033: * Not appropriate to search for the thing -- set the
! 2034: * path to be the name so Dir_MTime won't go grovelling for
! 2035: * it.
! 2036: */
! 2037: if (gn->suffix)
! 2038: gn->suffix->refCount--;
! 2039: gn->suffix = (targ == NULL) ? NULL : targ->suff;
! 2040: if (gn->suffix)
! 2041: gn->suffix->refCount++;
! 2042: if (gn->path != NULL)
! 2043: free(gn->path);
! 2044: gn->path = strdup(gn->name);
! 2045: }
! 2046:
! 2047: goto sfnd_return;
! 2048: }
! 2049:
! 2050: /*
! 2051: * If the suffix indicates that the target is a library, mark that in
! 2052: * the node's type field.
! 2053: */
! 2054: if (targ->suff->flags & SUFF_LIBRARY) {
! 2055: gn->type |= OP_LIB;
! 2056: }
! 2057:
! 2058: /*
! 2059: * Check for overriding transformation rule implied by sources
! 2060: */
! 2061: if (!Lst_IsEmpty(gn->children)) {
! 2062: src = SuffFindCmds(targ, slst);
! 2063:
! 2064: if (src != (Src *)NULL) {
! 2065: /*
! 2066: * Free up all the Src structures in the transformation path
! 2067: * up to, but not including, the parent node.
! 2068: */
! 2069: while (bottom && bottom->parent != NULL) {
! 2070: if (Lst_Member(slst, (ClientData) bottom) == NILLNODE) {
! 2071: Lst_AtEnd(slst, (ClientData) bottom);
! 2072: }
! 2073: bottom = bottom->parent;
! 2074: }
! 2075: bottom = src;
! 2076: }
! 2077: }
! 2078:
! 2079: if (bottom == NULL) {
! 2080: /*
! 2081: * No idea from where it can come -- return now.
! 2082: */
! 2083: goto sfnd_abort;
! 2084: }
! 2085:
! 2086: /*
! 2087: * We now have a list of Src structures headed by 'bottom' and linked via
! 2088: * their 'parent' pointers. What we do next is create links between
! 2089: * source and target nodes (which may or may not have been created)
! 2090: * and set the necessary local variables in each target. The
! 2091: * commands for each target are set from the commands of the
! 2092: * transformation rule used to get from the src suffix to the targ
! 2093: * suffix. Note that this causes the commands list of the original
! 2094: * node, gn, to be replaced by the commands of the final
! 2095: * transformation rule. Also, the unmade field of gn is incremented.
! 2096: * Etc.
! 2097: */
! 2098: if (bottom->node == NILGNODE) {
! 2099: bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
! 2100: }
! 2101:
! 2102: for (src = bottom; src->parent != (Src *)NULL; src = src->parent) {
! 2103: targ = src->parent;
! 2104:
! 2105: if (src->node->suffix)
! 2106: src->node->suffix->refCount--;
! 2107: src->node->suffix = src->suff;
! 2108: src->node->suffix->refCount++;
! 2109:
! 2110: if (targ->node == NILGNODE) {
! 2111: targ->node = Targ_FindNode(targ->file, TARG_CREATE);
! 2112: }
! 2113:
! 2114: SuffApplyTransform(targ->node, src->node,
! 2115: targ->suff, src->suff);
! 2116:
! 2117: if (targ->node != gn) {
! 2118: /*
! 2119: * Finish off the dependency-search process for any nodes
! 2120: * between bottom and gn (no point in questing around the
! 2121: * filesystem for their implicit source when it's already
! 2122: * known). Note that the node can't have any sources that
! 2123: * need expanding, since SuffFindThem will stop on an existing
! 2124: * node, so all we need to do is set the standard and System V
! 2125: * variables.
! 2126: */
! 2127: targ->node->type |= OP_DEPS_FOUND;
! 2128:
! 2129: Var_Set(PREFIX, targ->pref, targ->node);
! 2130:
! 2131: Var_Set(TARGET, targ->node->name, targ->node);
! 2132: }
! 2133: }
! 2134:
! 2135: if (gn->suffix)
! 2136: gn->suffix->refCount--;
! 2137: gn->suffix = src->suff;
! 2138: gn->suffix->refCount++;
! 2139:
! 2140: /*
! 2141: * So Dir_MTime doesn't go questing for it...
! 2142: */
! 2143: if (gn->path)
! 2144: free(gn->path);
! 2145: gn->path = strdup(gn->name);
! 2146:
! 2147: /*
! 2148: * Nuke the transformation path and the Src structures left over in the
! 2149: * two lists.
! 2150: */
! 2151: sfnd_return:
! 2152: if (bottom)
! 2153: if (Lst_Member(slst, (ClientData) bottom) == NILLNODE)
! 2154: Lst_AtEnd(slst, (ClientData) bottom);
! 2155:
! 2156: while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
! 2157: continue;
! 2158:
! 2159: Lst_Concat(slst, srcs, LST_CONCLINK);
! 2160: Lst_Concat(slst, targs, LST_CONCLINK);
! 2161: }
! 2162:
! 2163:
! 2164: /*-
! 2165: *-----------------------------------------------------------------------
! 2166: * Suff_FindDeps --
! 2167: * Find implicit sources for the target described by the graph node
! 2168: * gn
! 2169: *
! 2170: * Results:
! 2171: * Nothing.
! 2172: *
! 2173: * Side Effects:
! 2174: * Nodes are added to the graph below the passed-in node. The nodes
! 2175: * are marked to have their IMPSRC variable filled in. The
! 2176: * PREFIX variable is set for the given node and all its
! 2177: * implied children.
! 2178: *
! 2179: * Notes:
! 2180: * The path found by this target is the shortest path in the
! 2181: * transformation graph, which may pass through non-existent targets,
! 2182: * to an existing target. The search continues on all paths from the
! 2183: * root suffix until a file is found. I.e. if there's a path
! 2184: * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
! 2185: * the .c and .l files don't, the search will branch out in
! 2186: * all directions from .o and again from all the nodes on the
! 2187: * next level until the .l,v node is encountered.
! 2188: *
! 2189: *-----------------------------------------------------------------------
! 2190: */
! 2191:
! 2192: void
! 2193: Suff_FindDeps(gn)
! 2194: GNode *gn;
! 2195: {
! 2196:
! 2197: SuffFindDeps(gn, srclist);
! 2198: while (SuffRemoveSrc(srclist))
! 2199: continue;
! 2200: }
! 2201:
! 2202:
! 2203: static void
! 2204: SuffFindDeps (gn, slst)
! 2205: GNode *gn; /* node we're dealing with */
! 2206: Lst slst;
! 2207: {
! 2208: if (gn->type & OP_DEPS_FOUND) {
! 2209: /*
! 2210: * If dependencies already found, no need to do it again...
! 2211: */
! 2212: return;
! 2213: } else {
! 2214: gn->type |= OP_DEPS_FOUND;
! 2215: }
! 2216:
! 2217: if (DEBUG(SUFF)) {
! 2218: printf ("SuffFindDeps (%s)\n", gn->name);
! 2219: }
! 2220:
! 2221: if (gn->type & OP_ARCHV) {
! 2222: SuffFindArchiveDeps(gn, slst);
! 2223: } else if (gn->type & OP_LIB) {
! 2224: /*
! 2225: * If the node is a library, it is the arch module's job to find it
! 2226: * and set the TARGET variable accordingly. We merely provide the
! 2227: * search path, assuming all libraries end in ".a" (if the suffix
! 2228: * hasn't been defined, there's nothing we can do for it, so we just
! 2229: * set the TARGET variable to the node's name in order to give it a
! 2230: * value).
! 2231: */
! 2232: LstNode ln;
! 2233: Suff *s;
! 2234:
! 2235: ln = Lst_Find (sufflist, (ClientData)LIBSUFF, SuffSuffHasNameP);
! 2236: if (gn->suffix)
! 2237: gn->suffix->refCount--;
! 2238: if (ln != NILLNODE) {
! 2239: gn->suffix = s = (Suff *) Lst_Datum (ln);
! 2240: gn->suffix->refCount++;
! 2241: Arch_FindLib (gn, s->searchPath);
! 2242: } else {
! 2243: gn->suffix = NULL;
! 2244: Var_Set (TARGET, gn->name, gn);
! 2245: }
! 2246: /*
! 2247: * Because a library (-lfoo) target doesn't follow the standard
! 2248: * filesystem conventions, we don't set the regular variables for
! 2249: * the thing. .PREFIX is simply made empty...
! 2250: */
! 2251: Var_Set(PREFIX, "", gn);
! 2252: } else {
! 2253: SuffFindNormalDeps(gn, slst);
! 2254: }
! 2255: }
! 2256:
! 2257: /*-
! 2258: *-----------------------------------------------------------------------
! 2259: * Suff_SetNull --
! 2260: * Define which suffix is the null suffix.
! 2261: *
! 2262: * Results:
! 2263: * None.
! 2264: *
! 2265: * Side Effects:
! 2266: * 'suffNull' is altered.
! 2267: *
! 2268: * Notes:
! 2269: * Need to handle the changing of the null suffix gracefully so the
! 2270: * old transformation rules don't just go away.
! 2271: *
! 2272: *-----------------------------------------------------------------------
! 2273: */
! 2274: void
! 2275: Suff_SetNull(name)
! 2276: char *name; /* Name of null suffix */
! 2277: {
! 2278: Suff *s;
! 2279: LstNode ln;
! 2280:
! 2281: ln = Lst_Find(sufflist, (ClientData)name, SuffSuffHasNameP);
! 2282: if (ln != NILLNODE) {
! 2283: s = (Suff *)Lst_Datum(ln);
! 2284: if (suffNull != (Suff *)NULL) {
! 2285: suffNull->flags &= ~SUFF_NULL;
! 2286: }
! 2287: s->flags |= SUFF_NULL;
! 2288: /*
! 2289: * XXX: Here's where the transformation mangling would take place
! 2290: */
! 2291: suffNull = s;
! 2292: } else {
! 2293: Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",
! 2294: name);
! 2295: }
! 2296: }
! 2297:
! 2298: /*-
! 2299: *-----------------------------------------------------------------------
! 2300: * Suff_Init --
! 2301: * Initialize suffixes module
! 2302: *
! 2303: * Results:
! 2304: * None
! 2305: *
! 2306: * Side Effects:
! 2307: * Many
! 2308: *-----------------------------------------------------------------------
! 2309: */
! 2310: void
! 2311: Suff_Init ()
! 2312: {
! 2313: sufflist = Lst_Init (FALSE);
! 2314: suffClean = Lst_Init(FALSE);
! 2315: srclist = Lst_Init (FALSE);
! 2316: transforms = Lst_Init (FALSE);
! 2317:
! 2318: sNum = 0;
! 2319: /*
! 2320: * Create null suffix for single-suffix rules (POSIX). The thing doesn't
! 2321: * actually go on the suffix list or everyone will think that's its
! 2322: * suffix.
! 2323: */
! 2324: emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));
! 2325:
! 2326: suffNull->name = strdup ("");
! 2327: suffNull->nameLen = 0;
! 2328: suffNull->searchPath = Lst_Init (FALSE);
! 2329: Dir_Concat(suffNull->searchPath, dirSearchPath);
! 2330: suffNull->children = Lst_Init (FALSE);
! 2331: suffNull->parents = Lst_Init (FALSE);
! 2332: suffNull->ref = Lst_Init (FALSE);
! 2333: suffNull->sNum = sNum++;
! 2334: suffNull->flags = SUFF_NULL;
! 2335: suffNull->refCount = 1;
! 2336:
! 2337: }
! 2338:
! 2339:
! 2340: /*-
! 2341: *----------------------------------------------------------------------
! 2342: * Suff_End --
! 2343: * Cleanup the this module
! 2344: *
! 2345: * Results:
! 2346: * None
! 2347: *
! 2348: * Side Effects:
! 2349: * The memory is free'd.
! 2350: *----------------------------------------------------------------------
! 2351: */
! 2352:
! 2353: void
! 2354: Suff_End()
! 2355: {
! 2356: Lst_Destroy(sufflist, SuffFree);
! 2357: Lst_Destroy(suffClean, SuffFree);
! 2358: if (suffNull)
! 2359: SuffFree(suffNull);
! 2360: Lst_Destroy(srclist, NOFREE);
! 2361: Lst_Destroy(transforms, NOFREE);
! 2362: }
! 2363:
! 2364:
! 2365: /********************* DEBUGGING FUNCTIONS **********************/
! 2366:
! 2367: static int SuffPrintName(s, dummy)
! 2368: ClientData s;
! 2369: ClientData dummy;
! 2370: {
! 2371: printf ("%s ", ((Suff *) s)->name);
! 2372: return (dummy ? 0 : 0);
! 2373: }
! 2374:
! 2375: static int
! 2376: SuffPrintSuff (sp, dummy)
! 2377: ClientData sp;
! 2378: ClientData dummy;
! 2379: {
! 2380: Suff *s = (Suff *) sp;
! 2381: int flags;
! 2382: int flag;
! 2383:
! 2384: printf ("# `%s' [%d] ", s->name, s->refCount);
! 2385:
! 2386: flags = s->flags;
! 2387: if (flags) {
! 2388: fputs (" (", stdout);
! 2389: while (flags) {
! 2390: flag = 1 << (ffs(flags) - 1);
! 2391: flags &= ~flag;
! 2392: switch (flag) {
! 2393: case SUFF_NULL:
! 2394: printf ("NULL");
! 2395: break;
! 2396: case SUFF_INCLUDE:
! 2397: printf ("INCLUDE");
! 2398: break;
! 2399: case SUFF_LIBRARY:
! 2400: printf ("LIBRARY");
! 2401: break;
! 2402: }
! 2403: fputc(flags ? '|' : ')', stdout);
! 2404: }
! 2405: }
! 2406: fputc ('\n', stdout);
! 2407: printf ("#\tTo: ");
! 2408: Lst_ForEach (s->parents, SuffPrintName, (ClientData)0);
! 2409: fputc ('\n', stdout);
! 2410: printf ("#\tFrom: ");
! 2411: Lst_ForEach (s->children, SuffPrintName, (ClientData)0);
! 2412: fputc ('\n', stdout);
! 2413: printf ("#\tSearch Path: ");
! 2414: Dir_PrintPath (s->searchPath);
! 2415: fputc ('\n', stdout);
! 2416: return (dummy ? 0 : 0);
! 2417: }
! 2418:
! 2419: static int
! 2420: SuffPrintTrans (tp, dummy)
! 2421: ClientData tp;
! 2422: ClientData dummy;
! 2423: {
! 2424: GNode *t = (GNode *) tp;
! 2425:
! 2426: printf ("%-16s: ", t->name);
! 2427: Targ_PrintType (t->type);
! 2428: fputc ('\n', stdout);
! 2429: Lst_ForEach (t->commands, Targ_PrintCmd, (ClientData)0);
! 2430: fputc ('\n', stdout);
! 2431: return(dummy ? 0 : 0);
! 2432: }
! 2433:
! 2434: void
! 2435: Suff_PrintAll()
! 2436: {
! 2437: printf ("#*** Suffixes:\n");
! 2438: Lst_ForEach (sufflist, SuffPrintSuff, (ClientData)0);
! 2439:
! 2440: printf ("#*** Transformations:\n");
! 2441: Lst_ForEach (transforms, SuffPrintTrans, (ClientData)0);
! 2442: }