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