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