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