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