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