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