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