1 /* 2 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 3 * Copyright (c) 1988, 1989 by Adam de Boor 4 * Copyright (c) 1989 by Berkeley Softworks 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 */ 38 39 #ifndef lint 40 static char sccsid[] = "@(#)suff.c 5.6 (Berkeley) 6/1/90"; 41 #endif /* not lint */ 42 43 /*- 44 * suff.c -- 45 * Functions to maintain suffix lists and find implicit dependents 46 * using suffix transformation rules 47 * 48 * Interface: 49 * Suff_Init Initialize all things to do with suffixes. 50 * 51 * Suff_DoPaths This function is used to make life easier 52 * when searching for a file according to its 53 * suffix. It takes the global search path, 54 * as defined using the .PATH: target, and appends 55 * its directories to the path of each of the 56 * defined suffixes, as specified using 57 * .PATH<suffix>: targets. In addition, all 58 * directories given for suffixes labeled as 59 * include files or libraries, using the .INCLUDES 60 * or .LIBS targets, are played with using 61 * Dir_MakeFlags to create the .INCLUDES and 62 * .LIBS global variables. 63 * 64 * Suff_ClearSuffixes Clear out all the suffixes and defined 65 * transformations. 66 * 67 * Suff_IsTransform Return TRUE if the passed string is the lhs 68 * of a transformation rule. 69 * 70 * Suff_AddSuffix Add the passed string as another known suffix. 71 * 72 * Suff_GetPath Return the search path for the given suffix. 73 * 74 * Suff_AddInclude Mark the given suffix as denoting an include 75 * file. 76 * 77 * Suff_AddLib Mark the given suffix as denoting a library. 78 * 79 * Suff_AddTransform Add another transformation to the suffix 80 * graph. Returns GNode suitable for framing, I 81 * mean, tacking commands, attributes, etc. on. 82 * 83 * Suff_SetNull Define the suffix to consider the suffix of 84 * any file that doesn't have a known one. 85 * 86 * Suff_FindDeps Find implicit sources for and the location of 87 * a target based on its suffix. Returns the 88 * bottom-most node added to the graph or NILGNODE 89 * if the target had no implicit sources. 90 */ 91 92 #include <stdio.h> 93 #include "make.h" 94 #include "bit.h" 95 96 static Lst sufflist; /* Lst of suffixes */ 97 static Lst transforms; /* Lst of transformation rules */ 98 99 static int sNum = 0; /* Counter for assigning suffix numbers */ 100 101 /* 102 * Structure describing an individual suffix. 103 */ 104 typedef struct _Suff { 105 char *name; /* The suffix itself */ 106 int nameLen; /* Length of the suffix */ 107 short flags; /* Type of suffix */ 108 #define SUFF_INCLUDE 0x01 /* One which is #include'd */ 109 #define SUFF_LIBRARY 0x02 /* One which contains a library */ 110 #define SUFF_NULL 0x04 /* The empty suffix */ 111 Lst searchPath; /* The path along which files of this suffix 112 * may be found */ 113 int sNum; /* The suffix number */ 114 Lst parents; /* Suffixes we have a transformation to */ 115 Lst children; /* Suffixes we have a transformation from */ 116 } Suff; 117 118 /* 119 * Structure used in the search for implied sources. 120 */ 121 typedef struct _Src { 122 char *file; /* The file to look for */ 123 char *pref; /* Prefix from which file was formed */ 124 Suff *suff; /* The suffix on the file */ 125 struct _Src *parent; /* The Src for which this is a source */ 126 GNode *node; /* The node describing the file */ 127 int children; /* Count of existing children (so we don't free 128 * this thing too early or never nuke it) */ 129 } Src; 130 131 static Suff *suffNull; /* The NULL suffix for this run */ 132 static Suff *emptySuff; /* The empty suffix required for POSIX 133 * single-suffix transformation rules */ 134 135 /*************** Lst Predicates ****************/ 136 /*- 137 *----------------------------------------------------------------------- 138 * SuffStrIsPrefix -- 139 * See if pref is a prefix of str. 140 * 141 * Results: 142 * NULL if it ain't, pointer to character in str after prefix if so 143 * 144 * Side Effects: 145 * None 146 *----------------------------------------------------------------------- 147 */ 148 static char * 149 SuffStrIsPrefix (pref, str) 150 register char *pref; /* possible prefix */ 151 register char *str; /* string to check */ 152 { 153 while (*str && *pref == *str) { 154 pref++; 155 str++; 156 } 157 158 return (*pref ? NULL : str); 159 } 160 161 /*- 162 *----------------------------------------------------------------------- 163 * SuffSuffIsSuffix -- 164 * See if suff is a suffix of str. Str should point to THE END of the 165 * string to check. (THE END == the null byte) 166 * 167 * Results: 168 * NULL if it ain't, pointer to character in str before suffix if 169 * it is. 170 * 171 * Side Effects: 172 * None 173 *----------------------------------------------------------------------- 174 */ 175 static char * 176 SuffSuffIsSuffix (s, str) 177 register Suff *s; /* possible suffix */ 178 char *str; /* string to examine */ 179 { 180 register char *p1; /* Pointer into suffix name */ 181 register char *p2; /* Pointer into string being examined */ 182 183 p1 = s->name + s->nameLen; 184 p2 = str; 185 186 while (p1 >= s->name && *p1 == *p2) { 187 p1--; 188 p2--; 189 } 190 191 return (p1 == s->name - 1 ? p2 : NULL); 192 } 193 194 /*- 195 *----------------------------------------------------------------------- 196 * SuffSuffIsSuffixP -- 197 * Predicate form of SuffSuffIsSuffix. Passed as the callback function 198 * to Lst_Find. 199 * 200 * Results: 201 * 0 if the suffix is the one desired, non-zero if not. 202 * 203 * Side Effects: 204 * None. 205 * 206 *----------------------------------------------------------------------- 207 */ 208 SuffSuffIsSuffixP(s, str) 209 Suff *s; 210 char *str; 211 { 212 return(!SuffSuffIsSuffix(s, str)); 213 } 214 215 /*- 216 *----------------------------------------------------------------------- 217 * SuffSuffHasNameP -- 218 * Callback procedure for finding a suffix based on its name. Used by 219 * Suff_GetPath. 220 * 221 * Results: 222 * 0 if the suffix is of the given name. non-zero otherwise. 223 * 224 * Side Effects: 225 * None 226 *----------------------------------------------------------------------- 227 */ 228 static int 229 SuffSuffHasNameP (s, sname) 230 Suff *s; /* Suffix to check */ 231 char *sname; /* Desired name */ 232 { 233 return (strcmp (sname, s->name)); 234 } 235 236 /*- 237 *----------------------------------------------------------------------- 238 * SuffSuffIsPrefix -- 239 * See if the suffix described by s is a prefix of the string. Care 240 * must be taken when using this to search for transformations and 241 * what-not, since there could well be two suffixes, one of which 242 * is a prefix of the other... 243 * 244 * Results: 245 * 0 if s is a prefix of str. non-zero otherwise 246 * 247 * Side Effects: 248 * None 249 *----------------------------------------------------------------------- 250 */ 251 static int 252 SuffSuffIsPrefix (s, str) 253 Suff *s; /* suffix to compare */ 254 char *str; /* string to examine */ 255 { 256 return (SuffStrIsPrefix (s->name, str) == NULL ? 1 : 0); 257 } 258 259 /*- 260 *----------------------------------------------------------------------- 261 * SuffGNHasNameP -- 262 * See if the graph node has the desired name 263 * 264 * Results: 265 * 0 if it does. non-zero if it doesn't 266 * 267 * Side Effects: 268 * None 269 *----------------------------------------------------------------------- 270 */ 271 static int 272 SuffGNHasNameP (gn, name) 273 GNode *gn; /* current node we're looking at */ 274 char *name; /* name we're looking for */ 275 { 276 return (strcmp (name, gn->name)); 277 } 278 279 /*********** Maintenance Functions ************/ 280 /*- 281 *----------------------------------------------------------------------- 282 * SuffFree -- 283 * Free up all memory associated with the given suffix structure. 284 * 285 * Results: 286 * none 287 * 288 * Side Effects: 289 * the suffix entry is detroyed 290 *----------------------------------------------------------------------- 291 */ 292 static void 293 SuffFree (s) 294 Suff *s; 295 { 296 Lst_Destroy (s->children, NOFREE); 297 Lst_Destroy (s->parents, NOFREE); 298 Lst_Destroy (s->searchPath, Dir_Destroy); 299 free ((Address)s->name); 300 free ((Address)s); 301 } 302 303 /*- 304 *----------------------------------------------------------------------- 305 * SuffInsert -- 306 * Insert the suffix into the list keeping the list ordered by suffix 307 * numbers. 308 * 309 * Results: 310 * None 311 * 312 * Side Effects: 313 * Not really 314 *----------------------------------------------------------------------- 315 */ 316 static void 317 SuffInsert (l, s) 318 Lst l; /* the list where in s should be inserted */ 319 Suff *s; /* the suffix to insert */ 320 { 321 LstNode ln; /* current element in l we're examining */ 322 Suff *s2; /* the suffix descriptor in this element */ 323 324 if (Lst_Open (l) == FAILURE) { 325 return; 326 } 327 while ((ln = Lst_Next (l)) != NILLNODE) { 328 s2 = (Suff *) Lst_Datum (ln); 329 if (s2->sNum >= s->sNum) { 330 break; 331 } 332 } 333 334 Lst_Close (l); 335 if (DEBUG(SUFF)) { 336 printf("inserting %s(%d)...", s->name, s->sNum); 337 } 338 if (ln == NILLNODE) { 339 if (DEBUG(SUFF)) { 340 printf("at end of list\n"); 341 } 342 (void)Lst_AtEnd (l, (ClientData)s); 343 } else if (s2->sNum != s->sNum) { 344 if (DEBUG(SUFF)) { 345 printf("before %s(%d)\n", s2->name, s2->sNum); 346 } 347 (void)Lst_Insert (l, ln, (ClientData)s); 348 } else if (DEBUG(SUFF)) { 349 printf("already there\n"); 350 } 351 } 352 353 /*- 354 *----------------------------------------------------------------------- 355 * Suff_ClearSuffixes -- 356 * This is gross. Nuke the list of suffixes but keep all transformation 357 * rules around. The transformation graph is destroyed in this process, 358 * but we leave the list of rules so when a new graph is formed the rules 359 * will remain. 360 * This function is called from the parse module when a 361 * .SUFFIXES:\n line is encountered. 362 * 363 * Results: 364 * none 365 * 366 * Side Effects: 367 * the sufflist and its graph nodes are destroyed 368 *----------------------------------------------------------------------- 369 */ 370 void 371 Suff_ClearSuffixes () 372 { 373 Lst_Destroy (sufflist, SuffFree); 374 375 sufflist = Lst_Init(FALSE); 376 sNum = 0; 377 suffNull = emptySuff; 378 } 379 380 /*- 381 *----------------------------------------------------------------------- 382 * SuffParseTransform -- 383 * Parse a transformation string to find its two component suffixes. 384 * 385 * Results: 386 * TRUE if the string is a valid transformation and FALSE otherwise. 387 * 388 * Side Effects: 389 * The passed pointers are overwritten. 390 * 391 *----------------------------------------------------------------------- 392 */ 393 static Boolean 394 SuffParseTransform(str, srcPtr, targPtr) 395 char *str; /* String being parsed */ 396 Suff **srcPtr; /* Place to store source of trans. */ 397 Suff **targPtr; /* Place to store target of trans. */ 398 { 399 register LstNode srcLn; /* element in suffix list of trans source*/ 400 register Suff *src; /* Source of transformation */ 401 register LstNode targLn; /* element in suffix list of trans target*/ 402 register char *str2; /* Extra pointer (maybe target suffix) */ 403 LstNode singleLn; /* element in suffix list of any suffix 404 * that exactly matches str */ 405 Suff *single; /* Source of possible transformation to 406 * null suffix */ 407 408 srcLn = NILLNODE; 409 singleLn = NILLNODE; 410 411 /* 412 * Loop looking first for a suffix that matches the start of the 413 * string and then for one that exactly matches the rest of it. If 414 * we can find two that meet these criteria, we've successfully 415 * parsed the string. 416 */ 417 while (1) { 418 if (srcLn == NILLNODE) { 419 srcLn = Lst_Find(sufflist, (ClientData)str, SuffSuffIsPrefix); 420 } else { 421 srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (ClientData)str, 422 SuffSuffIsPrefix); 423 } 424 if (srcLn == NILLNODE) { 425 /* 426 * Ran out of source suffixes -- no such rule 427 */ 428 if (singleLn != NILLNODE) { 429 /* 430 * Not so fast Mr. Smith! There was a suffix that encompassed 431 * the entire string, so we assume it was a transformation 432 * to the null suffix (thank you POSIX). We still prefer to 433 * find a double rule over a singleton, hence we leave this 434 * check until the end. 435 * 436 * XXX: Use emptySuff over suffNull? 437 */ 438 *srcPtr = single; 439 *targPtr = suffNull; 440 return(TRUE); 441 } 442 return (FALSE); 443 } 444 src = (Suff *) Lst_Datum (srcLn); 445 str2 = str + src->nameLen; 446 if (*str2 == '\0') { 447 single = src; 448 singleLn = srcLn; 449 } else { 450 targLn = Lst_Find(sufflist, (ClientData)str2, SuffSuffHasNameP); 451 if (targLn != NILLNODE) { 452 *srcPtr = src; 453 *targPtr = (Suff *)Lst_Datum(targLn); 454 return (TRUE); 455 } 456 } 457 } 458 } 459 460 /*- 461 *----------------------------------------------------------------------- 462 * Suff_IsTransform -- 463 * Return TRUE if the given string is a transformation rule 464 * 465 * 466 * Results: 467 * TRUE if the string is a concatenation of two known suffixes. 468 * FALSE otherwise 469 * 470 * Side Effects: 471 * None 472 *----------------------------------------------------------------------- 473 */ 474 Boolean 475 Suff_IsTransform (str) 476 char *str; /* string to check */ 477 { 478 Suff *src, *targ; 479 480 return (SuffParseTransform(str, &src, &targ)); 481 } 482 483 /*- 484 *----------------------------------------------------------------------- 485 * Suff_AddTransform -- 486 * Add the transformation rule described by the line to the 487 * list of rules and place the transformation itself in the graph 488 * 489 * Results: 490 * The node created for the transformation in the transforms list 491 * 492 * Side Effects: 493 * The node is placed on the end of the transforms Lst and links are 494 * made between the two suffixes mentioned in the target name 495 *----------------------------------------------------------------------- 496 */ 497 GNode * 498 Suff_AddTransform (line) 499 char *line; /* name of transformation to add */ 500 { 501 GNode *gn; /* GNode of transformation rule */ 502 Suff *s, /* source suffix */ 503 *t; /* target suffix */ 504 LstNode ln; /* Node for existing transformation */ 505 506 ln = Lst_Find (transforms, (ClientData)line, SuffGNHasNameP); 507 if (ln == NILLNODE) { 508 /* 509 * Make a new graph node for the transformation. It will be filled in 510 * by the Parse module. 511 */ 512 gn = Targ_NewGN (line); 513 (void)Lst_AtEnd (transforms, (ClientData)gn); 514 } else { 515 /* 516 * New specification for transformation rule. Just nuke the old list 517 * of commands so they can be filled in again... We don't actually 518 * free the commands themselves, because a given command can be 519 * attached to several different transformations. 520 */ 521 gn = (GNode *) Lst_Datum (ln); 522 Lst_Destroy (gn->commands, NOFREE); 523 Lst_Destroy (gn->children, NOFREE); 524 gn->commands = Lst_Init (FALSE); 525 gn->children = Lst_Init (FALSE); 526 } 527 528 gn->type = OP_TRANSFORM; 529 530 (void)SuffParseTransform(line, &s, &t); 531 532 /* 533 * link the two together in the proper relationship and order 534 */ 535 if (DEBUG(SUFF)) { 536 printf("defining transformation from `%s' to `%s'\n", 537 s->name, t->name); 538 } 539 SuffInsert (t->children, s); 540 SuffInsert (s->parents, t); 541 542 return (gn); 543 } 544 545 /*- 546 *----------------------------------------------------------------------- 547 * Suff_EndTransform -- 548 * Handle the finish of a transformation definition, removing the 549 * transformation from the graph if it has neither commands nor 550 * sources. This is a callback procedure for the Parse module via 551 * Lst_ForEach 552 * 553 * Results: 554 * === 0 555 * 556 * Side Effects: 557 * If the node has no commands or children, the children and parents 558 * lists of the affected suffices are altered. 559 * 560 *----------------------------------------------------------------------- 561 */ 562 int 563 Suff_EndTransform(gn) 564 GNode *gn; /* Node for transformation */ 565 { 566 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) && 567 Lst_IsEmpty(gn->children)) 568 { 569 Suff *s, *t; 570 LstNode ln; 571 572 (void)SuffParseTransform(gn->name, &s, &t); 573 574 if (DEBUG(SUFF)) { 575 printf("deleting transformation from %s to %s\n", 576 s->name, t->name); 577 } 578 579 /* 580 * Remove the source from the target's children list. We check for a 581 * nil return to handle a beanhead saying something like 582 * .c.o .c.o: 583 * 584 * We'll be called twice when the next target is seen, but .c and .o 585 * are only linked once... 586 */ 587 ln = Lst_Member(t->children, (ClientData)s); 588 if (ln != NILLNODE) { 589 (void)Lst_Remove(t->children, ln); 590 } 591 592 /* 593 * Remove the target from the source's parents list 594 */ 595 ln = Lst_Member(s->parents, (ClientData)t); 596 if (ln != NILLNODE) { 597 (void)Lst_Remove(s->parents, ln); 598 } 599 } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) { 600 printf("transformation %s complete\n", gn->name); 601 } 602 603 return(0); 604 } 605 606 /*- 607 *----------------------------------------------------------------------- 608 * SuffRebuildGraph -- 609 * Called from Suff_AddSuffix via Lst_ForEach to search through the 610 * list of existing transformation rules and rebuild the transformation 611 * graph when it has been destroyed by Suff_ClearSuffixes. If the 612 * given rule is a transformation involving this suffix and another, 613 * existing suffix, the proper relationship is established between 614 * the two. 615 * 616 * Results: 617 * Always 0. 618 * 619 * Side Effects: 620 * The appropriate links will be made between this suffix and 621 * others if transformation rules exist for it. 622 * 623 *----------------------------------------------------------------------- 624 */ 625 static int 626 SuffRebuildGraph(transform, s) 627 GNode *transform; /* Transformation to test */ 628 Suff *s; /* Suffix to rebuild */ 629 { 630 register char *cp; 631 register LstNode ln; 632 register Suff *s2; 633 634 /* 635 * First see if it is a transformation from this suffix. 636 */ 637 cp = SuffStrIsPrefix(s->name, transform->name); 638 if (cp != (char *)NULL) { 639 ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffHasNameP); 640 if (ln != NILLNODE) { 641 /* 642 * Found target. Link in and return, since it can't be anything 643 * else. 644 */ 645 s2 = (Suff *)Lst_Datum(ln); 646 SuffInsert(s2->children, s); 647 SuffInsert(s->parents, s2); 648 return(0); 649 } 650 } 651 652 /* 653 * Not from, maybe to? 654 */ 655 cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name)); 656 if (cp != (char *)NULL) { 657 /* 658 * Null-terminate the source suffix in order to find it. 659 */ 660 cp[1] = '\0'; 661 ln = Lst_Find(sufflist, (ClientData)transform->name, SuffSuffHasNameP); 662 /* 663 * Replace the start of the target suffix 664 */ 665 cp[1] = s->name[0]; 666 if (ln != NILLNODE) { 667 /* 668 * Found it -- establish the proper relationship 669 */ 670 s2 = (Suff *)Lst_Datum(ln); 671 SuffInsert(s->children, s2); 672 SuffInsert(s2->parents, s); 673 } 674 } 675 return(0); 676 } 677 678 /*- 679 *----------------------------------------------------------------------- 680 * Suff_AddSuffix -- 681 * Add the suffix in string to the end of the list of known suffixes. 682 * Should we restructure the suffix graph? Make doesn't... 683 * 684 * Results: 685 * None 686 * 687 * Side Effects: 688 * A GNode is created for the suffix and a Suff structure is created and 689 * added to the suffixes list unless the suffix was already known. 690 *----------------------------------------------------------------------- 691 */ 692 void 693 Suff_AddSuffix (str) 694 char *str; /* the name of the suffix to add */ 695 { 696 Suff *s; /* new suffix descriptor */ 697 LstNode ln; 698 699 ln = Lst_Find (sufflist, (ClientData)str, SuffSuffHasNameP); 700 if (ln == NILLNODE) { 701 s = (Suff *) emalloc (sizeof (Suff)); 702 703 s->name = strdup (str); 704 s->nameLen = strlen (s->name); 705 s->searchPath = Lst_Init (FALSE); 706 s->children = Lst_Init (FALSE); 707 s->parents = Lst_Init (FALSE); 708 s->sNum = sNum++; 709 s->flags = 0; 710 711 (void)Lst_AtEnd (sufflist, (ClientData)s); 712 /* 713 * Look for any existing transformations from or to this suffix. 714 * XXX: Only do this after a Suff_ClearSuffixes? 715 */ 716 Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s); 717 } 718 } 719 720 /*- 721 *----------------------------------------------------------------------- 722 * Suff_GetPath -- 723 * Return the search path for the given suffix, if it's defined. 724 * 725 * Results: 726 * The searchPath for the desired suffix or NILLST if the suffix isn't 727 * defined. 728 * 729 * Side Effects: 730 * None 731 *----------------------------------------------------------------------- 732 */ 733 Lst 734 Suff_GetPath (sname) 735 char *sname; 736 { 737 LstNode ln; 738 Suff *s; 739 740 ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP); 741 if (ln == NILLNODE) { 742 return (NILLST); 743 } else { 744 s = (Suff *) Lst_Datum (ln); 745 return (s->searchPath); 746 } 747 } 748 749 /*- 750 *----------------------------------------------------------------------- 751 * Suff_DoPaths -- 752 * Extend the search paths for all suffixes to include the default 753 * search path. 754 * 755 * Results: 756 * None. 757 * 758 * Side Effects: 759 * The searchPath field of all the suffixes is extended by the 760 * directories in dirSearchPath. If paths were specified for the 761 * ".h" suffix, the directories are stuffed into a global variable 762 * called ".INCLUDES" with each directory preceeded by a -I. The same 763 * is done for the ".a" suffix, except the variable is called 764 * ".LIBS" and the flag is -L. 765 *----------------------------------------------------------------------- 766 */ 767 void 768 Suff_DoPaths() 769 { 770 register Suff *s; 771 register LstNode ln; 772 Lst inIncludes; /* Cumulative .INCLUDES path */ 773 Lst inLibs; /* Cumulative .LIBS path */ 774 775 if (Lst_Open (sufflist) == FAILURE) { 776 return; 777 } 778 779 inIncludes = Lst_Init(FALSE); 780 inLibs = Lst_Init(FALSE); 781 782 while ((ln = Lst_Next (sufflist)) != NILLNODE) { 783 s = (Suff *) Lst_Datum (ln); 784 if (!Lst_IsEmpty (s->searchPath)) { 785 #ifdef INCLUDES 786 if (s->flags & SUFF_INCLUDE) { 787 Dir_Concat(inIncludes, s->searchPath); 788 } 789 #endif /* INCLUDES */ 790 #ifdef LIBRARIES 791 if (s->flags & SUFF_LIBRARY) { 792 Dir_Concat(inLibs, s->searchPath); 793 } 794 #endif /* LIBRARIES */ 795 Dir_Concat(s->searchPath, dirSearchPath); 796 } else { 797 Lst_Destroy (s->searchPath, Dir_Destroy); 798 s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir); 799 } 800 } 801 802 Var_Set(".INCLUDES", Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL); 803 Var_Set(".LIBS", Dir_MakeFlags("-L", inLibs), VAR_GLOBAL); 804 805 Lst_Destroy(inIncludes, Dir_Destroy); 806 Lst_Destroy(inLibs, Dir_Destroy); 807 808 Lst_Close (sufflist); 809 } 810 811 /*- 812 *----------------------------------------------------------------------- 813 * Suff_AddInclude -- 814 * Add the given suffix as a type of file which gets included. 815 * Called from the parse module when a .INCLUDES line is parsed. 816 * The suffix must have already been defined. 817 * 818 * Results: 819 * None. 820 * 821 * Side Effects: 822 * The SUFF_INCLUDE bit is set in the suffix's flags field 823 * 824 *----------------------------------------------------------------------- 825 */ 826 void 827 Suff_AddInclude (sname) 828 char *sname; /* Name of suffix to mark */ 829 { 830 LstNode ln; 831 Suff *s; 832 833 ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP); 834 if (ln != NILLNODE) { 835 s = (Suff *) Lst_Datum (ln); 836 s->flags |= SUFF_INCLUDE; 837 } 838 } 839 840 /*- 841 *----------------------------------------------------------------------- 842 * Suff_AddLib -- 843 * Add the given suffix as a type of file which is a library. 844 * Called from the parse module when parsing a .LIBS line. The 845 * suffix must have been defined via .SUFFIXES before this is 846 * called. 847 * 848 * Results: 849 * None. 850 * 851 * Side Effects: 852 * The SUFF_LIBRARY bit is set in the suffix's flags field 853 * 854 *----------------------------------------------------------------------- 855 */ 856 void 857 Suff_AddLib (sname) 858 char *sname; /* Name of suffix to mark */ 859 { 860 LstNode ln; 861 Suff *s; 862 863 ln = Lst_Find (sufflist, (ClientData)sname, SuffSuffHasNameP); 864 if (ln != NILLNODE) { 865 s = (Suff *) Lst_Datum (ln); 866 s->flags |= SUFF_LIBRARY; 867 } 868 } 869 870 /********** Implicit Source Search Functions *********/ 871 /* 872 * A structure for passing more than one argument to the Lst-library-invoked 873 * function... 874 */ 875 typedef struct { 876 Lst l; 877 Src *s; 878 } LstSrc; 879 880 /*- 881 *----------------------------------------------------------------------- 882 * SuffAddSrc -- 883 * Add a suffix as a Src structure to the given list with its parent 884 * being the given Src structure. If the suffix is the null suffix, 885 * the prefix is used unaltered as the file name in the Src structure. 886 * 887 * Results: 888 * always returns 0 889 * 890 * Side Effects: 891 * A Src structure is created and tacked onto the end of the list 892 *----------------------------------------------------------------------- 893 */ 894 static int 895 SuffAddSrc (s, ls) 896 Suff *s; /* suffix for which to create a Src structure */ 897 LstSrc *ls; /* list and parent for the new Src */ 898 { 899 Src *s2; /* new Src structure */ 900 Src *targ; /* Target structure */ 901 902 targ = ls->s; 903 904 if ((s->flags & SUFF_NULL) && (*s->name != '\0')) { 905 /* 906 * If the suffix has been marked as the NULL suffix, also create a Src 907 * structure for a file with no suffix attached. Two birds, and all 908 * that... 909 */ 910 s2 = (Src *) emalloc (sizeof (Src)); 911 s2->file = strdup(targ->pref); 912 s2->pref = targ->pref; 913 s2->parent = targ; 914 s2->node = NILGNODE; 915 s2->suff = s; 916 s2->children = 0; 917 targ->children += 1; 918 (void)Lst_AtEnd (ls->l, (ClientData)s2); 919 } 920 s2 = (Src *) emalloc (sizeof (Src)); 921 s2->file = str_concat (targ->pref, s->name, 0); 922 s2->pref = targ->pref; 923 s2->parent = targ; 924 s2->node = NILGNODE; 925 s2->suff = s; 926 s2->children = 0; 927 targ->children += 1; 928 (void)Lst_AtEnd (ls->l, (ClientData)s2); 929 930 return(0); 931 } 932 933 /*- 934 *----------------------------------------------------------------------- 935 * SuffAddLevel -- 936 * Add all the children of targ as Src structures to the given list 937 * 938 * Results: 939 * None 940 * 941 * Side Effects: 942 * Lots of structures are created and added to the list 943 *----------------------------------------------------------------------- 944 */ 945 static void 946 SuffAddLevel (l, targ) 947 Lst l; /* list to which to add the new level */ 948 Src *targ; /* Src structure to use as the parent */ 949 { 950 LstSrc ls; 951 952 ls.s = targ; 953 ls.l = l; 954 955 Lst_ForEach (targ->suff->children, SuffAddSrc, (ClientData)&ls); 956 } 957 958 /*- 959 *---------------------------------------------------------------------- 960 * SuffFreeSrc -- 961 * Free all memory associated with a Src structure 962 * 963 * Results: 964 * None 965 * 966 * Side Effects: 967 * The memory is free'd. 968 *---------------------------------------------------------------------- 969 */ 970 static void 971 SuffFreeSrc (s) 972 Src *s; 973 { 974 free ((Address)s->file); 975 if (!s->parent) { 976 free((Address)s->pref); 977 } else if (--s->parent->children == 0 && s->parent->parent) { 978 /* 979 * Parent has no more children, now we're gone, and it's not 980 * at the top of the tree, so blow it away too. 981 */ 982 SuffFreeSrc(s->parent); 983 } 984 free ((Address)s); 985 } 986 987 /*- 988 *----------------------------------------------------------------------- 989 * SuffFindThem -- 990 * Find the first existing file/target in the list srcs 991 * 992 * Results: 993 * The lowest structure in the chain of transformations 994 * 995 * Side Effects: 996 * None 997 *----------------------------------------------------------------------- 998 */ 999 static Src * 1000 SuffFindThem (srcs) 1001 Lst srcs; /* list of Src structures to search through */ 1002 { 1003 Src *s; /* current Src */ 1004 Src *rs; /* returned Src */ 1005 1006 rs = (Src *) NULL; 1007 1008 while (!Lst_IsEmpty (srcs)) { 1009 s = (Src *) Lst_DeQueue (srcs); 1010 1011 if (DEBUG(SUFF)) { 1012 printf ("\ttrying %s...", s->file); 1013 } 1014 /* 1015 * A file is considered to exist if either a node exists in the 1016 * graph for it or the file actually exists. 1017 */ 1018 if ((Targ_FindNode(s->file, TARG_NOCREATE) != NILGNODE) || 1019 (Dir_FindFile (s->file, s->suff->searchPath) != (char *) NULL)) 1020 { 1021 if (DEBUG(SUFF)) { 1022 printf ("got it\n"); 1023 } 1024 rs = s; 1025 break; 1026 } else { 1027 if (DEBUG(SUFF)) { 1028 printf ("not there\n"); 1029 } 1030 SuffAddLevel (srcs, s); 1031 } 1032 } 1033 return (rs); 1034 } 1035 1036 /*- 1037 *----------------------------------------------------------------------- 1038 * SuffFindCmds -- 1039 * See if any of the children of the target in the Src structure is 1040 * one from which the target can be transformed. If there is one, 1041 * a Src structure is put together for it and returned. 1042 * 1043 * Results: 1044 * The Src structure of the "winning" child, or NIL if no such beast. 1045 * 1046 * Side Effects: 1047 * A Src structure may be allocated. 1048 * 1049 *----------------------------------------------------------------------- 1050 */ 1051 static Src * 1052 SuffFindCmds (targ) 1053 Src *targ; /* Src structure to play with */ 1054 { 1055 LstNode ln; /* General-purpose list node */ 1056 register GNode *t, /* Target GNode */ 1057 *s; /* Source GNode */ 1058 int prefLen;/* The length of the defined prefix */ 1059 Suff *suff; /* Suffix on matching beastie */ 1060 Src *ret; /* Return value */ 1061 char *cp; 1062 1063 t = targ->node; 1064 (void) Lst_Open (t->children); 1065 prefLen = strlen (targ->pref); 1066 1067 while ((ln = Lst_Next (t->children)) != NILLNODE) { 1068 s = (GNode *)Lst_Datum (ln); 1069 1070 cp = rindex (s->name, '/'); 1071 if (cp == (char *)NULL) { 1072 cp = s->name; 1073 } else { 1074 cp++; 1075 } 1076 if (strncmp (cp, targ->pref, prefLen) == 0) { 1077 /* 1078 * The node matches the prefix ok, see if it has a known 1079 * suffix. 1080 */ 1081 ln = Lst_Find (sufflist, (ClientData)&cp[prefLen], 1082 SuffSuffHasNameP); 1083 if (ln != NILLNODE) { 1084 /* 1085 * It even has a known suffix, see if there's a transformation 1086 * defined between the node's suffix and the target's suffix. 1087 * 1088 * XXX: Handle multi-stage transformations here, too. 1089 */ 1090 suff = (Suff *)Lst_Datum (ln); 1091 1092 if (Lst_Member (suff->parents, 1093 (ClientData)targ->suff) != NILLNODE) 1094 { 1095 /* 1096 * Hot Damn! Create a new Src structure to describe 1097 * this transformation (making sure to duplicate the 1098 * source node's name so Suff_FindDeps can free it 1099 * again (ick)), and return the new structure. 1100 */ 1101 ret = (Src *)emalloc (sizeof(Src)); 1102 ret->file = strdup(s->name); 1103 ret->pref = targ->pref; 1104 ret->suff = suff; 1105 ret->parent = targ; 1106 ret->node = s; 1107 ret->children = 0; 1108 targ->children += 1; 1109 if (DEBUG(SUFF)) { 1110 printf ("\tusing existing source %s\n", s->name); 1111 } 1112 return (ret); 1113 } 1114 } 1115 } 1116 } 1117 Lst_Close (t->children); 1118 return ((Src *)NULL); 1119 } 1120 1121 /*- 1122 *----------------------------------------------------------------------- 1123 * SuffExpandChildren -- 1124 * Expand the names of any children of a given node that contain 1125 * variable invocations or file wildcards into actual targets. 1126 * 1127 * Results: 1128 * === 0 (continue) 1129 * 1130 * Side Effects: 1131 * The expanded node is removed from the parent's list of children, 1132 * and the parent's unmade counter is decremented, but other nodes 1133 * may be added. 1134 * 1135 *----------------------------------------------------------------------- 1136 */ 1137 static int 1138 SuffExpandChildren(cgn, pgn) 1139 GNode *cgn; /* Child to examine */ 1140 GNode *pgn; /* Parent node being processed */ 1141 { 1142 GNode *gn; /* New source 8) */ 1143 LstNode prevLN; /* Node after which new source should be put */ 1144 LstNode ln; /* List element for old source */ 1145 char *cp; /* Expanded value */ 1146 1147 /* 1148 * New nodes effectively take the place of the child, so place them 1149 * after the child 1150 */ 1151 prevLN = Lst_Member(pgn->children, (ClientData)cgn); 1152 1153 /* 1154 * First do variable expansion -- this takes precedence over 1155 * wildcard expansion. If the result contains wildcards, they'll be gotten 1156 * to later since the resulting words are tacked on to the end of 1157 * the children list. 1158 */ 1159 if (index(cgn->name, '$') != (char *)NULL) { 1160 if (DEBUG(SUFF)) { 1161 printf("Expanding \"%s\"...", cgn->name); 1162 } 1163 cp = Var_Subst(cgn->name, pgn, TRUE); 1164 1165 if (cp != (char *)NULL) { 1166 Lst members = Lst_Init(FALSE); 1167 1168 if (cgn->type & OP_ARCHV) { 1169 /* 1170 * Node was an archive(member) target, so we want to call 1171 * on the Arch module to find the nodes for us, expanding 1172 * variables in the parent's context. 1173 */ 1174 char *sacrifice = cp; 1175 1176 (void)Arch_ParseArchive(&sacrifice, members, pgn); 1177 } else { 1178 /* 1179 * Break the result into a vector of strings whose nodes 1180 * we can find, then add those nodes to the members list. 1181 * Unfortunately, we can't use brk_string b/c it 1182 * doesn't understand about variable specifications with 1183 * spaces in them... 1184 */ 1185 char *start; 1186 char *initcp = cp; /* For freeing... */ 1187 1188 for (start = cp; *start == ' ' || *start == '\t'; start++) { 1189 ; 1190 } 1191 for (cp = start; *cp != '\0'; cp++) { 1192 if (*cp == ' ' || *cp == '\t') { 1193 /* 1194 * White-space -- terminate element, find the node, 1195 * add it, skip any further spaces. 1196 */ 1197 *cp++ = '\0'; 1198 gn = Targ_FindNode(start, TARG_CREATE); 1199 (void)Lst_AtEnd(members, (ClientData)gn); 1200 while (*cp == ' ' || *cp == '\t') { 1201 cp++; 1202 } 1203 /* 1204 * Adjust cp for increment at start of loop, but 1205 * set start to first non-space. 1206 */ 1207 start = cp--; 1208 } else if (*cp == '$') { 1209 /* 1210 * Start of a variable spec -- contact variable module 1211 * to find the end so we can skip over it. 1212 */ 1213 char *junk; 1214 int len; 1215 Boolean doFree; 1216 1217 junk = Var_Parse(cp, pgn, TRUE, &len, &doFree); 1218 if (junk != var_Error) { 1219 cp += len - 1; 1220 } 1221 1222 if (doFree) { 1223 free(junk); 1224 } 1225 } else if (*cp == '\\' && *cp != '\0') { 1226 /* 1227 * Escaped something -- skip over it 1228 */ 1229 cp++; 1230 } 1231 } 1232 1233 if (cp != start) { 1234 /* 1235 * Stuff left over -- add it to the list too 1236 */ 1237 gn = Targ_FindNode(start, TARG_CREATE); 1238 (void)Lst_AtEnd(members, (ClientData)gn); 1239 } 1240 /* 1241 * Point cp back at the beginning again so the variable value 1242 * can be freed. 1243 */ 1244 cp = initcp; 1245 } 1246 /* 1247 * Add all elements of the members list to the parent node. 1248 */ 1249 while(!Lst_IsEmpty(members)) { 1250 gn = (GNode *)Lst_DeQueue(members); 1251 1252 if (DEBUG(SUFF)) { 1253 printf("%s...", gn->name); 1254 } 1255 if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) { 1256 (void)Lst_Append(pgn->children, prevLN, (ClientData)gn); 1257 prevLN = Lst_Succ(prevLN); 1258 (void)Lst_AtEnd(gn->parents, (ClientData)pgn); 1259 pgn->unmade++; 1260 } 1261 } 1262 Lst_Destroy(members, NOFREE); 1263 /* 1264 * Free the result 1265 */ 1266 free((char *)cp); 1267 } 1268 /* 1269 * Now the source is expanded, remove it from the list of children to 1270 * keep it from being processed. 1271 */ 1272 ln = Lst_Member(pgn->children, (ClientData)cgn); 1273 pgn->unmade--; 1274 Lst_Remove(pgn->children, ln); 1275 if (DEBUG(SUFF)) { 1276 printf("\n"); 1277 } 1278 } else if (Dir_HasWildcards(cgn->name)) { 1279 Lst exp; /* List of expansions */ 1280 Lst path; /* Search path along which to expand */ 1281 1282 /* 1283 * Find a path along which to expand the word. 1284 * 1285 * If the word has a known suffix, use that path. 1286 * If it has no known suffix and we're allowed to use the null 1287 * suffix, use its path. 1288 * Else use the default system search path. 1289 */ 1290 cp = cgn->name + strlen(cgn->name); 1291 ln = Lst_Find(sufflist, (ClientData)cp, SuffSuffIsSuffixP); 1292 1293 if (DEBUG(SUFF)) { 1294 printf("Wildcard expanding \"%s\"...", cgn->name); 1295 } 1296 1297 if (ln != NILLNODE) { 1298 Suff *s = (Suff *)Lst_Datum(ln); 1299 1300 if (DEBUG(SUFF)) { 1301 printf("suffix is \"%s\"...", s->name); 1302 } 1303 path = s->searchPath; 1304 } else { 1305 /* 1306 * Use default search path 1307 */ 1308 path = dirSearchPath; 1309 } 1310 1311 /* 1312 * Expand the word along the chosen path 1313 */ 1314 exp = Lst_Init(FALSE); 1315 Dir_Expand(cgn->name, path, exp); 1316 1317 while (!Lst_IsEmpty(exp)) { 1318 /* 1319 * Fetch next expansion off the list and find its GNode 1320 */ 1321 cp = (char *)Lst_DeQueue(exp); 1322 1323 if (DEBUG(SUFF)) { 1324 printf("%s...", cp); 1325 } 1326 gn = Targ_FindNode(cp, TARG_CREATE); 1327 1328 /* 1329 * If gn isn't already a child of the parent, make it so and 1330 * up the parent's count of unmade children. 1331 */ 1332 if (Lst_Member(pgn->children, (ClientData)gn) == NILLNODE) { 1333 (void)Lst_Append(pgn->children, prevLN, (ClientData)gn); 1334 prevLN = Lst_Succ(prevLN); 1335 (void)Lst_AtEnd(gn->parents, (ClientData)pgn); 1336 pgn->unmade++; 1337 } 1338 } 1339 1340 /* 1341 * Nuke what's left of the list 1342 */ 1343 Lst_Destroy(exp, NOFREE); 1344 1345 /* 1346 * Now the source is expanded, remove it from the list of children to 1347 * keep it from being processed. 1348 */ 1349 ln = Lst_Member(pgn->children, (ClientData)cgn); 1350 pgn->unmade--; 1351 Lst_Remove(pgn->children, ln); 1352 if (DEBUG(SUFF)) { 1353 printf("\n"); 1354 } 1355 } 1356 1357 return(0); 1358 } 1359 1360 /*- 1361 *----------------------------------------------------------------------- 1362 * SuffApplyTransform -- 1363 * Apply a transformation rule, given the source and target nodes 1364 * and suffixes. 1365 * 1366 * Results: 1367 * TRUE if successful, FALSE if not. 1368 * 1369 * Side Effects: 1370 * The source and target are linked and the commands from the 1371 * transformation are added to the target node's commands list. 1372 * All attributes but OP_DEPMASK and OP_TRANSFORM are applied 1373 * to the target. The target also inherits all the sources for 1374 * the transformation rule. 1375 * 1376 *----------------------------------------------------------------------- 1377 */ 1378 static Boolean 1379 SuffApplyTransform(tGn, sGn, t, s) 1380 GNode *tGn; /* Target node */ 1381 GNode *sGn; /* Source node */ 1382 Suff *t; /* Target suffix */ 1383 Suff *s; /* Source suffix */ 1384 { 1385 LstNode ln; /* General node */ 1386 char *tname; /* Name of transformation rule */ 1387 GNode *gn; /* Node for same */ 1388 1389 if (Lst_Member(tGn->children, (ClientData)sGn) == NILLNODE) { 1390 /* 1391 * Not already linked, so form the proper links between the 1392 * target and source. 1393 */ 1394 (void)Lst_AtEnd(tGn->children, (ClientData)sGn); 1395 (void)Lst_AtEnd(sGn->parents, (ClientData)tGn); 1396 tGn->unmade += 1; 1397 } 1398 1399 if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) { 1400 /* 1401 * When a :: node is used as the implied source of a node, we have 1402 * to link all its cohorts in as sources as well. Only the initial 1403 * sGn gets the target in its iParents list, however, as that 1404 * will be sufficient to get the .IMPSRC variable set for tGn 1405 */ 1406 for (ln=Lst_First(sGn->cohorts); ln != NILLNODE; ln=Lst_Succ(ln)) { 1407 gn = (GNode *)Lst_Datum(ln); 1408 1409 if (Lst_Member(tGn->children, (ClientData)gn) == NILLNODE) { 1410 /* 1411 * Not already linked, so form the proper links between the 1412 * target and source. 1413 */ 1414 (void)Lst_AtEnd(tGn->children, (ClientData)gn); 1415 (void)Lst_AtEnd(gn->parents, (ClientData)tGn); 1416 tGn->unmade += 1; 1417 } 1418 } 1419 } 1420 /* 1421 * Locate the transformation rule itself 1422 */ 1423 tname = str_concat(s->name, t->name, 0); 1424 ln = Lst_Find(transforms, (ClientData)tname, SuffGNHasNameP); 1425 free(tname); 1426 1427 if (ln == NILLNODE) { 1428 /* 1429 * Not really such a transformation rule (can happen when we're 1430 * called to link an OP_MEMBER and OP_ARCHV node), so return 1431 * FALSE. 1432 */ 1433 return(FALSE); 1434 } 1435 1436 gn = (GNode *)Lst_Datum(ln); 1437 1438 if (DEBUG(SUFF)) { 1439 printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); 1440 } 1441 1442 /* 1443 * Record last child for expansion purposes 1444 */ 1445 ln = Lst_Last(tGn->children); 1446 1447 /* 1448 * Pass the buck to Make_HandleUse to apply the rule 1449 */ 1450 (void)Make_HandleUse(gn, tGn); 1451 1452 /* 1453 * Deal with wildcards and variables in any acquired sources 1454 */ 1455 ln = Lst_Succ(ln); 1456 if (ln != NILLNODE) { 1457 Lst_ForEachFrom(tGn->children, ln, 1458 SuffExpandChildren, (ClientData)tGn); 1459 } 1460 1461 /* 1462 * Keep track of another parent to which this beast is transformed so 1463 * the .IMPSRC variable can be set correctly for the parent. 1464 */ 1465 (void)Lst_AtEnd(sGn->iParents, (ClientData)tGn); 1466 1467 return(TRUE); 1468 } 1469 1470 1471 /*- 1472 *----------------------------------------------------------------------- 1473 * SuffFindArchiveDeps -- 1474 * Locate dependencies for an OP_ARCHV node. 1475 * 1476 * Results: 1477 * None 1478 * 1479 * Side Effects: 1480 * Same as Suff_FindDeps 1481 * 1482 *----------------------------------------------------------------------- 1483 */ 1484 static void 1485 SuffFindArchiveDeps(gn) 1486 GNode *gn; /* Node for which to locate dependencies */ 1487 { 1488 char *eoarch; /* End of archive portion */ 1489 char *eoname; /* End of member portion */ 1490 GNode *mem; /* Node for member */ 1491 static char *copy[] = { /* Variables to be copied from the member node */ 1492 TARGET, /* Must be first */ 1493 PREFIX, /* Must be second */ 1494 }; 1495 char *vals[sizeof(copy)/sizeof(copy[0])]; 1496 int i; /* Index into copy and vals */ 1497 char *cp; /* Suffix for member */ 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 = index (gn->name, '('); 1506 eoname = index (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 Suff *s; /* Current suffix */ 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 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 bcopy(sopref, targ->pref, 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->pref = strdup(sopref); 1726 1727 SuffAddLevel(srcs, targ); 1728 (void)Lst_AtEnd(targs, (ClientData)targ); 1729 } 1730 1731 /* 1732 * Using the list of possible sources built up from the target suffix(es), 1733 * try and find an existing file/target that matches. 1734 */ 1735 bottom = SuffFindThem(srcs); 1736 1737 if (bottom == (Src *)NULL) { 1738 /* 1739 * No known transformations -- use the first suffix found for setting 1740 * the local variables. 1741 */ 1742 if (!Lst_IsEmpty(targs)) { 1743 targ = (Src *)Lst_Datum(Lst_First(targs)); 1744 } else { 1745 targ = (Src *)NULL; 1746 } 1747 } else { 1748 /* 1749 * Work up the transformation path to find the suffix of the 1750 * target to which the transformation was made. 1751 */ 1752 for (targ = bottom; targ->parent != NULL; targ = targ->parent) { 1753 ; 1754 } 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 suffNull->children = Lst_Init (FALSE); 2085 suffNull->parents = Lst_Init (FALSE); 2086 suffNull->sNum = sNum++; 2087 suffNull->flags = SUFF_NULL; 2088 2089 } 2090 2091 /********************* DEBUGGING FUNCTIONS **********************/ 2092 2093 static int SuffPrintName(s) Suff *s; {printf ("%s ", s->name); return (0);} 2094 2095 static int 2096 SuffPrintSuff (s) 2097 Suff *s; 2098 { 2099 int flags; 2100 int flag; 2101 2102 printf ("# `%s'", s->name); 2103 2104 flags = s->flags; 2105 if (flags) { 2106 fputs (" (", stdout); 2107 while (flags) { 2108 flag = 1 << (ffs(flags) - 1); 2109 flags &= ~flag; 2110 switch (flag) { 2111 case SUFF_NULL: 2112 printf ("NULL"); 2113 break; 2114 case SUFF_INCLUDE: 2115 printf ("INCLUDE"); 2116 break; 2117 case SUFF_LIBRARY: 2118 printf ("LIBRARY"); 2119 break; 2120 } 2121 putc(flags ? '|' : ')', stdout); 2122 } 2123 } 2124 putc ('\n', stdout); 2125 printf ("#\tTo: "); 2126 Lst_ForEach (s->parents, SuffPrintName, (ClientData)0); 2127 putc ('\n', stdout); 2128 printf ("#\tFrom: "); 2129 Lst_ForEach (s->children, SuffPrintName, (ClientData)0); 2130 putc ('\n', stdout); 2131 printf ("#\tSearch Path: "); 2132 Dir_PrintPath (s->searchPath); 2133 putc ('\n', stdout); 2134 return (0); 2135 } 2136 2137 static int 2138 SuffPrintTrans (t) 2139 GNode *t; 2140 { 2141 extern int Targ_PrintCmd(); 2142 2143 printf ("%-16s: ", t->name); 2144 Targ_PrintType (t->type); 2145 putc ('\n', stdout); 2146 Lst_ForEach (t->commands, Targ_PrintCmd, (ClientData)0); 2147 putc ('\n', stdout); 2148 return(0); 2149 } 2150 2151 Suff_PrintAll() 2152 { 2153 printf ("#*** Suffixes:\n"); 2154 Lst_ForEach (sufflist, SuffPrintSuff, (ClientData)0); 2155 2156 printf ("#*** Transformations:\n"); 2157 Lst_ForEach (transforms, SuffPrintTrans, (ClientData)0); 2158 } 2159 2160