1 /* $NetBSD: suff.c,v 1.361 2021/12/28 14:06:42 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Adam de Boor. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 /* 36 * Copyright (c) 1989 by Berkeley Softworks 37 * All rights reserved. 38 * 39 * This code is derived from software contributed to Berkeley by 40 * Adam de Boor. 41 * 42 * Redistribution and use in source and binary forms, with or without 43 * modification, are permitted provided that the following conditions 44 * are met: 45 * 1. Redistributions of source code must retain the above copyright 46 * notice, this list of conditions and the following disclaimer. 47 * 2. Redistributions in binary form must reproduce the above copyright 48 * notice, this list of conditions and the following disclaimer in the 49 * documentation and/or other materials provided with the distribution. 50 * 3. All advertising materials mentioning features or use of this software 51 * must display the following acknowledgement: 52 * This product includes software developed by the University of 53 * California, Berkeley and its contributors. 54 * 4. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 */ 70 71 /* 72 * Maintain suffix lists and find implicit dependents using suffix 73 * transformation rules such as ".c.o". 74 * 75 * Interface: 76 * Suff_Init Initialize the module. 77 * 78 * Suff_End Clean up the module. 79 * 80 * Suff_ExtendPaths 81 * Extend the search path of each suffix to include the 82 * default search path. 83 * 84 * Suff_ClearSuffixes 85 * Clear out all the suffixes and transformations. 86 * 87 * Suff_IsTransform 88 * See if the passed string is a transformation rule. 89 * 90 * Suff_AddSuffix Add the passed string as another known suffix. 91 * 92 * Suff_GetPath Return the search path for the given suffix. 93 * 94 * Suff_AddInclude 95 * Mark the given suffix as denoting an include file. 96 * 97 * Suff_AddLib Mark the given suffix as denoting a library. 98 * 99 * Suff_AddTransform 100 * Add another transformation to the suffix graph. 101 * 102 * Suff_SetNull Define the suffix to consider the suffix of 103 * any file that doesn't have a known one. 104 * 105 * Suff_FindDeps Find implicit sources for and the location of 106 * a target based on its suffix. Returns the 107 * bottom-most node added to the graph or NULL 108 * if the target had no implicit sources. 109 * 110 * Suff_FindPath Return the appropriate path to search in order to 111 * find the node. 112 */ 113 114 #include "make.h" 115 #include "dir.h" 116 117 /* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */ 118 MAKE_RCSID("$NetBSD: suff.c,v 1.361 2021/12/28 14:06:42 rillig Exp $"); 119 120 typedef List SuffixList; 121 typedef ListNode SuffixListNode; 122 123 typedef List CandidateList; 124 typedef ListNode CandidateListNode; 125 126 /* The defined suffixes, such as '.c', '.o', '.l'. */ 127 static SuffixList sufflist = LST_INIT; 128 #ifdef CLEANUP 129 /* The suffixes to be cleaned up at the end. */ 130 static SuffixList suffClean = LST_INIT; 131 #endif 132 133 /* 134 * The transformation rules, such as '.c.o' to transform '.c' into '.o', 135 * or simply '.c' to transform 'file.c' into 'file'. 136 */ 137 static GNodeList transforms = LST_INIT; 138 139 /* 140 * Counter for assigning suffix numbers. 141 * TODO: What are these suffix numbers used for? 142 */ 143 static int sNum = 0; 144 145 typedef List SuffixListList; 146 147 /* 148 * A suffix such as ".c" or ".o" that is used in suffix transformation rules 149 * such as ".c.o:". 150 */ 151 typedef struct Suffix { 152 /* The suffix itself, such as ".c" */ 153 char *name; 154 /* Length of the name, to avoid strlen calls */ 155 size_t nameLen; 156 /* 157 * This suffix marks include files. Their search path ends up in the 158 * undocumented special variable '.INCLUDES'. 159 */ 160 bool include:1; 161 /* 162 * This suffix marks library files. Their search path ends up in the 163 * undocumented special variable '.LIBS'. 164 */ 165 bool library:1; 166 /* 167 * The empty suffix. 168 * 169 * XXX: What is the difference between the empty suffix and the null 170 * suffix? 171 * 172 * XXX: Why is SUFF_NULL needed at all? Wouldn't nameLen == 0 mean 173 * the same? 174 */ 175 bool isNull:1; 176 /* The path along which files of this suffix may be found */ 177 SearchPath *searchPath; 178 179 /* The suffix number; TODO: document the purpose of this number */ 180 int sNum; 181 /* Reference count of list membership and several other places */ 182 int refCount; 183 184 /* Suffixes we have a transformation to */ 185 SuffixList parents; 186 /* Suffixes we have a transformation from */ 187 SuffixList children; 188 /* 189 * Lists in which this suffix is referenced. 190 * 191 * XXX: These lists are used nowhere, they are just appended to, for 192 * no apparent reason. They do have the side effect of increasing 193 * refCount though. 194 */ 195 SuffixListList ref; 196 } Suffix; 197 198 /* 199 * A candidate when searching for implied sources. 200 * 201 * For example, when "src.o" is to be made, a typical candidate is "src.c" 202 * via the transformation rule ".c.o". If that doesn't exist, maybe there is 203 * another transformation rule ".pas.c" that would make "src.pas" an indirect 204 * candidate as well. The first such chain that leads to an existing file or 205 * node is finally chosen to be made. 206 */ 207 typedef struct Candidate { 208 /* The file or node to look for. */ 209 char *file; 210 /* 211 * The prefix from which file was formed. Its memory is shared among 212 * all candidates. 213 */ 214 char *prefix; 215 /* The suffix on the file. */ 216 Suffix *suff; 217 218 /* 219 * The candidate that can be made from this, or NULL for the 220 * top-level candidate. 221 */ 222 struct Candidate *parent; 223 /* The node describing the file. */ 224 GNode *node; 225 226 /* 227 * Count of existing children, only used for memory management, so we 228 * don't free this candidate too early or too late. 229 */ 230 int numChildren; 231 #ifdef DEBUG_SRC 232 CandidateList childrenList; 233 #endif 234 } Candidate; 235 236 typedef struct CandidateSearcher { 237 238 CandidateList list; 239 240 /* 241 * TODO: Add HashSet for seen entries, to avoid endless loops such as 242 * in suff-transform-endless.mk. 243 */ 244 245 } CandidateSearcher; 246 247 248 /* TODO: Document the difference between nullSuff and emptySuff. */ 249 /* The NULL suffix for this run */ 250 static Suffix *nullSuff; 251 /* The empty suffix required for POSIX single-suffix transformation rules */ 252 static Suffix *emptySuff; 253 254 255 static Suffix * 256 Suffix_Ref(Suffix *suff) 257 { 258 suff->refCount++; 259 return suff; 260 } 261 262 /* Change the value of a Suffix variable, adjusting the reference counts. */ 263 static void 264 Suffix_Reassign(Suffix **var, Suffix *suff) 265 { 266 if (*var != NULL) 267 (*var)->refCount--; 268 *var = suff; 269 suff->refCount++; 270 } 271 272 /* Set a Suffix variable to NULL, adjusting the reference count. */ 273 static void 274 Suffix_Unassign(Suffix **var) 275 { 276 if (*var != NULL) 277 (*var)->refCount--; 278 *var = NULL; 279 } 280 281 /* 282 * See if pref is a prefix of str. 283 * Return NULL if it ain't, pointer to character in str after prefix if so. 284 */ 285 static const char * 286 StrTrimPrefix(const char *pref, const char *str) 287 { 288 while (*str != '\0' && *pref == *str) { 289 pref++; 290 str++; 291 } 292 293 return *pref != '\0' ? NULL : str; 294 } 295 296 /* 297 * See if suff is a suffix of str, and if so, return the pointer to the suffix 298 * in str, which at the same time marks the end of the prefix. 299 */ 300 static const char * 301 StrTrimSuffix(const char *str, size_t strLen, const char *suff, size_t suffLen) 302 { 303 const char *suffInStr; 304 size_t i; 305 306 if (strLen < suffLen) 307 return NULL; 308 309 suffInStr = str + strLen - suffLen; 310 for (i = 0; i < suffLen; i++) 311 if (suff[i] != suffInStr[i]) 312 return NULL; 313 314 return suffInStr; 315 } 316 317 /* 318 * See if suff is a suffix of name, and if so, return the end of the prefix 319 * in name. 320 */ 321 static const char * 322 Suffix_TrimSuffix(const Suffix *suff, size_t nameLen, const char *nameEnd) 323 { 324 return StrTrimSuffix(nameEnd - nameLen, nameLen, 325 suff->name, suff->nameLen); 326 } 327 328 static bool 329 Suffix_IsSuffix(const Suffix *suff, size_t nameLen, const char *nameEnd) 330 { 331 return Suffix_TrimSuffix(suff, nameLen, nameEnd) != NULL; 332 } 333 334 static Suffix * 335 FindSuffixByNameLen(const char *name, size_t nameLen) 336 { 337 SuffixListNode *ln; 338 339 for (ln = sufflist.first; ln != NULL; ln = ln->next) { 340 Suffix *suff = ln->datum; 341 if (suff->nameLen == nameLen && 342 memcmp(suff->name, name, nameLen) == 0) 343 return suff; 344 } 345 return NULL; 346 } 347 348 static Suffix * 349 FindSuffixByName(const char *name) 350 { 351 return FindSuffixByNameLen(name, strlen(name)); 352 } 353 354 static GNode * 355 FindTransformByName(const char *name) 356 { 357 GNodeListNode *ln; 358 359 for (ln = transforms.first; ln != NULL; ln = ln->next) { 360 GNode *gn = ln->datum; 361 if (strcmp(gn->name, name) == 0) 362 return gn; 363 } 364 return NULL; 365 } 366 367 static void 368 SuffixList_Unref(SuffixList *list, Suffix *suff) 369 { 370 SuffixListNode *ln = Lst_FindDatum(list, suff); 371 if (ln != NULL) { 372 Lst_Remove(list, ln); 373 suff->refCount--; 374 } 375 } 376 377 /* Free up all memory associated with the given suffix structure. */ 378 static void 379 Suffix_Free(Suffix *suff) 380 { 381 382 if (suff == nullSuff) 383 nullSuff = NULL; 384 385 if (suff == emptySuff) 386 emptySuff = NULL; 387 388 #if 0 389 /* We don't delete suffixes in order, so we cannot use this */ 390 if (suff->refCount != 0) 391 Punt("Internal error deleting suffix `%s' with refcount = %d", 392 suff->name, suff->refCount); 393 #endif 394 395 Lst_Done(&suff->ref); 396 Lst_Done(&suff->children); 397 Lst_Done(&suff->parents); 398 SearchPath_Free(suff->searchPath); 399 400 free(suff->name); 401 free(suff); 402 } 403 404 static void 405 SuffFree(void *p) 406 { 407 Suffix_Free(p); 408 } 409 410 /* Remove the suffix from the list, and free if it is otherwise unused. */ 411 static void 412 SuffixList_Remove(SuffixList *list, Suffix *suff) 413 { 414 SuffixList_Unref(list, suff); 415 if (suff->refCount == 0) { 416 /* XXX: can lead to suff->refCount == -1 */ 417 SuffixList_Unref(&sufflist, suff); 418 DEBUG1(SUFF, "Removing suffix \"%s\"\n", suff->name); 419 SuffFree(suff); 420 } 421 } 422 423 /* 424 * Insert the suffix into the list, keeping the list ordered by suffix 425 * number. 426 */ 427 static void 428 SuffixList_Insert(SuffixList *list, Suffix *suff) 429 { 430 SuffixListNode *ln; 431 Suffix *listSuff = NULL; 432 433 for (ln = list->first; ln != NULL; ln = ln->next) { 434 listSuff = ln->datum; 435 if (listSuff->sNum >= suff->sNum) 436 break; 437 } 438 439 if (ln == NULL) { 440 DEBUG2(SUFF, "inserting \"%s\" (%d) at end of list\n", 441 suff->name, suff->sNum); 442 Lst_Append(list, Suffix_Ref(suff)); 443 Lst_Append(&suff->ref, list); 444 } else if (listSuff->sNum != suff->sNum) { 445 DEBUG4(SUFF, "inserting \"%s\" (%d) before \"%s\" (%d)\n", 446 suff->name, suff->sNum, listSuff->name, listSuff->sNum); 447 Lst_InsertBefore(list, ln, Suffix_Ref(suff)); 448 Lst_Append(&suff->ref, list); 449 } else { 450 DEBUG2(SUFF, "\"%s\" (%d) is already there\n", 451 suff->name, suff->sNum); 452 } 453 } 454 455 static void 456 Relate(Suffix *srcSuff, Suffix *targSuff) 457 { 458 SuffixList_Insert(&targSuff->children, srcSuff); 459 SuffixList_Insert(&srcSuff->parents, targSuff); 460 } 461 462 static Suffix * 463 Suffix_New(const char *name) 464 { 465 Suffix *suff = bmake_malloc(sizeof *suff); 466 467 suff->name = bmake_strdup(name); 468 suff->nameLen = strlen(suff->name); 469 suff->searchPath = SearchPath_New(); 470 Lst_Init(&suff->children); 471 Lst_Init(&suff->parents); 472 Lst_Init(&suff->ref); 473 suff->sNum = sNum++; 474 suff->include = false; 475 suff->library = false; 476 suff->isNull = false; 477 suff->refCount = 1; /* XXX: why 1? It's not assigned anywhere yet. */ 478 479 return suff; 480 } 481 482 /* 483 * Nuke the list of suffixes but keep all transformation rules around. The 484 * transformation graph is destroyed in this process, but we leave the list 485 * of rules so when a new graph is formed, the rules will remain. This 486 * function is called when a line '.SUFFIXES:' with an empty suffixes list is 487 * encountered in a makefile. 488 */ 489 void 490 Suff_ClearSuffixes(void) 491 { 492 #ifdef CLEANUP 493 Lst_MoveAll(&suffClean, &sufflist); 494 #endif 495 DEBUG0(SUFF, "Clearing all suffixes\n"); 496 Lst_Init(&sufflist); 497 sNum = 0; 498 if (nullSuff != NULL) 499 SuffFree(nullSuff); 500 emptySuff = nullSuff = Suffix_New(""); 501 502 SearchPath_AddAll(nullSuff->searchPath, &dirSearchPath); 503 nullSuff->include = false; 504 nullSuff->library = false; 505 nullSuff->isNull = true; 506 } 507 508 /* 509 * Parse a transformation string such as ".c.o" to find its two component 510 * suffixes (the source ".c" and the target ".o"). If there are no such 511 * suffixes, try a single-suffix transformation as well. 512 * 513 * Return true if the string is a valid transformation. 514 */ 515 static bool 516 ParseTransform(const char *str, Suffix **out_src, Suffix **out_targ) 517 { 518 SuffixListNode *ln; 519 Suffix *single = NULL; 520 521 /* 522 * Loop looking first for a suffix that matches the start of the 523 * string and then for one that exactly matches the rest of it. If 524 * we can find two that meet these criteria, we've successfully 525 * parsed the string. 526 */ 527 for (ln = sufflist.first; ln != NULL; ln = ln->next) { 528 Suffix *src = ln->datum; 529 530 if (StrTrimPrefix(src->name, str) == NULL) 531 continue; 532 533 if (str[src->nameLen] == '\0') { 534 single = src; 535 } else { 536 Suffix *targ = FindSuffixByName(str + src->nameLen); 537 if (targ != NULL) { 538 *out_src = src; 539 *out_targ = targ; 540 return true; 541 } 542 } 543 } 544 545 if (single != NULL) { 546 /* 547 * There was a suffix that encompassed the entire string, so we 548 * assume it was a transformation to the null suffix (thank you 549 * POSIX; search for "single suffix" or "single-suffix"). 550 * 551 * We still prefer to find a double rule over a singleton, 552 * hence we leave this check until the end. 553 * 554 * XXX: Use emptySuff over nullSuff? 555 */ 556 *out_src = single; 557 *out_targ = nullSuff; 558 return true; 559 } 560 return false; 561 } 562 563 /* 564 * Return true if the given string is a transformation rule, that is, a 565 * concatenation of two known suffixes such as ".c.o" or a single suffix 566 * such as ".o". 567 */ 568 bool 569 Suff_IsTransform(const char *str) 570 { 571 Suffix *src, *targ; 572 573 return ParseTransform(str, &src, &targ); 574 } 575 576 /* 577 * Add the transformation rule to the list of rules and place the 578 * transformation itself in the graph. 579 * 580 * The transformation is linked to the two suffixes mentioned in the name. 581 * 582 * Input: 583 * name must have the form ".from.to" or just ".from" 584 * 585 * Results: 586 * The created or existing transformation node in the transforms list 587 */ 588 GNode * 589 Suff_AddTransform(const char *name) 590 { 591 Suffix *srcSuff; 592 Suffix *targSuff; 593 594 GNode *gn = FindTransformByName(name); 595 if (gn == NULL) { 596 /* 597 * Make a new graph node for the transformation. It will be 598 * filled in by the Parse module. 599 */ 600 gn = GNode_New(name); 601 Lst_Append(&transforms, gn); 602 } else { 603 /* 604 * New specification for transformation rule. Just nuke the 605 * old list of commands so they can be filled in again. We 606 * don't actually free the commands themselves, because a 607 * given command can be attached to several different 608 * transformations. 609 */ 610 Lst_Done(&gn->commands); 611 Lst_Init(&gn->commands); 612 Lst_Done(&gn->children); 613 Lst_Init(&gn->children); 614 } 615 616 gn->type = OP_TRANSFORM; 617 618 { 619 /* TODO: Avoid the redundant parsing here. */ 620 bool ok = ParseTransform(name, &srcSuff, &targSuff); 621 assert(ok); 622 /* LINTED 129 *//* expression has null effect */ 623 (void)ok; 624 } 625 626 /* Link the two together in the proper relationship and order. */ 627 DEBUG2(SUFF, "defining transformation from `%s' to `%s'\n", 628 srcSuff->name, targSuff->name); 629 Relate(srcSuff, targSuff); 630 631 return gn; 632 } 633 634 /* 635 * Handle the finish of a transformation definition, removing the 636 * transformation from the graph if it has neither commands nor sources. 637 * 638 * If the node has no commands or children, the children and parents lists 639 * of the affected suffixes are altered. 640 * 641 * Input: 642 * gn Node for transformation 643 */ 644 void 645 Suff_EndTransform(GNode *gn) 646 { 647 Suffix *srcSuff, *targSuff; 648 SuffixList *srcSuffParents; 649 650 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(&gn->cohorts)) 651 gn = gn->cohorts.last->datum; 652 653 if (!(gn->type & OP_TRANSFORM)) 654 return; 655 656 if (!Lst_IsEmpty(&gn->commands) || !Lst_IsEmpty(&gn->children)) { 657 DEBUG1(SUFF, "transformation %s complete\n", gn->name); 658 return; 659 } 660 661 /* 662 * SuffParseTransform() may fail for special rules which are not 663 * actual transformation rules. (e.g. .DEFAULT) 664 */ 665 if (!ParseTransform(gn->name, &srcSuff, &targSuff)) 666 return; 667 668 DEBUG2(SUFF, "deleting incomplete transformation from `%s' to `%s'\n", 669 srcSuff->name, targSuff->name); 670 671 /* 672 * Remember the parents since srcSuff could be deleted in 673 * SuffixList_Remove. 674 */ 675 srcSuffParents = &srcSuff->parents; 676 SuffixList_Remove(&targSuff->children, srcSuff); 677 SuffixList_Remove(srcSuffParents, targSuff); 678 } 679 680 /* 681 * Called from Suff_AddSuffix to search through the list of 682 * existing transformation rules and rebuild the transformation graph when 683 * it has been destroyed by Suff_ClearSuffixes. If the given rule is a 684 * transformation involving this suffix and another, existing suffix, the 685 * proper relationship is established between the two. 686 * 687 * The appropriate links will be made between this suffix and others if 688 * transformation rules exist for it. 689 * 690 * Input: 691 * transform Transformation to test 692 * suff Suffix to rebuild 693 */ 694 static void 695 RebuildGraph(GNode *transform, Suffix *suff) 696 { 697 const char *name = transform->name; 698 size_t nameLen = strlen(name); 699 const char *toName; 700 701 /* 702 * See if it is a transformation from this suffix to another suffix. 703 */ 704 toName = StrTrimPrefix(suff->name, name); 705 if (toName != NULL) { 706 Suffix *to = FindSuffixByName(toName); 707 if (to != NULL) { 708 Relate(suff, to); 709 return; 710 } 711 } 712 713 /* 714 * See if it is a transformation from another suffix to this suffix. 715 */ 716 toName = Suffix_TrimSuffix(suff, nameLen, name + nameLen); 717 if (toName != NULL) { 718 Suffix *from = FindSuffixByNameLen(name, 719 (size_t)(toName - name)); 720 if (from != NULL) 721 Relate(from, suff); 722 } 723 } 724 725 /* 726 * During Suff_AddSuffix, search through the list of existing targets and find 727 * if any of the existing targets can be turned into a transformation rule. 728 * 729 * If such a target is found and the target is the current main target, the 730 * main target is set to NULL and the next target examined (if that exists) 731 * becomes the main target. 732 * 733 * Results: 734 * true iff a new main target has been selected. 735 */ 736 static bool 737 UpdateTarget(GNode *target, GNode **inout_main, Suffix *suff, 738 bool *inout_removedMain) 739 { 740 Suffix *srcSuff, *targSuff; 741 char *ptr; 742 743 if (*inout_main == NULL && *inout_removedMain && 744 GNode_IsMainCandidate(target)) { 745 DEBUG1(MAKE, "Setting main node to \"%s\"\n", target->name); 746 *inout_main = target; 747 Targ_SetMain(target); 748 /* 749 * XXX: Why could it be a good idea to return true here? 750 * The main task of this function is to turn ordinary nodes 751 * into transformations, no matter whether or not a new .MAIN 752 * node has been found. 753 */ 754 /* 755 * XXX: Even when changing this to false, none of the existing 756 * unit tests fails. 757 */ 758 return true; 759 } 760 761 if (target->type == OP_TRANSFORM) 762 return false; 763 764 /* 765 * XXX: What about a transformation ".cpp.c"? If ".c" is added as 766 * a new suffix, it seems wrong that this transformation would be 767 * skipped just because ".c" happens to be a prefix of ".cpp". 768 */ 769 ptr = strstr(target->name, suff->name); 770 if (ptr == NULL) 771 return false; 772 773 /* 774 * XXX: In suff-rebuild.mk, in the line '.SUFFIXES: .c .b .a', this 775 * condition prevents the rule '.b.c' from being added again during 776 * Suff_AddSuffix(".b"). 777 * 778 * XXX: Removing this paragraph makes suff-add-later.mk use massive 779 * amounts of memory. 780 */ 781 if (ptr == target->name) 782 return false; 783 784 if (ParseTransform(target->name, &srcSuff, &targSuff)) { 785 if (*inout_main == target) { 786 DEBUG1(MAKE, 787 "Setting main node from \"%s\" back to null\n", 788 target->name); 789 *inout_removedMain = true; 790 *inout_main = NULL; 791 Targ_SetMain(NULL); 792 } 793 Lst_Done(&target->children); 794 Lst_Init(&target->children); 795 target->type = OP_TRANSFORM; 796 797 /* 798 * Link the two together in the proper relationship and order. 799 */ 800 DEBUG2(SUFF, "defining transformation from `%s' to `%s'\n", 801 srcSuff->name, targSuff->name); 802 Relate(srcSuff, targSuff); 803 } 804 return false; 805 } 806 807 /* 808 * Look at all existing targets to see if adding this suffix will make one 809 * of the current targets mutate into a suffix rule. 810 * 811 * This is ugly, but other makes treat all targets that start with a '.' as 812 * suffix rules. 813 */ 814 static void 815 UpdateTargets(GNode **inout_main, Suffix *suff) 816 { 817 bool removedMain = false; 818 GNodeListNode *ln; 819 820 for (ln = Targ_List()->first; ln != NULL; ln = ln->next) { 821 GNode *gn = ln->datum; 822 if (UpdateTarget(gn, inout_main, suff, &removedMain)) 823 break; 824 } 825 } 826 827 /* 828 * Add the suffix to the end of the list of known suffixes. 829 * Should we restructure the suffix graph? Make doesn't. 830 * 831 * A GNode is created for the suffix (XXX: this sounds completely wrong) and 832 * a Suffix structure is created and added to the suffixes list unless the 833 * suffix was already known. 834 * The mainNode passed can be modified if a target mutated into a 835 * transform and that target happened to be the main target. 836 * 837 * Input: 838 * name the name of the suffix to add 839 */ 840 void 841 Suff_AddSuffix(const char *name, GNode **inout_main) 842 { 843 GNodeListNode *ln; 844 845 Suffix *suff = FindSuffixByName(name); 846 if (suff != NULL) 847 return; 848 849 suff = Suffix_New(name); 850 Lst_Append(&sufflist, suff); 851 DEBUG1(SUFF, "Adding suffix \"%s\"\n", suff->name); 852 853 UpdateTargets(inout_main, suff); 854 855 /* 856 * Look for any existing transformations from or to this suffix. 857 * XXX: Only do this after a Suff_ClearSuffixes? 858 */ 859 for (ln = transforms.first; ln != NULL; ln = ln->next) 860 RebuildGraph(ln->datum, suff); 861 } 862 863 /* Return the search path for the given suffix, or NULL. */ 864 SearchPath * 865 Suff_GetPath(const char *sname) 866 { 867 Suffix *suff = FindSuffixByName(sname); 868 return suff != NULL ? suff->searchPath : NULL; 869 } 870 871 /* 872 * Extend the search paths for all suffixes to include the default search 873 * path (dirSearchPath). 874 * 875 * The default search path can be defined using the special target '.PATH'. 876 * The search path of each suffix can be defined using the special target 877 * '.PATH<suffix>'. 878 * 879 * If paths were specified for the ".h" suffix, the directories are stuffed 880 * into a global variable called ".INCLUDES" with each directory preceded by 881 * '-I'. The same is done for the ".a" suffix, except the variable is called 882 * ".LIBS" and the flag is '-L'. 883 */ 884 void 885 Suff_ExtendPaths(void) 886 { 887 SuffixListNode *ln; 888 char *flags; 889 SearchPath *includesPath = SearchPath_New(); 890 SearchPath *libsPath = SearchPath_New(); 891 892 for (ln = sufflist.first; ln != NULL; ln = ln->next) { 893 Suffix *suff = ln->datum; 894 if (!Lst_IsEmpty(&suff->searchPath->dirs)) { 895 #ifdef INCLUDES 896 if (suff->include) 897 SearchPath_AddAll(includesPath, 898 suff->searchPath); 899 #endif 900 #ifdef LIBRARIES 901 if (suff->library) 902 SearchPath_AddAll(libsPath, suff->searchPath); 903 #endif 904 SearchPath_AddAll(suff->searchPath, &dirSearchPath); 905 } else { 906 SearchPath_Free(suff->searchPath); 907 suff->searchPath = Dir_CopyDirSearchPath(); 908 } 909 } 910 911 flags = SearchPath_ToFlags(includesPath, "-I"); 912 Global_Set(".INCLUDES", flags); 913 free(flags); 914 915 flags = SearchPath_ToFlags(libsPath, "-L"); 916 Global_Set(".LIBS", flags); 917 free(flags); 918 919 SearchPath_Free(includesPath); 920 SearchPath_Free(libsPath); 921 } 922 923 /* 924 * Add the given suffix as a type of file which gets included. 925 * Called when a '.INCLUDES: .h' line is parsed. 926 * To have an effect, the suffix must already exist. 927 * This affects the magic variable '.INCLUDES'. 928 */ 929 void 930 Suff_AddInclude(const char *suffName) 931 { 932 Suffix *suff = FindSuffixByName(suffName); 933 if (suff != NULL) 934 suff->include = true; 935 } 936 937 /* 938 * Add the given suffix as a type of file which is a library. 939 * Called when a '.LIBS: .a' line is parsed. 940 * To have an effect, the suffix must already exist. 941 * This affects the magic variable '.LIBS'. 942 */ 943 void 944 Suff_AddLib(const char *suffName) 945 { 946 Suffix *suff = FindSuffixByName(suffName); 947 if (suff != NULL) 948 suff->library = true; 949 } 950 951 /********** Implicit Source Search Functions *********/ 952 953 static void 954 CandidateSearcher_Init(CandidateSearcher *cs) 955 { 956 Lst_Init(&cs->list); 957 } 958 959 static void 960 CandidateSearcher_Done(CandidateSearcher *cs) 961 { 962 Lst_Done(&cs->list); 963 } 964 965 static void 966 CandidateSearcher_Add(CandidateSearcher *cs, Candidate *cand) 967 { 968 /* TODO: filter duplicates */ 969 Lst_Append(&cs->list, cand); 970 } 971 972 static void 973 CandidateSearcher_AddIfNew(CandidateSearcher *cs, Candidate *cand) 974 { 975 /* TODO: filter duplicates */ 976 if (Lst_FindDatum(&cs->list, cand) == NULL) 977 Lst_Append(&cs->list, cand); 978 } 979 980 static void 981 CandidateSearcher_MoveAll(CandidateSearcher *cs, CandidateList *list) 982 { 983 /* TODO: filter duplicates */ 984 Lst_MoveAll(&cs->list, list); 985 } 986 987 988 #ifdef DEBUG_SRC 989 static void 990 CandidateList_PrintAddrs(CandidateList *list) 991 { 992 CandidateListNode *ln; 993 994 for (ln = list->first; ln != NULL; ln = ln->next) { 995 Candidate *cand = ln->datum; 996 debug_printf(" %p:%s", cand, cand->file); 997 } 998 debug_printf("\n"); 999 } 1000 #endif 1001 1002 static Candidate * 1003 Candidate_New(char *name, char *prefix, Suffix *suff, Candidate *parent, 1004 GNode *gn) 1005 { 1006 Candidate *cand = bmake_malloc(sizeof *cand); 1007 1008 cand->file = name; 1009 cand->prefix = prefix; 1010 cand->suff = Suffix_Ref(suff); 1011 cand->parent = parent; 1012 cand->node = gn; 1013 cand->numChildren = 0; 1014 #ifdef DEBUG_SRC 1015 Lst_Init(&cand->childrenList); 1016 #endif 1017 1018 return cand; 1019 } 1020 1021 /* Add a new candidate to the list. */ 1022 /*ARGSUSED*/ 1023 static void 1024 CandidateList_Add(CandidateList *list, char *srcName, Candidate *targ, 1025 Suffix *suff, const char *debug_tag) 1026 { 1027 Candidate *cand = Candidate_New(srcName, targ->prefix, suff, targ, 1028 NULL); 1029 targ->numChildren++; 1030 Lst_Append(list, cand); 1031 1032 #ifdef DEBUG_SRC 1033 Lst_Append(&targ->childrenList, cand); 1034 debug_printf("%s add suff %p:%s candidate %p:%s to list %p:", 1035 debug_tag, targ, targ->file, cand, cand->file, list); 1036 CandidateList_PrintAddrs(list); 1037 #endif 1038 } 1039 1040 /* 1041 * Add all candidates to the list that can be formed by applying a suffix to 1042 * the candidate. 1043 */ 1044 static void 1045 CandidateList_AddCandidatesFor(CandidateList *list, Candidate *cand) 1046 { 1047 SuffixListNode *ln; 1048 for (ln = cand->suff->children.first; ln != NULL; ln = ln->next) { 1049 Suffix *suff = ln->datum; 1050 1051 if (suff->isNull && suff->name[0] != '\0') { 1052 /* 1053 * If the suffix has been marked as the NULL suffix, 1054 * also create a candidate for a file with no suffix 1055 * attached. 1056 */ 1057 CandidateList_Add(list, bmake_strdup(cand->prefix), 1058 cand, suff, "1"); 1059 } 1060 1061 CandidateList_Add(list, str_concat2(cand->prefix, suff->name), 1062 cand, suff, "2"); 1063 } 1064 } 1065 1066 /* 1067 * Free the first candidate in the list that is not referenced anymore. 1068 * Return whether a candidate was removed. 1069 */ 1070 static bool 1071 RemoveCandidate(CandidateList *srcs) 1072 { 1073 CandidateListNode *ln; 1074 1075 #ifdef DEBUG_SRC 1076 debug_printf("cleaning list %p:", srcs); 1077 CandidateList_PrintAddrs(srcs); 1078 #endif 1079 1080 for (ln = srcs->first; ln != NULL; ln = ln->next) { 1081 Candidate *src = ln->datum; 1082 1083 if (src->numChildren == 0) { 1084 if (src->parent == NULL) 1085 free(src->prefix); 1086 else { 1087 #ifdef DEBUG_SRC 1088 /* XXX: Lst_RemoveDatum */ 1089 CandidateListNode *ln2; 1090 ln2 = Lst_FindDatum(&src->parent->childrenList, 1091 src); 1092 if (ln2 != NULL) 1093 Lst_Remove(&src->parent->childrenList, 1094 ln2); 1095 #endif 1096 src->parent->numChildren--; 1097 } 1098 #ifdef DEBUG_SRC 1099 debug_printf("free: list %p src %p:%s children %d\n", 1100 srcs, src, src->file, src->numChildren); 1101 Lst_Done(&src->childrenList); 1102 #endif 1103 Lst_Remove(srcs, ln); 1104 free(src->file); 1105 free(src); 1106 return true; 1107 } 1108 #ifdef DEBUG_SRC 1109 else { 1110 debug_printf("keep: list %p src %p:%s children %d:", 1111 srcs, src, src->file, src->numChildren); 1112 CandidateList_PrintAddrs(&src->childrenList); 1113 } 1114 #endif 1115 } 1116 1117 return false; 1118 } 1119 1120 /* Find the first existing file/target in srcs. */ 1121 static Candidate * 1122 FindThem(CandidateList *srcs, CandidateSearcher *cs) 1123 { 1124 HashSet seen; 1125 1126 HashSet_Init(&seen); 1127 1128 while (!Lst_IsEmpty(srcs)) { 1129 Candidate *src = Lst_Dequeue(srcs); 1130 1131 #ifdef DEBUG_SRC 1132 debug_printf("remove from list %p src %p:%s\n", 1133 srcs, src, src->file); 1134 #endif 1135 DEBUG1(SUFF, "\ttrying %s...", src->file); 1136 1137 /* 1138 * A file is considered to exist if either a node exists in the 1139 * graph for it or the file actually exists. 1140 */ 1141 if (Targ_FindNode(src->file) != NULL) { 1142 found: 1143 HashSet_Done(&seen); 1144 DEBUG0(SUFF, "got it\n"); 1145 return src; 1146 } 1147 1148 { 1149 char *file = Dir_FindFile(src->file, 1150 src->suff->searchPath); 1151 if (file != NULL) { 1152 free(file); 1153 goto found; 1154 } 1155 } 1156 1157 DEBUG0(SUFF, "not there\n"); 1158 1159 if (HashSet_Add(&seen, src->file)) 1160 CandidateList_AddCandidatesFor(srcs, src); 1161 else { 1162 DEBUG1(SUFF, "FindThem: skipping duplicate \"%s\"\n", 1163 src->file); 1164 } 1165 1166 CandidateSearcher_Add(cs, src); 1167 } 1168 1169 HashSet_Done(&seen); 1170 return NULL; 1171 } 1172 1173 /* 1174 * See if any of the children of the candidate's GNode is one from which the 1175 * target can be transformed. If there is one, a candidate is put together 1176 * for it and returned. 1177 */ 1178 static Candidate * 1179 FindCmds(Candidate *targ, CandidateSearcher *cs) 1180 { 1181 GNodeListNode *gln; 1182 GNode *tgn; /* Target GNode */ 1183 GNode *sgn; /* Source GNode */ 1184 size_t prefLen; /* The length of the defined prefix */ 1185 Suffix *suff; /* Suffix of the matching candidate */ 1186 Candidate *ret; /* Return value */ 1187 1188 tgn = targ->node; 1189 prefLen = strlen(targ->prefix); 1190 1191 for (gln = tgn->children.first; gln != NULL; gln = gln->next) { 1192 const char *base; 1193 1194 sgn = gln->datum; 1195 1196 if (sgn->type & OP_OPTIONAL && Lst_IsEmpty(&tgn->commands)) { 1197 /* 1198 * We haven't looked to see if .OPTIONAL files exist 1199 * yet, so don't use one as the implicit source. 1200 * This allows us to use .OPTIONAL in .depend files so 1201 * make won't complain "don't know how to make xxx.h" 1202 * when a dependent file has been moved/deleted. 1203 */ 1204 continue; 1205 } 1206 1207 base = str_basename(sgn->name); 1208 if (strncmp(base, targ->prefix, prefLen) != 0) 1209 continue; 1210 /* 1211 * The node matches the prefix, see if it has a known suffix. 1212 */ 1213 suff = FindSuffixByName(base + prefLen); 1214 if (suff == NULL) 1215 continue; 1216 1217 /* 1218 * It even has a known suffix, see if there's a transformation 1219 * defined between the node's suffix and the target's suffix. 1220 * 1221 * XXX: Handle multi-stage transformations here, too. 1222 */ 1223 1224 if (Lst_FindDatum(&suff->parents, targ->suff) != NULL) 1225 break; 1226 } 1227 1228 if (gln == NULL) 1229 return NULL; 1230 1231 ret = Candidate_New(bmake_strdup(sgn->name), targ->prefix, suff, targ, 1232 sgn); 1233 targ->numChildren++; 1234 #ifdef DEBUG_SRC 1235 debug_printf("3 add targ %p:%s ret %p:%s\n", 1236 targ, targ->file, ret, ret->file); 1237 Lst_Append(&targ->childrenList, ret); 1238 #endif 1239 CandidateSearcher_Add(cs, ret); 1240 DEBUG1(SUFF, "\tusing existing source %s\n", sgn->name); 1241 return ret; 1242 } 1243 1244 static void 1245 ExpandWildcards(GNodeListNode *cln, GNode *pgn) 1246 { 1247 GNode *cgn = cln->datum; 1248 StringList expansions; 1249 1250 if (!Dir_HasWildcards(cgn->name)) 1251 return; 1252 1253 /* 1254 * Expand the word along the chosen path 1255 */ 1256 Lst_Init(&expansions); 1257 SearchPath_Expand(Suff_FindPath(cgn), cgn->name, &expansions); 1258 1259 while (!Lst_IsEmpty(&expansions)) { 1260 GNode *gn; 1261 /* 1262 * Fetch next expansion off the list and find its GNode 1263 */ 1264 char *cp = Lst_Dequeue(&expansions); 1265 1266 DEBUG1(SUFF, "%s...", cp); 1267 gn = Targ_GetNode(cp); 1268 1269 /* Insert gn before the original child. */ 1270 Lst_InsertBefore(&pgn->children, cln, gn); 1271 Lst_Append(&gn->parents, pgn); 1272 pgn->unmade++; 1273 } 1274 1275 Lst_Done(&expansions); 1276 1277 DEBUG0(SUFF, "\n"); 1278 1279 /* 1280 * Now the source is expanded, remove it from the list of children to 1281 * keep it from being processed. 1282 */ 1283 pgn->unmade--; 1284 Lst_Remove(&pgn->children, cln); 1285 Lst_Remove(&cgn->parents, Lst_FindDatum(&cgn->parents, pgn)); 1286 } 1287 1288 /* 1289 * Break the result into a vector of strings whose nodes we can find, then 1290 * add those nodes to the members list. 1291 * 1292 * Unfortunately, we can't use Str_Words because it doesn't understand about 1293 * variable expressions with spaces in them. 1294 */ 1295 static void 1296 ExpandChildrenRegular(char *cp, GNode *pgn, GNodeList *members) 1297 { 1298 char *start; 1299 1300 pp_skip_hspace(&cp); 1301 start = cp; 1302 while (*cp != '\0') { 1303 if (*cp == ' ' || *cp == '\t') { 1304 GNode *gn; 1305 /* 1306 * White-space -- terminate element, find the node, 1307 * add it, skip any further spaces. 1308 */ 1309 *cp++ = '\0'; 1310 gn = Targ_GetNode(start); 1311 Lst_Append(members, gn); 1312 pp_skip_hspace(&cp); 1313 /* Continue at the next non-space. */ 1314 start = cp; 1315 } else if (*cp == '$') { 1316 /* Skip over the variable expression. */ 1317 const char *nested_p = cp; 1318 FStr junk; 1319 1320 (void)Var_Parse(&nested_p, pgn, VARE_PARSE_ONLY, &junk); 1321 /* TODO: handle errors */ 1322 if (junk.str == var_Error) { 1323 Parse_Error(PARSE_FATAL, 1324 "Malformed variable expression at \"%s\"", 1325 cp); 1326 cp++; 1327 } else { 1328 cp += nested_p - cp; 1329 } 1330 1331 FStr_Done(&junk); 1332 } else if (cp[0] == '\\' && cp[1] != '\0') { 1333 /* Escaped something -- skip over it. */ 1334 /* 1335 * XXX: In other places, escaping at this syntactical 1336 * position is done by a '$', not a '\'. The '\' is 1337 * only used in variable modifiers. 1338 */ 1339 cp += 2; 1340 } else { 1341 cp++; 1342 } 1343 } 1344 1345 if (cp != start) { 1346 /* 1347 * Stuff left over -- add it to the list too 1348 */ 1349 GNode *gn = Targ_GetNode(start); 1350 Lst_Append(members, gn); 1351 } 1352 } 1353 1354 /* 1355 * Expand the names of any children of a given node that contain variable 1356 * expressions or file wildcards into actual targets. 1357 * 1358 * The expanded node is removed from the parent's list of children, and the 1359 * parent's unmade counter is decremented, but other nodes may be added. 1360 * 1361 * Input: 1362 * cln Child to examine 1363 * pgn Parent node being processed 1364 */ 1365 static void 1366 ExpandChildren(GNodeListNode *cln, GNode *pgn) 1367 { 1368 GNode *cgn = cln->datum; 1369 char *cp; /* Expanded value */ 1370 1371 if (!Lst_IsEmpty(&cgn->order_pred) || !Lst_IsEmpty(&cgn->order_succ)) 1372 /* It is all too hard to process the result of .ORDER */ 1373 return; 1374 1375 if (cgn->type & OP_WAIT) 1376 /* Ignore these (& OP_PHONY ?) */ 1377 return; 1378 1379 /* 1380 * First do variable expansion -- this takes precedence over wildcard 1381 * expansion. If the result contains wildcards, they'll be gotten to 1382 * later since the resulting words are tacked on to the end of the 1383 * children list. 1384 */ 1385 if (strchr(cgn->name, '$') == NULL) { 1386 ExpandWildcards(cln, pgn); 1387 return; 1388 } 1389 1390 DEBUG1(SUFF, "Expanding \"%s\"...", cgn->name); 1391 (void)Var_Subst(cgn->name, pgn, VARE_UNDEFERR, &cp); 1392 /* TODO: handle errors */ 1393 1394 { 1395 GNodeList members = LST_INIT; 1396 1397 if (cgn->type & OP_ARCHV) { 1398 /* 1399 * Node was an 'archive(member)' target, so 1400 * call on the Arch module to find the nodes for us, 1401 * expanding variables in the parent's scope. 1402 */ 1403 char *p = cp; 1404 (void)Arch_ParseArchive(&p, &members, pgn); 1405 } else { 1406 ExpandChildrenRegular(cp, pgn, &members); 1407 } 1408 1409 /* 1410 * Add all elements of the members list to the parent node. 1411 */ 1412 while (!Lst_IsEmpty(&members)) { 1413 GNode *gn = Lst_Dequeue(&members); 1414 1415 DEBUG1(SUFF, "%s...", gn->name); 1416 /* 1417 * Add gn to the parents child list before the 1418 * original child. 1419 */ 1420 Lst_InsertBefore(&pgn->children, cln, gn); 1421 Lst_Append(&gn->parents, pgn); 1422 pgn->unmade++; 1423 /* Expand wildcards on new node */ 1424 ExpandWildcards(cln->prev, pgn); 1425 } 1426 Lst_Done(&members); 1427 1428 free(cp); 1429 } 1430 1431 DEBUG0(SUFF, "\n"); 1432 1433 /* 1434 * Now the source is expanded, remove it from the list of children to 1435 * keep it from being processed. 1436 */ 1437 pgn->unmade--; 1438 Lst_Remove(&pgn->children, cln); 1439 Lst_Remove(&cgn->parents, Lst_FindDatum(&cgn->parents, pgn)); 1440 } 1441 1442 static void 1443 ExpandAllChildren(GNode *gn) 1444 { 1445 GNodeListNode *ln, *nln; 1446 1447 for (ln = gn->children.first; ln != NULL; ln = nln) { 1448 nln = ln->next; 1449 ExpandChildren(ln, gn); 1450 } 1451 } 1452 1453 /* 1454 * Find a path along which to expand the node. 1455 * 1456 * If the node has a known suffix, use that path. 1457 * If it has no known suffix, use the default system search path. 1458 * 1459 * Input: 1460 * gn Node being examined 1461 * 1462 * Results: 1463 * The appropriate path to search for the GNode. 1464 */ 1465 SearchPath * 1466 Suff_FindPath(GNode *gn) 1467 { 1468 Suffix *suff = gn->suffix; 1469 1470 if (suff == NULL) { 1471 char *name = gn->name; 1472 size_t nameLen = strlen(gn->name); 1473 SuffixListNode *ln; 1474 for (ln = sufflist.first; ln != NULL; ln = ln->next) 1475 if (Suffix_IsSuffix(ln->datum, nameLen, name + nameLen)) 1476 break; 1477 1478 DEBUG1(SUFF, "Wildcard expanding \"%s\"...", gn->name); 1479 if (ln != NULL) 1480 suff = ln->datum; 1481 /* 1482 * XXX: Here we can save the suffix so we don't have to do 1483 * this again. 1484 */ 1485 } 1486 1487 if (suff != NULL) { 1488 DEBUG1(SUFF, "suffix is \"%s\"...\n", suff->name); 1489 return suff->searchPath; 1490 } else { 1491 DEBUG0(SUFF, "\n"); 1492 return &dirSearchPath; /* Use default search path */ 1493 } 1494 } 1495 1496 /* 1497 * Apply a transformation rule, given the source and target nodes and 1498 * suffixes. 1499 * 1500 * The source and target are linked and the commands from the transformation 1501 * are added to the target node's commands list. The target also inherits all 1502 * the sources for the transformation rule. 1503 * 1504 * Results: 1505 * true if successful, false if not. 1506 */ 1507 static bool 1508 ApplyTransform(GNode *tgn, GNode *sgn, Suffix *tsuff, Suffix *ssuff) 1509 { 1510 GNodeListNode *ln; 1511 char *tname; /* Name of transformation rule */ 1512 GNode *gn; /* Node for the transformation rule */ 1513 1514 /* Form the proper links between the target and source. */ 1515 Lst_Append(&tgn->children, sgn); 1516 Lst_Append(&sgn->parents, tgn); 1517 tgn->unmade++; 1518 1519 /* Locate the transformation rule itself. */ 1520 tname = str_concat2(ssuff->name, tsuff->name); 1521 gn = FindTransformByName(tname); 1522 free(tname); 1523 1524 /* This can happen when linking an OP_MEMBER and OP_ARCHV node. */ 1525 if (gn == NULL) 1526 return false; 1527 1528 DEBUG3(SUFF, "\tapplying %s -> %s to \"%s\"\n", 1529 ssuff->name, tsuff->name, tgn->name); 1530 1531 /* Record last child; Make_HandleUse may add child nodes. */ 1532 ln = tgn->children.last; 1533 1534 /* Apply the rule. */ 1535 Make_HandleUse(gn, tgn); 1536 1537 /* Deal with wildcards and variables in any acquired sources. */ 1538 ln = ln != NULL ? ln->next : NULL; 1539 while (ln != NULL) { 1540 GNodeListNode *nln = ln->next; 1541 ExpandChildren(ln, tgn); 1542 ln = nln; 1543 } 1544 1545 /* 1546 * Keep track of another parent to which this node is transformed so 1547 * the .IMPSRC variable can be set correctly for the parent. 1548 */ 1549 Lst_Append(&sgn->implicitParents, tgn); 1550 1551 return true; 1552 } 1553 1554 /* 1555 * Member has a known suffix, so look for a transformation rule from 1556 * it to a possible suffix of the archive. 1557 * 1558 * Rather than searching through the entire list, we just look at 1559 * suffixes to which the member's suffix may be transformed. 1560 */ 1561 static void 1562 ExpandMember(GNode *gn, const char *eoarch, GNode *mem, Suffix *memSuff) 1563 { 1564 GNodeListNode *ln; 1565 size_t nameLen = (size_t)(eoarch - gn->name); 1566 1567 /* Use first matching suffix... */ 1568 for (ln = memSuff->parents.first; ln != NULL; ln = ln->next) 1569 if (Suffix_IsSuffix(ln->datum, nameLen, eoarch)) 1570 break; 1571 1572 if (ln != NULL) { 1573 /* Got one -- apply it */ 1574 Suffix *suff = ln->datum; 1575 if (!ApplyTransform(gn, mem, suff, memSuff)) { 1576 DEBUG2(SUFF, "\tNo transformation from %s -> %s\n", 1577 memSuff->name, suff->name); 1578 } 1579 } 1580 } 1581 1582 static void FindDeps(GNode *, CandidateSearcher *); 1583 1584 /* 1585 * Locate dependencies for an OP_ARCHV node. 1586 * 1587 * Input: 1588 * gn Node for which to locate dependencies 1589 * 1590 * Side Effects: 1591 * Same as Suff_FindDeps 1592 */ 1593 static void 1594 FindDepsArchive(GNode *gn, CandidateSearcher *cs) 1595 { 1596 char *eoarch; /* End of archive portion */ 1597 char *eoname; /* End of member portion */ 1598 GNode *mem; /* Node for member */ 1599 Suffix *memSuff; 1600 const char *name; /* Start of member's name */ 1601 1602 /* 1603 * The node is an archive(member) pair. so we must find a 1604 * suffix for both of them. 1605 */ 1606 eoarch = strchr(gn->name, '('); 1607 eoname = strchr(eoarch, ')'); 1608 1609 /* 1610 * Caller guarantees the format `libname(member)', via 1611 * Arch_ParseArchive. 1612 */ 1613 assert(eoarch != NULL); 1614 assert(eoname != NULL); 1615 1616 *eoname = '\0'; /* Nuke parentheses during suffix search */ 1617 *eoarch = '\0'; /* So a suffix can be found */ 1618 1619 name = eoarch + 1; 1620 1621 /* 1622 * To simplify things, call Suff_FindDeps recursively on the member 1623 * now, so we can simply compare the member's .PREFIX and .TARGET 1624 * variables to locate its suffix. This allows us to figure out the 1625 * suffix to use for the archive without having to do a quadratic 1626 * search over the suffix list, backtracking for each one. 1627 */ 1628 mem = Targ_GetNode(name); 1629 FindDeps(mem, cs); 1630 1631 /* Create the link between the two nodes right off. */ 1632 Lst_Append(&gn->children, mem); 1633 Lst_Append(&mem->parents, gn); 1634 gn->unmade++; 1635 1636 /* Copy in the variables from the member node to this one. */ 1637 Var_Set(gn, PREFIX, GNode_VarPrefix(mem)); 1638 Var_Set(gn, TARGET, GNode_VarTarget(mem)); 1639 1640 memSuff = mem->suffix; 1641 if (memSuff == NULL) { /* Didn't know what it was. */ 1642 DEBUG0(SUFF, "using null suffix\n"); 1643 memSuff = nullSuff; 1644 } 1645 1646 1647 /* Set the other two local variables required for this target. */ 1648 Var_Set(gn, MEMBER, name); 1649 Var_Set(gn, ARCHIVE, gn->name); 1650 /* Set $@ for compatibility with other makes. */ 1651 Var_Set(gn, TARGET, gn->name); 1652 1653 /* 1654 * Now we've got the important local variables set, expand any sources 1655 * that still contain variables or wildcards in their names. 1656 */ 1657 ExpandAllChildren(gn); 1658 1659 if (memSuff != NULL) 1660 ExpandMember(gn, eoarch, mem, memSuff); 1661 1662 /* 1663 * Replace the opening and closing parens now we've no need of the 1664 * separate pieces. 1665 */ 1666 *eoarch = '('; 1667 *eoname = ')'; 1668 1669 /* 1670 * Pretend gn appeared to the left of a dependency operator so the 1671 * user needn't provide a transformation from the member to the 1672 * archive. 1673 */ 1674 if (!GNode_IsTarget(gn)) 1675 gn->type |= OP_DEPENDS; 1676 1677 /* 1678 * Flag the member as such so we remember to look in the archive for 1679 * its modification time. The OP_JOIN | OP_MADE is needed because 1680 * this target should never get made. 1681 */ 1682 mem->type |= OP_MEMBER | OP_JOIN | OP_MADE; 1683 } 1684 1685 /* 1686 * If the node is a library, it is the arch module's job to find it 1687 * and set the TARGET variable accordingly. We merely provide the 1688 * search path, assuming all libraries end in ".a" (if the suffix 1689 * hasn't been defined, there's nothing we can do for it, so we just 1690 * set the TARGET variable to the node's name in order to give it a 1691 * value). 1692 */ 1693 static void 1694 FindDepsLib(GNode *gn) 1695 { 1696 Suffix *suff = FindSuffixByName(LIBSUFF); 1697 if (suff != NULL) { 1698 Suffix_Reassign(&gn->suffix, suff); 1699 Arch_FindLib(gn, suff->searchPath); 1700 } else { 1701 Suffix_Unassign(&gn->suffix); 1702 Var_Set(gn, TARGET, gn->name); 1703 } 1704 1705 /* 1706 * Because a library (-lfoo) target doesn't follow the standard 1707 * filesystem conventions, we don't set the regular variables for 1708 * the thing. .PREFIX is simply made empty. 1709 */ 1710 Var_Set(gn, PREFIX, ""); 1711 } 1712 1713 static void 1714 FindDepsRegularKnown(const char *name, size_t nameLen, GNode *gn, 1715 CandidateList *srcs, CandidateList *targs) 1716 { 1717 SuffixListNode *ln; 1718 Candidate *targ; 1719 char *pref; 1720 1721 for (ln = sufflist.first; ln != NULL; ln = ln->next) { 1722 Suffix *suff = ln->datum; 1723 if (!Suffix_IsSuffix(suff, nameLen, name + nameLen)) 1724 continue; 1725 1726 pref = bmake_strldup(name, (size_t)(nameLen - suff->nameLen)); 1727 targ = Candidate_New(bmake_strdup(gn->name), pref, suff, NULL, 1728 gn); 1729 1730 CandidateList_AddCandidatesFor(srcs, targ); 1731 1732 /* Record the target so we can nuke it. */ 1733 Lst_Append(targs, targ); 1734 } 1735 } 1736 1737 static void 1738 FindDepsRegularUnknown(GNode *gn, const char *sopref, 1739 CandidateList *srcs, CandidateList *targs) 1740 { 1741 Candidate *targ; 1742 1743 if (!Lst_IsEmpty(targs) || nullSuff == NULL) 1744 return; 1745 1746 DEBUG1(SUFF, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name); 1747 1748 targ = Candidate_New(bmake_strdup(gn->name), bmake_strdup(sopref), 1749 nullSuff, NULL, gn); 1750 1751 /* 1752 * Only use the default suffix rules if we don't have commands 1753 * defined for this gnode; traditional make programs used to not 1754 * define suffix rules if the gnode had children but we don't do 1755 * this anymore. 1756 */ 1757 if (Lst_IsEmpty(&gn->commands)) 1758 CandidateList_AddCandidatesFor(srcs, targ); 1759 else { 1760 DEBUG0(SUFF, "not "); 1761 } 1762 1763 DEBUG0(SUFF, "adding suffix rules\n"); 1764 1765 Lst_Append(targs, targ); 1766 } 1767 1768 /* 1769 * Deal with finding the thing on the default search path. We always do 1770 * that, not only if the node is only a source (not on the lhs of a 1771 * dependency operator or [XXX] it has neither children or commands) as 1772 * the old pmake did. 1773 */ 1774 static void 1775 FindDepsRegularPath(GNode *gn, Candidate *targ) 1776 { 1777 if (gn->type & (OP_PHONY | OP_NOPATH)) 1778 return; 1779 1780 free(gn->path); 1781 gn->path = Dir_FindFile(gn->name, 1782 targ == NULL ? &dirSearchPath : targ->suff->searchPath); 1783 if (gn->path == NULL) 1784 return; 1785 1786 Var_Set(gn, TARGET, gn->path); 1787 1788 if (targ != NULL) { 1789 /* 1790 * Suffix known for the thing -- trim the suffix off 1791 * the path to form the proper .PREFIX variable. 1792 */ 1793 size_t savep = strlen(gn->path) - targ->suff->nameLen; 1794 char savec; 1795 1796 Suffix_Reassign(&gn->suffix, targ->suff); 1797 1798 savec = gn->path[savep]; 1799 gn->path[savep] = '\0'; 1800 1801 Var_Set(gn, PREFIX, str_basename(gn->path)); 1802 1803 gn->path[savep] = savec; 1804 } else { 1805 /* 1806 * The .PREFIX gets the full path if the target has no 1807 * known suffix. 1808 */ 1809 Suffix_Unassign(&gn->suffix); 1810 Var_Set(gn, PREFIX, str_basename(gn->path)); 1811 } 1812 } 1813 1814 /* 1815 * Locate implicit dependencies for regular targets. 1816 * 1817 * Input: 1818 * gn Node for which to find sources 1819 * 1820 * Side Effects: 1821 * Same as Suff_FindDeps 1822 */ 1823 static void 1824 FindDepsRegular(GNode *gn, CandidateSearcher *cs) 1825 { 1826 /* List of sources at which to look */ 1827 CandidateList srcs = LST_INIT; 1828 /* 1829 * List of targets to which things can be transformed. 1830 * They all have the same file, but different suff and prefix fields. 1831 */ 1832 CandidateList targs = LST_INIT; 1833 Candidate *bottom; /* Start of found transformation path */ 1834 Candidate *src; 1835 Candidate *targ; 1836 1837 const char *name = gn->name; 1838 size_t nameLen = strlen(name); 1839 1840 #ifdef DEBUG_SRC 1841 DEBUG1(SUFF, "FindDepsRegular \"%s\"\n", gn->name); 1842 #endif 1843 1844 /* 1845 * We're caught in a catch-22 here. On the one hand, we want to use 1846 * any transformation implied by the target's sources, but we can't 1847 * examine the sources until we've expanded any variables/wildcards 1848 * they may hold, and we can't do that until we've set up the 1849 * target's local variables and we can't do that until we know what 1850 * the proper suffix for the target is (in case there are two 1851 * suffixes one of which is a suffix of the other) and we can't know 1852 * that until we've found its implied source, which we may not want 1853 * to use if there's an existing source that implies a different 1854 * transformation. 1855 * 1856 * In an attempt to get around this, which may not work all the time, 1857 * but should work most of the time, we look for implied sources 1858 * first, checking transformations to all possible suffixes of the 1859 * target, use what we find to set the target's local variables, 1860 * expand the children, then look for any overriding transformations 1861 * they imply. Should we find one, we discard the one we found before. 1862 */ 1863 bottom = NULL; 1864 targ = NULL; 1865 1866 if (!(gn->type & OP_PHONY)) { 1867 1868 FindDepsRegularKnown(name, nameLen, gn, &srcs, &targs); 1869 1870 /* Handle target of unknown suffix... */ 1871 FindDepsRegularUnknown(gn, name, &srcs, &targs); 1872 1873 /* 1874 * Using the list of possible sources built up from the target 1875 * suffix(es), try and find an existing file/target that 1876 * matches. 1877 */ 1878 bottom = FindThem(&srcs, cs); 1879 1880 if (bottom == NULL) { 1881 /* 1882 * No known transformations -- use the first suffix 1883 * found for setting the local variables. 1884 */ 1885 if (targs.first != NULL) 1886 targ = targs.first->datum; 1887 else 1888 targ = NULL; 1889 } else { 1890 /* 1891 * Work up the transformation path to find the suffix 1892 * of the target to which the transformation was made. 1893 */ 1894 for (targ = bottom; 1895 targ->parent != NULL; targ = targ->parent) 1896 continue; 1897 } 1898 } 1899 1900 Var_Set(gn, TARGET, GNode_Path(gn)); 1901 Var_Set(gn, PREFIX, targ != NULL ? targ->prefix : gn->name); 1902 1903 /* 1904 * Now we've got the important local variables set, expand any sources 1905 * that still contain variables or wildcards in their names. 1906 */ 1907 { 1908 GNodeListNode *ln, *nln; 1909 for (ln = gn->children.first; ln != NULL; ln = nln) { 1910 nln = ln->next; 1911 ExpandChildren(ln, gn); 1912 } 1913 } 1914 1915 if (targ == NULL) { 1916 DEBUG1(SUFF, "\tNo valid suffix on %s\n", gn->name); 1917 1918 sfnd_abort: 1919 FindDepsRegularPath(gn, targ); 1920 goto sfnd_return; 1921 } 1922 1923 /* 1924 * If the suffix indicates that the target is a library, mark that in 1925 * the node's type field. 1926 */ 1927 if (targ->suff->library) 1928 gn->type |= OP_LIB; 1929 1930 /* 1931 * Check for overriding transformation rule implied by sources 1932 */ 1933 if (!Lst_IsEmpty(&gn->children)) { 1934 src = FindCmds(targ, cs); 1935 1936 if (src != NULL) { 1937 /* 1938 * Free up all the candidates in the transformation 1939 * path, up to but not including the parent node. 1940 */ 1941 while (bottom != NULL && bottom->parent != NULL) { 1942 CandidateSearcher_AddIfNew(cs, bottom); 1943 bottom = bottom->parent; 1944 } 1945 bottom = src; 1946 } 1947 } 1948 1949 if (bottom == NULL) { 1950 /* No idea from where it can come -- return now. */ 1951 goto sfnd_abort; 1952 } 1953 1954 /* 1955 * We now have a list of candidates headed by 'bottom' and linked via 1956 * their 'parent' pointers. What we do next is create links between 1957 * source and target nodes (which may or may not have been created) 1958 * and set the necessary local variables in each target. 1959 * 1960 * The commands for each target are set from the commands of the 1961 * transformation rule used to get from the src suffix to the targ 1962 * suffix. Note that this causes the commands list of the original 1963 * node, gn, to be replaced with the commands of the final 1964 * transformation rule. 1965 */ 1966 if (bottom->node == NULL) 1967 bottom->node = Targ_GetNode(bottom->file); 1968 1969 for (src = bottom; src->parent != NULL; src = src->parent) { 1970 targ = src->parent; 1971 1972 Suffix_Reassign(&src->node->suffix, src->suff); 1973 1974 if (targ->node == NULL) 1975 targ->node = Targ_GetNode(targ->file); 1976 1977 ApplyTransform(targ->node, src->node, 1978 targ->suff, src->suff); 1979 1980 if (targ->node != gn) { 1981 /* 1982 * Finish off the dependency-search process for any 1983 * nodes between bottom and gn (no point in questing 1984 * around the filesystem for their implicit source 1985 * when it's already known). Note that the node 1986 * can't have any sources that need expanding, since 1987 * SuffFindThem will stop on an existing node, so all 1988 * we need to do is set the standard variables. 1989 */ 1990 targ->node->type |= OP_DEPS_FOUND; 1991 Var_Set(targ->node, PREFIX, targ->prefix); 1992 Var_Set(targ->node, TARGET, targ->node->name); 1993 } 1994 } 1995 1996 Suffix_Reassign(&gn->suffix, src->suff); 1997 1998 /* 1999 * Nuke the transformation path and the candidates left over in the 2000 * two lists. 2001 */ 2002 sfnd_return: 2003 if (bottom != NULL) 2004 CandidateSearcher_AddIfNew(cs, bottom); 2005 2006 while (RemoveCandidate(&srcs) || RemoveCandidate(&targs)) 2007 continue; 2008 2009 CandidateSearcher_MoveAll(cs, &srcs); 2010 CandidateSearcher_MoveAll(cs, &targs); 2011 } 2012 2013 static void 2014 CandidateSearcher_CleanUp(CandidateSearcher *cs) 2015 { 2016 while (RemoveCandidate(&cs->list)) 2017 continue; 2018 assert(Lst_IsEmpty(&cs->list)); 2019 } 2020 2021 2022 /* 2023 * Find implicit sources for the target. 2024 * 2025 * Nodes are added to the graph as children of the passed-in node. The nodes 2026 * are marked to have their IMPSRC variable filled in. The PREFIX variable 2027 * is set for the given node and all its implied children. 2028 * 2029 * The path found by this target is the shortest path in the transformation 2030 * graph, which may pass through nonexistent targets, to an existing target. 2031 * The search continues on all paths from the root suffix until a file is 2032 * found. I.e. if there's a path .o -> .c -> .l -> .l,v from the root and the 2033 * .l,v file exists but the .c and .l files don't, the search will branch out 2034 * in all directions from .o and again from all the nodes on the next level 2035 * until the .l,v node is encountered. 2036 */ 2037 void 2038 Suff_FindDeps(GNode *gn) 2039 { 2040 CandidateSearcher cs; 2041 2042 CandidateSearcher_Init(&cs); 2043 2044 FindDeps(gn, &cs); 2045 2046 CandidateSearcher_CleanUp(&cs); 2047 CandidateSearcher_Done(&cs); 2048 } 2049 2050 static void 2051 FindDeps(GNode *gn, CandidateSearcher *cs) 2052 { 2053 if (gn->type & OP_DEPS_FOUND) 2054 return; 2055 gn->type |= OP_DEPS_FOUND; 2056 2057 /* Make sure we have these set, may get revised below. */ 2058 Var_Set(gn, TARGET, GNode_Path(gn)); 2059 Var_Set(gn, PREFIX, gn->name); 2060 2061 DEBUG1(SUFF, "SuffFindDeps \"%s\"\n", gn->name); 2062 2063 if (gn->type & OP_ARCHV) 2064 FindDepsArchive(gn, cs); 2065 else if (gn->type & OP_LIB) 2066 FindDepsLib(gn); 2067 else 2068 FindDepsRegular(gn, cs); 2069 } 2070 2071 /* 2072 * Define which suffix is the null suffix. 2073 * 2074 * Need to handle the changing of the null suffix gracefully so the old 2075 * transformation rules don't just go away. 2076 * 2077 * Input: 2078 * name Name of null suffix 2079 */ 2080 void 2081 Suff_SetNull(const char *name) 2082 { 2083 Suffix *suff = FindSuffixByName(name); 2084 if (suff == NULL) { 2085 Parse_Error(PARSE_WARNING, 2086 "Desired null suffix %s not defined", 2087 name); 2088 return; 2089 } 2090 2091 if (nullSuff != NULL) 2092 nullSuff->isNull = false; 2093 suff->isNull = true; 2094 /* XXX: Here's where the transformation mangling would take place. */ 2095 nullSuff = suff; 2096 } 2097 2098 /* Initialize the suffixes module. */ 2099 void 2100 Suff_Init(void) 2101 { 2102 /* 2103 * Create null suffix for single-suffix rules (POSIX). The thing 2104 * doesn't actually go on the suffix list or everyone will think 2105 * that's its suffix. 2106 */ 2107 Suff_ClearSuffixes(); 2108 } 2109 2110 2111 /* Clean up the suffixes module. */ 2112 void 2113 Suff_End(void) 2114 { 2115 #ifdef CLEANUP 2116 Lst_DoneCall(&sufflist, SuffFree); 2117 Lst_DoneCall(&suffClean, SuffFree); 2118 if (nullSuff != NULL) 2119 SuffFree(nullSuff); 2120 Lst_Done(&transforms); 2121 #endif 2122 } 2123 2124 2125 static void 2126 PrintSuffNames(const char *prefix, const SuffixList *suffs) 2127 { 2128 SuffixListNode *ln; 2129 2130 debug_printf("#\t%s: ", prefix); 2131 for (ln = suffs->first; ln != NULL; ln = ln->next) { 2132 const Suffix *suff = ln->datum; 2133 debug_printf("%s ", suff->name); 2134 } 2135 debug_printf("\n"); 2136 } 2137 2138 static void 2139 Suffix_Print(const Suffix *suff) 2140 { 2141 Buffer buf; 2142 2143 Buf_InitSize(&buf, 16); 2144 Buf_AddFlag(&buf, suff->include, "SUFF_INCLUDE"); 2145 Buf_AddFlag(&buf, suff->library, "SUFF_LIBRARY"); 2146 Buf_AddFlag(&buf, suff->isNull, "SUFF_NULL"); 2147 2148 debug_printf("# \"%s\" (num %d, ref %d)", 2149 suff->name, suff->sNum, suff->refCount); 2150 if (buf.len > 0) 2151 debug_printf(" (%s)", buf.data); 2152 debug_printf("\n"); 2153 2154 Buf_Done(&buf); 2155 2156 PrintSuffNames("To", &suff->parents); 2157 PrintSuffNames("From", &suff->children); 2158 2159 debug_printf("#\tSearch Path: "); 2160 SearchPath_Print(suff->searchPath); 2161 debug_printf("\n"); 2162 } 2163 2164 static void 2165 PrintTransformation(GNode *t) 2166 { 2167 debug_printf("%-16s:", t->name); 2168 Targ_PrintType(t->type); 2169 debug_printf("\n"); 2170 Targ_PrintCmds(t); 2171 debug_printf("\n"); 2172 } 2173 2174 void 2175 Suff_PrintAll(void) 2176 { 2177 debug_printf("#*** Suffixes:\n"); 2178 { 2179 SuffixListNode *ln; 2180 for (ln = sufflist.first; ln != NULL; ln = ln->next) 2181 Suffix_Print(ln->datum); 2182 } 2183 2184 debug_printf("#*** Transformations:\n"); 2185 { 2186 GNodeListNode *ln; 2187 for (ln = transforms.first; ln != NULL; ln = ln->next) 2188 PrintTransformation(ln->datum); 2189 } 2190 } 2191 2192 char * 2193 Suff_NamesStr(void) 2194 { 2195 Buffer buf; 2196 SuffixListNode *ln; 2197 Suffix *suff; 2198 2199 Buf_InitSize(&buf, 16); 2200 for (ln = sufflist.first; ln != NULL; ln = ln->next) { 2201 suff = ln->datum; 2202 if (ln != sufflist.first) 2203 Buf_AddByte(&buf, ' '); 2204 Buf_AddStr(&buf, suff->name); 2205 } 2206 return Buf_DoneData(&buf); 2207 } 2208