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