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