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