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