xref: /openbsd/usr.bin/make/suff.c (revision c9fc29cf)
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