Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s);
Lst_ForEach(transforms, SuffRebuildGraph, s);
static Src *SuffFindCmds __P((Src *, Lst));static int SuffExpandChildren __P((ClientData, ClientData));static Boolean SuffApplyTransform __P((GNode *, GNode *, Suff *, Suff *));static void SuffFindDeps __P((GNode *, Lst));static void SuffFindArchiveDeps __P((GNode *, Lst));static void SuffFindNormalDeps __P((GNode *, Lst));static int SuffPrintName __P((ClientData, ClientData));static int SuffPrintSuff __P((ClientData, ClientData));static int SuffPrintTrans __P((ClientData, ClientData));	/*************** Lst Predicates ****************//*- *----------------------------------------------------------------------- * SuffStrIsPrefix  -- *	See if pref is a prefix of str. * * Results: *	NULL if it ain't, pointer to character in str after prefix if so * * Side Effects: *	None *----------------------------------------------------------------------- */static char    *SuffStrIsPrefix (pref, str)    register char  *pref;	/* possible prefix */    register char  *str;	/* string to check */{    while (*str && *pref == *str) {	pref++;	str++;    }    return (*pref ? NULL : str);}/*- *----------------------------------------------------------------------- * SuffSuffIsSuffix  -- *	See if suff is a suffix of str. Str should point to THE END of the *	string to check. (THE END == the null byte) * * Results: *	NULL if it ain't, pointer to character in str before suffix if *	it is. * * Side Effects: *	None *----------------------------------------------------------------------- */static char *SuffSuffIsSuffix (s, str)    register Suff  *s;		/* possible suffix */    char           *str;	/* string to examine */{    register char  *p1;	    	/* Pointer into suffix name */    register char  *p2;	    	/* Pointer into string being examined */    p1 = s->name + s->nameLen;    p2 = str;    while (p1 >= s->name && *p1 == *p2) {	p1--;	p2--;    }    return (p1 == s->name - 1 ? p2 : NULL);}/*- *----------------------------------------------------------------------- * SuffSuffIsSuffixP -- *	Predicate form of SuffSuffIsSuffix. Passed as the callback function *	to Lst_Find. * * Results: *	0 if the suffix is the one desired, non-zero if not. * * Side Effects: *	None. * *----------------------------------------------------------------------- */static intSuffSuffIsSuffixP(s, str)    ClientData   s;    ClientData   str;{    return(!SuffSuffIsSuffix((Suff *) s, (char *) str));}/*- *----------------------------------------------------------------------- * SuffSuffHasNameP -- *	Callback procedure for finding a suffix based on its name. Used by *	Suff_GetPath. * * Results: *	0 if the suffix is of the given name. non-zero otherwise. * * Side Effects: *	None *----------------------------------------------------------------------- */static intSuffSuffHasNameP (s, sname)    ClientData    s;	    	    /* Suffix to check */    ClientData    sname; 	    /* Desired name */{    return (strcmp ((char *) sname, ((Suff *) s)->name));}/*- *----------------------------------------------------------------------- * SuffSuffIsPrefix  -- *	See if the suffix described by s is a prefix of the string. Care *	must be taken when using this to search for transformations and *	what-not, since there could well be two suffixes, one of which *	is a prefix of the other... * * Results: *	0 if s is a prefix of str. non-zero otherwise * * Side Effects: *	None *----------------------------------------------------------------------- */static intSuffSuffIsPrefix (s, str)    ClientData   s;		/* suffix to compare */    ClientData   str;	/* string to examine */{    return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);}/*- *----------------------------------------------------------------------- * SuffGNHasNameP  -- *	See if the graph node has the desired name * * Results: *	0 if it does. non-zero if it doesn't * * Side Effects: *	None *----------------------------------------------------------------------- */static intSuffGNHasNameP (gn, name)    ClientData      gn;		/* current node we're looking at */    ClientData      name;	/* name we're looking for */{    return (strcmp ((char *) name, ((GNode *) gn)->name));} 	    /*********** Maintenance Functions ************/static voidSuffUnRef(lp, sp)    ClientData lp;    ClientData sp;{    Lst l = (Lst) lp;    LstNode ln = Lst_Member(l, sp);    if (ln != NULL)	Lst_Remove(l, ln);}/*- *----------------------------------------------------------------------- * SuffFree  -- *	Free up all memory associated with the given suffix structure. * * Results: *	none * * Side Effects: *	the suffix entry is detroyed *----------------------------------------------------------------------- */static voidSuffFree (sp)    ClientData sp;{    Suff           *s = (Suff *) sp;    if (s == suffNull)	suffNull = NULL;    if (s == emptySuff)	emptySuff = NULL;    Lst_Destroy (s->ref, NOFREE);    Lst_Destroy (s->children, NOFREE);    Lst_Destroy (s->parents, NOFREE);    Lst_Destroy (s->searchPath, Dir_Destroy);    free ((Address)s->name);    free ((Address)s);}/*- *----------------------------------------------------------------------- * SuffRemove  -- *	Remove the suffix from the list *----------------------------------------------------------------------- */static voidSuffRemove(l, s)    Lst l;    Suff *s;{    SuffUnRef((ClientData) l, (ClientData) s);}/*- *----------------------------------------------------------------------- * SuffInsert  -- *	Insert the suffix into the list keeping the list ordered by suffix *	numbers. * * Results: *	None * * Side Effects: *	The reference count of the suffix is incremented *----------------------------------------------------------------------- */static voidSuffInsert (l, s)    Lst           l;		/* the list where in s should be inserted */    Suff          *s;		/* the suffix to insert */{    LstNode 	  ln;		/* current element in l we're examining */    Suff          *s2 = NULL;	/* the suffix descriptor in this element */    if (Lst_Open (l) == FAILURE) {	return;    }    while ((ln = Lst_Next (l)) != NULL) {	s2 = (Suff *) Lst_Datum (ln);	if (s2->sNum >= s->sNum) {	    break;	}    }    Lst_Close (l);    if (DEBUG(SUFF)) {	printf("inserting %s(%d)...", s->name, s->sNum);    }    if (ln == NULL) {	if (DEBUG(SUFF)) {	    printf("at end of list\n");	}	Lst_AtEnd (l, (ClientData)s);	Lst_AtEnd(s->ref, (ClientData) l);    } else if (s2->sNum != s->sNum) {	if (DEBUG(SUFF)) {	    printf("before %s(%d)\n", s2->name, s2->sNum);	}	Lst_Insert(l, ln, (ClientData)s);	Lst_AtEnd(s->ref, (ClientData) l);    } else if (DEBUG(SUFF)) {	printf("already there\n");    }}/*- *----------------------------------------------------------------------- * Suff_ClearSuffixes -- *	This is gross. Nuke the list of suffixes but keep all transformation *	rules around. The transformation graph is destroyed in this process, *	but we leave the list of rules so when a new graph is formed the rules *	will remain. *	This function is called from the parse module when a *	.SUFFIXES:\n line is encountered. * * Results: *	none * * Side Effects: *	the sufflist and its graph nodes are destroyed *----------------------------------------------------------------------- */voidSuff_ClearSuffixes (){#ifdef CLEANUP    Lst_Concat(suffClean, sufflist, LST_CONCLINK);#endif    sufflist = Lst_Init();    sNum = 0;    suffNull = emptySuff;}/*- *----------------------------------------------------------------------- * SuffParseTransform -- *	Parse a transformation string to find its two component suffixes. * * Results: *	TRUE if the string is a valid transformation and FALSE otherwise. * * Side Effects: *	The passed pointers are overwritten. * *----------------------------------------------------------------------- */static BooleanSuffParseTransform(str, srcPtr, targPtr)    char    	  	*str;	    	/* String being parsed */    Suff    	  	**srcPtr;   	/* Place to store source of trans. */    Suff    	  	**targPtr;  	/* Place to store target of trans. */{    register LstNode	srcLn;	    /* element in suffix list of trans source*/    register Suff    	*src;	    /* Source of transformation */    register LstNode    targLn;	    /* element in suffix list of trans target*/    register char    	*str2;	    /* Extra pointer (maybe target suffix) */    LstNode 	    	singleLn;   /* element in suffix list of any suffix				     * that exactly matches str */    Suff    	    	*single = NULL;/* Source of possible transformation to				     * null suffix */    srcLn = NULL;    singleLn = NULL;    /*     * Loop looking first for a suffix that matches the start of the     * string and then for one that exactly matches the rest of it. If     * we can find two that meet these criteria, we've successfully     * parsed the string.     */    for (;;) {	if (srcLn == NULL) {	    srcLn = Lst_Find(sufflist, SuffSuffIsPrefix, (ClientData)str);	} else {	    srcLn = Lst_FindFrom(Lst_Succ(srcLn), 				  SuffSuffIsPrefix, (ClientData)str);	}	if (srcLn == NULL) {	    /*	     * Ran out of source suffixes -- no such rule	     */	    if (singleLn != NULL) {		/*		 * Not so fast Mr. Smith! There was a suffix that encompassed		 * the entire string, so we assume it was a transformation		 * to the null suffix (thank you POSIX). We still prefer to		 * find a double rule over a singleton, hence we leave this		 * check until the end.		 *		 * XXX: Use emptySuff over suffNull?		 */		*srcPtr = single;		*targPtr = suffNull;		return(TRUE);	    }	    return (FALSE);	}	src = (Suff *) Lst_Datum (srcLn);	str2 = str + src->nameLen;	if (*str2 == '\0') {	    single = src;	    singleLn = srcLn;	} else {	    targLn = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)str2);	    if (targLn != NULL) {		*srcPtr = src;		*targPtr = (Suff *)Lst_Datum(targLn);		return (TRUE);	    }	}    }}/*- *----------------------------------------------------------------------- * Suff_IsTransform  -- *	Return TRUE if the given string is a transformation rule * * * Results: *	TRUE if the string is a concatenation of two known suffixes. *	FALSE otherwise * * Side Effects: *	None *----------------------------------------------------------------------- */BooleanSuff_IsTransform (str)    char          *str;	    	/* string to check */{    Suff    	  *src, *targ;    return (SuffParseTransform(str, &src, &targ));}/*- *----------------------------------------------------------------------- * Suff_AddTransform -- *	Add the transformation rule described by the line to the *	list of rules and place the transformation itself in the graph * * Results: *	The node created for the transformation in the transforms list * * Side Effects: *	The node is placed on the end of the transforms Lst and links are *	made between the two suffixes mentioned in the target name *----------------------------------------------------------------------- */GNode *Suff_AddTransform (line)    char          *line;	/* name of transformation to add */{    GNode         *gn;		/* GNode of transformation rule */    Suff          *s,		/* source suffix */                  *t;		/* target suffix */    LstNode 	  ln;	    	/* Node for existing transformation */    ln = Lst_Find(transforms, SuffGNHasNameP, (ClientData)line);    if (ln == NULL) {	/*	 * Make a new graph node for the transformation. It will be filled in	 * by the Parse module.	 */	gn = Targ_NewGN (line);	Lst_AtEnd (transforms, (ClientData)gn);    } else {	/*	 * New specification for transformation rule. Just nuke the old list	 * of commands so they can be filled in again... We don't actually	 * free the commands themselves, because a given command can be	 * attached to several different transformations.	 */	gn = (GNode *) Lst_Datum (ln);	Lst_Destroy (gn->commands, NOFREE);	Lst_Destroy (gn->children, NOFREE);	gn->commands = Lst_Init();	gn->children = Lst_Init();    }    gn->type = OP_TRANSFORM;    (void)SuffParseTransform(line, &s, &t);    /*     * link the two together in the proper relationship and order     */    if (DEBUG(SUFF)) {	printf("defining transformation from `%s' to `%s'\n",		s->name, t->name);    }    SuffInsert (t->children, s);    SuffInsert (s->parents, t);    return (gn);}/*- *----------------------------------------------------------------------- * Suff_EndTransform -- *	Handle the finish of a transformation definition, removing the *	transformation from the graph if it has neither commands nor *	sources. This is a callback procedure for the Parse module via *	Lst_ForEach * * Results: *	=== 0 * * Side Effects: *	If the node has no commands or children, the children and parents *	lists of the affected suffices are altered. * *----------------------------------------------------------------------- */intSuff_EndTransform(gnp, dummy)    ClientData   gnp;    	/* Node for transformation */    ClientData   dummy;    	/* Node for transformation */{    GNode *gn = (GNode *) gnp;    if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&	Lst_IsEmpty(gn->children))    {	Suff	*s, *t;	(void)SuffParseTransform(gn->name, &s, &t);	if (DEBUG(SUFF)) {	    printf("deleting transformation from `%s' to `%s'\n",		    s->name, t->name);	}	/*	 * Remove the source from the target's children list. 	 *	 * We'll be called twice when the next target is seen, but .c and .o	 * are only linked once...	 */	SuffRemove(t->children, s);	/*	 * Remove the target from the source's parents list	 */	SuffRemove(s->parents, t);    } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {	printf("transformation %s complete\n", gn->name);    }    return(dummy ? 0 : 0);}/*- *----------------------------------------------------------------------- * SuffRebuildGraph -- *	Called from Suff_AddSuffix via Lst_ForEach to search through the *	list of existing transformation rules and rebuild the transformation *	graph when it has been destroyed by Suff_ClearSuffixes. If the *	given rule is a transformation involving this suffix and another, *	existing suffix, the proper relationship is established between *	the two. * * Results: *	Always 0. * * Side Effects: *	The appropriate links will be made between this suffix and *	others if transformation rules exist for it. * *----------------------------------------------------------------------- */static intSuffRebuildGraph(transformp, sp)    ClientData  transformp; /* Transformation to test */    ClientData  sp;	    /* Suffix to rebuild */{    GNode   	*transform = (GNode *) transformp;    Suff    	*s = (Suff *) sp;    char 	*cp;    LstNode	ln;    Suff  	*s2;    /*     * First see if it is a transformation from this suffix.     */    cp = SuffStrIsPrefix(s->name, transform->name);    if (cp != (char *)NULL) {	ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)cp);	if (ln != NULL) {	    /*	     * Found target. Link in and return, since it can't be anything	     * else.	     */	    s2 = (Suff *)Lst_Datum(ln);	    SuffInsert(s2->children, s);	    SuffInsert(s->parents, s2);	    return(0);	}    }    /*     * Not from, maybe to?     */    cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));    if (cp != (char *)NULL) {	/*	 * Null-terminate the source suffix in order to find it.	 */	cp[1] = '\0';	ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)transform->name);	/*	 * Replace the start of the target suffix	 */	cp[1] = s->name[0];	if (ln != NULL) {	    /*	     * Found it -- establish the proper relationship	     */	    s2 = (Suff *)Lst_Datum(ln);	    SuffInsert(s->children, s2);	    SuffInsert(s2->parents, s);	}    }    return(0);}/*- *----------------------------------------------------------------------- * Suff_AddSuffix -- *	Add the suffix in string to the end of the list of known suffixes. *	Should we restructure the suffix graph? Make doesn't... * * Results: *	None * * Side Effects: *	A GNode is created for the suffix and a Suff structure is created and *	added to the suffixes list unless the suffix was already known. *----------------------------------------------------------------------- */voidSuff_AddSuffix (str)    char          *str;	    /* the name of the suffix to add */{    Suff          *s;	    /* new suffix descriptor */    LstNode 	  ln;    ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)str);    if (ln == NULL) {	s = (Suff *) emalloc (sizeof (Suff));	s->name =   	estrdup (str);	s->nameLen = 	strlen (s->name);	s->searchPath = Lst_Init();	s->children = 	Lst_Init();	s->parents = 	Lst_Init();	s->ref = 	Lst_Init();	s->sNum =   	sNum++;	s->flags =  	0;	Lst_AtEnd(sufflist, (ClientData)s);	/*	 * Look for any existing transformations from or to this suffix.	 * XXX: Only do this after a Suff_ClearSuffixes?	 */	Lst_ForEach (transforms, SuffRebuildGraph, (ClientData)s);    }}/*- *----------------------------------------------------------------------- * Suff_GetPath -- *	Return the search path for the given suffix, if it's defined. * * Results: *	The searchPath for the desired suffix or NULL if the suffix isn't *	defined. * * Side Effects: *	None *----------------------------------------------------------------------- */LstSuff_GetPath (sname)    char    	  *sname;{    LstNode   	  ln;    Suff    	  *s;    ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)sname);    if (ln == NULL) {	return (NULL);    } else {	s = (Suff *) Lst_Datum (ln);	return (s->searchPath);    }}/*- *----------------------------------------------------------------------- * Suff_DoPaths -- *	Extend the search paths for all suffixes to include the default *	search path. * * Results: *	None. * * Side Effects: *	The searchPath field of all the suffixes is extended by the *	directories in dirSearchPath. If paths were specified for the *	".h" suffix, the directories are stuffed into a global variable *	called ".INCLUDES" with each directory preceeded by a -I. The same *	is done for the ".a" suffix, except the variable is called *	".LIBS" and the flag is -L. *----------------------------------------------------------------------- */voidSuff_DoPaths(){    register Suff   	*s;    register LstNode  	ln;    char		*ptr;    Lst	    	    	inIncludes; /* Cumulative .INCLUDES path */    Lst	    	    	inLibs;	    /* Cumulative .LIBS path */    if (Lst_Open (sufflist) == FAILURE) {	return;    }    inIncludes = Lst_Init();    inLibs = Lst_Init();    while ((ln = Lst_Next (sufflist)) != NULL) {	s = (Suff *) Lst_Datum (ln);	if (!Lst_IsEmpty (s->searchPath)) {#ifdef INCLUDES	    if (s->flags & SUFF_INCLUDE) {		Dir_Concat(inIncludes, s->searchPath);	    }#endif /* INCLUDES */#ifdef LIBRARIES	    if (s->flags & SUFF_LIBRARY) {		Dir_Concat(inLibs, s->searchPath);	    }#endif /* LIBRARIES */	    Dir_Concat(s->searchPath, dirSearchPath);	} else {	    Lst_Destroy (s->searchPath, Dir_Destroy);	    s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);	}    }    Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);    free(ptr);    Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);    free(ptr);    Lst_Destroy(inIncludes, Dir_Destroy);    Lst_Destroy(inLibs, Dir_Destroy);    Lst_Close (sufflist);}/*- *----------------------------------------------------------------------- * Suff_AddInclude -- *	Add the given suffix as a type of file which gets included. *	Called from the parse module when a .INCLUDES line is parsed. *	The suffix must have already been defined. * * Results: *	None. * * Side Effects: *	The SUFF_INCLUDE bit is set in the suffix's flags field * *----------------------------------------------------------------------- */voidSuff_AddInclude (sname)    char	  *sname;     /* Name of suffix to mark */{    LstNode	  ln;    Suff	  *s;    ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)sname);    if (ln != NULL) {	s = (Suff *) Lst_Datum (ln);	s->flags |= SUFF_INCLUDE;    }}/*- *----------------------------------------------------------------------- * Suff_AddLib -- *	Add the given suffix as a type of file which is a library. *	Called from the parse module when parsing a .LIBS line. The *	suffix must have been defined via .SUFFIXES before this is *	called. * * Results: *	None. * * Side Effects: *	The SUFF_LIBRARY bit is set in the suffix's flags field * *----------------------------------------------------------------------- */voidSuff_AddLib (sname)    char	  *sname;     /* Name of suffix to mark */{    LstNode	  ln;    Suff	  *s;    ln = Lst_Find(sufflist, SuffSuffHasNameP, (ClientData)sname);    if (ln != NULL) {	s = (Suff *) Lst_Datum (ln);	s->flags |= SUFF_LIBRARY;    }} 	  /********** Implicit Source Search Functions *********//*- *----------------------------------------------------------------------- * SuffAddSrc  -- *	Add a suffix as a Src structure to the given list with its parent *	being the given Src structure. If the suffix is the null suffix, *	the prefix is used unaltered as the file name in the Src structure. * * Results: *	always returns 0 * * Side Effects: *	A Src structure is created and tacked onto the end of the list *----------------------------------------------------------------------- */static intSuffAddSrc (sp, lsp)    ClientData	sp;	    /* suffix for which to create a Src structure */    ClientData  lsp;	    /* list and parent for the new Src */{    Suff	*s = (Suff *) sp;    LstSrc      *ls = (LstSrc *) lsp;    Src         *s2;	    /* new Src structure */    Src    	*targ; 	    /* Target structure */    targ = ls->s;    if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {	/*	 * If the suffix has been marked as the NULL suffix, also create a Src	 * structure for a file with no suffix attached. Two birds, and all	 * that...	 */	s2 = (Src *) emalloc (sizeof (Src));	s2->file =  	estrdup(targ->pref);	s2->pref =  	targ->pref;	s2->parent = 	targ;	s2->node =  	NULL;	s2->suff =  	s;	s2->children =	0;	targ->children += 1;	Lst_AtEnd(ls->l, (ClientData)s2);#ifdef DEBUG_SRC	s2->cp = Lst_Init();	Lst_AtEnd(targ->cp, (ClientData) s2);	printf("1 add %x %x to %x:", targ, s2, ls->l);	Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);	printf("\n");#endif    }    s2 = (Src *) emalloc (sizeof (Src));    s2->file = 	    str_concat (targ->pref, s->name, 0);    s2->pref =	    targ->pref;    s2->parent =    targ;    s2->node = 	    NULL;    s2->suff = 	    s;    s2->children =  0;    targ->children += 1;    Lst_AtEnd(ls->l, (ClientData)s2);#ifdef DEBUG_SRC    s2->cp = Lst_Init();    Lst_AtEnd(targ->cp, (ClientData)s2);    printf("2 add %x %x to %x:", targ, s2, ls->l);    Lst_ForEach(ls->l, PrintAddr, (ClientData) 0);    printf("\n");#endif    return(0);}/*- *----------------------------------------------------------------------- * SuffAddLevel  -- *	Add all the children of targ as Src structures to the given list * * Results: *	None * * Side Effects: * 	Lots of structures are created and added to the list *----------------------------------------------------------------------- */static voidSuffAddLevel (l, targ)    Lst            l;		/* list to which to add the new level */    Src            *targ;	/* Src structure to use as the parent */{    LstSrc         ls;    ls.s = targ;    ls.l = l;    Lst_ForEach (targ->suff->children, SuffAddSrc, (ClientData)&ls);}/*- *---------------------------------------------------------------------- * SuffRemoveSrc -- *	Free all src structures in list that don't have a reference count * * Results: *	Ture if an src was removed * * Side Effects: *	The memory is free'd. *---------------------------------------------------------------------- */static intSuffRemoveSrc (l)    Lst l;{    LstNode ln;    Src *s;    int t = 0;    if (Lst_Open (l) == FAILURE) {	return 0;    }#ifdef DEBUG_SRC    printf("cleaning %lx: ", (unsigned long) l);    Lst_ForEach(l, PrintAddr, (ClientData) 0);    printf("\n");#endif    while ((ln = Lst_Next (l)) != NULL) {	s = (Src *) Lst_Datum (ln);	if (s->children == 0) {	    free ((Address)s->file);	    if (!s->parent)		free((Address)s->pref);	    else {#ifdef DEBUG_SRC		LstNode ln = Lst_Member(s->parent->cp, (ClientData)s);		if (ln != NULL)		    Lst_Remove(s->parent->cp, ln);#endif		--s->parent->children;	    }#ifdef DEBUG_SRC	    printf("free: [l=%x] p=%x %d\n", l, s, s->children);	    Lst_Destroy(s->cp, NOFREE);#endif	    Lst_Remove(l, ln);	    free ((Address)s);	    t |= 1;	    Lst_Close(l);	    return TRUE;	}#ifdef DEBUG_SRC	else {	    printf("keep: [l=%x] p=%x %d: ", l, s, s->children);	    Lst_ForEach(s->cp, PrintAddr, (ClientData) 0);	    printf("\n");	}#endif    }    Lst_Close(l);    return t;}/*- *----------------------------------------------------------------------- * SuffFindThem -- *	Find the first existing file/target in the list srcs * * Results: *	The lowest structure in the chain of transformations * * Side Effects: *	None *----------------------------------------------------------------------- */static Src *SuffFindThem (srcs, slst)    Lst            srcs;	/* list of Src structures to search through */    Lst		   slst;{    Src            *s;		/* current Src */    Src		   *rs;		/* returned Src */    char	   *ptr;    rs = (Src *) NULL;    while ((s = (Src *)Lst_DeQueue(srcs)) != NULL) {	if (DEBUG(SUFF)) {	    printf ("\ttrying %s...", s->file);	}	/*	 * A file is considered to exist if either a node exists in the	 * graph for it or the file actually exists.	 */	if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {#ifdef DEBUG_SRC	    printf("remove %x from %x\n", s, srcs);#endif	    rs = s;	    break;	}	if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {	    rs = s;#ifdef DEBUG_SRC	    printf("remove %x from %x\n", s, srcs);#endif	    free(ptr);	    break;	}	if (DEBUG(SUFF)) {	    printf ("not there\n");	}	SuffAddLevel (srcs, s);	Lst_AtEnd(slst, (ClientData)s);    }    if (DEBUG(SUFF) && rs) {	printf ("got it\n");    }    return (rs);}/*- *----------------------------------------------------------------------- * SuffFindCmds -- *	See if any of the children of the target in the Src structure is *	one from which the target can be transformed. If there is one, *	a Src structure is put together for it and returned. * * Results: *	The Src structure of the "winning" child, or NULL if no such beast. * * Side Effects: *	A Src structure may be allocated. * *----------------------------------------------------------------------- */static Src *SuffFindCmds (targ, slst)    Src	    	*targ;	/* Src structure to play with */    Lst		slst;{    LstNode 	  	ln; 	/* General-purpose list node */    register GNode	*t, 	/* Target GNode */	    	  	*s; 	/* Source GNode */    int	    	  	prefLen;/* The length of the defined prefix */    Suff    	  	*suff;	/* Suffix on matching beastie */    Src	    	  	*ret;	/* Return value */    char    	  	*cp;    t = targ->node;    (void) Lst_Open (t->children);    prefLen = strlen (targ->pref);    while ((ln = Lst_Next (t->children)) != NULL) {	s = (GNode *)Lst_Datum (ln);	cp = strrchr (s->name, '/');	if (cp == (char *)NULL) {	    cp = s->name;	} else {	    cp++;	}	if (strncmp (cp, targ->pref, prefLen) == 0) {	    /*	     * The node matches the prefix ok, see if it has a known	     * suffix.	     */	    ln = Lst_Find(sufflist, SuffSuffHasNameP, 	    	(ClientData)&cp[prefLen]);	    if (ln != NULL) {		/*		 * It even has a known suffix, see if there's a transformation		 * defined between the node's suffix and the target's suffix.		 *		 * XXX: Handle multi-stage transformations here, too.		 */		suff = (Suff *)Lst_Datum (ln);		if (Lst_Member (suff->parents,				(ClientData)targ->suff) != NULL)		{		    /*		     * Hot Damn! Create a new Src structure to describe		     * this transformation (making sure to duplicate the		     * source node's name so Suff_FindDeps can free it		     * again (ick)), and return the new structure.		     */		    ret = (Src *)emalloc (sizeof (Src));		    ret->file = estrdup(s->name);		    ret->pref = targ->pref;		    ret->suff = suff;		    ret->parent = targ;		    ret->node = s;		    ret->children = 0;		    targ->children += 1;#ifdef DEBUG_SRC		    ret->cp = Lst_Init();		    printf("3 add %x %x\n", targ, ret);		    Lst_AtEnd(targ->cp, (ClientData)ret);#endif		    Lst_AtEnd(slst, (ClientData)ret);		    if (DEBUG(SUFF)) {			printf ("\tusing existing source %s\n", s->name);		    }		    return (ret);		}	    }	}    }    Lst_Close (t->children);    return ((Src *)NULL);}