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