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