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