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