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