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

Last change on this file since 38 was 35, checked in by bird, 22 years ago

emx is kind of working again...

  • 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 efree
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 efree ((Address)s->name);
362 efree ((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 * efree 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 efree(ptr);
908 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
909 efree(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 efree'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 efree ((Address)s->file);
1108 if (!s->parent)
1109 efree((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("efree: [l=%x] p=%x %d\n", l, s, s->children);
1120 Lst_Destroy(s->cp, NOFREE);
1121#endif
1122 Lst_Remove(l, ln);
1123 efree ((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 efree(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 efree 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 efree(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 efree((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 efree(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 efree'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.