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