source: trunk/src/kmk/suff.c@ 22

Last change on this file since 22 was 9, checked in by bird, 23 years ago

Initial revision

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 62.9 KB
Line 
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 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: src/usr.bin/make/suff.c,v 1.26 2002/10/09 03:42:10 jmallett Exp $");
43
44/*-
45 * suff.c --
46 * Functions to maintain suffix lists and find implicit dependents
47 * using suffix transformation rules
48 *
49 * Interface:
50 * Suff_Init Initialize all things to do with suffixes.
51 *
52 * Suff_End Cleanup the module
53 *
54 * Suff_DoPaths This function is used to make life easier
55 * when searching for a file according to its
56 * suffix. It takes the global search path,
57 * as defined using the .PATH: target, and appends
58 * its directories to the path of each of the
59 * defined suffixes, as specified using
60 * .PATH<suffix>: targets. In addition, all
61 * directories given for suffixes labeled as
62 * include files or libraries, using the .INCLUDES
63 * or .LIBS targets, are played with using
64 * Dir_MakeFlags to create the .INCLUDES and
65 * .LIBS global variables.
66 *
67 * Suff_ClearSuffixes Clear out all the suffixes and defined
68 * transformations.
69 *
70 * Suff_IsTransform Return TRUE if the passed string is the lhs
71 * of a transformation rule.
72 *
73 * Suff_AddSuffix Add the passed string as another known suffix.
74 *
75 * Suff_GetPath Return the search path for the given suffix.
76 *
77 * Suff_AddInclude Mark the given suffix as denoting an include
78 * file.
79 *
80 * Suff_AddLib Mark the given suffix as denoting a library.
81 *
82 * Suff_AddTransform Add another transformation to the suffix
83 * graph. Returns GNode suitable for framing, I
84 * mean, tacking commands, attributes, etc. on.
85 *
86 * Suff_SetNull Define the suffix to consider the suffix of
87 * any file that doesn't have a known one.
88 *
89 * Suff_FindDeps Find implicit sources for and the location of
90 * a target based on its suffix. Returns the
91 * bottom-most node added to the graph or NULL
92 * if the target had no implicit sources.
93 */
94
95#include <stdio.h>
96#include "make.h"
97#include "hash.h"
98#include "dir.h"
99
100static Lst sufflist; /* Lst of suffixes */
101static Lst suffClean; /* Lst of suffixes to be cleaned */
102static Lst srclist; /* Lst of sources */
103static Lst transforms; /* Lst of transformation rules */
104
105static int sNum = 0; /* Counter for assigning suffix numbers */
106
107/*
108 * Structure describing an individual suffix.
109 */
110typedef struct _Suff {
111 char *name; /* The suffix itself */
112 int nameLen; /* Length of the suffix */
113 short flags; /* Type of suffix */
114#define SUFF_INCLUDE 0x01 /* One which is #include'd */
115#define SUFF_LIBRARY 0x02 /* One which contains a library */
116#define SUFF_NULL 0x04 /* The empty suffix */
117 Lst searchPath; /* The path along which files of this suffix
118 * may be found */
119 int sNum; /* The suffix number */
120 int refCount; /* Reference count of list membership */
121 Lst parents; /* Suffixes we have a transformation to */
122 Lst children; /* Suffixes we have a transformation from */
123 Lst ref; /* List of lists this suffix is referenced */
124} Suff;
125
126/*
127 * Structure used in the search for implied sources.
128 */
129typedef struct _Src {
130 char *file; /* The file to look for */
131 char *pref; /* Prefix from which file was formed */
132 Suff *suff; /* The suffix on the file */
133 struct _Src *parent; /* The Src for which this is a source */
134 GNode *node; /* The node describing the file */
135 int children; /* Count of existing children (so we don't free
136 * this thing too early or never nuke it) */
137#ifdef DEBUG_SRC
138 Lst cp; /* Debug; children list */
139#endif
140} Src;
141
142/*
143 * A structure for passing more than one argument to the Lst-library-invoked
144 * function...
145 */
146typedef struct {
147 Lst l;
148 Src *s;
149} LstSrc;
150
151static Suff *suffNull; /* The NULL suffix for this run */
152static Suff *emptySuff; /* The empty suffix required for POSIX
153 * single-suffix transformation rules */
154
155
156static char *SuffStrIsPrefix(char *, char *);
157static char *SuffSuffIsSuffix(Suff *, char *);
158static int SuffSuffIsSuffixP(void *, void *);
159static int SuffSuffHasNameP(void *, void *);
160static int SuffSuffIsPrefix(void *, void *);
161static int SuffGNHasNameP(void *, void *);
162static void SuffFree(void *);
163static void SuffInsert(Lst, Suff *);
164static void SuffRemove(Lst, Suff *);
165static Boolean SuffParseTransform(char *, Suff **, Suff **);
166static int SuffRebuildGraph(void *, void *);
167static int SuffAddSrc(void *, void *);
168static int SuffRemoveSrc(Lst);
169static void SuffAddLevel(Lst, Src *);
170static Src *SuffFindThem(Lst, Lst);
171static Src *SuffFindCmds(Src *, Lst);
172static int SuffExpandChildren(void *, void *);
173static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
174static void SuffFindDeps(GNode *, Lst);
175static void SuffFindArchiveDeps(GNode *, Lst);
176static void SuffFindNormalDeps(GNode *, Lst);
177static int SuffPrintName(void *, void *);
178static int SuffPrintSuff(void *, void *);
179static int SuffPrintTrans(void *, void *);
180
181 /*************** Lst Predicates ****************/
182/*-
183 *-----------------------------------------------------------------------
184 * SuffStrIsPrefix --
185 * See if pref is a prefix of str.
186 *
187 * Results:
188 * NULL if it ain't, pointer to character in str after prefix if so
189 *
190 * Side Effects:
191 * None
192 *-----------------------------------------------------------------------
193 */
194static char *
195SuffStrIsPrefix (char *pref, char *str)
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 */
219static char *
220SuffSuffIsSuffix (Suff *s, char *str)
221{
222 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 *-----------------------------------------------------------------------
249 */
250static int
251SuffSuffIsSuffixP(void *s, void *str)
252{
253 return(!SuffSuffIsSuffix((Suff *) s, (char *) str));
254}
255
256/*-
257 *-----------------------------------------------------------------------
258 * SuffSuffHasNameP --
259 * Callback procedure for finding a suffix based on its name. Used by
260 * Suff_GetPath.
261 *
262 * Results:
263 * 0 if the suffix is of the given name. non-zero otherwise.
264 *
265 * Side Effects:
266 * None
267 *-----------------------------------------------------------------------
268 */
269static int
270SuffSuffHasNameP (void *s, void *sname)
271{
272 return (strcmp ((char *) sname, ((Suff *) s)->name));
273}
274
275/*-
276 *-----------------------------------------------------------------------
277 * SuffSuffIsPrefix --
278 * See if the suffix described by s is a prefix of the string. Care
279 * must be taken when using this to search for transformations and
280 * what-not, since there could well be two suffixes, one of which
281 * is a prefix of the other...
282 *
283 * Results:
284 * 0 if s is a prefix of str. non-zero otherwise
285 *
286 * Side Effects:
287 * None
288 *-----------------------------------------------------------------------
289 */
290static int
291SuffSuffIsPrefix (void *s, void *str)
292{
293 return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);
294}
295
296/*-
297 *-----------------------------------------------------------------------
298 * SuffGNHasNameP --
299 * See if the graph node has the desired name
300 *
301 * Results:
302 * 0 if it does. non-zero if it doesn't
303 *
304 * Side Effects:
305 * None
306 *-----------------------------------------------------------------------
307 */
308static int
309SuffGNHasNameP (void *gn, void *name)
310{
311 return (strcmp ((char *) name, ((GNode *) gn)->name));
312}
313
314 /*********** Maintenance Functions ************/
315
316/*-
317 *-----------------------------------------------------------------------
318 * SuffFree --
319 * Free up all memory associated with the given suffix structure.
320 *
321 * Results:
322 * none
323 *
324 * Side Effects:
325 * the suffix entry is detroyed
326 *-----------------------------------------------------------------------
327 */
328static void
329SuffFree (void *sp)
330{
331 Suff *s = (Suff *) sp;
332
333 if (s == suffNull)
334 suffNull = NULL;
335
336 if (s == emptySuff)
337 emptySuff = NULL;
338
339 Lst_Destroy (s->ref, NOFREE);
340 Lst_Destroy (s->children, NOFREE);
341 Lst_Destroy (s->parents, NOFREE);
342 Lst_Destroy (s->searchPath, Dir_Destroy);
343
344 free (s->name);
345 free (s);
346}
347
348/*-
349 *-----------------------------------------------------------------------
350 * SuffRemove --
351 * Remove the suffix into the list
352 *
353 * Results:
354 * None
355 *
356 * Side Effects:
357 * The reference count for the suffix is decremented
358 *-----------------------------------------------------------------------
359 */
360static void
361SuffRemove(Lst l, Suff *s)
362{
363 LstNode ln = Lst_Member(l, (void *)s);
364 if (ln != NULL) {
365 Lst_Remove(l, ln);
366 s->refCount--;
367 }
368}
369
370
371/*-
372 *-----------------------------------------------------------------------
373 * SuffInsert --
374 * Insert the suffix into the list keeping the list ordered by suffix
375 * numbers.
376 *
377 * Results:
378 * None
379 *
380 * Side Effects:
381 * The reference count of the suffix is incremented
382 *-----------------------------------------------------------------------
383 */
384static void
385SuffInsert (Lst l, Suff *s)
386{
387 LstNode ln; /* current element in l we're examining */
388 Suff *s2 = NULL; /* the suffix descriptor in this element */
389
390 if (Lst_Open (l) == FAILURE) {
391 return;
392 }
393 while ((ln = Lst_Next (l)) != NULL) {
394 s2 = (Suff *) Lst_Datum (ln);
395 if (s2->sNum >= s->sNum) {
396 break;
397 }
398 }
399 if (s2 == NULL) {
400 DEBUGF(SUFF, ("inserting an empty list?..."));
401 }
402
403 Lst_Close (l);
404 DEBUGF(SUFF, ("inserting %s(%d)...", s->name, s->sNum));
405 if (ln == NULL) {
406 DEBUGF(SUFF, ("at end of list\n"));
407 (void)Lst_AtEnd (l, (void *)s);
408 s->refCount++;
409 (void)Lst_AtEnd(s->ref, (void *) l);
410 } else if (s2->sNum != s->sNum) {
411 DEBUGF(SUFF, ("before %s(%d)\n", s2->name, s2->sNum));
412 (void)Lst_Insert (l, ln, (void *)s);
413 s->refCount++;
414 (void)Lst_AtEnd(s->ref, (void *) l);
415 } else {
416 DEBUGF(SUFF, ("already there\n"));
417 }
418}
419
420/*-
421 *-----------------------------------------------------------------------
422 * Suff_ClearSuffixes --
423 * This is gross. Nuke the list of suffixes but keep all transformation
424 * rules around. The transformation graph is destroyed in this process,
425 * but we leave the list of rules so when a new graph is formed the rules
426 * will remain.
427 * This function is called from the parse module when a
428 * .SUFFIXES:\n line is encountered.
429 *
430 * Results:
431 * none
432 *
433 * Side Effects:
434 * the sufflist and its graph nodes are destroyed
435 *-----------------------------------------------------------------------
436 */
437void
438Suff_ClearSuffixes (void)
439{
440 Lst_Concat (suffClean, sufflist, LST_CONCLINK);
441 sufflist = Lst_Init(FALSE);
442 sNum = 1;
443 suffNull = emptySuff;
444 /*
445 * Clear suffNull's children list (the other suffixes are built new, but
446 * suffNull is used as is).
447 * NOFREE is used because all suffixes are are on the suffClean list.
448 * suffNull should not have parents.
449 */
450 Lst_Destroy(suffNull->children, NOFREE);
451 suffNull->children = Lst_Init(FALSE);
452}
453
454/*-
455 *-----------------------------------------------------------------------
456 * SuffParseTransform --
457 * Parse a transformation string to find its two component suffixes.
458 *
459 * Results:
460 * TRUE if the string is a valid transformation and FALSE otherwise.
461 *
462 * Side Effects:
463 * The passed pointers are overwritten.
464 *
465 *-----------------------------------------------------------------------
466 */
467static Boolean
468SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr)
469{
470 LstNode srcLn; /* element in suffix list of trans source*/
471 Suff *src; /* Source of transformation */
472 LstNode targLn; /* element in suffix list of trans target*/
473 char *str2; /* Extra pointer (maybe target suffix) */
474 LstNode singleLn; /* element in suffix list of any suffix
475 * that exactly matches str */
476 Suff *single = NULL;/* Source of possible transformation to
477 * null suffix */
478
479 srcLn = NULL;
480 singleLn = NULL;
481
482 /*
483 * Loop looking first for a suffix that matches the start of the
484 * string and then for one that exactly matches the rest of it. If
485 * we can find two that meet these criteria, we've successfully
486 * parsed the string.
487 */
488 for (;;) {
489 if (srcLn == NULL) {
490 srcLn = Lst_Find(sufflist, (void *)str, SuffSuffIsPrefix);
491 } else {
492 srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (void *)str,
493 SuffSuffIsPrefix);
494 }
495 if (srcLn == NULL) {
496 /*
497 * Ran out of source suffixes -- no such rule
498 */
499 if (singleLn != NULL) {
500 /*
501 * Not so fast Mr. Smith! There was a suffix that encompassed
502 * the entire string, so we assume it was a transformation
503 * to the null suffix (thank you POSIX). We still prefer to
504 * find a double rule over a singleton, hence we leave this
505 * check until the end.
506 *
507 * XXX: Use emptySuff over suffNull?
508 */
509 *srcPtr = single;
510 *targPtr = suffNull;
511 return(TRUE);
512 }
513 return (FALSE);
514 }
515 src = (Suff *) Lst_Datum (srcLn);
516 str2 = str + src->nameLen;
517 if (*str2 == '\0') {
518 single = src;
519 singleLn = srcLn;
520 } else {
521 targLn = Lst_Find(sufflist, (void *)str2, SuffSuffHasNameP);
522 if (targLn != NULL) {
523 *srcPtr = src;
524 *targPtr = (Suff *)Lst_Datum(targLn);
525 return (TRUE);
526 }
527 }
528 }
529}
530
531/*-
532 *-----------------------------------------------------------------------
533 * Suff_IsTransform --
534 * Return TRUE if the given string is a transformation rule
535 *
536 *
537 * Results:
538 * TRUE if the string is a concatenation of two known suffixes.
539 * FALSE otherwise
540 *
541 * Side Effects:
542 * None
543 *-----------------------------------------------------------------------
544 */
545Boolean
546Suff_IsTransform (char *str)
547{
548 Suff *src, *targ;
549
550 return (SuffParseTransform(str, &src, &targ));
551}
552
553/*-
554 *-----------------------------------------------------------------------
555 * Suff_AddTransform --
556 * Add the transformation rule described by the line to the
557 * list of rules and place the transformation itself in the graph
558 *
559 * Results:
560 * The node created for the transformation in the transforms list
561 *
562 * Side Effects:
563 * The node is placed on the end of the transforms Lst and links are
564 * made between the two suffixes mentioned in the target name
565 *-----------------------------------------------------------------------
566 */
567GNode *
568Suff_AddTransform (char *line)
569{
570 GNode *gn; /* GNode of transformation rule */
571 Suff *s, /* source suffix */
572 *t; /* target suffix */
573 LstNode ln; /* Node for existing transformation */
574
575 ln = Lst_Find (transforms, (void *)line, SuffGNHasNameP);
576 if (ln == NULL) {
577 /*
578 * Make a new graph node for the transformation. It will be filled in
579 * by the Parse module.
580 */
581 gn = Targ_NewGN (line);
582 (void)Lst_AtEnd (transforms, (void *)gn);
583 } else {
584 /*
585 * New specification for transformation rule. Just nuke the old list
586 * of commands so they can be filled in again... We don't actually
587 * free the commands themselves, because a given command can be
588 * attached to several different transformations.
589 */
590 gn = (GNode *) Lst_Datum (ln);
591 Lst_Destroy (gn->commands, NOFREE);
592 Lst_Destroy (gn->children, NOFREE);
593 gn->commands = Lst_Init (FALSE);
594 gn->children = Lst_Init (FALSE);
595 }
596
597 gn->type = OP_TRANSFORM;
598
599 (void)SuffParseTransform(line, &s, &t);
600
601 /*
602 * link the two together in the proper relationship and order
603 */
604 DEBUGF(SUFF, ("defining transformation from `%s' to `%s'\n",
605 s->name, t->name));
606 SuffInsert (t->children, s);
607 SuffInsert (s->parents, t);
608
609 return (gn);
610}
611
612/*-
613 *-----------------------------------------------------------------------
614 * Suff_EndTransform --
615 * Handle the finish of a transformation definition, removing the
616 * transformation from the graph if it has neither commands nor
617 * sources. This is a callback procedure for the Parse module via
618 * Lst_ForEach
619 *
620 * Results:
621 * === 0
622 *
623 * Side Effects:
624 * If the node has no commands or children, the children and parents
625 * lists of the affected suffices are altered.
626 *
627 *-----------------------------------------------------------------------
628 */
629int
630Suff_EndTransform(void *gnp, void *dummy __unused)
631{
632 GNode *gn = (GNode *) gnp;
633
634 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
635 Lst_IsEmpty(gn->children))
636 {
637 Suff *s, *t;
638
639 (void)SuffParseTransform(gn->name, &s, &t);
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 */
684static int
685SuffRebuildGraph(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 */
756void
757Suff_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 */
798Lst
799Suff_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 */
831void
832Suff_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 */
893void
894Suff_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 */
922void
923Suff_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 */
951static int
952SuffAddSrc (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 */
1018static void
1019SuffAddLevel (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 */
1041static int
1042SuffRemoveSrc (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 */
1108static Src *
1109SuffFindThem (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 */
1170static Src *
1171SuffFindCmds (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 */
1260static int
1261SuffExpandChildren(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 */
1486static Boolean
1487SuffApplyTransform(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 */
1586static void
1587SuffFindArchiveDeps(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 efree(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 */
1717static void
1718SuffFindNormalDeps(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 *target;
1772
1773 /*
1774 * Allocate a Src structure to which things can be transformed
1775 */
1776 target = (Src *)emalloc(sizeof (Src));
1777 target->file = estrdup(gn->name);
1778 target->suff = (Suff *)Lst_Datum(ln);
1779 target->suff->refCount++;
1780 target->node = gn;
1781 target->parent = (Src *)NULL;
1782 target->children = 0;
1783#ifdef DEBUG_SRC
1784 target->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 - target->suff->nameLen) - sopref;
1792 target->pref = emalloc(prefLen + 1);
1793 memcpy(target->pref, sopref, prefLen);
1794 target->pref[prefLen] = '\0';
1795
1796 /*
1797 * Add nodes from which the target can be made
1798 */
1799 SuffAddLevel(srcs, target);
1800
1801 /*
1802 * Record the target so we can nuke it
1803 */
1804 (void)Lst_AtEnd(targs, (void *)target);
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
1891sfnd_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 efree(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 efree(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 */
2066sfnd_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
2107void
2108Suff_FindDeps(GNode *gn)
2109{
2110
2111 SuffFindDeps(gn, srclist);
2112 while (SuffRemoveSrc(srclist))
2113 continue;
2114}
2115
2116
2117static void
2118SuffFindDeps (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 */
2184void
2185Suff_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 */
2219void
2220Suff_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
2262void
2263Suff_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
2276static int
2277SuffPrintName(void *s, void *dummy __unused)
2278{
2279 printf ("`%s' ", ((Suff *) s)->name);
2280 return (0);
2281}
2282
2283static int
2284SuffPrintSuff (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 default:
2309 break;
2310 }
2311 fputc(flags ? '|' : ')', stdout);
2312 }
2313 }
2314 fputc ('\n', stdout);
2315 printf ("#\tTo: ");
2316 Lst_ForEach (s->parents, SuffPrintName, (void *)0);
2317 fputc ('\n', stdout);
2318 printf ("#\tFrom: ");
2319 Lst_ForEach (s->children, SuffPrintName, (void *)0);
2320 fputc ('\n', stdout);
2321 printf ("#\tSearch Path: ");
2322 Dir_PrintPath (s->searchPath);
2323 fputc ('\n', stdout);
2324 return (0);
2325}
2326
2327static int
2328SuffPrintTrans (void *tp, void *dummy __unused)
2329{
2330 GNode *t = (GNode *) tp;
2331
2332 printf ("%-16s: ", t->name);
2333 Targ_PrintType (t->type);
2334 fputc ('\n', stdout);
2335 Lst_ForEach (t->commands, Targ_PrintCmd, (void *)0);
2336 fputc ('\n', stdout);
2337 return (0);
2338}
2339
2340void
2341Suff_PrintAll(void)
2342{
2343 printf ("#*** Suffixes:\n");
2344 Lst_ForEach (sufflist, SuffPrintSuff, (void *)0);
2345
2346 printf ("#*** Transformations:\n");
2347 Lst_ForEach (transforms, SuffPrintTrans, (void *)0);
2348}
Note: See TracBrowser for help on using the repository browser.