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