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