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