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