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