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