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