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