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