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