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