VirtualBox

source: kBuild/trunk/src/kmk/suff.c@ 30

Last change on this file since 30 was 25, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r24,
which included commits to RCS files with non-trunk default branches.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette