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