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