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