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