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