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