Deleted Added
full compact
suff.c (103508) suff.c (103545)
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)suff.c 8.4 (Berkeley) 3/21/94
39 */
40
41#include <sys/cdefs.h>
1/*
2 * Copyright (c) 1988, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (c) 1989 by Berkeley Softworks
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)suff.c 8.4 (Berkeley) 3/21/94
39 */
40
41#include <sys/cdefs.h>
42__FBSDID("$FreeBSD: head/usr.bin/make/suff.c 103508 2002-09-17 22:31:26Z jmallett $");
42__FBSDID("$FreeBSD: head/usr.bin/make/suff.c 103545 2002-09-18 16:13:03Z jmallett $");
43
44/*-
45 * suff.c --
46 * Functions to maintain suffix lists and find implicit dependents
47 * using suffix transformation rules
48 *
49 * Interface:
50 * Suff_Init Initialize all things to do with suffixes.
51 *
52 * Suff_End Cleanup the module
53 *
54 * Suff_DoPaths This function is used to make life easier
55 * when searching for a file according to its
56 * suffix. It takes the global search path,
57 * as defined using the .PATH: target, and appends
58 * its directories to the path of each of the
59 * defined suffixes, as specified using
60 * .PATH<suffix>: targets. In addition, all
61 * directories given for suffixes labeled as
62 * include files or libraries, using the .INCLUDES
63 * or .LIBS targets, are played with using
64 * Dir_MakeFlags to create the .INCLUDES and
65 * .LIBS global variables.
66 *
67 * Suff_ClearSuffixes Clear out all the suffixes and defined
68 * transformations.
69 *
70 * Suff_IsTransform Return TRUE if the passed string is the lhs
71 * of a transformation rule.
72 *
73 * Suff_AddSuffix Add the passed string as another known suffix.
74 *
75 * Suff_GetPath Return the search path for the given suffix.
76 *
77 * Suff_AddInclude Mark the given suffix as denoting an include
78 * file.
79 *
80 * Suff_AddLib Mark the given suffix as denoting a library.
81 *
82 * Suff_AddTransform Add another transformation to the suffix
83 * graph. Returns GNode suitable for framing, I
84 * mean, tacking commands, attributes, etc. on.
85 *
86 * Suff_SetNull Define the suffix to consider the suffix of
87 * any file that doesn't have a known one.
88 *
89 * Suff_FindDeps Find implicit sources for and the location of
90 * a target based on its suffix. Returns the
91 * bottom-most node added to the graph or NULL
92 * if the target had no implicit sources.
93 */
94
95#include <stdio.h>
96#include "make.h"
97#include "hash.h"
98#include "dir.h"
99
100static Lst sufflist; /* Lst of suffixes */
101static Lst suffClean; /* Lst of suffixes to be cleaned */
102static Lst srclist; /* Lst of sources */
103static Lst transforms; /* Lst of transformation rules */
104
105static int sNum = 0; /* Counter for assigning suffix numbers */
106
107/*
108 * Structure describing an individual suffix.
109 */
110typedef struct _Suff {
111 char *name; /* The suffix itself */
112 int nameLen; /* Length of the suffix */
113 short flags; /* Type of suffix */
114#define SUFF_INCLUDE 0x01 /* One which is #include'd */
115#define SUFF_LIBRARY 0x02 /* One which contains a library */
116#define SUFF_NULL 0x04 /* The empty suffix */
117 Lst searchPath; /* The path along which files of this suffix
118 * may be found */
119 int sNum; /* The suffix number */
120 int refCount; /* Reference count of list membership */
121 Lst parents; /* Suffixes we have a transformation to */
122 Lst children; /* Suffixes we have a transformation from */
123 Lst ref; /* List of lists this suffix is referenced */
124} Suff;
125
126/*
127 * Structure used in the search for implied sources.
128 */
129typedef struct _Src {
130 char *file; /* The file to look for */
131 char *pref; /* Prefix from which file was formed */
132 Suff *suff; /* The suffix on the file */
133 struct _Src *parent; /* The Src for which this is a source */
134 GNode *node; /* The node describing the file */
135 int children; /* Count of existing children (so we don't free
136 * this thing too early or never nuke it) */
137#ifdef DEBUG_SRC
138 Lst cp; /* Debug; children list */
139#endif
140} Src;
141
142/*
143 * A structure for passing more than one argument to the Lst-library-invoked
144 * function...
145 */
146typedef struct {
147 Lst l;
148 Src *s;
149} LstSrc;
150
151static Suff *suffNull; /* The NULL suffix for this run */
152static Suff *emptySuff; /* The empty suffix required for POSIX
153 * single-suffix transformation rules */
154
155
156static char *SuffStrIsPrefix(char *, char *);
157static char *SuffSuffIsSuffix(Suff *, char *);
158static int SuffSuffIsSuffixP(void *, void *);
159static int SuffSuffHasNameP(void *, void *);
160static int SuffSuffIsPrefix(void *, void *);
161static int SuffGNHasNameP(void *, void *);
162static void SuffFree(void *);
163static void SuffInsert(Lst, Suff *);
164static void SuffRemove(Lst, Suff *);
165static Boolean SuffParseTransform(char *, Suff **, Suff **);
166static int SuffRebuildGraph(void *, void *);
167static int SuffAddSrc(void *, void *);
168static int SuffRemoveSrc(Lst);
169static void SuffAddLevel(Lst, Src *);
170static Src *SuffFindThem(Lst, Lst);
171static Src *SuffFindCmds(Src *, Lst);
172static int SuffExpandChildren(void *, void *);
173static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
174static void SuffFindDeps(GNode *, Lst);
175static void SuffFindArchiveDeps(GNode *, Lst);
176static void SuffFindNormalDeps(GNode *, Lst);
177static int SuffPrintName(void *, void *);
178static int SuffPrintSuff(void *, void *);
179static int SuffPrintTrans(void *, void *);
180
181 /*************** Lst Predicates ****************/
182/*-
183 *-----------------------------------------------------------------------
184 * SuffStrIsPrefix --
185 * See if pref is a prefix of str.
186 *
187 * Results:
188 * NULL if it ain't, pointer to character in str after prefix if so
189 *
190 * Side Effects:
191 * None
192 *-----------------------------------------------------------------------
193 */
194static char *
195SuffStrIsPrefix (pref, str)
196 char *pref; /* possible prefix */
197 char *str; /* string to check */
198{
199 while (*str && *pref == *str) {
200 pref++;
201 str++;
202 }
203
204 return (*pref ? NULL : str);
205}
206
207/*-
208 *-----------------------------------------------------------------------
209 * SuffSuffIsSuffix --
210 * See if suff is a suffix of str. Str should point to THE END of the
211 * string to check. (THE END == the null byte)
212 *
213 * Results:
214 * NULL if it ain't, pointer to character in str before suffix if
215 * it is.
216 *
217 * Side Effects:
218 * None
219 *-----------------------------------------------------------------------
220 */
221static char *
222SuffSuffIsSuffix (s, str)
223 Suff *s; /* possible suffix */
224 char *str; /* string to examine */
225{
226 char *p1; /* Pointer into suffix name */
227 char *p2; /* Pointer into string being examined */
228
229 p1 = s->name + s->nameLen;
230 p2 = str;
231
232 while (p1 >= s->name && *p1 == *p2) {
233 p1--;
234 p2--;
235 }
236
237 return (p1 == s->name - 1 ? p2 : NULL);
238}
239
240/*-
241 *-----------------------------------------------------------------------
242 * SuffSuffIsSuffixP --
243 * Predicate form of SuffSuffIsSuffix. Passed as the callback function
244 * to Lst_Find.
245 *
246 * Results:
247 * 0 if the suffix is the one desired, non-zero if not.
248 *
249 * Side Effects:
250 * None.
251 *
252 *-----------------------------------------------------------------------
253 */
254static int
255SuffSuffIsSuffixP(s, str)
256 void * s;
257 void * str;
258{
259 return(!SuffSuffIsSuffix((Suff *) s, (char *) str));
260}
261
262/*-
263 *-----------------------------------------------------------------------
264 * SuffSuffHasNameP --
265 * Callback procedure for finding a suffix based on its name. Used by
266 * Suff_GetPath.
267 *
268 * Results:
269 * 0 if the suffix is of the given name. non-zero otherwise.
270 *
271 * Side Effects:
272 * None
273 *-----------------------------------------------------------------------
274 */
275static int
276SuffSuffHasNameP (s, sname)
277 void * s; /* Suffix to check */
278 void * sname; /* Desired name */
279{
280 return (strcmp ((char *) sname, ((Suff *) s)->name));
281}
282
283/*-
284 *-----------------------------------------------------------------------
285 * SuffSuffIsPrefix --
286 * See if the suffix described by s is a prefix of the string. Care
287 * must be taken when using this to search for transformations and
288 * what-not, since there could well be two suffixes, one of which
289 * is a prefix of the other...
290 *
291 * Results:
292 * 0 if s is a prefix of str. non-zero otherwise
293 *
294 * Side Effects:
295 * None
296 *-----------------------------------------------------------------------
297 */
298static int
299SuffSuffIsPrefix (s, str)
300 void * s; /* suffix to compare */
301 void * str; /* string to examine */
302{
303 return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);
304}
305
306/*-
307 *-----------------------------------------------------------------------
308 * SuffGNHasNameP --
309 * See if the graph node has the desired name
310 *
311 * Results:
312 * 0 if it does. non-zero if it doesn't
313 *
314 * Side Effects:
315 * None
316 *-----------------------------------------------------------------------
317 */
318static int
319SuffGNHasNameP (gn, name)
320 void * gn; /* current node we're looking at */
321 void * name; /* name we're looking for */
322{
323 return (strcmp ((char *) name, ((GNode *) gn)->name));
324}
325
326 /*********** Maintenance Functions ************/
327
328/*-
329 *-----------------------------------------------------------------------
330 * SuffFree --
331 * Free up all memory associated with the given suffix structure.
332 *
333 * Results:
334 * none
335 *
336 * Side Effects:
337 * the suffix entry is detroyed
338 *-----------------------------------------------------------------------
339 */
340static void
341SuffFree (sp)
342 void * sp;
343{
344 Suff *s = (Suff *) sp;
345
346 if (s == suffNull)
347 suffNull = NULL;
348
349 if (s == emptySuff)
350 emptySuff = NULL;
351
352 Lst_Destroy (s->ref, NOFREE);
353 Lst_Destroy (s->children, NOFREE);
354 Lst_Destroy (s->parents, NOFREE);
355 Lst_Destroy (s->searchPath, Dir_Destroy);
356
357 free (s->name);
358 free (s);
359}
360
361/*-
362 *-----------------------------------------------------------------------
363 * SuffRemove --
364 * Remove the suffix into the list
365 *
366 * Results:
367 * None
368 *
369 * Side Effects:
370 * The reference count for the suffix is decremented
371 *-----------------------------------------------------------------------
372 */
373static void
374SuffRemove(l, s)
375 Lst l;
376 Suff *s;
377{
378 LstNode ln = Lst_Member(l, (void *)s);
379 if (ln != NULL) {
380 Lst_Remove(l, ln);
381 s->refCount--;
382 }
383}
384
385/*-
386 *-----------------------------------------------------------------------
387 * SuffInsert --
388 * Insert the suffix into the list keeping the list ordered by suffix
389 * numbers.
390 *
391 * Results:
392 * None
393 *
394 * Side Effects:
395 * The reference count of the suffix is incremented
396 *-----------------------------------------------------------------------
397 */
398static void
399SuffInsert (l, s)
400 Lst l; /* the list where in s should be inserted */
401 Suff *s; /* the suffix to insert */
402{
403 LstNode ln; /* current element in l we're examining */
404 Suff *s2 = NULL; /* the suffix descriptor in this element */
405
406 if (Lst_Open (l) == FAILURE) {
407 return;
408 }
409 while ((ln = Lst_Next (l)) != NULL) {
410 s2 = (Suff *) Lst_Datum (ln);
411 if (s2->sNum >= s->sNum) {
412 break;
413 }
414 }
415
416 Lst_Close (l);
43
44/*-
45 * suff.c --
46 * Functions to maintain suffix lists and find implicit dependents
47 * using suffix transformation rules
48 *
49 * Interface:
50 * Suff_Init Initialize all things to do with suffixes.
51 *
52 * Suff_End Cleanup the module
53 *
54 * Suff_DoPaths This function is used to make life easier
55 * when searching for a file according to its
56 * suffix. It takes the global search path,
57 * as defined using the .PATH: target, and appends
58 * its directories to the path of each of the
59 * defined suffixes, as specified using
60 * .PATH<suffix>: targets. In addition, all
61 * directories given for suffixes labeled as
62 * include files or libraries, using the .INCLUDES
63 * or .LIBS targets, are played with using
64 * Dir_MakeFlags to create the .INCLUDES and
65 * .LIBS global variables.
66 *
67 * Suff_ClearSuffixes Clear out all the suffixes and defined
68 * transformations.
69 *
70 * Suff_IsTransform Return TRUE if the passed string is the lhs
71 * of a transformation rule.
72 *
73 * Suff_AddSuffix Add the passed string as another known suffix.
74 *
75 * Suff_GetPath Return the search path for the given suffix.
76 *
77 * Suff_AddInclude Mark the given suffix as denoting an include
78 * file.
79 *
80 * Suff_AddLib Mark the given suffix as denoting a library.
81 *
82 * Suff_AddTransform Add another transformation to the suffix
83 * graph. Returns GNode suitable for framing, I
84 * mean, tacking commands, attributes, etc. on.
85 *
86 * Suff_SetNull Define the suffix to consider the suffix of
87 * any file that doesn't have a known one.
88 *
89 * Suff_FindDeps Find implicit sources for and the location of
90 * a target based on its suffix. Returns the
91 * bottom-most node added to the graph or NULL
92 * if the target had no implicit sources.
93 */
94
95#include <stdio.h>
96#include "make.h"
97#include "hash.h"
98#include "dir.h"
99
100static Lst sufflist; /* Lst of suffixes */
101static Lst suffClean; /* Lst of suffixes to be cleaned */
102static Lst srclist; /* Lst of sources */
103static Lst transforms; /* Lst of transformation rules */
104
105static int sNum = 0; /* Counter for assigning suffix numbers */
106
107/*
108 * Structure describing an individual suffix.
109 */
110typedef struct _Suff {
111 char *name; /* The suffix itself */
112 int nameLen; /* Length of the suffix */
113 short flags; /* Type of suffix */
114#define SUFF_INCLUDE 0x01 /* One which is #include'd */
115#define SUFF_LIBRARY 0x02 /* One which contains a library */
116#define SUFF_NULL 0x04 /* The empty suffix */
117 Lst searchPath; /* The path along which files of this suffix
118 * may be found */
119 int sNum; /* The suffix number */
120 int refCount; /* Reference count of list membership */
121 Lst parents; /* Suffixes we have a transformation to */
122 Lst children; /* Suffixes we have a transformation from */
123 Lst ref; /* List of lists this suffix is referenced */
124} Suff;
125
126/*
127 * Structure used in the search for implied sources.
128 */
129typedef struct _Src {
130 char *file; /* The file to look for */
131 char *pref; /* Prefix from which file was formed */
132 Suff *suff; /* The suffix on the file */
133 struct _Src *parent; /* The Src for which this is a source */
134 GNode *node; /* The node describing the file */
135 int children; /* Count of existing children (so we don't free
136 * this thing too early or never nuke it) */
137#ifdef DEBUG_SRC
138 Lst cp; /* Debug; children list */
139#endif
140} Src;
141
142/*
143 * A structure for passing more than one argument to the Lst-library-invoked
144 * function...
145 */
146typedef struct {
147 Lst l;
148 Src *s;
149} LstSrc;
150
151static Suff *suffNull; /* The NULL suffix for this run */
152static Suff *emptySuff; /* The empty suffix required for POSIX
153 * single-suffix transformation rules */
154
155
156static char *SuffStrIsPrefix(char *, char *);
157static char *SuffSuffIsSuffix(Suff *, char *);
158static int SuffSuffIsSuffixP(void *, void *);
159static int SuffSuffHasNameP(void *, void *);
160static int SuffSuffIsPrefix(void *, void *);
161static int SuffGNHasNameP(void *, void *);
162static void SuffFree(void *);
163static void SuffInsert(Lst, Suff *);
164static void SuffRemove(Lst, Suff *);
165static Boolean SuffParseTransform(char *, Suff **, Suff **);
166static int SuffRebuildGraph(void *, void *);
167static int SuffAddSrc(void *, void *);
168static int SuffRemoveSrc(Lst);
169static void SuffAddLevel(Lst, Src *);
170static Src *SuffFindThem(Lst, Lst);
171static Src *SuffFindCmds(Src *, Lst);
172static int SuffExpandChildren(void *, void *);
173static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
174static void SuffFindDeps(GNode *, Lst);
175static void SuffFindArchiveDeps(GNode *, Lst);
176static void SuffFindNormalDeps(GNode *, Lst);
177static int SuffPrintName(void *, void *);
178static int SuffPrintSuff(void *, void *);
179static int SuffPrintTrans(void *, void *);
180
181 /*************** Lst Predicates ****************/
182/*-
183 *-----------------------------------------------------------------------
184 * SuffStrIsPrefix --
185 * See if pref is a prefix of str.
186 *
187 * Results:
188 * NULL if it ain't, pointer to character in str after prefix if so
189 *
190 * Side Effects:
191 * None
192 *-----------------------------------------------------------------------
193 */
194static char *
195SuffStrIsPrefix (pref, str)
196 char *pref; /* possible prefix */
197 char *str; /* string to check */
198{
199 while (*str && *pref == *str) {
200 pref++;
201 str++;
202 }
203
204 return (*pref ? NULL : str);
205}
206
207/*-
208 *-----------------------------------------------------------------------
209 * SuffSuffIsSuffix --
210 * See if suff is a suffix of str. Str should point to THE END of the
211 * string to check. (THE END == the null byte)
212 *
213 * Results:
214 * NULL if it ain't, pointer to character in str before suffix if
215 * it is.
216 *
217 * Side Effects:
218 * None
219 *-----------------------------------------------------------------------
220 */
221static char *
222SuffSuffIsSuffix (s, str)
223 Suff *s; /* possible suffix */
224 char *str; /* string to examine */
225{
226 char *p1; /* Pointer into suffix name */
227 char *p2; /* Pointer into string being examined */
228
229 p1 = s->name + s->nameLen;
230 p2 = str;
231
232 while (p1 >= s->name && *p1 == *p2) {
233 p1--;
234 p2--;
235 }
236
237 return (p1 == s->name - 1 ? p2 : NULL);
238}
239
240/*-
241 *-----------------------------------------------------------------------
242 * SuffSuffIsSuffixP --
243 * Predicate form of SuffSuffIsSuffix. Passed as the callback function
244 * to Lst_Find.
245 *
246 * Results:
247 * 0 if the suffix is the one desired, non-zero if not.
248 *
249 * Side Effects:
250 * None.
251 *
252 *-----------------------------------------------------------------------
253 */
254static int
255SuffSuffIsSuffixP(s, str)
256 void * s;
257 void * str;
258{
259 return(!SuffSuffIsSuffix((Suff *) s, (char *) str));
260}
261
262/*-
263 *-----------------------------------------------------------------------
264 * SuffSuffHasNameP --
265 * Callback procedure for finding a suffix based on its name. Used by
266 * Suff_GetPath.
267 *
268 * Results:
269 * 0 if the suffix is of the given name. non-zero otherwise.
270 *
271 * Side Effects:
272 * None
273 *-----------------------------------------------------------------------
274 */
275static int
276SuffSuffHasNameP (s, sname)
277 void * s; /* Suffix to check */
278 void * sname; /* Desired name */
279{
280 return (strcmp ((char *) sname, ((Suff *) s)->name));
281}
282
283/*-
284 *-----------------------------------------------------------------------
285 * SuffSuffIsPrefix --
286 * See if the suffix described by s is a prefix of the string. Care
287 * must be taken when using this to search for transformations and
288 * what-not, since there could well be two suffixes, one of which
289 * is a prefix of the other...
290 *
291 * Results:
292 * 0 if s is a prefix of str. non-zero otherwise
293 *
294 * Side Effects:
295 * None
296 *-----------------------------------------------------------------------
297 */
298static int
299SuffSuffIsPrefix (s, str)
300 void * s; /* suffix to compare */
301 void * str; /* string to examine */
302{
303 return (SuffStrIsPrefix (((Suff *) s)->name, (char *) str) == NULL ? 1 : 0);
304}
305
306/*-
307 *-----------------------------------------------------------------------
308 * SuffGNHasNameP --
309 * See if the graph node has the desired name
310 *
311 * Results:
312 * 0 if it does. non-zero if it doesn't
313 *
314 * Side Effects:
315 * None
316 *-----------------------------------------------------------------------
317 */
318static int
319SuffGNHasNameP (gn, name)
320 void * gn; /* current node we're looking at */
321 void * name; /* name we're looking for */
322{
323 return (strcmp ((char *) name, ((GNode *) gn)->name));
324}
325
326 /*********** Maintenance Functions ************/
327
328/*-
329 *-----------------------------------------------------------------------
330 * SuffFree --
331 * Free up all memory associated with the given suffix structure.
332 *
333 * Results:
334 * none
335 *
336 * Side Effects:
337 * the suffix entry is detroyed
338 *-----------------------------------------------------------------------
339 */
340static void
341SuffFree (sp)
342 void * sp;
343{
344 Suff *s = (Suff *) sp;
345
346 if (s == suffNull)
347 suffNull = NULL;
348
349 if (s == emptySuff)
350 emptySuff = NULL;
351
352 Lst_Destroy (s->ref, NOFREE);
353 Lst_Destroy (s->children, NOFREE);
354 Lst_Destroy (s->parents, NOFREE);
355 Lst_Destroy (s->searchPath, Dir_Destroy);
356
357 free (s->name);
358 free (s);
359}
360
361/*-
362 *-----------------------------------------------------------------------
363 * SuffRemove --
364 * Remove the suffix into the list
365 *
366 * Results:
367 * None
368 *
369 * Side Effects:
370 * The reference count for the suffix is decremented
371 *-----------------------------------------------------------------------
372 */
373static void
374SuffRemove(l, s)
375 Lst l;
376 Suff *s;
377{
378 LstNode ln = Lst_Member(l, (void *)s);
379 if (ln != NULL) {
380 Lst_Remove(l, ln);
381 s->refCount--;
382 }
383}
384
385/*-
386 *-----------------------------------------------------------------------
387 * SuffInsert --
388 * Insert the suffix into the list keeping the list ordered by suffix
389 * numbers.
390 *
391 * Results:
392 * None
393 *
394 * Side Effects:
395 * The reference count of the suffix is incremented
396 *-----------------------------------------------------------------------
397 */
398static void
399SuffInsert (l, s)
400 Lst l; /* the list where in s should be inserted */
401 Suff *s; /* the suffix to insert */
402{
403 LstNode ln; /* current element in l we're examining */
404 Suff *s2 = NULL; /* the suffix descriptor in this element */
405
406 if (Lst_Open (l) == FAILURE) {
407 return;
408 }
409 while ((ln = Lst_Next (l)) != NULL) {
410 s2 = (Suff *) Lst_Datum (ln);
411 if (s2->sNum >= s->sNum) {
412 break;
413 }
414 }
415
416 Lst_Close (l);
417 DEBUGF(SUFF, "inserting %s(%d)...", s->name, s->sNum);
417 DEBUGF(SUFF, ("inserting %s(%d)...", s->name, s->sNum));
418 if (ln == NULL) {
418 if (ln == NULL) {
419 DEBUGF(SUFF, "at end of list\n");
419 DEBUGF(SUFF, ("at end of list\n"));
420 (void)Lst_AtEnd (l, (void *)s);
421 s->refCount++;
422 (void)Lst_AtEnd(s->ref, (void *) l);
423 } else if (s2->sNum != s->sNum) {
420 (void)Lst_AtEnd (l, (void *)s);
421 s->refCount++;
422 (void)Lst_AtEnd(s->ref, (void *) l);
423 } else if (s2->sNum != s->sNum) {
424 DEBUGF(SUFF, "before %s(%d)\n", s2->name, s2->sNum);
424 DEBUGF(SUFF, ("before %s(%d)\n", s2->name, s2->sNum));
425 (void)Lst_Insert (l, ln, (void *)s);
426 s->refCount++;
427 (void)Lst_AtEnd(s->ref, (void *) l);
428 } else {
425 (void)Lst_Insert (l, ln, (void *)s);
426 s->refCount++;
427 (void)Lst_AtEnd(s->ref, (void *) l);
428 } else {
429 DEBUGF(SUFF, "already there\n");
429 DEBUGF(SUFF, ("already there\n"));
430 }
431}
432
433/*-
434 *-----------------------------------------------------------------------
435 * Suff_ClearSuffixes --
436 * This is gross. Nuke the list of suffixes but keep all transformation
437 * rules around. The transformation graph is destroyed in this process,
438 * but we leave the list of rules so when a new graph is formed the rules
439 * will remain.
440 * This function is called from the parse module when a
441 * .SUFFIXES:\n line is encountered.
442 *
443 * Results:
444 * none
445 *
446 * Side Effects:
447 * the sufflist and its graph nodes are destroyed
448 *-----------------------------------------------------------------------
449 */
450void
451Suff_ClearSuffixes ()
452{
453 Lst_Concat (suffClean, sufflist, LST_CONCLINK);
454 sufflist = Lst_Init(FALSE);
455 sNum = 1;
456 suffNull = emptySuff;
457 /*
458 * Clear suffNull's children list (the other suffixes are built new, but
459 * suffNull is used as is).
460 * NOFREE is used because all suffixes are are on the suffClean list.
461 * suffNull should not have parents.
462 */
463 Lst_Destroy(suffNull->children, NOFREE);
464 suffNull->children = Lst_Init(FALSE);
465}
466
467/*-
468 *-----------------------------------------------------------------------
469 * SuffParseTransform --
470 * Parse a transformation string to find its two component suffixes.
471 *
472 * Results:
473 * TRUE if the string is a valid transformation and FALSE otherwise.
474 *
475 * Side Effects:
476 * The passed pointers are overwritten.
477 *
478 *-----------------------------------------------------------------------
479 */
480static Boolean
481SuffParseTransform(str, srcPtr, targPtr)
482 char *str; /* String being parsed */
483 Suff **srcPtr; /* Place to store source of trans. */
484 Suff **targPtr; /* Place to store target of trans. */
485{
486 LstNode srcLn; /* element in suffix list of trans source*/
487 Suff *src; /* Source of transformation */
488 LstNode targLn; /* element in suffix list of trans target*/
489 char *str2; /* Extra pointer (maybe target suffix) */
490 LstNode singleLn; /* element in suffix list of any suffix
491 * that exactly matches str */
492 Suff *single = NULL;/* Source of possible transformation to
493 * null suffix */
494
495 srcLn = NULL;
496 singleLn = NULL;
497
498 /*
499 * Loop looking first for a suffix that matches the start of the
500 * string and then for one that exactly matches the rest of it. If
501 * we can find two that meet these criteria, we've successfully
502 * parsed the string.
503 */
504 for (;;) {
505 if (srcLn == NULL) {
506 srcLn = Lst_Find(sufflist, (void *)str, SuffSuffIsPrefix);
507 } else {
508 srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (void *)str,
509 SuffSuffIsPrefix);
510 }
511 if (srcLn == NULL) {
512 /*
513 * Ran out of source suffixes -- no such rule
514 */
515 if (singleLn != NULL) {
516 /*
517 * Not so fast Mr. Smith! There was a suffix that encompassed
518 * the entire string, so we assume it was a transformation
519 * to the null suffix (thank you POSIX). We still prefer to
520 * find a double rule over a singleton, hence we leave this
521 * check until the end.
522 *
523 * XXX: Use emptySuff over suffNull?
524 */
525 *srcPtr = single;
526 *targPtr = suffNull;
527 return(TRUE);
528 }
529 return (FALSE);
530 }
531 src = (Suff *) Lst_Datum (srcLn);
532 str2 = str + src->nameLen;
533 if (*str2 == '\0') {
534 single = src;
535 singleLn = srcLn;
536 } else {
537 targLn = Lst_Find(sufflist, (void *)str2, SuffSuffHasNameP);
538 if (targLn != NULL) {
539 *srcPtr = src;
540 *targPtr = (Suff *)Lst_Datum(targLn);
541 return (TRUE);
542 }
543 }
544 }
545}
546
547/*-
548 *-----------------------------------------------------------------------
549 * Suff_IsTransform --
550 * Return TRUE if the given string is a transformation rule
551 *
552 *
553 * Results:
554 * TRUE if the string is a concatenation of two known suffixes.
555 * FALSE otherwise
556 *
557 * Side Effects:
558 * None
559 *-----------------------------------------------------------------------
560 */
561Boolean
562Suff_IsTransform (str)
563 char *str; /* string to check */
564{
565 Suff *src, *targ;
566
567 return (SuffParseTransform(str, &src, &targ));
568}
569
570/*-
571 *-----------------------------------------------------------------------
572 * Suff_AddTransform --
573 * Add the transformation rule described by the line to the
574 * list of rules and place the transformation itself in the graph
575 *
576 * Results:
577 * The node created for the transformation in the transforms list
578 *
579 * Side Effects:
580 * The node is placed on the end of the transforms Lst and links are
581 * made between the two suffixes mentioned in the target name
582 *-----------------------------------------------------------------------
583 */
584GNode *
585Suff_AddTransform (line)
586 char *line; /* name of transformation to add */
587{
588 GNode *gn; /* GNode of transformation rule */
589 Suff *s, /* source suffix */
590 *t; /* target suffix */
591 LstNode ln; /* Node for existing transformation */
592
593 ln = Lst_Find (transforms, (void *)line, SuffGNHasNameP);
594 if (ln == NULL) {
595 /*
596 * Make a new graph node for the transformation. It will be filled in
597 * by the Parse module.
598 */
599 gn = Targ_NewGN (line);
600 (void)Lst_AtEnd (transforms, (void *)gn);
601 } else {
602 /*
603 * New specification for transformation rule. Just nuke the old list
604 * of commands so they can be filled in again... We don't actually
605 * free the commands themselves, because a given command can be
606 * attached to several different transformations.
607 */
608 gn = (GNode *) Lst_Datum (ln);
609 Lst_Destroy (gn->commands, NOFREE);
610 Lst_Destroy (gn->children, NOFREE);
611 gn->commands = Lst_Init (FALSE);
612 gn->children = Lst_Init (FALSE);
613 }
614
615 gn->type = OP_TRANSFORM;
616
617 (void)SuffParseTransform(line, &s, &t);
618
619 /*
620 * link the two together in the proper relationship and order
621 */
430 }
431}
432
433/*-
434 *-----------------------------------------------------------------------
435 * Suff_ClearSuffixes --
436 * This is gross. Nuke the list of suffixes but keep all transformation
437 * rules around. The transformation graph is destroyed in this process,
438 * but we leave the list of rules so when a new graph is formed the rules
439 * will remain.
440 * This function is called from the parse module when a
441 * .SUFFIXES:\n line is encountered.
442 *
443 * Results:
444 * none
445 *
446 * Side Effects:
447 * the sufflist and its graph nodes are destroyed
448 *-----------------------------------------------------------------------
449 */
450void
451Suff_ClearSuffixes ()
452{
453 Lst_Concat (suffClean, sufflist, LST_CONCLINK);
454 sufflist = Lst_Init(FALSE);
455 sNum = 1;
456 suffNull = emptySuff;
457 /*
458 * Clear suffNull's children list (the other suffixes are built new, but
459 * suffNull is used as is).
460 * NOFREE is used because all suffixes are are on the suffClean list.
461 * suffNull should not have parents.
462 */
463 Lst_Destroy(suffNull->children, NOFREE);
464 suffNull->children = Lst_Init(FALSE);
465}
466
467/*-
468 *-----------------------------------------------------------------------
469 * SuffParseTransform --
470 * Parse a transformation string to find its two component suffixes.
471 *
472 * Results:
473 * TRUE if the string is a valid transformation and FALSE otherwise.
474 *
475 * Side Effects:
476 * The passed pointers are overwritten.
477 *
478 *-----------------------------------------------------------------------
479 */
480static Boolean
481SuffParseTransform(str, srcPtr, targPtr)
482 char *str; /* String being parsed */
483 Suff **srcPtr; /* Place to store source of trans. */
484 Suff **targPtr; /* Place to store target of trans. */
485{
486 LstNode srcLn; /* element in suffix list of trans source*/
487 Suff *src; /* Source of transformation */
488 LstNode targLn; /* element in suffix list of trans target*/
489 char *str2; /* Extra pointer (maybe target suffix) */
490 LstNode singleLn; /* element in suffix list of any suffix
491 * that exactly matches str */
492 Suff *single = NULL;/* Source of possible transformation to
493 * null suffix */
494
495 srcLn = NULL;
496 singleLn = NULL;
497
498 /*
499 * Loop looking first for a suffix that matches the start of the
500 * string and then for one that exactly matches the rest of it. If
501 * we can find two that meet these criteria, we've successfully
502 * parsed the string.
503 */
504 for (;;) {
505 if (srcLn == NULL) {
506 srcLn = Lst_Find(sufflist, (void *)str, SuffSuffIsPrefix);
507 } else {
508 srcLn = Lst_FindFrom (sufflist, Lst_Succ(srcLn), (void *)str,
509 SuffSuffIsPrefix);
510 }
511 if (srcLn == NULL) {
512 /*
513 * Ran out of source suffixes -- no such rule
514 */
515 if (singleLn != NULL) {
516 /*
517 * Not so fast Mr. Smith! There was a suffix that encompassed
518 * the entire string, so we assume it was a transformation
519 * to the null suffix (thank you POSIX). We still prefer to
520 * find a double rule over a singleton, hence we leave this
521 * check until the end.
522 *
523 * XXX: Use emptySuff over suffNull?
524 */
525 *srcPtr = single;
526 *targPtr = suffNull;
527 return(TRUE);
528 }
529 return (FALSE);
530 }
531 src = (Suff *) Lst_Datum (srcLn);
532 str2 = str + src->nameLen;
533 if (*str2 == '\0') {
534 single = src;
535 singleLn = srcLn;
536 } else {
537 targLn = Lst_Find(sufflist, (void *)str2, SuffSuffHasNameP);
538 if (targLn != NULL) {
539 *srcPtr = src;
540 *targPtr = (Suff *)Lst_Datum(targLn);
541 return (TRUE);
542 }
543 }
544 }
545}
546
547/*-
548 *-----------------------------------------------------------------------
549 * Suff_IsTransform --
550 * Return TRUE if the given string is a transformation rule
551 *
552 *
553 * Results:
554 * TRUE if the string is a concatenation of two known suffixes.
555 * FALSE otherwise
556 *
557 * Side Effects:
558 * None
559 *-----------------------------------------------------------------------
560 */
561Boolean
562Suff_IsTransform (str)
563 char *str; /* string to check */
564{
565 Suff *src, *targ;
566
567 return (SuffParseTransform(str, &src, &targ));
568}
569
570/*-
571 *-----------------------------------------------------------------------
572 * Suff_AddTransform --
573 * Add the transformation rule described by the line to the
574 * list of rules and place the transformation itself in the graph
575 *
576 * Results:
577 * The node created for the transformation in the transforms list
578 *
579 * Side Effects:
580 * The node is placed on the end of the transforms Lst and links are
581 * made between the two suffixes mentioned in the target name
582 *-----------------------------------------------------------------------
583 */
584GNode *
585Suff_AddTransform (line)
586 char *line; /* name of transformation to add */
587{
588 GNode *gn; /* GNode of transformation rule */
589 Suff *s, /* source suffix */
590 *t; /* target suffix */
591 LstNode ln; /* Node for existing transformation */
592
593 ln = Lst_Find (transforms, (void *)line, SuffGNHasNameP);
594 if (ln == NULL) {
595 /*
596 * Make a new graph node for the transformation. It will be filled in
597 * by the Parse module.
598 */
599 gn = Targ_NewGN (line);
600 (void)Lst_AtEnd (transforms, (void *)gn);
601 } else {
602 /*
603 * New specification for transformation rule. Just nuke the old list
604 * of commands so they can be filled in again... We don't actually
605 * free the commands themselves, because a given command can be
606 * attached to several different transformations.
607 */
608 gn = (GNode *) Lst_Datum (ln);
609 Lst_Destroy (gn->commands, NOFREE);
610 Lst_Destroy (gn->children, NOFREE);
611 gn->commands = Lst_Init (FALSE);
612 gn->children = Lst_Init (FALSE);
613 }
614
615 gn->type = OP_TRANSFORM;
616
617 (void)SuffParseTransform(line, &s, &t);
618
619 /*
620 * link the two together in the proper relationship and order
621 */
622 DEBUGF(SUFF, "defining transformation from `%s' to `%s'\n",
623 s->name, t->name);
622 DEBUGF(SUFF, ("defining transformation from `%s' to `%s'\n",
623 s->name, t->name));
624 SuffInsert (t->children, s);
625 SuffInsert (s->parents, t);
626
627 return (gn);
628}
629
630/*-
631 *-----------------------------------------------------------------------
632 * Suff_EndTransform --
633 * Handle the finish of a transformation definition, removing the
634 * transformation from the graph if it has neither commands nor
635 * sources. This is a callback procedure for the Parse module via
636 * Lst_ForEach
637 *
638 * Results:
639 * === 0
640 *
641 * Side Effects:
642 * If the node has no commands or children, the children and parents
643 * lists of the affected suffices are altered.
644 *
645 *-----------------------------------------------------------------------
646 */
647int
648Suff_EndTransform(gnp, dummy)
649 void * gnp; /* Node for transformation */
650 void * dummy; /* Node for transformation */
651{
652 GNode *gn = (GNode *) gnp;
653
654 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
655 Lst_IsEmpty(gn->children))
656 {
657 Suff *s, *t;
658
659 (void)SuffParseTransform(gn->name, &s, &t);
660
624 SuffInsert (t->children, s);
625 SuffInsert (s->parents, t);
626
627 return (gn);
628}
629
630/*-
631 *-----------------------------------------------------------------------
632 * Suff_EndTransform --
633 * Handle the finish of a transformation definition, removing the
634 * transformation from the graph if it has neither commands nor
635 * sources. This is a callback procedure for the Parse module via
636 * Lst_ForEach
637 *
638 * Results:
639 * === 0
640 *
641 * Side Effects:
642 * If the node has no commands or children, the children and parents
643 * lists of the affected suffices are altered.
644 *
645 *-----------------------------------------------------------------------
646 */
647int
648Suff_EndTransform(gnp, dummy)
649 void * gnp; /* Node for transformation */
650 void * dummy; /* Node for transformation */
651{
652 GNode *gn = (GNode *) gnp;
653
654 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
655 Lst_IsEmpty(gn->children))
656 {
657 Suff *s, *t;
658
659 (void)SuffParseTransform(gn->name, &s, &t);
660
661 DEBUGF(SUFF, "deleting transformation from `%s' to `%s'\n",
662 s->name, t->name);
661 DEBUGF(SUFF, ("deleting transformation from `%s' to `%s'\n",
662 s->name, t->name));
663
664 /*
665 * Remove the source from the target's children list. We check for a
666 * NULL return to handle a beanhead saying something like
667 * .c.o .c.o:
668 *
669 * We'll be called twice when the next target is seen, but .c and .o
670 * are only linked once...
671 */
672 SuffRemove(t->children, s);
673
674 /*
675 * Remove the target from the source's parents list
676 */
677 SuffRemove(s->parents, t);
678 } else if (gn->type & OP_TRANSFORM) {
663
664 /*
665 * Remove the source from the target's children list. We check for a
666 * NULL return to handle a beanhead saying something like
667 * .c.o .c.o:
668 *
669 * We'll be called twice when the next target is seen, but .c and .o
670 * are only linked once...
671 */
672 SuffRemove(t->children, s);
673
674 /*
675 * Remove the target from the source's parents list
676 */
677 SuffRemove(s->parents, t);
678 } else if (gn->type & OP_TRANSFORM) {
679 DEBUGF(SUFF, "transformation %s complete\n", gn->name);
679 DEBUGF(SUFF, ("transformation %s complete\n", gn->name));
680 }
681
682 return(dummy ? 0 : 0);
683}
684
685/*-
686 *-----------------------------------------------------------------------
687 * SuffRebuildGraph --
688 * Called from Suff_AddSuffix via Lst_ForEach to search through the
689 * list of existing transformation rules and rebuild the transformation
690 * graph when it has been destroyed by Suff_ClearSuffixes. If the
691 * given rule is a transformation involving this suffix and another,
692 * existing suffix, the proper relationship is established between
693 * the two.
694 *
695 * Results:
696 * Always 0.
697 *
698 * Side Effects:
699 * The appropriate links will be made between this suffix and
700 * others if transformation rules exist for it.
701 *
702 *-----------------------------------------------------------------------
703 */
704static int
705SuffRebuildGraph(transformp, sp)
706 void * transformp; /* Transformation to test */
707 void * sp; /* Suffix to rebuild */
708{
709 GNode *transform = (GNode *) transformp;
710 Suff *s = (Suff *) sp;
711 char *cp;
712 LstNode ln;
713 Suff *s2 = NULL;
714
715 /*
716 * First see if it is a transformation from this suffix.
717 */
718 cp = SuffStrIsPrefix(s->name, transform->name);
719 if (cp != (char *)NULL) {
720 if (cp[0] == '\0') /* null rule */
721 s2 = suffNull;
722 else {
723 ln = Lst_Find(sufflist, (void *)cp, SuffSuffHasNameP);
724 if (ln != NULL)
725 s2 = (Suff *)Lst_Datum(ln);
726 }
727 if (s2 != NULL) {
728 /*
729 * Found target. Link in and return, since it can't be anything
730 * else.
731 */
732 SuffInsert(s2->children, s);
733 SuffInsert(s->parents, s2);
734 return(0);
735 }
736 }
737
738 /*
739 * Not from, maybe to?
740 */
741 cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
742 if (cp != (char *)NULL) {
743 /*
744 * Null-terminate the source suffix in order to find it.
745 */
746 cp[1] = '\0';
747 ln = Lst_Find(sufflist, (void *)transform->name, SuffSuffHasNameP);
748 /*
749 * Replace the start of the target suffix
750 */
751 cp[1] = s->name[0];
752 if (ln != NULL) {
753 /*
754 * Found it -- establish the proper relationship
755 */
756 s2 = (Suff *)Lst_Datum(ln);
757 SuffInsert(s->children, s2);
758 SuffInsert(s2->parents, s);
759 }
760 }
761 return(0);
762}
763
764/*-
765 *-----------------------------------------------------------------------
766 * Suff_AddSuffix --
767 * Add the suffix in string to the end of the list of known suffixes.
768 * Should we restructure the suffix graph? Make doesn't...
769 *
770 * Results:
771 * None
772 *
773 * Side Effects:
774 * A GNode is created for the suffix and a Suff structure is created and
775 * added to the suffixes list unless the suffix was already known.
776 *-----------------------------------------------------------------------
777 */
778void
779Suff_AddSuffix (str)
780 char *str; /* the name of the suffix to add */
781{
782 Suff *s; /* new suffix descriptor */
783 LstNode ln;
784
785 ln = Lst_Find (sufflist, (void *)str, SuffSuffHasNameP);
786 if (ln == NULL) {
787 s = (Suff *) emalloc (sizeof (Suff));
788
789 s->name = estrdup (str);
790 s->nameLen = strlen (s->name);
791 s->searchPath = Lst_Init (FALSE);
792 s->children = Lst_Init (FALSE);
793 s->parents = Lst_Init (FALSE);
794 s->ref = Lst_Init (FALSE);
795 s->sNum = sNum++;
796 s->flags = 0;
797 s->refCount = 0;
798
799 (void)Lst_AtEnd (sufflist, (void *)s);
800 /*
801 * Look for any existing transformations from or to this suffix.
802 * XXX: Only do this after a Suff_ClearSuffixes?
803 */
804 Lst_ForEach (transforms, SuffRebuildGraph, (void *)s);
805 }
806}
807
808/*-
809 *-----------------------------------------------------------------------
810 * Suff_GetPath --
811 * Return the search path for the given suffix, if it's defined.
812 *
813 * Results:
814 * The searchPath for the desired suffix or NULL if the suffix isn't
815 * defined.
816 *
817 * Side Effects:
818 * None
819 *-----------------------------------------------------------------------
820 */
821Lst
822Suff_GetPath (sname)
823 char *sname;
824{
825 LstNode ln;
826 Suff *s;
827
828 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
829 if (ln == NULL) {
830 return (NULL);
831 } else {
832 s = (Suff *) Lst_Datum (ln);
833 return (s->searchPath);
834 }
835}
836
837/*-
838 *-----------------------------------------------------------------------
839 * Suff_DoPaths --
840 * Extend the search paths for all suffixes to include the default
841 * search path.
842 *
843 * Results:
844 * None.
845 *
846 * Side Effects:
847 * The searchPath field of all the suffixes is extended by the
848 * directories in dirSearchPath. If paths were specified for the
849 * ".h" suffix, the directories are stuffed into a global variable
850 * called ".INCLUDES" with each directory preceded by a -I. The same
851 * is done for the ".a" suffix, except the variable is called
852 * ".LIBS" and the flag is -L.
853 *-----------------------------------------------------------------------
854 */
855void
856Suff_DoPaths()
857{
858 Suff *s;
859 LstNode ln;
860 char *ptr;
861 Lst inIncludes; /* Cumulative .INCLUDES path */
862 Lst inLibs; /* Cumulative .LIBS path */
863
864 if (Lst_Open (sufflist) == FAILURE) {
865 return;
866 }
867
868 inIncludes = Lst_Init(FALSE);
869 inLibs = Lst_Init(FALSE);
870
871 while ((ln = Lst_Next (sufflist)) != NULL) {
872 s = (Suff *) Lst_Datum (ln);
873 if (!Lst_IsEmpty (s->searchPath)) {
874#ifdef INCLUDES
875 if (s->flags & SUFF_INCLUDE) {
876 Dir_Concat(inIncludes, s->searchPath);
877 }
878#endif /* INCLUDES */
879#ifdef LIBRARIES
880 if (s->flags & SUFF_LIBRARY) {
881 Dir_Concat(inLibs, s->searchPath);
882 }
883#endif /* LIBRARIES */
884 Dir_Concat(s->searchPath, dirSearchPath);
885 } else {
886 Lst_Destroy (s->searchPath, Dir_Destroy);
887 s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
888 }
889 }
890
891 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);
892 free(ptr);
893 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
894 free(ptr);
895
896 Lst_Destroy(inIncludes, Dir_Destroy);
897 Lst_Destroy(inLibs, Dir_Destroy);
898
899 Lst_Close (sufflist);
900}
901
902/*-
903 *-----------------------------------------------------------------------
904 * Suff_AddInclude --
905 * Add the given suffix as a type of file which gets included.
906 * Called from the parse module when a .INCLUDES line is parsed.
907 * The suffix must have already been defined.
908 *
909 * Results:
910 * None.
911 *
912 * Side Effects:
913 * The SUFF_INCLUDE bit is set in the suffix's flags field
914 *
915 *-----------------------------------------------------------------------
916 */
917void
918Suff_AddInclude (sname)
919 char *sname; /* Name of suffix to mark */
920{
921 LstNode ln;
922 Suff *s;
923
924 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
925 if (ln != NULL) {
926 s = (Suff *) Lst_Datum (ln);
927 s->flags |= SUFF_INCLUDE;
928 }
929}
930
931/*-
932 *-----------------------------------------------------------------------
933 * Suff_AddLib --
934 * Add the given suffix as a type of file which is a library.
935 * Called from the parse module when parsing a .LIBS line. The
936 * suffix must have been defined via .SUFFIXES before this is
937 * called.
938 *
939 * Results:
940 * None.
941 *
942 * Side Effects:
943 * The SUFF_LIBRARY bit is set in the suffix's flags field
944 *
945 *-----------------------------------------------------------------------
946 */
947void
948Suff_AddLib (sname)
949 char *sname; /* Name of suffix to mark */
950{
951 LstNode ln;
952 Suff *s;
953
954 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
955 if (ln != NULL) {
956 s = (Suff *) Lst_Datum (ln);
957 s->flags |= SUFF_LIBRARY;
958 }
959}
960
961 /********** Implicit Source Search Functions *********/
962
963/*-
964 *-----------------------------------------------------------------------
965 * SuffAddSrc --
966 * Add a suffix as a Src structure to the given list with its parent
967 * being the given Src structure. If the suffix is the null suffix,
968 * the prefix is used unaltered as the file name in the Src structure.
969 *
970 * Results:
971 * always returns 0
972 *
973 * Side Effects:
974 * A Src structure is created and tacked onto the end of the list
975 *-----------------------------------------------------------------------
976 */
977static int
978SuffAddSrc (sp, lsp)
979 void * sp; /* suffix for which to create a Src structure */
980 void * lsp; /* list and parent for the new Src */
981{
982 Suff *s = (Suff *) sp;
983 LstSrc *ls = (LstSrc *) lsp;
984 Src *s2; /* new Src structure */
985 Src *targ; /* Target structure */
986
987 targ = ls->s;
988
989 if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
990 /*
991 * If the suffix has been marked as the NULL suffix, also create a Src
992 * structure for a file with no suffix attached. Two birds, and all
993 * that...
994 */
995 s2 = (Src *) emalloc (sizeof (Src));
996 s2->file = estrdup(targ->pref);
997 s2->pref = targ->pref;
998 s2->parent = targ;
999 s2->node = NULL;
1000 s2->suff = s;
1001 s->refCount++;
1002 s2->children = 0;
1003 targ->children += 1;
1004 (void)Lst_AtEnd (ls->l, (void *)s2);
1005#ifdef DEBUG_SRC
1006 s2->cp = Lst_Init(FALSE);
1007 Lst_AtEnd(targ->cp, (void *) s2);
1008 printf("1 add %x %x to %x:", targ, s2, ls->l);
1009 Lst_ForEach(ls->l, PrintAddr, (void *) 0);
1010 printf("\n");
1011#endif
1012 }
1013 s2 = (Src *) emalloc (sizeof (Src));
1014 s2->file = str_concat (targ->pref, s->name, 0);
1015 s2->pref = targ->pref;
1016 s2->parent = targ;
1017 s2->node = NULL;
1018 s2->suff = s;
1019 s->refCount++;
1020 s2->children = 0;
1021 targ->children += 1;
1022 (void)Lst_AtEnd (ls->l, (void *)s2);
1023#ifdef DEBUG_SRC
1024 s2->cp = Lst_Init(FALSE);
1025 Lst_AtEnd(targ->cp, (void *) s2);
1026 printf("2 add %x %x to %x:", targ, s2, ls->l);
1027 Lst_ForEach(ls->l, PrintAddr, (void *) 0);
1028 printf("\n");
1029#endif
1030
1031 return(0);
1032}
1033
1034/*-
1035 *-----------------------------------------------------------------------
1036 * SuffAddLevel --
1037 * Add all the children of targ as Src structures to the given list
1038 *
1039 * Results:
1040 * None
1041 *
1042 * Side Effects:
1043 * Lots of structures are created and added to the list
1044 *-----------------------------------------------------------------------
1045 */
1046static void
1047SuffAddLevel (l, targ)
1048 Lst l; /* list to which to add the new level */
1049 Src *targ; /* Src structure to use as the parent */
1050{
1051 LstSrc ls;
1052
1053 ls.s = targ;
1054 ls.l = l;
1055
1056 Lst_ForEach (targ->suff->children, SuffAddSrc, (void *)&ls);
1057}
1058
1059/*-
1060 *----------------------------------------------------------------------
1061 * SuffRemoveSrc --
1062 * Free all src structures in list that don't have a reference count
1063 *
1064 * Results:
1065 * Ture if an src was removed
1066 *
1067 * Side Effects:
1068 * The memory is free'd.
1069 *----------------------------------------------------------------------
1070 */
1071static int
1072SuffRemoveSrc (l)
1073 Lst l;
1074{
1075 LstNode ln;
1076 Src *s;
1077 int t = 0;
1078
1079 if (Lst_Open (l) == FAILURE) {
1080 return 0;
1081 }
1082#ifdef DEBUG_SRC
1083 printf("cleaning %lx: ", (unsigned long) l);
1084 Lst_ForEach(l, PrintAddr, (void *) 0);
1085 printf("\n");
1086#endif
1087
1088
1089 while ((ln = Lst_Next (l)) != NULL) {
1090 s = (Src *) Lst_Datum (ln);
1091 if (s->children == 0) {
1092 free (s->file);
1093 if (!s->parent)
1094 free(s->pref);
1095 else {
1096#ifdef DEBUG_SRC
1097 LstNode ln = Lst_Member(s->parent->cp, (void *)s);
1098 if (ln != NULL)
1099 Lst_Remove(s->parent->cp, ln);
1100#endif
1101 --s->parent->children;
1102 }
1103#ifdef DEBUG_SRC
1104 printf("free: [l=%x] p=%x %d\n", l, s, s->children);
1105 Lst_Destroy(s->cp, NOFREE);
1106#endif
1107 Lst_Remove(l, ln);
1108 free (s);
1109 t |= 1;
1110 Lst_Close(l);
1111 return TRUE;
1112 }
1113#ifdef DEBUG_SRC
1114 else {
1115 printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
1116 Lst_ForEach(s->cp, PrintAddr, (void *) 0);
1117 printf("\n");
1118 }
1119#endif
1120 }
1121
1122 Lst_Close(l);
1123
1124 return t;
1125}
1126
1127/*-
1128 *-----------------------------------------------------------------------
1129 * SuffFindThem --
1130 * Find the first existing file/target in the list srcs
1131 *
1132 * Results:
1133 * The lowest structure in the chain of transformations
1134 *
1135 * Side Effects:
1136 * None
1137 *-----------------------------------------------------------------------
1138 */
1139static Src *
1140SuffFindThem (srcs, slst)
1141 Lst srcs; /* list of Src structures to search through */
1142 Lst slst;
1143{
1144 Src *s; /* current Src */
1145 Src *rs; /* returned Src */
1146 char *ptr;
1147
1148 rs = (Src *) NULL;
1149
1150 while (!Lst_IsEmpty (srcs)) {
1151 s = (Src *) Lst_DeQueue (srcs);
1152
680 }
681
682 return(dummy ? 0 : 0);
683}
684
685/*-
686 *-----------------------------------------------------------------------
687 * SuffRebuildGraph --
688 * Called from Suff_AddSuffix via Lst_ForEach to search through the
689 * list of existing transformation rules and rebuild the transformation
690 * graph when it has been destroyed by Suff_ClearSuffixes. If the
691 * given rule is a transformation involving this suffix and another,
692 * existing suffix, the proper relationship is established between
693 * the two.
694 *
695 * Results:
696 * Always 0.
697 *
698 * Side Effects:
699 * The appropriate links will be made between this suffix and
700 * others if transformation rules exist for it.
701 *
702 *-----------------------------------------------------------------------
703 */
704static int
705SuffRebuildGraph(transformp, sp)
706 void * transformp; /* Transformation to test */
707 void * sp; /* Suffix to rebuild */
708{
709 GNode *transform = (GNode *) transformp;
710 Suff *s = (Suff *) sp;
711 char *cp;
712 LstNode ln;
713 Suff *s2 = NULL;
714
715 /*
716 * First see if it is a transformation from this suffix.
717 */
718 cp = SuffStrIsPrefix(s->name, transform->name);
719 if (cp != (char *)NULL) {
720 if (cp[0] == '\0') /* null rule */
721 s2 = suffNull;
722 else {
723 ln = Lst_Find(sufflist, (void *)cp, SuffSuffHasNameP);
724 if (ln != NULL)
725 s2 = (Suff *)Lst_Datum(ln);
726 }
727 if (s2 != NULL) {
728 /*
729 * Found target. Link in and return, since it can't be anything
730 * else.
731 */
732 SuffInsert(s2->children, s);
733 SuffInsert(s->parents, s2);
734 return(0);
735 }
736 }
737
738 /*
739 * Not from, maybe to?
740 */
741 cp = SuffSuffIsSuffix(s, transform->name + strlen(transform->name));
742 if (cp != (char *)NULL) {
743 /*
744 * Null-terminate the source suffix in order to find it.
745 */
746 cp[1] = '\0';
747 ln = Lst_Find(sufflist, (void *)transform->name, SuffSuffHasNameP);
748 /*
749 * Replace the start of the target suffix
750 */
751 cp[1] = s->name[0];
752 if (ln != NULL) {
753 /*
754 * Found it -- establish the proper relationship
755 */
756 s2 = (Suff *)Lst_Datum(ln);
757 SuffInsert(s->children, s2);
758 SuffInsert(s2->parents, s);
759 }
760 }
761 return(0);
762}
763
764/*-
765 *-----------------------------------------------------------------------
766 * Suff_AddSuffix --
767 * Add the suffix in string to the end of the list of known suffixes.
768 * Should we restructure the suffix graph? Make doesn't...
769 *
770 * Results:
771 * None
772 *
773 * Side Effects:
774 * A GNode is created for the suffix and a Suff structure is created and
775 * added to the suffixes list unless the suffix was already known.
776 *-----------------------------------------------------------------------
777 */
778void
779Suff_AddSuffix (str)
780 char *str; /* the name of the suffix to add */
781{
782 Suff *s; /* new suffix descriptor */
783 LstNode ln;
784
785 ln = Lst_Find (sufflist, (void *)str, SuffSuffHasNameP);
786 if (ln == NULL) {
787 s = (Suff *) emalloc (sizeof (Suff));
788
789 s->name = estrdup (str);
790 s->nameLen = strlen (s->name);
791 s->searchPath = Lst_Init (FALSE);
792 s->children = Lst_Init (FALSE);
793 s->parents = Lst_Init (FALSE);
794 s->ref = Lst_Init (FALSE);
795 s->sNum = sNum++;
796 s->flags = 0;
797 s->refCount = 0;
798
799 (void)Lst_AtEnd (sufflist, (void *)s);
800 /*
801 * Look for any existing transformations from or to this suffix.
802 * XXX: Only do this after a Suff_ClearSuffixes?
803 */
804 Lst_ForEach (transforms, SuffRebuildGraph, (void *)s);
805 }
806}
807
808/*-
809 *-----------------------------------------------------------------------
810 * Suff_GetPath --
811 * Return the search path for the given suffix, if it's defined.
812 *
813 * Results:
814 * The searchPath for the desired suffix or NULL if the suffix isn't
815 * defined.
816 *
817 * Side Effects:
818 * None
819 *-----------------------------------------------------------------------
820 */
821Lst
822Suff_GetPath (sname)
823 char *sname;
824{
825 LstNode ln;
826 Suff *s;
827
828 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
829 if (ln == NULL) {
830 return (NULL);
831 } else {
832 s = (Suff *) Lst_Datum (ln);
833 return (s->searchPath);
834 }
835}
836
837/*-
838 *-----------------------------------------------------------------------
839 * Suff_DoPaths --
840 * Extend the search paths for all suffixes to include the default
841 * search path.
842 *
843 * Results:
844 * None.
845 *
846 * Side Effects:
847 * The searchPath field of all the suffixes is extended by the
848 * directories in dirSearchPath. If paths were specified for the
849 * ".h" suffix, the directories are stuffed into a global variable
850 * called ".INCLUDES" with each directory preceded by a -I. The same
851 * is done for the ".a" suffix, except the variable is called
852 * ".LIBS" and the flag is -L.
853 *-----------------------------------------------------------------------
854 */
855void
856Suff_DoPaths()
857{
858 Suff *s;
859 LstNode ln;
860 char *ptr;
861 Lst inIncludes; /* Cumulative .INCLUDES path */
862 Lst inLibs; /* Cumulative .LIBS path */
863
864 if (Lst_Open (sufflist) == FAILURE) {
865 return;
866 }
867
868 inIncludes = Lst_Init(FALSE);
869 inLibs = Lst_Init(FALSE);
870
871 while ((ln = Lst_Next (sufflist)) != NULL) {
872 s = (Suff *) Lst_Datum (ln);
873 if (!Lst_IsEmpty (s->searchPath)) {
874#ifdef INCLUDES
875 if (s->flags & SUFF_INCLUDE) {
876 Dir_Concat(inIncludes, s->searchPath);
877 }
878#endif /* INCLUDES */
879#ifdef LIBRARIES
880 if (s->flags & SUFF_LIBRARY) {
881 Dir_Concat(inLibs, s->searchPath);
882 }
883#endif /* LIBRARIES */
884 Dir_Concat(s->searchPath, dirSearchPath);
885 } else {
886 Lst_Destroy (s->searchPath, Dir_Destroy);
887 s->searchPath = Lst_Duplicate(dirSearchPath, Dir_CopyDir);
888 }
889 }
890
891 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);
892 free(ptr);
893 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
894 free(ptr);
895
896 Lst_Destroy(inIncludes, Dir_Destroy);
897 Lst_Destroy(inLibs, Dir_Destroy);
898
899 Lst_Close (sufflist);
900}
901
902/*-
903 *-----------------------------------------------------------------------
904 * Suff_AddInclude --
905 * Add the given suffix as a type of file which gets included.
906 * Called from the parse module when a .INCLUDES line is parsed.
907 * The suffix must have already been defined.
908 *
909 * Results:
910 * None.
911 *
912 * Side Effects:
913 * The SUFF_INCLUDE bit is set in the suffix's flags field
914 *
915 *-----------------------------------------------------------------------
916 */
917void
918Suff_AddInclude (sname)
919 char *sname; /* Name of suffix to mark */
920{
921 LstNode ln;
922 Suff *s;
923
924 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
925 if (ln != NULL) {
926 s = (Suff *) Lst_Datum (ln);
927 s->flags |= SUFF_INCLUDE;
928 }
929}
930
931/*-
932 *-----------------------------------------------------------------------
933 * Suff_AddLib --
934 * Add the given suffix as a type of file which is a library.
935 * Called from the parse module when parsing a .LIBS line. The
936 * suffix must have been defined via .SUFFIXES before this is
937 * called.
938 *
939 * Results:
940 * None.
941 *
942 * Side Effects:
943 * The SUFF_LIBRARY bit is set in the suffix's flags field
944 *
945 *-----------------------------------------------------------------------
946 */
947void
948Suff_AddLib (sname)
949 char *sname; /* Name of suffix to mark */
950{
951 LstNode ln;
952 Suff *s;
953
954 ln = Lst_Find (sufflist, (void *)sname, SuffSuffHasNameP);
955 if (ln != NULL) {
956 s = (Suff *) Lst_Datum (ln);
957 s->flags |= SUFF_LIBRARY;
958 }
959}
960
961 /********** Implicit Source Search Functions *********/
962
963/*-
964 *-----------------------------------------------------------------------
965 * SuffAddSrc --
966 * Add a suffix as a Src structure to the given list with its parent
967 * being the given Src structure. If the suffix is the null suffix,
968 * the prefix is used unaltered as the file name in the Src structure.
969 *
970 * Results:
971 * always returns 0
972 *
973 * Side Effects:
974 * A Src structure is created and tacked onto the end of the list
975 *-----------------------------------------------------------------------
976 */
977static int
978SuffAddSrc (sp, lsp)
979 void * sp; /* suffix for which to create a Src structure */
980 void * lsp; /* list and parent for the new Src */
981{
982 Suff *s = (Suff *) sp;
983 LstSrc *ls = (LstSrc *) lsp;
984 Src *s2; /* new Src structure */
985 Src *targ; /* Target structure */
986
987 targ = ls->s;
988
989 if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
990 /*
991 * If the suffix has been marked as the NULL suffix, also create a Src
992 * structure for a file with no suffix attached. Two birds, and all
993 * that...
994 */
995 s2 = (Src *) emalloc (sizeof (Src));
996 s2->file = estrdup(targ->pref);
997 s2->pref = targ->pref;
998 s2->parent = targ;
999 s2->node = NULL;
1000 s2->suff = s;
1001 s->refCount++;
1002 s2->children = 0;
1003 targ->children += 1;
1004 (void)Lst_AtEnd (ls->l, (void *)s2);
1005#ifdef DEBUG_SRC
1006 s2->cp = Lst_Init(FALSE);
1007 Lst_AtEnd(targ->cp, (void *) s2);
1008 printf("1 add %x %x to %x:", targ, s2, ls->l);
1009 Lst_ForEach(ls->l, PrintAddr, (void *) 0);
1010 printf("\n");
1011#endif
1012 }
1013 s2 = (Src *) emalloc (sizeof (Src));
1014 s2->file = str_concat (targ->pref, s->name, 0);
1015 s2->pref = targ->pref;
1016 s2->parent = targ;
1017 s2->node = NULL;
1018 s2->suff = s;
1019 s->refCount++;
1020 s2->children = 0;
1021 targ->children += 1;
1022 (void)Lst_AtEnd (ls->l, (void *)s2);
1023#ifdef DEBUG_SRC
1024 s2->cp = Lst_Init(FALSE);
1025 Lst_AtEnd(targ->cp, (void *) s2);
1026 printf("2 add %x %x to %x:", targ, s2, ls->l);
1027 Lst_ForEach(ls->l, PrintAddr, (void *) 0);
1028 printf("\n");
1029#endif
1030
1031 return(0);
1032}
1033
1034/*-
1035 *-----------------------------------------------------------------------
1036 * SuffAddLevel --
1037 * Add all the children of targ as Src structures to the given list
1038 *
1039 * Results:
1040 * None
1041 *
1042 * Side Effects:
1043 * Lots of structures are created and added to the list
1044 *-----------------------------------------------------------------------
1045 */
1046static void
1047SuffAddLevel (l, targ)
1048 Lst l; /* list to which to add the new level */
1049 Src *targ; /* Src structure to use as the parent */
1050{
1051 LstSrc ls;
1052
1053 ls.s = targ;
1054 ls.l = l;
1055
1056 Lst_ForEach (targ->suff->children, SuffAddSrc, (void *)&ls);
1057}
1058
1059/*-
1060 *----------------------------------------------------------------------
1061 * SuffRemoveSrc --
1062 * Free all src structures in list that don't have a reference count
1063 *
1064 * Results:
1065 * Ture if an src was removed
1066 *
1067 * Side Effects:
1068 * The memory is free'd.
1069 *----------------------------------------------------------------------
1070 */
1071static int
1072SuffRemoveSrc (l)
1073 Lst l;
1074{
1075 LstNode ln;
1076 Src *s;
1077 int t = 0;
1078
1079 if (Lst_Open (l) == FAILURE) {
1080 return 0;
1081 }
1082#ifdef DEBUG_SRC
1083 printf("cleaning %lx: ", (unsigned long) l);
1084 Lst_ForEach(l, PrintAddr, (void *) 0);
1085 printf("\n");
1086#endif
1087
1088
1089 while ((ln = Lst_Next (l)) != NULL) {
1090 s = (Src *) Lst_Datum (ln);
1091 if (s->children == 0) {
1092 free (s->file);
1093 if (!s->parent)
1094 free(s->pref);
1095 else {
1096#ifdef DEBUG_SRC
1097 LstNode ln = Lst_Member(s->parent->cp, (void *)s);
1098 if (ln != NULL)
1099 Lst_Remove(s->parent->cp, ln);
1100#endif
1101 --s->parent->children;
1102 }
1103#ifdef DEBUG_SRC
1104 printf("free: [l=%x] p=%x %d\n", l, s, s->children);
1105 Lst_Destroy(s->cp, NOFREE);
1106#endif
1107 Lst_Remove(l, ln);
1108 free (s);
1109 t |= 1;
1110 Lst_Close(l);
1111 return TRUE;
1112 }
1113#ifdef DEBUG_SRC
1114 else {
1115 printf("keep: [l=%x] p=%x %d: ", l, s, s->children);
1116 Lst_ForEach(s->cp, PrintAddr, (void *) 0);
1117 printf("\n");
1118 }
1119#endif
1120 }
1121
1122 Lst_Close(l);
1123
1124 return t;
1125}
1126
1127/*-
1128 *-----------------------------------------------------------------------
1129 * SuffFindThem --
1130 * Find the first existing file/target in the list srcs
1131 *
1132 * Results:
1133 * The lowest structure in the chain of transformations
1134 *
1135 * Side Effects:
1136 * None
1137 *-----------------------------------------------------------------------
1138 */
1139static Src *
1140SuffFindThem (srcs, slst)
1141 Lst srcs; /* list of Src structures to search through */
1142 Lst slst;
1143{
1144 Src *s; /* current Src */
1145 Src *rs; /* returned Src */
1146 char *ptr;
1147
1148 rs = (Src *) NULL;
1149
1150 while (!Lst_IsEmpty (srcs)) {
1151 s = (Src *) Lst_DeQueue (srcs);
1152
1153 DEBUGF(SUFF, "\ttrying %s...", s->file);
1153 DEBUGF(SUFF, ("\ttrying %s...", s->file));
1154
1155 /*
1156 * A file is considered to exist if either a node exists in the
1157 * graph for it or the file actually exists.
1158 */
1159 if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
1160#ifdef DEBUG_SRC
1161 printf("remove %x from %x\n", s, srcs);
1162#endif
1163 rs = s;
1164 break;
1165 }
1166
1167 if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {
1168 rs = s;
1169#ifdef DEBUG_SRC
1170 printf("remove %x from %x\n", s, srcs);
1171#endif
1172 free(ptr);
1173 break;
1174 }
1175
1154
1155 /*
1156 * A file is considered to exist if either a node exists in the
1157 * graph for it or the file actually exists.
1158 */
1159 if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
1160#ifdef DEBUG_SRC
1161 printf("remove %x from %x\n", s, srcs);
1162#endif
1163 rs = s;
1164 break;
1165 }
1166
1167 if ((ptr = Dir_FindFile (s->file, s->suff->searchPath)) != NULL) {
1168 rs = s;
1169#ifdef DEBUG_SRC
1170 printf("remove %x from %x\n", s, srcs);
1171#endif
1172 free(ptr);
1173 break;
1174 }
1175
1176 DEBUGF(SUFF, "not there\n");
1176 DEBUGF(SUFF, ("not there\n"));
1177
1178 SuffAddLevel (srcs, s);
1179 Lst_AtEnd(slst, (void *) s);
1180 }
1181
1182 if (rs) {
1177
1178 SuffAddLevel (srcs, s);
1179 Lst_AtEnd(slst, (void *) s);
1180 }
1181
1182 if (rs) {
1183 DEBUGF(SUFF, "got it\n");
1183 DEBUGF(SUFF, ("got it\n"));
1184 }
1185 return (rs);
1186}
1187
1188/*-
1189 *-----------------------------------------------------------------------
1190 * SuffFindCmds --
1191 * See if any of the children of the target in the Src structure is
1192 * one from which the target can be transformed. If there is one,
1193 * a Src structure is put together for it and returned.
1194 *
1195 * Results:
1196 * The Src structure of the "winning" child, or NULL if no such beast.
1197 *
1198 * Side Effects:
1199 * A Src structure may be allocated.
1200 *
1201 *-----------------------------------------------------------------------
1202 */
1203static Src *
1204SuffFindCmds (targ, slst)
1205 Src *targ; /* Src structure to play with */
1206 Lst slst;
1207{
1208 LstNode ln; /* General-purpose list node */
1209 GNode *t, /* Target GNode */
1210 *s; /* Source GNode */
1211 int prefLen;/* The length of the defined prefix */
1212 Suff *suff; /* Suffix on matching beastie */
1213 Src *ret; /* Return value */
1214 char *cp;
1215
1216 t = targ->node;
1217 (void) Lst_Open (t->children);
1218 prefLen = strlen (targ->pref);
1219
1220 while ((ln = Lst_Next (t->children)) != NULL) {
1221 s = (GNode *)Lst_Datum (ln);
1222
1223 cp = strrchr (s->name, '/');
1224 if (cp == (char *)NULL) {
1225 cp = s->name;
1226 } else {
1227 cp++;
1228 }
1229 if (strncmp (cp, targ->pref, prefLen) == 0) {
1230 /*
1231 * The node matches the prefix ok, see if it has a known
1232 * suffix.
1233 */
1234 ln = Lst_Find (sufflist, (void *)&cp[prefLen],
1235 SuffSuffHasNameP);
1236 if (ln != NULL) {
1237 /*
1238 * It even has a known suffix, see if there's a transformation
1239 * defined between the node's suffix and the target's suffix.
1240 *
1241 * XXX: Handle multi-stage transformations here, too.
1242 */
1243 suff = (Suff *)Lst_Datum (ln);
1244
1245 if (Lst_Member (suff->parents,
1246 (void *)targ->suff) != NULL)
1247 {
1248 /*
1249 * Hot Damn! Create a new Src structure to describe
1250 * this transformation (making sure to duplicate the
1251 * source node's name so Suff_FindDeps can free it
1252 * again (ick)), and return the new structure.
1253 */
1254 ret = (Src *)emalloc (sizeof (Src));
1255 ret->file = estrdup(s->name);
1256 ret->pref = targ->pref;
1257 ret->suff = suff;
1258 suff->refCount++;
1259 ret->parent = targ;
1260 ret->node = s;
1261 ret->children = 0;
1262 targ->children += 1;
1263#ifdef DEBUG_SRC
1264 ret->cp = Lst_Init(FALSE);
1265 printf("3 add %x %x\n", targ, ret);
1266 Lst_AtEnd(targ->cp, (void *) ret);
1267#endif
1268 Lst_AtEnd(slst, (void *) ret);
1184 }
1185 return (rs);
1186}
1187
1188/*-
1189 *-----------------------------------------------------------------------
1190 * SuffFindCmds --
1191 * See if any of the children of the target in the Src structure is
1192 * one from which the target can be transformed. If there is one,
1193 * a Src structure is put together for it and returned.
1194 *
1195 * Results:
1196 * The Src structure of the "winning" child, or NULL if no such beast.
1197 *
1198 * Side Effects:
1199 * A Src structure may be allocated.
1200 *
1201 *-----------------------------------------------------------------------
1202 */
1203static Src *
1204SuffFindCmds (targ, slst)
1205 Src *targ; /* Src structure to play with */
1206 Lst slst;
1207{
1208 LstNode ln; /* General-purpose list node */
1209 GNode *t, /* Target GNode */
1210 *s; /* Source GNode */
1211 int prefLen;/* The length of the defined prefix */
1212 Suff *suff; /* Suffix on matching beastie */
1213 Src *ret; /* Return value */
1214 char *cp;
1215
1216 t = targ->node;
1217 (void) Lst_Open (t->children);
1218 prefLen = strlen (targ->pref);
1219
1220 while ((ln = Lst_Next (t->children)) != NULL) {
1221 s = (GNode *)Lst_Datum (ln);
1222
1223 cp = strrchr (s->name, '/');
1224 if (cp == (char *)NULL) {
1225 cp = s->name;
1226 } else {
1227 cp++;
1228 }
1229 if (strncmp (cp, targ->pref, prefLen) == 0) {
1230 /*
1231 * The node matches the prefix ok, see if it has a known
1232 * suffix.
1233 */
1234 ln = Lst_Find (sufflist, (void *)&cp[prefLen],
1235 SuffSuffHasNameP);
1236 if (ln != NULL) {
1237 /*
1238 * It even has a known suffix, see if there's a transformation
1239 * defined between the node's suffix and the target's suffix.
1240 *
1241 * XXX: Handle multi-stage transformations here, too.
1242 */
1243 suff = (Suff *)Lst_Datum (ln);
1244
1245 if (Lst_Member (suff->parents,
1246 (void *)targ->suff) != NULL)
1247 {
1248 /*
1249 * Hot Damn! Create a new Src structure to describe
1250 * this transformation (making sure to duplicate the
1251 * source node's name so Suff_FindDeps can free it
1252 * again (ick)), and return the new structure.
1253 */
1254 ret = (Src *)emalloc (sizeof (Src));
1255 ret->file = estrdup(s->name);
1256 ret->pref = targ->pref;
1257 ret->suff = suff;
1258 suff->refCount++;
1259 ret->parent = targ;
1260 ret->node = s;
1261 ret->children = 0;
1262 targ->children += 1;
1263#ifdef DEBUG_SRC
1264 ret->cp = Lst_Init(FALSE);
1265 printf("3 add %x %x\n", targ, ret);
1266 Lst_AtEnd(targ->cp, (void *) ret);
1267#endif
1268 Lst_AtEnd(slst, (void *) ret);
1269 DEBUGF(SUFF, "\tusing existing source %s\n", s->name);
1269 DEBUGF(SUFF, ("\tusing existing source %s\n", s->name));
1270 return (ret);
1271 }
1272 }
1273 }
1274 }
1275 Lst_Close (t->children);
1276 return ((Src *)NULL);
1277}
1278
1279/*-
1280 *-----------------------------------------------------------------------
1281 * SuffExpandChildren --
1282 * Expand the names of any children of a given node that contain
1283 * variable invocations or file wildcards into actual targets.
1284 *
1285 * Results:
1286 * === 0 (continue)
1287 *
1288 * Side Effects:
1289 * The expanded node is removed from the parent's list of children,
1290 * and the parent's unmade counter is decremented, but other nodes
1291 * may be added.
1292 *
1293 *-----------------------------------------------------------------------
1294 */
1295static int
1296SuffExpandChildren(cgnp, pgnp)
1297 void * cgnp; /* Child to examine */
1298 void * pgnp; /* Parent node being processed */
1299{
1300 GNode *cgn = (GNode *) cgnp;
1301 GNode *pgn = (GNode *) pgnp;
1302 GNode *gn; /* New source 8) */
1303 LstNode prevLN; /* Node after which new source should be put */
1304 LstNode ln; /* List element for old source */
1305 char *cp; /* Expanded value */
1306
1307 /*
1308 * New nodes effectively take the place of the child, so place them
1309 * after the child
1310 */
1311 prevLN = Lst_Member(pgn->children, (void *)cgn);
1312
1313 /*
1314 * First do variable expansion -- this takes precedence over
1315 * wildcard expansion. If the result contains wildcards, they'll be gotten
1316 * to later since the resulting words are tacked on to the end of
1317 * the children list.
1318 */
1319 if (strchr(cgn->name, '$') != (char *)NULL) {
1270 return (ret);
1271 }
1272 }
1273 }
1274 }
1275 Lst_Close (t->children);
1276 return ((Src *)NULL);
1277}
1278
1279/*-
1280 *-----------------------------------------------------------------------
1281 * SuffExpandChildren --
1282 * Expand the names of any children of a given node that contain
1283 * variable invocations or file wildcards into actual targets.
1284 *
1285 * Results:
1286 * === 0 (continue)
1287 *
1288 * Side Effects:
1289 * The expanded node is removed from the parent's list of children,
1290 * and the parent's unmade counter is decremented, but other nodes
1291 * may be added.
1292 *
1293 *-----------------------------------------------------------------------
1294 */
1295static int
1296SuffExpandChildren(cgnp, pgnp)
1297 void * cgnp; /* Child to examine */
1298 void * pgnp; /* Parent node being processed */
1299{
1300 GNode *cgn = (GNode *) cgnp;
1301 GNode *pgn = (GNode *) pgnp;
1302 GNode *gn; /* New source 8) */
1303 LstNode prevLN; /* Node after which new source should be put */
1304 LstNode ln; /* List element for old source */
1305 char *cp; /* Expanded value */
1306
1307 /*
1308 * New nodes effectively take the place of the child, so place them
1309 * after the child
1310 */
1311 prevLN = Lst_Member(pgn->children, (void *)cgn);
1312
1313 /*
1314 * First do variable expansion -- this takes precedence over
1315 * wildcard expansion. If the result contains wildcards, they'll be gotten
1316 * to later since the resulting words are tacked on to the end of
1317 * the children list.
1318 */
1319 if (strchr(cgn->name, '$') != (char *)NULL) {
1320 DEBUGF(SUFF, "Expanding \"%s\"...", cgn->name);
1320 DEBUGF(SUFF, ("Expanding \"%s\"...", cgn->name));
1321 cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
1322
1323 if (cp != (char *)NULL) {
1324 Lst members = Lst_Init(FALSE);
1325
1326 if (cgn->type & OP_ARCHV) {
1327 /*
1328 * Node was an archive(member) target, so we want to call
1329 * on the Arch module to find the nodes for us, expanding
1330 * variables in the parent's context.
1331 */
1332 char *sacrifice = cp;
1333
1334 (void)Arch_ParseArchive(&sacrifice, members, pgn);
1335 } else {
1336 /*
1337 * Break the result into a vector of strings whose nodes
1338 * we can find, then add those nodes to the members list.
1339 * Unfortunately, we can't use brk_string b/c it
1340 * doesn't understand about variable specifications with
1341 * spaces in them...
1342 */
1343 char *start;
1344 char *initcp = cp; /* For freeing... */
1345
1346 for (start = cp; *start == ' ' || *start == '\t'; start++)
1347 continue;
1348 for (cp = start; *cp != '\0'; cp++) {
1349 if (*cp == ' ' || *cp == '\t') {
1350 /*
1351 * White-space -- terminate element, find the node,
1352 * add it, skip any further spaces.
1353 */
1354 *cp++ = '\0';
1355 gn = Targ_FindNode(start, TARG_CREATE);
1356 (void)Lst_AtEnd(members, (void *)gn);
1357 while (*cp == ' ' || *cp == '\t') {
1358 cp++;
1359 }
1360 /*
1361 * Adjust cp for increment at start of loop, but
1362 * set start to first non-space.
1363 */
1364 start = cp--;
1365 } else if (*cp == '$') {
1366 /*
1367 * Start of a variable spec -- contact variable module
1368 * to find the end so we can skip over it.
1369 */
1370 char *junk;
1371 int len;
1372 Boolean doFree;
1373
1374 junk = Var_Parse(cp, pgn, TRUE, &len, &doFree);
1375 if (junk != var_Error) {
1376 cp += len - 1;
1377 }
1378
1379 if (doFree) {
1380 free(junk);
1381 }
1382 } else if (*cp == '\\' && *cp != '\0') {
1383 /*
1384 * Escaped something -- skip over it
1385 */
1386 cp++;
1387 }
1388 }
1389
1390 if (cp != start) {
1391 /*
1392 * Stuff left over -- add it to the list too
1393 */
1394 gn = Targ_FindNode(start, TARG_CREATE);
1395 (void)Lst_AtEnd(members, (void *)gn);
1396 }
1397 /*
1398 * Point cp back at the beginning again so the variable value
1399 * can be freed.
1400 */
1401 cp = initcp;
1402 }
1403 /*
1404 * Add all elements of the members list to the parent node.
1405 */
1406 while(!Lst_IsEmpty(members)) {
1407 gn = (GNode *)Lst_DeQueue(members);
1408
1321 cp = Var_Subst(NULL, cgn->name, pgn, TRUE);
1322
1323 if (cp != (char *)NULL) {
1324 Lst members = Lst_Init(FALSE);
1325
1326 if (cgn->type & OP_ARCHV) {
1327 /*
1328 * Node was an archive(member) target, so we want to call
1329 * on the Arch module to find the nodes for us, expanding
1330 * variables in the parent's context.
1331 */
1332 char *sacrifice = cp;
1333
1334 (void)Arch_ParseArchive(&sacrifice, members, pgn);
1335 } else {
1336 /*
1337 * Break the result into a vector of strings whose nodes
1338 * we can find, then add those nodes to the members list.
1339 * Unfortunately, we can't use brk_string b/c it
1340 * doesn't understand about variable specifications with
1341 * spaces in them...
1342 */
1343 char *start;
1344 char *initcp = cp; /* For freeing... */
1345
1346 for (start = cp; *start == ' ' || *start == '\t'; start++)
1347 continue;
1348 for (cp = start; *cp != '\0'; cp++) {
1349 if (*cp == ' ' || *cp == '\t') {
1350 /*
1351 * White-space -- terminate element, find the node,
1352 * add it, skip any further spaces.
1353 */
1354 *cp++ = '\0';
1355 gn = Targ_FindNode(start, TARG_CREATE);
1356 (void)Lst_AtEnd(members, (void *)gn);
1357 while (*cp == ' ' || *cp == '\t') {
1358 cp++;
1359 }
1360 /*
1361 * Adjust cp for increment at start of loop, but
1362 * set start to first non-space.
1363 */
1364 start = cp--;
1365 } else if (*cp == '$') {
1366 /*
1367 * Start of a variable spec -- contact variable module
1368 * to find the end so we can skip over it.
1369 */
1370 char *junk;
1371 int len;
1372 Boolean doFree;
1373
1374 junk = Var_Parse(cp, pgn, TRUE, &len, &doFree);
1375 if (junk != var_Error) {
1376 cp += len - 1;
1377 }
1378
1379 if (doFree) {
1380 free(junk);
1381 }
1382 } else if (*cp == '\\' && *cp != '\0') {
1383 /*
1384 * Escaped something -- skip over it
1385 */
1386 cp++;
1387 }
1388 }
1389
1390 if (cp != start) {
1391 /*
1392 * Stuff left over -- add it to the list too
1393 */
1394 gn = Targ_FindNode(start, TARG_CREATE);
1395 (void)Lst_AtEnd(members, (void *)gn);
1396 }
1397 /*
1398 * Point cp back at the beginning again so the variable value
1399 * can be freed.
1400 */
1401 cp = initcp;
1402 }
1403 /*
1404 * Add all elements of the members list to the parent node.
1405 */
1406 while(!Lst_IsEmpty(members)) {
1407 gn = (GNode *)Lst_DeQueue(members);
1408
1409 DEBUGF(SUFF, "%s...", gn->name);
1409 DEBUGF(SUFF, ("%s...", gn->name));
1410 if (Lst_Member(pgn->children, (void *)gn) == NULL) {
1411 (void)Lst_Append(pgn->children, prevLN, (void *)gn);
1412 prevLN = Lst_Succ(prevLN);
1413 (void)Lst_AtEnd(gn->parents, (void *)pgn);
1414 pgn->unmade++;
1415 }
1416 }
1417 Lst_Destroy(members, NOFREE);
1418 /*
1419 * Free the result
1420 */
1421 free((char *)cp);
1422 }
1423 /*
1424 * Now the source is expanded, remove it from the list of children to
1425 * keep it from being processed.
1426 */
1427 ln = Lst_Member(pgn->children, (void *)cgn);
1428 pgn->unmade--;
1429 Lst_Remove(pgn->children, ln);
1410 if (Lst_Member(pgn->children, (void *)gn) == NULL) {
1411 (void)Lst_Append(pgn->children, prevLN, (void *)gn);
1412 prevLN = Lst_Succ(prevLN);
1413 (void)Lst_AtEnd(gn->parents, (void *)pgn);
1414 pgn->unmade++;
1415 }
1416 }
1417 Lst_Destroy(members, NOFREE);
1418 /*
1419 * Free the result
1420 */
1421 free((char *)cp);
1422 }
1423 /*
1424 * Now the source is expanded, remove it from the list of children to
1425 * keep it from being processed.
1426 */
1427 ln = Lst_Member(pgn->children, (void *)cgn);
1428 pgn->unmade--;
1429 Lst_Remove(pgn->children, ln);
1430 DEBUGF(SUFF, "\n");
1430 DEBUGF(SUFF, ("\n"));
1431 } else if (Dir_HasWildcards(cgn->name)) {
1432 Lst exp; /* List of expansions */
1433 Lst path; /* Search path along which to expand */
1434
1435 /*
1436 * Find a path along which to expand the word.
1437 *
1438 * If the word has a known suffix, use that path.
1439 * If it has no known suffix and we're allowed to use the null
1440 * suffix, use its path.
1441 * Else use the default system search path.
1442 */
1443 cp = cgn->name + strlen(cgn->name);
1444 ln = Lst_Find(sufflist, (void *)cp, SuffSuffIsSuffixP);
1445
1431 } else if (Dir_HasWildcards(cgn->name)) {
1432 Lst exp; /* List of expansions */
1433 Lst path; /* Search path along which to expand */
1434
1435 /*
1436 * Find a path along which to expand the word.
1437 *
1438 * If the word has a known suffix, use that path.
1439 * If it has no known suffix and we're allowed to use the null
1440 * suffix, use its path.
1441 * Else use the default system search path.
1442 */
1443 cp = cgn->name + strlen(cgn->name);
1444 ln = Lst_Find(sufflist, (void *)cp, SuffSuffIsSuffixP);
1445
1446 DEBUGF(SUFF, "Wildcard expanding \"%s\"...", cgn->name);
1446 DEBUGF(SUFF, ("Wildcard expanding \"%s\"...", cgn->name));
1447
1448 if (ln != NULL) {
1449 Suff *s = (Suff *)Lst_Datum(ln);
1450
1447
1448 if (ln != NULL) {
1449 Suff *s = (Suff *)Lst_Datum(ln);
1450
1451 DEBUGF(SUFF, "suffix is \"%s\"...", s->name);
1451 DEBUGF(SUFF, ("suffix is \"%s\"...", s->name));
1452 path = s->searchPath;
1453 } else {
1454 /*
1455 * Use default search path
1456 */
1457 path = dirSearchPath;
1458 }
1459
1460 /*
1461 * Expand the word along the chosen path
1462 */
1463 exp = Lst_Init(FALSE);
1464 Dir_Expand(cgn->name, path, exp);
1465
1466 while (!Lst_IsEmpty(exp)) {
1467 /*
1468 * Fetch next expansion off the list and find its GNode
1469 */
1470 cp = (char *)Lst_DeQueue(exp);
1471
1452 path = s->searchPath;
1453 } else {
1454 /*
1455 * Use default search path
1456 */
1457 path = dirSearchPath;
1458 }
1459
1460 /*
1461 * Expand the word along the chosen path
1462 */
1463 exp = Lst_Init(FALSE);
1464 Dir_Expand(cgn->name, path, exp);
1465
1466 while (!Lst_IsEmpty(exp)) {
1467 /*
1468 * Fetch next expansion off the list and find its GNode
1469 */
1470 cp = (char *)Lst_DeQueue(exp);
1471
1472 DEBUGF(SUFF, "%s...", cp);
1472 DEBUGF(SUFF, ("%s...", cp));
1473 gn = Targ_FindNode(cp, TARG_CREATE);
1474
1475 /*
1476 * If gn isn't already a child of the parent, make it so and
1477 * up the parent's count of unmade children.
1478 */
1479 if (Lst_Member(pgn->children, (void *)gn) == NULL) {
1480 (void)Lst_Append(pgn->children, prevLN, (void *)gn);
1481 prevLN = Lst_Succ(prevLN);
1482 (void)Lst_AtEnd(gn->parents, (void *)pgn);
1483 pgn->unmade++;
1484 }
1485 }
1486
1487 /*
1488 * Nuke what's left of the list
1489 */
1490 Lst_Destroy(exp, NOFREE);
1491
1492 /*
1493 * Now the source is expanded, remove it from the list of children to
1494 * keep it from being processed.
1495 */
1496 ln = Lst_Member(pgn->children, (void *)cgn);
1497 pgn->unmade--;
1498 Lst_Remove(pgn->children, ln);
1473 gn = Targ_FindNode(cp, TARG_CREATE);
1474
1475 /*
1476 * If gn isn't already a child of the parent, make it so and
1477 * up the parent's count of unmade children.
1478 */
1479 if (Lst_Member(pgn->children, (void *)gn) == NULL) {
1480 (void)Lst_Append(pgn->children, prevLN, (void *)gn);
1481 prevLN = Lst_Succ(prevLN);
1482 (void)Lst_AtEnd(gn->parents, (void *)pgn);
1483 pgn->unmade++;
1484 }
1485 }
1486
1487 /*
1488 * Nuke what's left of the list
1489 */
1490 Lst_Destroy(exp, NOFREE);
1491
1492 /*
1493 * Now the source is expanded, remove it from the list of children to
1494 * keep it from being processed.
1495 */
1496 ln = Lst_Member(pgn->children, (void *)cgn);
1497 pgn->unmade--;
1498 Lst_Remove(pgn->children, ln);
1499 DEBUGF(SUFF, "\n");
1499 DEBUGF(SUFF, ("\n"));
1500 }
1501
1502 return(0);
1503}
1504
1505/*-
1506 *-----------------------------------------------------------------------
1507 * SuffApplyTransform --
1508 * Apply a transformation rule, given the source and target nodes
1509 * and suffixes.
1510 *
1511 * Results:
1512 * TRUE if successful, FALSE if not.
1513 *
1514 * Side Effects:
1515 * The source and target are linked and the commands from the
1516 * transformation are added to the target node's commands list.
1517 * All attributes but OP_DEPMASK and OP_TRANSFORM are applied
1518 * to the target. The target also inherits all the sources for
1519 * the transformation rule.
1520 *
1521 *-----------------------------------------------------------------------
1522 */
1523static Boolean
1524SuffApplyTransform(tGn, sGn, t, s)
1525 GNode *tGn; /* Target node */
1526 GNode *sGn; /* Source node */
1527 Suff *t; /* Target suffix */
1528 Suff *s; /* Source suffix */
1529{
1530 LstNode ln; /* General node */
1531 char *tname; /* Name of transformation rule */
1532 GNode *gn; /* Node for same */
1533
1534 if (Lst_Member(tGn->children, (void *)sGn) == NULL) {
1535 /*
1536 * Not already linked, so form the proper links between the
1537 * target and source.
1538 */
1539 (void)Lst_AtEnd(tGn->children, (void *)sGn);
1540 (void)Lst_AtEnd(sGn->parents, (void *)tGn);
1541 tGn->unmade += 1;
1542 }
1543
1544 if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1545 /*
1546 * When a :: node is used as the implied source of a node, we have
1547 * to link all its cohorts in as sources as well. Only the initial
1548 * sGn gets the target in its iParents list, however, as that
1549 * will be sufficient to get the .IMPSRC variable set for tGn
1550 */
1551 for (ln=Lst_First(sGn->cohorts); ln != NULL; ln=Lst_Succ(ln)) {
1552 gn = (GNode *)Lst_Datum(ln);
1553
1554 if (Lst_Member(tGn->children, (void *)gn) == NULL) {
1555 /*
1556 * Not already linked, so form the proper links between the
1557 * target and source.
1558 */
1559 (void)Lst_AtEnd(tGn->children, (void *)gn);
1560 (void)Lst_AtEnd(gn->parents, (void *)tGn);
1561 tGn->unmade += 1;
1562 }
1563 }
1564 }
1565 /*
1566 * Locate the transformation rule itself
1567 */
1568 tname = str_concat(s->name, t->name, 0);
1569 ln = Lst_Find(transforms, (void *)tname, SuffGNHasNameP);
1570 free(tname);
1571
1572 if (ln == NULL) {
1573 /*
1574 * Not really such a transformation rule (can happen when we're
1575 * called to link an OP_MEMBER and OP_ARCHV node), so return
1576 * FALSE.
1577 */
1578 return(FALSE);
1579 }
1580
1581 gn = (GNode *)Lst_Datum(ln);
1582
1500 }
1501
1502 return(0);
1503}
1504
1505/*-
1506 *-----------------------------------------------------------------------
1507 * SuffApplyTransform --
1508 * Apply a transformation rule, given the source and target nodes
1509 * and suffixes.
1510 *
1511 * Results:
1512 * TRUE if successful, FALSE if not.
1513 *
1514 * Side Effects:
1515 * The source and target are linked and the commands from the
1516 * transformation are added to the target node's commands list.
1517 * All attributes but OP_DEPMASK and OP_TRANSFORM are applied
1518 * to the target. The target also inherits all the sources for
1519 * the transformation rule.
1520 *
1521 *-----------------------------------------------------------------------
1522 */
1523static Boolean
1524SuffApplyTransform(tGn, sGn, t, s)
1525 GNode *tGn; /* Target node */
1526 GNode *sGn; /* Source node */
1527 Suff *t; /* Target suffix */
1528 Suff *s; /* Source suffix */
1529{
1530 LstNode ln; /* General node */
1531 char *tname; /* Name of transformation rule */
1532 GNode *gn; /* Node for same */
1533
1534 if (Lst_Member(tGn->children, (void *)sGn) == NULL) {
1535 /*
1536 * Not already linked, so form the proper links between the
1537 * target and source.
1538 */
1539 (void)Lst_AtEnd(tGn->children, (void *)sGn);
1540 (void)Lst_AtEnd(sGn->parents, (void *)tGn);
1541 tGn->unmade += 1;
1542 }
1543
1544 if ((sGn->type & OP_OPMASK) == OP_DOUBLEDEP) {
1545 /*
1546 * When a :: node is used as the implied source of a node, we have
1547 * to link all its cohorts in as sources as well. Only the initial
1548 * sGn gets the target in its iParents list, however, as that
1549 * will be sufficient to get the .IMPSRC variable set for tGn
1550 */
1551 for (ln=Lst_First(sGn->cohorts); ln != NULL; ln=Lst_Succ(ln)) {
1552 gn = (GNode *)Lst_Datum(ln);
1553
1554 if (Lst_Member(tGn->children, (void *)gn) == NULL) {
1555 /*
1556 * Not already linked, so form the proper links between the
1557 * target and source.
1558 */
1559 (void)Lst_AtEnd(tGn->children, (void *)gn);
1560 (void)Lst_AtEnd(gn->parents, (void *)tGn);
1561 tGn->unmade += 1;
1562 }
1563 }
1564 }
1565 /*
1566 * Locate the transformation rule itself
1567 */
1568 tname = str_concat(s->name, t->name, 0);
1569 ln = Lst_Find(transforms, (void *)tname, SuffGNHasNameP);
1570 free(tname);
1571
1572 if (ln == NULL) {
1573 /*
1574 * Not really such a transformation rule (can happen when we're
1575 * called to link an OP_MEMBER and OP_ARCHV node), so return
1576 * FALSE.
1577 */
1578 return(FALSE);
1579 }
1580
1581 gn = (GNode *)Lst_Datum(ln);
1582
1583 DEBUGF(SUFF, "\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
1583 DEBUGF(SUFF, ("\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name));
1584
1585 /*
1586 * Record last child for expansion purposes
1587 */
1588 ln = Lst_Last(tGn->children);
1589
1590 /*
1591 * Pass the buck to Make_HandleUse to apply the rule
1592 */
1593 (void)Make_HandleUse(gn, tGn);
1594
1595 /*
1596 * Deal with wildcards and variables in any acquired sources
1597 */
1598 ln = Lst_Succ(ln);
1599 if (ln != NULL) {
1600 Lst_ForEachFrom(tGn->children, ln,
1601 SuffExpandChildren, (void *)tGn);
1602 }
1603
1604 /*
1605 * Keep track of another parent to which this beast is transformed so
1606 * the .IMPSRC variable can be set correctly for the parent.
1607 */
1608 (void)Lst_AtEnd(sGn->iParents, (void *)tGn);
1609
1610 return(TRUE);
1611}
1612
1613
1614/*-
1615 *-----------------------------------------------------------------------
1616 * SuffFindArchiveDeps --
1617 * Locate dependencies for an OP_ARCHV node.
1618 *
1619 * Results:
1620 * None
1621 *
1622 * Side Effects:
1623 * Same as Suff_FindDeps
1624 *
1625 *-----------------------------------------------------------------------
1626 */
1627static void
1628SuffFindArchiveDeps(gn, slst)
1629 GNode *gn; /* Node for which to locate dependencies */
1630 Lst slst;
1631{
1632 char *eoarch; /* End of archive portion */
1633 char *eoname; /* End of member portion */
1634 GNode *mem; /* Node for member */
1635 static char *copy[] = { /* Variables to be copied from the member node */
1636 TARGET, /* Must be first */
1637 PREFIX, /* Must be second */
1638 };
1639 int i; /* Index into copy and vals */
1640 Suff *ms; /* Suffix descriptor for member */
1641 char *name; /* Start of member's name */
1642
1643 /*
1644 * The node is an archive(member) pair. so we must find a
1645 * suffix for both of them.
1646 */
1647 eoarch = strchr (gn->name, '(');
1648 eoname = strchr (eoarch, ')');
1649
1650 *eoname = '\0'; /* Nuke parentheses during suffix search */
1651 *eoarch = '\0'; /* So a suffix can be found */
1652
1653 name = eoarch + 1;
1654
1655 /*
1656 * To simplify things, call Suff_FindDeps recursively on the member now,
1657 * so we can simply compare the member's .PREFIX and .TARGET variables
1658 * to locate its suffix. This allows us to figure out the suffix to
1659 * use for the archive without having to do a quadratic search over the
1660 * suffix list, backtracking for each one...
1661 */
1662 mem = Targ_FindNode(name, TARG_CREATE);
1663 SuffFindDeps(mem, slst);
1664
1665 /*
1666 * Create the link between the two nodes right off
1667 */
1668 if (Lst_Member(gn->children, (void *)mem) == NULL) {
1669 (void)Lst_AtEnd(gn->children, (void *)mem);
1670 (void)Lst_AtEnd(mem->parents, (void *)gn);
1671 gn->unmade += 1;
1672 }
1673
1674 /*
1675 * Copy in the variables from the member node to this one.
1676 */
1677 for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
1678 char *p1;
1679 Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn);
1680 efree(p1);
1681
1682 }
1683
1684 ms = mem->suffix;
1685 if (ms == NULL) {
1686 /*
1687 * Didn't know what it was -- use .NULL suffix if not in make mode
1688 */
1584
1585 /*
1586 * Record last child for expansion purposes
1587 */
1588 ln = Lst_Last(tGn->children);
1589
1590 /*
1591 * Pass the buck to Make_HandleUse to apply the rule
1592 */
1593 (void)Make_HandleUse(gn, tGn);
1594
1595 /*
1596 * Deal with wildcards and variables in any acquired sources
1597 */
1598 ln = Lst_Succ(ln);
1599 if (ln != NULL) {
1600 Lst_ForEachFrom(tGn->children, ln,
1601 SuffExpandChildren, (void *)tGn);
1602 }
1603
1604 /*
1605 * Keep track of another parent to which this beast is transformed so
1606 * the .IMPSRC variable can be set correctly for the parent.
1607 */
1608 (void)Lst_AtEnd(sGn->iParents, (void *)tGn);
1609
1610 return(TRUE);
1611}
1612
1613
1614/*-
1615 *-----------------------------------------------------------------------
1616 * SuffFindArchiveDeps --
1617 * Locate dependencies for an OP_ARCHV node.
1618 *
1619 * Results:
1620 * None
1621 *
1622 * Side Effects:
1623 * Same as Suff_FindDeps
1624 *
1625 *-----------------------------------------------------------------------
1626 */
1627static void
1628SuffFindArchiveDeps(gn, slst)
1629 GNode *gn; /* Node for which to locate dependencies */
1630 Lst slst;
1631{
1632 char *eoarch; /* End of archive portion */
1633 char *eoname; /* End of member portion */
1634 GNode *mem; /* Node for member */
1635 static char *copy[] = { /* Variables to be copied from the member node */
1636 TARGET, /* Must be first */
1637 PREFIX, /* Must be second */
1638 };
1639 int i; /* Index into copy and vals */
1640 Suff *ms; /* Suffix descriptor for member */
1641 char *name; /* Start of member's name */
1642
1643 /*
1644 * The node is an archive(member) pair. so we must find a
1645 * suffix for both of them.
1646 */
1647 eoarch = strchr (gn->name, '(');
1648 eoname = strchr (eoarch, ')');
1649
1650 *eoname = '\0'; /* Nuke parentheses during suffix search */
1651 *eoarch = '\0'; /* So a suffix can be found */
1652
1653 name = eoarch + 1;
1654
1655 /*
1656 * To simplify things, call Suff_FindDeps recursively on the member now,
1657 * so we can simply compare the member's .PREFIX and .TARGET variables
1658 * to locate its suffix. This allows us to figure out the suffix to
1659 * use for the archive without having to do a quadratic search over the
1660 * suffix list, backtracking for each one...
1661 */
1662 mem = Targ_FindNode(name, TARG_CREATE);
1663 SuffFindDeps(mem, slst);
1664
1665 /*
1666 * Create the link between the two nodes right off
1667 */
1668 if (Lst_Member(gn->children, (void *)mem) == NULL) {
1669 (void)Lst_AtEnd(gn->children, (void *)mem);
1670 (void)Lst_AtEnd(mem->parents, (void *)gn);
1671 gn->unmade += 1;
1672 }
1673
1674 /*
1675 * Copy in the variables from the member node to this one.
1676 */
1677 for (i = (sizeof(copy)/sizeof(copy[0]))-1; i >= 0; i--) {
1678 char *p1;
1679 Var_Set(copy[i], Var_Value(copy[i], mem, &p1), gn);
1680 efree(p1);
1681
1682 }
1683
1684 ms = mem->suffix;
1685 if (ms == NULL) {
1686 /*
1687 * Didn't know what it was -- use .NULL suffix if not in make mode
1688 */
1689 DEBUGF(SUFF, "using null suffix\n");
1689 DEBUGF(SUFF, ("using null suffix\n"));
1690 ms = suffNull;
1691 }
1692
1693
1694 /*
1695 * Set the other two local variables required for this target.
1696 */
1697 Var_Set (MEMBER, name, gn);
1698 Var_Set (ARCHIVE, gn->name, gn);
1699
1700 if (ms != NULL) {
1701 /*
1702 * Member has a known suffix, so look for a transformation rule from
1703 * it to a possible suffix of the archive. Rather than searching
1704 * through the entire list, we just look at suffixes to which the
1705 * member's suffix may be transformed...
1706 */
1707 LstNode ln;
1708
1709 /*
1710 * Use first matching suffix...
1711 */
1712 ln = Lst_Find(ms->parents, eoarch, SuffSuffIsSuffixP);
1713
1714 if (ln != NULL) {
1715 /*
1716 * Got one -- apply it
1717 */
1718 if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms)) {
1690 ms = suffNull;
1691 }
1692
1693
1694 /*
1695 * Set the other two local variables required for this target.
1696 */
1697 Var_Set (MEMBER, name, gn);
1698 Var_Set (ARCHIVE, gn->name, gn);
1699
1700 if (ms != NULL) {
1701 /*
1702 * Member has a known suffix, so look for a transformation rule from
1703 * it to a possible suffix of the archive. Rather than searching
1704 * through the entire list, we just look at suffixes to which the
1705 * member's suffix may be transformed...
1706 */
1707 LstNode ln;
1708
1709 /*
1710 * Use first matching suffix...
1711 */
1712 ln = Lst_Find(ms->parents, eoarch, SuffSuffIsSuffixP);
1713
1714 if (ln != NULL) {
1715 /*
1716 * Got one -- apply it
1717 */
1718 if (!SuffApplyTransform(gn, mem, (Suff *)Lst_Datum(ln), ms)) {
1719 DEBUGF(SUFF, "\tNo transformation from %s -> %s\n",
1720 ms->name, ((Suff *)Lst_Datum(ln))->name);
1719 DEBUGF(SUFF, ("\tNo transformation from %s -> %s\n",
1720 ms->name, ((Suff *)Lst_Datum(ln))->name));
1721 }
1722 }
1723 }
1724
1725 /*
1726 * Replace the opening and closing parens now we've no need of the separate
1727 * pieces.
1728 */
1729 *eoarch = '('; *eoname = ')';
1730
1731 /*
1732 * Pretend gn appeared to the left of a dependency operator so
1733 * the user needn't provide a transformation from the member to the
1734 * archive.
1735 */
1736 if (OP_NOP(gn->type)) {
1737 gn->type |= OP_DEPENDS;
1738 }
1739
1740 /*
1741 * Flag the member as such so we remember to look in the archive for
1742 * its modification time.
1743 */
1744 mem->type |= OP_MEMBER;
1745}
1746
1747/*-
1748 *-----------------------------------------------------------------------
1749 * SuffFindNormalDeps --
1750 * Locate implicit dependencies for regular targets.
1751 *
1752 * Results:
1753 * None.
1754 *
1755 * Side Effects:
1756 * Same as Suff_FindDeps...
1757 *
1758 *-----------------------------------------------------------------------
1759 */
1760static void
1761SuffFindNormalDeps(gn, slst)
1762 GNode *gn; /* Node for which to find sources */
1763 Lst slst;
1764{
1765 char *eoname; /* End of name */
1766 char *sopref; /* Start of prefix */
1767 LstNode ln; /* Next suffix node to check */
1768 Lst srcs; /* List of sources at which to look */
1769 Lst targs; /* List of targets to which things can be
1770 * transformed. They all have the same file,
1771 * but different suff and pref fields */
1772 Src *bottom; /* Start of found transformation path */
1773 Src *src; /* General Src pointer */
1774 char *pref; /* Prefix to use */
1775 Src *targ; /* General Src target pointer */
1776
1777
1778 eoname = gn->name + strlen(gn->name);
1779
1780 sopref = gn->name;
1781
1782 /*
1783 * Begin at the beginning...
1784 */
1785 ln = Lst_First(sufflist);
1786 srcs = Lst_Init(FALSE);
1787 targs = Lst_Init(FALSE);
1788
1789 /*
1790 * We're caught in a catch-22 here. On the one hand, we want to use any
1791 * transformation implied by the target's sources, but we can't examine
1792 * the sources until we've expanded any variables/wildcards they may hold,
1793 * and we can't do that until we've set up the target's local variables
1794 * and we can't do that until we know what the proper suffix for the
1795 * target is (in case there are two suffixes one of which is a suffix of
1796 * the other) and we can't know that until we've found its implied
1797 * source, which we may not want to use if there's an existing source
1798 * that implies a different transformation.
1799 *
1800 * In an attempt to get around this, which may not work all the time,
1801 * but should work most of the time, we look for implied sources first,
1802 * checking transformations to all possible suffixes of the target,
1803 * use what we find to set the target's local variables, expand the
1804 * children, then look for any overriding transformations they imply.
1805 * Should we find one, we discard the one we found before.
1806 */
1807
1808 while (ln != NULL) {
1809 /*
1810 * Look for next possible suffix...
1811 */
1812 ln = Lst_FindFrom(sufflist, ln, eoname, SuffSuffIsSuffixP);
1813
1814 if (ln != NULL) {
1815 int prefLen; /* Length of the prefix */
1816 Src *targ;
1817
1818 /*
1819 * Allocate a Src structure to which things can be transformed
1820 */
1821 targ = (Src *)emalloc(sizeof (Src));
1822 targ->file = estrdup(gn->name);
1823 targ->suff = (Suff *)Lst_Datum(ln);
1824 targ->suff->refCount++;
1825 targ->node = gn;
1826 targ->parent = (Src *)NULL;
1827 targ->children = 0;
1828#ifdef DEBUG_SRC
1829 targ->cp = Lst_Init(FALSE);
1830#endif
1831
1832 /*
1833 * Allocate room for the prefix, whose end is found by subtracting
1834 * the length of the suffix from the end of the name.
1835 */
1836 prefLen = (eoname - targ->suff->nameLen) - sopref;
1837 targ->pref = emalloc(prefLen + 1);
1838 memcpy(targ->pref, sopref, prefLen);
1839 targ->pref[prefLen] = '\0';
1840
1841 /*
1842 * Add nodes from which the target can be made
1843 */
1844 SuffAddLevel(srcs, targ);
1845
1846 /*
1847 * Record the target so we can nuke it
1848 */
1849 (void)Lst_AtEnd(targs, (void *)targ);
1850
1851 /*
1852 * Search from this suffix's successor...
1853 */
1854 ln = Lst_Succ(ln);
1855 }
1856 }
1857
1858 /*
1859 * Handle target of unknown suffix...
1860 */
1861 if (Lst_IsEmpty(targs) && suffNull != NULL) {
1721 }
1722 }
1723 }
1724
1725 /*
1726 * Replace the opening and closing parens now we've no need of the separate
1727 * pieces.
1728 */
1729 *eoarch = '('; *eoname = ')';
1730
1731 /*
1732 * Pretend gn appeared to the left of a dependency operator so
1733 * the user needn't provide a transformation from the member to the
1734 * archive.
1735 */
1736 if (OP_NOP(gn->type)) {
1737 gn->type |= OP_DEPENDS;
1738 }
1739
1740 /*
1741 * Flag the member as such so we remember to look in the archive for
1742 * its modification time.
1743 */
1744 mem->type |= OP_MEMBER;
1745}
1746
1747/*-
1748 *-----------------------------------------------------------------------
1749 * SuffFindNormalDeps --
1750 * Locate implicit dependencies for regular targets.
1751 *
1752 * Results:
1753 * None.
1754 *
1755 * Side Effects:
1756 * Same as Suff_FindDeps...
1757 *
1758 *-----------------------------------------------------------------------
1759 */
1760static void
1761SuffFindNormalDeps(gn, slst)
1762 GNode *gn; /* Node for which to find sources */
1763 Lst slst;
1764{
1765 char *eoname; /* End of name */
1766 char *sopref; /* Start of prefix */
1767 LstNode ln; /* Next suffix node to check */
1768 Lst srcs; /* List of sources at which to look */
1769 Lst targs; /* List of targets to which things can be
1770 * transformed. They all have the same file,
1771 * but different suff and pref fields */
1772 Src *bottom; /* Start of found transformation path */
1773 Src *src; /* General Src pointer */
1774 char *pref; /* Prefix to use */
1775 Src *targ; /* General Src target pointer */
1776
1777
1778 eoname = gn->name + strlen(gn->name);
1779
1780 sopref = gn->name;
1781
1782 /*
1783 * Begin at the beginning...
1784 */
1785 ln = Lst_First(sufflist);
1786 srcs = Lst_Init(FALSE);
1787 targs = Lst_Init(FALSE);
1788
1789 /*
1790 * We're caught in a catch-22 here. On the one hand, we want to use any
1791 * transformation implied by the target's sources, but we can't examine
1792 * the sources until we've expanded any variables/wildcards they may hold,
1793 * and we can't do that until we've set up the target's local variables
1794 * and we can't do that until we know what the proper suffix for the
1795 * target is (in case there are two suffixes one of which is a suffix of
1796 * the other) and we can't know that until we've found its implied
1797 * source, which we may not want to use if there's an existing source
1798 * that implies a different transformation.
1799 *
1800 * In an attempt to get around this, which may not work all the time,
1801 * but should work most of the time, we look for implied sources first,
1802 * checking transformations to all possible suffixes of the target,
1803 * use what we find to set the target's local variables, expand the
1804 * children, then look for any overriding transformations they imply.
1805 * Should we find one, we discard the one we found before.
1806 */
1807
1808 while (ln != NULL) {
1809 /*
1810 * Look for next possible suffix...
1811 */
1812 ln = Lst_FindFrom(sufflist, ln, eoname, SuffSuffIsSuffixP);
1813
1814 if (ln != NULL) {
1815 int prefLen; /* Length of the prefix */
1816 Src *targ;
1817
1818 /*
1819 * Allocate a Src structure to which things can be transformed
1820 */
1821 targ = (Src *)emalloc(sizeof (Src));
1822 targ->file = estrdup(gn->name);
1823 targ->suff = (Suff *)Lst_Datum(ln);
1824 targ->suff->refCount++;
1825 targ->node = gn;
1826 targ->parent = (Src *)NULL;
1827 targ->children = 0;
1828#ifdef DEBUG_SRC
1829 targ->cp = Lst_Init(FALSE);
1830#endif
1831
1832 /*
1833 * Allocate room for the prefix, whose end is found by subtracting
1834 * the length of the suffix from the end of the name.
1835 */
1836 prefLen = (eoname - targ->suff->nameLen) - sopref;
1837 targ->pref = emalloc(prefLen + 1);
1838 memcpy(targ->pref, sopref, prefLen);
1839 targ->pref[prefLen] = '\0';
1840
1841 /*
1842 * Add nodes from which the target can be made
1843 */
1844 SuffAddLevel(srcs, targ);
1845
1846 /*
1847 * Record the target so we can nuke it
1848 */
1849 (void)Lst_AtEnd(targs, (void *)targ);
1850
1851 /*
1852 * Search from this suffix's successor...
1853 */
1854 ln = Lst_Succ(ln);
1855 }
1856 }
1857
1858 /*
1859 * Handle target of unknown suffix...
1860 */
1861 if (Lst_IsEmpty(targs) && suffNull != NULL) {
1862 DEBUGF(SUFF, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
1862 DEBUGF(SUFF, ("\tNo known suffix on %s. Using .NULL suffix\n", gn->name));
1863
1864 targ = (Src *)emalloc(sizeof (Src));
1865 targ->file = estrdup(gn->name);
1866 targ->suff = suffNull;
1867 targ->suff->refCount++;
1868 targ->node = gn;
1869 targ->parent = (Src *)NULL;
1870 targ->children = 0;
1871 targ->pref = estrdup(sopref);
1872#ifdef DEBUG_SRC
1873 targ->cp = Lst_Init(FALSE);
1874#endif
1875
1876 /*
1877 * Only use the default suffix rules if we don't have commands
1878 * or dependencies defined for this gnode
1879 */
1880 if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
1881 SuffAddLevel(srcs, targ);
1882 else {
1863
1864 targ = (Src *)emalloc(sizeof (Src));
1865 targ->file = estrdup(gn->name);
1866 targ->suff = suffNull;
1867 targ->suff->refCount++;
1868 targ->node = gn;
1869 targ->parent = (Src *)NULL;
1870 targ->children = 0;
1871 targ->pref = estrdup(sopref);
1872#ifdef DEBUG_SRC
1873 targ->cp = Lst_Init(FALSE);
1874#endif
1875
1876 /*
1877 * Only use the default suffix rules if we don't have commands
1878 * or dependencies defined for this gnode
1879 */
1880 if (Lst_IsEmpty(gn->commands) && Lst_IsEmpty(gn->children))
1881 SuffAddLevel(srcs, targ);
1882 else {
1883 DEBUGF(SUFF, "not ");
1883 DEBUGF(SUFF, ("not "));
1884 }
1885
1884 }
1885
1886 DEBUGF(SUFF, "adding suffix rules\n");
1886 DEBUGF(SUFF, ("adding suffix rules\n"));
1887
1888 (void)Lst_AtEnd(targs, (void *)targ);
1889 }
1890
1891 /*
1892 * Using the list of possible sources built up from the target suffix(es),
1893 * try and find an existing file/target that matches.
1894 */
1895 bottom = SuffFindThem(srcs, slst);
1896
1897 if (bottom == (Src *)NULL) {
1898 /*
1899 * No known transformations -- use the first suffix found for setting
1900 * the local variables.
1901 */
1902 if (!Lst_IsEmpty(targs)) {
1903 targ = (Src *)Lst_Datum(Lst_First(targs));
1904 } else {
1905 targ = (Src *)NULL;
1906 }
1907 } else {
1908 /*
1909 * Work up the transformation path to find the suffix of the
1910 * target to which the transformation was made.
1911 */
1912 for (targ = bottom; targ->parent != NULL; targ = targ->parent)
1913 continue;
1914 }
1915
1916 /*
1917 * The .TARGET variable we always set to be the name at this point,
1918 * since it's only set to the path if the thing is only a source and
1919 * if it's only a source, it doesn't matter what we put here as far
1920 * as expanding sources is concerned, since it has none...
1921 */
1922 Var_Set(TARGET, gn->name, gn);
1923
1924 pref = (targ != NULL) ? targ->pref : gn->name;
1925 Var_Set(PREFIX, pref, gn);
1926
1927 /*
1928 * Now we've got the important local variables set, expand any sources
1929 * that still contain variables or wildcards in their names.
1930 */
1931 Lst_ForEach(gn->children, SuffExpandChildren, (void *)gn);
1932
1933 if (targ == NULL) {
1887
1888 (void)Lst_AtEnd(targs, (void *)targ);
1889 }
1890
1891 /*
1892 * Using the list of possible sources built up from the target suffix(es),
1893 * try and find an existing file/target that matches.
1894 */
1895 bottom = SuffFindThem(srcs, slst);
1896
1897 if (bottom == (Src *)NULL) {
1898 /*
1899 * No known transformations -- use the first suffix found for setting
1900 * the local variables.
1901 */
1902 if (!Lst_IsEmpty(targs)) {
1903 targ = (Src *)Lst_Datum(Lst_First(targs));
1904 } else {
1905 targ = (Src *)NULL;
1906 }
1907 } else {
1908 /*
1909 * Work up the transformation path to find the suffix of the
1910 * target to which the transformation was made.
1911 */
1912 for (targ = bottom; targ->parent != NULL; targ = targ->parent)
1913 continue;
1914 }
1915
1916 /*
1917 * The .TARGET variable we always set to be the name at this point,
1918 * since it's only set to the path if the thing is only a source and
1919 * if it's only a source, it doesn't matter what we put here as far
1920 * as expanding sources is concerned, since it has none...
1921 */
1922 Var_Set(TARGET, gn->name, gn);
1923
1924 pref = (targ != NULL) ? targ->pref : gn->name;
1925 Var_Set(PREFIX, pref, gn);
1926
1927 /*
1928 * Now we've got the important local variables set, expand any sources
1929 * that still contain variables or wildcards in their names.
1930 */
1931 Lst_ForEach(gn->children, SuffExpandChildren, (void *)gn);
1932
1933 if (targ == NULL) {
1934 DEBUGF(SUFF, "\tNo valid suffix on %s\n", gn->name);
1934 DEBUGF(SUFF, ("\tNo valid suffix on %s\n", gn->name));
1935
1936sfnd_abort:
1937 /*
1938 * Deal with finding the thing on the default search path if the
1939 * node is only a source (not on the lhs of a dependency operator
1940 * or [XXX] it has neither children or commands).
1941 */
1942 if (OP_NOP(gn->type) ||
1943 (Lst_IsEmpty(gn->children) && Lst_IsEmpty(gn->commands)))
1944 {
1945 gn->path = Dir_FindFile(gn->name,
1946 (targ == NULL ? dirSearchPath :
1947 targ->suff->searchPath));
1948 if (gn->path != NULL) {
1949 char *ptr;
1950 Var_Set(TARGET, gn->path, gn);
1951
1952 if (targ != NULL) {
1953 /*
1954 * Suffix known for the thing -- trim the suffix off
1955 * the path to form the proper .PREFIX variable.
1956 */
1957 int savep = strlen(gn->path) - targ->suff->nameLen;
1958 char savec;
1959
1960 if (gn->suffix)
1961 gn->suffix->refCount--;
1962 gn->suffix = targ->suff;
1963 gn->suffix->refCount++;
1964
1965 savec = gn->path[savep];
1966 gn->path[savep] = '\0';
1967
1968 if ((ptr = strrchr(gn->path, '/')) != NULL)
1969 ptr++;
1970 else
1971 ptr = gn->path;
1972
1973 Var_Set(PREFIX, ptr, gn);
1974
1975 gn->path[savep] = savec;
1976 } else {
1977 /*
1978 * The .PREFIX gets the full path if the target has
1979 * no known suffix.
1980 */
1981 if (gn->suffix)
1982 gn->suffix->refCount--;
1983 gn->suffix = NULL;
1984
1985 if ((ptr = strrchr(gn->path, '/')) != NULL)
1986 ptr++;
1987 else
1988 ptr = gn->path;
1989
1990 Var_Set(PREFIX, ptr, gn);
1991 }
1992 }
1993 } else {
1994 /*
1995 * Not appropriate to search for the thing -- set the
1996 * path to be the name so Dir_MTime won't go grovelling for
1997 * it.
1998 */
1999 if (gn->suffix)
2000 gn->suffix->refCount--;
2001 gn->suffix = (targ == NULL) ? NULL : targ->suff;
2002 if (gn->suffix)
2003 gn->suffix->refCount++;
2004 efree(gn->path);
2005 gn->path = estrdup(gn->name);
2006 }
2007
2008 goto sfnd_return;
2009 }
2010
2011 /*
2012 * If the suffix indicates that the target is a library, mark that in
2013 * the node's type field.
2014 */
2015 if (targ->suff->flags & SUFF_LIBRARY) {
2016 gn->type |= OP_LIB;
2017 }
2018
2019 /*
2020 * Check for overriding transformation rule implied by sources
2021 */
2022 if (!Lst_IsEmpty(gn->children)) {
2023 src = SuffFindCmds(targ, slst);
2024
2025 if (src != (Src *)NULL) {
2026 /*
2027 * Free up all the Src structures in the transformation path
2028 * up to, but not including, the parent node.
2029 */
2030 while (bottom && bottom->parent != NULL) {
2031 if (Lst_Member(slst, (void *) bottom) == NULL) {
2032 Lst_AtEnd(slst, (void *) bottom);
2033 }
2034 bottom = bottom->parent;
2035 }
2036 bottom = src;
2037 }
2038 }
2039
2040 if (bottom == NULL) {
2041 /*
2042 * No idea from where it can come -- return now.
2043 */
2044 goto sfnd_abort;
2045 }
2046
2047 /*
2048 * We now have a list of Src structures headed by 'bottom' and linked via
2049 * their 'parent' pointers. What we do next is create links between
2050 * source and target nodes (which may or may not have been created)
2051 * and set the necessary local variables in each target. The
2052 * commands for each target are set from the commands of the
2053 * transformation rule used to get from the src suffix to the targ
2054 * suffix. Note that this causes the commands list of the original
2055 * node, gn, to be replaced by the commands of the final
2056 * transformation rule. Also, the unmade field of gn is incremented.
2057 * Etc.
2058 */
2059 if (bottom->node == NULL) {
2060 bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
2061 }
2062
2063 for (src = bottom; src->parent != (Src *)NULL; src = src->parent) {
2064 targ = src->parent;
2065
2066 if (src->node->suffix)
2067 src->node->suffix->refCount--;
2068 src->node->suffix = src->suff;
2069 src->node->suffix->refCount++;
2070
2071 if (targ->node == NULL) {
2072 targ->node = Targ_FindNode(targ->file, TARG_CREATE);
2073 }
2074
2075 SuffApplyTransform(targ->node, src->node,
2076 targ->suff, src->suff);
2077
2078 if (targ->node != gn) {
2079 /*
2080 * Finish off the dependency-search process for any nodes
2081 * between bottom and gn (no point in questing around the
2082 * filesystem for their implicit source when it's already
2083 * known). Note that the node can't have any sources that
2084 * need expanding, since SuffFindThem will stop on an existing
2085 * node, so all we need to do is set the standard and System V
2086 * variables.
2087 */
2088 targ->node->type |= OP_DEPS_FOUND;
2089
2090 Var_Set(PREFIX, targ->pref, targ->node);
2091
2092 Var_Set(TARGET, targ->node->name, targ->node);
2093 }
2094 }
2095
2096 if (gn->suffix)
2097 gn->suffix->refCount--;
2098 gn->suffix = src->suff;
2099 gn->suffix->refCount++;
2100
2101 /*
2102 * So Dir_MTime doesn't go questing for it...
2103 */
2104 efree(gn->path);
2105 gn->path = estrdup(gn->name);
2106
2107 /*
2108 * Nuke the transformation path and the Src structures left over in the
2109 * two lists.
2110 */
2111sfnd_return:
2112 if (bottom)
2113 if (Lst_Member(slst, (void *) bottom) == NULL)
2114 Lst_AtEnd(slst, (void *) bottom);
2115
2116 while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
2117 continue;
2118
2119 Lst_Concat(slst, srcs, LST_CONCLINK);
2120 Lst_Concat(slst, targs, LST_CONCLINK);
2121}
2122
2123
2124/*-
2125 *-----------------------------------------------------------------------
2126 * Suff_FindDeps --
2127 * Find implicit sources for the target described by the graph node
2128 * gn
2129 *
2130 * Results:
2131 * Nothing.
2132 *
2133 * Side Effects:
2134 * Nodes are added to the graph below the passed-in node. The nodes
2135 * are marked to have their IMPSRC variable filled in. The
2136 * PREFIX variable is set for the given node and all its
2137 * implied children.
2138 *
2139 * Notes:
2140 * The path found by this target is the shortest path in the
2141 * transformation graph, which may pass through non-existent targets,
2142 * to an existing target. The search continues on all paths from the
2143 * root suffix until a file is found. I.e. if there's a path
2144 * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
2145 * the .c and .l files don't, the search will branch out in
2146 * all directions from .o and again from all the nodes on the
2147 * next level until the .l,v node is encountered.
2148 *
2149 *-----------------------------------------------------------------------
2150 */
2151
2152void
2153Suff_FindDeps(gn)
2154 GNode *gn;
2155{
2156
2157 SuffFindDeps(gn, srclist);
2158 while (SuffRemoveSrc(srclist))
2159 continue;
2160}
2161
2162
2163static void
2164SuffFindDeps (gn, slst)
2165 GNode *gn; /* node we're dealing with */
2166 Lst slst;
2167{
2168 if (gn->type & OP_DEPS_FOUND) {
2169 /*
2170 * If dependencies already found, no need to do it again...
2171 */
2172 return;
2173 } else {
2174 gn->type |= OP_DEPS_FOUND;
2175 }
2176
1935
1936sfnd_abort:
1937 /*
1938 * Deal with finding the thing on the default search path if the
1939 * node is only a source (not on the lhs of a dependency operator
1940 * or [XXX] it has neither children or commands).
1941 */
1942 if (OP_NOP(gn->type) ||
1943 (Lst_IsEmpty(gn->children) && Lst_IsEmpty(gn->commands)))
1944 {
1945 gn->path = Dir_FindFile(gn->name,
1946 (targ == NULL ? dirSearchPath :
1947 targ->suff->searchPath));
1948 if (gn->path != NULL) {
1949 char *ptr;
1950 Var_Set(TARGET, gn->path, gn);
1951
1952 if (targ != NULL) {
1953 /*
1954 * Suffix known for the thing -- trim the suffix off
1955 * the path to form the proper .PREFIX variable.
1956 */
1957 int savep = strlen(gn->path) - targ->suff->nameLen;
1958 char savec;
1959
1960 if (gn->suffix)
1961 gn->suffix->refCount--;
1962 gn->suffix = targ->suff;
1963 gn->suffix->refCount++;
1964
1965 savec = gn->path[savep];
1966 gn->path[savep] = '\0';
1967
1968 if ((ptr = strrchr(gn->path, '/')) != NULL)
1969 ptr++;
1970 else
1971 ptr = gn->path;
1972
1973 Var_Set(PREFIX, ptr, gn);
1974
1975 gn->path[savep] = savec;
1976 } else {
1977 /*
1978 * The .PREFIX gets the full path if the target has
1979 * no known suffix.
1980 */
1981 if (gn->suffix)
1982 gn->suffix->refCount--;
1983 gn->suffix = NULL;
1984
1985 if ((ptr = strrchr(gn->path, '/')) != NULL)
1986 ptr++;
1987 else
1988 ptr = gn->path;
1989
1990 Var_Set(PREFIX, ptr, gn);
1991 }
1992 }
1993 } else {
1994 /*
1995 * Not appropriate to search for the thing -- set the
1996 * path to be the name so Dir_MTime won't go grovelling for
1997 * it.
1998 */
1999 if (gn->suffix)
2000 gn->suffix->refCount--;
2001 gn->suffix = (targ == NULL) ? NULL : targ->suff;
2002 if (gn->suffix)
2003 gn->suffix->refCount++;
2004 efree(gn->path);
2005 gn->path = estrdup(gn->name);
2006 }
2007
2008 goto sfnd_return;
2009 }
2010
2011 /*
2012 * If the suffix indicates that the target is a library, mark that in
2013 * the node's type field.
2014 */
2015 if (targ->suff->flags & SUFF_LIBRARY) {
2016 gn->type |= OP_LIB;
2017 }
2018
2019 /*
2020 * Check for overriding transformation rule implied by sources
2021 */
2022 if (!Lst_IsEmpty(gn->children)) {
2023 src = SuffFindCmds(targ, slst);
2024
2025 if (src != (Src *)NULL) {
2026 /*
2027 * Free up all the Src structures in the transformation path
2028 * up to, but not including, the parent node.
2029 */
2030 while (bottom && bottom->parent != NULL) {
2031 if (Lst_Member(slst, (void *) bottom) == NULL) {
2032 Lst_AtEnd(slst, (void *) bottom);
2033 }
2034 bottom = bottom->parent;
2035 }
2036 bottom = src;
2037 }
2038 }
2039
2040 if (bottom == NULL) {
2041 /*
2042 * No idea from where it can come -- return now.
2043 */
2044 goto sfnd_abort;
2045 }
2046
2047 /*
2048 * We now have a list of Src structures headed by 'bottom' and linked via
2049 * their 'parent' pointers. What we do next is create links between
2050 * source and target nodes (which may or may not have been created)
2051 * and set the necessary local variables in each target. The
2052 * commands for each target are set from the commands of the
2053 * transformation rule used to get from the src suffix to the targ
2054 * suffix. Note that this causes the commands list of the original
2055 * node, gn, to be replaced by the commands of the final
2056 * transformation rule. Also, the unmade field of gn is incremented.
2057 * Etc.
2058 */
2059 if (bottom->node == NULL) {
2060 bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
2061 }
2062
2063 for (src = bottom; src->parent != (Src *)NULL; src = src->parent) {
2064 targ = src->parent;
2065
2066 if (src->node->suffix)
2067 src->node->suffix->refCount--;
2068 src->node->suffix = src->suff;
2069 src->node->suffix->refCount++;
2070
2071 if (targ->node == NULL) {
2072 targ->node = Targ_FindNode(targ->file, TARG_CREATE);
2073 }
2074
2075 SuffApplyTransform(targ->node, src->node,
2076 targ->suff, src->suff);
2077
2078 if (targ->node != gn) {
2079 /*
2080 * Finish off the dependency-search process for any nodes
2081 * between bottom and gn (no point in questing around the
2082 * filesystem for their implicit source when it's already
2083 * known). Note that the node can't have any sources that
2084 * need expanding, since SuffFindThem will stop on an existing
2085 * node, so all we need to do is set the standard and System V
2086 * variables.
2087 */
2088 targ->node->type |= OP_DEPS_FOUND;
2089
2090 Var_Set(PREFIX, targ->pref, targ->node);
2091
2092 Var_Set(TARGET, targ->node->name, targ->node);
2093 }
2094 }
2095
2096 if (gn->suffix)
2097 gn->suffix->refCount--;
2098 gn->suffix = src->suff;
2099 gn->suffix->refCount++;
2100
2101 /*
2102 * So Dir_MTime doesn't go questing for it...
2103 */
2104 efree(gn->path);
2105 gn->path = estrdup(gn->name);
2106
2107 /*
2108 * Nuke the transformation path and the Src structures left over in the
2109 * two lists.
2110 */
2111sfnd_return:
2112 if (bottom)
2113 if (Lst_Member(slst, (void *) bottom) == NULL)
2114 Lst_AtEnd(slst, (void *) bottom);
2115
2116 while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
2117 continue;
2118
2119 Lst_Concat(slst, srcs, LST_CONCLINK);
2120 Lst_Concat(slst, targs, LST_CONCLINK);
2121}
2122
2123
2124/*-
2125 *-----------------------------------------------------------------------
2126 * Suff_FindDeps --
2127 * Find implicit sources for the target described by the graph node
2128 * gn
2129 *
2130 * Results:
2131 * Nothing.
2132 *
2133 * Side Effects:
2134 * Nodes are added to the graph below the passed-in node. The nodes
2135 * are marked to have their IMPSRC variable filled in. The
2136 * PREFIX variable is set for the given node and all its
2137 * implied children.
2138 *
2139 * Notes:
2140 * The path found by this target is the shortest path in the
2141 * transformation graph, which may pass through non-existent targets,
2142 * to an existing target. The search continues on all paths from the
2143 * root suffix until a file is found. I.e. if there's a path
2144 * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
2145 * the .c and .l files don't, the search will branch out in
2146 * all directions from .o and again from all the nodes on the
2147 * next level until the .l,v node is encountered.
2148 *
2149 *-----------------------------------------------------------------------
2150 */
2151
2152void
2153Suff_FindDeps(gn)
2154 GNode *gn;
2155{
2156
2157 SuffFindDeps(gn, srclist);
2158 while (SuffRemoveSrc(srclist))
2159 continue;
2160}
2161
2162
2163static void
2164SuffFindDeps (gn, slst)
2165 GNode *gn; /* node we're dealing with */
2166 Lst slst;
2167{
2168 if (gn->type & OP_DEPS_FOUND) {
2169 /*
2170 * If dependencies already found, no need to do it again...
2171 */
2172 return;
2173 } else {
2174 gn->type |= OP_DEPS_FOUND;
2175 }
2176
2177 DEBUGF(SUFF, "SuffFindDeps (%s)\n", gn->name);
2177 DEBUGF(SUFF, ("SuffFindDeps (%s)\n", gn->name));
2178
2179 if (gn->type & OP_ARCHV) {
2180 SuffFindArchiveDeps(gn, slst);
2181 } else if (gn->type & OP_LIB) {
2182 /*
2183 * If the node is a library, it is the arch module's job to find it
2184 * and set the TARGET variable accordingly. We merely provide the
2185 * search path, assuming all libraries end in ".a" (if the suffix
2186 * hasn't been defined, there's nothing we can do for it, so we just
2187 * set the TARGET variable to the node's name in order to give it a
2188 * value).
2189 */
2190 LstNode ln;
2191 Suff *s;
2192
2193 ln = Lst_Find (sufflist, (void *)LIBSUFF, SuffSuffHasNameP);
2194 if (gn->suffix)
2195 gn->suffix->refCount--;
2196 if (ln != NULL) {
2197 gn->suffix = s = (Suff *) Lst_Datum (ln);
2198 gn->suffix->refCount++;
2199 Arch_FindLib (gn, s->searchPath);
2200 } else {
2201 gn->suffix = NULL;
2202 Var_Set (TARGET, gn->name, gn);
2203 }
2204 /*
2205 * Because a library (-lfoo) target doesn't follow the standard
2206 * filesystem conventions, we don't set the regular variables for
2207 * the thing. .PREFIX is simply made empty...
2208 */
2209 Var_Set(PREFIX, "", gn);
2210 } else {
2211 SuffFindNormalDeps(gn, slst);
2212 }
2213}
2214
2215/*-
2216 *-----------------------------------------------------------------------
2217 * Suff_SetNull --
2218 * Define which suffix is the null suffix.
2219 *
2220 * Results:
2221 * None.
2222 *
2223 * Side Effects:
2224 * 'suffNull' is altered.
2225 *
2226 * Notes:
2227 * Need to handle the changing of the null suffix gracefully so the
2228 * old transformation rules don't just go away.
2229 *
2230 *-----------------------------------------------------------------------
2231 */
2232void
2233Suff_SetNull(name)
2234 char *name; /* Name of null suffix */
2235{
2236 Suff *s;
2237 LstNode ln;
2238
2239 ln = Lst_Find(sufflist, (void *)name, SuffSuffHasNameP);
2240 if (ln != NULL) {
2241 s = (Suff *)Lst_Datum(ln);
2242 if (suffNull != (Suff *)NULL) {
2243 suffNull->flags &= ~SUFF_NULL;
2244 }
2245 s->flags |= SUFF_NULL;
2246 /*
2247 * XXX: Here's where the transformation mangling would take place
2248 */
2249 suffNull = s;
2250 } else {
2251 Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",
2252 name);
2253 }
2254}
2255
2256/*-
2257 *-----------------------------------------------------------------------
2258 * Suff_Init --
2259 * Initialize suffixes module
2260 *
2261 * Results:
2262 * None
2263 *
2264 * Side Effects:
2265 * Many
2266 *-----------------------------------------------------------------------
2267 */
2268void
2269Suff_Init ()
2270{
2271 sufflist = Lst_Init (FALSE);
2272 suffClean = Lst_Init(FALSE);
2273 srclist = Lst_Init (FALSE);
2274 transforms = Lst_Init (FALSE);
2275
2276 sNum = 0;
2277 /*
2278 * Create null suffix for single-suffix rules (POSIX). The thing doesn't
2279 * actually go on the suffix list or everyone will think that's its
2280 * suffix.
2281 */
2282 emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));
2283
2284 suffNull->name = estrdup ("");
2285 suffNull->nameLen = 0;
2286 suffNull->searchPath = Lst_Init (FALSE);
2287 Dir_Concat(suffNull->searchPath, dirSearchPath);
2288 suffNull->children = Lst_Init (FALSE);
2289 suffNull->parents = Lst_Init (FALSE);
2290 suffNull->ref = Lst_Init (FALSE);
2291 suffNull->sNum = sNum++;
2292 suffNull->flags = SUFF_NULL;
2293 suffNull->refCount = 1;
2294
2295}
2296
2297
2298/*-
2299 *----------------------------------------------------------------------
2300 * Suff_End --
2301 * Cleanup the this module
2302 *
2303 * Results:
2304 * None
2305 *
2306 * Side Effects:
2307 * The memory is free'd.
2308 *----------------------------------------------------------------------
2309 */
2310
2311void
2312Suff_End()
2313{
2314 Lst_Destroy(sufflist, SuffFree);
2315 Lst_Destroy(suffClean, SuffFree);
2316 if (suffNull)
2317 SuffFree(suffNull);
2318 Lst_Destroy(srclist, NOFREE);
2319 Lst_Destroy(transforms, NOFREE);
2320}
2321
2322
2323/********************* DEBUGGING FUNCTIONS **********************/
2324
2325static int SuffPrintName(s, dummy)
2326 void * s;
2327 void * dummy;
2328{
2329 printf ("`%s' ", ((Suff *) s)->name);
2330 return (dummy ? 0 : 0);
2331}
2332
2333static int
2334SuffPrintSuff (sp, dummy)
2335 void * sp;
2336 void * dummy;
2337{
2338 Suff *s = (Suff *) sp;
2339 int flags;
2340 int flag;
2341
2342 printf ("# `%s' [%d] ", s->name, s->refCount);
2343
2344 flags = s->flags;
2345 if (flags) {
2346 fputs (" (", stdout);
2347 while (flags) {
2348 flag = 1 << (ffs(flags) - 1);
2349 flags &= ~flag;
2350 switch (flag) {
2351 case SUFF_NULL:
2352 printf ("NULL");
2353 break;
2354 case SUFF_INCLUDE:
2355 printf ("INCLUDE");
2356 break;
2357 case SUFF_LIBRARY:
2358 printf ("LIBRARY");
2359 break;
2360 }
2361 fputc(flags ? '|' : ')', stdout);
2362 }
2363 }
2364 fputc ('\n', stdout);
2365 printf ("#\tTo: ");
2366 Lst_ForEach (s->parents, SuffPrintName, (void *)0);
2367 fputc ('\n', stdout);
2368 printf ("#\tFrom: ");
2369 Lst_ForEach (s->children, SuffPrintName, (void *)0);
2370 fputc ('\n', stdout);
2371 printf ("#\tSearch Path: ");
2372 Dir_PrintPath (s->searchPath);
2373 fputc ('\n', stdout);
2374 return (dummy ? 0 : 0);
2375}
2376
2377static int
2378SuffPrintTrans (tp, dummy)
2379 void * tp;
2380 void * dummy;
2381{
2382 GNode *t = (GNode *) tp;
2383
2384 printf ("%-16s: ", t->name);
2385 Targ_PrintType (t->type);
2386 fputc ('\n', stdout);
2387 Lst_ForEach (t->commands, Targ_PrintCmd, (void *)0);
2388 fputc ('\n', stdout);
2389 return(dummy ? 0 : 0);
2390}
2391
2392void
2393Suff_PrintAll()
2394{
2395 printf ("#*** Suffixes:\n");
2396 Lst_ForEach (sufflist, SuffPrintSuff, (void *)0);
2397
2398 printf ("#*** Transformations:\n");
2399 Lst_ForEach (transforms, SuffPrintTrans, (void *)0);
2400}
2178
2179 if (gn->type & OP_ARCHV) {
2180 SuffFindArchiveDeps(gn, slst);
2181 } else if (gn->type & OP_LIB) {
2182 /*
2183 * If the node is a library, it is the arch module's job to find it
2184 * and set the TARGET variable accordingly. We merely provide the
2185 * search path, assuming all libraries end in ".a" (if the suffix
2186 * hasn't been defined, there's nothing we can do for it, so we just
2187 * set the TARGET variable to the node's name in order to give it a
2188 * value).
2189 */
2190 LstNode ln;
2191 Suff *s;
2192
2193 ln = Lst_Find (sufflist, (void *)LIBSUFF, SuffSuffHasNameP);
2194 if (gn->suffix)
2195 gn->suffix->refCount--;
2196 if (ln != NULL) {
2197 gn->suffix = s = (Suff *) Lst_Datum (ln);
2198 gn->suffix->refCount++;
2199 Arch_FindLib (gn, s->searchPath);
2200 } else {
2201 gn->suffix = NULL;
2202 Var_Set (TARGET, gn->name, gn);
2203 }
2204 /*
2205 * Because a library (-lfoo) target doesn't follow the standard
2206 * filesystem conventions, we don't set the regular variables for
2207 * the thing. .PREFIX is simply made empty...
2208 */
2209 Var_Set(PREFIX, "", gn);
2210 } else {
2211 SuffFindNormalDeps(gn, slst);
2212 }
2213}
2214
2215/*-
2216 *-----------------------------------------------------------------------
2217 * Suff_SetNull --
2218 * Define which suffix is the null suffix.
2219 *
2220 * Results:
2221 * None.
2222 *
2223 * Side Effects:
2224 * 'suffNull' is altered.
2225 *
2226 * Notes:
2227 * Need to handle the changing of the null suffix gracefully so the
2228 * old transformation rules don't just go away.
2229 *
2230 *-----------------------------------------------------------------------
2231 */
2232void
2233Suff_SetNull(name)
2234 char *name; /* Name of null suffix */
2235{
2236 Suff *s;
2237 LstNode ln;
2238
2239 ln = Lst_Find(sufflist, (void *)name, SuffSuffHasNameP);
2240 if (ln != NULL) {
2241 s = (Suff *)Lst_Datum(ln);
2242 if (suffNull != (Suff *)NULL) {
2243 suffNull->flags &= ~SUFF_NULL;
2244 }
2245 s->flags |= SUFF_NULL;
2246 /*
2247 * XXX: Here's where the transformation mangling would take place
2248 */
2249 suffNull = s;
2250 } else {
2251 Parse_Error (PARSE_WARNING, "Desired null suffix %s not defined.",
2252 name);
2253 }
2254}
2255
2256/*-
2257 *-----------------------------------------------------------------------
2258 * Suff_Init --
2259 * Initialize suffixes module
2260 *
2261 * Results:
2262 * None
2263 *
2264 * Side Effects:
2265 * Many
2266 *-----------------------------------------------------------------------
2267 */
2268void
2269Suff_Init ()
2270{
2271 sufflist = Lst_Init (FALSE);
2272 suffClean = Lst_Init(FALSE);
2273 srclist = Lst_Init (FALSE);
2274 transforms = Lst_Init (FALSE);
2275
2276 sNum = 0;
2277 /*
2278 * Create null suffix for single-suffix rules (POSIX). The thing doesn't
2279 * actually go on the suffix list or everyone will think that's its
2280 * suffix.
2281 */
2282 emptySuff = suffNull = (Suff *) emalloc (sizeof (Suff));
2283
2284 suffNull->name = estrdup ("");
2285 suffNull->nameLen = 0;
2286 suffNull->searchPath = Lst_Init (FALSE);
2287 Dir_Concat(suffNull->searchPath, dirSearchPath);
2288 suffNull->children = Lst_Init (FALSE);
2289 suffNull->parents = Lst_Init (FALSE);
2290 suffNull->ref = Lst_Init (FALSE);
2291 suffNull->sNum = sNum++;
2292 suffNull->flags = SUFF_NULL;
2293 suffNull->refCount = 1;
2294
2295}
2296
2297
2298/*-
2299 *----------------------------------------------------------------------
2300 * Suff_End --
2301 * Cleanup the this module
2302 *
2303 * Results:
2304 * None
2305 *
2306 * Side Effects:
2307 * The memory is free'd.
2308 *----------------------------------------------------------------------
2309 */
2310
2311void
2312Suff_End()
2313{
2314 Lst_Destroy(sufflist, SuffFree);
2315 Lst_Destroy(suffClean, SuffFree);
2316 if (suffNull)
2317 SuffFree(suffNull);
2318 Lst_Destroy(srclist, NOFREE);
2319 Lst_Destroy(transforms, NOFREE);
2320}
2321
2322
2323/********************* DEBUGGING FUNCTIONS **********************/
2324
2325static int SuffPrintName(s, dummy)
2326 void * s;
2327 void * dummy;
2328{
2329 printf ("`%s' ", ((Suff *) s)->name);
2330 return (dummy ? 0 : 0);
2331}
2332
2333static int
2334SuffPrintSuff (sp, dummy)
2335 void * sp;
2336 void * dummy;
2337{
2338 Suff *s = (Suff *) sp;
2339 int flags;
2340 int flag;
2341
2342 printf ("# `%s' [%d] ", s->name, s->refCount);
2343
2344 flags = s->flags;
2345 if (flags) {
2346 fputs (" (", stdout);
2347 while (flags) {
2348 flag = 1 << (ffs(flags) - 1);
2349 flags &= ~flag;
2350 switch (flag) {
2351 case SUFF_NULL:
2352 printf ("NULL");
2353 break;
2354 case SUFF_INCLUDE:
2355 printf ("INCLUDE");
2356 break;
2357 case SUFF_LIBRARY:
2358 printf ("LIBRARY");
2359 break;
2360 }
2361 fputc(flags ? '|' : ')', stdout);
2362 }
2363 }
2364 fputc ('\n', stdout);
2365 printf ("#\tTo: ");
2366 Lst_ForEach (s->parents, SuffPrintName, (void *)0);
2367 fputc ('\n', stdout);
2368 printf ("#\tFrom: ");
2369 Lst_ForEach (s->children, SuffPrintName, (void *)0);
2370 fputc ('\n', stdout);
2371 printf ("#\tSearch Path: ");
2372 Dir_PrintPath (s->searchPath);
2373 fputc ('\n', stdout);
2374 return (dummy ? 0 : 0);
2375}
2376
2377static int
2378SuffPrintTrans (tp, dummy)
2379 void * tp;
2380 void * dummy;
2381{
2382 GNode *t = (GNode *) tp;
2383
2384 printf ("%-16s: ", t->name);
2385 Targ_PrintType (t->type);
2386 fputc ('\n', stdout);
2387 Lst_ForEach (t->commands, Targ_PrintCmd, (void *)0);
2388 fputc ('\n', stdout);
2389 return(dummy ? 0 : 0);
2390}
2391
2392void
2393Suff_PrintAll()
2394{
2395 printf ("#*** Suffixes:\n");
2396 Lst_ForEach (sufflist, SuffPrintSuff, (void *)0);
2397
2398 printf ("#*** Transformations:\n");
2399 Lst_ForEach (transforms, SuffPrintTrans, (void *)0);
2400}