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