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