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