1141104Sharti/*-
21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks
51590Srgrimes * All rights reserved.
61590Srgrimes *
71590Srgrimes * This code is derived from software contributed to Berkeley by
81590Srgrimes * Adam de Boor.
91590Srgrimes *
101590Srgrimes * Redistribution and use in source and binary forms, with or without
111590Srgrimes * modification, are permitted provided that the following conditions
121590Srgrimes * are met:
131590Srgrimes * 1. Redistributions of source code must retain the above copyright
141590Srgrimes *    notice, this list of conditions and the following disclaimer.
151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161590Srgrimes *    notice, this list of conditions and the following disclaimer in the
171590Srgrimes *    documentation and/or other materials provided with the distribution.
181590Srgrimes * 3. All advertising materials mentioning features or use of this software
191590Srgrimes *    must display the following acknowledgement:
201590Srgrimes *	This product includes software developed by the University of
211590Srgrimes *	California, Berkeley and its contributors.
221590Srgrimes * 4. Neither the name of the University nor the names of its contributors
231590Srgrimes *    may be used to endorse or promote products derived from this software
241590Srgrimes *    without specific prior written permission.
251590Srgrimes *
261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361590Srgrimes * SUCH DAMAGE.
3762833Swsanchez *
3862833Swsanchez * @(#)suff.c	8.4 (Berkeley) 3/21/94
391590Srgrimes */
401590Srgrimes
4162833Swsanchez#include <sys/cdefs.h>
4294587Sobrien__FBSDID("$FreeBSD$");
431590Srgrimes
441590Srgrimes/*-
451590Srgrimes * suff.c --
461590Srgrimes *	Functions to maintain suffix lists and find implicit dependents
471590Srgrimes *	using suffix transformation rules
481590Srgrimes *
491590Srgrimes * Interface:
501590Srgrimes *	Suff_Init 	    	Initialize all things to do with suffixes.
511590Srgrimes *
521590Srgrimes *	Suff_DoPaths	    	This function is used to make life easier
531590Srgrimes *	    	  	    	when searching for a file according to its
541590Srgrimes *	    	  	    	suffix. It takes the global search path,
551590Srgrimes *	    	  	    	as defined using the .PATH: target, and appends
561590Srgrimes *	    	  	    	its directories to the path of each of the
571590Srgrimes *	    	  	    	defined suffixes, as specified using
581590Srgrimes *	    	  	    	.PATH<suffix>: targets. In addition, all
591590Srgrimes *	    	  	    	directories given for suffixes labeled as
601590Srgrimes *	    	  	    	include files or libraries, using the .INCLUDES
611590Srgrimes *	    	  	    	or .LIBS targets, are played with using
621590Srgrimes *	    	  	    	Dir_MakeFlags to create the .INCLUDES and
631590Srgrimes *	    	  	    	.LIBS global variables.
641590Srgrimes *
651590Srgrimes *	Suff_ClearSuffixes  	Clear out all the suffixes and defined
661590Srgrimes *	    	  	    	transformations.
671590Srgrimes *
681590Srgrimes *	Suff_IsTransform    	Return TRUE if the passed string is the lhs
691590Srgrimes *	    	  	    	of a transformation rule.
701590Srgrimes *
711590Srgrimes *	Suff_AddSuffix	    	Add the passed string as another known suffix.
721590Srgrimes *
731590Srgrimes *	Suff_GetPath	    	Return the search path for the given suffix.
741590Srgrimes *
751590Srgrimes *	Suff_AddInclude	    	Mark the given suffix as denoting an include
761590Srgrimes *	    	  	    	file.
771590Srgrimes *
781590Srgrimes *	Suff_AddLib	    	Mark the given suffix as denoting a library.
791590Srgrimes *
801590Srgrimes *	Suff_AddTransform   	Add another transformation to the suffix
811590Srgrimes *	    	  	    	graph. Returns  GNode suitable for framing, I
821590Srgrimes *	    	  	    	mean, tacking commands, attributes, etc. on.
831590Srgrimes *
841590Srgrimes *	Suff_SetNull	    	Define the suffix to consider the suffix of
851590Srgrimes *	    	  	    	any file that doesn't have a known one.
861590Srgrimes *
871590Srgrimes *	Suff_FindDeps	    	Find implicit sources for and the location of
881590Srgrimes *	    	  	    	a target based on its suffix. Returns the
8969527Swill *	    	  	    	bottom-most node added to the graph or NULL
901590Srgrimes *	    	  	    	if the target had no implicit sources.
911590Srgrimes */
921590Srgrimes
93144020Sharti#include <sys/queue.h>
94143807Sharti#include <assert.h>
95141104Sharti#include <string.h>
96141104Sharti#include <stdlib.h>
971590Srgrimes
98141104Sharti#include "arch.h"
99142457Sharti#include "buf.h"
100141104Sharti#include "config.h"
101141104Sharti#include "dir.h"
102141104Sharti#include "globals.h"
103141104Sharti#include "GNode.h"
104141104Sharti#include "lst.h"
105141104Sharti#include "make.h"
106141104Sharti#include "parse.h"
107141104Sharti#include "str.h"
108141104Sharti#include "suff.h"
109141104Sharti#include "targ.h"
110141104Sharti#include "util.h"
111141104Sharti#include "var.h"
112141104Sharti
113138916Sharti/* Lst of suffixes */
114138916Shartistatic Lst sufflist = Lst_Initializer(sufflist);
1151590Srgrimes
116138916Sharti/* Lst of suffixes to be cleaned */
117138916Shartistatic Lst suffClean = Lst_Initializer(suffClean);
118138916Sharti
119138916Sharti/* Lst of sources */
120138916Shartistatic Lst srclist = Lst_Initializer(srclist);
121138916Sharti
122138916Sharti/* Lst of transformation rules */
123138916Shartistatic Lst transforms = Lst_Initializer(transforms);
124138916Sharti
125143407Sharti/* Counter for assigning suffix numbers */
126143407Shartistatic int sNum = 0;
1271590Srgrimes
1281590Srgrimes/*
1291590Srgrimes * Structure describing an individual suffix.
1301590Srgrimes */
131143411Shartitypedef struct Suff {
132143407Sharti	char	*name;		/* The suffix itself */
133143407Sharti	int	nameLen;	/* Length of the suffix */
134143407Sharti	short	flags;		/* Type of suffix */
135143407Sharti#define	SUFF_INCLUDE	0x01	/* One which is #include'd */
136143407Sharti#define	SUFF_LIBRARY	0x02	/* One which contains a library */
137143407Sharti#define	SUFF_NULL	0x04	/* The empty suffix */
138144020Sharti	struct Path searchPath;	/* Path for files with this suffix */
139143407Sharti	int	sNum;		/* The suffix number */
140143407Sharti	int	refCount;	/* Reference count of list membership */
141143407Sharti	Lst	parents;	/* Suffixes we have a transformation to */
142143407Sharti	Lst	children;	/* Suffixes we have a transformation from */
143143407Sharti	Lst	ref;		/* List of lists this suffix is referenced */
1441590Srgrimes} Suff;
1451590Srgrimes
1461590Srgrimes/*
1471590Srgrimes * Structure used in the search for implied sources.
1481590Srgrimes */
149143411Shartitypedef struct Src {
150143407Sharti	char	*file;		/* The file to look for */
151143407Sharti	char	*pref;		/* Prefix from which file was formed */
152143407Sharti	Suff	*suff;		/* The suffix on the file */
153143411Sharti	struct Src *parent;	/* The Src for which this is a source */
154143407Sharti	GNode	*node;		/* The node describing the file */
155143407Sharti	int	children;	/* Count of existing children (so we don't free
1561590Srgrimes				 * this thing too early or never nuke it) */
1575814Sjkh#ifdef DEBUG_SRC
158143407Sharti	Lst	cp;		/* Debug; children list */
1595814Sjkh#endif
1601590Srgrimes} Src;
1611590Srgrimes
162143407Sharti/* The NULL suffix for this run */
163143407Shartistatic Suff	*suffNull;
1641590Srgrimes
165143407Sharti/* The empty suffix required for POSIX single-suffix transformation rules */
166143407Shartistatic Suff	*emptySuff;
1671590Srgrimes
168138512Shartistatic void SuffFindDeps(GNode *, Lst *);
1691590Srgrimes
170141271Sharti
1711590Srgrimes/*-
1721590Srgrimes *-----------------------------------------------------------------------
1731590Srgrimes * SuffSuffIsSuffix  --
174143807Sharti *	See if suff is a suffix of str.
1751590Srgrimes *
1761590Srgrimes * Results:
1771590Srgrimes *	NULL if it ain't, pointer to character in str before suffix if
1781590Srgrimes *	it is.
1791590Srgrimes *
1801590Srgrimes * Side Effects:
1811590Srgrimes *	None
1821590Srgrimes *-----------------------------------------------------------------------
1831590Srgrimes */
1841590Srgrimesstatic char *
185138561ShartiSuffSuffIsSuffix(const Suff *s, char *str)
1861590Srgrimes{
187143407Sharti	const char	*p1;	/* Pointer into suffix name */
188143407Sharti	char		*p2;	/* Pointer into string being examined */
189143807Sharti	size_t		len;
1901590Srgrimes
191143807Sharti	len = strlen(str);
192143407Sharti	p1 = s->name + s->nameLen;
193143807Sharti	p2 = str + len;
1941590Srgrimes
195143807Sharti	while (p1 >= s->name && len > 0 && *p1 == *p2) {
196143407Sharti		p1--;
197143407Sharti		p2--;
198143807Sharti		len--;
199143407Sharti	}
2001590Srgrimes
201143407Sharti	return (p1 == s->name - 1 ? p2 : NULL);
2021590Srgrimes}
2031590Srgrimes
2041590Srgrimes/*-
2051590Srgrimes *-----------------------------------------------------------------------
206143911Sharti * SuffSuffFind --
207143911Sharti *	Find a suffix given its name.
2081590Srgrimes *
2091590Srgrimes * Results:
210143911Sharti *	The suffix or NULL.
2111590Srgrimes *
2121590Srgrimes * Side Effects:
2131590Srgrimes *	None
2141590Srgrimes *-----------------------------------------------------------------------
2151590Srgrimes */
216143911Shartistatic Suff *
217143911ShartiSuffSuffFind(const char *s)
2181590Srgrimes{
219143911Sharti	LstNode	*ln;
220138232Sharti
221143911Sharti	LST_FOREACH(ln, &sufflist) {
222143911Sharti		if (strcmp(s, ((const Suff *)Lst_Datum(ln))->name) == 0)
223143911Sharti			return (Lst_Datum(ln));
224143911Sharti	}
225143911Sharti	return (NULL);
2261590Srgrimes}
2271590Srgrimes
2281590Srgrimes/*-
2291590Srgrimes *-----------------------------------------------------------------------
230143911Sharti * SuffTransFind
231143911Sharti *	Find a transform.
2321590Srgrimes *
2331590Srgrimes * Results:
234143911Sharti *	transform or NULL.
2351590Srgrimes *
2361590Srgrimes * Side Effects:
2371590Srgrimes *	None
2381590Srgrimes *-----------------------------------------------------------------------
2391590Srgrimes */
240143911Shartistatic GNode *
241143911ShartiSuffTransFind(const char *name)
2421590Srgrimes{
243143911Sharti	LstNode	*ln;
244138232Sharti
245143911Sharti	LST_FOREACH(ln, &transforms) {
246143911Sharti		if (strcmp(name, ((const GNode *)Lst_Datum(ln))->name) == 0)
247143911Sharti			return (Lst_Datum(ln));
248138561Sharti	}
249143911Sharti	return (NULL);
2501590Srgrimes}
2511590Srgrimes
2521590Srgrimes 	    /*********** Maintenance Functions ************/
2535814Sjkh
254138972Sharti#if 0
255138972Sharti/*
256138972Sharti * Keep this function for now until it is clear why a .SUFFIXES: doesn't
257138972Sharti * actually delete the suffixes but just puts them on the suffClean list.
258138972Sharti */
2591590Srgrimes/*-
2601590Srgrimes *-----------------------------------------------------------------------
2611590Srgrimes * SuffFree  --
2621590Srgrimes *	Free up all memory associated with the given suffix structure.
2631590Srgrimes *
2641590Srgrimes * Results:
2651590Srgrimes *	none
2661590Srgrimes *
2671590Srgrimes * Side Effects:
2681590Srgrimes *	the suffix entry is detroyed
2691590Srgrimes *-----------------------------------------------------------------------
2701590Srgrimes */
2711590Srgrimesstatic void
272138232ShartiSuffFree(void *sp)
2731590Srgrimes{
274143407Sharti	Suff *s = sp;
2755814Sjkh
276143407Sharti	if (s == suffNull)
277143407Sharti		suffNull = NULL;
2785814Sjkh
279143407Sharti	if (s == emptySuff)
280143407Sharti		emptySuff = NULL;
2815814Sjkh
282143407Sharti	Lst_Destroy(&s->ref, NOFREE);
283143407Sharti	Lst_Destroy(&s->children, NOFREE);
284143407Sharti	Lst_Destroy(&s->parents, NOFREE);
285143407Sharti	Lst_Destroy(&s->searchPath, Dir_Destroy);
2865814Sjkh
287143407Sharti	free(s->name);
288143407Sharti	free(s);
2891590Srgrimes}
290138972Sharti#endif
2911590Srgrimes
2921590Srgrimes/*-
2931590Srgrimes *-----------------------------------------------------------------------
2945814Sjkh * SuffRemove  --
2955814Sjkh *	Remove the suffix into the list
2965814Sjkh *
2975814Sjkh * Results:
2985814Sjkh *	None
2995814Sjkh *
3005814Sjkh * Side Effects:
30135464Sphk *	The reference count for the suffix is decremented
3025814Sjkh *-----------------------------------------------------------------------
3035814Sjkh */
3045814Sjkhstatic void
305138512ShartiSuffRemove(Lst *l, Suff *s)
3065814Sjkh{
307143407Sharti	LstNode	*ln = Lst_Member(l, s);
308138264Sharti
309143407Sharti	if (ln != NULL) {
310143407Sharti		Lst_Remove(l, ln);
311143407Sharti		s->refCount--;
312143407Sharti	}
3135814Sjkh}
314138232Sharti
3155814Sjkh/*-
3165814Sjkh *-----------------------------------------------------------------------
3171590Srgrimes * SuffInsert  --
3181590Srgrimes *	Insert the suffix into the list keeping the list ordered by suffix
3191590Srgrimes *	numbers.
3201590Srgrimes *
3211590Srgrimes * Results:
3221590Srgrimes *	None
3231590Srgrimes *
3241590Srgrimes * Side Effects:
3255814Sjkh *	The reference count of the suffix is incremented
3261590Srgrimes *-----------------------------------------------------------------------
3271590Srgrimes */
3281590Srgrimesstatic void
329138512ShartiSuffInsert(Lst *l, Suff *s)
3301590Srgrimes{
331143407Sharti	LstNode	*ln;	/* current element in l we're examining */
332143407Sharti	Suff	*s2;	/* the suffix descriptor in this element */
3331590Srgrimes
334143407Sharti	s2 = NULL;
335143407Sharti	for (ln = Lst_First(l); ln != NULL; ln = Lst_Succ(ln)) {
336143407Sharti		s2 = Lst_Datum(ln);
337143407Sharti		if (s2->sNum >= s->sNum)
338143407Sharti			break;
339143407Sharti	}
340143407Sharti	if (s2 == NULL) {
341143407Sharti		DEBUGF(SUFF, ("inserting an empty list?..."));
342143407Sharti	}
3431590Srgrimes
344143407Sharti	DEBUGF(SUFF, ("inserting %s(%d)...", s->name, s->sNum));
345143407Sharti	if (ln == NULL) {
346143407Sharti		DEBUGF(SUFF, ("at end of list\n"));
347143407Sharti		Lst_AtEnd(l, s);
348143407Sharti		s->refCount++;
349143407Sharti		Lst_AtEnd(&s->ref, l);
350143407Sharti	} else if (s2->sNum != s->sNum) {
351143407Sharti		DEBUGF(SUFF, ("before %s(%d)\n", s2->name, s2->sNum));
352143407Sharti		Lst_Insert(l, ln, s);
353143407Sharti		s->refCount++;
354143407Sharti		Lst_AtEnd(&s->ref, l);
355143407Sharti	} else {
356143407Sharti		DEBUGF(SUFF, ("already there\n"));
357143407Sharti	}
3581590Srgrimes}
3591590Srgrimes
3601590Srgrimes/*-
3611590Srgrimes *-----------------------------------------------------------------------
3621590Srgrimes * Suff_ClearSuffixes --
3631590Srgrimes *	This is gross. Nuke the list of suffixes but keep all transformation
3641590Srgrimes *	rules around. The transformation graph is destroyed in this process,
3651590Srgrimes *	but we leave the list of rules so when a new graph is formed the rules
3661590Srgrimes *	will remain.
3671590Srgrimes *	This function is called from the parse module when a
3681590Srgrimes *	.SUFFIXES:\n line is encountered.
3691590Srgrimes *
3701590Srgrimes * Results:
3711590Srgrimes *	none
3721590Srgrimes *
3731590Srgrimes * Side Effects:
3741590Srgrimes *	the sufflist and its graph nodes are destroyed
3751590Srgrimes *-----------------------------------------------------------------------
3761590Srgrimes */
3771590Srgrimesvoid
378138232ShartiSuff_ClearSuffixes(void)
3791590Srgrimes{
380138232Sharti
381143407Sharti	Lst_Concat(&suffClean, &sufflist, LST_CONCLINK);
382138916Sharti
383143407Sharti	sNum = 1;
384143407Sharti	suffNull = emptySuff;
385143407Sharti	/*
386143407Sharti	 * Clear suffNull's children list (the other suffixes are built new, but
387143407Sharti	 * suffNull is used as is).
388143407Sharti	 * NOFREE is used because all suffixes are are on the suffClean list.
389143407Sharti	 * suffNull should not have parents.
390143407Sharti	 */
391143407Sharti	Lst_Destroy(&suffNull->children, NOFREE);
3921590Srgrimes}
3931590Srgrimes
3941590Srgrimes/*-
3951590Srgrimes *-----------------------------------------------------------------------
3961590Srgrimes * SuffParseTransform --
3971590Srgrimes *	Parse a transformation string to find its two component suffixes.
3981590Srgrimes *
3991590Srgrimes * Results:
4001590Srgrimes *	TRUE if the string is a valid transformation and FALSE otherwise.
4011590Srgrimes *
4021590Srgrimes * Side Effects:
4031590Srgrimes *	The passed pointers are overwritten.
4041590Srgrimes *
4051590Srgrimes *-----------------------------------------------------------------------
4061590Srgrimes */
4071590Srgrimesstatic Boolean
408104696SjmallettSuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr)
4091590Srgrimes{
410143407Sharti	LstNode	*srcLn;		/* element in suffix list of trans source*/
411143407Sharti	Suff	*src;		/* Source of transformation */
412143407Sharti	char	*str2;		/* Extra pointer (maybe target suffix) */
413143407Sharti	LstNode	*singleLn;	/* element in suffix list of any suffix
414143407Sharti				 * that exactly matches str */
415143407Sharti	Suff	*single = NULL;	/* Source of possible transformation to
416143407Sharti				 * null suffix */
4171590Srgrimes
418143407Sharti	singleLn = NULL;
4198874Srgrimes
420143407Sharti	/*
421143407Sharti	 * Loop looking first for a suffix that matches the start of the
422143407Sharti	 * string and then for one that exactly matches the rest of it. If
423143407Sharti	 * we can find two that meet these criteria, we've successfully
424143407Sharti	 * parsed the string.
425143407Sharti	 */
426143911Sharti	srcLn = Lst_First(&sufflist);
427143407Sharti	for (;;) {
428143911Sharti		/* advance to next possible suffix */
429143911Sharti		while (srcLn != NULL) {
430143911Sharti			src = Lst_Datum(srcLn);
431143911Sharti			if (strncmp(str, src->name, strlen(src->name)) == 0)
432143911Sharti				break;
433143911Sharti			srcLn = LST_NEXT(srcLn);
434143407Sharti		}
435143911Sharti
436143407Sharti		if (srcLn == NULL) {
437143407Sharti			/*
438143407Sharti			 * Ran out of source suffixes -- no such rule
439143407Sharti			 */
440143407Sharti			if (singleLn != NULL) {
441143407Sharti				/*
442143407Sharti				 * Not so fast Mr. Smith! There was a suffix
443143407Sharti				 * that encompassed the entire string, so we
444143407Sharti				 * assume it was a transformation to the null
445143407Sharti				 * suffix (thank you POSIX). We still prefer to
446143407Sharti				 * find a double rule over a singleton, hence we
447143407Sharti				 * leave this check until the end.
448143407Sharti				 *
449143407Sharti				 * XXX: Use emptySuff over suffNull?
450143407Sharti				 */
451143407Sharti				*srcPtr = single;
452143407Sharti				*targPtr = suffNull;
453143407Sharti				return (TRUE);
454143407Sharti			}
455143407Sharti			return (FALSE);
456143407Sharti		}
457143407Sharti		str2 = str + src->nameLen;
458143407Sharti		if (*str2 == '\0') {
459143407Sharti			single = src;
460143407Sharti			singleLn = srcLn;
461143407Sharti		} else {
462143911Sharti
463143911Sharti			*targPtr = SuffSuffFind(str2);
464143911Sharti			if (*targPtr != NULL) {
465143407Sharti				*srcPtr = src;
466143407Sharti				return (TRUE);
467143407Sharti			}
468143407Sharti		}
469143911Sharti		/* next one */
470143911Sharti		srcLn = LST_NEXT(srcLn);
4711590Srgrimes	}
4721590Srgrimes}
4731590Srgrimes
4741590Srgrimes/*-
4751590Srgrimes *-----------------------------------------------------------------------
4761590Srgrimes * Suff_IsTransform  --
4771590Srgrimes *	Return TRUE if the given string is a transformation rule
4781590Srgrimes *
4791590Srgrimes *
4801590Srgrimes * Results:
4811590Srgrimes *	TRUE if the string is a concatenation of two known suffixes.
4821590Srgrimes *	FALSE otherwise
4831590Srgrimes *
4841590Srgrimes * Side Effects:
4851590Srgrimes *	None
4861590Srgrimes *-----------------------------------------------------------------------
4871590Srgrimes */
4881590SrgrimesBoolean
489138232ShartiSuff_IsTransform(char *str)
4901590Srgrimes{
491143407Sharti	Suff	*src, *targ;
4921590Srgrimes
493143407Sharti	return (SuffParseTransform(str, &src, &targ));
4941590Srgrimes}
4951590Srgrimes
4961590Srgrimes/*-
4971590Srgrimes *-----------------------------------------------------------------------
4981590Srgrimes * Suff_AddTransform --
4991590Srgrimes *	Add the transformation rule described by the line to the
5001590Srgrimes *	list of rules and place the transformation itself in the graph
5011590Srgrimes *
5021590Srgrimes * Results:
5031590Srgrimes *	The node created for the transformation in the transforms list
5041590Srgrimes *
5051590Srgrimes * Side Effects:
5061590Srgrimes *	The node is placed on the end of the transforms Lst and links are
5071590Srgrimes *	made between the two suffixes mentioned in the target name
5081590Srgrimes *-----------------------------------------------------------------------
5091590Srgrimes */
5101590SrgrimesGNode *
511138232ShartiSuff_AddTransform(char *line)
5121590Srgrimes{
513143407Sharti	GNode	*gn;	/* GNode of transformation rule */
514143407Sharti	Suff	*s;	/* source suffix */
515143407Sharti	Suff	*t;	/* target suffix */
5161590Srgrimes
517187475Srdivacky	s = t = NULL;	/* silence gcc */
518143911Sharti	gn = SuffTransFind(line);
519143911Sharti	if (gn == NULL) {
520143407Sharti		/*
521143407Sharti		 * Make a new graph node for the transformation.
522143407Sharti		 * It will be filled in by the Parse module.
523143407Sharti		 */
524143407Sharti		gn = Targ_NewGN(line);
525143407Sharti		Lst_AtEnd(&transforms, gn);
526143407Sharti	} else {
527143407Sharti		/*
528143407Sharti		 * New specification for transformation rule. Just nuke the
529143407Sharti		 * old list of commands so they can be filled in again...
530143407Sharti		 * We don't actually free the commands themselves, because a
531143407Sharti		 * given command can be attached to several different
532143407Sharti		 * transformations.
533143407Sharti		 */
534143407Sharti		Lst_Destroy(&gn->commands, NOFREE);
535143407Sharti		Lst_Destroy(&gn->children, NOFREE);
536143407Sharti	}
5371590Srgrimes
538143407Sharti	gn->type = OP_TRANSFORM;
5391590Srgrimes
540143407Sharti	SuffParseTransform(line, &s, &t);
5411590Srgrimes
542143407Sharti	/*
543143407Sharti	 * link the two together in the proper relationship and order
544143407Sharti	 */
545143407Sharti	DEBUGF(SUFF, ("defining transformation from `%s' to `%s'\n",
546143407Sharti	    s->name, t->name));
547143407Sharti	SuffInsert(&t->children, s);
548143407Sharti	SuffInsert(&s->parents, t);
5491590Srgrimes
550143407Sharti	return (gn);
5511590Srgrimes}
5521590Srgrimes
5531590Srgrimes/*-
5541590Srgrimes *-----------------------------------------------------------------------
5551590Srgrimes * Suff_EndTransform --
5561590Srgrimes *	Handle the finish of a transformation definition, removing the
5571590Srgrimes *	transformation from the graph if it has neither commands nor
558143372Sharti *	sources. This is called from the Parse module at the end of
559143372Sharti *	a dependency block.
5601590Srgrimes *
5611590Srgrimes * Side Effects:
5621590Srgrimes *	If the node has no commands or children, the children and parents
5631590Srgrimes *	lists of the affected suffices are altered.
5641590Srgrimes *
5651590Srgrimes *-----------------------------------------------------------------------
5661590Srgrimes */
567143372Shartivoid
568143372ShartiSuff_EndTransform(const GNode *gn)
5691590Srgrimes{
570143372Sharti	Suff	*s, *t;
5718874Srgrimes
572143372Sharti	if (!Lst_IsEmpty(&gn->commands) || !Lst_IsEmpty(&gn->children)) {
573143372Sharti		DEBUGF(SUFF, ("transformation %s complete\n", gn->name));
574143372Sharti		return;
575143372Sharti	}
5761590Srgrimes
577143372Sharti	/*
578143372Sharti	 * SuffParseTransform() may fail for special rules which are not
579143372Sharti	 * actual transformation rules (e.g., .DEFAULT).
580143372Sharti	 */
581143372Sharti	if (!SuffParseTransform(gn->name, &s, &t))
582143372Sharti		return;
5831590Srgrimes
584143372Sharti	DEBUGF(SUFF, ("deleting transformation from `%s' to `%s'\n",
585143372Sharti	    s->name, t->name));
5861590Srgrimes
587143372Sharti	/*
588143372Sharti	 * Remove the source from the target's children list. We check
589143372Sharti	 * for a NULL return to handle a beanhead saying something like
590143372Sharti	 *  .c.o .c.o:
591143372Sharti	 *
592143372Sharti	 * We'll be called twice when the next target is seen, but .c
593143372Sharti	 * and .o are only linked once...
594143372Sharti	 */
595143372Sharti	SuffRemove(&t->children, s);
5961590Srgrimes
597143372Sharti	/*
598143372Sharti	 * Remove the target from the source's parents list
599143372Sharti	 */
600143372Sharti	SuffRemove(&s->parents, t);
6011590Srgrimes}
6021590Srgrimes
6031590Srgrimes/*-
6041590Srgrimes *-----------------------------------------------------------------------
6051590Srgrimes * SuffRebuildGraph --
606143556Sharti *	Called from Suff_AddSuffix via LST_FOREACH to search through the
6071590Srgrimes *	list of existing transformation rules and rebuild the transformation
6081590Srgrimes *	graph when it has been destroyed by Suff_ClearSuffixes. If the
6091590Srgrimes *	given rule is a transformation involving this suffix and another,
6101590Srgrimes *	existing suffix, the proper relationship is established between
6111590Srgrimes *	the two.
6121590Srgrimes *
6131590Srgrimes * Side Effects:
6141590Srgrimes *	The appropriate links will be made between this suffix and
6151590Srgrimes *	others if transformation rules exist for it.
6161590Srgrimes *
6171590Srgrimes *-----------------------------------------------------------------------
6181590Srgrimes */
619143556Shartistatic void
620143556ShartiSuffRebuildGraph(const GNode *transform, Suff *s)
6211590Srgrimes{
622143407Sharti	char	*cp;
623143407Sharti	Suff	*s2 = NULL;
6241590Srgrimes
625143407Sharti	/*
626143407Sharti	 * First see if it is a transformation from this suffix.
627143407Sharti	 */
628143911Sharti	if (strncmp(transform->name, s->name, strlen(s->name)) == 0) {
629143911Sharti		cp = transform->name + strlen(s->name);
630143911Sharti
631143407Sharti		if (cp[0] == '\0')  /* null rule */
632143407Sharti			s2 = suffNull;
633143911Sharti		else
634143911Sharti			s2 = SuffSuffFind(cp);
635143407Sharti		if (s2 != NULL) {
636143407Sharti			/*
637143407Sharti			 * Found target. Link in and return, since it can't be
638143407Sharti			 * anything else.
639143407Sharti			 */
640143407Sharti			SuffInsert(&s2->children, s);
641143407Sharti			SuffInsert(&s->parents, s2);
642143556Sharti			return;
643143407Sharti		}
64473970Stmm	}
6451590Srgrimes
6461590Srgrimes	/*
647143807Sharti	 * Not from, maybe to?
648143807Sharti	 */
649143807Sharti	cp = SuffSuffIsSuffix(s, transform->name);
650143407Sharti	if (cp != NULL) {
651143407Sharti		/*
652143407Sharti		 * Null-terminate the source suffix in order to find it.
653143407Sharti		 */
654143407Sharti		cp[1] = '\0';
655143911Sharti		s2 = SuffSuffFind(transform->name);
656143911Sharti
657143407Sharti		/*
658143407Sharti		 * Replace the start of the target suffix
659143407Sharti		 */
660143407Sharti		cp[1] = s->name[0];
661143911Sharti		if (s2 != NULL) {
662143407Sharti			/*
663143407Sharti			 * Found it -- establish the proper relationship
664143407Sharti			 */
665143407Sharti			SuffInsert(&s->children, s2);
666143407Sharti			SuffInsert(&s2->parents, s);
667143407Sharti		}
6681590Srgrimes	}
6691590Srgrimes}
6701590Srgrimes
6711590Srgrimes/*-
6721590Srgrimes *-----------------------------------------------------------------------
6731590Srgrimes * Suff_AddSuffix --
6741590Srgrimes *	Add the suffix in string to the end of the list of known suffixes.
6751590Srgrimes *	Should we restructure the suffix graph? Make doesn't...
6761590Srgrimes *
6771590Srgrimes * Results:
6781590Srgrimes *	None
6791590Srgrimes *
6801590Srgrimes * Side Effects:
6811590Srgrimes *	A GNode is created for the suffix and a Suff structure is created and
6821590Srgrimes *	added to the suffixes list unless the suffix was already known.
6831590Srgrimes *-----------------------------------------------------------------------
6841590Srgrimes */
6851590Srgrimesvoid
686138232ShartiSuff_AddSuffix(char *str)
6871590Srgrimes{
688143407Sharti	Suff	*s;	/* new suffix descriptor */
689143407Sharti	LstNode	*ln;
6901590Srgrimes
691143911Sharti	if (SuffSuffFind(str) != NULL)
692143556Sharti		/*
693143556Sharti		 * Already known
694143556Sharti		 */
695143556Sharti		return;
6961590Srgrimes
697143556Sharti	s = emalloc(sizeof(Suff));
6981590Srgrimes
699143556Sharti	s->name = estrdup(str);
700143556Sharti	s->nameLen = strlen(s->name);
701144020Sharti	TAILQ_INIT(&s->searchPath);
702143556Sharti	Lst_Init(&s->children);
703143556Sharti	Lst_Init(&s->parents);
704143556Sharti	Lst_Init(&s->ref);
705143556Sharti	s->sNum = sNum++;
706143556Sharti	s->flags = 0;
707143556Sharti	s->refCount = 0;
708138264Sharti
709143556Sharti	Lst_AtEnd(&sufflist, s);
710143556Sharti
711143556Sharti	/*
712143556Sharti	 * Look for any existing transformations from or to this suffix.
713143556Sharti	 * XXX: Only do this after a Suff_ClearSuffixes?
714143556Sharti	 */
715143556Sharti	LST_FOREACH(ln, &transforms)
716143556Sharti		SuffRebuildGraph(Lst_Datum(ln), s);
7171590Srgrimes}
7181590Srgrimes
7191590Srgrimes/*-
7201590Srgrimes *-----------------------------------------------------------------------
7211590Srgrimes * Suff_GetPath --
7221590Srgrimes *	Return the search path for the given suffix, if it's defined.
7231590Srgrimes *
7241590Srgrimes * Results:
72569527Swill *	The searchPath for the desired suffix or NULL if the suffix isn't
7261590Srgrimes *	defined.
7271590Srgrimes *
7281590Srgrimes * Side Effects:
7291590Srgrimes *	None
7301590Srgrimes *-----------------------------------------------------------------------
7311590Srgrimes */
732144020Shartistruct Path *
733138232ShartiSuff_GetPath(char *sname)
7341590Srgrimes{
735143407Sharti	Suff	*s;
7361590Srgrimes
737143911Sharti	s = SuffSuffFind(sname);
738143911Sharti	if (s == NULL)
739143407Sharti		return (NULL);
740143911Sharti	return (&s->searchPath);
7411590Srgrimes}
7421590Srgrimes
7431590Srgrimes/*-
7441590Srgrimes *-----------------------------------------------------------------------
7451590Srgrimes * Suff_DoPaths --
7461590Srgrimes *	Extend the search paths for all suffixes to include the default
7471590Srgrimes *	search path.
7481590Srgrimes *
7491590Srgrimes * Results:
7501590Srgrimes *	None.
7511590Srgrimes *
7521590Srgrimes * Side Effects:
7531590Srgrimes *	The searchPath field of all the suffixes is extended by the
7541590Srgrimes *	directories in dirSearchPath. If paths were specified for the
7551590Srgrimes *	".h" suffix, the directories are stuffed into a global variable
75672645Sasmodai *	called ".INCLUDES" with each directory preceded by a -I. The same
7571590Srgrimes *	is done for the ".a" suffix, except the variable is called
7581590Srgrimes *	".LIBS" and the flag is -L.
7591590Srgrimes *-----------------------------------------------------------------------
7601590Srgrimes */
7611590Srgrimesvoid
762104696SjmallettSuff_DoPaths(void)
7631590Srgrimes{
764143407Sharti	Suff	*s;
765143407Sharti	LstNode	*ln;
766143407Sharti	char	*ptr;
767144020Sharti	struct Path inIncludes;	/* Cumulative .INCLUDES path */
768144020Sharti	struct Path inLibs;	/* Cumulative .LIBS path */
7691590Srgrimes
770144020Sharti	TAILQ_INIT(&inIncludes);
771144020Sharti	TAILQ_INIT(&inLibs);
7721590Srgrimes
773143407Sharti	for (ln = Lst_First(&sufflist); ln != NULL; ln = Lst_Succ(ln)) {
774143407Sharti		s = Lst_Datum(ln);
7751590Srgrimes#ifdef INCLUDES
776144020Sharti		if (s->flags & SUFF_INCLUDE) {
777144020Sharti			Path_Concat(&inIncludes, &s->searchPath);
778144020Sharti		}
7791590Srgrimes#endif /* INCLUDES */
7801590Srgrimes#ifdef LIBRARIES
781144020Sharti		if (s->flags & SUFF_LIBRARY) {
782144020Sharti			Path_Concat(&inLibs, &s->searchPath);
783144020Sharti		}
7841590Srgrimes#endif /* LIBRARIES */
785144020Sharti		Path_Concat(&s->searchPath, &dirSearchPath);
7861590Srgrimes	}
7871590Srgrimes
788144020Sharti	ptr = Path_MakeFlags("-I", &inIncludes);
789186558Sobrien	Var_SetGlobal(".INCLUDES", ptr);
790143407Sharti	free(ptr);
791144020Sharti
792144020Sharti	ptr = Path_MakeFlags("-L", &inLibs);
793186558Sobrien	Var_SetGlobal(".LIBS", ptr);
794143407Sharti	free(ptr);
7951590Srgrimes
796144020Sharti	Path_Clear(&inIncludes);
797144020Sharti	Path_Clear(&inLibs);
7981590Srgrimes}
7991590Srgrimes
8001590Srgrimes/*-
8011590Srgrimes *-----------------------------------------------------------------------
8021590Srgrimes * Suff_AddInclude --
8031590Srgrimes *	Add the given suffix as a type of file which gets included.
8041590Srgrimes *	Called from the parse module when a .INCLUDES line is parsed.
8051590Srgrimes *	The suffix must have already been defined.
8061590Srgrimes *
8071590Srgrimes * Results:
8081590Srgrimes *	None.
8091590Srgrimes *
8101590Srgrimes * Side Effects:
8111590Srgrimes *	The SUFF_INCLUDE bit is set in the suffix's flags field
8121590Srgrimes *
8131590Srgrimes *-----------------------------------------------------------------------
8141590Srgrimes */
8151590Srgrimesvoid
816138232ShartiSuff_AddInclude(char *sname)
8171590Srgrimes{
818143407Sharti	Suff	*s;
8191590Srgrimes
820143911Sharti	if ((s = SuffSuffFind(sname)) != NULL)
821143407Sharti		s->flags |= SUFF_INCLUDE;
8221590Srgrimes}
8231590Srgrimes
8241590Srgrimes/*-
8251590Srgrimes *-----------------------------------------------------------------------
8261590Srgrimes * Suff_AddLib --
8271590Srgrimes *	Add the given suffix as a type of file which is a library.
8281590Srgrimes *	Called from the parse module when parsing a .LIBS line. The
8291590Srgrimes *	suffix must have been defined via .SUFFIXES before this is
8301590Srgrimes *	called.
8311590Srgrimes *
8321590Srgrimes * Results:
8331590Srgrimes *	None.
8341590Srgrimes *
8351590Srgrimes * Side Effects:
8361590Srgrimes *	The SUFF_LIBRARY bit is set in the suffix's flags field
8371590Srgrimes *
8381590Srgrimes *-----------------------------------------------------------------------
8391590Srgrimes */
8401590Srgrimesvoid
841138232ShartiSuff_AddLib(char *sname)
8421590Srgrimes{
843143407Sharti	Suff	*s;
8441590Srgrimes
845143911Sharti	if ((s = SuffSuffFind(sname)) != NULL)
846143407Sharti		s->flags |= SUFF_LIBRARY;
8471590Srgrimes}
8481590Srgrimes
849143567Sharti/*
850143567Sharti * Create a new Src structure
851143567Sharti */
852143567Shartistatic Src *
853143567ShartiSuffSrcCreate(char *file, char *prefix, Suff *suff, Src *parent, GNode *node)
854143567Sharti{
855143567Sharti	Src	*s;
856143567Sharti
857143567Sharti	s = emalloc(sizeof(*s));
858143567Sharti	s->file = file;
859143567Sharti	s->pref = prefix;
860143567Sharti	s->suff = suff;
861143567Sharti	s->parent = parent;
862143567Sharti	s->node = node;
863143567Sharti	s->children = 0;
864143567Sharti
865143567Sharti#ifdef DEBUG_SRC
866143567Sharti	Lst_Init(&s->cp);
867143567Sharti#endif
868143567Sharti
869143567Sharti	return (s);
870143567Sharti}
871143567Sharti
8721590Srgrimes 	  /********** Implicit Source Search Functions *********/
8731590Srgrimes
8741590Srgrimes/*-
8751590Srgrimes *-----------------------------------------------------------------------
876143600Sharti * SuffAddLevel  --
877143600Sharti *	Add all the children of targ as Src structures to the given list:
8781590Srgrimes *	Add a suffix as a Src structure to the given list with its parent
8791590Srgrimes *	being the given Src structure. If the suffix is the null suffix,
8801590Srgrimes *	the prefix is used unaltered as the file name in the Src structure.
8811590Srgrimes *
8821590Srgrimes * Results:
883143600Sharti *	None
8841590Srgrimes *
8851590Srgrimes * Side Effects:
886143600Sharti * 	Lots of structures are created and added to the list
8871590Srgrimes *-----------------------------------------------------------------------
8881590Srgrimes */
889143600Shartistatic void
890143600ShartiSuffAddLevel(Lst *l, Src *targ)
8911590Srgrimes{
892143600Sharti	LstNode		*ln;
893143600Sharti	Suff		*suff;
894143600Sharti	Src		*s2;
895143556Sharti#ifdef DEBUG_SRC
896143600Sharti	const LstNode	*ln1;
897143556Sharti#endif
8981590Srgrimes
899143600Sharti	LST_FOREACH(ln, &targ->suff->children) {
900143600Sharti		suff = Lst_Datum(ln);
9018874Srgrimes
902143600Sharti		if ((suff->flags & SUFF_NULL) && *suff->name != '\0') {
903143600Sharti			/*
904143600Sharti			 * If the suffix has been marked as the NULL suffix,
905143600Sharti			 * also create a Src structure for a file with no suffix
906143600Sharti			 * attached. Two birds, and all that...
907143600Sharti			 */
908143600Sharti			s2 = SuffSrcCreate(estrdup(targ->pref), targ->pref,
909143600Sharti			    suff, targ, NULL);
910143600Sharti			suff->refCount++;
911143600Sharti			targ->children += 1;
912143600Sharti			Lst_AtEnd(l, s2);
913143600Sharti#ifdef DEBUG_SRC
914143600Sharti			Lst_AtEnd(&targ->cp, s2);
915143600Sharti			printf("1 add %p %p to %p:", targ, s2, l);
916143600Sharti			LST_FOREACH(ln1, l)
917143600Sharti				printf("%p ", (const void *)Lst_Datum(ln1));
918143600Sharti			printf("\n");
919143600Sharti#endif
920143600Sharti		}
921143600Sharti		s2 = SuffSrcCreate(str_concat(targ->pref, suff->name, 0),
922143600Sharti		    targ->pref, suff, targ, NULL);
923143600Sharti		suff->refCount++;
924143407Sharti		targ->children += 1;
925143600Sharti		Lst_AtEnd(l, s2);
926143407Sharti#ifdef DEBUG_SRC
927143407Sharti		Lst_AtEnd(&targ->cp, s2);
928143600Sharti		printf("2 add %p %p to %p:", targ, s2, l);
929143600Sharti		LST_FOREACH(ln1, l)
930143600Sharti			printf("%p ", (const void *)Lst_Datum(ln1));
931143407Sharti		printf("\n");
932143407Sharti#endif
933143407Sharti	}
9341590Srgrimes}
9351590Srgrimes
9361590Srgrimes/*-
9371590Srgrimes *----------------------------------------------------------------------
9385814Sjkh * SuffRemoveSrc --
9395814Sjkh *	Free all src structures in list that don't have a reference count
940138564Sharti *	XXX this actually frees only the first of these.
9411590Srgrimes *
9421590Srgrimes * Results:
943108470Sschweikh *	True if a src was removed
9441590Srgrimes *
9451590Srgrimes * Side Effects:
9461590Srgrimes *	The memory is free'd.
9471590Srgrimes *----------------------------------------------------------------------
9481590Srgrimes */
9495814Sjkhstatic int
950138512ShartiSuffRemoveSrc(Lst *l)
9511590Srgrimes{
952143407Sharti	LstNode	*ln, *ln1;
953143407Sharti	Src	*s;
954143407Sharti	int	t = 0;
9555814Sjkh
9565814Sjkh#ifdef DEBUG_SRC
957143407Sharti	printf("cleaning %lx: ", (unsigned long) l);
958143556Sharti	LST_FOREACH(ln, l)
959143556Sharti		printf("%p ", (const void *)Lst_Datum(ln));
960143407Sharti	printf("\n");
9615814Sjkh#endif
9625814Sjkh
963143407Sharti	for (ln = Lst_First(l); ln != NULL; ln = ln1) {
964143407Sharti		ln1 = Lst_Succ(ln);
9655814Sjkh
966143407Sharti		s = (Src *)Lst_Datum(ln);
967143407Sharti		if (s->children == 0) {
968143407Sharti			free(s->file);
969143407Sharti			if (!s->parent)
970143407Sharti				free(s->pref);
971143407Sharti			else {
9725814Sjkh#ifdef DEBUG_SRC
973143407Sharti				LstNode *ln = Lst_Member(&s->parent->cp, s);
974143407Sharti				if (ln != NULL)
975143407Sharti					Lst_Remove(&s->parent->cp, ln);
9765814Sjkh#endif
977143407Sharti				--s->parent->children;
978143407Sharti			}
9795814Sjkh#ifdef DEBUG_SRC
980143407Sharti			printf("free: [l=%p] p=%p %d\n", l, s, s->children);
981143407Sharti			Lst_Destroy(&s->cp, NOFREE);
9825814Sjkh#endif
983143407Sharti			Lst_Remove(l, ln);
984143407Sharti			free(s);
985143407Sharti			t |= 1;
986143407Sharti			return (TRUE);
987143407Sharti		}
9885814Sjkh#ifdef DEBUG_SRC
989143407Sharti		else {
990143556Sharti			const LstNode *tln;
991143556Sharti
992143407Sharti			printf("keep: [l=%p] p=%p %d: ", l, s, s->children);
993143556Sharti			LST_FOREACH(tln, &s->cp)
994143556Sharti				printf("%p ", (const void *)Lst_Datum(tln));
995143407Sharti			printf("\n");
996143407Sharti		}
997143407Sharti#endif
9985814Sjkh	}
9995814Sjkh
1000143407Sharti	return (t);
10011590Srgrimes}
10021590Srgrimes
10031590Srgrimes/*-
10041590Srgrimes *-----------------------------------------------------------------------
10051590Srgrimes * SuffFindThem --
10061590Srgrimes *	Find the first existing file/target in the list srcs
10071590Srgrimes *
10081590Srgrimes * Results:
10091590Srgrimes *	The lowest structure in the chain of transformations
10101590Srgrimes *
10111590Srgrimes * Side Effects:
10121590Srgrimes *	None
10131590Srgrimes *-----------------------------------------------------------------------
10141590Srgrimes */
10151590Srgrimesstatic Src *
1016138512ShartiSuffFindThem(Lst *srcs, Lst *slst)
10171590Srgrimes{
1018143407Sharti	Src	*s;	/* current Src */
1019143407Sharti	Src	*rs;	/* returned Src */
1020143407Sharti	char	*ptr;
10211590Srgrimes
1022143407Sharti	rs = NULL;
10231590Srgrimes
1024143407Sharti	while (!Lst_IsEmpty (srcs)) {
1025143407Sharti		s = Lst_DeQueue(srcs);
10261590Srgrimes
1027143407Sharti		DEBUGF(SUFF, ("\ttrying %s...", s->file));
10285814Sjkh
1029143407Sharti		/*
1030143407Sharti		 * A file is considered to exist if either a node exists in the
1031143407Sharti		 * graph for it or the file actually exists.
1032143407Sharti		 */
1033143407Sharti		if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
10345814Sjkh#ifdef DEBUG_SRC
1035143407Sharti			printf("remove %p from %p\n", s, srcs);
10365814Sjkh#endif
1037143407Sharti			rs = s;
1038143407Sharti			break;
1039143407Sharti		}
10405814Sjkh
1041144020Sharti		if ((ptr = Path_FindFile(s->file,
1042143407Sharti		    &s->suff->searchPath)) != NULL) {
1043143407Sharti			rs = s;
10445814Sjkh#ifdef DEBUG_SRC
1045143407Sharti			printf("remove %p from %p\n", s, srcs);
10465814Sjkh#endif
1047143407Sharti			free(ptr);
1048143407Sharti			break;
1049143407Sharti		}
10505814Sjkh
1051143407Sharti		DEBUGF(SUFF, ("not there\n"));
10525814Sjkh
1053143407Sharti		SuffAddLevel(srcs, s);
1054143407Sharti		Lst_AtEnd(slst, s);
1055143407Sharti	}
10565814Sjkh
1057143407Sharti	if (rs) {
1058143407Sharti		DEBUGF(SUFF, ("got it\n"));
1059143407Sharti	}
1060143407Sharti	return (rs);
10611590Srgrimes}
10621590Srgrimes
10631590Srgrimes/*-
10641590Srgrimes *-----------------------------------------------------------------------
10651590Srgrimes * SuffFindCmds --
10661590Srgrimes *	See if any of the children of the target in the Src structure is
10671590Srgrimes *	one from which the target can be transformed. If there is one,
10681590Srgrimes *	a Src structure is put together for it and returned.
10691590Srgrimes *
10701590Srgrimes * Results:
107169527Swill *	The Src structure of the "winning" child, or NULL if no such beast.
10721590Srgrimes *
10731590Srgrimes * Side Effects:
10741590Srgrimes *	A Src structure may be allocated.
10751590Srgrimes *
10761590Srgrimes *-----------------------------------------------------------------------
10771590Srgrimes */
10781590Srgrimesstatic Src *
1079141270ShartiSuffFindCmds(Src *targ, Lst *slst)
10801590Srgrimes{
1081143407Sharti	LstNode	*ln;	/* General-purpose list node */
1082143407Sharti	GNode	*t;	/* Target GNode */
1083143407Sharti	GNode	*s;	/* Source GNode */
1084143407Sharti	int	prefLen;/* The length of the defined prefix */
1085143407Sharti	Suff	*suff;	/* Suffix on matching beastie */
1086143407Sharti	Src	*ret;	/* Return value */
1087143407Sharti	char	*cp;
10881590Srgrimes
1089143407Sharti	t = targ->node;
1090143407Sharti	prefLen = strlen(targ->pref);
10911590Srgrimes
1092143407Sharti	for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Succ(ln)) {
1093143407Sharti		s = Lst_Datum(ln);
10941590Srgrimes
1095143407Sharti		cp = strrchr(s->name, '/');
1096143407Sharti		if (cp == NULL) {
1097143407Sharti			cp = s->name;
1098143407Sharti		} else {
1099143407Sharti			cp++;
1100143407Sharti		}
1101143407Sharti		if (strncmp(cp, targ->pref, prefLen) == 0) {
1102143407Sharti			/*
1103143407Sharti			 * The node matches the prefix ok, see if it has
1104143911Sharti			 * a known suffix.
1105143407Sharti			 */
1106143911Sharti			suff = SuffSuffFind(&cp[prefLen]);
1107143911Sharti			if (suff != NULL) {
1108143407Sharti				/*
1109143407Sharti				 * It even has a known suffix, see if there's
1110143407Sharti				 * a transformation defined between the node's
1111143407Sharti				 * suffix and the target's suffix.
1112143407Sharti				 *
1113143407Sharti				 * XXX: Handle multi-stage transformations
1114143407Sharti				 * here, too.
1115143407Sharti				 */
1116143407Sharti				if (Lst_Member(&suff->parents,
1117143407Sharti				    targ->suff) != NULL) {
1118143407Sharti					/*
1119143407Sharti					 * Hot Damn! Create a new Src structure
1120143407Sharti					 * to describe this transformation
1121143407Sharti					 * (making sure to duplicate the
1122143407Sharti					 * source node's name so Suff_FindDeps
1123143407Sharti					 * can free it again (ick)), and return
1124143407Sharti					 * the new structure.
1125143407Sharti					 */
1126143567Sharti					ret = SuffSrcCreate(estrdup(s->name),
1127143567Sharti					    targ->pref, suff, targ, s);
1128143407Sharti					suff->refCount++;
1129143407Sharti					targ->children += 1;
11305814Sjkh#ifdef DEBUG_SRC
1131143407Sharti					printf("3 add %p %p\n", &targ, ret);
1132143407Sharti					Lst_AtEnd(&targ->cp, ret);
11335814Sjkh#endif
1134143407Sharti					Lst_AtEnd(slst, ret);
1135143407Sharti					DEBUGF(SUFF, ("\tusing existing source "
1136143407Sharti					    "%s\n", s->name));
1137143407Sharti					return (ret);
1138143407Sharti				}
1139143407Sharti			}
11401590Srgrimes		}
11411590Srgrimes	}
1142143407Sharti	return (NULL);
11431590Srgrimes}
11441590Srgrimes
11451590Srgrimes/*-
1146143327Sharti * The child node contains variable references. Expand them and return
1147143327Sharti * a list of expansions.
11481590Srgrimes */
1149143327Shartistatic void
1150143327ShartiSuffExpandVariables(GNode *parent, GNode *child, Lst *members)
11511590Srgrimes{
1152143327Sharti	Buffer	*buf;
1153143327Sharti	char	*cp;
1154143327Sharti	char	*start;
11551590Srgrimes
1156143327Sharti	Lst_Init(members);
11578874Srgrimes
1158143327Sharti	DEBUGF(SUFF, ("Expanding \"%s\"...", child->name));
1159146027Sharti	buf = Var_Subst(child->name, parent, TRUE);
1160143959Sharti	cp = Buf_Data(buf);
1161143327Sharti
1162143327Sharti	if (child->type & OP_ARCHV) {
1163143327Sharti		/*
1164143327Sharti		 * Node was an archive(member) target, so we
1165143327Sharti		 * want to call on the Arch module to find the
1166143327Sharti		 * nodes for us, expanding variables in the
1167143327Sharti		 * parent's context.
1168143327Sharti		 */
1169143327Sharti		Arch_ParseArchive(&cp, members, parent);
1170143327Sharti		Buf_Destroy(buf, TRUE);
1171143327Sharti		return;
1172143327Sharti	}
1173143297Sharti	/*
1174143327Sharti	 * Break the result into a vector of strings whose nodes we can find,
1175143327Sharti	 * then add those nodes to the members list. Unfortunately, we can't use
1176143327Sharti	 * brk_string b/c it doesn't understand about variable specifications
1177143327Sharti	 * with spaces in them... XXX
1178143297Sharti	 */
1179143327Sharti	for (start = cp; *start == ' ' || *start == '\t'; start++)
1180143327Sharti		;
1181143312Sharti
1182143327Sharti	for (cp = start; *cp != '\0'; cp++) {
1183143327Sharti		if (*cp == ' ' || *cp == '\t') {
1184143327Sharti			/*
1185143327Sharti			 * White-space -- terminate element, find the node,
1186143327Sharti			 * add it, skip any further spaces.
1187143327Sharti			 */
1188143327Sharti			*cp++ = '\0';
1189143327Sharti			Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE));
11901590Srgrimes
1191143327Sharti			while (*cp == ' ' || *cp == '\t') {
1192143327Sharti				cp++;
1193143327Sharti			}
1194143312Sharti			/*
1195143327Sharti			 * Adjust cp for increment at
1196143327Sharti			 * start of loop, but set start
1197143327Sharti			 * to first non-space.
1198143312Sharti			 */
1199143327Sharti			start = cp--;
1200143327Sharti
1201143327Sharti		} else if (*cp == '$') {
1202143312Sharti			/*
1203143327Sharti			 * Start of a variable spec -- contact variable module
1204143327Sharti			 * to find the end so we can skip over it.
1205143312Sharti			 */
1206143327Sharti			char	*junk;
1207143327Sharti			size_t	len = 0;
1208143327Sharti			Boolean	doFree;
12091590Srgrimes
1210143327Sharti			junk = Var_Parse(cp, parent, TRUE, &len, &doFree);
1211143327Sharti			if (junk != var_Error) {
1212143327Sharti				cp += len - 1;
1213143312Sharti			}
1214143327Sharti			if (doFree) {
1215143327Sharti				free(junk);
1216143327Sharti			}
1217143312Sharti
1218143327Sharti		} else if (*cp == '\\' && *cp != '\0') {
1219143327Sharti			/*
1220143327Sharti			 * Escaped something -- skip over it
1221143327Sharti			 */
1222143327Sharti			cp++;
1223143312Sharti		}
1224143327Sharti	}
12251590Srgrimes
1226143327Sharti	if (cp != start) {
1227143312Sharti		/*
1228143327Sharti		 * Stuff left over -- add it to the
1229143327Sharti		 * list too
1230143312Sharti		 */
1231143327Sharti		Lst_AtEnd(members, Targ_FindNode(start, TARG_CREATE));
1232143327Sharti	}
1233143312Sharti
1234143327Sharti	Buf_Destroy(buf, TRUE);
1235143327Sharti}
1236143327Sharti
1237143327Sharti/*-
1238143327Sharti * The child node contains wildcards. Expand them and return a list of
1239143327Sharti * expansions.
1240143327Sharti */
1241143327Shartistatic void
1242143327ShartiSuffExpandWildcards(GNode *child, Lst *members)
1243143327Sharti{
1244143327Sharti	char	*cp;
1245143327Sharti	Lst	exp;	/* List of expansions */
1246143327Sharti	LstNode	*ln;
1247144020Sharti	struct Path *path;	/* Search path along which to expand */
1248143327Sharti
1249143327Sharti	Lst_Init(members);
1250143327Sharti
1251143327Sharti	/*
1252143327Sharti	 * Find a path along which to expand the word.
1253143327Sharti	 *
1254143327Sharti	 * If the word has a known suffix, use that path.
1255143327Sharti	 * If it has no known suffix and we're allowed to use the null
1256143327Sharti	 *   suffix, use its path.
1257143327Sharti	 * Else use the default system search path.
1258143327Sharti	 */
1259143807Sharti	LST_FOREACH(ln, &sufflist) {
1260143807Sharti		if (SuffSuffIsSuffix(Lst_Datum(ln), child->name) != NULL)
1261143807Sharti			break;
1262143807Sharti	}
1263143327Sharti
1264143327Sharti	DEBUGF(SUFF, ("Wildcard expanding \"%s\"...", child->name));
1265143327Sharti
1266143327Sharti	if (ln != NULL) {
1267143327Sharti		Suff	*s = Lst_Datum(ln);
1268143327Sharti
1269143327Sharti		DEBUGF(SUFF, ("suffix is \"%s\"...", s->name));
1270143327Sharti		path = &s->searchPath;
1271143327Sharti	} else {
1272143312Sharti		/*
1273143327Sharti		 * Use default search path
1274143312Sharti		 */
1275143327Sharti		path = &dirSearchPath;
1276143327Sharti	}
1277143312Sharti
1278143327Sharti	/*
1279143327Sharti	 * Expand the word along the chosen path
1280143327Sharti	 */
1281143327Sharti	Lst_Init(&exp);
1282144020Sharti	Path_Expand(child->name, path, &exp);
12831590Srgrimes
1284143327Sharti	while (!Lst_IsEmpty(&exp)) {
12851590Srgrimes		/*
1286143327Sharti		 * Fetch next expansion off the list and find its GNode
12871590Srgrimes		 */
1288143327Sharti		cp = Lst_DeQueue(&exp);
12891590Srgrimes
1290143327Sharti		DEBUGF(SUFF, ("%s...", cp));
1291143327Sharti		Lst_AtEnd(members, Targ_FindNode(cp, TARG_CREATE));
1292143327Sharti	}
1293143327Sharti}
1294138916Sharti
1295143327Sharti/*-
1296143327Sharti *-----------------------------------------------------------------------
1297143327Sharti * SuffExpandChildren --
1298143327Sharti *	Expand the names of any children of a given node that contain
1299143327Sharti *	variable invocations or file wildcards into actual targets.
1300143327Sharti *
1301143327Sharti * Results:
1302143327Sharti *	== 0 (continue)
1303143327Sharti *
1304143327Sharti * Side Effects:
1305143327Sharti *	The expanded node is removed from the parent's list of children,
1306143327Sharti *	and the parent's unmade counter is decremented, but other nodes
1307143327Sharti * 	may be added.
1308143327Sharti *
1309143327Sharti *-----------------------------------------------------------------------
1310143327Sharti */
1311143327Shartistatic void
1312143327ShartiSuffExpandChildren(GNode *parent, LstNode *current)
1313143327Sharti{
1314143327Sharti	GNode	*cchild;	/* current child */
1315143327Sharti	GNode	*gn;
1316143327Sharti	LstNode	*prev;		/* node after which to append new source */
1317143327Sharti	Lst	members;	/* expanded nodes */
1318143327Sharti
1319143327Sharti	if (current == NULL) {
1320143327Sharti		/* start from begin of parent's children list */
1321143327Sharti		current = Lst_First(&parent->children);
1322143327Sharti	}
1323143327Sharti
1324143327Sharti	while (current != NULL) {
1325143327Sharti		cchild = Lst_Datum(current);
1326143327Sharti
1327143297Sharti		/*
1328143327Sharti		 * First do variable expansion -- this takes precedence over
1329143327Sharti		 * wildcard expansion. If the result contains wildcards, they'll
1330143327Sharti		 * be gotten to later since the resulting words are tacked
1331143327Sharti		 * instead of the current child onto the children list.
1332143297Sharti		 *
1333143327Sharti		 * XXXHB what if cchild contains lib.a(t1.o t2.o t3.o) but
1334143327Sharti		 * no $?
1335143297Sharti		 */
1336143327Sharti		if (strchr(cchild->name, '$') != NULL) {
1337143327Sharti			SuffExpandVariables(parent, cchild, &members);
13381590Srgrimes
1339143327Sharti		} else if (Dir_HasWildcards(cchild->name)) {
1340143327Sharti			SuffExpandWildcards(cchild, &members);
13411590Srgrimes
1342143297Sharti		} else {
1343143327Sharti			/* nothing special just advance to next child */
1344143327Sharti			current = LST_NEXT(current);
1345143327Sharti			continue;
1346143297Sharti		}
13471590Srgrimes
1348143297Sharti		/*
1349143327Sharti		 * New nodes effectively take the place of the child,
1350143327Sharti		 * so place them after the child
1351143297Sharti		 */
1352143327Sharti		prev = current;
13531590Srgrimes
1354143327Sharti		/*
1355143327Sharti		 * Add all new elements to the parent node if they aren't
1356143327Sharti		 * already children of it.
1357143327Sharti		 */
1358143327Sharti		while(!Lst_IsEmpty(&members)) {
1359143327Sharti			gn = Lst_DeQueue(&members);
13601590Srgrimes
1361143327Sharti			DEBUGF(SUFF, ("%s...", gn->name));
1362143327Sharti			if (Lst_Member(&parent->children, gn) == NULL) {
1363143327Sharti				Lst_Append(&parent->children, prev, gn);
1364143327Sharti				prev = Lst_Succ(prev);
1365143327Sharti				Lst_AtEnd(&gn->parents, parent);
1366143327Sharti				parent->unmade++;
1367143297Sharti			}
1368143297Sharti		}
13691590Srgrimes
1370143297Sharti		/*
1371143327Sharti		 * Now the source is expanded, remove it from the list
1372143327Sharti		 * of children to keep it from being processed.
1373143327Sharti		 * Advance to the next child.
1374143297Sharti		 */
1375143327Sharti		prev = current;
1376143327Sharti		current = LST_NEXT(current);
1377143327Sharti
1378143327Sharti		parent->unmade--;
1379143327Sharti		Lst_Remove(&parent->children, prev);
1380143297Sharti		DEBUGF(SUFF, ("\n"));
13811590Srgrimes	}
13821590Srgrimes}
13831590Srgrimes
13841590Srgrimes/*-
13851590Srgrimes *-----------------------------------------------------------------------
13861590Srgrimes * SuffApplyTransform --
13871590Srgrimes *	Apply a transformation rule, given the source and target nodes
13881590Srgrimes *	and suffixes.
13891590Srgrimes *
13901590Srgrimes * Results:
13911590Srgrimes *	TRUE if successful, FALSE if not.
13921590Srgrimes *
13931590Srgrimes * Side Effects:
13941590Srgrimes *	The source and target are linked and the commands from the
13951590Srgrimes *	transformation are added to the target node's commands list.
13961590Srgrimes *	All attributes but OP_DEPMASK and OP_TRANSFORM are applied
13971590Srgrimes *	to the target. The target also inherits all the sources for
13981590Srgrimes *	the transformation rule.
13991590Srgrimes *
14001590Srgrimes *-----------------------------------------------------------------------
14011590Srgrimes */
14021590Srgrimesstatic Boolean
1403104696SjmallettSuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s)
14041590Srgrimes{
1405143407Sharti	LstNode	*ln;	/* General node */
1406143407Sharti	char	*tname;	/* Name of transformation rule */
1407143407Sharti	GNode	*gn;	/* Node for same */
14081590Srgrimes
1409143407Sharti	if (Lst_Member(&tGn->children, sGn) == NULL) {
14101590Srgrimes		/*
14111590Srgrimes		 * Not already linked, so form the proper links between the
14121590Srgrimes		 * target and source.
14131590Srgrimes		 */
1414143407Sharti		Lst_AtEnd(&tGn->children, sGn);
1415143407Sharti		Lst_AtEnd(&sGn->parents, tGn);
14161590Srgrimes		tGn->unmade += 1;
14171590Srgrimes	}
14181590Srgrimes
1419143407Sharti	if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1420143407Sharti		/*
1421143407Sharti		 * When a :: node is used as the implied source of a node,
1422143407Sharti		 * we have to link all its cohorts in as sources as well. Only
1423143407Sharti		 * the initial sGn gets the target in its iParents list, however
1424143407Sharti		 * as that will be sufficient to get the .IMPSRC variable set
1425143407Sharti		 * for tGn
1426143407Sharti		 */
1427143407Sharti		for (ln = Lst_First(&sGn->cohorts); ln != NULL;
1428143407Sharti		    ln = Lst_Succ(ln)) {
1429143407Sharti			gn = Lst_Datum(ln);
1430143407Sharti
1431143407Sharti			if (Lst_Member(&tGn->children, gn) == NULL) {
1432143407Sharti				/*
1433143407Sharti				 * Not already linked, so form the proper
1434143407Sharti				 * links between the target and source.
1435143407Sharti				 */
1436143407Sharti				Lst_AtEnd(&tGn->children, gn);
1437143407Sharti				Lst_AtEnd(&gn->parents, tGn);
1438143407Sharti				tGn->unmade += 1;
1439143407Sharti			}
1440143407Sharti		}
1441143407Sharti	}
14421590Srgrimes	/*
1443143407Sharti	 * Locate the transformation rule itself
14441590Srgrimes	 */
1445143407Sharti	tname = str_concat(s->name, t->name, 0);
1446143911Sharti	gn = SuffTransFind(tname);
1447143407Sharti	free(tname);
14481590Srgrimes
1449143911Sharti	if (gn == NULL) {
1450143407Sharti		/*
1451143407Sharti		 * Not really such a transformation rule (can happen when we're
1452143407Sharti		 * called to link an OP_MEMBER and OP_ARCHV node), so return
1453143407Sharti		 * FALSE.
1454143407Sharti		 */
1455143407Sharti		return (FALSE);
1456143407Sharti	}
14578874Srgrimes
1458143407Sharti	DEBUGF(SUFF, ("\tapplying %s -> %s to \"%s\"\n",
1459143407Sharti	    s->name, t->name, tGn->name));
14608874Srgrimes
1461143407Sharti	/*
1462143407Sharti	 * Record last child for expansion purposes
1463143407Sharti	 */
1464143407Sharti	ln = Lst_Last(&tGn->children);
14651590Srgrimes
1466143407Sharti	/*
1467143407Sharti	 * Pass the buck to Make_HandleUse to apply the rule
1468143407Sharti	 */
1469143407Sharti	Make_HandleUse(gn, tGn);
14701590Srgrimes
1471143407Sharti	/*
1472143407Sharti	 * Deal with wildcards and variables in any acquired sources
1473143407Sharti	 */
1474143407Sharti	ln = Lst_Succ(ln);
1475143407Sharti	if (ln != NULL) {
1476143407Sharti		SuffExpandChildren(tGn, ln);
1477143407Sharti	}
14781590Srgrimes
1479143407Sharti	/*
1480143407Sharti	 * Keep track of another parent to which this beast is transformed so
1481143407Sharti	 * the .IMPSRC variable can be set correctly for the parent.
1482143407Sharti	 */
1483143407Sharti	Lst_AtEnd(&sGn->iParents, tGn);
1484143407Sharti
1485143407Sharti	return (TRUE);
14861590Srgrimes}
14871590Srgrimes
14881590Srgrimes
14891590Srgrimes/*-
14901590Srgrimes *-----------------------------------------------------------------------
14911590Srgrimes * SuffFindArchiveDeps --
14921590Srgrimes *	Locate dependencies for an OP_ARCHV node.
14931590Srgrimes *
14941590Srgrimes * Results:
14951590Srgrimes *	None
14961590Srgrimes *
14971590Srgrimes * Side Effects:
14981590Srgrimes *	Same as Suff_FindDeps
14991590Srgrimes *
15001590Srgrimes *-----------------------------------------------------------------------
15011590Srgrimes */
15021590Srgrimesstatic void
1503138512ShartiSuffFindArchiveDeps(GNode *gn, Lst *slst)
15041590Srgrimes{
1505143407Sharti	char	*eoarch;	/* End of archive portion */
1506143407Sharti	char	*eoname;	/* End of member portion */
1507146149Sharti	char	*name;		/* Start of member's name */
1508143407Sharti	GNode	*mem;		/* Node for member */
1509146149Sharti	Suff	*ms;		/* Suffix descriptor for member */
1510146149Sharti
1511146149Sharti	static const char *copy[] = {
1512143407Sharti		TARGET,		/* Must be first */
1513143407Sharti		PREFIX,		/* Must be second */
1514143407Sharti	};
15158874Srgrimes
1516143407Sharti	/*
1517143407Sharti	 * The node is an archive(member) pair. so we must find a
1518143407Sharti	 * suffix for both of them.
1519143407Sharti	 */
1520143407Sharti	eoarch = strchr(gn->name, '(');
1521143407Sharti	eoname = strchr(eoarch, ')');
15221590Srgrimes
1523143407Sharti	*eoname = '\0';	  /* Nuke parentheses during suffix search */
1524143407Sharti	*eoarch = '\0';	  /* So a suffix can be found */
15251590Srgrimes
1526143407Sharti	name = eoarch + 1;
15278874Srgrimes
1528143407Sharti	/*
1529143407Sharti	 * To simplify things, call Suff_FindDeps recursively on the member now,
1530143407Sharti	 * so we can simply compare the member's .PREFIX and .TARGET variables
1531143407Sharti	 * to locate its suffix. This allows us to figure out the suffix to
1532143407Sharti	 * use for the archive without having to do a quadratic search over the
1533143407Sharti	 * suffix list, backtracking for each one...
1534143407Sharti	 */
1535143407Sharti	mem = Targ_FindNode(name, TARG_CREATE);
1536143407Sharti	SuffFindDeps(mem, slst);
15371590Srgrimes
1538143407Sharti	/*
1539143407Sharti	 * Create the link between the two nodes right off
1540143407Sharti	 */
1541143407Sharti	if (Lst_Member(&gn->children, mem) == NULL) {
1542143407Sharti		Lst_AtEnd(&gn->children, mem);
1543143407Sharti		Lst_AtEnd(&mem->parents, gn);
1544143407Sharti		gn->unmade += 1;
1545143407Sharti	}
15468874Srgrimes
1547143407Sharti	/*
1548143407Sharti	 * Copy in the variables from the member node to this one.
1549143407Sharti	 */
1550146580Sharti	Var_Set(copy[1], Var_Value(copy[1], mem), gn);
1551146580Sharti	Var_Set(copy[0], Var_Value(copy[0], mem), gn);
15525814Sjkh
1553143407Sharti	ms = mem->suffix;
1554143407Sharti	if (ms == NULL) {
1555143407Sharti		/*
1556143407Sharti		 * Didn't know what it was -- use .NULL suffix if not in
1557143407Sharti		 * make mode
1558143407Sharti		 */
1559143407Sharti		DEBUGF(SUFF, ("using null suffix\n"));
1560143407Sharti		ms = suffNull;
1561143407Sharti	}
15621590Srgrimes
15631590Srgrimes	/*
1564143407Sharti	* Set the other two local variables required for this target.
1565143407Sharti	*/
1566143407Sharti	Var_Set(MEMBER, name, gn);
1567143407Sharti	Var_Set(ARCHIVE, gn->name, gn);
15681590Srgrimes
1569143407Sharti	if (ms != NULL) {
1570143407Sharti		/*
1571143407Sharti		 * Member has a known suffix, so look for a transformation rule
1572143407Sharti		 * from it to a possible suffix of the archive. Rather than
1573143407Sharti		 * searching through the entire list, we just look at suffixes
1574143407Sharti		 * to which the member's suffix may be transformed...
1575143407Sharti		 */
1576143407Sharti		LstNode *ln;
15771590Srgrimes
1578143407Sharti		/*
1579143407Sharti		 * Use first matching suffix...
1580143407Sharti		 */
1581143807Sharti		LST_FOREACH(ln, &ms->parents) {
1582143807Sharti			if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL)
1583143807Sharti				break;
1584143807Sharti		}
15851590Srgrimes
1586143407Sharti		if (ln != NULL) {
1587143407Sharti			/*
1588143407Sharti			 * Got one -- apply it
1589143407Sharti			 */
1590143407Sharti			if (!SuffApplyTransform(gn, mem, Lst_Datum(ln), ms)) {
1591143407Sharti				DEBUGF(SUFF, ("\tNo transformation from "
1592143407Sharti				    "%s -> %s\n", ms->name,
1593143407Sharti				    ((Suff *)Lst_Datum(ln))->name));
1594143407Sharti			}
1595143407Sharti		}
1596143407Sharti	}
1597143407Sharti
15981590Srgrimes	/*
1599143407Sharti	 * Replace the opening and closing parens now we've no need
1600143407Sharti	 * of the separate pieces.
16011590Srgrimes	 */
1602143407Sharti	*eoarch = '(';
1603143407Sharti	*eoname = ')';
16041590Srgrimes
16051590Srgrimes	/*
1606143407Sharti	 * Pretend gn appeared to the left of a dependency operator so
1607143407Sharti	 * the user needn't provide a transformation from the member to the
1608143407Sharti	 * archive.
16091590Srgrimes	 */
1610143407Sharti	if (OP_NOP(gn->type)) {
1611143407Sharti		gn->type |= OP_DEPENDS;
16121590Srgrimes	}
16131590Srgrimes
1614143407Sharti	/*
1615143407Sharti	 * Flag the member as such so we remember to look in the archive for
1616143407Sharti	 * its modification time.
1617143407Sharti	 */
1618143407Sharti	mem->type |= OP_MEMBER;
16191590Srgrimes}
16201590Srgrimes
16211590Srgrimes/*-
16221590Srgrimes *-----------------------------------------------------------------------
16231590Srgrimes * SuffFindNormalDeps --
16241590Srgrimes *	Locate implicit dependencies for regular targets.
16251590Srgrimes *
16261590Srgrimes * Results:
16271590Srgrimes *	None.
16281590Srgrimes *
16291590Srgrimes * Side Effects:
16301590Srgrimes *	Same as Suff_FindDeps...
16311590Srgrimes *
16321590Srgrimes *-----------------------------------------------------------------------
16331590Srgrimes */
16341590Srgrimesstatic void
1635138512ShartiSuffFindNormalDeps(GNode *gn, Lst *slst)
16361590Srgrimes{
1637143407Sharti	char	*eoname;	/* End of name */
1638143407Sharti	char	*sopref;	/* Start of prefix */
1639143407Sharti	LstNode	*ln;		/* Next suffix node to check */
1640143407Sharti	Lst	srcs;		/* List of sources at which to look */
1641143407Sharti	Lst	targs;		/* List of targets to which things can be
1642143407Sharti				 * transformed. They all have the same file,
1643143407Sharti				 * but different suff and pref fields */
1644143407Sharti	Src	*bottom;	/* Start of found transformation path */
1645143407Sharti	Src	*src;		/* General Src pointer */
1646143407Sharti	char	*pref;		/* Prefix to use */
1647143407Sharti	Src	*targ;		/* General Src target pointer */
16481590Srgrimes
1649143407Sharti	eoname = gn->name + strlen(gn->name);
1650143407Sharti	sopref = gn->name;
16511590Srgrimes
1652143407Sharti	/*
1653143407Sharti	 * Begin at the beginning...
1654143407Sharti	 */
1655143407Sharti	ln = Lst_First(&sufflist);
1656143407Sharti	Lst_Init(&srcs);
1657143407Sharti	Lst_Init(&targs);
16581590Srgrimes
16591590Srgrimes	/*
1660143407Sharti	 * We're caught in a catch-22 here. On the one hand, we want to use any
1661143407Sharti	 * transformation implied by the target's sources, but we can't examine
1662143407Sharti	 * the sources until we've expanded any variables/wildcards they may
1663143407Sharti	 * hold, and we can't do that until we've set up the target's local
1664143407Sharti	 * variables and we can't do that until we know what the proper suffix
1665143407Sharti	 * for the target is (in case there are two suffixes one of which is a
1666143407Sharti	 * suffix of the other) and we can't know that until we've found its
1667143407Sharti	 * implied source, which we may not want to use if there's an existing
1668143407Sharti	 * source that implies a different transformation.
1669143407Sharti	 *
1670143407Sharti	 * In an attempt to get around this, which may not work all the time,
1671143407Sharti	 * but should work most of the time, we look for implied sources first,
1672143407Sharti	 * checking transformations to all possible suffixes of the target,
1673143407Sharti	 * use what we find to set the target's local variables, expand the
1674143407Sharti	 * children, then look for any overriding transformations they imply.
1675143407Sharti	 * Should we find one, we discard the one we found before.
16761590Srgrimes	 */
16771590Srgrimes
1678143407Sharti	while (ln != NULL) {
1679143407Sharti		/*
1680143407Sharti		 * Look for next possible suffix...
1681143407Sharti		 */
1682143807Sharti		while (ln != NULL) {
1683143807Sharti			if (SuffSuffIsSuffix(Lst_Datum(ln), gn->name) != NULL)
1684143807Sharti				break;
1685143807Sharti			ln = LST_NEXT(ln);
1686143807Sharti		}
1687143807Sharti
1688143407Sharti		if (ln != NULL) {
1689143407Sharti			int	prefLen;	/* Length of the prefix */
1690143407Sharti			Src	*target;
1691143407Sharti
1692143407Sharti			/*
1693143407Sharti			 * Allocate a Src structure to which things can be
1694143407Sharti			 * transformed
1695143407Sharti			 */
1696143567Sharti			target = SuffSrcCreate(estrdup(gn->name), NULL,
1697143567Sharti			    Lst_Datum(ln), NULL, gn);
1698143407Sharti			target->suff->refCount++;
16998874Srgrimes
1700143407Sharti			/*
1701143407Sharti			 * Allocate room for the prefix, whose end is found
1702143407Sharti			 * by subtracting the length of the suffix from
1703143407Sharti			 * the end of the name.
1704143407Sharti			 */
1705143407Sharti			prefLen = (eoname - target->suff->nameLen) - sopref;
1706143807Sharti			assert(prefLen >= 0);
1707143407Sharti			target->pref = emalloc(prefLen + 1);
1708143407Sharti			memcpy(target->pref, sopref, prefLen);
1709143407Sharti			target->pref[prefLen] = '\0';
17101590Srgrimes
1711143407Sharti			/*
1712143407Sharti			 * Add nodes from which the target can be made
1713143407Sharti			 */
1714143407Sharti			SuffAddLevel(&srcs, target);
17151590Srgrimes
1716143407Sharti			/*
1717143407Sharti			 * Record the target so we can nuke it
1718143407Sharti			 */
1719143407Sharti			Lst_AtEnd(&targs, target);
17201590Srgrimes
1721143407Sharti			/*
1722143407Sharti			 * Search from this suffix's successor...
1723143407Sharti			 */
1724143407Sharti			ln = Lst_Succ(ln);
1725143407Sharti		}
17261590Srgrimes	}
17271590Srgrimes
1728143407Sharti	/*
1729143407Sharti	 * Handle target of unknown suffix...
1730143407Sharti	 */
1731143407Sharti	if (Lst_IsEmpty(&targs) && suffNull != NULL) {
1732143407Sharti		DEBUGF(SUFF, ("\tNo known suffix on %s. Using .NULL suffix\n",
1733143407Sharti		    gn->name));
17348874Srgrimes
1735143567Sharti		targ = SuffSrcCreate(estrdup(gn->name), estrdup(sopref),
1736143567Sharti		    suffNull, NULL, gn);
1737143407Sharti		targ->suff->refCount++;
17381590Srgrimes
1739143407Sharti		/*
1740143407Sharti		 * Only use the default suffix rules if we don't have commands
1741143407Sharti		 * or dependencies defined for this gnode
1742143407Sharti		 */
1743143407Sharti		if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
1744143407Sharti			SuffAddLevel(&srcs, targ);
1745143407Sharti		else {
1746143407Sharti			DEBUGF(SUFF, ("not "));
1747143407Sharti		}
17489254Sache
1749143407Sharti		DEBUGF(SUFF, ("adding suffix rules\n"));
17509254Sache
1751143407Sharti		Lst_AtEnd(&targs, targ);
1752143407Sharti	}
17538874Srgrimes
17541590Srgrimes	/*
1755143407Sharti	 * Using the list of possible sources built up from the target
1756143407Sharti	 * suffix(es), try and find an existing file/target that matches.
17571590Srgrimes	 */
1758143407Sharti	bottom = SuffFindThem(&srcs, slst);
1759143407Sharti
1760143407Sharti	if (bottom == NULL) {
1761143407Sharti		/*
1762143407Sharti		 * No known transformations -- use the first suffix found for
1763143407Sharti		 * setting the local variables.
1764143407Sharti		 */
1765143407Sharti		if (!Lst_IsEmpty(&targs)) {
1766143407Sharti			targ = Lst_Datum(Lst_First(&targs));
1767143407Sharti		} else {
1768143407Sharti			targ = NULL;
1769143407Sharti		}
17701590Srgrimes	} else {
1771143407Sharti		/*
1772143407Sharti		 * Work up the transformation path to find the suffix of the
1773143407Sharti		 * target to which the transformation was made.
1774143407Sharti		 */
1775143407Sharti		for (targ = bottom; targ->parent != NULL; targ = targ->parent)
1776143407Sharti			continue;
17771590Srgrimes	}
1778143407Sharti
17791590Srgrimes	/*
1780143407Sharti	 * The .TARGET variable we always set to be the name at this point,
1781143407Sharti	 * since it's only set to the path if the thing is only a source and
1782143407Sharti	 * if it's only a source, it doesn't matter what we put here as far
1783143407Sharti	 * as expanding sources is concerned, since it has none...
17841590Srgrimes	 */
1785143407Sharti	Var_Set(TARGET, gn->name, gn);
17861590Srgrimes
1787143407Sharti	pref = (targ != NULL) ? targ->pref : gn->name;
1788143407Sharti	Var_Set(PREFIX, pref, gn);
17891590Srgrimes
1790143407Sharti	/*
1791143407Sharti	 * Now we've got the important local variables set, expand any sources
1792143407Sharti	 * that still contain variables or wildcards in their names.
1793143407Sharti	 */
1794143407Sharti	SuffExpandChildren(gn, NULL);
17951590Srgrimes
1796143407Sharti	if (targ == NULL) {
1797143407Sharti		DEBUGF(SUFF, ("\tNo valid suffix on %s\n", gn->name));
17988874Srgrimes
1799143407Sharti  sfnd_abort:
1800143407Sharti		/*
1801143407Sharti		 * Deal with finding the thing on the default search path if the
1802143407Sharti		 * node is only a source (not on the lhs of a dependency
1803143407Sharti		 * operator or [XXX] it has neither children or commands).
1804143407Sharti		 */
1805143407Sharti		if (OP_NOP(gn->type) || (Lst_IsEmpty(&gn->children) &&
1806143407Sharti		    Lst_IsEmpty(&gn->commands))) {
1807144020Sharti			gn->path = Path_FindFile(gn->name,
1808143407Sharti			    (targ == NULL ? &dirSearchPath :
1809143407Sharti			    &targ->suff->searchPath));
1810143407Sharti			if (gn->path != NULL) {
1811143407Sharti				char *ptr;
1812143407Sharti				Var_Set(TARGET, gn->path, gn);
18131590Srgrimes
1814143407Sharti				if (targ != NULL) {
1815143407Sharti					/*
1816143407Sharti					 * Suffix known for the thing -- trim
1817143407Sharti					 * the suffix off the path to form the
1818143407Sharti					 * proper .PREFIX variable.
1819143407Sharti					 */
1820143407Sharti					int	savep = strlen(gn->path) -
1821143407Sharti						    targ->suff->nameLen;
1822143407Sharti					char	savec;
18231590Srgrimes
1824143407Sharti					if (gn->suffix)
1825143407Sharti						gn->suffix->refCount--;
1826143407Sharti					gn->suffix = targ->suff;
1827143407Sharti					gn->suffix->refCount++;
18281590Srgrimes
1829143407Sharti					savec = gn->path[savep];
1830143407Sharti					gn->path[savep] = '\0';
18311590Srgrimes
1832143407Sharti					if ((ptr = strrchr(gn->path, '/')) != NULL)
1833143407Sharti						ptr++;
1834143407Sharti					else
1835143407Sharti						ptr = gn->path;
18361590Srgrimes
1837143407Sharti					Var_Set(PREFIX, ptr, gn);
18381590Srgrimes
1839143407Sharti					gn->path[savep] = savec;
1840143407Sharti				} else {
1841143407Sharti					/*
1842143407Sharti					 * The .PREFIX gets the full path if
1843143407Sharti					 * the target has no known suffix.
1844143407Sharti					 */
1845143407Sharti					if (gn->suffix)
1846143407Sharti						gn->suffix->refCount--;
1847143407Sharti					gn->suffix = NULL;
184818730Ssteve
1849143407Sharti					if ((ptr = strrchr(gn->path, '/')) != NULL)
1850143407Sharti						ptr++;
1851143407Sharti					else
1852143407Sharti						ptr = gn->path;
1853143407Sharti
1854143407Sharti					Var_Set(PREFIX, ptr, gn);
1855143407Sharti				}
1856143407Sharti			}
18571590Srgrimes		} else {
1858143407Sharti			/*
1859143407Sharti			 * Not appropriate to search for the thing -- set the
1860143407Sharti			 * path to be the name so Dir_MTime won't go
1861143407Sharti			 * grovelling for it.
1862143407Sharti			 */
1863143407Sharti			if (gn->suffix)
1864143407Sharti				gn->suffix->refCount--;
1865143407Sharti			gn->suffix = (targ == NULL) ? NULL : targ->suff;
1866143407Sharti			if (gn->suffix)
1867143407Sharti				gn->suffix->refCount++;
1868143407Sharti			free(gn->path);
1869143407Sharti			gn->path = estrdup(gn->name);
1870143407Sharti		}
18711590Srgrimes
1872143407Sharti		goto sfnd_return;
1873143407Sharti	}
187418730Ssteve
1875143407Sharti	/*
1876143407Sharti	 * If the suffix indicates that the target is a library, mark that in
1877143407Sharti	 * the node's type field.
1878143407Sharti	 */
1879143407Sharti	if (targ->suff->flags & SUFF_LIBRARY) {
1880143407Sharti		gn->type |= OP_LIB;
18811590Srgrimes	}
18828874Srgrimes
1883143407Sharti	/*
1884143407Sharti	 * Check for overriding transformation rule implied by sources
1885143407Sharti	 */
1886143407Sharti	if (!Lst_IsEmpty(&gn->children)) {
1887143407Sharti		src = SuffFindCmds(targ, slst);
18881590Srgrimes
1889143407Sharti		if (src != NULL) {
1890143407Sharti			/*
1891143407Sharti			 * Free up all the Src structures in the
1892143407Sharti			 * transformation path up to, but not including,
1893143407Sharti			 * the parent node.
1894143407Sharti			 */
1895143407Sharti			while (bottom && bottom->parent != NULL) {
1896143407Sharti				if (Lst_Member(slst, bottom) == NULL) {
1897143407Sharti					Lst_AtEnd(slst, bottom);
1898143407Sharti				}
1899143407Sharti				bottom = bottom->parent;
1900143407Sharti			}
1901143407Sharti			bottom = src;
19025814Sjkh		}
19031590Srgrimes	}
19041590Srgrimes
1905143407Sharti	if (bottom == NULL) {
1906143407Sharti		/*
1907143407Sharti		 * No idea from where it can come -- return now.
1908143407Sharti		 */
1909143407Sharti		goto sfnd_abort;
1910143407Sharti	}
1911143407Sharti
19121590Srgrimes	/*
1913143407Sharti	 * We now have a list of Src structures headed by 'bottom' and linked
1914143407Sharti	 * via their 'parent' pointers. What we do next is create links between
1915143407Sharti	 * source and target nodes (which may or may not have been created)
1916143407Sharti	 * and set the necessary local variables in each target. The
1917143407Sharti	 * commands for each target are set from the commands of the
1918143407Sharti	 * transformation rule used to get from the src suffix to the targ
1919143407Sharti	 * suffix. Note that this causes the commands list of the original
1920143407Sharti	 * node, gn, to be replaced by the commands of the final
1921143407Sharti	 * transformation rule. Also, the unmade field of gn is incremented.
1922143407Sharti	 * Etc.
19231590Srgrimes	 */
1924143407Sharti	if (bottom->node == NULL) {
1925143407Sharti		bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
1926143407Sharti	}
19271590Srgrimes
1928143407Sharti	for (src = bottom; src->parent != NULL; src = src->parent) {
1929143407Sharti		targ = src->parent;
19308874Srgrimes
1931143407Sharti		if (src->node->suffix)
1932143407Sharti			src->node->suffix->refCount--;
1933143407Sharti		src->node->suffix = src->suff;
1934143407Sharti		src->node->suffix->refCount++;
19351590Srgrimes
1936143407Sharti		if (targ->node == NULL) {
1937143407Sharti			targ->node = Targ_FindNode(targ->file, TARG_CREATE);
1938143407Sharti		}
19391590Srgrimes
1940143407Sharti		SuffApplyTransform(targ->node, src->node,
1941143407Sharti		    targ->suff, src->suff);
19421590Srgrimes
1943143407Sharti		if (targ->node != gn) {
1944143407Sharti			/*
1945143407Sharti			 * Finish off the dependency-search process for any
1946143407Sharti			 * nodes between bottom and gn (no point in questing
1947143407Sharti			 * around the filesystem for their implicit source
1948143407Sharti			 * when it's already known). Note that the node can't
1949143407Sharti			 * have any sources that need expanding, since
1950143407Sharti			 * SuffFindThem will stop on an existing
1951143407Sharti			 * node, so all we need to do is set the standard and
1952143407Sharti			 * System V variables.
1953143407Sharti			 */
1954143407Sharti			targ->node->type |= OP_DEPS_FOUND;
19551590Srgrimes
1956143407Sharti			Var_Set(PREFIX, targ->pref, targ->node);
1957143407Sharti			Var_Set(TARGET, targ->node->name, targ->node);
1958143407Sharti		}
19591590Srgrimes	}
19601590Srgrimes
1961143407Sharti	if (gn->suffix)
1962143407Sharti		gn->suffix->refCount--;
1963143407Sharti	gn->suffix = src->suff;
1964143407Sharti	gn->suffix->refCount++;
19651590Srgrimes
1966143407Sharti	/*
1967143407Sharti	 * So Dir_MTime doesn't go questing for it...
1968143407Sharti	 */
1969143407Sharti	free(gn->path);
1970143407Sharti	gn->path = estrdup(gn->name);
19711590Srgrimes
1972143407Sharti	/*
1973143407Sharti	 * Nuke the transformation path and the Src structures left over in the
1974143407Sharti	 * two lists.
1975143407Sharti	 */
1976143407Sharti  sfnd_return:
1977143407Sharti	if (bottom)
1978143407Sharti		if (Lst_Member(slst, bottom) == NULL)
1979143407Sharti			Lst_AtEnd(slst, bottom);
19801590Srgrimes
1981143407Sharti	while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))
1982143407Sharti		continue;
19835814Sjkh
1984143407Sharti	Lst_Concat(slst, &srcs, LST_CONCLINK);
1985143407Sharti	Lst_Concat(slst, &targs, LST_CONCLINK);
19861590Srgrimes}
19878874Srgrimes
19881590Srgrimes/*-
19891590Srgrimes *-----------------------------------------------------------------------
19901590Srgrimes * Suff_FindDeps  --
19911590Srgrimes *	Find implicit sources for the target described by the graph node
19921590Srgrimes *	gn
19931590Srgrimes *
19941590Srgrimes * Results:
19951590Srgrimes *	Nothing.
19961590Srgrimes *
19971590Srgrimes * Side Effects:
19981590Srgrimes *	Nodes are added to the graph below the passed-in node. The nodes
19991590Srgrimes *	are marked to have their IMPSRC variable filled in. The
20001590Srgrimes *	PREFIX variable is set for the given node and all its
20011590Srgrimes *	implied children.
20021590Srgrimes *
20031590Srgrimes * Notes:
20041590Srgrimes *	The path found by this target is the shortest path in the
20051590Srgrimes *	transformation graph, which may pass through non-existent targets,
20061590Srgrimes *	to an existing target. The search continues on all paths from the
20071590Srgrimes *	root suffix until a file is found. I.e. if there's a path
20081590Srgrimes *	.o -> .c -> .l -> .l,v from the root and the .l,v file exists but
20091590Srgrimes *	the .c and .l files don't, the search will branch out in
20101590Srgrimes *	all directions from .o and again from all the nodes on the
20111590Srgrimes *	next level until the .l,v node is encountered.
20121590Srgrimes *
20131590Srgrimes *-----------------------------------------------------------------------
20141590Srgrimes */
20151590Srgrimesvoid
2016104696SjmallettSuff_FindDeps(GNode *gn)
20175814Sjkh{
20188874Srgrimes
2019143407Sharti	SuffFindDeps(gn, &srclist);
2020143407Sharti	while (SuffRemoveSrc(&srclist))
2021143407Sharti		continue;
20225814Sjkh}
20235814Sjkh
20245814Sjkh
20255814Sjkhstatic void
2026138512ShartiSuffFindDeps(GNode *gn, Lst *slst)
20271590Srgrimes{
2028138232Sharti
2029143407Sharti	if (gn->type & OP_DEPS_FOUND) {
2030143407Sharti		/*
2031143407Sharti		 * If dependencies already found, no need to do it again...
2032143407Sharti		 */
2033143407Sharti		return;
2034143407Sharti	} else {
2035143407Sharti		gn->type |= OP_DEPS_FOUND;
2036143407Sharti	}
20378874Srgrimes
2038143407Sharti	DEBUGF(SUFF, ("SuffFindDeps (%s)\n", gn->name));
20398874Srgrimes
2040143407Sharti	if (gn->type & OP_ARCHV) {
2041143407Sharti		SuffFindArchiveDeps(gn, slst);
20428874Srgrimes
2043143407Sharti	} else if (gn->type & OP_LIB) {
2044143407Sharti		/*
2045143407Sharti		* If the node is a library, it is the arch module's job to find
2046143407Sharti		* it and set the TARGET variable accordingly. We merely provide
2047143407Sharti		* the search path, assuming all libraries end in ".a" (if the
2048143407Sharti		* suffix hasn't been defined, there's nothing we can do for it,
2049143407Sharti		* so we just set the TARGET variable to the node's name in order
2050143407Sharti		* to give it a value).
2051143407Sharti		*/
2052143407Sharti		Suff	*s;
2053143407Sharti
2054143911Sharti		s = SuffSuffFind(LIBSUFF);
2055143407Sharti		if (gn->suffix)
2056143407Sharti			gn->suffix->refCount--;
2057143911Sharti		if (s != NULL) {
2058143911Sharti			gn->suffix = s;
2059143407Sharti			gn->suffix->refCount++;
2060143407Sharti			Arch_FindLib(gn, &s->searchPath);
2061143407Sharti		} else {
2062143407Sharti			gn->suffix = NULL;
2063143407Sharti			Var_Set(TARGET, gn->name, gn);
2064143407Sharti		}
2065143407Sharti
2066143407Sharti		/*
2067143407Sharti		* Because a library (-lfoo) target doesn't follow the standard
2068143407Sharti		* filesystem conventions, we don't set the regular variables for
2069143407Sharti		* the thing. .PREFIX is simply made empty...
2070143407Sharti		*/
2071143407Sharti		Var_Set(PREFIX, "", gn);
2072143407Sharti
20731590Srgrimes	} else {
2074143407Sharti		SuffFindNormalDeps(gn, slst);
20751590Srgrimes	}
20761590Srgrimes}
20771590Srgrimes
20781590Srgrimes/*-
20791590Srgrimes *-----------------------------------------------------------------------
20801590Srgrimes * Suff_SetNull --
20811590Srgrimes *	Define which suffix is the null suffix.
20821590Srgrimes *
20831590Srgrimes * Results:
20841590Srgrimes *	None.
20851590Srgrimes *
20861590Srgrimes * Side Effects:
20871590Srgrimes *	'suffNull' is altered.
20881590Srgrimes *
20891590Srgrimes * Notes:
20901590Srgrimes *	Need to handle the changing of the null suffix gracefully so the
20911590Srgrimes *	old transformation rules don't just go away.
20921590Srgrimes *
20931590Srgrimes *-----------------------------------------------------------------------
20941590Srgrimes */
20951590Srgrimesvoid
2096104696SjmallettSuff_SetNull(char *name)
20971590Srgrimes{
2098143407Sharti	Suff	*s;
20991590Srgrimes
2100143911Sharti	if ((s = SuffSuffFind(name)) == NULL) {
2101143407Sharti		Parse_Error(PARSE_WARNING, "Desired null suffix %s "
2102143407Sharti		    "not defined.", name);
2103143911Sharti		return;
21041590Srgrimes	}
2105143911Sharti
2106143911Sharti	if (suffNull != NULL) {
2107143911Sharti		suffNull->flags &= ~SUFF_NULL;
2108143911Sharti	}
2109143911Sharti	s->flags |= SUFF_NULL;
2110143911Sharti
2111143911Sharti	/*
2112143911Sharti	 * XXX: Here's where the transformation mangling
2113143911Sharti	 * would take place
2114143911Sharti	 */
2115143911Sharti	suffNull = s;
21161590Srgrimes}
21171590Srgrimes
21181590Srgrimes/*-
21191590Srgrimes *-----------------------------------------------------------------------
21201590Srgrimes * Suff_Init --
21211590Srgrimes *	Initialize suffixes module
21221590Srgrimes *
21231590Srgrimes * Results:
21241590Srgrimes *	None
21251590Srgrimes *
21261590Srgrimes * Side Effects:
21271590Srgrimes *	Many
21281590Srgrimes *-----------------------------------------------------------------------
21291590Srgrimes */
21301590Srgrimesvoid
2131138232ShartiSuff_Init(void)
21321590Srgrimes{
2133138232Sharti
2134143407Sharti	sNum = 0;
2135143407Sharti	/*
2136143407Sharti	* Create null suffix for single-suffix rules (POSIX). The thing doesn't
2137143407Sharti	* actually go on the suffix list or everyone will think that's its
2138143407Sharti	* suffix.
2139143407Sharti	*/
2140143407Sharti	emptySuff = suffNull = emalloc(sizeof(Suff));
21411590Srgrimes
2142143407Sharti	suffNull->name = estrdup("");
2143143407Sharti	suffNull->nameLen = 0;
2144144020Sharti	TAILQ_INIT(&suffNull->searchPath);
2145144020Sharti	Path_Concat(&suffNull->searchPath, &dirSearchPath);
2146143407Sharti	Lst_Init(&suffNull->children);
2147143407Sharti	Lst_Init(&suffNull->parents);
2148143407Sharti	Lst_Init(&suffNull->ref);
2149143407Sharti	suffNull->sNum = sNum++;
2150143407Sharti	suffNull->flags = SUFF_NULL;
2151143407Sharti	suffNull->refCount = 1;
21521590Srgrimes}
21531590Srgrimes
21541590Srgrimes/********************* DEBUGGING FUNCTIONS **********************/
21551590Srgrimes
2156143414Shartivoid
2157143414ShartiSuff_PrintAll(void)
21585814Sjkh{
2159143414Sharti	const LstNode	*ln;
2160143414Sharti	const LstNode	*tln;
2161143414Sharti	const GNode	*gn;
2162143414Sharti	const Suff	*s;
2163138232Sharti
2164143414Sharti	static const struct flag2str suff_flags[] = {
2165143414Sharti		{ SUFF_INCLUDE,	"INCLUDE" },
2166143414Sharti		{ SUFF_LIBRARY,	"LIBRARY" },
2167143414Sharti		{ SUFF_NULL,	"NULL" },
2168143414Sharti		{ 0,		NULL }
2169143414Sharti	};
21701590Srgrimes
2171143414Sharti	printf("#*** Suffixes:\n");
2172143414Sharti	LST_FOREACH(ln, &sufflist) {
2173143414Sharti		s = Lst_Datum(ln);
2174143414Sharti		printf("# `%s' [%d] ", s->name, s->refCount);
21751590Srgrimes
2176143414Sharti		if (s->flags != 0) {
2177143414Sharti			printf(" ");
2178146184Sharti			print_flags(stdout, suff_flags, s->flags, 1);
2179143407Sharti		}
21801590Srgrimes
2181143414Sharti		printf("\n#\tTo: ");
2182143414Sharti		LST_FOREACH(tln, &s->parents)
2183143414Sharti			printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name);
21841590Srgrimes
2185143414Sharti		printf("\n#\tFrom: ");
2186143414Sharti		LST_FOREACH(tln, &s->children)
2187143414Sharti			printf("`%s' ", ((const Suff *)Lst_Datum(tln))->name);
21881590Srgrimes
2189143414Sharti		printf("\n#\tSearch Path: ");
2190144020Sharti		Path_Print(&s->searchPath);
21911590Srgrimes
2192143414Sharti		printf("\n");
2193143414Sharti	}
2194138232Sharti
2195143407Sharti	printf("#*** Transformations:\n");
2196143414Sharti	LST_FOREACH(ln, &transforms) {
2197143414Sharti		gn = Lst_Datum(ln);
2198143414Sharti		printf("%-16s: ", gn->name);
2199143414Sharti		Targ_PrintType(gn->type);
2200143414Sharti		printf("\n");
2201143414Sharti		LST_FOREACH(tln, &gn->commands)
2202143414Sharti			printf("\t%s\n", (const char *)Lst_Datum(tln));
2203143414Sharti		printf("\n");
2204143414Sharti	}
22051590Srgrimes}
2206