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