Annotation of src/usr.bin/make/suff.c, Revision 1.103
1.103 ! espie 1: /* $OpenBSD: suff.c,v 1.102 2020/01/13 15:41:53 espie Exp $ */
1.5 millert 2: /* $NetBSD: suff.c,v 1.13 1996/11/06 17:59:25 christos Exp $ */
1.1 deraadt 3:
4: /*
1.5 millert 5: * Copyright (c) 1988, 1989, 1990, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 deraadt 7: * Copyright (c) 1989 by Berkeley Softworks
8: * All rights reserved.
9: *
10: * This code is derived from software contributed to Berkeley by
11: * Adam de Boor.
12: *
13: * Redistribution and use in source and binary forms, with or without
14: * modification, are permitted provided that the following conditions
15: * are met:
16: * 1. Redistributions of source code must retain the above copyright
17: * notice, this list of conditions and the following disclaimer.
18: * 2. Redistributions in binary form must reproduce the above copyright
19: * notice, this list of conditions and the following disclaimer in the
20: * documentation and/or other materials provided with the distribution.
1.50 millert 21: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 22: * may be used to endorse or promote products derived from this software
23: * without specific prior written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35: * SUCH DAMAGE.
36: */
37:
38: /*-
39: * suff.c --
40: * Functions to maintain suffix lists and find implicit dependents
41: * using suffix transformation rules
42: */
43:
1.42 espie 44: #include <ctype.h>
1.85 espie 45: #include <stddef.h>
46: #include <stdint.h>
1.42 espie 47: #include <stdio.h>
1.43 espie 48: #include <stdlib.h>
1.42 espie 49: #include <string.h>
1.70 espie 50: #include <ohash.h>
1.42 espie 51: #include "defines.h"
52: #include "dir.h"
1.70 espie 53: #include "engine.h"
1.42 espie 54: #include "suff.h"
55: #include "var.h"
56: #include "targ.h"
57: #include "error.h"
58: #include "str.h"
59: #include "lst.h"
60: #include "memory.h"
61: #include "gnode.h"
1.52 espie 62: #include "stats.h"
1.81 espie 63: #include "dump.h"
1.100 espie 64: #include "expandchildren.h"
1.36 espie 65:
1.72 espie 66: /* XXX the suffixes hash is stored using a specific hash function, suitable
67: * for looking up suffixes in reverse.
68: */
69: static struct ohash suffixes;
70:
71: /* We remember the longest suffix, so we don't need to look beyond that. */
1.99 espie 72: size_t maxLen = 0U;
1.72 espie 73: static LIST srclist;
74:
75: /* Transforms (.c.o) are stored in another hash, independently from suffixes.
76: * When make sees a target, it checks whether it's currently parsable as a
77: * transform (according to the active suffixes). If yes, it's stored as a
78: * new transform.
79: *
80: * XXX
81: * But transforms DO NOT have a canonical decomposition as a set of suffixes,
82: * and will be used as necessary later, when looking up implicit rules for
83: * actual targets.
84: *
85: * For instance, a transform .a.b.c can be parsed as .a -> .b.c if suffixes
86: * .a and .b.c are active, and then LATER, reused as .a.b -> .c if suffixes
87: * .a.b and .c are active.
88: */
1.70 espie 89: static struct ohash transforms;
1.1 deraadt 90:
1.72 espie 91: /* conflicts between suffixes are solved by suffix declaration order. */
92: static int order = 0;
1.1 deraadt 93:
94: /*
95: * Structure describing an individual suffix.
96: */
1.82 espie 97: struct Suff_ {
1.72 espie 98: size_t nameLen; /* optimisation: strlen(name) */
99: short flags;
100: #define SUFF_ACTIVE 0x08 /* We never destroy suffixes and rules, */
101: /* we just deactivate them. */
1.70 espie 102: #define SUFF_PATH 0x10 /* False suffix: actually, the path keyword */
103: LIST searchPath; /* The path along which files of this suffix
104: * may be found */
1.78 espie 105: int order; /* order of declaration for conflict
1.72 espie 106: * resolution. */
107: LIST parents; /* List of Suff we have a transformation to */
108: LIST children; /* List of Suff we have a transformation from */
109: char name[1];
1.82 espie 110: };
1.1 deraadt 111:
1.70 espie 112: static struct ohash_info suff_info = {
1.78 espie 113: offsetof(struct Suff_, name), NULL,
1.88 espie 114: hash_calloc, hash_free, element_alloc
1.70 espie 115: };
116:
1.1 deraadt 117: /*
118: * Structure used in the search for implied sources.
119: */
1.40 espie 120: typedef struct Src_ {
1.70 espie 121: char *file; /* The file to look for */
1.84 espie 122: char *prefix; /* Prefix from which file was formed */
1.70 espie 123: Suff *suff; /* The suffix on the file */
124: struct Src_ *parent; /* The Src for which this is a source */
125: GNode *node; /* The node describing the file */
126: int children; /* Count of existing children (so we don't free
1.1 deraadt 127: * this thing too early or never nuke it) */
128: #ifdef DEBUG_SRC
1.70 espie 129: LIST cp; /* Debug; children list */
1.1 deraadt 130: #endif
131: } Src;
132:
133: /*
134: * A structure for passing more than one argument to the Lst-library-invoked
135: * function...
136: */
137: typedef struct {
1.70 espie 138: Lst l;
139: Src *s;
1.1 deraadt 140: } LstSrc;
141:
1.70 espie 142: static Suff *emptySuff; /* The empty suffix required for POSIX
143: * single-suffix transformation rules */
144:
145:
146: #define parse_transform(s, p, q) parse_transformi(s, s + strlen(s), p, q)
147: static bool parse_transformi(const char *, const char *, Suff **, Suff **);
148: #define new_suffix(s) new_suffixi(s, NULL)
149: static Suff *new_suffixi(const char *, const char *);
150: static void reverse_hash_add_char(uint32_t *, const char *);
151: static uint32_t reverse_hashi(const char *, const char **);
152: static unsigned int reverse_slot(struct ohash *, const char *, const char **);
153: static void record_possible_suffix(Suff *, GNode *, char *, Lst, Lst);
154: static void record_possible_suffixes(GNode *, Lst, Lst);
155: static Suff *find_suffix_as_suffix(Lst, const char *, const char *);
156: static Suff *add_suffixi(const char *, const char *);
1.1 deraadt 157:
1.41 espie 158: static void SuffInsert(Lst, Suff *);
159: static void SuffAddSrc(void *, void *);
1.95 espie 160: static bool SuffRemoveSrc(Lst);
1.41 espie 161: static void SuffAddLevel(Lst, Src *);
162: static Src *SuffFindThem(Lst, Lst);
163: static Src *SuffFindCmds(Src *, Lst);
1.42 espie 164: static bool SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
1.41 espie 165: static void SuffFindDeps(GNode *, Lst);
166: static void SuffFindArchiveDeps(GNode *, Lst);
167: static void SuffFindNormalDeps(GNode *, Lst);
168: static void SuffPrintName(void *);
169: static void SuffPrintSuff(void *);
1.70 espie 170: static void SuffPrintTrans(GNode *);
1.1 deraadt 171:
1.70 espie 172: #define find_suff(name) find_suffi(name, NULL)
173: static Suff *find_suffi(const char *, const char *);
174: static Suff *find_best_suffix(const char *, const char *);
175: static GNode *find_transform(const char *);
176: static GNode *find_or_create_transformi(const char *, const char *);
177: static void setup_paths(void);
178: static void build_suffixes_graph(void);
179: static void special_path_hack(void);
1.52 espie 180:
1.42 espie 181: #ifdef DEBUG_SRC
182: static void PrintAddr(void *);
183: #endif
1.70 espie 184:
1.72 espie 185: /* hash functions for the suffixes hash */
186: /* add one char to the hash */
1.70 espie 187: static void
188: reverse_hash_add_char(uint32_t *pk, const char *s)
189: {
190: *pk = ((*pk << 2) | (*pk >> 30)) ^ *s;
191: }
192:
1.72 espie 193: /* build a full hash from end to start */
1.70 espie 194: static uint32_t
195: reverse_hashi(const char *s, const char **e)
1.1 deraadt 196: {
1.70 espie 197: const char *p;
198: uint32_t k;
199:
200: if (*e == NULL)
201: *e = s + strlen(s);
202: p = *e;
203: if (p == s)
204: k = 0;
205: else
206: k = *--p;
207: while (p != s) {
208: reverse_hash_add_char(&k, --p);
1.66 espie 209: }
1.70 espie 210: return k;
211: }
212:
213: static unsigned int
214: reverse_slot(struct ohash *h, const char *s, const char **e)
215: {
216: uint32_t hv;
1.1 deraadt 217:
1.70 espie 218: hv = reverse_hashi(s, e);
219: return ohash_lookup_interval(h, s, *e, hv);
1.1 deraadt 220: }
221:
1.70 espie 222:
1.1 deraadt 223: static char *
1.70 espie 224: suffix_is_suffix(Suff *s, const char *str, const char *estr)
1.1 deraadt 225: {
1.70 espie 226: const char *p1; /* Pointer into suffix name */
227: const char *p2; /* Pointer into string being examined */
1.1 deraadt 228:
1.70 espie 229: if (estr - str < (ptrdiff_t) s->nameLen)
230: return NULL;
1.66 espie 231: p1 = s->name + s->nameLen;
1.70 espie 232: p2 = estr;
1.1 deraadt 233:
1.66 espie 234: while (p1 != s->name) {
235: p1--;
236: p2--;
237: if (*p1 != *p2)
238: return NULL;
239: }
1.1 deraadt 240:
1.66 espie 241: return (char *)p2;
1.1 deraadt 242: }
243:
1.70 espie 244: static Suff *
245: find_suffi(const char *name, const char *ename)
1.1 deraadt 246: {
1.70 espie 247: unsigned int slot;
248: #ifdef STATS_SUFF
249: STAT_SUFF_LOOKUP_NAME++;
250: #endif
251: slot = reverse_slot(&suffixes, name, &ename);
252: return ohash_find(&suffixes, slot);
1.1 deraadt 253: }
254:
1.70 espie 255: static GNode *
256: find_transform(const char *name)
1.1 deraadt 257: {
1.70 espie 258: unsigned int slot;
1.1 deraadt 259:
1.52 espie 260: #ifdef STATS_SUFF
1.70 espie 261: STAT_TRANSFORM_LOOKUP_NAME++;
1.52 espie 262: #endif
1.70 espie 263: slot = ohash_qlookup(&transforms, name);
264:
265: return ohash_find(&transforms, slot);
1.52 espie 266: }
267:
1.70 espie 268: static GNode *
269: find_or_create_transformi(const char *name, const char *end)
1.52 espie 270: {
1.70 espie 271: GNode *r;
272: unsigned int slot;
1.52 espie 273:
274: #ifdef STATS_SUFF
1.66 espie 275: STAT_TRANSFORM_LOOKUP_NAME++;
1.52 espie 276: #endif
1.70 espie 277: slot = ohash_qlookupi(&transforms, name, &end);
1.1 deraadt 278:
1.70 espie 279: r = ohash_find(&transforms, slot);
1.1 deraadt 280:
1.70 espie 281: if (r == NULL) {
282: r = Targ_NewGNi(name, end);
283: ohash_insert(&transforms, slot, r);
284: }
285: return r;
286: }
1.1 deraadt 287:
288: /*-
289: *-----------------------------------------------------------------------
290: * SuffInsert --
291: * Insert the suffix into the list keeping the list ordered by suffix
292: * numbers.
293: *
294: * Side Effects:
295: * The reference count of the suffix is incremented
296: *-----------------------------------------------------------------------
297: */
298: static void
1.51 espie 299: SuffInsert(Lst l, Suff *s)
1.1 deraadt 300: {
1.70 espie 301: LstNode ln; /* current element in l we're examining */
302: Suff *s2 = NULL; /* the suffix descriptor in this element */
1.1 deraadt 303:
1.66 espie 304: for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
1.91 espie 305: s2 = Lst_Datum(ln);
1.72 espie 306: if (s2->order >= s->order)
1.66 espie 307: break;
308: }
1.1 deraadt 309:
1.70 espie 310: if (DEBUG(SUFF))
1.72 espie 311: printf("inserting %s(%d)...", s->name, s->order);
1.66 espie 312: if (ln == NULL) {
1.70 espie 313: if (DEBUG(SUFF))
1.66 espie 314: printf("at end of list\n");
315: Lst_AtEnd(l, s);
1.72 espie 316: } else if (s2->order != s->order) {
1.70 espie 317: if (DEBUG(SUFF))
1.72 espie 318: printf("before %s(%d)\n", s2->name, s2->order);
1.66 espie 319: Lst_Insert(l, ln, s);
320: } else if (DEBUG(SUFF)) {
321: printf("already there\n");
1.1 deraadt 322: }
323: }
324:
1.99 espie 325: /* Suff_DisableAllSuffixes
326: * mark all current suffixes as inactive, and reset precedence
327: * computation. */
328: void
329: Suff_DisableAllSuffixes(void)
1.70 espie 330: {
331: unsigned int i;
332: Suff *s;
333:
334: for (s = ohash_first(&suffixes, &i); s != NULL;
335: s = ohash_next(&suffixes, &i))
1.72 espie 336: s->flags &= ~SUFF_ACTIVE;
1.70 espie 337:
1.72 espie 338: order = 0;
1.70 espie 339: maxLen = 0;
340: }
341:
342:
343: /* okay = parse_transform(str, &src, &targ);
344: * try parsing a string as a transformation rule, returns true if
345: * successful. Fills &src, &targ with the constituent suffixes.
346: * Special hack: source suffixes must exist OR be the special SUFF_PATH
347: * pseudo suffix (.PATH)
1.1 deraadt 348: */
1.42 espie 349: static bool
1.70 espie 350: parse_transformi(const char *str, const char *e, Suff **srcPtr, Suff **targPtr)
351: {
352: Suff *src, *target, *best_src, *best_target;
353: const char *p;
354:
355: size_t len;
356: uint32_t hv;
357: unsigned int slot;
358:
359: /* empty string -> no suffix */
360: if (e == str)
361: return false;
362:
363: len = e - str;
1.66 espie 364:
1.70 espie 365: if (len > 2 * maxLen)
366: return false;
367:
368: p = e;
369: best_src = best_target = NULL;
1.66 espie 370:
1.70 espie 371: hv = *--p;
372: while (p != str) {
373: slot = ohash_lookup_interval(&suffixes, p, e, hv);
374: /* no double suffix in there */
375: if (p - str <= (ptrdiff_t)maxLen) {
376: target = ohash_find(&suffixes, slot);
1.72 espie 377: if (target != NULL && (target->flags & SUFF_ACTIVE)) {
1.70 espie 378: src = find_suffi(str, p);
379: if (src != NULL &&
1.72 espie 380: (src->flags & (SUFF_ACTIVE | SUFF_PATH))) {
1.70 espie 381: /* XXX even if we find a set of suffixes, we
382: * have to keep going to find the best one,
383: * namely, the one whose src appears first in
384: * .SUFFIXES
1.66 espie 385: */
1.70 espie 386: if (best_src == NULL ||
1.72 espie 387: src->order < best_src->order) {
1.70 espie 388: best_src = src;
389: best_target = target;
390: }
391: }
1.66 espie 392: }
393: }
1.70 espie 394: /* can't be a suffix anyways */
395: if (e - p >= (ptrdiff_t)maxLen)
396: break;
397: reverse_hash_add_char(&hv, --p);
398: }
399:
400: if (p == str && best_src == NULL) {
401: /* no double suffix transformation, resort to single suffix if
402: * we find one. */
403: slot = ohash_lookup_interval(&suffixes, p, e, hv);
404: src = ohash_find(&suffixes, slot);
1.72 espie 405: if (src != NULL && (src->flags & (SUFF_ACTIVE | SUFF_PATH))) {
1.70 espie 406: best_src = src;
1.81 espie 407: best_target = emptySuff;
1.70 espie 408: }
409: }
410: if (best_src != NULL) {
411: *srcPtr = best_src;
412: *targPtr = best_target;
413: return true;
414: } else {
415: return false;
1.1 deraadt 416: }
417: }
418:
1.70 espie 419: static void
420: special_path_hack(void)
421: {
422: Suff *path = add_suffixi(".PATH", NULL);
423: path->flags |= SUFF_PATH;
424: }
425:
426: static Suff *
427: find_best_suffix(const char *s, const char *e)
1.1 deraadt 428: {
1.70 espie 429: const char *p;
430: uint32_t hv;
431: unsigned int slot;
432: Suff *best = NULL;
433: Suff *suff;
1.1 deraadt 434:
1.70 espie 435: if (e == s)
436: return NULL;
437: p = e;
438: hv = *--p;
439: while (p != s) {
440: slot = ohash_lookup_interval(&suffixes, p, e, hv);
441: suff = ohash_find(&suffixes, slot);
442: if (suff != NULL)
1.72 espie 443: if (best == NULL || suff->order < best->order)
1.70 espie 444: best = suff;
445: if (e - p >= (ptrdiff_t)maxLen)
446: break;
447: reverse_hash_add_char(&hv, --p);
448: }
449: return best;
1.1 deraadt 450: }
451:
1.100 espie 452: Lst
453: find_best_path(const char *name)
454: {
455: Suff *s = find_best_suffix(name, name + strlen(name));
456: if (s != NULL) {
457: if (DEBUG(SUFF))
458: printf("suffix is \"%s\"...", s->name);
459: return &s->searchPath;
460: } else
461: return defaultPath;
462: }
463:
1.1 deraadt 464: /*-
465: *-----------------------------------------------------------------------
1.70 espie 466: * Suff_ParseAsTransform --
467: * Try parsing a target line as a transformation rule, depending on
468: * existing suffixes.
1.1 deraadt 469: *
1.82 espie 470: * Possibly create a new transform, or reset an existing one.
1.1 deraadt 471: *-----------------------------------------------------------------------
472: */
473: GNode *
1.70 espie 474: Suff_ParseAsTransform(const char *line, const char *end)
1.1 deraadt 475: {
1.70 espie 476: GNode *gn; /* GNode of transformation rule */
477: Suff *s; /* source suffix */
478: Suff *t; /* target suffix */
479:
480: if (!parse_transformi(line, end, &s, &t))
481: return NULL;
1.1 deraadt 482:
1.70 espie 483: gn = find_or_create_transformi(line, end);
484: /* In case the transform already exists, nuke old commands and children.
485: * Note we can't free them, since there might be stuff that references
486: * them elsewhere
487: */
488: if (!Lst_IsEmpty(&gn->commands)) {
1.66 espie 489: Lst_Destroy(&gn->commands, NOFREE);
490: Lst_Init(&gn->commands);
1.70 espie 491: }
492: if (!Lst_IsEmpty(&gn->children)) {
1.66 espie 493: Lst_Destroy(&gn->children, NOFREE);
494: Lst_Init(&gn->children);
495: }
1.1 deraadt 496:
1.66 espie 497: gn->type = OP_TRANSFORM;
1.70 espie 498: if (s->flags & SUFF_PATH) {
1.101 espie 499: gn->special = SPECIAL_PATH;
1.70 espie 500: gn->suffix = t;
501: }
1.1 deraadt 502:
1.70 espie 503: if (DEBUG(SUFF))
1.66 espie 504: printf("defining transformation from `%s' to `%s'\n",
505: s->name, t->name);
1.70 espie 506: return gn;
507: }
508:
509: static void
510: make_suffix_known(Suff *s)
511: {
1.72 espie 512: if ((s->flags & SUFF_ACTIVE) == 0) {
513: s->order = order++;
514: s->flags |= SUFF_ACTIVE;
1.70 espie 515: if (s->nameLen > maxLen)
516: maxLen = s->nameLen;
1.66 espie 517: }
1.70 espie 518: }
1.1 deraadt 519:
1.70 espie 520: static Suff *
521: new_suffixi(const char *str, const char *eptr)
522: {
523: Suff *s;
524:
525: s = ohash_create_entry(&suff_info, str, &eptr);
526: s->nameLen = eptr - str;
527: Lst_Init(&s->searchPath);
528: Lst_Init(&s->children);
529: Lst_Init(&s->parents);
530: s->flags = 0;
531: return s;
1.1 deraadt 532: }
533:
534: /*-
535: *-----------------------------------------------------------------------
1.70 espie 536: * Suff_AddSuffix --
537: * Add the suffix in string to the end of the list of known suffixes.
538: * Should we restructure the suffix graph? Make doesn't...
1.1 deraadt 539: *
540: * Side Effects:
1.70 espie 541: * A GNode is created for the suffix and a Suff structure is created and
542: * added to the known suffixes, unless it was already known.
1.1 deraadt 543: *-----------------------------------------------------------------------
544: */
1.27 espie 545: void
1.70 espie 546: Suff_AddSuffixi(const char *str, const char *end)
1.1 deraadt 547: {
1.70 espie 548: (void)add_suffixi(str, end);
549: }
1.5 millert 550:
1.70 espie 551: static Suff *
552: add_suffixi(const char *str, const char *end)
553: {
554: Suff *s; /* new suffix descriptor */
1.66 espie 555:
1.70 espie 556: unsigned int slot;
1.66 espie 557:
1.70 espie 558: slot = reverse_slot(&suffixes, str, &end);
559: s = ohash_find(&suffixes, slot);
560: if (s == NULL) {
561: s = new_suffixi(str, end);
562: ohash_insert(&suffixes, slot, s);
563: }
564: make_suffix_known(s);
565: return s;
566: }
1.1 deraadt 567:
1.70 espie 568: Lst
569: find_suffix_path(GNode *gn)
570: {
571: if (gn->suffix != NULL && gn->suffix != emptySuff)
572: return &(gn->suffix->searchPath);
573: else
574: return defaultPath;
575: }
1.1 deraadt 576:
1.70 espie 577: static void
578: build_suffixes_graph(void)
1.1 deraadt 579: {
1.70 espie 580: Suff *s, *s2;
581: GNode *gn;
582: unsigned int i;
583:
584: for (gn = ohash_first(&transforms, &i); gn != NULL;
585: gn = ohash_next(&transforms, &i)) {
586: if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
587: continue;
1.101 espie 588: if (gn->special == SPECIAL_PATH)
1.70 espie 589: continue;
590: if (parse_transform(gn->name, &s, &s2)) {
591: SuffInsert(&s2->children, s);
592: SuffInsert(&s->parents, s2);
593: }
1.66 espie 594: }
1.1 deraadt 595: }
596:
597: /*-
598: *-----------------------------------------------------------------------
1.70 espie 599: * setup_paths
1.1 deraadt 600: * Extend the search paths for all suffixes to include the default
601: * search path.
602: *
603: * Side Effects:
604: * The searchPath field of all the suffixes is extended by the
1.99 espie 605: * directories in defaultPath.
1.1 deraadt 606: *-----------------------------------------------------------------------
607: */
1.70 espie 608: static void
609: setup_paths(void)
1.1 deraadt 610: {
1.70 espie 611: unsigned int i;
612: Suff *s;
1.66 espie 613:
1.70 espie 614: for (s = ohash_first(&suffixes, &i); s != NULL;
615: s = ohash_next(&suffixes, &i)) {
616: if (!Lst_IsEmpty(&s->searchPath))
1.66 espie 617: Dir_Concat(&s->searchPath, defaultPath);
1.70 espie 618: else
1.66 espie 619: Lst_Clone(&s->searchPath, defaultPath, Dir_CopyDir);
620: }
1.1 deraadt 621: }
622:
623: void
1.70 espie 624: process_suffixes_after_makefile_is_read(void)
1.1 deraadt 625: {
1.70 espie 626: /* once the Makefile is finish reading, we can set up the default PATH
627: * stuff, and build the final suffixes graph
628: */
629: setup_paths();
630: /* and we link all transforms to active suffixes at this point. */
631: build_suffixes_graph();
1.1 deraadt 632: }
1.41 espie 633: /********** Implicit Source Search Functions *********/
1.1 deraadt 634:
635: /*-
636: *-----------------------------------------------------------------------
637: * SuffAddSrc --
638: * Add a suffix as a Src structure to the given list with its parent
639: * being the given Src structure. If the suffix is the null suffix,
640: * the prefix is used unaltered as the file name in the Src structure.
641: *
642: * Side Effects:
643: * A Src structure is created and tacked onto the end of the list
644: *-----------------------------------------------------------------------
645: */
1.27 espie 646: static void
1.51 espie 647: SuffAddSrc(
1.70 espie 648: void *sp, /* suffix for which to create a Src structure */
649: void *lsp) /* list and parent for the new Src */
1.1 deraadt 650: {
1.89 espie 651: Suff *s = sp;
652: LstSrc *ls = lsp;
1.70 espie 653: Src *s2; /* new Src structure */
654: Src *targ; /* Target structure */
1.1 deraadt 655:
1.66 espie 656: targ = ls->s;
1.5 millert 657:
1.41 espie 658: s2 = emalloc(sizeof(Src));
1.84 espie 659: s2->file = Str_concat(targ->prefix, s->name, 0);
660: s2->prefix = targ->prefix;
1.70 espie 661: s2->parent = targ;
662: s2->node = NULL;
663: s2->suff = s;
664: s2->children = 0;
1.65 espie 665: targ->children++;
1.25 espie 666: Lst_AtEnd(ls->l, s2);
1.1 deraadt 667: #ifdef DEBUG_SRC
1.70 espie 668: Lst_Init(&s2->cp);
1.29 espie 669: Lst_AtEnd(&targ->cp, s2);
1.66 espie 670: printf("2 add %x %x to %x:", targ, s2, ls->l);
1.27 espie 671: Lst_Every(ls->l, PrintAddr);
1.1 deraadt 672: printf("\n");
673: #endif
1.41 espie 674:
1.1 deraadt 675: }
676:
677: /*-
678: *-----------------------------------------------------------------------
679: * SuffAddLevel --
680: * Add all the children of targ as Src structures to the given list
681: *
682: * Side Effects:
1.41 espie 683: * Lots of structures are created and added to the list
1.1 deraadt 684: *-----------------------------------------------------------------------
685: */
686: static void
1.51 espie 687: SuffAddLevel(
1.70 espie 688: Lst l, /* list to which to add the new level */
689: Src *targ) /* Src structure to use as the parent */
1.1 deraadt 690: {
1.66 espie 691: LstSrc ls;
1.1 deraadt 692:
1.66 espie 693: ls.s = targ;
694: ls.l = l;
1.1 deraadt 695:
1.66 espie 696: Lst_ForEach(&targ->suff->children, SuffAddSrc, &ls);
1.1 deraadt 697: }
698:
699: /*-
700: *----------------------------------------------------------------------
701: * SuffRemoveSrc --
1.95 espie 702: * Free Src structure with a zero reference count in a list
1.1 deraadt 703: *
1.95 espie 704: * returns true if a src was removed
1.1 deraadt 705: *----------------------------------------------------------------------
706: */
1.95 espie 707: static bool
1.51 espie 708: SuffRemoveSrc(Lst l)
1.1 deraadt 709: {
1.66 espie 710: LstNode ln;
711: Src *s;
1.1 deraadt 712:
713: #ifdef DEBUG_SRC
1.66 espie 714: printf("cleaning %lx: ", (unsigned long)l);
715: Lst_Every(l, PrintAddr);
716: printf("\n");
1.1 deraadt 717: #endif
718:
719:
1.66 espie 720: for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
1.91 espie 721: s = Lst_Datum(ln);
1.66 espie 722: if (s->children == 0) {
723: free(s->file);
724: if (!s->parent)
1.84 espie 725: free(s->prefix);
1.66 espie 726: else {
1.1 deraadt 727: #ifdef DEBUG_SRC
1.66 espie 728: LstNode ln2 = Lst_Member(&s->parent->cp, s);
729: if (ln2 != NULL)
730: Lst_Remove(&s->parent->cp, ln2);
1.1 deraadt 731: #endif
1.66 espie 732: --s->parent->children;
733: }
1.1 deraadt 734: #ifdef DEBUG_SRC
1.66 espie 735: printf("free: [l=%x] p=%x %d\n", l, s, s->children);
736: Lst_Destroy(&s->cp, NOFREE);
1.1 deraadt 737: #endif
1.66 espie 738: Lst_Remove(l, ln);
739: free(s);
740: return true;
741: }
1.1 deraadt 742: #ifdef DEBUG_SRC
1.66 espie 743: else {
744: printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
745: Lst_Every(&s->cp, PrintAddr);
746: printf("\n");
747: }
748: #endif
1.1 deraadt 749: }
750:
1.95 espie 751: return false;
1.1 deraadt 752: }
753:
754: /*-
755: *-----------------------------------------------------------------------
756: * SuffFindThem --
757: * Find the first existing file/target in the list srcs
758: *
759: * Results:
760: * The lowest structure in the chain of transformations
761: *-----------------------------------------------------------------------
762: */
763: static Src *
1.51 espie 764: SuffFindThem(
1.70 espie 765: Lst srcs, /* list of Src structures to search through */
766: Lst slst)
1.1 deraadt 767: {
1.70 espie 768: Src *s; /* current Src */
769: Src *rs; /* returned Src */
770: char *ptr;
1.66 espie 771:
772: rs = NULL;
773:
1.91 espie 774: while ((s = Lst_DeQueue(srcs)) != NULL) {
1.70 espie 775: if (DEBUG(SUFF))
1.66 espie 776: printf("\ttrying %s...", s->file);
1.1 deraadt 777:
1.66 espie 778: /*
779: * A file is considered to exist if either a node exists in the
780: * graph for it or the file actually exists.
781: */
782: if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
1.1 deraadt 783: #ifdef DEBUG_SRC
1.66 espie 784: printf("remove %x from %x\n", s, srcs);
1.1 deraadt 785: #endif
1.66 espie 786: rs = s;
787: break;
788: }
1.1 deraadt 789:
1.67 espie 790: if ((ptr = Dir_FindFile(s->file, &s->suff->searchPath))
1.66 espie 791: != NULL) {
792: rs = s;
1.1 deraadt 793: #ifdef DEBUG_SRC
1.66 espie 794: printf("remove %x from %x\n", s, srcs);
1.1 deraadt 795: #endif
1.66 espie 796: free(ptr);
797: break;
798: }
799:
1.70 espie 800: if (DEBUG(SUFF))
801: printf("not there\n");
1.66 espie 802:
803: SuffAddLevel(srcs, s);
804: Lst_AtEnd(slst, s);
1.1 deraadt 805: }
806:
1.70 espie 807: if (DEBUG(SUFF) && rs)
808: printf("got it\n");
1.66 espie 809: return rs;
1.1 deraadt 810: }
811:
812: /*-
813: *-----------------------------------------------------------------------
814: * SuffFindCmds --
815: * See if any of the children of the target in the Src structure is
816: * one from which the target can be transformed. If there is one,
817: * a Src structure is put together for it and returned.
818: *-----------------------------------------------------------------------
819: */
820: static Src *
1.84 espie 821: SuffFindCmds(Src *targ, Lst slst)
1.41 espie 822: {
1.70 espie 823: LstNode ln; /* General-purpose list node */
824: GNode *t; /* Target GNode */
825: GNode *s; /* Source GNode */
1.84 espie 826: int prefixLen; /* The length of the defined prefix */
1.70 espie 827: Suff *suff; /* Suffix on matching beastie */
828: Src *ret; /* Return value */
829: const char *cp;
1.66 espie 830:
831: t = targ->node;
1.84 espie 832: prefixLen = strlen(targ->prefix);
1.66 espie 833:
834: for (ln = Lst_First(&t->children); ln != NULL; ln = Lst_Adv(ln)) {
1.91 espie 835: s = Lst_Datum(ln);
1.66 espie 836:
837: cp = strrchr(s->name, '/');
1.84 espie 838: if (cp == NULL)
1.66 espie 839: cp = s->name;
1.84 espie 840: else
1.66 espie 841: cp++;
1.84 espie 842: if (strncmp(cp, targ->prefix, prefixLen) != 0)
843: continue;
844: /* The node matches the prefix ok, see if it has a known
845: * suffix. */
846: suff = find_suff(&cp[prefixLen]);
847: if (suff == NULL)
848: continue;
849: /*
850: * It even has a known suffix, see if there's a transformation
851: * defined between the node's suffix and the target's suffix.
852: *
853: * XXX: Handle multi-stage transformations here, too.
854: */
855: if (Lst_Member(&suff->parents, targ->suff) == NULL)
856: continue;
857: /*
858: * Create a new Src structure to describe this transformation
859: * (making sure to duplicate the source node's name so
860: * Suff_FindDeps can free it again (ick)), and return the new
861: * structure.
862: */
863: ret = emalloc(sizeof(Src));
864: ret->file = estrdup(s->name);
865: ret->prefix = targ->prefix;
866: ret->suff = suff;
867: ret->parent = targ;
868: ret->node = s;
869: ret->children = 0;
870: targ->children++;
1.1 deraadt 871: #ifdef DEBUG_SRC
1.84 espie 872: Lst_Init(&ret->cp);
873: printf("3 add %x %x\n", targ, ret);
874: Lst_AtEnd(&targ->cp, ret);
1.66 espie 875: #endif
1.84 espie 876: Lst_AtEnd(slst, ret);
877: if (DEBUG(SUFF))
878: printf("\tusing existing source %s\n", s->name);
879: return ret;
1.1 deraadt 880: }
1.66 espie 881: return NULL;
1.41 espie 882: }
883:
1.1 deraadt 884: /*-
885: *-----------------------------------------------------------------------
886: * SuffApplyTransform --
887: * Apply a transformation rule, given the source and target nodes
888: * and suffixes.
889: *
890: * Results:
1.42 espie 891: * true if successful, false if not.
1.1 deraadt 892: *
893: * Side Effects:
894: * The source and target are linked and the commands from the
895: * transformation are added to the target node's commands list.
896: * All attributes but OP_DEPMASK and OP_TRANSFORM are applied
897: * to the target. The target also inherits all the sources for
898: * the transformation rule.
899: *-----------------------------------------------------------------------
900: */
1.42 espie 901: static bool
1.51 espie 902: SuffApplyTransform(
903: GNode *tGn, /* Target node */
904: GNode *sGn, /* Source node */
905: Suff *t, /* Target suffix */
906: Suff *s) /* Source suffix */
1.1 deraadt 907: {
1.66 espie 908: LstNode ln; /* General node */
909: char *tname; /* Name of transformation rule */
910: GNode *gn; /* Node for same */
1.1 deraadt 911:
1.66 espie 912: if (Lst_AddNew(&tGn->children, sGn)) {
1.41 espie 913: /* Not already linked, so form the proper links between the
914: * target and source. */
1.100 espie 915: LinkParent(sGn, tGn);
1.1 deraadt 916: }
917:
1.66 espie 918: if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
919: /* When a :: node is used as the implied source of a node, we
1.74 espie 920: * have to link all its cohorts in as sources as well. There's
1.78 espie 921: * only one implied src, as that will be sufficient to get
1.74 espie 922: * the .IMPSRC variable set for tGn. */
1.66 espie 923: for (ln=Lst_First(&sGn->cohorts); ln != NULL; ln=Lst_Adv(ln)) {
1.91 espie 924: gn = Lst_Datum(ln);
1.66 espie 925:
926: if (Lst_AddNew(&tGn->children, gn)) {
927: /* Not already linked, so form the proper links
928: * between the target and source. */
1.100 espie 929: LinkParent(gn, tGn);
1.66 espie 930: }
931: }
932: }
933: /* Locate the transformation rule itself. */
934: tname = Str_concat(s->name, t->name, 0);
1.70 espie 935: gn = find_transform(tname);
1.66 espie 936: free(tname);
937:
1.70 espie 938: if (gn == NULL)
1.66 espie 939: /*
940: * Not really such a transformation rule (can happen when we're
941: * called to link an OP_MEMBER and OP_ARCHV node), so return
942: * false.
943: */
944: return false;
1.1 deraadt 945:
1.66 espie 946: if (DEBUG(SUFF))
1.67 espie 947: printf("\tapplying %s -> %s to \"%s\"\n", s->name, t->name,
1.66 espie 948: tGn->name);
1.1 deraadt 949:
1.66 espie 950: /* Record last child for expansion purposes. */
951: ln = Lst_Last(&tGn->children);
1.5 millert 952:
1.66 espie 953: /* Pass the buck to Make_HandleUse to apply the rule. */
954: Make_HandleUse(gn, tGn);
1.1 deraadt 955:
1.66 espie 956: /* Deal with wildcards and variables in any acquired sources. */
1.77 espie 957: expand_children_from(tGn, Lst_Succ(ln));
1.1 deraadt 958:
1.66 espie 959: /* Keep track of another parent to which this beast is transformed so
960: * the .IMPSRC variable can be set correctly for the parent. */
1.74 espie 961: tGn->impliedsrc = sGn;
1.1 deraadt 962:
1.66 espie 963: return true;
1.1 deraadt 964: }
965:
1.70 espie 966: static Suff *
967: find_suffix_as_suffix(Lst l, const char *b, const char *e)
968: {
969: LstNode ln;
970: Suff *s;
971:
972: for (ln = Lst_First(l); ln != NULL; ln = Lst_Adv(ln)) {
1.91 espie 973: s = Lst_Datum(ln);
1.70 espie 974: if (suffix_is_suffix(s, b, e))
975: return s;
976: }
977: return NULL;
978: }
1.1 deraadt 979:
980: /*-
981: *-----------------------------------------------------------------------
982: * SuffFindArchiveDeps --
983: * Locate dependencies for an OP_ARCHV node.
984: *
985: * Side Effects:
986: * Same as Suff_FindDeps
987: *-----------------------------------------------------------------------
988: */
989: static void
1.51 espie 990: SuffFindArchiveDeps(
1.70 espie 991: GNode *gn, /* Node for which to locate dependencies */
1.51 espie 992: Lst slst)
1.1 deraadt 993: {
1.70 espie 994: char *eoarch; /* End of archive portion */
995: char *eoname; /* End of member portion */
996: GNode *mem; /* Node for member */
997: Suff *ms; /* Suffix descriptor for member */
998: char *name; /* Start of member's name */
1.66 espie 999:
1000: /* The node is an archive(member) pair. so we must find a suffix
1001: * for both of them. */
1002: eoarch = strchr(gn->name, '(');
1003: if (eoarch == NULL)
1004: return;
1005:
1006: name = eoarch + 1;
1007:
1008: eoname = strchr(name, ')');
1009: if (eoname == NULL)
1010: return;
1011:
1012: /* To simplify things, call Suff_FindDeps recursively on the member now,
1013: * so we can simply compare the member's .PREFIX and .TARGET variables
1014: * to locate its suffix. This allows us to figure out the suffix to
1015: * use for the archive without having to do a quadratic search over the
1016: * suffix list, backtracking for each one... */
1017: mem = Targ_FindNodei(name, eoname, TARG_CREATE);
1018: SuffFindDeps(mem, slst);
1019:
1020: /* Create the link between the two nodes right off. */
1.80 guenther 1021: if (Lst_AddNew(&gn->children, mem))
1.100 espie 1022: LinkParent(mem, gn);
1.66 espie 1023:
1024: /* Copy variables from member node to this one. */
1.76 espie 1025: Var(TARGET_INDEX, gn) = Var(TARGET_INDEX, mem);
1026: Var(PREFIX_INDEX, gn) = Var(PREFIX_INDEX, mem);
1.66 espie 1027:
1028: ms = mem->suffix;
1029: if (ms == NULL) {
1030: /* Didn't know what it was -- use .NULL suffix if not in make
1031: * mode. */
1032: if (DEBUG(SUFF))
1.81 espie 1033: printf("using empty suffix\n");
1034: ms = emptySuff;
1.66 espie 1035: }
1.5 millert 1036:
1.1 deraadt 1037:
1.66 espie 1038: /* Set the other two local variables required for this target. */
1.76 espie 1039: Var(MEMBER_INDEX, gn) = mem->name;
1040: Var(ARCHIVE_INDEX, gn) = gn->name;
1.1 deraadt 1041:
1.66 espie 1042: if (ms != NULL) {
1043: /*
1044: * Member has a known suffix, so look for a transformation rule
1045: * from it to a possible suffix of the archive. Rather than
1046: * searching through the entire list, we just look at suffixes
1047: * to which the member's suffix may be transformed...
1048: */
1.1 deraadt 1049:
1.70 espie 1050: Suff *suff;
1.1 deraadt 1051:
1.70 espie 1052: suff = find_suffix_as_suffix(&ms->parents, gn->name, eoarch);
1053:
1054: if (suff != NULL) {
1.66 espie 1055: /* Got one -- apply it. */
1.70 espie 1056: if (!SuffApplyTransform(gn, mem, suff, ms) &&
1057: DEBUG(SUFF))
1.66 espie 1058: printf("\tNo transformation from %s -> %s\n",
1.70 espie 1059: ms->name, suff->name);
1.66 espie 1060: }
1.1 deraadt 1061: }
1062:
1.66 espie 1063: /* Pretend gn appeared to the left of a dependency operator so
1064: * the user needn't provide a transformation from the member to the
1065: * archive. */
1066: if (OP_NOP(gn->type))
1067: gn->type |= OP_DEPENDS;
1068:
1069: /* Flag the member as such so we remember to look in the archive for
1070: * its modification time. */
1071: mem->type |= OP_MEMBER;
1.1 deraadt 1072: }
1073:
1.70 espie 1074: static void
1075: record_possible_suffix(Suff *s, GNode *gn, char *eoname, Lst srcs, Lst targs)
1076: {
1.84 espie 1077: int prefixLen;
1.70 espie 1078: Src *targ;
1079:
1080: targ = emalloc(sizeof(Src));
1081: targ->file = estrdup(gn->name);
1082: targ->suff = s;
1083: targ->node = gn;
1084: targ->parent = NULL;
1085: targ->children = 0;
1086: #ifdef DEBUG_SRC
1087: Lst_Init(&targ->cp);
1088: #endif
1089:
1090: /* Allocate room for the prefix, whose end is found by
1091: * subtracting the length of the suffix from the end of
1092: * the name. */
1.84 espie 1093: prefixLen = (eoname - targ->suff->nameLen) - gn->name;
1094: targ->prefix = emalloc(prefixLen + 1);
1095: memcpy(targ->prefix, gn->name, prefixLen);
1096: targ->prefix[prefixLen] = '\0';
1.70 espie 1097:
1098: /* Add nodes from which the target can be made. */
1099: SuffAddLevel(srcs, targ);
1100:
1101: /* Record the target so we can nuke it. */
1102: Lst_AtEnd(targs, targ);
1103: }
1104:
1105: static void
1106: record_possible_suffixes(GNode *gn, Lst srcs, Lst targs)
1107: {
1108: char *s = gn->name;
1109: char *e = s + strlen(s);
1110: const char *p;
1111: uint32_t hv;
1112: unsigned int slot;
1113: Suff *suff;
1114:
1115: if (e == s)
1116: return;
1117:
1118: p = e;
1119: hv = *--p;
1120:
1121: while (p != s) {
1122: slot = ohash_lookup_interval(&suffixes, p, e, hv);
1123: suff = ohash_find(&suffixes, slot);
1.72 espie 1124: if (suff != NULL && (suff->flags & SUFF_ACTIVE))
1.70 espie 1125: record_possible_suffix(suff, gn, e, srcs, targs);
1126: if (e - p >= (ptrdiff_t)maxLen)
1127: break;
1128: reverse_hash_add_char(&hv, --p);
1129: }
1130: }
1131:
1.1 deraadt 1132: /*-
1133: *-----------------------------------------------------------------------
1134: * SuffFindNormalDeps --
1135: * Locate implicit dependencies for regular targets.
1136: *
1137: * Side Effects:
1138: * Same as Suff_FindDeps...
1139: *-----------------------------------------------------------------------
1140: */
1141: static void
1.51 espie 1142: SuffFindNormalDeps(
1143: GNode *gn, /* Node for which to find sources */
1144: Lst slst)
1.1 deraadt 1145: {
1.70 espie 1146: LIST srcs; /* List of sources at which to look */
1147: LIST targs; /* List of targets to which things can be
1148: * transformed. They all have the same file,
1.84 espie 1149: * but different suff and prefix fields */
1.70 espie 1150: Src *bottom; /* Start of found transformation path */
1151: Src *src; /* General Src pointer */
1.84 espie 1152: char *prefix; /* Prefix to use */
1.70 espie 1153: Src *targ; /* General Src target pointer */
1.66 espie 1154:
1155:
1156: Lst_Init(&srcs);
1157: Lst_Init(&targs);
1158:
1159: /* We're caught in a catch-22 here. On the one hand, we want to use any
1160: * transformation implied by the target's sources, but we can't examine
1161: * the sources until we've expanded any variables/wildcards they may
1162: * hold, and we can't do that until we've set up the target's local
1163: * variables and we can't do that until we know what the proper suffix
1164: * for the target is (in case there are two suffixes one of which is a
1165: * suffix of the other) and we can't know that until we've found its
1166: * implied source, which we may not want to use if there's an existing
1167: * source that implies a different transformation.
1168: *
1169: * In an attempt to get around this, which may not work all the time,
1170: * but should work most of the time, we look for implied sources first,
1171: * checking transformations to all possible suffixes of the target, use
1172: * what we find to set the target's local variables, expand the
1173: * children, then look for any overriding transformations they imply.
1174: * Should we find one, we discard the one we found before. */
1175:
1.1 deraadt 1176:
1.94 espie 1177: record_possible_suffixes(gn, &srcs, &targs);
1.66 espie 1178: /* Handle target of unknown suffix... */
1.94 espie 1179: if (Lst_IsEmpty(&srcs)) {
1.70 espie 1180: if (DEBUG(SUFF))
1.81 espie 1181: printf("\tNo known suffix on %s. Using empty suffix\n",
1.66 espie 1182: gn->name);
1.5 millert 1183:
1.66 espie 1184: targ = emalloc(sizeof(Src));
1185: targ->file = estrdup(gn->name);
1.81 espie 1186: targ->suff = emptySuff;
1.66 espie 1187: targ->node = gn;
1188: targ->parent = NULL;
1189: targ->children = 0;
1.84 espie 1190: targ->prefix = estrdup(gn->name);
1.1 deraadt 1191: #ifdef DEBUG_SRC
1.66 espie 1192: Lst_Init(&targ->cp);
1.1 deraadt 1193: #endif
1194:
1.66 espie 1195: /* Only use the default suffix rules if we don't have commands
1196: * or dependencies defined for this gnode. */
1.94 espie 1197: if (Lst_IsEmpty(&gn->commands) && Lst_IsEmpty(&gn->children))
1.66 espie 1198: SuffAddLevel(&srcs, targ);
1199: else {
1200: if (DEBUG(SUFF))
1201: printf("not ");
1202: }
1.1 deraadt 1203:
1.66 espie 1204: if (DEBUG(SUFF))
1205: printf("adding suffix rules\n");
1.1 deraadt 1206:
1.66 espie 1207: Lst_AtEnd(&targs, targ);
1208: }
1.5 millert 1209:
1.66 espie 1210: /* Using the list of possible sources built up from the target
1211: * suffix(es), try and find an existing file/target that matches. */
1212: bottom = SuffFindThem(&srcs, slst);
1213:
1214: if (bottom == NULL) {
1215: /* No known transformations -- use the first suffix found for
1216: * setting the local variables. */
1217: if (!Lst_IsEmpty(&targs))
1.91 espie 1218: targ = Lst_Datum(Lst_First(&targs));
1.66 espie 1219: else
1220: targ = NULL;
1221: } else {
1222: /* Work up the transformation path to find the suffix of the
1223: * target to which the transformation was made. */
1224: for (targ = bottom; targ->parent != NULL; targ = targ->parent)
1225: continue;
1226: }
1227:
1228: /* The .TARGET variable we always set to be the name at this point,
1229: * since it's only set to the path if the thing is only a source and
1230: * if it's only a source, it doesn't matter what we put here as far
1231: * as expanding sources is concerned, since it has none... */
1.76 espie 1232: Var(TARGET_INDEX, gn) = gn->name;
1.66 espie 1233:
1.84 espie 1234: prefix = targ != NULL ? estrdup(targ->prefix) : gn->name;
1235: Var(PREFIX_INDEX, gn) = prefix;
1.66 espie 1236:
1237: /* Now we've got the important local variables set, expand any sources
1238: * that still contain variables or wildcards in their names. */
1.77 espie 1239: expand_all_children(gn);
1.66 espie 1240:
1241: if (targ == NULL) {
1242: if (DEBUG(SUFF))
1243: printf("\tNo valid suffix on %s\n", gn->name);
1.1 deraadt 1244:
1245: sfnd_abort:
1.70 espie 1246: /* Deal with finding the thing on the default search path if the
1247: * node is only a source (not on the lhs of a dependency operator
1248: * or [XXX] it has neither children or commands). */
1.66 espie 1249: if (OP_NOP(gn->type) ||
1.67 espie 1250: (Lst_IsEmpty(&gn->children) &&
1.66 espie 1251: Lst_IsEmpty(&gn->commands))) {
1252: gn->path = Dir_FindFile(gn->name,
1253: (targ == NULL ? defaultPath :
1254: &targ->suff->searchPath));
1255: if (gn->path != NULL) {
1256: char *ptr;
1.76 espie 1257: Var(TARGET_INDEX, gn) = estrdup(gn->path);
1.66 espie 1258:
1259: if (targ != NULL) {
1260: /* Suffix known for the thing -- trim
1261: * the suffix off the path to form the
1262: * proper .PREFIX variable. */
1.67 espie 1263: int savep = strlen(gn->path) -
1.66 espie 1264: targ->suff->nameLen;
1265: char savec;
1266:
1267: gn->suffix = targ->suff;
1268:
1269: savec = gn->path[savep];
1270: gn->path[savep] = '\0';
1271:
1.70 espie 1272: if ((ptr = strrchr(gn->path, '/')) !=
1273: NULL)
1.66 espie 1274: ptr++;
1275: else
1276: ptr = gn->path;
1277:
1.76 espie 1278: Var(PREFIX_INDEX, gn) = estrdup(ptr);
1.66 espie 1279:
1280: gn->path[savep] = savec;
1281: } else {
1.70 espie 1282: /* The .PREFIX gets the full path if the
1283: * target has no known suffix. */
1.66 espie 1284: gn->suffix = NULL;
1285:
1.70 espie 1286: if ((ptr = strrchr(gn->path, '/')) !=
1287: NULL)
1.66 espie 1288: ptr++;
1289: else
1290: ptr = gn->path;
1291:
1.76 espie 1292: Var(PREFIX_INDEX, gn) = estrdup(ptr);
1.66 espie 1293: }
1294: }
1295: } else {
1296: /* Not appropriate to search for the thing -- set the
1297: * path to be the name so Dir_MTime won't go grovelling
1298: * for it. */
1299: gn->suffix = targ == NULL ? NULL : targ->suff;
1.92 espie 1300: free(gn->path);
1.66 espie 1301: gn->path = estrdup(gn->name);
1302: }
1.1 deraadt 1303:
1.66 espie 1304: goto sfnd_return;
1305: }
1.2 deraadt 1306:
1.66 espie 1307: /* Check for overriding transformation rule implied by sources. */
1308: if (!Lst_IsEmpty(&gn->children)) {
1309: src = SuffFindCmds(targ, slst);
1310:
1311: if (src != NULL) {
1312: /* Free up all the Src structures in the transformation
1313: * path up to, but not including, the parent node. */
1314: while (bottom && bottom->parent != NULL) {
1315: (void)Lst_AddNew(slst, bottom);
1316: bottom = bottom->parent;
1317: }
1318: bottom = src;
1.1 deraadt 1319: }
1320: }
1.5 millert 1321:
1.66 espie 1322: if (bottom == NULL) {
1323: /* No idea from where it can come -- return now. */
1324: goto sfnd_abort;
1325: }
1326:
1327: /* We now have a list of Src structures headed by 'bottom' and linked
1328: * via their 'parent' pointers. What we do next is create links between
1329: * source and target nodes (which may or may not have been created) and
1330: * set the necessary local variables in each target. The commands for
1331: * each target are set from the commands of the transformation rule
1332: * used to get from the src suffix to the targ suffix. Note that this
1333: * causes the commands list of the original node, gn, to be replaced by
1.97 espie 1334: * the commands of the final transformation rule. Also, the children
1335: * to build field of gn is incremented. Etc. */
1.66 espie 1336: if (bottom->node == NULL) {
1337: bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
1.1 deraadt 1338: }
1339:
1.66 espie 1340: for (src = bottom; src->parent != NULL; src = src->parent) {
1341: targ = src->parent;
1.1 deraadt 1342:
1.66 espie 1343: src->node->suffix = src->suff;
1.5 millert 1344:
1.66 espie 1345: if (targ->node == NULL) {
1346: targ->node = Targ_FindNode(targ->file, TARG_CREATE);
1347: }
1.1 deraadt 1348:
1.70 espie 1349: SuffApplyTransform(targ->node, src->node,
1350: targ->suff, src->suff);
1.1 deraadt 1351:
1.66 espie 1352: if (targ->node != gn) {
1353: /* Finish off the dependency-search process for any
1354: * nodes between bottom and gn (no point in questing
1355: * around the filesystem for their implicit source when
1356: * it's already known). Note that the node can't have
1357: * any sources that need expanding, since SuffFindThem
1358: * will stop on an existing node, so all we need to do
1359: * is set the standard and System V variables. */
1360: targ->node->type |= OP_DEPS_FOUND;
1.1 deraadt 1361:
1.84 espie 1362: Var(PREFIX_INDEX, targ->node) = estrdup(targ->prefix);
1.1 deraadt 1363:
1.76 espie 1364: Var(TARGET_INDEX, targ->node) = targ->node->name;
1.66 espie 1365: }
1.1 deraadt 1366: }
1367:
1.66 espie 1368: gn->suffix = src->suff;
1.1 deraadt 1369:
1.66 espie 1370: /* So Dir_MTime doesn't go questing for it... */
1.92 espie 1371: free(gn->path);
1.66 espie 1372: gn->path = estrdup(gn->name);
1.1 deraadt 1373:
1.66 espie 1374: /* Nuke the transformation path and the Src structures left over in the
1375: * two lists. */
1.1 deraadt 1376: sfnd_return:
1.66 espie 1377: if (bottom)
1378: (void)Lst_AddNew(slst, bottom);
1.1 deraadt 1379:
1.66 espie 1380: while (SuffRemoveSrc(&srcs) || SuffRemoveSrc(&targs))
1381: continue;
1.1 deraadt 1382:
1.66 espie 1383: Lst_ConcatDestroy(slst, &srcs);
1384: Lst_ConcatDestroy(slst, &targs);
1.1 deraadt 1385: }
1.5 millert 1386:
1387:
1.1 deraadt 1388: /*-
1389: *-----------------------------------------------------------------------
1390: * Suff_FindDeps --
1391: * Find implicit sources for the target described by the graph node
1392: * gn
1393: *
1394: * Side Effects:
1395: * Nodes are added to the graph below the passed-in node. The nodes
1396: * are marked to have their IMPSRC variable filled in. The
1397: * PREFIX variable is set for the given node and all its
1398: * implied children.
1399: *
1400: * Notes:
1401: * The path found by this target is the shortest path in the
1402: * transformation graph, which may pass through non-existent targets,
1403: * to an existing target. The search continues on all paths from the
1404: * root suffix until a file is found. I.e. if there's a path
1405: * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
1406: * the .c and .l files don't, the search will branch out in
1407: * all directions from .o and again from all the nodes on the
1408: * next level until the .l,v node is encountered.
1409: *-----------------------------------------------------------------------
1410: */
1411:
1412: void
1.51 espie 1413: Suff_FindDeps(GNode *gn)
1.1 deraadt 1414: {
1.5 millert 1415:
1.66 espie 1416: SuffFindDeps(gn, &srclist);
1417: while (SuffRemoveSrc(&srclist))
1418: continue;
1.1 deraadt 1419: }
1420:
1421:
1422: static void
1.51 espie 1423: SuffFindDeps(GNode *gn, Lst slst)
1.1 deraadt 1424: {
1.66 espie 1425: if (gn->type & OP_DEPS_FOUND) {
1426: /*
1427: * If dependencies already found, no need to do it again...
1428: */
1429: return;
1430: } else {
1431: gn->type |= OP_DEPS_FOUND;
1432: }
1.5 millert 1433:
1.70 espie 1434: if (DEBUG(SUFF))
1.66 espie 1435: printf("SuffFindDeps (%s)\n", gn->name);
1.5 millert 1436:
1.87 espie 1437: current_node = gn;
1.81 espie 1438: if (gn->type & OP_ARCHV)
1.66 espie 1439: SuffFindArchiveDeps(gn, slst);
1.81 espie 1440: else
1.66 espie 1441: SuffFindNormalDeps(gn, slst);
1.87 espie 1442: current_node = NULL;
1.1 deraadt 1443: }
1444:
1445: /*-
1446: *-----------------------------------------------------------------------
1447: * Suff_Init --
1448: * Initialize suffixes module
1449: *
1450: * Side Effects:
1451: * Many
1452: *-----------------------------------------------------------------------
1453: */
1454: void
1.51 espie 1455: Suff_Init(void)
1.1 deraadt 1456: {
1.66 espie 1457: Static_Lst_Init(&srclist);
1.70 espie 1458: ohash_init(&transforms, 4, &gnode_info);
1.66 espie 1459:
1.99 espie 1460: /* Create null suffix for single-suffix rules (POSIX). The thing doesn't
1461: * actually go on the suffix list as it matches everything. */
1.70 espie 1462: emptySuff = new_suffix("");
1.99 espie 1463: emptySuff->flags = SUFF_ACTIVE;
1464: emptySuff->order = 0;
1.70 espie 1465: Dir_Concat(&emptySuff->searchPath, defaultPath);
1466: ohash_init(&suffixes, 4, &suff_info);
1467: special_path_hack();
1.1 deraadt 1468: }
1469:
1470:
1471: /********************* DEBUGGING FUNCTIONS **********************/
1472:
1.70 espie 1473: static void
1.81 espie 1474: SuffPrintName(void *p)
1.1 deraadt 1475: {
1.90 espie 1476: const Suff *s = p;
1.81 espie 1477: printf("%s ", s == emptySuff ? "<empty>" : s->name);
1.1 deraadt 1478: }
1479:
1.27 espie 1480: static void
1.51 espie 1481: SuffPrintSuff(void *sp)
1.1 deraadt 1482: {
1.89 espie 1483: Suff *s = sp;
1.66 espie 1484:
1.81 espie 1485: printf("# %-5s ", s->name);
1.66 espie 1486:
1.81 espie 1487: if (!Lst_IsEmpty(&s->parents)) {
1488: printf(" ->");
1489: Lst_Every(&s->parents, SuffPrintName);
1490: }
1491: if (!Lst_IsEmpty(&s->children)) {
1492: printf(" <-");
1493: Lst_Every(&s->children, SuffPrintName);
1.1 deraadt 1494: }
1.66 espie 1495: fputc('\n', stdout);
1.1 deraadt 1496: }
1497:
1.27 espie 1498: static void
1.70 espie 1499: SuffPrintTrans(GNode *t)
1.1 deraadt 1500: {
1.66 espie 1501: printf("%-16s: ", t->name);
1502: Targ_PrintType(t->type);
1503: fputc('\n', stdout);
1504: Lst_Every(&t->commands, Targ_PrintCmd);
1505: fputc('\n', stdout);
1.1 deraadt 1506: }
1507:
1.81 espie 1508: static int
1509: compare_order(const void *a, const void *b)
1510: {
1511: const Suff **pa = (const Suff **)a;
1512: const Suff **pb = (const Suff **)b;
1513: return (*pb)->order - (*pa)->order;
1514: }
1515:
1516: static void
1517: print_path(Suff *s)
1518: {
1519: /* do we need to print it ? compare against defaultPath */
1520: LstNode ln1, ln2;
1521: bool first = true;
1522:
1523: for (ln1 = Lst_First(&s->searchPath), ln2 = Lst_First(defaultPath);
1524: ln1 != NULL && ln2 != NULL;
1525: ln1 = Lst_Adv(ln1)) {
1526: if (Lst_Datum(ln1) == Lst_Datum(ln2)) {
1527: ln2 = Lst_Adv(ln2);
1528: continue;
1529: }
1530: if (first) {
1531: printf(".PATH%s:", s->name);
1532: first = false;
1533: }
1534: printf(" %s", PathEntry_name(Lst_Datum(ln1)));
1535: }
1536: if (!first)
1537: printf("\n\n");
1538: }
1539:
1.1 deraadt 1540: void
1.51 espie 1541: Suff_PrintAll(void)
1.1 deraadt 1542: {
1.81 espie 1543: Suff **t;
1544: GNode **u;
1.70 espie 1545: unsigned int i;
1.81 espie 1546: bool reprint;
1.70 espie 1547:
1548:
1.81 espie 1549: printf("# Suffixes graph\n");
1550: t = sort_ohash_by_name(&suffixes);
1551: for (i = 0; t[i] != NULL; i++)
1552: if (!(t[i]->flags & SUFF_PATH))
1553: SuffPrintSuff(t[i]);
1554:
1555: printf("\n.PATH: ");
1556: Dir_PrintPath(defaultPath);
1557: printf("\n\n");
1558: for (i = 0; t[i] != NULL; i++)
1559: if (!(t[i]->flags & SUFF_PATH))
1560: print_path(t[i]);
1561: free(t);
1562:
1563: reprint = false;
1564: t = sort_ohash(&suffixes, compare_order);
1565: printf(".SUFFIXES:");
1566: for (i = 0; t[i] != NULL; i++) {
1567: if (t[i]->flags & SUFF_PATH)
1568: continue;
1569: printf(" %s", t[i]->name);
1570: if (!(t[i]->flags & SUFF_ACTIVE))
1571: reprint = true;
1572: }
1573: printf("\n\n");
1574: u = sort_ohash_by_name(&transforms);
1575: for (i = 0; u[i] != NULL; i++)
1576: SuffPrintTrans(u[i]);
1577: free(u);
1578:
1579: if (reprint) {
1580: printf(".SUFFIXES:");
1581: for (i = 0; t[i] != NULL; i++)
1582: if (t[i]->flags & SUFF_ACTIVE)
1583: printf(" %s", t[i]->name);
1584: printf("\n");
1585: }
1586: free(t);
1.1 deraadt 1587: }
1.42 espie 1588:
1589: #ifdef DEBUG_SRC
1590: static void
1.51 espie 1591: PrintAddr(void *a)
1.42 espie 1592: {
1.66 espie 1593: printf("%lx ", (unsigned long)a);
1.42 espie 1594: }
1595: #endif