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