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