Fri Aug 28 06:37:21 2020 UTC ()
make(1): fix assertion failure in suffix handling

Found by running ./build.sh, in the very early stage.
Fixed by restoring the previous behavior of returning NULL for invalid
arguments.


(rillig)
diff -r1.125 -r1.126 src/usr.bin/make/suff.c

cvs diff -r1.125 -r1.126 src/usr.bin/make/suff.c (switch to unified diff)

--- src/usr.bin/make/suff.c 2020/08/28 04:48:57 1.125
+++ src/usr.bin/make/suff.c 2020/08/28 06:37:21 1.126
@@ -1,1627 +1,1629 @@ @@ -1,1627 +1,1629 @@
1/* $NetBSD: suff.c,v 1.125 2020/08/28 04:48:57 rillig Exp $ */ 1/* $NetBSD: suff.c,v 1.126 2020/08/28 06:37:21 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors 54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: suff.c,v 1.125 2020/08/28 04:48:57 rillig Exp $"; 72static char rcsid[] = "$NetBSD: suff.c,v 1.126 2020/08/28 06:37:21 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; 77static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
78#else 78#else
79__RCSID("$NetBSD: suff.c,v 1.125 2020/08/28 04:48:57 rillig Exp $"); 79__RCSID("$NetBSD: suff.c,v 1.126 2020/08/28 06:37:21 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * suff.c -- 85 * suff.c --
86 * Functions to maintain suffix lists and find implicit dependents 86 * Functions to maintain suffix lists and find implicit dependents
87 * using suffix transformation rules 87 * using suffix transformation rules
88 * 88 *
89 * Interface: 89 * Interface:
90 * Suff_Init Initialize all things to do with suffixes. 90 * Suff_Init Initialize all things to do with suffixes.
91 * 91 *
92 * Suff_End Cleanup the module 92 * Suff_End Cleanup the module
93 * 93 *
94 * Suff_DoPaths This function is used to make life easier 94 * Suff_DoPaths This function is used to make life easier
95 * when searching for a file according to its 95 * when searching for a file according to its
96 * suffix. It takes the global search path, 96 * suffix. It takes the global search path,
97 * as defined using the .PATH: target, and appends 97 * as defined using the .PATH: target, and appends
98 * its directories to the path of each of the 98 * its directories to the path of each of the
99 * defined suffixes, as specified using 99 * defined suffixes, as specified using
100 * .PATH<suffix>: targets. In addition, all 100 * .PATH<suffix>: targets. In addition, all
101 * directories given for suffixes labeled as 101 * directories given for suffixes labeled as
102 * include files or libraries, using the .INCLUDES 102 * include files or libraries, using the .INCLUDES
103 * or .LIBS targets, are played with using 103 * or .LIBS targets, are played with using
104 * Dir_MakeFlags to create the .INCLUDES and 104 * Dir_MakeFlags to create the .INCLUDES and
105 * .LIBS global variables. 105 * .LIBS global variables.
106 * 106 *
107 * Suff_ClearSuffixes Clear out all the suffixes and defined 107 * Suff_ClearSuffixes Clear out all the suffixes and defined
108 * transformations. 108 * transformations.
109 * 109 *
110 * Suff_IsTransform Return TRUE if the passed string is the lhs 110 * Suff_IsTransform Return TRUE if the passed string is the lhs
111 * of a transformation rule. 111 * of a transformation rule.
112 * 112 *
113 * Suff_AddSuffix Add the passed string as another known suffix. 113 * Suff_AddSuffix Add the passed string as another known suffix.
114 * 114 *
115 * Suff_GetPath Return the search path for the given suffix. 115 * Suff_GetPath Return the search path for the given suffix.
116 * 116 *
117 * Suff_AddInclude Mark the given suffix as denoting an include 117 * Suff_AddInclude Mark the given suffix as denoting an include
118 * file. 118 * file.
119 * 119 *
120 * Suff_AddLib Mark the given suffix as denoting a library. 120 * Suff_AddLib Mark the given suffix as denoting a library.
121 * 121 *
122 * Suff_AddTransform Add another transformation to the suffix 122 * Suff_AddTransform Add another transformation to the suffix
123 * graph. Returns GNode suitable for framing, I 123 * graph. Returns GNode suitable for framing, I
124 * mean, tacking commands, attributes, etc. on. 124 * mean, tacking commands, attributes, etc. on.
125 * 125 *
126 * Suff_SetNull Define the suffix to consider the suffix of 126 * Suff_SetNull Define the suffix to consider the suffix of
127 * any file that doesn't have a known one. 127 * any file that doesn't have a known one.
128 * 128 *
129 * Suff_FindDeps Find implicit sources for and the location of 129 * Suff_FindDeps Find implicit sources for and the location of
130 * a target based on its suffix. Returns the 130 * a target based on its suffix. Returns the
131 * bottom-most node added to the graph or NULL 131 * bottom-most node added to the graph or NULL
132 * if the target had no implicit sources. 132 * if the target had no implicit sources.
133 * 133 *
134 * Suff_FindPath Return the appropriate path to search in 134 * Suff_FindPath Return the appropriate path to search in
135 * order to find the node. 135 * order to find the node.
136 */ 136 */
137 137
138#include "make.h" 138#include "make.h"
139#include "dir.h" 139#include "dir.h"
140 140
141static Lst sufflist; /* Lst of suffixes */ 141static Lst sufflist; /* Lst of suffixes */
142#ifdef CLEANUP 142#ifdef CLEANUP
143static Lst suffClean; /* Lst of suffixes to be cleaned */ 143static Lst suffClean; /* Lst of suffixes to be cleaned */
144#endif 144#endif
145static Lst srclist; /* Lst of sources */ 145static Lst srclist; /* Lst of sources */
146static Lst transforms; /* Lst of transformation rules */ 146static Lst transforms; /* Lst of transformation rules */
147 147
148static int sNum = 0; /* Counter for assigning suffix numbers */ 148static int sNum = 0; /* Counter for assigning suffix numbers */
149 149
150typedef enum { 150typedef enum {
151 SUFF_INCLUDE = 0x01, /* One which is #include'd */ 151 SUFF_INCLUDE = 0x01, /* One which is #include'd */
152 SUFF_LIBRARY = 0x02, /* One which contains a library */ 152 SUFF_LIBRARY = 0x02, /* One which contains a library */
153 SUFF_NULL = 0x04 /* The empty suffix */ 153 SUFF_NULL = 0x04 /* The empty suffix */
154 /* XXX: Why is SUFF_NULL needed? Wouldn't nameLen == 0 mean the same? */ 154 /* XXX: Why is SUFF_NULL needed? Wouldn't nameLen == 0 mean the same? */
155} SuffFlags; 155} SuffFlags;
156 156
157ENUM_FLAGS_RTTI_3(SuffFlags, 157ENUM_FLAGS_RTTI_3(SuffFlags,
158 SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL); 158 SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL);
159 159
160/* 160/*
161 * Structure describing an individual suffix. 161 * Structure describing an individual suffix.
162 */ 162 */
163typedef struct Suff { 163typedef struct Suff {
164 char *name; /* The suffix itself, such as ".c" */ 164 char *name; /* The suffix itself, such as ".c" */
165 int nameLen; /* Length of the name, to avoid strlen calls */ 165 int nameLen; /* Length of the name, to avoid strlen calls */
166 SuffFlags flags; /* Type of suffix */ 166 SuffFlags flags; /* Type of suffix */
167 Lst searchPath; /* The path along which files of this suffix 167 Lst searchPath; /* The path along which files of this suffix
168 * may be found */ 168 * may be found */
169 int sNum; /* The suffix number */ 169 int sNum; /* The suffix number */
170 int refCount; /* Reference count of list membership */ 170 int refCount; /* Reference count of list membership */
171 Lst parents; /* Suffixes we have a transformation to */ 171 Lst parents; /* Suffixes we have a transformation to */
172 Lst children; /* Suffixes we have a transformation from */ 172 Lst children; /* Suffixes we have a transformation from */
173 Lst ref; /* List of lists this suffix is referenced */ 173 Lst ref; /* List of lists this suffix is referenced */
174} Suff; 174} Suff;
175 175
176/* 176/*
177 * for SuffSuffIsSuffix 177 * for SuffSuffIsSuffix
178 */ 178 */
179typedef struct { 179typedef struct {
180 char *ename; /* The end of the name */ 180 char *ename; /* The end of the name */
181 int len; /* Length of the name */ 181 int len; /* Length of the name */
182} SuffixCmpData; 182} SuffixCmpData;
183 183
184/* 184/*
185 * Structure used in the search for implied sources. 185 * Structure used in the search for implied sources.
186 */ 186 */
187typedef struct _Src { 187typedef struct _Src {
188 char *file; /* The file to look for */ 188 char *file; /* The file to look for */
189 char *pref; /* Prefix from which file was formed */ 189 char *pref; /* Prefix from which file was formed */
190 Suff *suff; /* The suffix on the file */ 190 Suff *suff; /* The suffix on the file */
191 struct _Src *parent; /* The Src for which this is a source */ 191 struct _Src *parent; /* The Src for which this is a source */
192 GNode *node; /* The node describing the file */ 192 GNode *node; /* The node describing the file */
193 int children; /* Count of existing children (so we don't free 193 int children; /* Count of existing children (so we don't free
194 * this thing too early or never nuke it) */ 194 * this thing too early or never nuke it) */
195#ifdef DEBUG_SRC 195#ifdef DEBUG_SRC
196 Lst cp; /* Debug; children list */ 196 Lst cp; /* Debug; children list */
197#endif 197#endif
198} Src; 198} Src;
199 199
200/* 200/*
201 * A structure for passing more than one argument to the Lst-library-invoked 201 * A structure for passing more than one argument to the Lst-library-invoked
202 * function... 202 * function...
203 */ 203 */
204typedef struct { 204typedef struct {
205 Lst l; 205 Lst l;
206 Src *s; 206 Src *s;
207} LstSrc; 207} LstSrc;
208 208
209typedef struct { 209typedef struct {
210 GNode **gn; 210 GNode **gn;
211 Suff *s; 211 Suff *s;
212 Boolean r; 212 Boolean r;
213} GNodeSuff; 213} GNodeSuff;
214 214
215static Suff *suffNull; /* The NULL suffix for this run */ 215static Suff *suffNull; /* The NULL suffix for this run */
216static Suff *emptySuff; /* The empty suffix required for POSIX 216static Suff *emptySuff; /* The empty suffix required for POSIX
217 * single-suffix transformation rules */ 217 * single-suffix transformation rules */
218 218
219 219
220static const char *SuffStrIsPrefix(const char *, const char *); 220static const char *SuffStrIsPrefix(const char *, const char *);
221static char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *); 221static char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *);
222static int SuffSuffIsSuffixP(const void *, const void *); 222static int SuffSuffIsSuffixP(const void *, const void *);
223static int SuffSuffHasNameP(const void *, const void *); 223static int SuffSuffHasNameP(const void *, const void *);
224static int SuffSuffIsPrefix(const void *, const void *); 224static int SuffSuffIsPrefix(const void *, const void *);
225static int SuffGNHasNameP(const void *, const void *); 225static int SuffGNHasNameP(const void *, const void *);
226static void SuffUnRef(void *, void *); 226static void SuffUnRef(void *, void *);
227static void SuffFree(void *); 227static void SuffFree(void *);
228static void SuffInsert(Lst, Suff *); 228static void SuffInsert(Lst, Suff *);
229static void SuffRemove(Lst, Suff *); 229static void SuffRemove(Lst, Suff *);
230static Boolean SuffParseTransform(char *, Suff **, Suff **); 230static Boolean SuffParseTransform(char *, Suff **, Suff **);
231static int SuffRebuildGraph(void *, void *); 231static int SuffRebuildGraph(void *, void *);
232static int SuffScanTargets(void *, void *); 232static int SuffScanTargets(void *, void *);
233static int SuffAddSrc(void *, void *); 233static int SuffAddSrc(void *, void *);
234static int SuffRemoveSrc(Lst); 234static int SuffRemoveSrc(Lst);
235static void SuffAddLevel(Lst, Src *); 235static void SuffAddLevel(Lst, Src *);
236static Src *SuffFindCmds(Src *, Lst); 236static Src *SuffFindCmds(Src *, Lst);
237static void SuffExpandChildren(LstNode, GNode *); 237static void SuffExpandChildren(LstNode, GNode *);
238static void SuffExpandWildcards(LstNode, GNode *); 238static void SuffExpandWildcards(LstNode, GNode *);
239static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); 239static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
240static void SuffFindDeps(GNode *, Lst); 240static void SuffFindDeps(GNode *, Lst);
241static void SuffFindArchiveDeps(GNode *, Lst); 241static void SuffFindArchiveDeps(GNode *, Lst);
242static void SuffFindNormalDeps(GNode *, Lst); 242static void SuffFindNormalDeps(GNode *, Lst);
243static int SuffPrintName(void *, void *); 243static int SuffPrintName(void *, void *);
244static int SuffPrintSuff(void *, void *); 244static int SuffPrintSuff(void *, void *);
245static int SuffPrintTrans(void *, void *); 245static int SuffPrintTrans(void *, void *);
246 246
247 /*************** Lst Predicates ****************/ 247 /*************** Lst Predicates ****************/
248/*- 248/*-
249 *----------------------------------------------------------------------- 249 *-----------------------------------------------------------------------
250 * SuffStrIsPrefix -- 250 * SuffStrIsPrefix --
251 * See if pref is a prefix of str. 251 * See if pref is a prefix of str.
252 * 252 *
253 * Input: 253 * Input:
254 * pref possible prefix 254 * pref possible prefix
255 * str string to check 255 * str string to check
256 * 256 *
257 * Results: 257 * Results:
258 * NULL if it ain't, pointer to character in str after prefix if so 258 * NULL if it ain't, pointer to character in str after prefix if so
259 * 259 *
260 * Side Effects: 260 * Side Effects:
261 * None 261 * None
262 *----------------------------------------------------------------------- 262 *-----------------------------------------------------------------------
263 */ 263 */
264static const char * 264static const char *
265SuffStrIsPrefix(const char *pref, const char *str) 265SuffStrIsPrefix(const char *pref, const char *str)
266{ 266{
267 while (*str && *pref == *str) { 267 while (*str && *pref == *str) {
268 pref++; 268 pref++;
269 str++; 269 str++;
270 } 270 }
271 271
272 return *pref ? NULL : str; 272 return *pref ? NULL : str;
273} 273}
274 274
275/*- 275/*-
276 *----------------------------------------------------------------------- 276 *-----------------------------------------------------------------------
277 * SuffSuffIsSuffix -- 277 * SuffSuffIsSuffix --
278 * See if suff is a suffix of str. sd->ename should point to THE END 278 * See if suff is a suffix of str. sd->ename should point to THE END
279 * of the string to check. (THE END == the null byte) 279 * of the string to check. (THE END == the null byte)
280 * 280 *
281 * Input: 281 * Input:
282 * s possible suffix 282 * s possible suffix
283 * sd string to examine 283 * sd string to examine
284 * 284 *
285 * Results: 285 * Results:
286 * NULL if it ain't, pointer to character in str before suffix if 286 * NULL if it ain't, pointer to character in str before suffix if
287 * it is. 287 * it is.
288 * 288 *
289 * Side Effects: 289 * Side Effects:
290 * None 290 * None
291 *----------------------------------------------------------------------- 291 *-----------------------------------------------------------------------
292 */ 292 */
293static char * 293static char *
294SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd) 294SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd)
295{ 295{
296 char *p1; /* Pointer into suffix name */ 296 char *p1; /* Pointer into suffix name */
297 char *p2; /* Pointer into string being examined */ 297 char *p2; /* Pointer into string being examined */
298 298
299 if (sd->len < s->nameLen) 299 if (sd->len < s->nameLen)
300 return NULL; /* this string is shorter than the suffix */ 300 return NULL; /* this string is shorter than the suffix */
301 301
302 p1 = s->name + s->nameLen; 302 p1 = s->name + s->nameLen;
303 p2 = sd->ename; 303 p2 = sd->ename;
304 304
305 while (p1 >= s->name && *p1 == *p2) { 305 while (p1 >= s->name && *p1 == *p2) {
306 p1--; 306 p1--;
307 p2--; 307 p2--;
308 } 308 }
309 309
310 return p1 == s->name - 1 ? p2 : NULL; 310 return p1 == s->name - 1 ? p2 : NULL;
311} 311}
312 312
313/*- 313/*-
314 *----------------------------------------------------------------------- 314 *-----------------------------------------------------------------------
315 * SuffSuffIsSuffixP -- 315 * SuffSuffIsSuffixP --
316 * Predicate form of SuffSuffIsSuffix. Passed as the callback function 316 * Predicate form of SuffSuffIsSuffix. Passed as the callback function
317 * to Lst_Find. 317 * to Lst_Find.
318 * 318 *
319 * Results: 319 * Results:
320 * 0 if the suffix is the one desired, non-zero if not. 320 * 0 if the suffix is the one desired, non-zero if not.
321 * 321 *
322 * Side Effects: 322 * Side Effects:
323 * None. 323 * None.
324 * 324 *
325 *----------------------------------------------------------------------- 325 *-----------------------------------------------------------------------
326 */ 326 */
327static int 327static int
328SuffSuffIsSuffixP(const void *s, const void *sd) 328SuffSuffIsSuffixP(const void *s, const void *sd)
329{ 329{
330 return !SuffSuffIsSuffix(s, sd); 330 return !SuffSuffIsSuffix(s, sd);
331} 331}
332 332
333/*- 333/*-
334 *----------------------------------------------------------------------- 334 *-----------------------------------------------------------------------
335 * SuffSuffHasNameP -- 335 * SuffSuffHasNameP --
336 * Callback procedure for finding a suffix based on its name. Used by 336 * Callback procedure for finding a suffix based on its name. Used by
337 * Suff_GetPath. 337 * Suff_GetPath.
338 * 338 *
339 * Input: 339 * Input:
340 * s Suffix to check 340 * s Suffix to check
341 * sd Desired name 341 * sd Desired name
342 * 342 *
343 * Results: 343 * Results:
344 * 0 if the suffix is of the given name. non-zero otherwise. 344 * 0 if the suffix is of the given name. non-zero otherwise.
345 * 345 *
346 * Side Effects: 346 * Side Effects:
347 * None 347 * None
348 *----------------------------------------------------------------------- 348 *-----------------------------------------------------------------------
349 */ 349 */
350static int 350static int
351SuffSuffHasNameP(const void *s, const void *sname) 351SuffSuffHasNameP(const void *s, const void *sname)
352{ 352{
353 return strcmp(sname, ((const Suff *)s)->name); 353 return strcmp(sname, ((const Suff *)s)->name);
354} 354}
355 355
356/*- 356/*-
357 *----------------------------------------------------------------------- 357 *-----------------------------------------------------------------------
358 * SuffSuffIsPrefix -- 358 * SuffSuffIsPrefix --
359 * See if the suffix described by s is a prefix of the string. Care 359 * See if the suffix described by s is a prefix of the string. Care
360 * must be taken when using this to search for transformations and 360 * must be taken when using this to search for transformations and
361 * what-not, since there could well be two suffixes, one of which 361 * what-not, since there could well be two suffixes, one of which
362 * is a prefix of the other... 362 * is a prefix of the other...
363 * 363 *
364 * Input: 364 * Input:
365 * s suffix to compare 365 * s suffix to compare
366 * str string to examine 366 * str string to examine
367 * 367 *
368 * Results: 368 * Results:
369 * 0 if s is a prefix of str. non-zero otherwise 369 * 0 if s is a prefix of str. non-zero otherwise
370 * 370 *
371 * Side Effects: 371 * Side Effects:
372 * None 372 * None
373 *----------------------------------------------------------------------- 373 *-----------------------------------------------------------------------
374 */ 374 */
375static int 375static int
376SuffSuffIsPrefix(const void *s, const void *str) 376SuffSuffIsPrefix(const void *s, const void *str)
377{ 377{
378 return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL; 378 return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL;
379} 379}
380 380
381/*- 381/*-
382 *----------------------------------------------------------------------- 382 *-----------------------------------------------------------------------
383 * SuffGNHasNameP -- 383 * SuffGNHasNameP --
384 * See if the graph node has the desired name 384 * See if the graph node has the desired name
385 * 385 *
386 * Input: 386 * Input:
387 * gn current node we're looking at 387 * gn current node we're looking at
388 * name name we're looking for 388 * name name we're looking for
389 * 389 *
390 * Results: 390 * Results:
391 * 0 if it does. non-zero if it doesn't 391 * 0 if it does. non-zero if it doesn't
392 * 392 *
393 * Side Effects: 393 * Side Effects:
394 * None 394 * None
395 *----------------------------------------------------------------------- 395 *-----------------------------------------------------------------------
396 */ 396 */
397static int 397static int
398SuffGNHasNameP(const void *gn, const void *name) 398SuffGNHasNameP(const void *gn, const void *name)
399{ 399{
400 return strcmp(name, ((const GNode *)gn)->name); 400 return strcmp(name, ((const GNode *)gn)->name);
401} 401}
402 402
403 /*********** Maintenance Functions ************/ 403 /*********** Maintenance Functions ************/
404 404
405static void 405static void
406SuffUnRef(void *lp, void *sp) 406SuffUnRef(void *lp, void *sp)
407{ 407{
408 Lst l = (Lst) lp; 408 Lst l = (Lst) lp;
409 409
410 LstNode ln = Lst_Member(l, sp); 410 LstNode ln = Lst_Member(l, sp);
411 if (ln != NULL) { 411 if (ln != NULL) {
412 Lst_Remove(l, ln); 412 Lst_Remove(l, ln);
413 ((Suff *)sp)->refCount--; 413 ((Suff *)sp)->refCount--;
414 } 414 }
415} 415}
416 416
417/*- 417/*-
418 *----------------------------------------------------------------------- 418 *-----------------------------------------------------------------------
419 * SuffFree -- 419 * SuffFree --
420 * Free up all memory associated with the given suffix structure. 420 * Free up all memory associated with the given suffix structure.
421 * 421 *
422 * Results: 422 * Results:
423 * none 423 * none
424 * 424 *
425 * Side Effects: 425 * Side Effects:
426 * the suffix entry is detroyed 426 * the suffix entry is detroyed
427 *----------------------------------------------------------------------- 427 *-----------------------------------------------------------------------
428 */ 428 */
429static void 429static void
430SuffFree(void *sp) 430SuffFree(void *sp)
431{ 431{
432 Suff *s = (Suff *)sp; 432 Suff *s = (Suff *)sp;
433 433
434 if (s == suffNull) 434 if (s == suffNull)
435 suffNull = NULL; 435 suffNull = NULL;
436 436
437 if (s == emptySuff) 437 if (s == emptySuff)
438 emptySuff = NULL; 438 emptySuff = NULL;
439 439
440#ifdef notdef 440#ifdef notdef
441 /* We don't delete suffixes in order, so we cannot use this */ 441 /* We don't delete suffixes in order, so we cannot use this */
442 if (s->refCount) 442 if (s->refCount)
443 Punt("Internal error deleting suffix `%s' with refcount = %d", s->name, 443 Punt("Internal error deleting suffix `%s' with refcount = %d", s->name,
444 s->refCount); 444 s->refCount);
445#endif 445#endif
446 446
447 Lst_Free(s->ref); 447 Lst_Free(s->ref);
448 Lst_Free(s->children); 448 Lst_Free(s->children);
449 Lst_Free(s->parents); 449 Lst_Free(s->parents);
450 Lst_Destroy(s->searchPath, Dir_Destroy); 450 Lst_Destroy(s->searchPath, Dir_Destroy);
451 451
452 free(s->name); 452 free(s->name);
453 free(s); 453 free(s);
454} 454}
455 455
456/*- 456/*-
457 *----------------------------------------------------------------------- 457 *-----------------------------------------------------------------------
458 * SuffRemove -- 458 * SuffRemove --
459 * Remove the suffix into the list 459 * Remove the suffix into the list
460 * 460 *
461 * Results: 461 * Results:
462 * None 462 * None
463 * 463 *
464 * Side Effects: 464 * Side Effects:
465 * The reference count for the suffix is decremented and the 465 * The reference count for the suffix is decremented and the
466 * suffix is possibly freed 466 * suffix is possibly freed
467 *----------------------------------------------------------------------- 467 *-----------------------------------------------------------------------
468 */ 468 */
469static void 469static void
470SuffRemove(Lst l, Suff *s) 470SuffRemove(Lst l, Suff *s)
471{ 471{
472 SuffUnRef(l, s); 472 SuffUnRef(l, s);
473 if (s->refCount == 0) { 473 if (s->refCount == 0) {
474 SuffUnRef(sufflist, s); 474 SuffUnRef(sufflist, s);
475 SuffFree(s); 475 SuffFree(s);
476 } 476 }
477} 477}
478 478
479/*- 479/*-
480 *----------------------------------------------------------------------- 480 *-----------------------------------------------------------------------
481 * SuffInsert -- 481 * SuffInsert --
482 * Insert the suffix into the list keeping the list ordered by suffix 482 * Insert the suffix into the list keeping the list ordered by suffix
483 * numbers. 483 * numbers.
484 * 484 *
485 * Input: 485 * Input:
486 * l the list where in s should be inserted 486 * l the list where in s should be inserted
487 * s the suffix to insert 487 * s the suffix to insert
488 * 488 *
489 * Results: 489 * Results:
490 * None 490 * None
491 * 491 *
492 * Side Effects: 492 * Side Effects:
493 * The reference count of the suffix is incremented 493 * The reference count of the suffix is incremented
494 *----------------------------------------------------------------------- 494 *-----------------------------------------------------------------------
495 */ 495 */
496static void 496static void
497SuffInsert(Lst l, Suff *s) 497SuffInsert(Lst l, Suff *s)
498{ 498{
499 LstNode ln; /* current element in l we're examining */ 499 LstNode ln; /* current element in l we're examining */
500 Suff *s2 = NULL; /* the suffix descriptor in this element */ 500 Suff *s2 = NULL; /* the suffix descriptor in this element */
501 501
502 Lst_Open(l); 502 Lst_Open(l);
503 while ((ln = Lst_Next(l)) != NULL) { 503 while ((ln = Lst_Next(l)) != NULL) {
504 s2 = Lst_Datum(ln); 504 s2 = Lst_Datum(ln);
505 if (s2->sNum >= s->sNum) { 505 if (s2->sNum >= s->sNum) {
506 break; 506 break;
507 } 507 }
508 } 508 }
509 Lst_Close(l); 509 Lst_Close(l);
510 510
511 if (DEBUG(SUFF)) { 511 if (DEBUG(SUFF)) {
512 fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum); 512 fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum);
513 } 513 }
514 if (ln == NULL) { 514 if (ln == NULL) {
515 if (DEBUG(SUFF)) { 515 if (DEBUG(SUFF)) {
516 fprintf(debug_file, "at end of list\n"); 516 fprintf(debug_file, "at end of list\n");
517 } 517 }
518 Lst_Append(l, s); 518 Lst_Append(l, s);
519 s->refCount++; 519 s->refCount++;
520 Lst_Append(s->ref, l); 520 Lst_Append(s->ref, l);
521 } else if (s2->sNum != s->sNum) { 521 } else if (s2->sNum != s->sNum) {
522 if (DEBUG(SUFF)) { 522 if (DEBUG(SUFF)) {
523 fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum); 523 fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum);
524 } 524 }
525 Lst_InsertBefore(l, ln, s); 525 Lst_InsertBefore(l, ln, s);
526 s->refCount++; 526 s->refCount++;
527 Lst_Append(s->ref, l); 527 Lst_Append(s->ref, l);
528 } else if (DEBUG(SUFF)) { 528 } else if (DEBUG(SUFF)) {
529 fprintf(debug_file, "already there\n"); 529 fprintf(debug_file, "already there\n");
530 } 530 }
531} 531}
532 532
533static Suff * 533static Suff *
534SuffNew(const char *name) 534SuffNew(const char *name)
535{ 535{
536 Suff *s = bmake_malloc(sizeof(Suff)); 536 Suff *s = bmake_malloc(sizeof(Suff));
537 537
538 s->name = bmake_strdup(name); 538 s->name = bmake_strdup(name);
539 s->nameLen = strlen(s->name); 539 s->nameLen = strlen(s->name);
540 s->searchPath = Lst_Init(); 540 s->searchPath = Lst_Init();
541 s->children = Lst_Init(); 541 s->children = Lst_Init();
542 s->parents = Lst_Init(); 542 s->parents = Lst_Init();
543 s->ref = Lst_Init(); 543 s->ref = Lst_Init();
544 s->sNum = sNum++; 544 s->sNum = sNum++;
545 s->flags = 0; 545 s->flags = 0;
546 s->refCount = 1; 546 s->refCount = 1;
547 547
548 return s; 548 return s;
549} 549}
550 550
551/*- 551/*-
552 *----------------------------------------------------------------------- 552 *-----------------------------------------------------------------------
553 * Suff_ClearSuffixes -- 553 * Suff_ClearSuffixes --
554 * This is gross. Nuke the list of suffixes but keep all transformation 554 * This is gross. Nuke the list of suffixes but keep all transformation
555 * rules around. The transformation graph is destroyed in this process, 555 * rules around. The transformation graph is destroyed in this process,
556 * but we leave the list of rules so when a new graph is formed the rules 556 * but we leave the list of rules so when a new graph is formed the rules
557 * will remain. 557 * will remain.
558 * This function is called from the parse module when a 558 * This function is called from the parse module when a
559 * .SUFFIXES:\n line is encountered. 559 * .SUFFIXES:\n line is encountered.
560 * 560 *
561 * Results: 561 * Results:
562 * none 562 * none
563 * 563 *
564 * Side Effects: 564 * Side Effects:
565 * the sufflist and its graph nodes are destroyed 565 * the sufflist and its graph nodes are destroyed
566 *----------------------------------------------------------------------- 566 *-----------------------------------------------------------------------
567 */ 567 */
568void 568void
569Suff_ClearSuffixes(void) 569Suff_ClearSuffixes(void)
570{ 570{
571#ifdef CLEANUP 571#ifdef CLEANUP
572 Lst_MoveAll(suffClean, sufflist); 572 Lst_MoveAll(suffClean, sufflist);
573#endif 573#endif
574 sufflist = Lst_Init(); 574 sufflist = Lst_Init();
575 sNum = 0; 575 sNum = 0;
576 if (suffNull) 576 if (suffNull)
577 SuffFree(suffNull); 577 SuffFree(suffNull);
578 emptySuff = suffNull = SuffNew(""); 578 emptySuff = suffNull = SuffNew("");
579 579
580 Dir_Concat(suffNull->searchPath, dirSearchPath); 580 Dir_Concat(suffNull->searchPath, dirSearchPath);
581 suffNull->flags = SUFF_NULL; 581 suffNull->flags = SUFF_NULL;
582} 582}
583 583
584/*- 584/*-
585 *----------------------------------------------------------------------- 585 *-----------------------------------------------------------------------
586 * SuffParseTransform -- 586 * SuffParseTransform --
587 * Parse a transformation string to find its two component suffixes. 587 * Parse a transformation string to find its two component suffixes.
588 * 588 *
589 * Input: 589 * Input:
590 * str String being parsed 590 * str String being parsed
591 * srcPtr Place to store source of trans. 591 * srcPtr Place to store source of trans.
592 * targPtr Place to store target of trans. 592 * targPtr Place to store target of trans.
593 * 593 *
594 * Results: 594 * Results:
595 * TRUE if the string is a valid transformation and FALSE otherwise. 595 * TRUE if the string is a valid transformation and FALSE otherwise.
596 * 596 *
597 * Side Effects: 597 * Side Effects:
598 * The passed pointers are overwritten. 598 * The passed pointers are overwritten.
599 * 599 *
600 *----------------------------------------------------------------------- 600 *-----------------------------------------------------------------------
601 */ 601 */
602static Boolean 602static Boolean
603SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr) 603SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr)
604{ 604{
605 LstNode srcLn; /* element in suffix list of trans source*/ 605 LstNode srcLn; /* element in suffix list of trans source*/
606 Suff *src; /* Source of transformation */ 606 Suff *src; /* Source of transformation */
607 LstNode targLn; /* element in suffix list of trans target*/ 607 LstNode targLn; /* element in suffix list of trans target*/
608 char *str2; /* Extra pointer (maybe target suffix) */ 608 char *str2; /* Extra pointer (maybe target suffix) */
609 LstNode singleLn; /* element in suffix list of any suffix 609 LstNode singleLn; /* element in suffix list of any suffix
610 * that exactly matches str */ 610 * that exactly matches str */
611 Suff *single = NULL;/* Source of possible transformation to 611 Suff *single = NULL;/* Source of possible transformation to
612 * null suffix */ 612 * null suffix */
613 613
614 srcLn = NULL; 614 srcLn = NULL;
615 singleLn = NULL; 615 singleLn = NULL;
616 616
617 /* 617 /*
618 * Loop looking first for a suffix that matches the start of the 618 * Loop looking first for a suffix that matches the start of the
619 * string and then for one that exactly matches the rest of it. If 619 * string and then for one that exactly matches the rest of it. If
620 * we can find two that meet these criteria, we've successfully 620 * we can find two that meet these criteria, we've successfully
621 * parsed the string. 621 * parsed the string.
622 */ 622 */
623 for (;;) { 623 for (;;) {
624 if (srcLn == NULL) { 624 if (srcLn == NULL) {
625 srcLn = Lst_Find(sufflist, SuffSuffIsPrefix, str); 625 srcLn = Lst_Find(sufflist, SuffSuffIsPrefix, str);
626 } else { 626 } else {
627 srcLn = Lst_FindFrom(sufflist, Lst_Succ(srcLn), 627 LstNode succ = Lst_Succ(srcLn);
628 SuffSuffIsPrefix, str); 628 srcLn = succ != NULL
 629 ? Lst_FindFrom(sufflist, succ, SuffSuffIsPrefix, str)
 630 : NULL;
629 } 631 }
630 if (srcLn == NULL) { 632 if (srcLn == NULL) {
631 /* 633 /*
632 * Ran out of source suffixes -- no such rule 634 * Ran out of source suffixes -- no such rule
633 */ 635 */
634 if (singleLn != NULL) { 636 if (singleLn != NULL) {
635 /* 637 /*
636 * Not so fast Mr. Smith! There was a suffix that encompassed 638 * Not so fast Mr. Smith! There was a suffix that encompassed
637 * the entire string, so we assume it was a transformation 639 * the entire string, so we assume it was a transformation
638 * to the null suffix (thank you POSIX). We still prefer to 640 * to the null suffix (thank you POSIX). We still prefer to
639 * find a double rule over a singleton, hence we leave this 641 * find a double rule over a singleton, hence we leave this
640 * check until the end. 642 * check until the end.
641 * 643 *
642 * XXX: Use emptySuff over suffNull? 644 * XXX: Use emptySuff over suffNull?
643 */ 645 */
644 *srcPtr = single; 646 *srcPtr = single;
645 *targPtr = suffNull; 647 *targPtr = suffNull;
646 return TRUE; 648 return TRUE;
647 } 649 }
648 return FALSE; 650 return FALSE;
649 } 651 }
650 src = Lst_Datum(srcLn); 652 src = Lst_Datum(srcLn);
651 str2 = str + src->nameLen; 653 str2 = str + src->nameLen;
652 if (*str2 == '\0') { 654 if (*str2 == '\0') {
653 single = src; 655 single = src;
654 singleLn = srcLn; 656 singleLn = srcLn;
655 } else { 657 } else {
656 targLn = Lst_Find(sufflist, SuffSuffHasNameP, str2); 658 targLn = Lst_Find(sufflist, SuffSuffHasNameP, str2);
657 if (targLn != NULL) { 659 if (targLn != NULL) {
658 *srcPtr = src; 660 *srcPtr = src;
659 *targPtr = Lst_Datum(targLn); 661 *targPtr = Lst_Datum(targLn);
660 return TRUE; 662 return TRUE;
661 } 663 }
662 } 664 }
663 } 665 }
664} 666}
665 667
666/*- 668/*-
667 *----------------------------------------------------------------------- 669 *-----------------------------------------------------------------------
668 * Suff_IsTransform -- 670 * Suff_IsTransform --
669 * Return TRUE if the given string is a transformation rule 671 * Return TRUE if the given string is a transformation rule
670 * 672 *
671 * 673 *
672 * Input: 674 * Input:
673 * str string to check 675 * str string to check
674 * 676 *
675 * Results: 677 * Results:
676 * TRUE if the string is a concatenation of two known suffixes. 678 * TRUE if the string is a concatenation of two known suffixes.
677 * FALSE otherwise 679 * FALSE otherwise
678 * 680 *
679 * Side Effects: 681 * Side Effects:
680 * None 682 * None
681 *----------------------------------------------------------------------- 683 *-----------------------------------------------------------------------
682 */ 684 */
683Boolean 685Boolean
684Suff_IsTransform(char *str) 686Suff_IsTransform(char *str)
685{ 687{
686 Suff *src, *targ; 688 Suff *src, *targ;
687 689
688 return SuffParseTransform(str, &src, &targ); 690 return SuffParseTransform(str, &src, &targ);
689} 691}
690 692
691/*- 693/*-
692 *----------------------------------------------------------------------- 694 *-----------------------------------------------------------------------
693 * Suff_AddTransform -- 695 * Suff_AddTransform --
694 * Add the transformation rule described by the line to the 696 * Add the transformation rule described by the line to the
695 * list of rules and place the transformation itself in the graph 697 * list of rules and place the transformation itself in the graph
696 * 698 *
697 * Input: 699 * Input:
698 * line name of transformation to add 700 * line name of transformation to add
699 * 701 *
700 * Results: 702 * Results:
701 * The node created for the transformation in the transforms list 703 * The node created for the transformation in the transforms list
702 * 704 *
703 * Side Effects: 705 * Side Effects:
704 * The node is placed on the end of the transforms Lst and links are 706 * The node is placed on the end of the transforms Lst and links are
705 * made between the two suffixes mentioned in the target name 707 * made between the two suffixes mentioned in the target name
706 *----------------------------------------------------------------------- 708 *-----------------------------------------------------------------------
707 */ 709 */
708GNode * 710GNode *
709Suff_AddTransform(char *line) 711Suff_AddTransform(char *line)
710{ 712{
711 GNode *gn; /* GNode of transformation rule */ 713 GNode *gn; /* GNode of transformation rule */
712 Suff *s, /* source suffix */ 714 Suff *s, /* source suffix */
713 *t; /* target suffix */ 715 *t; /* target suffix */
714 LstNode ln; /* Node for existing transformation */ 716 LstNode ln; /* Node for existing transformation */
715 717
716 ln = Lst_Find(transforms, SuffGNHasNameP, line); 718 ln = Lst_Find(transforms, SuffGNHasNameP, line);
717 if (ln == NULL) { 719 if (ln == NULL) {
718 /* 720 /*
719 * Make a new graph node for the transformation. It will be filled in 721 * Make a new graph node for the transformation. It will be filled in
720 * by the Parse module. 722 * by the Parse module.
721 */ 723 */
722 gn = Targ_NewGN(line); 724 gn = Targ_NewGN(line);
723 Lst_Append(transforms, gn); 725 Lst_Append(transforms, gn);
724 } else { 726 } else {
725 /* 727 /*
726 * New specification for transformation rule. Just nuke the old list 728 * New specification for transformation rule. Just nuke the old list
727 * of commands so they can be filled in again... We don't actually 729 * of commands so they can be filled in again... We don't actually
728 * free the commands themselves, because a given command can be 730 * free the commands themselves, because a given command can be
729 * attached to several different transformations. 731 * attached to several different transformations.
730 */ 732 */
731 gn = Lst_Datum(ln); 733 gn = Lst_Datum(ln);
732 Lst_Free(gn->commands); 734 Lst_Free(gn->commands);
733 Lst_Free(gn->children); 735 Lst_Free(gn->children);
734 gn->commands = Lst_Init(); 736 gn->commands = Lst_Init();
735 gn->children = Lst_Init(); 737 gn->children = Lst_Init();
736 } 738 }
737 739
738 gn->type = OP_TRANSFORM; 740 gn->type = OP_TRANSFORM;
739 741
740 (void)SuffParseTransform(line, &s, &t); 742 (void)SuffParseTransform(line, &s, &t);
741 743
742 /* 744 /*
743 * link the two together in the proper relationship and order 745 * link the two together in the proper relationship and order
744 */ 746 */
745 if (DEBUG(SUFF)) { 747 if (DEBUG(SUFF)) {
746 fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 748 fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
747 s->name, t->name); 749 s->name, t->name);
748 } 750 }
749 SuffInsert(t->children, s); 751 SuffInsert(t->children, s);
750 SuffInsert(s->parents, t); 752 SuffInsert(s->parents, t);
751 753
752 return gn; 754 return gn;
753} 755}
754 756
755/*- 757/*-
756 *----------------------------------------------------------------------- 758 *-----------------------------------------------------------------------
757 * Suff_EndTransform -- 759 * Suff_EndTransform --
758 * Handle the finish of a transformation definition, removing the 760 * Handle the finish of a transformation definition, removing the
759 * transformation from the graph if it has neither commands nor 761 * transformation from the graph if it has neither commands nor
760 * sources. This is a callback procedure for the Parse module via 762 * sources. This is a callback procedure for the Parse module via
761 * Lst_ForEach 763 * Lst_ForEach
762 * 764 *
763 * Input: 765 * Input:
764 * gnp Node for transformation 766 * gnp Node for transformation
765 * dummy Node for transformation 767 * dummy Node for transformation
766 * 768 *
767 * Results: 769 * Results:
768 * === 0 770 * === 0
769 * 771 *
770 * Side Effects: 772 * Side Effects:
771 * If the node has no commands or children, the children and parents 773 * If the node has no commands or children, the children and parents
772 * lists of the affected suffixes are altered. 774 * lists of the affected suffixes are altered.
773 * 775 *
774 *----------------------------------------------------------------------- 776 *-----------------------------------------------------------------------
775 */ 777 */
776int 778int
777Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED) 779Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED)
778{ 780{
779 GNode *gn = (GNode *)gnp; 781 GNode *gn = (GNode *)gnp;
780 782
781 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts)) 783 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(gn->cohorts))
782 gn = Lst_Datum(Lst_Last(gn->cohorts)); 784 gn = Lst_Datum(Lst_Last(gn->cohorts));
783 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) && 785 if ((gn->type & OP_TRANSFORM) && Lst_IsEmpty(gn->commands) &&
784 Lst_IsEmpty(gn->children)) 786 Lst_IsEmpty(gn->children))
785 { 787 {
786 Suff *s, *t; 788 Suff *s, *t;
787 789
788 /* 790 /*
789 * SuffParseTransform() may fail for special rules which are not 791 * SuffParseTransform() may fail for special rules which are not
790 * actual transformation rules. (e.g. .DEFAULT) 792 * actual transformation rules. (e.g. .DEFAULT)
791 */ 793 */
792 if (SuffParseTransform(gn->name, &s, &t)) { 794 if (SuffParseTransform(gn->name, &s, &t)) {
793 Lst p; 795 Lst p;
794 796
795 if (DEBUG(SUFF)) { 797 if (DEBUG(SUFF)) {
796 fprintf(debug_file, "deleting transformation from `%s' to `%s'\n", 798 fprintf(debug_file, "deleting transformation from `%s' to `%s'\n",
797 s->name, t->name); 799 s->name, t->name);
798 } 800 }
799 801
800 /* 802 /*
801 * Store s->parents because s could be deleted in SuffRemove 803 * Store s->parents because s could be deleted in SuffRemove
802 */ 804 */
803 p = s->parents; 805 p = s->parents;
804 806
805 /* 807 /*
806 * Remove the source from the target's children list. We check for a 808 * Remove the source from the target's children list. We check for a
807 * nil return to handle a beanhead saying something like 809 * nil return to handle a beanhead saying something like
808 * .c.o .c.o: 810 * .c.o .c.o:
809 * 811 *
810 * We'll be called twice when the next target is seen, but .c and .o 812 * We'll be called twice when the next target is seen, but .c and .o
811 * are only linked once... 813 * are only linked once...
812 */ 814 */
813 SuffRemove(t->children, s); 815 SuffRemove(t->children, s);
814 816
815 /* 817 /*
816 * Remove the target from the source's parents list 818 * Remove the target from the source's parents list
817 */ 819 */
818 SuffRemove(p, t); 820 SuffRemove(p, t);
819 } 821 }
820 } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) { 822 } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
821 fprintf(debug_file, "transformation %s complete\n", gn->name); 823 fprintf(debug_file, "transformation %s complete\n", gn->name);
822 } 824 }
823 825
824 return 0; 826 return 0;
825} 827}
826 828
827/*- 829/*-
828 *----------------------------------------------------------------------- 830 *-----------------------------------------------------------------------
829 * SuffRebuildGraph -- 831 * SuffRebuildGraph --
830 * Called from Suff_AddSuffix via Lst_ForEach to search through the 832 * Called from Suff_AddSuffix via Lst_ForEach to search through the
831 * list of existing transformation rules and rebuild the transformation 833 * list of existing transformation rules and rebuild the transformation
832 * graph when it has been destroyed by Suff_ClearSuffixes. If the 834 * graph when it has been destroyed by Suff_ClearSuffixes. If the
833 * given rule is a transformation involving this suffix and another, 835 * given rule is a transformation involving this suffix and another,
834 * existing suffix, the proper relationship is established between 836 * existing suffix, the proper relationship is established between
835 * the two. 837 * the two.
836 * 838 *
837 * Input: 839 * Input:
838 * transformp Transformation to test 840 * transformp Transformation to test
839 * sp Suffix to rebuild 841 * sp Suffix to rebuild
840 * 842 *
841 * Results: 843 * Results:
842 * Always 0. 844 * Always 0.
843 * 845 *
844 * Side Effects: 846 * Side Effects:
845 * The appropriate links will be made between this suffix and 847 * The appropriate links will be made between this suffix and
846 * others if transformation rules exist for it. 848 * others if transformation rules exist for it.
847 * 849 *
848 *----------------------------------------------------------------------- 850 *-----------------------------------------------------------------------
849 */ 851 */
850static int 852static int
851SuffRebuildGraph(void *transformp, void *sp) 853SuffRebuildGraph(void *transformp, void *sp)
852{ 854{
853 GNode *transform = (GNode *)transformp; 855 GNode *transform = (GNode *)transformp;
854 Suff *s = (Suff *)sp; 856 Suff *s = (Suff *)sp;
855 char *cp; 857 char *cp;
856 LstNode ln; 858 LstNode ln;
857 Suff *s2; 859 Suff *s2;
858 SuffixCmpData sd; 860 SuffixCmpData sd;
859 861
860 /* 862 /*
861 * First see if it is a transformation from this suffix. 863 * First see if it is a transformation from this suffix.
862 */ 864 */
863 cp = UNCONST(SuffStrIsPrefix(s->name, transform->name)); 865 cp = UNCONST(SuffStrIsPrefix(s->name, transform->name));
864 if (cp != NULL) { 866 if (cp != NULL) {
865 ln = Lst_Find(sufflist, SuffSuffHasNameP, cp); 867 ln = Lst_Find(sufflist, SuffSuffHasNameP, cp);
866 if (ln != NULL) { 868 if (ln != NULL) {
867 /* 869 /*
868 * Found target. Link in and return, since it can't be anything 870 * Found target. Link in and return, since it can't be anything
869 * else. 871 * else.
870 */ 872 */
871 s2 = Lst_Datum(ln); 873 s2 = Lst_Datum(ln);
872 SuffInsert(s2->children, s); 874 SuffInsert(s2->children, s);
873 SuffInsert(s->parents, s2); 875 SuffInsert(s->parents, s2);
874 return 0; 876 return 0;
875 } 877 }
876 } 878 }
877 879
878 /* 880 /*
879 * Not from, maybe to? 881 * Not from, maybe to?
880 */ 882 */
881 sd.len = strlen(transform->name); 883 sd.len = strlen(transform->name);
882 sd.ename = transform->name + sd.len; 884 sd.ename = transform->name + sd.len;
883 cp = SuffSuffIsSuffix(s, &sd); 885 cp = SuffSuffIsSuffix(s, &sd);
884 if (cp != NULL) { 886 if (cp != NULL) {
885 /* 887 /*
886 * Null-terminate the source suffix in order to find it. 888 * Null-terminate the source suffix in order to find it.
887 */ 889 */
888 cp[1] = '\0'; 890 cp[1] = '\0';
889 ln = Lst_Find(sufflist, SuffSuffHasNameP, transform->name); 891 ln = Lst_Find(sufflist, SuffSuffHasNameP, transform->name);
890 /* 892 /*
891 * Replace the start of the target suffix 893 * Replace the start of the target suffix
892 */ 894 */
893 cp[1] = s->name[0]; 895 cp[1] = s->name[0];
894 if (ln != NULL) { 896 if (ln != NULL) {
895 /* 897 /*
896 * Found it -- establish the proper relationship 898 * Found it -- establish the proper relationship
897 */ 899 */
898 s2 = Lst_Datum(ln); 900 s2 = Lst_Datum(ln);
899 SuffInsert(s->children, s2); 901 SuffInsert(s->children, s2);
900 SuffInsert(s2->parents, s); 902 SuffInsert(s2->parents, s);
901 } 903 }
902 } 904 }
903 return 0; 905 return 0;
904} 906}
905 907
906/*- 908/*-
907 *----------------------------------------------------------------------- 909 *-----------------------------------------------------------------------
908 * SuffScanTargets -- 910 * SuffScanTargets --
909 * Called from Suff_AddSuffix via Lst_ForEach to search through the 911 * Called from Suff_AddSuffix via Lst_ForEach to search through the
910 * list of existing targets and find if any of the existing targets 912 * list of existing targets and find if any of the existing targets
911 * can be turned into a transformation rule. 913 * can be turned into a transformation rule.
912 * 914 *
913 * Results: 915 * Results:
914 * 1 if a new main target has been selected, 0 otherwise. 916 * 1 if a new main target has been selected, 0 otherwise.
915 * 917 *
916 * Side Effects: 918 * Side Effects:
917 * If such a target is found and the target is the current main 919 * If such a target is found and the target is the current main
918 * target, the main target is set to NULL and the next target 920 * target, the main target is set to NULL and the next target
919 * examined (if that exists) becomes the main target. 921 * examined (if that exists) becomes the main target.
920 * 922 *
921 *----------------------------------------------------------------------- 923 *-----------------------------------------------------------------------
922 */ 924 */
923static int 925static int
924SuffScanTargets(void *targetp, void *gsp) 926SuffScanTargets(void *targetp, void *gsp)
925{ 927{
926 GNode *target = (GNode *)targetp; 928 GNode *target = (GNode *)targetp;
927 GNodeSuff *gs = (GNodeSuff *)gsp; 929 GNodeSuff *gs = (GNodeSuff *)gsp;
928 Suff *s, *t; 930 Suff *s, *t;
929 char *ptr; 931 char *ptr;
930 932
931 if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) { 933 if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) {
932 *gs->gn = target; 934 *gs->gn = target;
933 Targ_SetMain(target); 935 Targ_SetMain(target);
934 return 1; 936 return 1;
935 } 937 }
936 938
937 if (target->type == OP_TRANSFORM) 939 if (target->type == OP_TRANSFORM)
938 return 0; 940 return 0;
939 941
940 if ((ptr = strstr(target->name, gs->s->name)) == NULL || 942 if ((ptr = strstr(target->name, gs->s->name)) == NULL ||
941 ptr == target->name) 943 ptr == target->name)
942 return 0; 944 return 0;
943 945
944 if (SuffParseTransform(target->name, &s, &t)) { 946 if (SuffParseTransform(target->name, &s, &t)) {
945 if (*gs->gn == target) { 947 if (*gs->gn == target) {
946 gs->r = TRUE; 948 gs->r = TRUE;
947 *gs->gn = NULL; 949 *gs->gn = NULL;
948 Targ_SetMain(NULL); 950 Targ_SetMain(NULL);
949 } 951 }
950 Lst_Free(target->children); 952 Lst_Free(target->children);
951 target->children = Lst_Init(); 953 target->children = Lst_Init();
952 target->type = OP_TRANSFORM; 954 target->type = OP_TRANSFORM;
953 /* 955 /*
954 * link the two together in the proper relationship and order 956 * link the two together in the proper relationship and order
955 */ 957 */
956 if (DEBUG(SUFF)) { 958 if (DEBUG(SUFF)) {
957 fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 959 fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
958 s->name, t->name); 960 s->name, t->name);
959 } 961 }
960 SuffInsert(t->children, s); 962 SuffInsert(t->children, s);
961 SuffInsert(s->parents, t); 963 SuffInsert(s->parents, t);
962 } 964 }
963 return 0; 965 return 0;
964} 966}
965 967
966/*- 968/*-
967 *----------------------------------------------------------------------- 969 *-----------------------------------------------------------------------
968 * Suff_AddSuffix -- 970 * Suff_AddSuffix --
969 * Add the suffix in string to the end of the list of known suffixes. 971 * Add the suffix in string to the end of the list of known suffixes.
970 * Should we restructure the suffix graph? Make doesn't... 972 * Should we restructure the suffix graph? Make doesn't...
971 * 973 *
972 * Input: 974 * Input:
973 * str the name of the suffix to add 975 * str the name of the suffix to add
974 * 976 *
975 * Results: 977 * Results:
976 * None 978 * None
977 * 979 *
978 * Side Effects: 980 * Side Effects:
979 * A GNode is created for the suffix and a Suff structure is created and 981 * A GNode is created for the suffix and a Suff structure is created and
980 * added to the suffixes list unless the suffix was already known. 982 * added to the suffixes list unless the suffix was already known.
981 * The mainNode passed can be modified if a target mutated into a 983 * The mainNode passed can be modified if a target mutated into a
982 * transform and that target happened to be the main target. 984 * transform and that target happened to be the main target.
983 *----------------------------------------------------------------------- 985 *-----------------------------------------------------------------------
984 */ 986 */
985void 987void
986Suff_AddSuffix(char *str, GNode **gn) 988Suff_AddSuffix(char *str, GNode **gn)
987{ 989{
988 Suff *s; /* new suffix descriptor */ 990 Suff *s; /* new suffix descriptor */
989 LstNode ln; 991 LstNode ln;
990 GNodeSuff gs; 992 GNodeSuff gs;
991 993
992 ln = Lst_Find(sufflist, SuffSuffHasNameP, str); 994 ln = Lst_Find(sufflist, SuffSuffHasNameP, str);
993 if (ln == NULL) { 995 if (ln == NULL) {
994 s = SuffNew(str); 996 s = SuffNew(str);
995 997
996 Lst_Append(sufflist, s); 998 Lst_Append(sufflist, s);
997 /* 999 /*
998 * We also look at our existing targets list to see if adding 1000 * We also look at our existing targets list to see if adding
999 * this suffix will make one of our current targets mutate into 1001 * this suffix will make one of our current targets mutate into
1000 * a suffix rule. This is ugly, but other makes treat all targets 1002 * a suffix rule. This is ugly, but other makes treat all targets
1001 * that start with a . as suffix rules. 1003 * that start with a . as suffix rules.
1002 */ 1004 */
1003 gs.gn = gn; 1005 gs.gn = gn;
1004 gs.s = s; 1006 gs.s = s;
1005 gs.r = FALSE; 1007 gs.r = FALSE;
1006 Lst_ForEach(Targ_List(), SuffScanTargets, &gs); 1008 Lst_ForEach(Targ_List(), SuffScanTargets, &gs);
1007 /* 1009 /*
1008 * Look for any existing transformations from or to this suffix. 1010 * Look for any existing transformations from or to this suffix.
1009 * XXX: Only do this after a Suff_ClearSuffixes? 1011 * XXX: Only do this after a Suff_ClearSuffixes?
1010 */ 1012 */
1011 Lst_ForEach(transforms, SuffRebuildGraph, s); 1013 Lst_ForEach(transforms, SuffRebuildGraph, s);
1012 } 1014 }
1013} 1015}
1014 1016
1015/*- 1017/*-
1016 *----------------------------------------------------------------------- 1018 *-----------------------------------------------------------------------
1017 * Suff_GetPath -- 1019 * Suff_GetPath --
1018 * Return the search path for the given suffix, if it's defined. 1020 * Return the search path for the given suffix, if it's defined.
1019 * 1021 *
1020 * Results: 1022 * Results:
1021 * The searchPath for the desired suffix or NULL if the suffix isn't 1023 * The searchPath for the desired suffix or NULL if the suffix isn't
1022 * defined. 1024 * defined.
1023 * 1025 *
1024 * Side Effects: 1026 * Side Effects:
1025 * None 1027 * None
1026 *----------------------------------------------------------------------- 1028 *-----------------------------------------------------------------------
1027 */ 1029 */
1028Lst 1030Lst
1029Suff_GetPath(char *sname) 1031Suff_GetPath(char *sname)
1030{ 1032{
1031 LstNode ln; 1033 LstNode ln;
1032 Suff *s; 1034 Suff *s;
1033 1035
1034 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname); 1036 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname);
1035 if (ln == NULL) { 1037 if (ln == NULL) {
1036 return NULL; 1038 return NULL;
1037 } else { 1039 } else {
1038 s = Lst_Datum(ln); 1040 s = Lst_Datum(ln);
1039 return s->searchPath; 1041 return s->searchPath;
1040 } 1042 }
1041} 1043}
1042 1044
1043/*- 1045/*-
1044 *----------------------------------------------------------------------- 1046 *-----------------------------------------------------------------------
1045 * Suff_DoPaths -- 1047 * Suff_DoPaths --
1046 * Extend the search paths for all suffixes to include the default 1048 * Extend the search paths for all suffixes to include the default
1047 * search path. 1049 * search path.
1048 * 1050 *
1049 * Results: 1051 * Results:
1050 * None. 1052 * None.
1051 * 1053 *
1052 * Side Effects: 1054 * Side Effects:
1053 * The searchPath field of all the suffixes is extended by the 1055 * The searchPath field of all the suffixes is extended by the
1054 * directories in dirSearchPath. If paths were specified for the 1056 * directories in dirSearchPath. If paths were specified for the
1055 * ".h" suffix, the directories are stuffed into a global variable 1057 * ".h" suffix, the directories are stuffed into a global variable
1056 * called ".INCLUDES" with each directory preceded by a -I. The same 1058 * called ".INCLUDES" with each directory preceded by a -I. The same
1057 * is done for the ".a" suffix, except the variable is called 1059 * is done for the ".a" suffix, except the variable is called
1058 * ".LIBS" and the flag is -L. 1060 * ".LIBS" and the flag is -L.
1059 *----------------------------------------------------------------------- 1061 *-----------------------------------------------------------------------
1060 */ 1062 */
1061void 1063void
1062Suff_DoPaths(void) 1064Suff_DoPaths(void)
1063{ 1065{
1064 Suff *s; 1066 Suff *s;
1065 LstNode ln; 1067 LstNode ln;
1066 char *ptr; 1068 char *ptr;
1067 Lst inIncludes; /* Cumulative .INCLUDES path */ 1069 Lst inIncludes; /* Cumulative .INCLUDES path */
1068 Lst inLibs; /* Cumulative .LIBS path */ 1070 Lst inLibs; /* Cumulative .LIBS path */
1069 1071
1070 1072
1071 inIncludes = Lst_Init(); 1073 inIncludes = Lst_Init();
1072 inLibs = Lst_Init(); 1074 inLibs = Lst_Init();
1073 1075
1074 Lst_Open(sufflist); 1076 Lst_Open(sufflist);
1075 while ((ln = Lst_Next(sufflist)) != NULL) { 1077 while ((ln = Lst_Next(sufflist)) != NULL) {
1076 s = Lst_Datum(ln); 1078 s = Lst_Datum(ln);
1077 if (!Lst_IsEmpty(s->searchPath)) { 1079 if (!Lst_IsEmpty(s->searchPath)) {
1078#ifdef INCLUDES 1080#ifdef INCLUDES
1079 if (s->flags & SUFF_INCLUDE) { 1081 if (s->flags & SUFF_INCLUDE) {
1080 Dir_Concat(inIncludes, s->searchPath); 1082 Dir_Concat(inIncludes, s->searchPath);
1081 } 1083 }
1082#endif /* INCLUDES */ 1084#endif /* INCLUDES */
1083#ifdef LIBRARIES 1085#ifdef LIBRARIES
1084 if (s->flags & SUFF_LIBRARY) { 1086 if (s->flags & SUFF_LIBRARY) {
1085 Dir_Concat(inLibs, s->searchPath); 1087 Dir_Concat(inLibs, s->searchPath);
1086 } 1088 }
1087#endif /* LIBRARIES */ 1089#endif /* LIBRARIES */
1088 Dir_Concat(s->searchPath, dirSearchPath); 1090 Dir_Concat(s->searchPath, dirSearchPath);
1089 } else { 1091 } else {
1090 Lst_Destroy(s->searchPath, Dir_Destroy); 1092 Lst_Destroy(s->searchPath, Dir_Destroy);
1091 s->searchPath = Lst_Copy(dirSearchPath, Dir_CopyDir); 1093 s->searchPath = Lst_Copy(dirSearchPath, Dir_CopyDir);
1092 } 1094 }
1093 } 1095 }
1094 Lst_Close(sufflist); 1096 Lst_Close(sufflist);
1095 1097
1096 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL); 1098 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);
1097 free(ptr); 1099 free(ptr);
1098 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL); 1100 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
1099 free(ptr); 1101 free(ptr);
1100 1102
1101 Lst_Destroy(inIncludes, Dir_Destroy); 1103 Lst_Destroy(inIncludes, Dir_Destroy);
1102 Lst_Destroy(inLibs, Dir_Destroy); 1104 Lst_Destroy(inLibs, Dir_Destroy);
1103} 1105}
1104 1106
1105/*- 1107/*-
1106 *----------------------------------------------------------------------- 1108 *-----------------------------------------------------------------------
1107 * Suff_AddInclude -- 1109 * Suff_AddInclude --
1108 * Add the given suffix as a type of file which gets included. 1110 * Add the given suffix as a type of file which gets included.
1109 * Called from the parse module when a .INCLUDES line is parsed. 1111 * Called from the parse module when a .INCLUDES line is parsed.
1110 * The suffix must have already been defined. 1112 * The suffix must have already been defined.
1111 * 1113 *
1112 * Input: 1114 * Input:
1113 * sname Name of the suffix to mark 1115 * sname Name of the suffix to mark
1114 * 1116 *
1115 * Results: 1117 * Results:
1116 * None. 1118 * None.
1117 * 1119 *
1118 * Side Effects: 1120 * Side Effects:
1119 * The SUFF_INCLUDE bit is set in the suffix's flags field 1121 * The SUFF_INCLUDE bit is set in the suffix's flags field
1120 * 1122 *
1121 *----------------------------------------------------------------------- 1123 *-----------------------------------------------------------------------
1122 */ 1124 */
1123void 1125void
1124Suff_AddInclude(char *sname) 1126Suff_AddInclude(char *sname)
1125{ 1127{
1126 LstNode ln; 1128 LstNode ln;
1127 Suff *s; 1129 Suff *s;
1128 1130
1129 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname); 1131 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname);
1130 if (ln != NULL) { 1132 if (ln != NULL) {
1131 s = Lst_Datum(ln); 1133 s = Lst_Datum(ln);
1132 s->flags |= SUFF_INCLUDE; 1134 s->flags |= SUFF_INCLUDE;
1133 } 1135 }
1134} 1136}
1135 1137
1136/*- 1138/*-
1137 *----------------------------------------------------------------------- 1139 *-----------------------------------------------------------------------
1138 * Suff_AddLib -- 1140 * Suff_AddLib --
1139 * Add the given suffix as a type of file which is a library. 1141 * Add the given suffix as a type of file which is a library.
1140 * Called from the parse module when parsing a .LIBS line. The 1142 * Called from the parse module when parsing a .LIBS line. The
1141 * suffix must have been defined via .SUFFIXES before this is 1143 * suffix must have been defined via .SUFFIXES before this is
1142 * called. 1144 * called.
1143 * 1145 *
1144 * Input: 1146 * Input:
1145 * sname Name of the suffix to mark 1147 * sname Name of the suffix to mark
1146 * 1148 *
1147 * Results: 1149 * Results:
1148 * None. 1150 * None.
1149 * 1151 *
1150 * Side Effects: 1152 * Side Effects:
1151 * The SUFF_LIBRARY bit is set in the suffix's flags field 1153 * The SUFF_LIBRARY bit is set in the suffix's flags field
1152 * 1154 *
1153 *----------------------------------------------------------------------- 1155 *-----------------------------------------------------------------------
1154 */ 1156 */
1155void 1157void
1156Suff_AddLib(char *sname) 1158Suff_AddLib(char *sname)
1157{ 1159{
1158 LstNode ln; 1160 LstNode ln;
1159 Suff *s; 1161 Suff *s;
1160 1162
1161 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname); 1163 ln = Lst_Find(sufflist, SuffSuffHasNameP, sname);
1162 if (ln != NULL) { 1164 if (ln != NULL) {
1163 s = Lst_Datum(ln); 1165 s = Lst_Datum(ln);
1164 s->flags |= SUFF_LIBRARY; 1166 s->flags |= SUFF_LIBRARY;
1165 } 1167 }
1166} 1168}
1167 1169
1168 /********** Implicit Source Search Functions *********/ 1170 /********** Implicit Source Search Functions *********/
1169 1171
1170/*- 1172/*-
1171 *----------------------------------------------------------------------- 1173 *-----------------------------------------------------------------------
1172 * SuffAddSrc -- 1174 * SuffAddSrc --
1173 * Add a suffix as a Src structure to the given list with its parent 1175 * Add a suffix as a Src structure to the given list with its parent
1174 * being the given Src structure. If the suffix is the null suffix, 1176 * being the given Src structure. If the suffix is the null suffix,
1175 * the prefix is used unaltered as the file name in the Src structure. 1177 * the prefix is used unaltered as the file name in the Src structure.
1176 * 1178 *
1177 * Input: 1179 * Input:
1178 * sp suffix for which to create a Src structure 1180 * sp suffix for which to create a Src structure
1179 * lsp list and parent for the new Src 1181 * lsp list and parent for the new Src
1180 * 1182 *
1181 * Results: 1183 * Results:
1182 * always returns 0 1184 * always returns 0
1183 * 1185 *
1184 * Side Effects: 1186 * Side Effects:
1185 * A Src structure is created and tacked onto the end of the list 1187 * A Src structure is created and tacked onto the end of the list
1186 *----------------------------------------------------------------------- 1188 *-----------------------------------------------------------------------
1187 */ 1189 */
1188static int 1190static int
1189SuffAddSrc(void *sp, void *lsp) 1191SuffAddSrc(void *sp, void *lsp)
1190{ 1192{
1191 Suff *s = (Suff *)sp; 1193 Suff *s = (Suff *)sp;
1192 LstSrc *ls = (LstSrc *)lsp; 1194 LstSrc *ls = (LstSrc *)lsp;
1193 Src *s2; /* new Src structure */ 1195 Src *s2; /* new Src structure */
1194 Src *targ; /* Target structure */ 1196 Src *targ; /* Target structure */
1195 1197
1196 targ = ls->s; 1198 targ = ls->s;
1197 1199
1198 if ((s->flags & SUFF_NULL) && (*s->name != '\0')) { 1200 if ((s->flags & SUFF_NULL) && (*s->name != '\0')) {
1199 /* 1201 /*
1200 * If the suffix has been marked as the NULL suffix, also create a Src 1202 * If the suffix has been marked as the NULL suffix, also create a Src
1201 * structure for a file with no suffix attached. Two birds, and all 1203 * structure for a file with no suffix attached. Two birds, and all
1202 * that... 1204 * that...
1203 */ 1205 */
1204 s2 = bmake_malloc(sizeof(Src)); 1206 s2 = bmake_malloc(sizeof(Src));
1205 s2->file = bmake_strdup(targ->pref); 1207 s2->file = bmake_strdup(targ->pref);
1206 s2->pref = targ->pref; 1208 s2->pref = targ->pref;
1207 s2->parent = targ; 1209 s2->parent = targ;
1208 s2->node = NULL; 1210 s2->node = NULL;
1209 s2->suff = s; 1211 s2->suff = s;
1210 s->refCount++; 1212 s->refCount++;
1211 s2->children = 0; 1213 s2->children = 0;
1212 targ->children += 1; 1214 targ->children += 1;
1213 Lst_Append(ls->l, s2); 1215 Lst_Append(ls->l, s2);
1214#ifdef DEBUG_SRC 1216#ifdef DEBUG_SRC
1215 s2->cp = Lst_Init(); 1217 s2->cp = Lst_Init();
1216 Lst_Append(targ->cp, s2); 1218 Lst_Append(targ->cp, s2);
1217 fprintf(debug_file, "1 add %p %p to %p:", targ, s2, ls->l); 1219 fprintf(debug_file, "1 add %p %p to %p:", targ, s2, ls->l);
1218 Lst_ForEach(ls->l, PrintAddr, NULL); 1220 Lst_ForEach(ls->l, PrintAddr, NULL);
1219 fprintf(debug_file, "\n"); 1221 fprintf(debug_file, "\n");
1220#endif 1222#endif
1221 } 1223 }
1222 s2 = bmake_malloc(sizeof(Src)); 1224 s2 = bmake_malloc(sizeof(Src));
1223 s2->file = str_concat2(targ->pref, s->name); 1225 s2->file = str_concat2(targ->pref, s->name);
1224 s2->pref = targ->pref; 1226 s2->pref = targ->pref;
1225 s2->parent = targ; 1227 s2->parent = targ;
1226 s2->node = NULL; 1228 s2->node = NULL;
1227 s2->suff = s; 1229 s2->suff = s;
1228 s->refCount++; 1230 s->refCount++;
1229 s2->children = 0; 1231 s2->children = 0;
1230 targ->children += 1; 1232 targ->children += 1;
1231 Lst_Append(ls->l, s2); 1233 Lst_Append(ls->l, s2);
1232#ifdef DEBUG_SRC 1234#ifdef DEBUG_SRC
1233 s2->cp = Lst_Init(); 1235 s2->cp = Lst_Init();
1234 Lst_Append(targ->cp, s2); 1236 Lst_Append(targ->cp, s2);
1235 fprintf(debug_file, "2 add %p %p to %p:", targ, s2, ls->l); 1237 fprintf(debug_file, "2 add %p %p to %p:", targ, s2, ls->l);
1236 Lst_ForEach(ls->l, PrintAddr, NULL); 1238 Lst_ForEach(ls->l, PrintAddr, NULL);
1237 fprintf(debug_file, "\n"); 1239 fprintf(debug_file, "\n");
1238#endif 1240#endif
1239 1241
1240 return 0; 1242 return 0;
1241} 1243}
1242 1244
1243/*- 1245/*-
1244 *----------------------------------------------------------------------- 1246 *-----------------------------------------------------------------------
1245 * SuffAddLevel -- 1247 * SuffAddLevel --
1246 * Add all the children of targ as Src structures to the given list 1248 * Add all the children of targ as Src structures to the given list
1247 * 1249 *
1248 * Input: 1250 * Input:
1249 * l list to which to add the new level 1251 * l list to which to add the new level
1250 * targ Src structure to use as the parent 1252 * targ Src structure to use as the parent
1251 * 1253 *
1252 * Results: 1254 * Results:
1253 * None 1255 * None
1254 * 1256 *
1255 * Side Effects: 1257 * Side Effects:
1256 * Lots of structures are created and added to the list 1258 * Lots of structures are created and added to the list
1257 *----------------------------------------------------------------------- 1259 *-----------------------------------------------------------------------
1258 */ 1260 */
1259static void 1261static void
1260SuffAddLevel(Lst l, Src *targ) 1262SuffAddLevel(Lst l, Src *targ)
1261{ 1263{
1262 LstSrc ls; 1264 LstSrc ls;
1263 1265
1264 ls.s = targ; 1266 ls.s = targ;
1265 ls.l = l; 1267 ls.l = l;
1266 1268
1267 Lst_ForEach(targ->suff->children, SuffAddSrc, &ls); 1269 Lst_ForEach(targ->suff->children, SuffAddSrc, &ls);
1268} 1270}
1269 1271
1270/*- 1272/*-
1271 *---------------------------------------------------------------------- 1273 *----------------------------------------------------------------------
1272 * SuffRemoveSrc -- 1274 * SuffRemoveSrc --
1273 * Free all src structures in list that don't have a reference count 1275 * Free all src structures in list that don't have a reference count
1274 * 1276 *
1275 * Results: 1277 * Results:
1276 * Ture if an src was removed 1278 * Ture if an src was removed
1277 * 1279 *
1278 * Side Effects: 1280 * Side Effects:
1279 * The memory is free'd. 1281 * The memory is free'd.
1280 *---------------------------------------------------------------------- 1282 *----------------------------------------------------------------------
1281 */ 1283 */
1282static int 1284static int
1283SuffRemoveSrc(Lst l) 1285SuffRemoveSrc(Lst l)
1284{ 1286{
1285 LstNode ln; 1287 LstNode ln;
1286 Src *s; 1288 Src *s;
1287 int t = 0; 1289 int t = 0;
1288 1290
1289 Lst_Open(l); 1291 Lst_Open(l);
1290 1292
1291#ifdef DEBUG_SRC 1293#ifdef DEBUG_SRC
1292 fprintf(debug_file, "cleaning %lx: ", (unsigned long) l); 1294 fprintf(debug_file, "cleaning %lx: ", (unsigned long) l);
1293 Lst_ForEach(l, PrintAddr, NULL); 1295 Lst_ForEach(l, PrintAddr, NULL);
1294 fprintf(debug_file, "\n"); 1296 fprintf(debug_file, "\n");
1295#endif 1297#endif
1296 1298
1297 1299
1298 while ((ln = Lst_Next(l)) != NULL) { 1300 while ((ln = Lst_Next(l)) != NULL) {
1299 s = Lst_Datum(ln); 1301 s = Lst_Datum(ln);
1300 if (s->children == 0) { 1302 if (s->children == 0) {
1301 free(s->file); 1303 free(s->file);
1302 if (!s->parent) 1304 if (!s->parent)
1303 free(s->pref); 1305 free(s->pref);
1304 else { 1306 else {
1305#ifdef DEBUG_SRC 1307#ifdef DEBUG_SRC
1306 LstNode ln2 = Lst_Member(s->parent->cp, s); 1308 LstNode ln2 = Lst_Member(s->parent->cp, s);
1307 if (ln2 != NULL) 1309 if (ln2 != NULL)
1308 Lst_Remove(s->parent->cp, ln2); 1310 Lst_Remove(s->parent->cp, ln2);
1309#endif 1311#endif
1310 --s->parent->children; 1312 --s->parent->children;
1311 } 1313 }
1312#ifdef DEBUG_SRC 1314#ifdef DEBUG_SRC
1313 fprintf(debug_file, "free: [l=%p] p=%p %d\n", l, s, s->children); 1315 fprintf(debug_file, "free: [l=%p] p=%p %d\n", l, s, s->children);
1314 Lst_Free(s->cp); 1316 Lst_Free(s->cp);
1315#endif 1317#endif
1316 Lst_Remove(l, ln); 1318 Lst_Remove(l, ln);
1317 free(s); 1319 free(s);
1318 t |= 1; 1320 t |= 1;
1319 Lst_Close(l); 1321 Lst_Close(l);
1320 return TRUE; 1322 return TRUE;
1321 } 1323 }
1322#ifdef DEBUG_SRC 1324#ifdef DEBUG_SRC
1323 else { 1325 else {
1324 fprintf(debug_file, "keep: [l=%p] p=%p %d: ", l, s, s->children); 1326 fprintf(debug_file, "keep: [l=%p] p=%p %d: ", l, s, s->children);
1325 Lst_ForEach(s->cp, PrintAddr, NULL); 1327 Lst_ForEach(s->cp, PrintAddr, NULL);
1326 fprintf(debug_file, "\n"); 1328 fprintf(debug_file, "\n");
1327 } 1329 }
1328#endif 1330#endif
1329 } 1331 }
1330 1332
1331 Lst_Close(l); 1333 Lst_Close(l);
1332 1334
1333 return t; 1335 return t;
1334} 1336}
1335 1337
1336/*- 1338/*-
1337 *----------------------------------------------------------------------- 1339 *-----------------------------------------------------------------------
1338 * SuffFindThem -- 1340 * SuffFindThem --
1339 * Find the first existing file/target in the list srcs 1341 * Find the first existing file/target in the list srcs
1340 * 1342 *
1341 * Input: 1343 * Input:
1342 * srcs list of Src structures to search through 1344 * srcs list of Src structures to search through
1343 * 1345 *
1344 * Results: 1346 * Results:
1345 * The lowest structure in the chain of transformations 1347 * The lowest structure in the chain of transformations
1346 * 1348 *
1347 * Side Effects: 1349 * Side Effects:
1348 * None 1350 * None
1349 *----------------------------------------------------------------------- 1351 *-----------------------------------------------------------------------
1350 */ 1352 */
1351static Src * 1353static Src *
1352SuffFindThem(Lst srcs, Lst slst) 1354SuffFindThem(Lst srcs, Lst slst)
1353{ 1355{
1354 Src *s; /* current Src */ 1356 Src *s; /* current Src */
1355 Src *rs; /* returned Src */ 1357 Src *rs; /* returned Src */
1356 char *ptr; 1358 char *ptr;
1357 1359
1358 rs = NULL; 1360 rs = NULL;
1359 1361
1360 while (!Lst_IsEmpty(srcs)) { 1362 while (!Lst_IsEmpty(srcs)) {
1361 s = Lst_Dequeue(srcs); 1363 s = Lst_Dequeue(srcs);
1362 1364
1363 if (DEBUG(SUFF)) { 1365 if (DEBUG(SUFF)) {
1364 fprintf(debug_file, "\ttrying %s...", s->file); 1366 fprintf(debug_file, "\ttrying %s...", s->file);
1365 } 1367 }
1366 1368
1367 /* 1369 /*
1368 * A file is considered to exist if either a node exists in the 1370 * A file is considered to exist if either a node exists in the
1369 * graph for it or the file actually exists. 1371 * graph for it or the file actually exists.
1370 */ 1372 */
1371 if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) { 1373 if (Targ_FindNode(s->file, TARG_NOCREATE) != NULL) {
1372#ifdef DEBUG_SRC 1374#ifdef DEBUG_SRC
1373 fprintf(debug_file, "remove %p from %p\n", s, srcs); 1375 fprintf(debug_file, "remove %p from %p\n", s, srcs);
1374#endif 1376#endif
1375 rs = s; 1377 rs = s;
1376 break; 1378 break;
1377 } 1379 }
1378 1380
1379 if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) { 1381 if ((ptr = Dir_FindFile(s->file, s->suff->searchPath)) != NULL) {
1380 rs = s; 1382 rs = s;
1381#ifdef DEBUG_SRC 1383#ifdef DEBUG_SRC
1382 fprintf(debug_file, "remove %p from %p\n", s, srcs); 1384 fprintf(debug_file, "remove %p from %p\n", s, srcs);
1383#endif 1385#endif
1384 free(ptr); 1386 free(ptr);
1385 break; 1387 break;
1386 } 1388 }
1387 1389
1388 if (DEBUG(SUFF)) { 1390 if (DEBUG(SUFF)) {
1389 fprintf(debug_file, "not there\n"); 1391 fprintf(debug_file, "not there\n");
1390 } 1392 }
1391 1393
1392 SuffAddLevel(srcs, s); 1394 SuffAddLevel(srcs, s);
1393 Lst_Append(slst, s); 1395 Lst_Append(slst, s);
1394 } 1396 }
1395 1397
1396 if (DEBUG(SUFF) && rs) { 1398 if (DEBUG(SUFF) && rs) {
1397 fprintf(debug_file, "got it\n"); 1399 fprintf(debug_file, "got it\n");
1398 } 1400 }
1399 return rs; 1401 return rs;
1400} 1402}
1401 1403
1402/*- 1404/*-
1403 *----------------------------------------------------------------------- 1405 *-----------------------------------------------------------------------
1404 * SuffFindCmds -- 1406 * SuffFindCmds --
1405 * See if any of the children of the target in the Src structure is 1407 * See if any of the children of the target in the Src structure is
1406 * one from which the target can be transformed. If there is one, 1408 * one from which the target can be transformed. If there is one,
1407 * a Src structure is put together for it and returned. 1409 * a Src structure is put together for it and returned.
1408 * 1410 *
1409 * Input: 1411 * Input:
1410 * targ Src structure to play with 1412 * targ Src structure to play with
1411 * 1413 *
1412 * Results: 1414 * Results:
1413 * The Src structure of the "winning" child, or NULL if no such beast. 1415 * The Src structure of the "winning" child, or NULL if no such beast.
1414 * 1416 *
1415 * Side Effects: 1417 * Side Effects:
1416 * A Src structure may be allocated. 1418 * A Src structure may be allocated.
1417 * 1419 *
1418 *----------------------------------------------------------------------- 1420 *-----------------------------------------------------------------------
1419 */ 1421 */
1420static Src * 1422static Src *
1421SuffFindCmds(Src *targ, Lst slst) 1423SuffFindCmds(Src *targ, Lst slst)
1422{ 1424{
1423 LstNode ln; /* General-purpose list node */ 1425 LstNode ln; /* General-purpose list node */
1424 GNode *t, /* Target GNode */ 1426 GNode *t, /* Target GNode */
1425 *s; /* Source GNode */ 1427 *s; /* Source GNode */
1426 int prefLen;/* The length of the defined prefix */ 1428 int prefLen;/* The length of the defined prefix */
1427 Suff *suff; /* Suffix on matching beastie */ 1429 Suff *suff; /* Suffix on matching beastie */
1428 Src *ret; /* Return value */ 1430 Src *ret; /* Return value */
1429 char *cp; 1431 char *cp;
1430 1432
1431 t = targ->node; 1433 t = targ->node;
1432 Lst_Open(t->children); 1434 Lst_Open(t->children);
1433 prefLen = strlen(targ->pref); 1435 prefLen = strlen(targ->pref);
1434 1436
1435 for (;;) { 1437 for (;;) {
1436 ln = Lst_Next(t->children); 1438 ln = Lst_Next(t->children);
1437 if (ln == NULL) { 1439 if (ln == NULL) {
1438 Lst_Close(t->children); 1440 Lst_Close(t->children);
1439 return NULL; 1441 return NULL;
1440 } 1442 }
1441 s = Lst_Datum(ln); 1443 s = Lst_Datum(ln);
1442 1444
1443 if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->commands)) { 1445 if (s->type & OP_OPTIONAL && Lst_IsEmpty(t->commands)) {
1444 /* 1446 /*
1445 * We haven't looked to see if .OPTIONAL files exist yet, so 1447 * We haven't looked to see if .OPTIONAL files exist yet, so
1446 * don't use one as the implicit source. 1448 * don't use one as the implicit source.
1447 * This allows us to use .OPTIONAL in .depend files so make won't 1449 * This allows us to use .OPTIONAL in .depend files so make won't
1448 * complain "don't know how to make xxx.h' when a dependent file 1450 * complain "don't know how to make xxx.h' when a dependent file
1449 * has been moved/deleted. 1451 * has been moved/deleted.
1450 */ 1452 */
1451 continue; 1453 continue;
1452 } 1454 }
1453 1455
1454 cp = strrchr(s->name, '/'); 1456 cp = strrchr(s->name, '/');
1455 if (cp == NULL) { 1457 if (cp == NULL) {
1456 cp = s->name; 1458 cp = s->name;
1457 } else { 1459 } else {
1458 cp++; 1460 cp++;
1459 } 1461 }
1460 if (strncmp(cp, targ->pref, prefLen) != 0) 1462 if (strncmp(cp, targ->pref, prefLen) != 0)
1461 continue; 1463 continue;
1462 /* 1464 /*
1463 * The node matches the prefix ok, see if it has a known 1465 * The node matches the prefix ok, see if it has a known
1464 * suffix. 1466 * suffix.
1465 */ 1467 */
1466 ln = Lst_Find(sufflist, SuffSuffHasNameP, &cp[prefLen]); 1468 ln = Lst_Find(sufflist, SuffSuffHasNameP, &cp[prefLen]);
1467 if (ln == NULL) 1469 if (ln == NULL)
1468 continue; 1470 continue;
1469 /* 1471 /*
1470 * It even has a known suffix, see if there's a transformation 1472 * It even has a known suffix, see if there's a transformation
1471 * defined between the node's suffix and the target's suffix. 1473 * defined between the node's suffix and the target's suffix.
1472 * 1474 *
1473 * XXX: Handle multi-stage transformations here, too. 1475 * XXX: Handle multi-stage transformations here, too.
1474 */ 1476 */
1475 suff = Lst_Datum(ln); 1477 suff = Lst_Datum(ln);
1476 1478
1477 /* XXX: Can targ->suff be NULL here? */ 1479 /* XXX: Can targ->suff be NULL here? */
1478 if (targ->suff != NULL && 1480 if (targ->suff != NULL &&
1479 Lst_Member(suff->parents, targ->suff) != NULL) 1481 Lst_Member(suff->parents, targ->suff) != NULL)
1480 break; 1482 break;
1481 } 1483 }
1482 1484
1483 /* 1485 /*
1484 * Hot Damn! Create a new Src structure to describe 1486 * Hot Damn! Create a new Src structure to describe
1485 * this transformation (making sure to duplicate the 1487 * this transformation (making sure to duplicate the
1486 * source node's name so Suff_FindDeps can free it 1488 * source node's name so Suff_FindDeps can free it
1487 * again (ick)), and return the new structure. 1489 * again (ick)), and return the new structure.
1488 */ 1490 */
1489 ret = bmake_malloc(sizeof(Src)); 1491 ret = bmake_malloc(sizeof(Src));
1490 ret->file = bmake_strdup(s->name); 1492 ret->file = bmake_strdup(s->name);
1491 ret->pref = targ->pref; 1493 ret->pref = targ->pref;
1492 ret->suff = suff; 1494 ret->suff = suff;
1493 suff->refCount++; 1495 suff->refCount++;
1494 ret->parent = targ; 1496 ret->parent = targ;
1495 ret->node = s; 1497 ret->node = s;
1496 ret->children = 0; 1498 ret->children = 0;
1497 targ->children += 1; 1499 targ->children += 1;
1498#ifdef DEBUG_SRC 1500#ifdef DEBUG_SRC
1499 ret->cp = Lst_Init(); 1501 ret->cp = Lst_Init();
1500 fprintf(debug_file, "3 add %p %p\n", targ, ret); 1502 fprintf(debug_file, "3 add %p %p\n", targ, ret);
1501 Lst_Append(targ->cp, ret); 1503 Lst_Append(targ->cp, ret);
1502#endif 1504#endif
1503 Lst_Append(slst, ret); 1505 Lst_Append(slst, ret);
1504 if (DEBUG(SUFF)) { 1506 if (DEBUG(SUFF)) {
1505 fprintf(debug_file, "\tusing existing source %s\n", s->name); 1507 fprintf(debug_file, "\tusing existing source %s\n", s->name);
1506 } 1508 }
1507 return ret; 1509 return ret;
1508} 1510}
1509 1511
1510/*- 1512/*-
1511 *----------------------------------------------------------------------- 1513 *-----------------------------------------------------------------------
1512 * SuffExpandChildren -- 1514 * SuffExpandChildren --
1513 * Expand the names of any children of a given node that contain 1515 * Expand the names of any children of a given node that contain
1514 * variable invocations or file wildcards into actual targets. 1516 * variable invocations or file wildcards into actual targets.
1515 * 1517 *
1516 * Input: 1518 * Input:
1517 * cln Child to examine 1519 * cln Child to examine
1518 * pgn Parent node being processed 1520 * pgn Parent node being processed
1519 * 1521 *
1520 * Results: 1522 * Results:
1521 * === 0 (continue) 1523 * === 0 (continue)
1522 * 1524 *
1523 * Side Effects: 1525 * Side Effects:
1524 * The expanded node is removed from the parent's list of children, 1526 * The expanded node is removed from the parent's list of children,
1525 * and the parent's unmade counter is decremented, but other nodes 1527 * and the parent's unmade counter is decremented, but other nodes
1526 * may be added. 1528 * may be added.
1527 * 1529 *
1528 *----------------------------------------------------------------------- 1530 *-----------------------------------------------------------------------
1529 */ 1531 */
1530static void 1532static void
1531SuffExpandChildren(LstNode cln, GNode *pgn) 1533SuffExpandChildren(LstNode cln, GNode *pgn)
1532{ 1534{
1533 GNode *cgn = Lst_Datum(cln); 1535 GNode *cgn = Lst_Datum(cln);
1534 GNode *gn; /* New source 8) */ 1536 GNode *gn; /* New source 8) */
1535 char *cp; /* Expanded value */ 1537 char *cp; /* Expanded value */
1536 1538
1537 if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ)) 1539 if (!Lst_IsEmpty(cgn->order_pred) || !Lst_IsEmpty(cgn->order_succ))
1538 /* It is all too hard to process the result of .ORDER */ 1540 /* It is all too hard to process the result of .ORDER */
1539 return; 1541 return;
1540 1542
1541 if (cgn->type & OP_WAIT) 1543 if (cgn->type & OP_WAIT)
1542 /* Ignore these (& OP_PHONY ?) */ 1544 /* Ignore these (& OP_PHONY ?) */
1543 return; 1545 return;
1544 1546
1545 /* 1547 /*
1546 * First do variable expansion -- this takes precedence over 1548 * First do variable expansion -- this takes precedence over
1547 * wildcard expansion. If the result contains wildcards, they'll be gotten 1549 * wildcard expansion. If the result contains wildcards, they'll be gotten
1548 * to later since the resulting words are tacked on to the end of 1550 * to later since the resulting words are tacked on to the end of
1549 * the children list. 1551 * the children list.
1550 */ 1552 */
1551 if (strchr(cgn->name, '$') == NULL) { 1553 if (strchr(cgn->name, '$') == NULL) {
1552 SuffExpandWildcards(cln, pgn); 1554 SuffExpandWildcards(cln, pgn);
1553 return; 1555 return;
1554 } 1556 }
1555 1557
1556 if (DEBUG(SUFF)) { 1558 if (DEBUG(SUFF)) {
1557 fprintf(debug_file, "Expanding \"%s\"...", cgn->name); 1559 fprintf(debug_file, "Expanding \"%s\"...", cgn->name);
1558 } 1560 }
1559 cp = Var_Subst(cgn->name, pgn, VARE_UNDEFERR|VARE_WANTRES); 1561 cp = Var_Subst(cgn->name, pgn, VARE_UNDEFERR|VARE_WANTRES);
1560 1562
1561 if (cp != NULL) { 1563 if (cp != NULL) {
1562 Lst members = Lst_Init(); 1564 Lst members = Lst_Init();
1563 1565
1564 if (cgn->type & OP_ARCHV) { 1566 if (cgn->type & OP_ARCHV) {
1565 /* 1567 /*
1566 * Node was an archive(member) target, so we want to call 1568 * Node was an archive(member) target, so we want to call
1567 * on the Arch module to find the nodes for us, expanding 1569 * on the Arch module to find the nodes for us, expanding
1568 * variables in the parent's context. 1570 * variables in the parent's context.
1569 */ 1571 */
1570 char *sacrifice = cp; 1572 char *sacrifice = cp;
1571 1573
1572 (void)Arch_ParseArchive(&sacrifice, members, pgn); 1574 (void)Arch_ParseArchive(&sacrifice, members, pgn);
1573 } else { 1575 } else {
1574 /* 1576 /*
1575 * Break the result into a vector of strings whose nodes 1577 * Break the result into a vector of strings whose nodes
1576 * we can find, then add those nodes to the members list. 1578 * we can find, then add those nodes to the members list.
1577 * Unfortunately, we can't use brk_string b/c it 1579 * Unfortunately, we can't use brk_string b/c it
1578 * doesn't understand about variable specifications with 1580 * doesn't understand about variable specifications with
1579 * spaces in them... 1581 * spaces in them...
1580 */ 1582 */
1581 char *start; 1583 char *start;
1582 char *initcp = cp; /* For freeing... */ 1584 char *initcp = cp; /* For freeing... */
1583 1585
1584 for (start = cp; *start == ' ' || *start == '\t'; start++) 1586 for (start = cp; *start == ' ' || *start == '\t'; start++)
1585 continue; 1587 continue;
1586 for (cp = start; *cp != '\0'; cp++) { 1588 for (cp = start; *cp != '\0'; cp++) {
1587 if (*cp == ' ' || *cp == '\t') { 1589 if (*cp == ' ' || *cp == '\t') {
1588 /* 1590 /*
1589 * White-space -- terminate element, find the node, 1591 * White-space -- terminate element, find the node,
1590 * add it, skip any further spaces. 1592 * add it, skip any further spaces.
1591 */ 1593 */
1592 *cp++ = '\0'; 1594 *cp++ = '\0';
1593 gn = Targ_FindNode(start, TARG_CREATE); 1595 gn = Targ_FindNode(start, TARG_CREATE);
1594 Lst_Append(members, gn); 1596 Lst_Append(members, gn);
1595 while (*cp == ' ' || *cp == '\t') { 1597 while (*cp == ' ' || *cp == '\t') {
1596 cp++; 1598 cp++;
1597 } 1599 }
1598 /* 1600 /*
1599 * Adjust cp for increment at start of loop, but 1601 * Adjust cp for increment at start of loop, but
1600 * set start to first non-space. 1602 * set start to first non-space.
1601 */ 1603 */
1602 start = cp--; 1604 start = cp--;
1603 } else if (*cp == '$') { 1605 } else if (*cp == '$') {
1604 /* 1606 /*
1605 * Start of a variable spec -- contact variable module 1607 * Start of a variable spec -- contact variable module
1606 * to find the end so we can skip over it. 1608 * to find the end so we can skip over it.
1607 */ 1609 */
1608 const char *junk; 1610 const char *junk;
1609 int len; 1611 int len;
1610 void *freeIt; 1612 void *freeIt;
1611 1613
1612 junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES, 1614 junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES,
1613 &len, &freeIt); 1615 &len, &freeIt);
1614 if (junk != var_Error) { 1616 if (junk != var_Error) {
1615 cp += len - 1; 1617 cp += len - 1;
1616 } 1618 }
1617 1619
1618 free(freeIt); 1620 free(freeIt);
1619 } else if (*cp == '\\' && cp[1] != '\0') { 1621 } else if (*cp == '\\' && cp[1] != '\0') {
1620 /* 1622 /*
1621 * Escaped something -- skip over it 1623 * Escaped something -- skip over it
1622 */ 1624 */
1623 cp++; 1625 cp++;
1624 } 1626 }
1625 } 1627 }
1626 1628
1627 if (cp != start) { 1629 if (cp != start) {