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