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