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