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