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