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