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