Fri Aug 28 03:35:45 2020 UTC ()
make(1): print suffix flags in the standard way

This changes the output (it is now SUFF_NULL instead of just NULL), and
the order of the flags in the output is reversed.


(rillig)
diff -r1.127 -r1.128 src/usr.bin/make/make.h
diff -r1.121 -r1.122 src/usr.bin/make/suff.c

cvs diff -r1.127 -r1.128 src/usr.bin/make/make.h (switch to unified diff)

--- src/usr.bin/make/make.h 2020/08/26 23:00:47 1.127
+++ src/usr.bin/make/make.h 2020/08/28 03:35:45 1.128
@@ -1,581 +1,582 @@ @@ -1,581 +1,582 @@
1/* $NetBSD: make.h,v 1.127 2020/08/26 23:00:47 rillig Exp $ */ 1/* $NetBSD: make.h,v 1.128 2020/08/28 03:35:45 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 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 34 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
35 */ 35 */
36 36
37/* 37/*
38 * Copyright (c) 1989 by Berkeley Softworks 38 * Copyright (c) 1989 by Berkeley Softworks
39 * All rights reserved. 39 * All rights reserved.
40 * 40 *
41 * This code is derived from software contributed to Berkeley by 41 * This code is derived from software contributed to Berkeley by
42 * Adam de Boor. 42 * Adam de Boor.
43 * 43 *
44 * Redistribution and use in source and binary forms, with or without 44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions 45 * modification, are permitted provided that the following conditions
46 * are met: 46 * are met:
47 * 1. Redistributions of source code must retain the above copyright 47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer. 48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright 49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the 50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution. 51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software 52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement: 53 * must display the following acknowledgement:
54 * This product includes software developed by the University of 54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors. 55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors 56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software 57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission. 58 * without specific prior written permission.
59 * 59 *
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE. 70 * SUCH DAMAGE.
71 * 71 *
72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
73 */ 73 */
74 74
75/*- 75/*-
76 * make.h -- 76 * make.h --
77 * The global definitions for pmake 77 * The global definitions for pmake
78 */ 78 */
79 79
80#ifndef MAKE_MAKE_H 80#ifndef MAKE_MAKE_H
81#define MAKE_MAKE_H 81#define MAKE_MAKE_H
82 82
83#include <sys/types.h> 83#include <sys/types.h>
84#include <sys/param.h> 84#include <sys/param.h>
85 85
86#include <assert.h> 86#include <assert.h>
87#include <ctype.h> 87#include <ctype.h>
88#include <fcntl.h> 88#include <fcntl.h>
89#include <stdio.h> 89#include <stdio.h>
90#include <stdlib.h> 90#include <stdlib.h>
91#include <string.h> 91#include <string.h>
92#include <unistd.h> 92#include <unistd.h>
93 93
94#ifdef BSD4_4 94#ifdef BSD4_4
95# include <sys/cdefs.h> 95# include <sys/cdefs.h>
96#endif 96#endif
97 97
98#ifndef FD_CLOEXEC 98#ifndef FD_CLOEXEC
99#define FD_CLOEXEC 1 99#define FD_CLOEXEC 1
100#endif 100#endif
101 101
102#if defined(__GNUC__) 102#if defined(__GNUC__)
103#define MAKE_GNUC_PREREQ(x, y) \ 103#define MAKE_GNUC_PREREQ(x, y) \
104 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ 104 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
105 (__GNUC__ > (x))) 105 (__GNUC__ > (x)))
106#else /* defined(__GNUC__) */ 106#else /* defined(__GNUC__) */
107#define MAKE_GNUC_PREREQ(x, y) 0 107#define MAKE_GNUC_PREREQ(x, y) 0
108#endif /* defined(__GNUC__) */ 108#endif /* defined(__GNUC__) */
109 109
110#if MAKE_GNUC_PREREQ(2, 7) 110#if MAKE_GNUC_PREREQ(2, 7)
111#define MAKE_ATTR_UNUSED __attribute__((__unused__)) 111#define MAKE_ATTR_UNUSED __attribute__((__unused__))
112#else 112#else
113#define MAKE_ATTR_UNUSED /* delete */ 113#define MAKE_ATTR_UNUSED /* delete */
114#endif 114#endif
115 115
116#if MAKE_GNUC_PREREQ(2, 5) 116#if MAKE_GNUC_PREREQ(2, 5)
117#define MAKE_ATTR_DEAD __attribute__((__noreturn__)) 117#define MAKE_ATTR_DEAD __attribute__((__noreturn__))
118#elif defined(__GNUC__) 118#elif defined(__GNUC__)
119#define MAKE_ATTR_DEAD __volatile 119#define MAKE_ATTR_DEAD __volatile
120#else 120#else
121#define MAKE_ATTR_DEAD /* delete */ 121#define MAKE_ATTR_DEAD /* delete */
122#endif 122#endif
123 123
124#if MAKE_GNUC_PREREQ(2, 7) 124#if MAKE_GNUC_PREREQ(2, 7)
125#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \ 125#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \
126 __attribute__((__format__ (__printf__, fmtarg, firstvararg))) 126 __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
127#else 127#else
128#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */ 128#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */
129#endif 129#endif
130 130
131/* 131/*
132 * A boolean type is defined as an integer, not an enum. This allows a 132 * A boolean type is defined as an integer, not an enum. This allows a
133 * boolean argument to be an expression that isn't strictly 0 or 1 valued. 133 * boolean argument to be an expression that isn't strictly 0 or 1 valued.
134 */ 134 */
135 135
136typedef int Boolean; 136typedef int Boolean;
137#ifndef TRUE 137#ifndef TRUE
138#define TRUE 1 138#define TRUE 1
139#endif /* TRUE */ 139#endif /* TRUE */
140#ifndef FALSE 140#ifndef FALSE
141#define FALSE 0 141#define FALSE 0
142#endif /* FALSE */ 142#endif /* FALSE */
143 143
144/* 144/*
145 * Functions that must return a status can return a ReturnStatus to 145 * Functions that must return a status can return a ReturnStatus to
146 * indicate success or type of failure. 146 * indicate success or type of failure.
147 */ 147 */
148 148
149typedef int ReturnStatus; 149typedef int ReturnStatus;
150 150
151/* 151/*
152 * The following statuses overlap with the first 2 generic statuses 152 * The following statuses overlap with the first 2 generic statuses
153 * defined in status.h: 153 * defined in status.h:
154 * 154 *
155 * SUCCESS There was no error. 155 * SUCCESS There was no error.
156 * FAILURE There was a general error. 156 * FAILURE There was a general error.
157 */ 157 */
158 158
159#define SUCCESS 0x00000000 159#define SUCCESS 0x00000000
160#define FAILURE 0x00000001 160#define FAILURE 0x00000001
161 161
162#include "lst.h" 162#include "lst.h"
 163#include "enum.h"
163#include "hash.h" 164#include "hash.h"
164#include "config.h" 165#include "config.h"
165#include "buf.h" 166#include "buf.h"
166#include "make_malloc.h" 167#include "make_malloc.h"
167 168
168typedef enum { 169typedef enum {
169 UNMADE, /* Not examined yet */ 170 UNMADE, /* Not examined yet */
170 DEFERRED, /* Examined once (building child) */ 171 DEFERRED, /* Examined once (building child) */
171 REQUESTED, /* on toBeMade list */ 172 REQUESTED, /* on toBeMade list */
172 BEINGMADE, /* Target is already being made. 173 BEINGMADE, /* Target is already being made.
173 * Indicates a cycle in the graph. */ 174 * Indicates a cycle in the graph. */
174 MADE, /* Was out-of-date and has been made */ 175 MADE, /* Was out-of-date and has been made */
175 UPTODATE, /* Was already up-to-date */ 176 UPTODATE, /* Was already up-to-date */
176 ERROR, /* An error occurred while it was being 177 ERROR, /* An error occurred while it was being
177 * made (used only in compat mode) */ 178 * made (used only in compat mode) */
178 ABORTED /* The target was aborted due to an error 179 ABORTED /* The target was aborted due to an error
179 * making an inferior (compat). */ 180 * making an inferior (compat). */
180} GNodeMade; 181} GNodeMade;
181 182
182/* The OP_ constants are used when parsing a dependency line as a way of 183/* The OP_ constants are used when parsing a dependency line as a way of
183 * communicating to other parts of the program the way in which a target 184 * communicating to other parts of the program the way in which a target
184 * should be made. 185 * should be made.
185 * 186 *
186 * These constants are bitwise-OR'ed together and placed in the 'type' field 187 * These constants are bitwise-OR'ed together and placed in the 'type' field
187 * of each node. Any node that has a 'type' field which satisfies the OP_NOP 188 * of each node. Any node that has a 'type' field which satisfies the OP_NOP
188 * function was never never on the left-hand side of an operator, though it 189 * function was never never on the left-hand side of an operator, though it
189 * may have been on the right-hand side... */ 190 * may have been on the right-hand side... */
190typedef enum { 191typedef enum {
191 /* Execution of commands depends on children (:) */ 192 /* Execution of commands depends on children (:) */
192 OP_DEPENDS = 1 << 0, 193 OP_DEPENDS = 1 << 0,
193 /* Always execute commands (!) */ 194 /* Always execute commands (!) */
194 OP_FORCE = 1 << 1, 195 OP_FORCE = 1 << 1,
195 /* Execution of commands depends on children per line (::) */ 196 /* Execution of commands depends on children per line (::) */
196 OP_DOUBLEDEP = 1 << 2, 197 OP_DOUBLEDEP = 1 << 2,
197 198
198 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP, 199 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP,
199 200
200 /* Don't care if the target doesn't exist and can't be created */ 201 /* Don't care if the target doesn't exist and can't be created */
201 OP_OPTIONAL = 1 << 3, 202 OP_OPTIONAL = 1 << 3,
202 /* Use associated commands for parents */ 203 /* Use associated commands for parents */
203 OP_USE = 1 << 4, 204 OP_USE = 1 << 4,
204 /* Target is never out of date, but always execute commands anyway. 205 /* Target is never out of date, but always execute commands anyway.
205 * Its time doesn't matter, so it has none...sort of */ 206 * Its time doesn't matter, so it has none...sort of */
206 OP_EXEC = 1 << 5, 207 OP_EXEC = 1 << 5,
207 /* Ignore errors when creating the node */ 208 /* Ignore errors when creating the node */
208 OP_IGNORE = 1 << 6, 209 OP_IGNORE = 1 << 6,
209 /* Don't remove the target when interrupted */ 210 /* Don't remove the target when interrupted */
210 OP_PRECIOUS = 1 << 7, 211 OP_PRECIOUS = 1 << 7,
211 /* Don't echo commands when executed */ 212 /* Don't echo commands when executed */
212 OP_SILENT = 1 << 8, 213 OP_SILENT = 1 << 8,
213 /* Target is a recursive make so its commands should always be executed 214 /* Target is a recursive make so its commands should always be executed
214 * when it is out of date, regardless of the state of the -n or -t flags */ 215 * when it is out of date, regardless of the state of the -n or -t flags */
215 OP_MAKE = 1 << 9, 216 OP_MAKE = 1 << 9,
216 /* Target is out-of-date only if any of its children was out-of-date */ 217 /* Target is out-of-date only if any of its children was out-of-date */
217 OP_JOIN = 1 << 10, 218 OP_JOIN = 1 << 10,
218 /* Assume the children of the node have been already made */ 219 /* Assume the children of the node have been already made */
219 OP_MADE = 1 << 11, 220 OP_MADE = 1 << 11,
220 /* Special .BEGIN, .END, .INTERRUPT */ 221 /* Special .BEGIN, .END, .INTERRUPT */
221 OP_SPECIAL = 1 << 12, 222 OP_SPECIAL = 1 << 12,
222 /* Like .USE, only prepend commands */ 223 /* Like .USE, only prepend commands */
223 OP_USEBEFORE = 1 << 13, 224 OP_USEBEFORE = 1 << 13,
224 /* The node is invisible to its parents. I.e. it doesn't show up in the 225 /* The node is invisible to its parents. I.e. it doesn't show up in the
225 * parents' local variables. */ 226 * parents' local variables. */
226 OP_INVISIBLE = 1 << 14, 227 OP_INVISIBLE = 1 << 14,
227 /* The node is exempt from normal 'main target' processing in parse.c */ 228 /* The node is exempt from normal 'main target' processing in parse.c */
228 OP_NOTMAIN = 1 << 15, 229 OP_NOTMAIN = 1 << 15,
229 /* Not a file target; run always */ 230 /* Not a file target; run always */
230 OP_PHONY = 1 << 16, 231 OP_PHONY = 1 << 16,
231 /* Don't search for file in the path */ 232 /* Don't search for file in the path */
232 OP_NOPATH = 1 << 17, 233 OP_NOPATH = 1 << 17,
233 /* .WAIT phony node */ 234 /* .WAIT phony node */
234 OP_WAIT = 1 << 18, 235 OP_WAIT = 1 << 18,
235 /* .NOMETA do not create a .meta file */ 236 /* .NOMETA do not create a .meta file */
236 OP_NOMETA = 1 << 19, 237 OP_NOMETA = 1 << 19,
237 /* .META we _do_ want a .meta file */ 238 /* .META we _do_ want a .meta file */
238 OP_META = 1 << 20, 239 OP_META = 1 << 20,
239 /* Do not compare commands in .meta file */ 240 /* Do not compare commands in .meta file */
240 OP_NOMETA_CMP = 1 << 21, 241 OP_NOMETA_CMP = 1 << 21,
241 /* Possibly a submake node */ 242 /* Possibly a submake node */
242 OP_SUBMAKE = 1 << 22, 243 OP_SUBMAKE = 1 << 22,
243 244
244 /* Attributes applied by PMake */ 245 /* Attributes applied by PMake */
245 246
246 /* The node is a transformation rule */ 247 /* The node is a transformation rule */
247 OP_TRANSFORM = 1 << 31, 248 OP_TRANSFORM = 1 << 31,
248 /* Target is a member of an archive */ 249 /* Target is a member of an archive */
249 OP_MEMBER = 1 << 30, 250 OP_MEMBER = 1 << 30,
250 /* Target is a library */ 251 /* Target is a library */
251 OP_LIB = 1 << 29, 252 OP_LIB = 1 << 29,
252 /* Target is an archive construct */ 253 /* Target is an archive construct */
253 OP_ARCHV = 1 << 28, 254 OP_ARCHV = 1 << 28,
254 /* Target has all the commands it should. Used when parsing to catch 255 /* Target has all the commands it should. Used when parsing to catch
255 * multiple commands for a target. */ 256 * multiple commands for a target. */
256 OP_HAS_COMMANDS = 1 << 27, 257 OP_HAS_COMMANDS = 1 << 27,
257 /* Saving commands on .END (Compat) */ 258 /* Saving commands on .END (Compat) */
258 OP_SAVE_CMDS = 1 << 26, 259 OP_SAVE_CMDS = 1 << 26,
259 /* Already processed by Suff_FindDeps */ 260 /* Already processed by Suff_FindDeps */
260 OP_DEPS_FOUND = 1 << 25, 261 OP_DEPS_FOUND = 1 << 25,
261 /* Node found while expanding .ALLSRC */ 262 /* Node found while expanding .ALLSRC */
262 OP_MARK = 1 << 24 263 OP_MARK = 1 << 24
263} GNodeType; 264} GNodeType;
264 265
265typedef enum { 266typedef enum {
266 REMAKE = 0x0001, /* this target needs to be (re)made */ 267 REMAKE = 0x0001, /* this target needs to be (re)made */
267 CHILDMADE = 0x0002, /* children of this target were made */ 268 CHILDMADE = 0x0002, /* children of this target were made */
268 FORCE = 0x0004, /* children don't exist, and we pretend made */ 269 FORCE = 0x0004, /* children don't exist, and we pretend made */
269 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */ 270 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */
270 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */ 271 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */
271 FROM_DEPEND = 0x0020, /* Node created from .depend */ 272 FROM_DEPEND = 0x0020, /* Node created from .depend */
272 DONE_ALLSRC = 0x0040, /* We do it once only */ 273 DONE_ALLSRC = 0x0040, /* We do it once only */
273 CYCLE = 0x1000, /* Used by MakePrintStatus */ 274 CYCLE = 0x1000, /* Used by MakePrintStatus */
274 DONECYCLE = 0x2000, /* Used by MakePrintStatus */ 275 DONECYCLE = 0x2000, /* Used by MakePrintStatus */
275 INTERNAL = 0x4000 /* Internal use only */ 276 INTERNAL = 0x4000 /* Internal use only */
276} GNodeFlags; 277} GNodeFlags;
277 278
278/* A graph node represents a target that can possibly be made, including its 279/* A graph node represents a target that can possibly be made, including its
279 * relation to other targets and a lot of other details. */ 280 * relation to other targets and a lot of other details. */
280typedef struct GNode { 281typedef struct GNode {
281 /* The target's name, such as "clean" or "make.c" */ 282 /* The target's name, such as "clean" or "make.c" */
282 char *name; 283 char *name;
283 /* The unexpanded name of a .USE node */ 284 /* The unexpanded name of a .USE node */
284 char *uname; 285 char *uname;
285 /* The full pathname of the file belonging to the target. 286 /* The full pathname of the file belonging to the target.
286 * XXX: What about .PHONY targets? These don't have an associated path. */ 287 * XXX: What about .PHONY targets? These don't have an associated path. */
287 char *path; 288 char *path;
288 289
289 /* The type of operator used to define the sources (see the OP flags below). 290 /* The type of operator used to define the sources (see the OP flags below).
290 * XXX: This looks like a wild mixture of type and flags. */ 291 * XXX: This looks like a wild mixture of type and flags. */
291 GNodeType type; 292 GNodeType type;
292 /* whether it is involved in this invocation of make */ 293 /* whether it is involved in this invocation of make */
293 GNodeFlags flags; 294 GNodeFlags flags;
294 295
295 /* The state of processing on this node */ 296 /* The state of processing on this node */
296 GNodeMade made; 297 GNodeMade made;
297 int unmade; /* The number of unmade children */ 298 int unmade; /* The number of unmade children */
298 299
299 time_t mtime; /* Its modification time */ 300 time_t mtime; /* Its modification time */
300 struct GNode *cmgn; /* The youngest child */ 301 struct GNode *cmgn; /* The youngest child */
301 302
302 /* Links to parents for which this is an implied source. May be empty. 303 /* Links to parents for which this is an implied source. May be empty.
303 * Nodes that depend on this, as gleaned from the transformation rules. */ 304 * Nodes that depend on this, as gleaned from the transformation rules. */
304 Lst iParents; 305 Lst iParents;
305 306
306 /* Other nodes of the same name for the :: operator. */ 307 /* Other nodes of the same name for the :: operator. */
307 Lst cohorts; 308 Lst cohorts;
308 309
309 /* The nodes that depend on this one, or in other words, the nodes for 310 /* The nodes that depend on this one, or in other words, the nodes for
310 * which this is a source. */ 311 * which this is a source. */
311 Lst parents; 312 Lst parents;
312 /* The nodes on which this one depends. */ 313 /* The nodes on which this one depends. */
313 Lst children; 314 Lst children;
314 315
315 /* .ORDER nodes we need made. The nodes that must be made (if they're 316 /* .ORDER nodes we need made. The nodes that must be made (if they're
316 * made) before this node can be made, but that do not enter into the 317 * made) before this node can be made, but that do not enter into the
317 * datedness of this node. */ 318 * datedness of this node. */
318 Lst order_pred; 319 Lst order_pred;
319 /* .ORDER nodes who need us. The nodes that must be made (if they're made 320 /* .ORDER nodes who need us. The nodes that must be made (if they're made
320 * at all) after this node is made, but that do not depend on this node, 321 * at all) after this node is made, but that do not depend on this node,
321 * in the normal sense. */ 322 * in the normal sense. */
322 Lst order_succ; 323 Lst order_succ;
323 324
324 /* #n for this cohort */ 325 /* #n for this cohort */
325 char cohort_num[8]; 326 char cohort_num[8];
326 /* The number of unmade instances on the cohorts list */ 327 /* The number of unmade instances on the cohorts list */
327 int unmade_cohorts; 328 int unmade_cohorts;
328 /* Pointer to the first instance of a :: node; only set when on a cohorts 329 /* Pointer to the first instance of a :: node; only set when on a cohorts
329 * list */ 330 * list */
330 struct GNode *centurion; 331 struct GNode *centurion;
331 332
332 /* Last time (sequence number) we tried to make this node */ 333 /* Last time (sequence number) we tried to make this node */
333 unsigned int checked; 334 unsigned int checked;
334 335
335 /* The "local" variables that are specific to this target and this target 336 /* The "local" variables that are specific to this target and this target
336 * only, such as $@, $<, $?. */ 337 * only, such as $@, $<, $?. */
337 Hash_Table context; 338 Hash_Table context;
338 339
339 /* The commands to be given to a shell to create this target. */ 340 /* The commands to be given to a shell to create this target. */
340 Lst commands; 341 Lst commands;
341 342
342 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone 343 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone
343 * but the Suff module) */ 344 * but the Suff module) */
344 struct Suff *suffix; 345 struct Suff *suffix;
345 346
346 /* filename where the GNode got defined */ 347 /* filename where the GNode got defined */
347 const char *fname; 348 const char *fname;
348 /* line number where the GNode got defined */ 349 /* line number where the GNode got defined */
349 int lineno; 350 int lineno;
350} GNode; 351} GNode;
351 352
352#define NoExecute(gn) ((gn->type & OP_MAKE) ? noRecursiveExecute : noExecute) 353#define NoExecute(gn) ((gn->type & OP_MAKE) ? noRecursiveExecute : noExecute)
353/* 354/*
354 * OP_NOP will return TRUE if the node with the given type was not the 355 * OP_NOP will return TRUE if the node with the given type was not the
355 * object of a dependency operator 356 * object of a dependency operator
356 */ 357 */
357#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000) 358#define OP_NOP(t) (((t) & OP_OPMASK) == 0x00000000)
358 359
359#define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM) 360#define OP_NOTARGET (OP_NOTMAIN|OP_USE|OP_EXEC|OP_TRANSFORM)
360 361
361/* 362/*
362 * The TARG_ constants are used when calling the Targ_FindNode and 363 * The TARG_ constants are used when calling the Targ_FindNode and
363 * Targ_FindList functions in targ.c. They simply tell the functions what to 364 * Targ_FindList functions in targ.c. They simply tell the functions what to
364 * do if the desired node(s) is (are) not found. If the TARG_CREATE constant 365 * do if the desired node(s) is (are) not found. If the TARG_CREATE constant
365 * is given, a new, empty node will be created for the target, placed in the 366 * is given, a new, empty node will be created for the target, placed in the
366 * table of all targets and its address returned. If TARG_NOCREATE is given, 367 * table of all targets and its address returned. If TARG_NOCREATE is given,
367 * a NULL pointer will be returned. 368 * a NULL pointer will be returned.
368 */ 369 */
369#define TARG_NOCREATE 0x00 /* don't create it */ 370#define TARG_NOCREATE 0x00 /* don't create it */
370#define TARG_CREATE 0x01 /* create node if not found */ 371#define TARG_CREATE 0x01 /* create node if not found */
371#define TARG_NOHASH 0x02 /* don't look in/add to hash table */ 372#define TARG_NOHASH 0x02 /* don't look in/add to hash table */
372 373
373/* 374/*
374 * Error levels for parsing. PARSE_FATAL means the process cannot continue 375 * Error levels for parsing. PARSE_FATAL means the process cannot continue
375 * once the makefile has been parsed. PARSE_WARNING means it can. Passed 376 * once the makefile has been parsed. PARSE_WARNING means it can. Passed
376 * as the first argument to Parse_Error. 377 * as the first argument to Parse_Error.
377 */ 378 */
378#define PARSE_INFO 3 379#define PARSE_INFO 3
379#define PARSE_WARNING 2 380#define PARSE_WARNING 2
380#define PARSE_FATAL 1 381#define PARSE_FATAL 1
381 382
382/* 383/*
383 * Values returned by Cond_Eval. 384 * Values returned by Cond_Eval.
384 */ 385 */
385typedef enum { 386typedef enum {
386 COND_PARSE, /* Parse the next lines */ 387 COND_PARSE, /* Parse the next lines */
387 COND_SKIP, /* Skip the next lines */ 388 COND_SKIP, /* Skip the next lines */
388 COND_INVALID /* Not a conditional statement */ 389 COND_INVALID /* Not a conditional statement */
389} CondEvalResult; 390} CondEvalResult;
390 391
391/* 392/*
392 * Definitions for the "local" variables. Used only for clarity. 393 * Definitions for the "local" variables. Used only for clarity.
393 */ 394 */
394#define TARGET "@" /* Target of dependency */ 395#define TARGET "@" /* Target of dependency */
395#define OODATE "?" /* All out-of-date sources */ 396#define OODATE "?" /* All out-of-date sources */
396#define ALLSRC ">" /* All sources */ 397#define ALLSRC ">" /* All sources */
397#define IMPSRC "<" /* Source implied by transformation */ 398#define IMPSRC "<" /* Source implied by transformation */
398#define PREFIX "*" /* Common prefix */ 399#define PREFIX "*" /* Common prefix */
399#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ 400#define ARCHIVE "!" /* Archive in "archive(member)" syntax */
400#define MEMBER "%" /* Member in "archive(member)" syntax */ 401#define MEMBER "%" /* Member in "archive(member)" syntax */
401 402
402#define FTARGET "@F" /* file part of TARGET */ 403#define FTARGET "@F" /* file part of TARGET */
403#define DTARGET "@D" /* directory part of TARGET */ 404#define DTARGET "@D" /* directory part of TARGET */
404#define FIMPSRC "<F" /* file part of IMPSRC */ 405#define FIMPSRC "<F" /* file part of IMPSRC */
405#define DIMPSRC "<D" /* directory part of IMPSRC */ 406#define DIMPSRC "<D" /* directory part of IMPSRC */
406#define FPREFIX "*F" /* file part of PREFIX */ 407#define FPREFIX "*F" /* file part of PREFIX */
407#define DPREFIX "*D" /* directory part of PREFIX */ 408#define DPREFIX "*D" /* directory part of PREFIX */
408 409
409/* 410/*
410 * Global Variables 411 * Global Variables
411 */ 412 */
412extern Lst create; /* The list of target names specified on the 413extern Lst create; /* The list of target names specified on the
413 * command line. used to resolve #if 414 * command line. used to resolve #if
414 * make(...) statements */ 415 * make(...) statements */
415extern Lst dirSearchPath; /* The list of directories to search when 416extern Lst dirSearchPath; /* The list of directories to search when
416 * looking for targets */ 417 * looking for targets */
417 418
418extern Boolean compatMake; /* True if we are make compatible */ 419extern Boolean compatMake; /* True if we are make compatible */
419extern Boolean ignoreErrors; /* True if should ignore all errors */ 420extern Boolean ignoreErrors; /* True if should ignore all errors */
420extern Boolean beSilent; /* True if should print no commands */ 421extern Boolean beSilent; /* True if should print no commands */
421extern Boolean noExecute; /* True if should execute nothing */ 422extern Boolean noExecute; /* True if should execute nothing */
422extern Boolean noRecursiveExecute; /* True if should execute nothing */ 423extern Boolean noRecursiveExecute; /* True if should execute nothing */
423extern Boolean allPrecious; /* True if every target is precious */ 424extern Boolean allPrecious; /* True if every target is precious */
424extern Boolean deleteOnError; /* True if failed targets should be deleted */ 425extern Boolean deleteOnError; /* True if failed targets should be deleted */
425extern Boolean keepgoing; /* True if should continue on unaffected 426extern Boolean keepgoing; /* True if should continue on unaffected
426 * portions of the graph when have an error 427 * portions of the graph when have an error
427 * in one portion */ 428 * in one portion */
428extern Boolean touchFlag; /* TRUE if targets should just be 'touched' 429extern Boolean touchFlag; /* TRUE if targets should just be 'touched'
429 * if out of date. Set by the -t flag */ 430 * if out of date. Set by the -t flag */
430extern Boolean queryFlag; /* TRUE if we aren't supposed to really make 431extern Boolean queryFlag; /* TRUE if we aren't supposed to really make
431 * anything, just see if the targets are out- 432 * anything, just see if the targets are out-
432 * of-date */ 433 * of-date */
433extern Boolean doing_depend; /* TRUE if processing .depend */ 434extern Boolean doing_depend; /* TRUE if processing .depend */
434 435
435extern Boolean checkEnvFirst; /* TRUE if environment should be searched for 436extern Boolean checkEnvFirst; /* TRUE if environment should be searched for
436 * variables before the global context */ 437 * variables before the global context */
437 438
438extern Boolean parseWarnFatal; /* TRUE if makefile parsing warnings are 439extern Boolean parseWarnFatal; /* TRUE if makefile parsing warnings are
439 * treated as errors */ 440 * treated as errors */
440 441
441extern Boolean varNoExportEnv; /* TRUE if we should not export variables 442extern Boolean varNoExportEnv; /* TRUE if we should not export variables
442 * set on the command line to the env. */ 443 * set on the command line to the env. */
443 444
444extern GNode *DEFAULT; /* .DEFAULT rule */ 445extern GNode *DEFAULT; /* .DEFAULT rule */
445 446
446extern GNode *VAR_INTERNAL; /* Variables defined internally by make 447extern GNode *VAR_INTERNAL; /* Variables defined internally by make
447 * which should not override those set by 448 * which should not override those set by
448 * makefiles. 449 * makefiles.
449 */ 450 */
450extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g 451extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
451 * in the Makefile itself */ 452 * in the Makefile itself */
452extern GNode *VAR_CMD; /* Variables defined on the command line */ 453extern GNode *VAR_CMD; /* Variables defined on the command line */
453extern char var_Error[]; /* Value returned by Var_Parse when an error 454extern char var_Error[]; /* Value returned by Var_Parse when an error
454 * is encountered. It actually points to 455 * is encountered. It actually points to
455 * an empty string, so naive callers needn't 456 * an empty string, so naive callers needn't
456 * worry about it. */ 457 * worry about it. */
457 458
458extern time_t now; /* The time at the start of this whole 459extern time_t now; /* The time at the start of this whole
459 * process */ 460 * process */
460 461
461extern Boolean oldVars; /* Do old-style variable substitution */ 462extern Boolean oldVars; /* Do old-style variable substitution */
462 463
463extern Lst sysIncPath; /* The system include path. */ 464extern Lst sysIncPath; /* The system include path. */
464extern Lst defIncPath; /* The default include path. */ 465extern Lst defIncPath; /* The default include path. */
465 466
466extern char curdir[]; /* Startup directory */ 467extern char curdir[]; /* Startup directory */
467extern char *progname; /* The program name */ 468extern char *progname; /* The program name */
468extern char *makeDependfile; /* .depend */ 469extern char *makeDependfile; /* .depend */
469extern char **savedEnv; /* if we replaced environ this will be non-NULL */ 470extern char **savedEnv; /* if we replaced environ this will be non-NULL */
470 471
471extern int makelevel; 472extern int makelevel;
472 473
473/* 474/*
474 * We cannot vfork() in a child of vfork(). 475 * We cannot vfork() in a child of vfork().
475 * Most systems do not enforce this but some do. 476 * Most systems do not enforce this but some do.
476 */ 477 */
477#define vFork() ((getpid() == myPid) ? vfork() : fork()) 478#define vFork() ((getpid() == myPid) ? vfork() : fork())
478extern pid_t myPid; 479extern pid_t myPid;
479 480
480#define MAKEFLAGS ".MAKEFLAGS" 481#define MAKEFLAGS ".MAKEFLAGS"
481#define MAKEOVERRIDES ".MAKEOVERRIDES" 482#define MAKEOVERRIDES ".MAKEOVERRIDES"
482#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */ 483#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */
483#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */ 484#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */
484#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all the makefiles we read */ 485#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all the makefiles we read */
485#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */ 486#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
486#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE" 487#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
487#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */ 488#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */
488#define MAKE_MODE ".MAKE.MODE" 489#define MAKE_MODE ".MAKE.MODE"
489#ifndef MAKE_LEVEL_ENV 490#ifndef MAKE_LEVEL_ENV
490# define MAKE_LEVEL_ENV "MAKELEVEL" 491# define MAKE_LEVEL_ENV "MAKELEVEL"
491#endif 492#endif
492 493
493/* 494/*
494 * debug control: 495 * debug control:
495 * There is one bit per module. It is up to the module what debug 496 * There is one bit per module. It is up to the module what debug
496 * information to print. 497 * information to print.
497 */ 498 */
498extern FILE *debug_file; /* Output is written here - default stderr */ 499extern FILE *debug_file; /* Output is written here - default stderr */
499extern int debug; 500extern int debug;
500#define DEBUG_ARCH 0x00001 501#define DEBUG_ARCH 0x00001
501#define DEBUG_COND 0x00002 502#define DEBUG_COND 0x00002
502#define DEBUG_DIR 0x00004 503#define DEBUG_DIR 0x00004
503#define DEBUG_GRAPH1 0x00008 504#define DEBUG_GRAPH1 0x00008
504#define DEBUG_GRAPH2 0x00010 505#define DEBUG_GRAPH2 0x00010
505#define DEBUG_JOB 0x00020 506#define DEBUG_JOB 0x00020
506#define DEBUG_MAKE 0x00040 507#define DEBUG_MAKE 0x00040
507#define DEBUG_SUFF 0x00080 508#define DEBUG_SUFF 0x00080
508#define DEBUG_TARG 0x00100 509#define DEBUG_TARG 0x00100
509#define DEBUG_VAR 0x00200 510#define DEBUG_VAR 0x00200
510#define DEBUG_FOR 0x00400 511#define DEBUG_FOR 0x00400
511#define DEBUG_SHELL 0x00800 512#define DEBUG_SHELL 0x00800
512#define DEBUG_ERROR 0x01000 513#define DEBUG_ERROR 0x01000
513#define DEBUG_LOUD 0x02000 514#define DEBUG_LOUD 0x02000
514#define DEBUG_META 0x04000 515#define DEBUG_META 0x04000
515#define DEBUG_HASH 0x08000 516#define DEBUG_HASH 0x08000
516 517
517#define DEBUG_GRAPH3 0x10000 518#define DEBUG_GRAPH3 0x10000
518#define DEBUG_SCRIPT 0x20000 519#define DEBUG_SCRIPT 0x20000
519#define DEBUG_PARSE 0x40000 520#define DEBUG_PARSE 0x40000
520#define DEBUG_CWD 0x80000 521#define DEBUG_CWD 0x80000
521 522
522#define DEBUG_LINT 0x100000 523#define DEBUG_LINT 0x100000
523 524
524#define CONCAT(a,b) a##b 525#define CONCAT(a,b) a##b
525 526
526#define DEBUG(module) (debug & CONCAT(DEBUG_,module)) 527#define DEBUG(module) (debug & CONCAT(DEBUG_,module))
527 528
528#include "nonints.h" 529#include "nonints.h"
529 530
530int Make_TimeStamp(GNode *, GNode *); 531int Make_TimeStamp(GNode *, GNode *);
531Boolean Make_OODate(GNode *); 532Boolean Make_OODate(GNode *);
532void Make_ExpandUse(Lst); 533void Make_ExpandUse(Lst);
533time_t Make_Recheck(GNode *); 534time_t Make_Recheck(GNode *);
534void Make_HandleUse(GNode *, GNode *); 535void Make_HandleUse(GNode *, GNode *);
535void Make_Update(GNode *); 536void Make_Update(GNode *);
536void Make_DoAllVar(GNode *); 537void Make_DoAllVar(GNode *);
537Boolean Make_Run(Lst); 538Boolean Make_Run(Lst);
538int dieQuietly(GNode *, int); 539int dieQuietly(GNode *, int);
539void PrintOnError(GNode *, const char *); 540void PrintOnError(GNode *, const char *);
540void Main_ExportMAKEFLAGS(Boolean); 541void Main_ExportMAKEFLAGS(Boolean);
541Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); 542Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
542int mkTempFile(const char *, char **); 543int mkTempFile(const char *, char **);
543int str2Lst_Append(Lst, char *, const char *); 544int str2Lst_Append(Lst, char *, const char *);
544int cached_lstat(const char *, void *); 545int cached_lstat(const char *, void *);
545int cached_stat(const char *, void *); 546int cached_stat(const char *, void *);
546void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *); 547void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
547 548
548#ifdef __GNUC__ 549#ifdef __GNUC__
549#define UNCONST(ptr) ({ \ 550#define UNCONST(ptr) ({ \
550 union __unconst { \ 551 union __unconst { \
551 const void *__cp; \ 552 const void *__cp; \
552 void *__p; \ 553 void *__p; \
553 } __d; \ 554 } __d; \
554 __d.__cp = ptr, __d.__p; }) 555 __d.__cp = ptr, __d.__p; })
555#else 556#else
556#define UNCONST(ptr) (void *)(ptr) 557#define UNCONST(ptr) (void *)(ptr)
557#endif 558#endif
558 559
559#ifndef MIN 560#ifndef MIN
560#define MIN(a, b) ((a < b) ? a : b) 561#define MIN(a, b) ((a < b) ? a : b)
561#endif 562#endif
562#ifndef MAX 563#ifndef MAX
563#define MAX(a, b) ((a > b) ? a : b) 564#define MAX(a, b) ((a > b) ? a : b)
564#endif 565#endif
565 566
566/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */ 567/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
567#include <limits.h> 568#include <limits.h>
568#ifndef MAXPATHLEN 569#ifndef MAXPATHLEN
569#define MAXPATHLEN 4096 570#define MAXPATHLEN 4096
570#endif 571#endif
571#ifndef PATH_MAX 572#ifndef PATH_MAX
572#define PATH_MAX MAXPATHLEN 573#define PATH_MAX MAXPATHLEN
573#endif 574#endif
574 575
575#if defined(SYSV) 576#if defined(SYSV)
576#define KILLPG(pid, sig) kill(-(pid), (sig)) 577#define KILLPG(pid, sig) kill(-(pid), (sig))
577#else 578#else
578#define KILLPG(pid, sig) killpg((pid), (sig)) 579#define KILLPG(pid, sig) killpg((pid), (sig))
579#endif 580#endif
580 581
581#endif /* MAKE_MAKE_H */ 582#endif /* MAKE_MAKE_H */

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

--- src/usr.bin/make/suff.c 2020/08/27 19:15:35 1.121
+++ src/usr.bin/make/suff.c 2020/08/28 03:35:45 1.122
@@ -1,1160 +1,1164 @@ @@ -1,1160 +1,1164 @@
1/* $NetBSD: suff.c,v 1.121 2020/08/27 19:15:35 rillig Exp $ */ 1/* $NetBSD: suff.c,v 1.122 2020/08/28 03:35:45 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors 54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: suff.c,v 1.121 2020/08/27 19:15:35 rillig Exp $"; 72static char rcsid[] = "$NetBSD: suff.c,v 1.122 2020/08/28 03:35:45 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94"; 77static char sccsid[] = "@(#)suff.c 8.4 (Berkeley) 3/21/94";
78#else 78#else
79__RCSID("$NetBSD: suff.c,v 1.121 2020/08/27 19:15:35 rillig Exp $"); 79__RCSID("$NetBSD: suff.c,v 1.122 2020/08/28 03:35:45 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * suff.c -- 85 * suff.c --
86 * Functions to maintain suffix lists and find implicit dependents 86 * Functions to maintain suffix lists and find implicit dependents
87 * using suffix transformation rules 87 * using suffix transformation rules
88 * 88 *
89 * Interface: 89 * Interface:
90 * Suff_Init Initialize all things to do with suffixes. 90 * Suff_Init Initialize all things to do with suffixes.
91 * 91 *
92 * Suff_End Cleanup the module 92 * Suff_End Cleanup the module
93 * 93 *
94 * Suff_DoPaths This function is used to make life easier 94 * Suff_DoPaths This function is used to make life easier
95 * when searching for a file according to its 95 * when searching for a file according to its
96 * suffix. It takes the global search path, 96 * suffix. It takes the global search path,
97 * as defined using the .PATH: target, and appends 97 * as defined using the .PATH: target, and appends
98 * its directories to the path of each of the 98 * its directories to the path of each of the
99 * defined suffixes, as specified using 99 * defined suffixes, as specified using
100 * .PATH<suffix>: targets. In addition, all 100 * .PATH<suffix>: targets. In addition, all
101 * directories given for suffixes labeled as 101 * directories given for suffixes labeled as
102 * include files or libraries, using the .INCLUDES 102 * include files or libraries, using the .INCLUDES
103 * or .LIBS targets, are played with using 103 * or .LIBS targets, are played with using
104 * Dir_MakeFlags to create the .INCLUDES and 104 * Dir_MakeFlags to create the .INCLUDES and
105 * .LIBS global variables. 105 * .LIBS global variables.
106 * 106 *
107 * Suff_ClearSuffixes Clear out all the suffixes and defined 107 * Suff_ClearSuffixes Clear out all the suffixes and defined
108 * transformations. 108 * transformations.
109 * 109 *
110 * Suff_IsTransform Return TRUE if the passed string is the lhs 110 * Suff_IsTransform Return TRUE if the passed string is the lhs
111 * of a transformation rule. 111 * of a transformation rule.
112 * 112 *
113 * Suff_AddSuffix Add the passed string as another known suffix. 113 * Suff_AddSuffix Add the passed string as another known suffix.
114 * 114 *
115 * Suff_GetPath Return the search path for the given suffix. 115 * Suff_GetPath Return the search path for the given suffix.
116 * 116 *
117 * Suff_AddInclude Mark the given suffix as denoting an include 117 * Suff_AddInclude Mark the given suffix as denoting an include
118 * file. 118 * file.
119 * 119 *
120 * Suff_AddLib Mark the given suffix as denoting a library. 120 * Suff_AddLib Mark the given suffix as denoting a library.
121 * 121 *
122 * Suff_AddTransform Add another transformation to the suffix 122 * Suff_AddTransform Add another transformation to the suffix
123 * graph. Returns GNode suitable for framing, I 123 * graph. Returns GNode suitable for framing, I
124 * mean, tacking commands, attributes, etc. on. 124 * mean, tacking commands, attributes, etc. on.
125 * 125 *
126 * Suff_SetNull Define the suffix to consider the suffix of 126 * Suff_SetNull Define the suffix to consider the suffix of
127 * any file that doesn't have a known one. 127 * any file that doesn't have a known one.
128 * 128 *
129 * Suff_FindDeps Find implicit sources for and the location of 129 * Suff_FindDeps Find implicit sources for and the location of
130 * a target based on its suffix. Returns the 130 * a target based on its suffix. Returns the
131 * bottom-most node added to the graph or NULL 131 * bottom-most node added to the graph or NULL
132 * if the target had no implicit sources. 132 * if the target had no implicit sources.
133 * 133 *
134 * Suff_FindPath Return the appropriate path to search in 134 * Suff_FindPath Return the appropriate path to search in
135 * order to find the node. 135 * order to find the node.
136 */ 136 */
137 137
138#include "make.h" 138#include "make.h"
139#include "dir.h" 139#include "dir.h"
140 140
141static Lst sufflist; /* Lst of suffixes */ 141static Lst sufflist; /* Lst of suffixes */
142#ifdef CLEANUP 142#ifdef CLEANUP
143static Lst suffClean; /* Lst of suffixes to be cleaned */ 143static Lst suffClean; /* Lst of suffixes to be cleaned */
144#endif 144#endif
145static Lst srclist; /* Lst of sources */ 145static Lst srclist; /* Lst of sources */
146static Lst transforms; /* Lst of transformation rules */ 146static Lst transforms; /* Lst of transformation rules */
147 147
148static int sNum = 0; /* Counter for assigning suffix numbers */ 148static int sNum = 0; /* Counter for assigning suffix numbers */
149 149
150typedef enum { 150typedef enum {
151 SUFF_INCLUDE = 0x01, /* One which is #include'd */ 151 SUFF_INCLUDE = 0x01, /* One which is #include'd */
152 SUFF_LIBRARY = 0x02, /* One which contains a library */ 152 SUFF_LIBRARY = 0x02, /* One which contains a library */
153 SUFF_NULL = 0x04 /* The empty suffix */ 153 SUFF_NULL = 0x04 /* The empty suffix */
 154 /* XXX: Why is SUFF_NULL needed? Wouldn't nameLen == 0 mean the same? */
154} SuffFlags; 155} SuffFlags;
155 156
 157ENUM_FLAGS_RTTI_3(SuffFlags,
 158 SUFF_INCLUDE, SUFF_LIBRARY, SUFF_NULL);
 159
156/* 160/*
157 * Structure describing an individual suffix. 161 * Structure describing an individual suffix.
158 */ 162 */
159typedef struct Suff { 163typedef struct Suff {
160 char *name; /* The suffix itself */ 164 char *name; /* The suffix itself, such as ".c" */
161 int nameLen; /* Length of the suffix */ 165 int nameLen; /* Length of the name, to avoid strlen calls */
162 SuffFlags flags; /* Type of suffix */ 166 SuffFlags flags; /* Type of suffix */
163 Lst searchPath; /* The path along which files of this suffix 167 Lst searchPath; /* The path along which files of this suffix
164 * may be found */ 168 * may be found */
165 int sNum; /* The suffix number */ 169 int sNum; /* The suffix number */
166 int refCount; /* Reference count of list membership */ 170 int refCount; /* Reference count of list membership */
167 Lst parents; /* Suffixes we have a transformation to */ 171 Lst parents; /* Suffixes we have a transformation to */
168 Lst children; /* Suffixes we have a transformation from */ 172 Lst children; /* Suffixes we have a transformation from */
169 Lst ref; /* List of lists this suffix is referenced */ 173 Lst ref; /* List of lists this suffix is referenced */
170} Suff; 174} Suff;
171 175
172/* 176/*
173 * for SuffSuffIsSuffix 177 * for SuffSuffIsSuffix
174 */ 178 */
175typedef struct { 179typedef struct {
176 char *ename; /* The end of the name */ 180 char *ename; /* The end of the name */
177 int len; /* Length of the name */ 181 int len; /* Length of the name */
178} SuffixCmpData; 182} SuffixCmpData;
179 183
180/* 184/*
181 * Structure used in the search for implied sources. 185 * Structure used in the search for implied sources.
182 */ 186 */
183typedef struct _Src { 187typedef struct _Src {
184 char *file; /* The file to look for */ 188 char *file; /* The file to look for */
185 char *pref; /* Prefix from which file was formed */ 189 char *pref; /* Prefix from which file was formed */
186 Suff *suff; /* The suffix on the file */ 190 Suff *suff; /* The suffix on the file */
187 struct _Src *parent; /* The Src for which this is a source */ 191 struct _Src *parent; /* The Src for which this is a source */
188 GNode *node; /* The node describing the file */ 192 GNode *node; /* The node describing the file */
189 int children; /* Count of existing children (so we don't free 193 int children; /* Count of existing children (so we don't free
190 * this thing too early or never nuke it) */ 194 * this thing too early or never nuke it) */
191#ifdef DEBUG_SRC 195#ifdef DEBUG_SRC
192 Lst cp; /* Debug; children list */ 196 Lst cp; /* Debug; children list */
193#endif 197#endif
194} Src; 198} Src;
195 199
196/* 200/*
197 * A structure for passing more than one argument to the Lst-library-invoked 201 * A structure for passing more than one argument to the Lst-library-invoked
198 * function... 202 * function...
199 */ 203 */
200typedef struct { 204typedef struct {
201 Lst l; 205 Lst l;
202 Src *s; 206 Src *s;
203} LstSrc; 207} LstSrc;
204 208
205typedef struct { 209typedef struct {
206 GNode **gn; 210 GNode **gn;
207 Suff *s; 211 Suff *s;
208 Boolean r; 212 Boolean r;
209} GNodeSuff; 213} GNodeSuff;
210 214
211static Suff *suffNull; /* The NULL suffix for this run */ 215static Suff *suffNull; /* The NULL suffix for this run */
212static Suff *emptySuff; /* The empty suffix required for POSIX 216static Suff *emptySuff; /* The empty suffix required for POSIX
213 * single-suffix transformation rules */ 217 * single-suffix transformation rules */
214 218
215 219
216static const char *SuffStrIsPrefix(const char *, const char *); 220static const char *SuffStrIsPrefix(const char *, const char *);
217static char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *); 221static char *SuffSuffIsSuffix(const Suff *, const SuffixCmpData *);
218static int SuffSuffIsSuffixP(const void *, const void *); 222static int SuffSuffIsSuffixP(const void *, const void *);
219static int SuffSuffHasNameP(const void *, const void *); 223static int SuffSuffHasNameP(const void *, const void *);
220static int SuffSuffIsPrefix(const void *, const void *); 224static int SuffSuffIsPrefix(const void *, const void *);
221static int SuffGNHasNameP(const void *, const void *); 225static int SuffGNHasNameP(const void *, const void *);
222static void SuffUnRef(void *, void *); 226static void SuffUnRef(void *, void *);
223static void SuffFree(void *); 227static void SuffFree(void *);
224static void SuffInsert(Lst, Suff *); 228static void SuffInsert(Lst, Suff *);
225static void SuffRemove(Lst, Suff *); 229static void SuffRemove(Lst, Suff *);
226static Boolean SuffParseTransform(char *, Suff **, Suff **); 230static Boolean SuffParseTransform(char *, Suff **, Suff **);
227static int SuffRebuildGraph(void *, void *); 231static int SuffRebuildGraph(void *, void *);
228static int SuffScanTargets(void *, void *); 232static int SuffScanTargets(void *, void *);
229static int SuffAddSrc(void *, void *); 233static int SuffAddSrc(void *, void *);
230static int SuffRemoveSrc(Lst); 234static int SuffRemoveSrc(Lst);
231static void SuffAddLevel(Lst, Src *); 235static void SuffAddLevel(Lst, Src *);
232static Src *SuffFindCmds(Src *, Lst); 236static Src *SuffFindCmds(Src *, Lst);
233static void SuffExpandChildren(LstNode, GNode *); 237static void SuffExpandChildren(LstNode, GNode *);
234static void SuffExpandWildcards(LstNode, GNode *); 238static void SuffExpandWildcards(LstNode, GNode *);
235static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *); 239static Boolean SuffApplyTransform(GNode *, GNode *, Suff *, Suff *);
236static void SuffFindDeps(GNode *, Lst); 240static void SuffFindDeps(GNode *, Lst);
237static void SuffFindArchiveDeps(GNode *, Lst); 241static void SuffFindArchiveDeps(GNode *, Lst);
238static void SuffFindNormalDeps(GNode *, Lst); 242static void SuffFindNormalDeps(GNode *, Lst);
239static int SuffPrintName(void *, void *); 243static int SuffPrintName(void *, void *);
240static int SuffPrintSuff(void *, void *); 244static int SuffPrintSuff(void *, void *);
241static int SuffPrintTrans(void *, void *); 245static int SuffPrintTrans(void *, void *);
242 246
243 /*************** Lst Predicates ****************/ 247 /*************** Lst Predicates ****************/
244/*- 248/*-
245 *----------------------------------------------------------------------- 249 *-----------------------------------------------------------------------
246 * SuffStrIsPrefix -- 250 * SuffStrIsPrefix --
247 * See if pref is a prefix of str. 251 * See if pref is a prefix of str.
248 * 252 *
249 * Input: 253 * Input:
250 * pref possible prefix 254 * pref possible prefix
251 * str string to check 255 * str string to check
252 * 256 *
253 * Results: 257 * Results:
254 * NULL if it ain't, pointer to character in str after prefix if so 258 * NULL if it ain't, pointer to character in str after prefix if so
255 * 259 *
256 * Side Effects: 260 * Side Effects:
257 * None 261 * None
258 *----------------------------------------------------------------------- 262 *-----------------------------------------------------------------------
259 */ 263 */
260static const char * 264static const char *
261SuffStrIsPrefix(const char *pref, const char *str) 265SuffStrIsPrefix(const char *pref, const char *str)
262{ 266{
263 while (*str && *pref == *str) { 267 while (*str && *pref == *str) {
264 pref++; 268 pref++;
265 str++; 269 str++;
266 } 270 }
267 271
268 return *pref ? NULL : str; 272 return *pref ? NULL : str;
269} 273}
270 274
271/*- 275/*-
272 *----------------------------------------------------------------------- 276 *-----------------------------------------------------------------------
273 * SuffSuffIsSuffix -- 277 * SuffSuffIsSuffix --
274 * See if suff is a suffix of str. sd->ename should point to THE END 278 * See if suff is a suffix of str. sd->ename should point to THE END
275 * of the string to check. (THE END == the null byte) 279 * of the string to check. (THE END == the null byte)
276 * 280 *
277 * Input: 281 * Input:
278 * s possible suffix 282 * s possible suffix
279 * sd string to examine 283 * sd string to examine
280 * 284 *
281 * Results: 285 * Results:
282 * NULL if it ain't, pointer to character in str before suffix if 286 * NULL if it ain't, pointer to character in str before suffix if
283 * it is. 287 * it is.
284 * 288 *
285 * Side Effects: 289 * Side Effects:
286 * None 290 * None
287 *----------------------------------------------------------------------- 291 *-----------------------------------------------------------------------
288 */ 292 */
289static char * 293static char *
290SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd) 294SuffSuffIsSuffix(const Suff *s, const SuffixCmpData *sd)
291{ 295{
292 char *p1; /* Pointer into suffix name */ 296 char *p1; /* Pointer into suffix name */
293 char *p2; /* Pointer into string being examined */ 297 char *p2; /* Pointer into string being examined */
294 298
295 if (sd->len < s->nameLen) 299 if (sd->len < s->nameLen)
296 return NULL; /* this string is shorter than the suffix */ 300 return NULL; /* this string is shorter than the suffix */
297 301
298 p1 = s->name + s->nameLen; 302 p1 = s->name + s->nameLen;
299 p2 = sd->ename; 303 p2 = sd->ename;
300 304
301 while (p1 >= s->name && *p1 == *p2) { 305 while (p1 >= s->name && *p1 == *p2) {
302 p1--; 306 p1--;
303 p2--; 307 p2--;
304 } 308 }
305 309
306 return p1 == s->name - 1 ? p2 : NULL; 310 return p1 == s->name - 1 ? p2 : NULL;
307} 311}
308 312
309/*- 313/*-
310 *----------------------------------------------------------------------- 314 *-----------------------------------------------------------------------
311 * SuffSuffIsSuffixP -- 315 * SuffSuffIsSuffixP --
312 * Predicate form of SuffSuffIsSuffix. Passed as the callback function 316 * Predicate form of SuffSuffIsSuffix. Passed as the callback function
313 * to Lst_Find. 317 * to Lst_Find.
314 * 318 *
315 * Results: 319 * Results:
316 * 0 if the suffix is the one desired, non-zero if not. 320 * 0 if the suffix is the one desired, non-zero if not.
317 * 321 *
318 * Side Effects: 322 * Side Effects:
319 * None. 323 * None.
320 * 324 *
321 *----------------------------------------------------------------------- 325 *-----------------------------------------------------------------------
322 */ 326 */
323static int 327static int
324SuffSuffIsSuffixP(const void *s, const void *sd) 328SuffSuffIsSuffixP(const void *s, const void *sd)
325{ 329{
326 return !SuffSuffIsSuffix(s, sd); 330 return !SuffSuffIsSuffix(s, sd);
327} 331}
328 332
329/*- 333/*-
330 *----------------------------------------------------------------------- 334 *-----------------------------------------------------------------------
331 * SuffSuffHasNameP -- 335 * SuffSuffHasNameP --
332 * Callback procedure for finding a suffix based on its name. Used by 336 * Callback procedure for finding a suffix based on its name. Used by
333 * Suff_GetPath. 337 * Suff_GetPath.
334 * 338 *
335 * Input: 339 * Input:
336 * s Suffix to check 340 * s Suffix to check
337 * sd Desired name 341 * sd Desired name
338 * 342 *
339 * Results: 343 * Results:
340 * 0 if the suffix is of the given name. non-zero otherwise. 344 * 0 if the suffix is of the given name. non-zero otherwise.
341 * 345 *
342 * Side Effects: 346 * Side Effects:
343 * None 347 * None
344 *----------------------------------------------------------------------- 348 *-----------------------------------------------------------------------
345 */ 349 */
346static int 350static int
347SuffSuffHasNameP(const void *s, const void *sname) 351SuffSuffHasNameP(const void *s, const void *sname)
348{ 352{
349 return strcmp(sname, ((const Suff *)s)->name); 353 return strcmp(sname, ((const Suff *)s)->name);
350} 354}
351 355
352/*- 356/*-
353 *----------------------------------------------------------------------- 357 *-----------------------------------------------------------------------
354 * SuffSuffIsPrefix -- 358 * SuffSuffIsPrefix --
355 * See if the suffix described by s is a prefix of the string. Care 359 * See if the suffix described by s is a prefix of the string. Care
356 * must be taken when using this to search for transformations and 360 * must be taken when using this to search for transformations and
357 * what-not, since there could well be two suffixes, one of which 361 * what-not, since there could well be two suffixes, one of which
358 * is a prefix of the other... 362 * is a prefix of the other...
359 * 363 *
360 * Input: 364 * Input:
361 * s suffix to compare 365 * s suffix to compare
362 * str string to examine 366 * str string to examine
363 * 367 *
364 * Results: 368 * Results:
365 * 0 if s is a prefix of str. non-zero otherwise 369 * 0 if s is a prefix of str. non-zero otherwise
366 * 370 *
367 * Side Effects: 371 * Side Effects:
368 * None 372 * None
369 *----------------------------------------------------------------------- 373 *-----------------------------------------------------------------------
370 */ 374 */
371static int 375static int
372SuffSuffIsPrefix(const void *s, const void *str) 376SuffSuffIsPrefix(const void *s, const void *str)
373{ 377{
374 return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL; 378 return SuffStrIsPrefix(((const Suff *)s)->name, str) == NULL;
375} 379}
376 380
377/*- 381/*-
378 *----------------------------------------------------------------------- 382 *-----------------------------------------------------------------------
379 * SuffGNHasNameP -- 383 * SuffGNHasNameP --
380 * See if the graph node has the desired name 384 * See if the graph node has the desired name
381 * 385 *
382 * Input: 386 * Input:
383 * gn current node we're looking at 387 * gn current node we're looking at
384 * name name we're looking for 388 * name name we're looking for
385 * 389 *
386 * Results: 390 * Results:
387 * 0 if it does. non-zero if it doesn't 391 * 0 if it does. non-zero if it doesn't
388 * 392 *
389 * Side Effects: 393 * Side Effects:
390 * None 394 * None
391 *----------------------------------------------------------------------- 395 *-----------------------------------------------------------------------
392 */ 396 */
393static int 397static int
394SuffGNHasNameP(const void *gn, const void *name) 398SuffGNHasNameP(const void *gn, const void *name)
395{ 399{
396 return strcmp(name, ((const GNode *)gn)->name); 400 return strcmp(name, ((const GNode *)gn)->name);
397} 401}
398 402
399 /*********** Maintenance Functions ************/ 403 /*********** Maintenance Functions ************/
400 404
401static void 405static void
402SuffUnRef(void *lp, void *sp) 406SuffUnRef(void *lp, void *sp)
403{ 407{
404 Lst l = (Lst) lp; 408 Lst l = (Lst) lp;
405 409
406 LstNode ln = Lst_MemberS(l, sp); 410 LstNode ln = Lst_MemberS(l, sp);
407 if (ln != NULL) { 411 if (ln != NULL) {
408 Lst_RemoveS(l, ln); 412 Lst_RemoveS(l, ln);
409 ((Suff *)sp)->refCount--; 413 ((Suff *)sp)->refCount--;
410 } 414 }
411} 415}
412 416
413/*- 417/*-
414 *----------------------------------------------------------------------- 418 *-----------------------------------------------------------------------
415 * SuffFree -- 419 * SuffFree --
416 * Free up all memory associated with the given suffix structure. 420 * Free up all memory associated with the given suffix structure.
417 * 421 *
418 * Results: 422 * Results:
419 * none 423 * none
420 * 424 *
421 * Side Effects: 425 * Side Effects:
422 * the suffix entry is detroyed 426 * the suffix entry is detroyed
423 *----------------------------------------------------------------------- 427 *-----------------------------------------------------------------------
424 */ 428 */
425static void 429static void
426SuffFree(void *sp) 430SuffFree(void *sp)
427{ 431{
428 Suff *s = (Suff *)sp; 432 Suff *s = (Suff *)sp;
429 433
430 if (s == suffNull) 434 if (s == suffNull)
431 suffNull = NULL; 435 suffNull = NULL;
432 436
433 if (s == emptySuff) 437 if (s == emptySuff)
434 emptySuff = NULL; 438 emptySuff = NULL;
435 439
436#ifdef notdef 440#ifdef notdef
437 /* We don't delete suffixes in order, so we cannot use this */ 441 /* We don't delete suffixes in order, so we cannot use this */
438 if (s->refCount) 442 if (s->refCount)
439 Punt("Internal error deleting suffix `%s' with refcount = %d", s->name, 443 Punt("Internal error deleting suffix `%s' with refcount = %d", s->name,
440 s->refCount); 444 s->refCount);
441#endif 445#endif
442 446
443 Lst_FreeS(s->ref); 447 Lst_FreeS(s->ref);
444 Lst_FreeS(s->children); 448 Lst_FreeS(s->children);
445 Lst_FreeS(s->parents); 449 Lst_FreeS(s->parents);
446 Lst_DestroyS(s->searchPath, Dir_Destroy); 450 Lst_DestroyS(s->searchPath, Dir_Destroy);
447 451
448 free(s->name); 452 free(s->name);
449 free(s); 453 free(s);
450} 454}
451 455
452/*- 456/*-
453 *----------------------------------------------------------------------- 457 *-----------------------------------------------------------------------
454 * SuffRemove -- 458 * SuffRemove --
455 * Remove the suffix into the list 459 * Remove the suffix into the list
456 * 460 *
457 * Results: 461 * Results:
458 * None 462 * None
459 * 463 *
460 * Side Effects: 464 * Side Effects:
461 * The reference count for the suffix is decremented and the 465 * The reference count for the suffix is decremented and the
462 * suffix is possibly freed 466 * suffix is possibly freed
463 *----------------------------------------------------------------------- 467 *-----------------------------------------------------------------------
464 */ 468 */
465static void 469static void
466SuffRemove(Lst l, Suff *s) 470SuffRemove(Lst l, Suff *s)
467{ 471{
468 SuffUnRef(l, s); 472 SuffUnRef(l, s);
469 if (s->refCount == 0) { 473 if (s->refCount == 0) {
470 SuffUnRef(sufflist, s); 474 SuffUnRef(sufflist, s);
471 SuffFree(s); 475 SuffFree(s);
472 } 476 }
473} 477}
474 478
475/*- 479/*-
476 *----------------------------------------------------------------------- 480 *-----------------------------------------------------------------------
477 * SuffInsert -- 481 * SuffInsert --
478 * Insert the suffix into the list keeping the list ordered by suffix 482 * Insert the suffix into the list keeping the list ordered by suffix
479 * numbers. 483 * numbers.
480 * 484 *
481 * Input: 485 * Input:
482 * l the list where in s should be inserted 486 * l the list where in s should be inserted
483 * s the suffix to insert 487 * s the suffix to insert
484 * 488 *
485 * Results: 489 * Results:
486 * None 490 * None
487 * 491 *
488 * Side Effects: 492 * Side Effects:
489 * The reference count of the suffix is incremented 493 * The reference count of the suffix is incremented
490 *----------------------------------------------------------------------- 494 *-----------------------------------------------------------------------
491 */ 495 */
492static void 496static void
493SuffInsert(Lst l, Suff *s) 497SuffInsert(Lst l, Suff *s)
494{ 498{
495 LstNode ln; /* current element in l we're examining */ 499 LstNode ln; /* current element in l we're examining */
496 Suff *s2 = NULL; /* the suffix descriptor in this element */ 500 Suff *s2 = NULL; /* the suffix descriptor in this element */
497 501
498 Lst_OpenS(l); 502 Lst_OpenS(l);
499 while ((ln = Lst_NextS(l)) != NULL) { 503 while ((ln = Lst_NextS(l)) != NULL) {
500 s2 = Lst_DatumS(ln); 504 s2 = Lst_DatumS(ln);
501 if (s2->sNum >= s->sNum) { 505 if (s2->sNum >= s->sNum) {
502 break; 506 break;
503 } 507 }
504 } 508 }
505 Lst_CloseS(l); 509 Lst_CloseS(l);
506 510
507 if (DEBUG(SUFF)) { 511 if (DEBUG(SUFF)) {
508 fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum); 512 fprintf(debug_file, "inserting %s(%d)...", s->name, s->sNum);
509 } 513 }
510 if (ln == NULL) { 514 if (ln == NULL) {
511 if (DEBUG(SUFF)) { 515 if (DEBUG(SUFF)) {
512 fprintf(debug_file, "at end of list\n"); 516 fprintf(debug_file, "at end of list\n");
513 } 517 }
514 Lst_AppendS(l, s); 518 Lst_AppendS(l, s);
515 s->refCount++; 519 s->refCount++;
516 Lst_AppendS(s->ref, l); 520 Lst_AppendS(s->ref, l);
517 } else if (s2->sNum != s->sNum) { 521 } else if (s2->sNum != s->sNum) {
518 if (DEBUG(SUFF)) { 522 if (DEBUG(SUFF)) {
519 fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum); 523 fprintf(debug_file, "before %s(%d)\n", s2->name, s2->sNum);
520 } 524 }
521 Lst_InsertBeforeS(l, ln, s); 525 Lst_InsertBeforeS(l, ln, s);
522 s->refCount++; 526 s->refCount++;
523 Lst_AppendS(s->ref, l); 527 Lst_AppendS(s->ref, l);
524 } else if (DEBUG(SUFF)) { 528 } else if (DEBUG(SUFF)) {
525 fprintf(debug_file, "already there\n"); 529 fprintf(debug_file, "already there\n");
526 } 530 }
527} 531}
528 532
529static Suff * 533static Suff *
530SuffNew(const char *name) 534SuffNew(const char *name)
531{ 535{
532 Suff *s = bmake_malloc(sizeof(Suff)); 536 Suff *s = bmake_malloc(sizeof(Suff));
533 537
534 s->name = bmake_strdup(name); 538 s->name = bmake_strdup(name);
535 s->nameLen = strlen(s->name); 539 s->nameLen = strlen(s->name);
536 s->searchPath = Lst_Init(); 540 s->searchPath = Lst_Init();
537 s->children = Lst_Init(); 541 s->children = Lst_Init();
538 s->parents = Lst_Init(); 542 s->parents = Lst_Init();
539 s->ref = Lst_Init(); 543 s->ref = Lst_Init();
540 s->sNum = sNum++; 544 s->sNum = sNum++;
541 s->flags = 0; 545 s->flags = 0;
542 s->refCount = 1; 546 s->refCount = 1;
543 547
544 return s; 548 return s;
545} 549}
546 550
547/*- 551/*-
548 *----------------------------------------------------------------------- 552 *-----------------------------------------------------------------------
549 * Suff_ClearSuffixes -- 553 * Suff_ClearSuffixes --
550 * This is gross. Nuke the list of suffixes but keep all transformation 554 * This is gross. Nuke the list of suffixes but keep all transformation
551 * rules around. The transformation graph is destroyed in this process, 555 * rules around. The transformation graph is destroyed in this process,
552 * but we leave the list of rules so when a new graph is formed the rules 556 * but we leave the list of rules so when a new graph is formed the rules
553 * will remain. 557 * will remain.
554 * This function is called from the parse module when a 558 * This function is called from the parse module when a
555 * .SUFFIXES:\n line is encountered. 559 * .SUFFIXES:\n line is encountered.
556 * 560 *
557 * Results: 561 * Results:
558 * none 562 * none
559 * 563 *
560 * Side Effects: 564 * Side Effects:
561 * the sufflist and its graph nodes are destroyed 565 * the sufflist and its graph nodes are destroyed
562 *----------------------------------------------------------------------- 566 *-----------------------------------------------------------------------
563 */ 567 */
564void 568void
565Suff_ClearSuffixes(void) 569Suff_ClearSuffixes(void)
566{ 570{
567#ifdef CLEANUP 571#ifdef CLEANUP
568 Lst_MoveAllS(suffClean, sufflist); 572 Lst_MoveAllS(suffClean, sufflist);
569#endif 573#endif
570 sufflist = Lst_Init(); 574 sufflist = Lst_Init();
571 sNum = 0; 575 sNum = 0;
572 if (suffNull) 576 if (suffNull)
573 SuffFree(suffNull); 577 SuffFree(suffNull);
574 emptySuff = suffNull = SuffNew(""); 578 emptySuff = suffNull = SuffNew("");
575 579
576 Dir_Concat(suffNull->searchPath, dirSearchPath); 580 Dir_Concat(suffNull->searchPath, dirSearchPath);
577 suffNull->flags = SUFF_NULL; 581 suffNull->flags = SUFF_NULL;
578} 582}
579 583
580/*- 584/*-
581 *----------------------------------------------------------------------- 585 *-----------------------------------------------------------------------
582 * SuffParseTransform -- 586 * SuffParseTransform --
583 * Parse a transformation string to find its two component suffixes. 587 * Parse a transformation string to find its two component suffixes.
584 * 588 *
585 * Input: 589 * Input:
586 * str String being parsed 590 * str String being parsed
587 * srcPtr Place to store source of trans. 591 * srcPtr Place to store source of trans.
588 * targPtr Place to store target of trans. 592 * targPtr Place to store target of trans.
589 * 593 *
590 * Results: 594 * Results:
591 * TRUE if the string is a valid transformation and FALSE otherwise. 595 * TRUE if the string is a valid transformation and FALSE otherwise.
592 * 596 *
593 * Side Effects: 597 * Side Effects:
594 * The passed pointers are overwritten. 598 * The passed pointers are overwritten.
595 * 599 *
596 *----------------------------------------------------------------------- 600 *-----------------------------------------------------------------------
597 */ 601 */
598static Boolean 602static Boolean
599SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr) 603SuffParseTransform(char *str, Suff **srcPtr, Suff **targPtr)
600{ 604{
601 LstNode srcLn; /* element in suffix list of trans source*/ 605 LstNode srcLn; /* element in suffix list of trans source*/
602 Suff *src; /* Source of transformation */ 606 Suff *src; /* Source of transformation */
603 LstNode targLn; /* element in suffix list of trans target*/ 607 LstNode targLn; /* element in suffix list of trans target*/
604 char *str2; /* Extra pointer (maybe target suffix) */ 608 char *str2; /* Extra pointer (maybe target suffix) */
605 LstNode singleLn; /* element in suffix list of any suffix 609 LstNode singleLn; /* element in suffix list of any suffix
606 * that exactly matches str */ 610 * that exactly matches str */
607 Suff *single = NULL;/* Source of possible transformation to 611 Suff *single = NULL;/* Source of possible transformation to
608 * null suffix */ 612 * null suffix */
609 613
610 srcLn = NULL; 614 srcLn = NULL;
611 singleLn = NULL; 615 singleLn = NULL;
612 616
613 /* 617 /*
614 * Loop looking first for a suffix that matches the start of the 618 * Loop looking first for a suffix that matches the start of the
615 * string and then for one that exactly matches the rest of it. If 619 * string and then for one that exactly matches the rest of it. If
616 * we can find two that meet these criteria, we've successfully 620 * we can find two that meet these criteria, we've successfully
617 * parsed the string. 621 * parsed the string.
618 */ 622 */
619 for (;;) { 623 for (;;) {
620 if (srcLn == NULL) { 624 if (srcLn == NULL) {
621 srcLn = Lst_FindS(sufflist, SuffSuffIsPrefix, str); 625 srcLn = Lst_FindS(sufflist, SuffSuffIsPrefix, str);
622 } else { 626 } else {
623 srcLn = Lst_FindFrom(sufflist, Lst_SuccS(srcLn), 627 srcLn = Lst_FindFrom(sufflist, Lst_SuccS(srcLn),
624 SuffSuffIsPrefix, str); 628 SuffSuffIsPrefix, str);
625 } 629 }
626 if (srcLn == NULL) { 630 if (srcLn == NULL) {
627 /* 631 /*
628 * Ran out of source suffixes -- no such rule 632 * Ran out of source suffixes -- no such rule
629 */ 633 */
630 if (singleLn != NULL) { 634 if (singleLn != NULL) {
631 /* 635 /*
632 * Not so fast Mr. Smith! There was a suffix that encompassed 636 * Not so fast Mr. Smith! There was a suffix that encompassed
633 * the entire string, so we assume it was a transformation 637 * the entire string, so we assume it was a transformation
634 * to the null suffix (thank you POSIX). We still prefer to 638 * to the null suffix (thank you POSIX). We still prefer to
635 * find a double rule over a singleton, hence we leave this 639 * find a double rule over a singleton, hence we leave this
636 * check until the end. 640 * check until the end.
637 * 641 *
638 * XXX: Use emptySuff over suffNull? 642 * XXX: Use emptySuff over suffNull?
639 */ 643 */
640 *srcPtr = single; 644 *srcPtr = single;
641 *targPtr = suffNull; 645 *targPtr = suffNull;
642 return TRUE; 646 return TRUE;
643 } 647 }
644 return FALSE; 648 return FALSE;
645 } 649 }
646 src = Lst_DatumS(srcLn); 650 src = Lst_DatumS(srcLn);
647 str2 = str + src->nameLen; 651 str2 = str + src->nameLen;
648 if (*str2 == '\0') { 652 if (*str2 == '\0') {
649 single = src; 653 single = src;
650 singleLn = srcLn; 654 singleLn = srcLn;
651 } else { 655 } else {
652 targLn = Lst_FindS(sufflist, SuffSuffHasNameP, str2); 656 targLn = Lst_FindS(sufflist, SuffSuffHasNameP, str2);
653 if (targLn != NULL) { 657 if (targLn != NULL) {
654 *srcPtr = src; 658 *srcPtr = src;
655 *targPtr = Lst_DatumS(targLn); 659 *targPtr = Lst_DatumS(targLn);
656 return TRUE; 660 return TRUE;
657 } 661 }
658 } 662 }
659 } 663 }
660} 664}
661 665
662/*- 666/*-
663 *----------------------------------------------------------------------- 667 *-----------------------------------------------------------------------
664 * Suff_IsTransform -- 668 * Suff_IsTransform --
665 * Return TRUE if the given string is a transformation rule 669 * Return TRUE if the given string is a transformation rule
666 * 670 *
667 * 671 *
668 * Input: 672 * Input:
669 * str string to check 673 * str string to check
670 * 674 *
671 * Results: 675 * Results:
672 * TRUE if the string is a concatenation of two known suffixes. 676 * TRUE if the string is a concatenation of two known suffixes.
673 * FALSE otherwise 677 * FALSE otherwise
674 * 678 *
675 * Side Effects: 679 * Side Effects:
676 * None 680 * None
677 *----------------------------------------------------------------------- 681 *-----------------------------------------------------------------------
678 */ 682 */
679Boolean 683Boolean
680Suff_IsTransform(char *str) 684Suff_IsTransform(char *str)
681{ 685{
682 Suff *src, *targ; 686 Suff *src, *targ;
683 687
684 return SuffParseTransform(str, &src, &targ); 688 return SuffParseTransform(str, &src, &targ);
685} 689}
686 690
687/*- 691/*-
688 *----------------------------------------------------------------------- 692 *-----------------------------------------------------------------------
689 * Suff_AddTransform -- 693 * Suff_AddTransform --
690 * Add the transformation rule described by the line to the 694 * Add the transformation rule described by the line to the
691 * list of rules and place the transformation itself in the graph 695 * list of rules and place the transformation itself in the graph
692 * 696 *
693 * Input: 697 * Input:
694 * line name of transformation to add 698 * line name of transformation to add
695 * 699 *
696 * Results: 700 * Results:
697 * The node created for the transformation in the transforms list 701 * The node created for the transformation in the transforms list
698 * 702 *
699 * Side Effects: 703 * Side Effects:
700 * The node is placed on the end of the transforms Lst and links are 704 * The node is placed on the end of the transforms Lst and links are
701 * made between the two suffixes mentioned in the target name 705 * made between the two suffixes mentioned in the target name
702 *----------------------------------------------------------------------- 706 *-----------------------------------------------------------------------
703 */ 707 */
704GNode * 708GNode *
705Suff_AddTransform(char *line) 709Suff_AddTransform(char *line)
706{ 710{
707 GNode *gn; /* GNode of transformation rule */ 711 GNode *gn; /* GNode of transformation rule */
708 Suff *s, /* source suffix */ 712 Suff *s, /* source suffix */
709 *t; /* target suffix */ 713 *t; /* target suffix */
710 LstNode ln; /* Node for existing transformation */ 714 LstNode ln; /* Node for existing transformation */
711 715
712 ln = Lst_Find(transforms, SuffGNHasNameP, line); 716 ln = Lst_Find(transforms, SuffGNHasNameP, line);
713 if (ln == NULL) { 717 if (ln == NULL) {
714 /* 718 /*
715 * Make a new graph node for the transformation. It will be filled in 719 * Make a new graph node for the transformation. It will be filled in
716 * by the Parse module. 720 * by the Parse module.
717 */ 721 */
718 gn = Targ_NewGN(line); 722 gn = Targ_NewGN(line);
719 Lst_AppendS(transforms, gn); 723 Lst_AppendS(transforms, gn);
720 } else { 724 } else {
721 /* 725 /*
722 * New specification for transformation rule. Just nuke the old list 726 * New specification for transformation rule. Just nuke the old list
723 * of commands so they can be filled in again... We don't actually 727 * of commands so they can be filled in again... We don't actually
724 * free the commands themselves, because a given command can be 728 * free the commands themselves, because a given command can be
725 * attached to several different transformations. 729 * attached to several different transformations.
726 */ 730 */
727 gn = Lst_DatumS(ln); 731 gn = Lst_DatumS(ln);
728 Lst_FreeS(gn->commands); 732 Lst_FreeS(gn->commands);
729 Lst_FreeS(gn->children); 733 Lst_FreeS(gn->children);
730 gn->commands = Lst_Init(); 734 gn->commands = Lst_Init();
731 gn->children = Lst_Init(); 735 gn->children = Lst_Init();
732 } 736 }
733 737
734 gn->type = OP_TRANSFORM; 738 gn->type = OP_TRANSFORM;
735 739
736 (void)SuffParseTransform(line, &s, &t); 740 (void)SuffParseTransform(line, &s, &t);
737 741
738 /* 742 /*
739 * link the two together in the proper relationship and order 743 * link the two together in the proper relationship and order
740 */ 744 */
741 if (DEBUG(SUFF)) { 745 if (DEBUG(SUFF)) {
742 fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 746 fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
743 s->name, t->name); 747 s->name, t->name);
744 } 748 }
745 SuffInsert(t->children, s); 749 SuffInsert(t->children, s);
746 SuffInsert(s->parents, t); 750 SuffInsert(s->parents, t);
747 751
748 return gn; 752 return gn;
749} 753}
750 754
751/*- 755/*-
752 *----------------------------------------------------------------------- 756 *-----------------------------------------------------------------------
753 * Suff_EndTransform -- 757 * Suff_EndTransform --
754 * Handle the finish of a transformation definition, removing the 758 * Handle the finish of a transformation definition, removing the
755 * transformation from the graph if it has neither commands nor 759 * transformation from the graph if it has neither commands nor
756 * sources. This is a callback procedure for the Parse module via 760 * sources. This is a callback procedure for the Parse module via
757 * Lst_ForEach 761 * Lst_ForEach
758 * 762 *
759 * Input: 763 * Input:
760 * gnp Node for transformation 764 * gnp Node for transformation
761 * dummy Node for transformation 765 * dummy Node for transformation
762 * 766 *
763 * Results: 767 * Results:
764 * === 0 768 * === 0
765 * 769 *
766 * Side Effects: 770 * Side Effects:
767 * If the node has no commands or children, the children and parents 771 * If the node has no commands or children, the children and parents
768 * lists of the affected suffixes are altered. 772 * lists of the affected suffixes are altered.
769 * 773 *
770 *----------------------------------------------------------------------- 774 *-----------------------------------------------------------------------
771 */ 775 */
772int 776int
773Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED) 777Suff_EndTransform(void *gnp, void *dummy MAKE_ATTR_UNUSED)
774{ 778{
775 GNode *gn = (GNode *)gnp; 779 GNode *gn = (GNode *)gnp;
776 780
777 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmptyS(gn->cohorts)) 781 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmptyS(gn->cohorts))
778 gn = Lst_DatumS(Lst_LastS(gn->cohorts)); 782 gn = Lst_DatumS(Lst_LastS(gn->cohorts));
779 if ((gn->type & OP_TRANSFORM) && Lst_IsEmptyS(gn->commands) && 783 if ((gn->type & OP_TRANSFORM) && Lst_IsEmptyS(gn->commands) &&
780 Lst_IsEmptyS(gn->children)) 784 Lst_IsEmptyS(gn->children))
781 { 785 {
782 Suff *s, *t; 786 Suff *s, *t;
783 787
784 /* 788 /*
785 * SuffParseTransform() may fail for special rules which are not 789 * SuffParseTransform() may fail for special rules which are not
786 * actual transformation rules. (e.g. .DEFAULT) 790 * actual transformation rules. (e.g. .DEFAULT)
787 */ 791 */
788 if (SuffParseTransform(gn->name, &s, &t)) { 792 if (SuffParseTransform(gn->name, &s, &t)) {
789 Lst p; 793 Lst p;
790 794
791 if (DEBUG(SUFF)) { 795 if (DEBUG(SUFF)) {
792 fprintf(debug_file, "deleting transformation from `%s' to `%s'\n", 796 fprintf(debug_file, "deleting transformation from `%s' to `%s'\n",
793 s->name, t->name); 797 s->name, t->name);
794 } 798 }
795 799
796 /* 800 /*
797 * Store s->parents because s could be deleted in SuffRemove 801 * Store s->parents because s could be deleted in SuffRemove
798 */ 802 */
799 p = s->parents; 803 p = s->parents;
800 804
801 /* 805 /*
802 * Remove the source from the target's children list. We check for a 806 * Remove the source from the target's children list. We check for a
803 * nil return to handle a beanhead saying something like 807 * nil return to handle a beanhead saying something like
804 * .c.o .c.o: 808 * .c.o .c.o:
805 * 809 *
806 * We'll be called twice when the next target is seen, but .c and .o 810 * We'll be called twice when the next target is seen, but .c and .o
807 * are only linked once... 811 * are only linked once...
808 */ 812 */
809 SuffRemove(t->children, s); 813 SuffRemove(t->children, s);
810 814
811 /* 815 /*
812 * Remove the target from the source's parents list 816 * Remove the target from the source's parents list
813 */ 817 */
814 SuffRemove(p, t); 818 SuffRemove(p, t);
815 } 819 }
816 } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) { 820 } else if ((gn->type & OP_TRANSFORM) && DEBUG(SUFF)) {
817 fprintf(debug_file, "transformation %s complete\n", gn->name); 821 fprintf(debug_file, "transformation %s complete\n", gn->name);
818 } 822 }
819 823
820 return 0; 824 return 0;
821} 825}
822 826
823/*- 827/*-
824 *----------------------------------------------------------------------- 828 *-----------------------------------------------------------------------
825 * SuffRebuildGraph -- 829 * SuffRebuildGraph --
826 * Called from Suff_AddSuffix via Lst_ForEach to search through the 830 * Called from Suff_AddSuffix via Lst_ForEach to search through the
827 * list of existing transformation rules and rebuild the transformation 831 * list of existing transformation rules and rebuild the transformation
828 * graph when it has been destroyed by Suff_ClearSuffixes. If the 832 * graph when it has been destroyed by Suff_ClearSuffixes. If the
829 * given rule is a transformation involving this suffix and another, 833 * given rule is a transformation involving this suffix and another,
830 * existing suffix, the proper relationship is established between 834 * existing suffix, the proper relationship is established between
831 * the two. 835 * the two.
832 * 836 *
833 * Input: 837 * Input:
834 * transformp Transformation to test 838 * transformp Transformation to test
835 * sp Suffix to rebuild 839 * sp Suffix to rebuild
836 * 840 *
837 * Results: 841 * Results:
838 * Always 0. 842 * Always 0.
839 * 843 *
840 * Side Effects: 844 * Side Effects:
841 * The appropriate links will be made between this suffix and 845 * The appropriate links will be made between this suffix and
842 * others if transformation rules exist for it. 846 * others if transformation rules exist for it.
843 * 847 *
844 *----------------------------------------------------------------------- 848 *-----------------------------------------------------------------------
845 */ 849 */
846static int 850static int
847SuffRebuildGraph(void *transformp, void *sp) 851SuffRebuildGraph(void *transformp, void *sp)
848{ 852{
849 GNode *transform = (GNode *)transformp; 853 GNode *transform = (GNode *)transformp;
850 Suff *s = (Suff *)sp; 854 Suff *s = (Suff *)sp;
851 char *cp; 855 char *cp;
852 LstNode ln; 856 LstNode ln;
853 Suff *s2; 857 Suff *s2;
854 SuffixCmpData sd; 858 SuffixCmpData sd;
855 859
856 /* 860 /*
857 * First see if it is a transformation from this suffix. 861 * First see if it is a transformation from this suffix.
858 */ 862 */
859 cp = UNCONST(SuffStrIsPrefix(s->name, transform->name)); 863 cp = UNCONST(SuffStrIsPrefix(s->name, transform->name));
860 if (cp != NULL) { 864 if (cp != NULL) {
861 ln = Lst_FindS(sufflist, SuffSuffHasNameP, cp); 865 ln = Lst_FindS(sufflist, SuffSuffHasNameP, cp);
862 if (ln != NULL) { 866 if (ln != NULL) {
863 /* 867 /*
864 * Found target. Link in and return, since it can't be anything 868 * Found target. Link in and return, since it can't be anything
865 * else. 869 * else.
866 */ 870 */
867 s2 = Lst_DatumS(ln); 871 s2 = Lst_DatumS(ln);
868 SuffInsert(s2->children, s); 872 SuffInsert(s2->children, s);
869 SuffInsert(s->parents, s2); 873 SuffInsert(s->parents, s2);
870 return 0; 874 return 0;
871 } 875 }
872 } 876 }
873 877
874 /* 878 /*
875 * Not from, maybe to? 879 * Not from, maybe to?
876 */ 880 */
877 sd.len = strlen(transform->name); 881 sd.len = strlen(transform->name);
878 sd.ename = transform->name + sd.len; 882 sd.ename = transform->name + sd.len;
879 cp = SuffSuffIsSuffix(s, &sd); 883 cp = SuffSuffIsSuffix(s, &sd);
880 if (cp != NULL) { 884 if (cp != NULL) {
881 /* 885 /*
882 * Null-terminate the source suffix in order to find it. 886 * Null-terminate the source suffix in order to find it.
883 */ 887 */
884 cp[1] = '\0'; 888 cp[1] = '\0';
885 ln = Lst_FindS(sufflist, SuffSuffHasNameP, transform->name); 889 ln = Lst_FindS(sufflist, SuffSuffHasNameP, transform->name);
886 /* 890 /*
887 * Replace the start of the target suffix 891 * Replace the start of the target suffix
888 */ 892 */
889 cp[1] = s->name[0]; 893 cp[1] = s->name[0];
890 if (ln != NULL) { 894 if (ln != NULL) {
891 /* 895 /*
892 * Found it -- establish the proper relationship 896 * Found it -- establish the proper relationship
893 */ 897 */
894 s2 = Lst_DatumS(ln); 898 s2 = Lst_DatumS(ln);
895 SuffInsert(s->children, s2); 899 SuffInsert(s->children, s2);
896 SuffInsert(s2->parents, s); 900 SuffInsert(s2->parents, s);
897 } 901 }
898 } 902 }
899 return 0; 903 return 0;
900} 904}
901 905
902/*- 906/*-
903 *----------------------------------------------------------------------- 907 *-----------------------------------------------------------------------
904 * SuffScanTargets -- 908 * SuffScanTargets --
905 * Called from Suff_AddSuffix via Lst_ForEach to search through the 909 * Called from Suff_AddSuffix via Lst_ForEach to search through the
906 * list of existing targets and find if any of the existing targets 910 * list of existing targets and find if any of the existing targets
907 * can be turned into a transformation rule. 911 * can be turned into a transformation rule.
908 * 912 *
909 * Results: 913 * Results:
910 * 1 if a new main target has been selected, 0 otherwise. 914 * 1 if a new main target has been selected, 0 otherwise.
911 * 915 *
912 * Side Effects: 916 * Side Effects:
913 * If such a target is found and the target is the current main 917 * If such a target is found and the target is the current main
914 * target, the main target is set to NULL and the next target 918 * target, the main target is set to NULL and the next target
915 * examined (if that exists) becomes the main target. 919 * examined (if that exists) becomes the main target.
916 * 920 *
917 *----------------------------------------------------------------------- 921 *-----------------------------------------------------------------------
918 */ 922 */
919static int 923static int
920SuffScanTargets(void *targetp, void *gsp) 924SuffScanTargets(void *targetp, void *gsp)
921{ 925{
922 GNode *target = (GNode *)targetp; 926 GNode *target = (GNode *)targetp;
923 GNodeSuff *gs = (GNodeSuff *)gsp; 927 GNodeSuff *gs = (GNodeSuff *)gsp;
924 Suff *s, *t; 928 Suff *s, *t;
925 char *ptr; 929 char *ptr;
926 930
927 if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) { 931 if (*gs->gn == NULL && gs->r && (target->type & OP_NOTARGET) == 0) {
928 *gs->gn = target; 932 *gs->gn = target;
929 Targ_SetMain(target); 933 Targ_SetMain(target);
930 return 1; 934 return 1;
931 } 935 }
932 936
933 if (target->type == OP_TRANSFORM) 937 if (target->type == OP_TRANSFORM)
934 return 0; 938 return 0;
935 939
936 if ((ptr = strstr(target->name, gs->s->name)) == NULL || 940 if ((ptr = strstr(target->name, gs->s->name)) == NULL ||
937 ptr == target->name) 941 ptr == target->name)
938 return 0; 942 return 0;
939 943
940 if (SuffParseTransform(target->name, &s, &t)) { 944 if (SuffParseTransform(target->name, &s, &t)) {
941 if (*gs->gn == target) { 945 if (*gs->gn == target) {
942 gs->r = TRUE; 946 gs->r = TRUE;
943 *gs->gn = NULL; 947 *gs->gn = NULL;
944 Targ_SetMain(NULL); 948 Targ_SetMain(NULL);
945 } 949 }
946 Lst_FreeS(target->children); 950 Lst_FreeS(target->children);
947 target->children = Lst_Init(); 951 target->children = Lst_Init();
948 target->type = OP_TRANSFORM; 952 target->type = OP_TRANSFORM;
949 /* 953 /*
950 * link the two together in the proper relationship and order 954 * link the two together in the proper relationship and order
951 */ 955 */
952 if (DEBUG(SUFF)) { 956 if (DEBUG(SUFF)) {
953 fprintf(debug_file, "defining transformation from `%s' to `%s'\n", 957 fprintf(debug_file, "defining transformation from `%s' to `%s'\n",
954 s->name, t->name); 958 s->name, t->name);
955 } 959 }
956 SuffInsert(t->children, s); 960 SuffInsert(t->children, s);
957 SuffInsert(s->parents, t); 961 SuffInsert(s->parents, t);
958 } 962 }
959 return 0; 963 return 0;
960} 964}
961 965
962/*- 966/*-
963 *----------------------------------------------------------------------- 967 *-----------------------------------------------------------------------
964 * Suff_AddSuffix -- 968 * Suff_AddSuffix --
965 * Add the suffix in string to the end of the list of known suffixes. 969 * Add the suffix in string to the end of the list of known suffixes.
966 * Should we restructure the suffix graph? Make doesn't... 970 * Should we restructure the suffix graph? Make doesn't...
967 * 971 *
968 * Input: 972 * Input:
969 * str the name of the suffix to add 973 * str the name of the suffix to add
970 * 974 *
971 * Results: 975 * Results:
972 * None 976 * None
973 * 977 *
974 * Side Effects: 978 * Side Effects:
975 * A GNode is created for the suffix and a Suff structure is created and 979 * A GNode is created for the suffix and a Suff structure is created and
976 * added to the suffixes list unless the suffix was already known. 980 * added to the suffixes list unless the suffix was already known.
977 * The mainNode passed can be modified if a target mutated into a 981 * The mainNode passed can be modified if a target mutated into a
978 * transform and that target happened to be the main target. 982 * transform and that target happened to be the main target.
979 *----------------------------------------------------------------------- 983 *-----------------------------------------------------------------------
980 */ 984 */
981void 985void
982Suff_AddSuffix(char *str, GNode **gn) 986Suff_AddSuffix(char *str, GNode **gn)
983{ 987{
984 Suff *s; /* new suffix descriptor */ 988 Suff *s; /* new suffix descriptor */
985 LstNode ln; 989 LstNode ln;
986 GNodeSuff gs; 990 GNodeSuff gs;
987 991
988 ln = Lst_FindS(sufflist, SuffSuffHasNameP, str); 992 ln = Lst_FindS(sufflist, SuffSuffHasNameP, str);
989 if (ln == NULL) { 993 if (ln == NULL) {
990 s = SuffNew(str); 994 s = SuffNew(str);
991 995
992 Lst_AppendS(sufflist, s); 996 Lst_AppendS(sufflist, s);
993 /* 997 /*
994 * We also look at our existing targets list to see if adding 998 * We also look at our existing targets list to see if adding
995 * this suffix will make one of our current targets mutate into 999 * this suffix will make one of our current targets mutate into
996 * a suffix rule. This is ugly, but other makes treat all targets 1000 * a suffix rule. This is ugly, but other makes treat all targets
997 * that start with a . as suffix rules. 1001 * that start with a . as suffix rules.
998 */ 1002 */
999 gs.gn = gn; 1003 gs.gn = gn;
1000 gs.s = s; 1004 gs.s = s;
1001 gs.r = FALSE; 1005 gs.r = FALSE;
1002 Lst_ForEachS(Targ_List(), SuffScanTargets, &gs); 1006 Lst_ForEachS(Targ_List(), SuffScanTargets, &gs);
1003 /* 1007 /*
1004 * Look for any existing transformations from or to this suffix. 1008 * Look for any existing transformations from or to this suffix.
1005 * XXX: Only do this after a Suff_ClearSuffixes? 1009 * XXX: Only do this after a Suff_ClearSuffixes?
1006 */ 1010 */
1007 Lst_ForEachS(transforms, SuffRebuildGraph, s); 1011 Lst_ForEachS(transforms, SuffRebuildGraph, s);
1008 } 1012 }
1009} 1013}
1010 1014
1011/*- 1015/*-
1012 *----------------------------------------------------------------------- 1016 *-----------------------------------------------------------------------
1013 * Suff_GetPath -- 1017 * Suff_GetPath --
1014 * Return the search path for the given suffix, if it's defined. 1018 * Return the search path for the given suffix, if it's defined.
1015 * 1019 *
1016 * Results: 1020 * Results:
1017 * The searchPath for the desired suffix or NULL if the suffix isn't 1021 * The searchPath for the desired suffix or NULL if the suffix isn't
1018 * defined. 1022 * defined.
1019 * 1023 *
1020 * Side Effects: 1024 * Side Effects:
1021 * None 1025 * None
1022 *----------------------------------------------------------------------- 1026 *-----------------------------------------------------------------------
1023 */ 1027 */
1024Lst 1028Lst
1025Suff_GetPath(char *sname) 1029Suff_GetPath(char *sname)
1026{ 1030{
1027 LstNode ln; 1031 LstNode ln;
1028 Suff *s; 1032 Suff *s;
1029 1033
1030 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname); 1034 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname);
1031 if (ln == NULL) { 1035 if (ln == NULL) {
1032 return NULL; 1036 return NULL;
1033 } else { 1037 } else {
1034 s = Lst_DatumS(ln); 1038 s = Lst_DatumS(ln);
1035 return s->searchPath; 1039 return s->searchPath;
1036 } 1040 }
1037} 1041}
1038 1042
1039/*- 1043/*-
1040 *----------------------------------------------------------------------- 1044 *-----------------------------------------------------------------------
1041 * Suff_DoPaths -- 1045 * Suff_DoPaths --
1042 * Extend the search paths for all suffixes to include the default 1046 * Extend the search paths for all suffixes to include the default
1043 * search path. 1047 * search path.
1044 * 1048 *
1045 * Results: 1049 * Results:
1046 * None. 1050 * None.
1047 * 1051 *
1048 * Side Effects: 1052 * Side Effects:
1049 * The searchPath field of all the suffixes is extended by the 1053 * The searchPath field of all the suffixes is extended by the
1050 * directories in dirSearchPath. If paths were specified for the 1054 * directories in dirSearchPath. If paths were specified for the
1051 * ".h" suffix, the directories are stuffed into a global variable 1055 * ".h" suffix, the directories are stuffed into a global variable
1052 * called ".INCLUDES" with each directory preceded by a -I. The same 1056 * called ".INCLUDES" with each directory preceded by a -I. The same
1053 * is done for the ".a" suffix, except the variable is called 1057 * is done for the ".a" suffix, except the variable is called
1054 * ".LIBS" and the flag is -L. 1058 * ".LIBS" and the flag is -L.
1055 *----------------------------------------------------------------------- 1059 *-----------------------------------------------------------------------
1056 */ 1060 */
1057void 1061void
1058Suff_DoPaths(void) 1062Suff_DoPaths(void)
1059{ 1063{
1060 Suff *s; 1064 Suff *s;
1061 LstNode ln; 1065 LstNode ln;
1062 char *ptr; 1066 char *ptr;
1063 Lst inIncludes; /* Cumulative .INCLUDES path */ 1067 Lst inIncludes; /* Cumulative .INCLUDES path */
1064 Lst inLibs; /* Cumulative .LIBS path */ 1068 Lst inLibs; /* Cumulative .LIBS path */
1065 1069
1066 1070
1067 inIncludes = Lst_Init(); 1071 inIncludes = Lst_Init();
1068 inLibs = Lst_Init(); 1072 inLibs = Lst_Init();
1069 1073
1070 Lst_OpenS(sufflist); 1074 Lst_OpenS(sufflist);
1071 while ((ln = Lst_NextS(sufflist)) != NULL) { 1075 while ((ln = Lst_NextS(sufflist)) != NULL) {
1072 s = Lst_DatumS(ln); 1076 s = Lst_DatumS(ln);
1073 if (!Lst_IsEmptyS(s->searchPath)) { 1077 if (!Lst_IsEmptyS(s->searchPath)) {
1074#ifdef INCLUDES 1078#ifdef INCLUDES
1075 if (s->flags & SUFF_INCLUDE) { 1079 if (s->flags & SUFF_INCLUDE) {
1076 Dir_Concat(inIncludes, s->searchPath); 1080 Dir_Concat(inIncludes, s->searchPath);
1077 } 1081 }
1078#endif /* INCLUDES */ 1082#endif /* INCLUDES */
1079#ifdef LIBRARIES 1083#ifdef LIBRARIES
1080 if (s->flags & SUFF_LIBRARY) { 1084 if (s->flags & SUFF_LIBRARY) {
1081 Dir_Concat(inLibs, s->searchPath); 1085 Dir_Concat(inLibs, s->searchPath);
1082 } 1086 }
1083#endif /* LIBRARIES */ 1087#endif /* LIBRARIES */
1084 Dir_Concat(s->searchPath, dirSearchPath); 1088 Dir_Concat(s->searchPath, dirSearchPath);
1085 } else { 1089 } else {
1086 Lst_DestroyS(s->searchPath, Dir_Destroy); 1090 Lst_DestroyS(s->searchPath, Dir_Destroy);
1087 s->searchPath = Lst_CopyS(dirSearchPath, Dir_CopyDir); 1091 s->searchPath = Lst_CopyS(dirSearchPath, Dir_CopyDir);
1088 } 1092 }
1089 } 1093 }
1090 Lst_CloseS(sufflist); 1094 Lst_CloseS(sufflist);
1091 1095
1092 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL); 1096 Var_Set(".INCLUDES", ptr = Dir_MakeFlags("-I", inIncludes), VAR_GLOBAL);
1093 free(ptr); 1097 free(ptr);
1094 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL); 1098 Var_Set(".LIBS", ptr = Dir_MakeFlags("-L", inLibs), VAR_GLOBAL);
1095 free(ptr); 1099 free(ptr);
1096 1100
1097 Lst_DestroyS(inIncludes, Dir_Destroy); 1101 Lst_DestroyS(inIncludes, Dir_Destroy);
1098 Lst_DestroyS(inLibs, Dir_Destroy); 1102 Lst_DestroyS(inLibs, Dir_Destroy);
1099} 1103}
1100 1104
1101/*- 1105/*-
1102 *----------------------------------------------------------------------- 1106 *-----------------------------------------------------------------------
1103 * Suff_AddInclude -- 1107 * Suff_AddInclude --
1104 * Add the given suffix as a type of file which gets included. 1108 * Add the given suffix as a type of file which gets included.
1105 * Called from the parse module when a .INCLUDES line is parsed. 1109 * Called from the parse module when a .INCLUDES line is parsed.
1106 * The suffix must have already been defined. 1110 * The suffix must have already been defined.
1107 * 1111 *
1108 * Input: 1112 * Input:
1109 * sname Name of the suffix to mark 1113 * sname Name of the suffix to mark
1110 * 1114 *
1111 * Results: 1115 * Results:
1112 * None. 1116 * None.
1113 * 1117 *
1114 * Side Effects: 1118 * Side Effects:
1115 * The SUFF_INCLUDE bit is set in the suffix's flags field 1119 * The SUFF_INCLUDE bit is set in the suffix's flags field
1116 * 1120 *
1117 *----------------------------------------------------------------------- 1121 *-----------------------------------------------------------------------
1118 */ 1122 */
1119void 1123void
1120Suff_AddInclude(char *sname) 1124Suff_AddInclude(char *sname)
1121{ 1125{
1122 LstNode ln; 1126 LstNode ln;
1123 Suff *s; 1127 Suff *s;
1124 1128
1125 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname); 1129 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname);
1126 if (ln != NULL) { 1130 if (ln != NULL) {
1127 s = Lst_DatumS(ln); 1131 s = Lst_DatumS(ln);
1128 s->flags |= SUFF_INCLUDE; 1132 s->flags |= SUFF_INCLUDE;
1129 } 1133 }
1130} 1134}
1131 1135
1132/*- 1136/*-
1133 *----------------------------------------------------------------------- 1137 *-----------------------------------------------------------------------
1134 * Suff_AddLib -- 1138 * Suff_AddLib --
1135 * Add the given suffix as a type of file which is a library. 1139 * Add the given suffix as a type of file which is a library.
1136 * Called from the parse module when parsing a .LIBS line. The 1140 * Called from the parse module when parsing a .LIBS line. The
1137 * suffix must have been defined via .SUFFIXES before this is 1141 * suffix must have been defined via .SUFFIXES before this is
1138 * called. 1142 * called.
1139 * 1143 *
1140 * Input: 1144 * Input:
1141 * sname Name of the suffix to mark 1145 * sname Name of the suffix to mark
1142 * 1146 *
1143 * Results: 1147 * Results:
1144 * None. 1148 * None.
1145 * 1149 *
1146 * Side Effects: 1150 * Side Effects:
1147 * The SUFF_LIBRARY bit is set in the suffix's flags field 1151 * The SUFF_LIBRARY bit is set in the suffix's flags field
1148 * 1152 *
1149 *----------------------------------------------------------------------- 1153 *-----------------------------------------------------------------------
1150 */ 1154 */
1151void 1155void
1152Suff_AddLib(char *sname) 1156Suff_AddLib(char *sname)
1153{ 1157{
1154 LstNode ln; 1158 LstNode ln;
1155 Suff *s; 1159 Suff *s;
1156 1160
1157 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname); 1161 ln = Lst_FindS(sufflist, SuffSuffHasNameP, sname);
1158 if (ln != NULL) { 1162 if (ln != NULL) {
1159 s = Lst_DatumS(ln); 1163 s = Lst_DatumS(ln);
1160 s->flags |= SUFF_LIBRARY; 1164 s->flags |= SUFF_LIBRARY;
@@ -1606,1059 +1610,1044 @@ SuffExpandChildren(LstNode cln, GNode *p @@ -1606,1059 +1610,1044 @@ SuffExpandChildren(LstNode cln, GNode *p
1606 void *freeIt; 1610 void *freeIt;
1607 1611
1608 junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES, 1612 junk = Var_Parse(cp, pgn, VARE_UNDEFERR|VARE_WANTRES,
1609 &len, &freeIt); 1613 &len, &freeIt);
1610 if (junk != var_Error) { 1614 if (junk != var_Error) {
1611 cp += len - 1; 1615 cp += len - 1;
1612 } 1616 }
1613 1617
1614 free(freeIt); 1618 free(freeIt);
1615 } else if (*cp == '\\' && cp[1] != '\0') { 1619 } else if (*cp == '\\' && cp[1] != '\0') {
1616 /* 1620 /*
1617 * Escaped something -- skip over it 1621 * Escaped something -- skip over it
1618 */ 1622 */
1619 cp++; 1623 cp++;
1620 } 1624 }
1621 } 1625 }
1622 1626
1623 if (cp != start) { 1627 if (cp != start) {
1624 /* 1628 /*
1625 * Stuff left over -- add it to the list too 1629 * Stuff left over -- add it to the list too
1626 */ 1630 */
1627 gn = Targ_FindNode(start, TARG_CREATE); 1631 gn = Targ_FindNode(start, TARG_CREATE);
1628 Lst_AppendS(members, gn); 1632 Lst_AppendS(members, gn);
1629 } 1633 }
1630 /* 1634 /*
1631 * Point cp back at the beginning again so the variable value 1635 * Point cp back at the beginning again so the variable value
1632 * can be freed. 1636 * can be freed.
1633 */ 1637 */
1634 cp = initcp; 1638 cp = initcp;
1635 } 1639 }
1636 1640
1637 /* 1641 /*
1638 * Add all elements of the members list to the parent node. 1642 * Add all elements of the members list to the parent node.
1639 */ 1643 */
1640 while(!Lst_IsEmptyS(members)) { 1644 while(!Lst_IsEmptyS(members)) {
1641 gn = Lst_DequeueS(members); 1645 gn = Lst_DequeueS(members);
1642 1646
1643 if (DEBUG(SUFF)) { 1647 if (DEBUG(SUFF)) {
1644 fprintf(debug_file, "%s...", gn->name); 1648 fprintf(debug_file, "%s...", gn->name);
1645 } 1649 }
1646 /* Add gn to the parents child list before the original child */ 1650 /* Add gn to the parents child list before the original child */
1647 Lst_InsertBeforeS(pgn->children, cln, gn); 1651 Lst_InsertBeforeS(pgn->children, cln, gn);
1648 Lst_AppendS(gn->parents, pgn); 1652 Lst_AppendS(gn->parents, pgn);
1649 pgn->unmade++; 1653 pgn->unmade++;
1650 /* Expand wildcards on new node */ 1654 /* Expand wildcards on new node */
1651 SuffExpandWildcards(Lst_PrevS(cln), pgn); 1655 SuffExpandWildcards(Lst_PrevS(cln), pgn);
1652 } 1656 }
1653 Lst_FreeS(members); 1657 Lst_FreeS(members);
1654 1658
1655 /* 1659 /*
1656 * Free the result 1660 * Free the result
1657 */ 1661 */
1658 free(cp); 1662 free(cp);
1659 } 1663 }
1660 if (DEBUG(SUFF)) { 1664 if (DEBUG(SUFF)) {
1661 fprintf(debug_file, "\n"); 1665 fprintf(debug_file, "\n");
1662 } 1666 }
1663 1667
1664 /* 1668 /*
1665 * Now the source is expanded, remove it from the list of children to 1669 * Now the source is expanded, remove it from the list of children to
1666 * keep it from being processed. 1670 * keep it from being processed.
1667 */ 1671 */
1668 pgn->unmade--; 1672 pgn->unmade--;
1669 Lst_RemoveS(pgn->children, cln); 1673 Lst_RemoveS(pgn->children, cln);
1670 Lst_RemoveS(cgn->parents, Lst_MemberS(cgn->parents, pgn)); 1674 Lst_RemoveS(cgn->parents, Lst_MemberS(cgn->parents, pgn));
1671} 1675}
1672 1676
1673static void 1677static void
1674SuffExpandWildcards(LstNode cln, GNode *pgn) 1678SuffExpandWildcards(LstNode cln, GNode *pgn)
1675{ 1679{
1676 GNode *cgn = Lst_DatumS(cln); 1680 GNode *cgn = Lst_DatumS(cln);
1677 GNode *gn; /* New source 8) */ 1681 GNode *gn; /* New source 8) */
1678 char *cp; /* Expanded value */ 1682 char *cp; /* Expanded value */
1679 Lst explist; /* List of expansions */ 1683 Lst explist; /* List of expansions */
1680 1684
1681 if (!Dir_HasWildcards(cgn->name)) 1685 if (!Dir_HasWildcards(cgn->name))
1682 return; 1686 return;
1683 1687
1684 /* 1688 /*
1685 * Expand the word along the chosen path 1689 * Expand the word along the chosen path
1686 */ 1690 */
1687 explist = Lst_Init(); 1691 explist = Lst_Init();
1688 Dir_Expand(cgn->name, Suff_FindPath(cgn), explist); 1692 Dir_Expand(cgn->name, Suff_FindPath(cgn), explist);
1689 1693
1690 while (!Lst_IsEmptyS(explist)) { 1694 while (!Lst_IsEmptyS(explist)) {
1691 /* 1695 /*
1692 * Fetch next expansion off the list and find its GNode 1696 * Fetch next expansion off the list and find its GNode
1693 */ 1697 */
1694 cp = Lst_DequeueS(explist); 1698 cp = Lst_DequeueS(explist);
1695 1699
1696 if (DEBUG(SUFF)) { 1700 if (DEBUG(SUFF)) {
1697 fprintf(debug_file, "%s...", cp); 1701 fprintf(debug_file, "%s...", cp);
1698 } 1702 }
1699 gn = Targ_FindNode(cp, TARG_CREATE); 1703 gn = Targ_FindNode(cp, TARG_CREATE);
1700 1704
1701 /* Add gn to the parents child list before the original child */ 1705 /* Add gn to the parents child list before the original child */
1702 Lst_InsertBeforeS(pgn->children, cln, gn); 1706 Lst_InsertBeforeS(pgn->children, cln, gn);
1703 Lst_AppendS(gn->parents, pgn); 1707 Lst_AppendS(gn->parents, pgn);
1704 pgn->unmade++; 1708 pgn->unmade++;
1705 } 1709 }
1706 1710
1707 Lst_FreeS(explist); 1711 Lst_FreeS(explist);
1708 1712
1709 if (DEBUG(SUFF)) { 1713 if (DEBUG(SUFF)) {
1710 fprintf(debug_file, "\n"); 1714 fprintf(debug_file, "\n");
1711 } 1715 }
1712 1716
1713 /* 1717 /*
1714 * Now the source is expanded, remove it from the list of children to 1718 * Now the source is expanded, remove it from the list of children to
1715 * keep it from being processed. 1719 * keep it from being processed.
1716 */ 1720 */
1717 pgn->unmade--; 1721 pgn->unmade--;
1718 Lst_RemoveS(pgn->children, cln); 1722 Lst_RemoveS(pgn->children, cln);
1719 Lst_RemoveS(cgn->parents, Lst_MemberS(cgn->parents, pgn)); 1723 Lst_RemoveS(cgn->parents, Lst_MemberS(cgn->parents, pgn));
1720} 1724}
1721 1725
1722/*- 1726/*-
1723 *----------------------------------------------------------------------- 1727 *-----------------------------------------------------------------------
1724 * Suff_FindPath -- 1728 * Suff_FindPath --
1725 * Find a path along which to expand the node. 1729 * Find a path along which to expand the node.
1726 * 1730 *
1727 * If the word has a known suffix, use that path. 1731 * If the word has a known suffix, use that path.
1728 * If it has no known suffix, use the default system search path. 1732 * If it has no known suffix, use the default system search path.
1729 * 1733 *
1730 * Input: 1734 * Input:
1731 * gn Node being examined 1735 * gn Node being examined
1732 * 1736 *
1733 * Results: 1737 * Results:
1734 * The appropriate path to search for the GNode. 1738 * The appropriate path to search for the GNode.
1735 * 1739 *
1736 * Side Effects: 1740 * Side Effects:
1737 * XXX: We could set the suffix here so that we don't have to scan 1741 * XXX: We could set the suffix here so that we don't have to scan
1738 * again. 1742 * again.
1739 * 1743 *
1740 *----------------------------------------------------------------------- 1744 *-----------------------------------------------------------------------
1741 */ 1745 */
1742Lst 1746Lst
1743Suff_FindPath(GNode* gn) 1747Suff_FindPath(GNode* gn)
1744{ 1748{
1745 Suff *suff = gn->suffix; 1749 Suff *suff = gn->suffix;
1746 1750
1747 if (suff == NULL) { 1751 if (suff == NULL) {
1748 SuffixCmpData sd; /* Search string data */ 1752 SuffixCmpData sd; /* Search string data */
1749 LstNode ln; 1753 LstNode ln;
1750 sd.len = strlen(gn->name); 1754 sd.len = strlen(gn->name);
1751 sd.ename = gn->name + sd.len; 1755 sd.ename = gn->name + sd.len;
1752 ln = Lst_FindS(sufflist, SuffSuffIsSuffixP, &sd); 1756 ln = Lst_FindS(sufflist, SuffSuffIsSuffixP, &sd);
1753 1757
1754 if (DEBUG(SUFF)) { 1758 if (DEBUG(SUFF)) {
1755 fprintf(debug_file, "Wildcard expanding \"%s\"...", gn->name); 1759 fprintf(debug_file, "Wildcard expanding \"%s\"...", gn->name);
1756 } 1760 }
1757 if (ln != NULL) 1761 if (ln != NULL)
1758 suff = Lst_DatumS(ln); 1762 suff = Lst_DatumS(ln);
1759 /* XXX: Here we can save the suffix so we don't have to do this again */ 1763 /* XXX: Here we can save the suffix so we don't have to do this again */
1760 } 1764 }
1761 1765
1762 if (suff != NULL) { 1766 if (suff != NULL) {
1763 if (DEBUG(SUFF)) { 1767 if (DEBUG(SUFF)) {
1764 fprintf(debug_file, "suffix is \"%s\"...", suff->name); 1768 fprintf(debug_file, "suffix is \"%s\"...", suff->name);
1765 } 1769 }
1766 return suff->searchPath; 1770 return suff->searchPath;
1767 } else { 1771 } else {
1768 /* 1772 /*
1769 * Use default search path 1773 * Use default search path
1770 */ 1774 */
1771 return dirSearchPath; 1775 return dirSearchPath;
1772 } 1776 }
1773} 1777}
1774 1778
1775/*- 1779/*-
1776 *----------------------------------------------------------------------- 1780 *-----------------------------------------------------------------------
1777 * SuffApplyTransform -- 1781 * SuffApplyTransform --
1778 * Apply a transformation rule, given the source and target nodes 1782 * Apply a transformation rule, given the source and target nodes
1779 * and suffixes. 1783 * and suffixes.
1780 * 1784 *
1781 * Input: 1785 * Input:
1782 * tGn Target node 1786 * tGn Target node
1783 * sGn Source node 1787 * sGn Source node
1784 * t Target suffix 1788 * t Target suffix
1785 * s Source suffix 1789 * s Source suffix
1786 * 1790 *
1787 * Results: 1791 * Results:
1788 * TRUE if successful, FALSE if not. 1792 * TRUE if successful, FALSE if not.
1789 * 1793 *
1790 * Side Effects: 1794 * Side Effects:
1791 * The source and target are linked and the commands from the 1795 * The source and target are linked and the commands from the
1792 * transformation are added to the target node's commands list. 1796 * transformation are added to the target node's commands list.
1793 * All attributes but OP_DEPMASK and OP_TRANSFORM are applied 1797 * All attributes but OP_DEPMASK and OP_TRANSFORM are applied
1794 * to the target. The target also inherits all the sources for 1798 * to the target. The target also inherits all the sources for
1795 * the transformation rule. 1799 * the transformation rule.
1796 * 1800 *
1797 *----------------------------------------------------------------------- 1801 *-----------------------------------------------------------------------
1798 */ 1802 */
1799static Boolean 1803static Boolean
1800SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s) 1804SuffApplyTransform(GNode *tGn, GNode *sGn, Suff *t, Suff *s)
1801{ 1805{
1802 LstNode ln, nln; /* General node */ 1806 LstNode ln, nln; /* General node */
1803 char *tname; /* Name of transformation rule */ 1807 char *tname; /* Name of transformation rule */
1804 GNode *gn; /* Node for same */ 1808 GNode *gn; /* Node for same */
1805 1809
1806 /* 1810 /*
1807 * Form the proper links between the target and source. 1811 * Form the proper links between the target and source.
1808 */ 1812 */
1809 Lst_AppendS(tGn->children, sGn); 1813 Lst_AppendS(tGn->children, sGn);
1810 Lst_AppendS(sGn->parents, tGn); 1814 Lst_AppendS(sGn->parents, tGn);
1811 tGn->unmade += 1; 1815 tGn->unmade += 1;
1812 1816
1813 /* 1817 /*
1814 * Locate the transformation rule itself 1818 * Locate the transformation rule itself
1815 */ 1819 */
1816 tname = str_concat2(s->name, t->name); 1820 tname = str_concat2(s->name, t->name);
1817 ln = Lst_Find(transforms, SuffGNHasNameP, tname); 1821 ln = Lst_Find(transforms, SuffGNHasNameP, tname);
1818 free(tname); 1822 free(tname);
1819 1823
1820 if (ln == NULL) { 1824 if (ln == NULL) {
1821 /* 1825 /*
1822 * Not really such a transformation rule (can happen when we're 1826 * Not really such a transformation rule (can happen when we're
1823 * called to link an OP_MEMBER and OP_ARCHV node), so return 1827 * called to link an OP_MEMBER and OP_ARCHV node), so return
1824 * FALSE. 1828 * FALSE.
1825 */ 1829 */
1826 return FALSE; 1830 return FALSE;
1827 } 1831 }
1828 1832
1829 gn = Lst_DatumS(ln); 1833 gn = Lst_DatumS(ln);
1830 1834
1831 if (DEBUG(SUFF)) { 1835 if (DEBUG(SUFF)) {
1832 fprintf(debug_file, "\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name); 1836 fprintf(debug_file, "\tapplying %s -> %s to \"%s\"\n", s->name, t->name, tGn->name);
1833 } 1837 }
1834 1838
1835 /* 1839 /*
1836 * Record last child for expansion purposes 1840 * Record last child for expansion purposes
1837 */ 1841 */
1838 ln = Lst_LastS(tGn->children); 1842 ln = Lst_LastS(tGn->children);
1839 1843
1840 /* 1844 /*
1841 * Pass the buck to Make_HandleUse to apply the rule 1845 * Pass the buck to Make_HandleUse to apply the rule
1842 */ 1846 */
1843 (void)Make_HandleUse(gn, tGn); 1847 (void)Make_HandleUse(gn, tGn);
1844 1848
1845 /* 1849 /*
1846 * Deal with wildcards and variables in any acquired sources 1850 * Deal with wildcards and variables in any acquired sources
1847 */ 1851 */
1848 for (ln = ln != NULL ? Lst_SuccS(ln) : NULL; ln != NULL; ln = nln) { 1852 for (ln = ln != NULL ? Lst_SuccS(ln) : NULL; ln != NULL; ln = nln) {
1849 nln = Lst_SuccS(ln); 1853 nln = Lst_SuccS(ln);
1850 SuffExpandChildren(ln, tGn); 1854 SuffExpandChildren(ln, tGn);
1851 } 1855 }
1852 1856
1853 /* 1857 /*
1854 * Keep track of another parent to which this beast is transformed so 1858 * Keep track of another parent to which this beast is transformed so
1855 * the .IMPSRC variable can be set correctly for the parent. 1859 * the .IMPSRC variable can be set correctly for the parent.
1856 */ 1860 */
1857 Lst_AppendS(sGn->iParents, tGn); 1861 Lst_AppendS(sGn->iParents, tGn);
1858 1862
1859 return TRUE; 1863 return TRUE;
1860} 1864}
1861 1865
1862 1866
1863/*- 1867/*-
1864 *----------------------------------------------------------------------- 1868 *-----------------------------------------------------------------------
1865 * SuffFindArchiveDeps -- 1869 * SuffFindArchiveDeps --
1866 * Locate dependencies for an OP_ARCHV node. 1870 * Locate dependencies for an OP_ARCHV node.
1867 * 1871 *
1868 * Input: 1872 * Input:
1869 * gn Node for which to locate dependencies 1873 * gn Node for which to locate dependencies
1870 * 1874 *
1871 * Results: 1875 * Results:
1872 * None 1876 * None
1873 * 1877 *
1874 * Side Effects: 1878 * Side Effects:
1875 * Same as Suff_FindDeps 1879 * Same as Suff_FindDeps
1876 * 1880 *
1877 *----------------------------------------------------------------------- 1881 *-----------------------------------------------------------------------
1878 */ 1882 */
1879static void 1883static void
1880SuffFindArchiveDeps(GNode *gn, Lst slst) 1884SuffFindArchiveDeps(GNode *gn, Lst slst)
1881{ 1885{
1882 char *eoarch; /* End of archive portion */ 1886 char *eoarch; /* End of archive portion */
1883 char *eoname; /* End of member portion */ 1887 char *eoname; /* End of member portion */
1884 GNode *mem; /* Node for member */ 1888 GNode *mem; /* Node for member */
1885 LstNode ln, nln; /* Next suffix node to check */ 1889 LstNode ln, nln; /* Next suffix node to check */
1886 Suff *ms; /* Suffix descriptor for member */ 1890 Suff *ms; /* Suffix descriptor for member */
1887 char *name; /* Start of member's name */ 1891 char *name; /* Start of member's name */
1888 1892
1889 /* 1893 /*
1890 * The node is an archive(member) pair. so we must find a 1894 * The node is an archive(member) pair. so we must find a
1891 * suffix for both of them. 1895 * suffix for both of them.
1892 */ 1896 */
1893 eoarch = strchr(gn->name, '('); 1897 eoarch = strchr(gn->name, '(');
1894 eoname = strchr(eoarch, ')'); 1898 eoname = strchr(eoarch, ')');
1895 1899
1896 /* 1900 /*
1897 * Caller guarantees the format `libname(member)', via 1901 * Caller guarantees the format `libname(member)', via
1898 * Arch_ParseArchive. 1902 * Arch_ParseArchive.
1899 */ 1903 */
1900 assert(eoarch != NULL); 1904 assert(eoarch != NULL);
1901 assert(eoname != NULL); 1905 assert(eoname != NULL);
1902 1906
1903 *eoname = '\0'; /* Nuke parentheses during suffix search */ 1907 *eoname = '\0'; /* Nuke parentheses during suffix search */
1904 *eoarch = '\0'; /* So a suffix can be found */ 1908 *eoarch = '\0'; /* So a suffix can be found */
1905 1909
1906 name = eoarch + 1; 1910 name = eoarch + 1;
1907 1911
1908 /* 1912 /*
1909 * To simplify things, call Suff_FindDeps recursively on the member now, 1913 * To simplify things, call Suff_FindDeps recursively on the member now,
1910 * so we can simply compare the member's .PREFIX and .TARGET variables 1914 * so we can simply compare the member's .PREFIX and .TARGET variables
1911 * to locate its suffix. This allows us to figure out the suffix to 1915 * to locate its suffix. This allows us to figure out the suffix to
1912 * use for the archive without having to do a quadratic search over the 1916 * use for the archive without having to do a quadratic search over the
1913 * suffix list, backtracking for each one... 1917 * suffix list, backtracking for each one...
1914 */ 1918 */
1915 mem = Targ_FindNode(name, TARG_CREATE); 1919 mem = Targ_FindNode(name, TARG_CREATE);
1916 SuffFindDeps(mem, slst); 1920 SuffFindDeps(mem, slst);
1917 1921
1918 /* 1922 /*
1919 * Create the link between the two nodes right off 1923 * Create the link between the two nodes right off
1920 */ 1924 */
1921 Lst_AppendS(gn->children, mem); 1925 Lst_AppendS(gn->children, mem);
1922 Lst_AppendS(mem->parents, gn); 1926 Lst_AppendS(mem->parents, gn);
1923 gn->unmade += 1; 1927 gn->unmade += 1;
1924 1928
1925 /* 1929 /*
1926 * Copy in the variables from the member node to this one. 1930 * Copy in the variables from the member node to this one.
1927 */ 1931 */
1928 { 1932 {
1929 char *freeIt; 1933 char *freeIt;
1930 Var_Set(PREFIX, Var_Value(PREFIX, mem, &freeIt), gn); 1934 Var_Set(PREFIX, Var_Value(PREFIX, mem, &freeIt), gn);
1931 bmake_free(freeIt); 1935 bmake_free(freeIt);
1932 Var_Set(TARGET, Var_Value(TARGET, mem, &freeIt), gn); 1936 Var_Set(TARGET, Var_Value(TARGET, mem, &freeIt), gn);
1933 bmake_free(freeIt); 1937 bmake_free(freeIt);
1934 } 1938 }
1935 1939
1936 ms = mem->suffix; 1940 ms = mem->suffix;
1937 if (ms == NULL) { 1941 if (ms == NULL) {
1938 /* 1942 /*
1939 * Didn't know what it was -- use .NULL suffix if not in make mode 1943 * Didn't know what it was -- use .NULL suffix if not in make mode
1940 */ 1944 */
1941 if (DEBUG(SUFF)) { 1945 if (DEBUG(SUFF)) {
1942 fprintf(debug_file, "using null suffix\n"); 1946 fprintf(debug_file, "using null suffix\n");
1943 } 1947 }
1944 ms = suffNull; 1948 ms = suffNull;
1945 } 1949 }
1946 1950
1947 1951
1948 /* 1952 /*
1949 * Set the other two local variables required for this target. 1953 * Set the other two local variables required for this target.
1950 */ 1954 */
1951 Var_Set(MEMBER, name, gn); 1955 Var_Set(MEMBER, name, gn);
1952 Var_Set(ARCHIVE, gn->name, gn); 1956 Var_Set(ARCHIVE, gn->name, gn);
1953 1957
1954 /* 1958 /*
1955 * Set $@ for compatibility with other makes 1959 * Set $@ for compatibility with other makes
1956 */ 1960 */
1957 Var_Set(TARGET, gn->name, gn); 1961 Var_Set(TARGET, gn->name, gn);
1958 1962
1959 /* 1963 /*
1960 * Now we've got the important local variables set, expand any sources 1964 * Now we've got the important local variables set, expand any sources
1961 * that still contain variables or wildcards in their names. 1965 * that still contain variables or wildcards in their names.
1962 */ 1966 */
1963 for (ln = Lst_FirstS(gn->children); ln != NULL; ln = nln) { 1967 for (ln = Lst_FirstS(gn->children); ln != NULL; ln = nln) {
1964 nln = Lst_SuccS(ln); 1968 nln = Lst_SuccS(ln);
1965 SuffExpandChildren(ln, gn); 1969 SuffExpandChildren(ln, gn);
1966 } 1970 }
1967 1971
1968 if (ms != NULL) { 1972 if (ms != NULL) {
1969 /* 1973 /*
1970 * Member has a known suffix, so look for a transformation rule from 1974 * Member has a known suffix, so look for a transformation rule from
1971 * it to a possible suffix of the archive. Rather than searching 1975 * it to a possible suffix of the archive. Rather than searching
1972 * through the entire list, we just look at suffixes to which the 1976 * through the entire list, we just look at suffixes to which the
1973 * member's suffix may be transformed... 1977 * member's suffix may be transformed...
1974 */ 1978 */
1975 SuffixCmpData sd; /* Search string data */ 1979 SuffixCmpData sd; /* Search string data */
1976 1980
1977 /* 1981 /*
1978 * Use first matching suffix... 1982 * Use first matching suffix...
1979 */ 1983 */
1980 sd.len = eoarch - gn->name; 1984 sd.len = eoarch - gn->name;
1981 sd.ename = eoarch; 1985 sd.ename = eoarch;
1982 ln = Lst_Find(ms->parents, SuffSuffIsSuffixP, &sd); 1986 ln = Lst_Find(ms->parents, SuffSuffIsSuffixP, &sd);
1983 1987
1984 if (ln != NULL) { 1988 if (ln != NULL) {
1985 /* 1989 /*
1986 * Got one -- apply it 1990 * Got one -- apply it
1987 */ 1991 */
1988 if (!SuffApplyTransform(gn, mem, (Suff *)Lst_DatumS(ln), ms) && 1992 if (!SuffApplyTransform(gn, mem, (Suff *)Lst_DatumS(ln), ms) &&
1989 DEBUG(SUFF)) 1993 DEBUG(SUFF))
1990 { 1994 {
1991 fprintf(debug_file, "\tNo transformation from %s -> %s\n", 1995 fprintf(debug_file, "\tNo transformation from %s -> %s\n",
1992 ms->name, ((Suff *)Lst_DatumS(ln))->name); 1996 ms->name, ((Suff *)Lst_DatumS(ln))->name);
1993 } 1997 }
1994 } 1998 }
1995 } 1999 }
1996 2000
1997 /* 2001 /*
1998 * Replace the opening and closing parens now we've no need of the separate 2002 * Replace the opening and closing parens now we've no need of the separate
1999 * pieces. 2003 * pieces.
2000 */ 2004 */
2001 *eoarch = '('; *eoname = ')'; 2005 *eoarch = '('; *eoname = ')';
2002 2006
2003 /* 2007 /*
2004 * Pretend gn appeared to the left of a dependency operator so 2008 * Pretend gn appeared to the left of a dependency operator so
2005 * the user needn't provide a transformation from the member to the 2009 * the user needn't provide a transformation from the member to the
2006 * archive. 2010 * archive.
2007 */ 2011 */
2008 if (OP_NOP(gn->type)) { 2012 if (OP_NOP(gn->type)) {
2009 gn->type |= OP_DEPENDS; 2013 gn->type |= OP_DEPENDS;
2010 } 2014 }
2011 2015
2012 /* 2016 /*
2013 * Flag the member as such so we remember to look in the archive for 2017 * Flag the member as such so we remember to look in the archive for
2014 * its modification time. The OP_JOIN | OP_MADE is needed because this 2018 * its modification time. The OP_JOIN | OP_MADE is needed because this
2015 * target should never get made. 2019 * target should never get made.
2016 */ 2020 */
2017 mem->type |= OP_MEMBER | OP_JOIN | OP_MADE; 2021 mem->type |= OP_MEMBER | OP_JOIN | OP_MADE;
2018} 2022}
2019 2023
2020/*- 2024/*-
2021 *----------------------------------------------------------------------- 2025 *-----------------------------------------------------------------------
2022 * SuffFindNormalDeps -- 2026 * SuffFindNormalDeps --
2023 * Locate implicit dependencies for regular targets. 2027 * Locate implicit dependencies for regular targets.
2024 * 2028 *
2025 * Input: 2029 * Input:
2026 * gn Node for which to find sources 2030 * gn Node for which to find sources
2027 * 2031 *
2028 * Results: 2032 * Results:
2029 * None. 2033 * None.
2030 * 2034 *
2031 * Side Effects: 2035 * Side Effects:
2032 * Same as Suff_FindDeps... 2036 * Same as Suff_FindDeps...
2033 * 2037 *
2034 *----------------------------------------------------------------------- 2038 *-----------------------------------------------------------------------
2035 */ 2039 */
2036static void 2040static void
2037SuffFindNormalDeps(GNode *gn, Lst slst) 2041SuffFindNormalDeps(GNode *gn, Lst slst)
2038{ 2042{
2039 char *eoname; /* End of name */ 2043 char *eoname; /* End of name */
2040 char *sopref; /* Start of prefix */ 2044 char *sopref; /* Start of prefix */
2041 LstNode ln, nln; /* Next suffix node to check */ 2045 LstNode ln, nln; /* Next suffix node to check */
2042 Lst srcs; /* List of sources at which to look */ 2046 Lst srcs; /* List of sources at which to look */
2043 Lst targs; /* List of targets to which things can be 2047 Lst targs; /* List of targets to which things can be
2044 * transformed. They all have the same file, 2048 * transformed. They all have the same file,
2045 * but different suff and pref fields */ 2049 * but different suff and pref fields */
2046 Src *bottom; /* Start of found transformation path */ 2050 Src *bottom; /* Start of found transformation path */
2047 Src *src; /* General Src pointer */ 2051 Src *src; /* General Src pointer */
2048 char *pref; /* Prefix to use */ 2052 char *pref; /* Prefix to use */
2049 Src *targ; /* General Src target pointer */ 2053 Src *targ; /* General Src target pointer */
2050 SuffixCmpData sd; /* Search string data */ 2054 SuffixCmpData sd; /* Search string data */
2051 2055
2052 2056
2053 sd.len = strlen(gn->name); 2057 sd.len = strlen(gn->name);
2054 sd.ename = eoname = gn->name + sd.len; 2058 sd.ename = eoname = gn->name + sd.len;
2055 2059
2056 sopref = gn->name; 2060 sopref = gn->name;
2057 2061
2058 /* 2062 /*
2059 * Begin at the beginning... 2063 * Begin at the beginning...
2060 */ 2064 */
2061 ln = Lst_First(sufflist); 2065 ln = Lst_First(sufflist);
2062 srcs = Lst_Init(); 2066 srcs = Lst_Init();
2063 targs = Lst_Init(); 2067 targs = Lst_Init();
2064 2068
2065 /* 2069 /*
2066 * We're caught in a catch-22 here. On the one hand, we want to use any 2070 * We're caught in a catch-22 here. On the one hand, we want to use any
2067 * transformation implied by the target's sources, but we can't examine 2071 * transformation implied by the target's sources, but we can't examine
2068 * the sources until we've expanded any variables/wildcards they may hold, 2072 * the sources until we've expanded any variables/wildcards they may hold,
2069 * and we can't do that until we've set up the target's local variables 2073 * and we can't do that until we've set up the target's local variables
2070 * and we can't do that until we know what the proper suffix for the 2074 * and we can't do that until we know what the proper suffix for the
2071 * target is (in case there are two suffixes one of which is a suffix of 2075 * target is (in case there are two suffixes one of which is a suffix of
2072 * the other) and we can't know that until we've found its implied 2076 * the other) and we can't know that until we've found its implied
2073 * source, which we may not want to use if there's an existing source 2077 * source, which we may not want to use if there's an existing source
2074 * that implies a different transformation. 2078 * that implies a different transformation.
2075 * 2079 *
2076 * In an attempt to get around this, which may not work all the time, 2080 * In an attempt to get around this, which may not work all the time,
2077 * but should work most of the time, we look for implied sources first, 2081 * but should work most of the time, we look for implied sources first,
2078 * checking transformations to all possible suffixes of the target, 2082 * checking transformations to all possible suffixes of the target,
2079 * use what we find to set the target's local variables, expand the 2083 * use what we find to set the target's local variables, expand the
2080 * children, then look for any overriding transformations they imply. 2084 * children, then look for any overriding transformations they imply.
2081 * Should we find one, we discard the one we found before. 2085 * Should we find one, we discard the one we found before.
2082 */ 2086 */
2083 bottom = NULL; 2087 bottom = NULL;
2084 targ = NULL; 2088 targ = NULL;
2085 2089
2086 if (!(gn->type & OP_PHONY)) { 2090 if (!(gn->type & OP_PHONY)) {
2087 2091
2088 while (ln != NULL) { 2092 while (ln != NULL) {
2089 /* 2093 /*
2090 * Look for next possible suffix... 2094 * Look for next possible suffix...
2091 */ 2095 */
2092 ln = Lst_FindFrom(sufflist, ln, SuffSuffIsSuffixP, &sd); 2096 ln = Lst_FindFrom(sufflist, ln, SuffSuffIsSuffixP, &sd);
2093 2097
2094 if (ln != NULL) { 2098 if (ln != NULL) {
2095 int prefLen; /* Length of the prefix */ 2099 int prefLen; /* Length of the prefix */
2096 2100
2097 /* 2101 /*
2098 * Allocate a Src structure to which things can be transformed 2102 * Allocate a Src structure to which things can be transformed
2099 */ 2103 */
2100 targ = bmake_malloc(sizeof(Src)); 2104 targ = bmake_malloc(sizeof(Src));
2101 targ->file = bmake_strdup(gn->name); 2105 targ->file = bmake_strdup(gn->name);
2102 targ->suff = Lst_DatumS(ln); 2106 targ->suff = Lst_DatumS(ln);
2103 targ->suff->refCount++; 2107 targ->suff->refCount++;
2104 targ->node = gn; 2108 targ->node = gn;
2105 targ->parent = NULL; 2109 targ->parent = NULL;
2106 targ->children = 0; 2110 targ->children = 0;
2107#ifdef DEBUG_SRC 2111#ifdef DEBUG_SRC
2108 targ->cp = Lst_Init(); 2112 targ->cp = Lst_Init();
2109#endif 2113#endif
2110 2114
2111 /* 2115 /*
2112 * Allocate room for the prefix, whose end is found by 2116 * Allocate room for the prefix, whose end is found by
2113 * subtracting the length of the suffix from 2117 * subtracting the length of the suffix from
2114 * the end of the name. 2118 * the end of the name.
2115 */ 2119 */
2116 prefLen = (eoname - targ->suff->nameLen) - sopref; 2120 prefLen = (eoname - targ->suff->nameLen) - sopref;
2117 targ->pref = bmake_malloc(prefLen + 1); 2121 targ->pref = bmake_malloc(prefLen + 1);
2118 memcpy(targ->pref, sopref, prefLen); 2122 memcpy(targ->pref, sopref, prefLen);
2119 targ->pref[prefLen] = '\0'; 2123 targ->pref[prefLen] = '\0';
2120 2124
2121 /* 2125 /*
2122 * Add nodes from which the target can be made 2126 * Add nodes from which the target can be made
2123 */ 2127 */
2124 SuffAddLevel(srcs, targ); 2128 SuffAddLevel(srcs, targ);
2125 2129
2126 /* 2130 /*
2127 * Record the target so we can nuke it 2131 * Record the target so we can nuke it
2128 */ 2132 */
2129 Lst_AppendS(targs, targ); 2133 Lst_AppendS(targs, targ);
2130 2134
2131 /* 2135 /*
2132 * Search from this suffix's successor... 2136 * Search from this suffix's successor...
2133 */ 2137 */
2134 ln = Lst_SuccS(ln); 2138 ln = Lst_SuccS(ln);
2135 } 2139 }
2136 } 2140 }
2137 2141
2138 /* 2142 /*
2139 * Handle target of unknown suffix... 2143 * Handle target of unknown suffix...
2140 */ 2144 */
2141 if (Lst_IsEmptyS(targs) && suffNull != NULL) { 2145 if (Lst_IsEmptyS(targs) && suffNull != NULL) {
2142 if (DEBUG(SUFF)) { 2146 if (DEBUG(SUFF)) {
2143 fprintf(debug_file, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name); 2147 fprintf(debug_file, "\tNo known suffix on %s. Using .NULL suffix\n", gn->name);
2144 } 2148 }
2145 2149
2146 targ = bmake_malloc(sizeof(Src)); 2150 targ = bmake_malloc(sizeof(Src));
2147 targ->file = bmake_strdup(gn->name); 2151 targ->file = bmake_strdup(gn->name);
2148 targ->suff = suffNull; 2152 targ->suff = suffNull;
2149 targ->suff->refCount++; 2153 targ->suff->refCount++;
2150 targ->node = gn; 2154 targ->node = gn;
2151 targ->parent = NULL; 2155 targ->parent = NULL;
2152 targ->children = 0; 2156 targ->children = 0;
2153 targ->pref = bmake_strdup(sopref); 2157 targ->pref = bmake_strdup(sopref);
2154#ifdef DEBUG_SRC 2158#ifdef DEBUG_SRC
2155 targ->cp = Lst_Init(); 2159 targ->cp = Lst_Init();
2156#endif 2160#endif
2157 2161
2158 /* 2162 /*
2159 * Only use the default suffix rules if we don't have commands 2163 * Only use the default suffix rules if we don't have commands
2160 * defined for this gnode; traditional make programs used to 2164 * defined for this gnode; traditional make programs used to
2161 * not define suffix rules if the gnode had children but we 2165 * not define suffix rules if the gnode had children but we
2162 * don't do this anymore. 2166 * don't do this anymore.
2163 */ 2167 */
2164 if (Lst_IsEmptyS(gn->commands)) 2168 if (Lst_IsEmptyS(gn->commands))
2165 SuffAddLevel(srcs, targ); 2169 SuffAddLevel(srcs, targ);
2166 else { 2170 else {
2167 if (DEBUG(SUFF)) 2171 if (DEBUG(SUFF))
2168 fprintf(debug_file, "not "); 2172 fprintf(debug_file, "not ");
2169 } 2173 }
2170 2174
2171 if (DEBUG(SUFF)) 2175 if (DEBUG(SUFF))
2172 fprintf(debug_file, "adding suffix rules\n"); 2176 fprintf(debug_file, "adding suffix rules\n");
2173 2177
2174 Lst_AppendS(targs, targ); 2178 Lst_AppendS(targs, targ);
2175 } 2179 }
2176 2180
2177 /* 2181 /*
2178 * Using the list of possible sources built up from the target 2182 * Using the list of possible sources built up from the target
2179 * suffix(es), try and find an existing file/target that matches. 2183 * suffix(es), try and find an existing file/target that matches.
2180 */ 2184 */
2181 bottom = SuffFindThem(srcs, slst); 2185 bottom = SuffFindThem(srcs, slst);
2182 2186
2183 if (bottom == NULL) { 2187 if (bottom == NULL) {
2184 /* 2188 /*
2185 * No known transformations -- use the first suffix found 2189 * No known transformations -- use the first suffix found
2186 * for setting the local variables. 2190 * for setting the local variables.
2187 */ 2191 */
2188 if (!Lst_IsEmptyS(targs)) { 2192 if (!Lst_IsEmptyS(targs)) {
2189 targ = Lst_DatumS(Lst_First(targs)); 2193 targ = Lst_DatumS(Lst_First(targs));
2190 } else { 2194 } else {
2191 targ = NULL; 2195 targ = NULL;
2192 } 2196 }
2193 } else { 2197 } else {
2194 /* 2198 /*
2195 * Work up the transformation path to find the suffix of the 2199 * Work up the transformation path to find the suffix of the
2196 * target to which the transformation was made. 2200 * target to which the transformation was made.
2197 */ 2201 */
2198 for (targ = bottom; targ->parent != NULL; targ = targ->parent) 2202 for (targ = bottom; targ->parent != NULL; targ = targ->parent)
2199 continue; 2203 continue;
2200 } 2204 }
2201 } 2205 }
2202 2206
2203 Var_Set(TARGET, gn->path ? gn->path : gn->name, gn); 2207 Var_Set(TARGET, gn->path ? gn->path : gn->name, gn);
2204 2208
2205 pref = (targ != NULL) ? targ->pref : gn->name; 2209 pref = (targ != NULL) ? targ->pref : gn->name;
2206 Var_Set(PREFIX, pref, gn); 2210 Var_Set(PREFIX, pref, gn);
2207 2211
2208 /* 2212 /*
2209 * Now we've got the important local variables set, expand any sources 2213 * Now we've got the important local variables set, expand any sources
2210 * that still contain variables or wildcards in their names. 2214 * that still contain variables or wildcards in their names.
2211 */ 2215 */
2212 for (ln = Lst_First(gn->children); ln != NULL; ln = nln) { 2216 for (ln = Lst_First(gn->children); ln != NULL; ln = nln) {
2213 nln = Lst_SuccS(ln); 2217 nln = Lst_SuccS(ln);
2214 SuffExpandChildren(ln, gn); 2218 SuffExpandChildren(ln, gn);
2215 } 2219 }
2216 2220
2217 if (targ == NULL) { 2221 if (targ == NULL) {
2218 if (DEBUG(SUFF)) { 2222 if (DEBUG(SUFF)) {
2219 fprintf(debug_file, "\tNo valid suffix on %s\n", gn->name); 2223 fprintf(debug_file, "\tNo valid suffix on %s\n", gn->name);
2220 } 2224 }
2221 2225
2222sfnd_abort: 2226sfnd_abort:
2223 /* 2227 /*
2224 * Deal with finding the thing on the default search path. We 2228 * Deal with finding the thing on the default search path. We
2225 * always do that, not only if the node is only a source (not 2229 * always do that, not only if the node is only a source (not
2226 * on the lhs of a dependency operator or [XXX] it has neither 2230 * on the lhs of a dependency operator or [XXX] it has neither
2227 * children or commands) as the old pmake did. 2231 * children or commands) as the old pmake did.
2228 */ 2232 */
2229 if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) { 2233 if ((gn->type & (OP_PHONY|OP_NOPATH)) == 0) {
2230 free(gn->path); 2234 free(gn->path);
2231 gn->path = Dir_FindFile(gn->name, 2235 gn->path = Dir_FindFile(gn->name,
2232 (targ == NULL ? dirSearchPath : 2236 (targ == NULL ? dirSearchPath :
2233 targ->suff->searchPath)); 2237 targ->suff->searchPath));
2234 if (gn->path != NULL) { 2238 if (gn->path != NULL) {
2235 char *ptr; 2239 char *ptr;
2236 Var_Set(TARGET, gn->path, gn); 2240 Var_Set(TARGET, gn->path, gn);
2237 2241
2238 if (targ != NULL) { 2242 if (targ != NULL) {
2239 /* 2243 /*
2240 * Suffix known for the thing -- trim the suffix off 2244 * Suffix known for the thing -- trim the suffix off
2241 * the path to form the proper .PREFIX variable. 2245 * the path to form the proper .PREFIX variable.
2242 */ 2246 */
2243 int savep = strlen(gn->path) - targ->suff->nameLen; 2247 int savep = strlen(gn->path) - targ->suff->nameLen;
2244 char savec; 2248 char savec;
2245 2249
2246 if (gn->suffix) 2250 if (gn->suffix)
2247 gn->suffix->refCount--; 2251 gn->suffix->refCount--;
2248 gn->suffix = targ->suff; 2252 gn->suffix = targ->suff;
2249 gn->suffix->refCount++; 2253 gn->suffix->refCount++;
2250 2254
2251 savec = gn->path[savep]; 2255 savec = gn->path[savep];
2252 gn->path[savep] = '\0'; 2256 gn->path[savep] = '\0';
2253 2257
2254 if ((ptr = strrchr(gn->path, '/')) != NULL) 2258 if ((ptr = strrchr(gn->path, '/')) != NULL)
2255 ptr++; 2259 ptr++;
2256 else 2260 else
2257 ptr = gn->path; 2261 ptr = gn->path;
2258 2262
2259 Var_Set(PREFIX, ptr, gn); 2263 Var_Set(PREFIX, ptr, gn);
2260 2264
2261 gn->path[savep] = savec; 2265 gn->path[savep] = savec;
2262 } else { 2266 } else {
2263 /* 2267 /*
2264 * The .PREFIX gets the full path if the target has 2268 * The .PREFIX gets the full path if the target has
2265 * no known suffix. 2269 * no known suffix.
2266 */ 2270 */
2267 if (gn->suffix) 2271 if (gn->suffix)
2268 gn->suffix->refCount--; 2272 gn->suffix->refCount--;
2269 gn->suffix = NULL; 2273 gn->suffix = NULL;
2270 2274
2271 if ((ptr = strrchr(gn->path, '/')) != NULL) 2275 if ((ptr = strrchr(gn->path, '/')) != NULL)
2272 ptr++; 2276 ptr++;
2273 else 2277 else
2274 ptr = gn->path; 2278 ptr = gn->path;
2275 2279
2276 Var_Set(PREFIX, ptr, gn); 2280 Var_Set(PREFIX, ptr, gn);
2277 } 2281 }
2278 } 2282 }
2279 } 2283 }
2280 2284
2281 goto sfnd_return; 2285 goto sfnd_return;
2282 } 2286 }
2283 2287
2284 /* 2288 /*
2285 * If the suffix indicates that the target is a library, mark that in 2289 * If the suffix indicates that the target is a library, mark that in
2286 * the node's type field. 2290 * the node's type field.
2287 */ 2291 */
2288 if (targ->suff->flags & SUFF_LIBRARY) { 2292 if (targ->suff->flags & SUFF_LIBRARY) {
2289 gn->type |= OP_LIB; 2293 gn->type |= OP_LIB;
2290 } 2294 }
2291 2295
2292 /* 2296 /*
2293 * Check for overriding transformation rule implied by sources 2297 * Check for overriding transformation rule implied by sources
2294 */ 2298 */
2295 if (!Lst_IsEmptyS(gn->children)) { 2299 if (!Lst_IsEmptyS(gn->children)) {
2296 src = SuffFindCmds(targ, slst); 2300 src = SuffFindCmds(targ, slst);
2297 2301
2298 if (src != NULL) { 2302 if (src != NULL) {
2299 /* 2303 /*
2300 * Free up all the Src structures in the transformation path 2304 * Free up all the Src structures in the transformation path
2301 * up to, but not including, the parent node. 2305 * up to, but not including, the parent node.
2302 */ 2306 */
2303 while (bottom && bottom->parent != NULL) { 2307 while (bottom && bottom->parent != NULL) {
2304 if (Lst_MemberS(slst, bottom) == NULL) { 2308 if (Lst_MemberS(slst, bottom) == NULL) {
2305 Lst_AppendS(slst, bottom); 2309 Lst_AppendS(slst, bottom);
2306 } 2310 }
2307 bottom = bottom->parent; 2311 bottom = bottom->parent;
2308 } 2312 }
2309 bottom = src; 2313 bottom = src;
2310 } 2314 }
2311 } 2315 }
2312 2316
2313 if (bottom == NULL) { 2317 if (bottom == NULL) {
2314 /* 2318 /*
2315 * No idea from where it can come -- return now. 2319 * No idea from where it can come -- return now.
2316 */ 2320 */
2317 goto sfnd_abort; 2321 goto sfnd_abort;
2318 } 2322 }
2319 2323
2320 /* 2324 /*
2321 * We now have a list of Src structures headed by 'bottom' and linked via 2325 * We now have a list of Src structures headed by 'bottom' and linked via
2322 * their 'parent' pointers. What we do next is create links between 2326 * their 'parent' pointers. What we do next is create links between
2323 * source and target nodes (which may or may not have been created) 2327 * source and target nodes (which may or may not have been created)
2324 * and set the necessary local variables in each target. The 2328 * and set the necessary local variables in each target. The
2325 * commands for each target are set from the commands of the 2329 * commands for each target are set from the commands of the
2326 * transformation rule used to get from the src suffix to the targ 2330 * transformation rule used to get from the src suffix to the targ
2327 * suffix. Note that this causes the commands list of the original 2331 * suffix. Note that this causes the commands list of the original
2328 * node, gn, to be replaced by the commands of the final 2332 * node, gn, to be replaced by the commands of the final
2329 * transformation rule. Also, the unmade field of gn is incremented. 2333 * transformation rule. Also, the unmade field of gn is incremented.
2330 * Etc. 2334 * Etc.
2331 */ 2335 */
2332 if (bottom->node == NULL) { 2336 if (bottom->node == NULL) {
2333 bottom->node = Targ_FindNode(bottom->file, TARG_CREATE); 2337 bottom->node = Targ_FindNode(bottom->file, TARG_CREATE);
2334 } 2338 }
2335 2339
2336 for (src = bottom; src->parent != NULL; src = src->parent) { 2340 for (src = bottom; src->parent != NULL; src = src->parent) {
2337 targ = src->parent; 2341 targ = src->parent;
2338 2342
2339 if (src->node->suffix) 2343 if (src->node->suffix)
2340 src->node->suffix->refCount--; 2344 src->node->suffix->refCount--;
2341 src->node->suffix = src->suff; 2345 src->node->suffix = src->suff;
2342 src->node->suffix->refCount++; 2346 src->node->suffix->refCount++;
2343 2347
2344 if (targ->node == NULL) { 2348 if (targ->node == NULL) {
2345 targ->node = Targ_FindNode(targ->file, TARG_CREATE); 2349 targ->node = Targ_FindNode(targ->file, TARG_CREATE);
2346 } 2350 }
2347 2351
2348 SuffApplyTransform(targ->node, src->node, 2352 SuffApplyTransform(targ->node, src->node,
2349 targ->suff, src->suff); 2353 targ->suff, src->suff);
2350 2354
2351 if (targ->node != gn) { 2355 if (targ->node != gn) {
2352 /* 2356 /*
2353 * Finish off the dependency-search process for any nodes 2357 * Finish off the dependency-search process for any nodes
2354 * between bottom and gn (no point in questing around the 2358 * between bottom and gn (no point in questing around the
2355 * filesystem for their implicit source when it's already 2359 * filesystem for their implicit source when it's already
2356 * known). Note that the node can't have any sources that 2360 * known). Note that the node can't have any sources that
2357 * need expanding, since SuffFindThem will stop on an existing 2361 * need expanding, since SuffFindThem will stop on an existing
2358 * node, so all we need to do is set the standard and System V 2362 * node, so all we need to do is set the standard and System V
2359 * variables. 2363 * variables.
2360 */ 2364 */
2361 targ->node->type |= OP_DEPS_FOUND; 2365 targ->node->type |= OP_DEPS_FOUND;
2362 2366
2363 Var_Set(PREFIX, targ->pref, targ->node); 2367 Var_Set(PREFIX, targ->pref, targ->node);
2364 2368
2365 Var_Set(TARGET, targ->node->name, targ->node); 2369 Var_Set(TARGET, targ->node->name, targ->node);
2366 } 2370 }
2367 } 2371 }
2368 2372
2369 if (gn->suffix) 2373 if (gn->suffix)
2370 gn->suffix->refCount--; 2374 gn->suffix->refCount--;
2371 gn->suffix = src->suff; 2375 gn->suffix = src->suff;
2372 gn->suffix->refCount++; 2376 gn->suffix->refCount++;
2373 2377
2374 /* 2378 /*
2375 * Nuke the transformation path and the Src structures left over in the 2379 * Nuke the transformation path and the Src structures left over in the
2376 * two lists. 2380 * two lists.
2377 */ 2381 */
2378sfnd_return: 2382sfnd_return:
2379 if (bottom) 2383 if (bottom)
2380 if (Lst_MemberS(slst, bottom) == NULL) 2384 if (Lst_MemberS(slst, bottom) == NULL)
2381 Lst_AppendS(slst, bottom); 2385 Lst_AppendS(slst, bottom);
2382 2386
2383 while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs)) 2387 while (SuffRemoveSrc(srcs) || SuffRemoveSrc(targs))
2384 continue; 2388 continue;
2385 2389
2386 Lst_MoveAllS(slst, srcs); 2390 Lst_MoveAllS(slst, srcs);
2387 Lst_MoveAllS(slst, targs); 2391 Lst_MoveAllS(slst, targs);
2388} 2392}
2389 2393
2390 2394
2391/*- 2395/*-
2392 *----------------------------------------------------------------------- 2396 *-----------------------------------------------------------------------
2393 * Suff_FindDeps -- 2397 * Suff_FindDeps --
2394 * Find implicit sources for the target described by the graph node 2398 * Find implicit sources for the target described by the graph node
2395 * gn 2399 * gn
2396 * 2400 *
2397 * Results: 2401 * Results:
2398 * Nothing. 2402 * Nothing.
2399 * 2403 *
2400 * Side Effects: 2404 * Side Effects:
2401 * Nodes are added to the graph below the passed-in node. The nodes 2405 * Nodes are added to the graph below the passed-in node. The nodes
2402 * are marked to have their IMPSRC variable filled in. The 2406 * are marked to have their IMPSRC variable filled in. The
2403 * PREFIX variable is set for the given node and all its 2407 * PREFIX variable is set for the given node and all its
2404 * implied children. 2408 * implied children.
2405 * 2409 *
2406 * Notes: 2410 * Notes:
2407 * The path found by this target is the shortest path in the 2411 * The path found by this target is the shortest path in the
2408 * transformation graph, which may pass through non-existent targets, 2412 * transformation graph, which may pass through non-existent targets,
2409 * to an existing target. The search continues on all paths from the 2413 * to an existing target. The search continues on all paths from the
2410 * root suffix until a file is found. I.e. if there's a path 2414 * root suffix until a file is found. I.e. if there's a path
2411 * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but 2415 * .o -> .c -> .l -> .l,v from the root and the .l,v file exists but
2412 * the .c and .l files don't, the search will branch out in 2416 * the .c and .l files don't, the search will branch out in
2413 * all directions from .o and again from all the nodes on the 2417 * all directions from .o and again from all the nodes on the
2414 * next level until the .l,v node is encountered. 2418 * next level until the .l,v node is encountered.
2415 * 2419 *
2416 *----------------------------------------------------------------------- 2420 *-----------------------------------------------------------------------
2417 */ 2421 */
2418 2422
2419void 2423void
2420Suff_FindDeps(GNode *gn) 2424Suff_FindDeps(GNode *gn)
2421{ 2425{
2422 2426
2423 SuffFindDeps(gn, srclist); 2427 SuffFindDeps(gn, srclist);
2424 while (SuffRemoveSrc(srclist)) 2428 while (SuffRemoveSrc(srclist))
2425 continue; 2429 continue;
2426} 2430}
2427 2431
2428 2432
2429/* 2433/*
2430 * Input: 2434 * Input:
2431 * gn node we're dealing with 2435 * gn node we're dealing with
2432 * 2436 *
2433 */ 2437 */
2434static void 2438static void
2435SuffFindDeps(GNode *gn, Lst slst) 2439SuffFindDeps(GNode *gn, Lst slst)
2436{ 2440{
2437 if (gn->type & OP_DEPS_FOUND) { 2441 if (gn->type & OP_DEPS_FOUND) {
2438 /* 2442 /*
2439 * If dependencies already found, no need to do it again... 2443 * If dependencies already found, no need to do it again...
2440 */ 2444 */
2441 return; 2445 return;
2442 } else { 2446 } else {
2443 gn->type |= OP_DEPS_FOUND; 2447 gn->type |= OP_DEPS_FOUND;
2444 } 2448 }
2445 /* 2449 /*
2446 * Make sure we have these set, may get revised below. 2450 * Make sure we have these set, may get revised below.
2447 */ 2451 */
2448 Var_Set(TARGET, gn->path ? gn->path : gn->name, gn); 2452 Var_Set(TARGET, gn->path ? gn->path : gn->name, gn);
2449 Var_Set(PREFIX, gn->name, gn); 2453 Var_Set(PREFIX, gn->name, gn);
2450 2454
2451 if (DEBUG(SUFF)) { 2455 if (DEBUG(SUFF)) {
2452 fprintf(debug_file, "SuffFindDeps (%s)\n", gn->name); 2456 fprintf(debug_file, "SuffFindDeps (%s)\n", gn->name);
2453 } 2457 }
2454 2458
2455 if (gn->type & OP_ARCHV) { 2459 if (gn->type & OP_ARCHV) {
2456 SuffFindArchiveDeps(gn, slst); 2460 SuffFindArchiveDeps(gn, slst);
2457 } else if (gn->type & OP_LIB) { 2461 } else if (gn->type & OP_LIB) {
2458 /* 2462 /*
2459 * If the node is a library, it is the arch module's job to find it 2463 * If the node is a library, it is the arch module's job to find it
2460 * and set the TARGET variable accordingly. We merely provide the 2464 * and set the TARGET variable accordingly. We merely provide the
2461 * search path, assuming all libraries end in ".a" (if the suffix 2465 * search path, assuming all libraries end in ".a" (if the suffix
2462 * hasn't been defined, there's nothing we can do for it, so we just 2466 * hasn't been defined, there's nothing we can do for it, so we just
2463 * set the TARGET variable to the node's name in order to give it a 2467 * set the TARGET variable to the node's name in order to give it a
2464 * value). 2468 * value).
2465 */ 2469 */
2466 LstNode ln; 2470 LstNode ln;
2467 Suff *s; 2471 Suff *s;
2468 2472
2469 ln = Lst_FindS(sufflist, SuffSuffHasNameP, LIBSUFF); 2473 ln = Lst_FindS(sufflist, SuffSuffHasNameP, LIBSUFF);
2470 if (gn->suffix) 2474 if (gn->suffix)
2471 gn->suffix->refCount--; 2475 gn->suffix->refCount--;
2472 if (ln != NULL) { 2476 if (ln != NULL) {
2473 gn->suffix = s = Lst_DatumS(ln); 2477 gn->suffix = s = Lst_DatumS(ln);
2474 gn->suffix->refCount++; 2478 gn->suffix->refCount++;
2475 Arch_FindLib(gn, s->searchPath); 2479 Arch_FindLib(gn, s->searchPath);
2476 } else { 2480 } else {
2477 gn->suffix = NULL; 2481 gn->suffix = NULL;
2478 Var_Set(TARGET, gn->name, gn); 2482 Var_Set(TARGET, gn->name, gn);
2479 } 2483 }
2480 /* 2484 /*
2481 * Because a library (-lfoo) target doesn't follow the standard 2485 * Because a library (-lfoo) target doesn't follow the standard
2482 * filesystem conventions, we don't set the regular variables for 2486 * filesystem conventions, we don't set the regular variables for
2483 * the thing. .PREFIX is simply made empty... 2487 * the thing. .PREFIX is simply made empty...
2484 */ 2488 */
2485 Var_Set(PREFIX, "", gn); 2489 Var_Set(PREFIX, "", gn);
2486 } else { 2490 } else {
2487 SuffFindNormalDeps(gn, slst); 2491 SuffFindNormalDeps(gn, slst);
2488 } 2492 }
2489} 2493}
2490 2494
2491/*- 2495/*-
2492 *----------------------------------------------------------------------- 2496 *-----------------------------------------------------------------------
2493 * Suff_SetNull -- 2497 * Suff_SetNull --
2494 * Define which suffix is the null suffix. 2498 * Define which suffix is the null suffix.
2495 * 2499 *
2496 * Input: 2500 * Input:
2497 * name Name of null suffix 2501 * name Name of null suffix
2498 * 2502 *
2499 * Results: 2503 * Results:
2500 * None. 2504 * None.
2501 * 2505 *
2502 * Side Effects: 2506 * Side Effects:
2503 * 'suffNull' is altered. 2507 * 'suffNull' is altered.
2504 * 2508 *
2505 * Notes: 2509 * Notes:
2506 * Need to handle the changing of the null suffix gracefully so the 2510 * Need to handle the changing of the null suffix gracefully so the
2507 * old transformation rules don't just go away. 2511 * old transformation rules don't just go away.
2508 * 2512 *
2509 *----------------------------------------------------------------------- 2513 *-----------------------------------------------------------------------
2510 */ 2514 */
2511void 2515void
2512Suff_SetNull(char *name) 2516Suff_SetNull(char *name)
2513{ 2517{
2514 Suff *s; 2518 Suff *s;
2515 LstNode ln; 2519 LstNode ln;
2516 2520
2517 ln = Lst_FindS(sufflist, SuffSuffHasNameP, name); 2521 ln = Lst_FindS(sufflist, SuffSuffHasNameP, name);
2518 if (ln != NULL) { 2522 if (ln != NULL) {
2519 s = Lst_DatumS(ln); 2523 s = Lst_DatumS(ln);
2520 if (suffNull != NULL) { 2524 if (suffNull != NULL) {
2521 suffNull->flags &= ~SUFF_NULL; 2525 suffNull->flags &= ~SUFF_NULL;
2522 } 2526 }
2523 s->flags |= SUFF_NULL; 2527 s->flags |= SUFF_NULL;
2524 /* 2528 /*
2525 * XXX: Here's where the transformation mangling would take place 2529 * XXX: Here's where the transformation mangling would take place
2526 */ 2530 */
2527 suffNull = s; 2531 suffNull = s;
2528 } else { 2532 } else {
2529 Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.", 2533 Parse_Error(PARSE_WARNING, "Desired null suffix %s not defined.",
2530 name); 2534 name);
2531 } 2535 }
2532} 2536}
2533 2537
2534/*- 2538/*-
2535 *----------------------------------------------------------------------- 2539 *-----------------------------------------------------------------------
2536 * Suff_Init -- 2540 * Suff_Init --
2537 * Initialize suffixes module 2541 * Initialize suffixes module
2538 * 2542 *
2539 * Results: 2543 * Results:
2540 * None 2544 * None
2541 * 2545 *
2542 * Side Effects: 2546 * Side Effects:
2543 * Many 2547 * Many
2544 *----------------------------------------------------------------------- 2548 *-----------------------------------------------------------------------
2545 */ 2549 */
2546void 2550void
2547Suff_Init(void) 2551Suff_Init(void)
2548{ 2552{
2549#ifdef CLEANUP 2553#ifdef CLEANUP
2550 suffClean = Lst_Init(); 2554 suffClean = Lst_Init();
2551 sufflist = Lst_Init(); 2555 sufflist = Lst_Init();
2552#endif 2556#endif
2553 srclist = Lst_Init(); 2557 srclist = Lst_Init();
2554 transforms = Lst_Init(); 2558 transforms = Lst_Init();
2555 2559
2556 /* 2560 /*
2557 * Create null suffix for single-suffix rules (POSIX). The thing doesn't 2561 * Create null suffix for single-suffix rules (POSIX). The thing doesn't
2558 * actually go on the suffix list or everyone will think that's its 2562 * actually go on the suffix list or everyone will think that's its
2559 * suffix. 2563 * suffix.
2560 */ 2564 */
2561 Suff_ClearSuffixes(); 2565 Suff_ClearSuffixes();
2562} 2566}
2563 2567
2564 2568
2565/*- 2569/*-
2566 *---------------------------------------------------------------------- 2570 *----------------------------------------------------------------------
2567 * Suff_End -- 2571 * Suff_End --
2568 * Cleanup the this module 2572 * Cleanup the this module
2569 * 2573 *
2570 * Results: 2574 * Results:
2571 * None 2575 * None
2572 * 2576 *
2573 * Side Effects: 2577 * Side Effects:
2574 * The memory is free'd. 2578 * The memory is free'd.
2575 *---------------------------------------------------------------------- 2579 *----------------------------------------------------------------------
2576 */ 2580 */
2577 2581
2578void 2582void
2579Suff_End(void) 2583Suff_End(void)
2580{ 2584{
2581#ifdef CLEANUP 2585#ifdef CLEANUP
2582 Lst_DestroyS(sufflist, SuffFree); 2586 Lst_DestroyS(sufflist, SuffFree);
2583 Lst_DestroyS(suffClean, SuffFree); 2587 Lst_DestroyS(suffClean, SuffFree);
2584 if (suffNull) 2588 if (suffNull)
2585 SuffFree(suffNull); 2589 SuffFree(suffNull);
2586 Lst_FreeS(srclist); 2590 Lst_FreeS(srclist);
2587 Lst_FreeS(transforms); 2591 Lst_FreeS(transforms);
2588#endif 2592#endif
2589} 2593}
2590 2594
2591 2595
2592/********************* DEBUGGING FUNCTIONS **********************/ 2596/********************* DEBUGGING FUNCTIONS **********************/
2593 2597
2594static int SuffPrintName(void *s, void *dummy MAKE_ATTR_UNUSED) 2598static int SuffPrintName(void *s, void *dummy MAKE_ATTR_UNUSED)
2595{ 2599{
2596 2600
2597 fprintf(debug_file, "%s ", ((Suff *)s)->name); 2601 fprintf(debug_file, "%s ", ((Suff *)s)->name);
2598 return 0; 2602 return 0;
2599} 2603}
2600 2604
2601static int 2605static int
2602SuffPrintSuff(void *sp, void *dummy MAKE_ATTR_UNUSED) 2606SuffPrintSuff(void *sp, void *dummy MAKE_ATTR_UNUSED)
2603{ 2607{
2604 Suff *s = (Suff *)sp; 2608 Suff *s = (Suff *)sp;
2605 int flags; 
2606 int flag; 
2607 2609
2608 fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount); 2610 fprintf(debug_file, "# `%s' [%d] ", s->name, s->refCount);
2609 2611
2610 flags = s->flags; 2612 if (s->flags != 0) {
2611 if (flags) { 2613 char flags_buf[SuffFlags_ToStringSize];
2612 fputs(" (", debug_file); 2614
2613 while (flags) { 2615 fprintf(debug_file, " (%s)",
2614 flag = 1 << (ffs(flags) - 1); 2616 Enum_FlagsToString(flags_buf, sizeof flags_buf,
2615 flags &= ~flag; 2617 s->flags, SuffFlags_ToStringSpecs));
2616 switch (flag) { 
2617 case SUFF_NULL: 
2618 fprintf(debug_file, "NULL"); 
2619 break; 
2620 case SUFF_INCLUDE: 
2621 fprintf(debug_file, "INCLUDE"); 
2622 break; 
2623 case SUFF_LIBRARY: 
2624 fprintf(debug_file, "LIBRARY"); 
2625 break; 
2626 } 
2627 fputc(flags ? '|' : ')', debug_file); 
2628 } 
2629 } 2618 }
2630 fputc('\n', debug_file); 2619 fputc('\n', debug_file);
2631 fprintf(debug_file, "#\tTo: "); 2620 fprintf(debug_file, "#\tTo: ");
2632 Lst_ForEachS(s->parents, SuffPrintName, NULL); 2621 Lst_ForEachS(s->parents, SuffPrintName, NULL);
2633 fputc('\n', debug_file); 2622 fputc('\n', debug_file);
2634 fprintf(debug_file, "#\tFrom: "); 2623 fprintf(debug_file, "#\tFrom: ");
2635 Lst_ForEachS(s->children, SuffPrintName, NULL); 2624 Lst_ForEachS(s->children, SuffPrintName, NULL);
2636 fputc('\n', debug_file); 2625 fputc('\n', debug_file);
2637 fprintf(debug_file, "#\tSearch Path: "); 2626 fprintf(debug_file, "#\tSearch Path: ");
2638 Dir_PrintPath(s->searchPath); 2627 Dir_PrintPath(s->searchPath);
2639 fputc('\n', debug_file); 2628 fputc('\n', debug_file);
2640 return 0; 2629 return 0;
2641} 2630}
2642 2631
2643static int 2632static int
2644SuffPrintTrans(void *tp, void *dummy MAKE_ATTR_UNUSED) 2633SuffPrintTrans(void *tp, void *dummy MAKE_ATTR_UNUSED)
2645{ 2634{
2646 GNode *t = (GNode *)tp; 2635 GNode *t = (GNode *)tp;
2647 2636
2648 fprintf(debug_file, "%-16s: ", t->name); 2637 fprintf(debug_file, "%-16s: ", t->name);
2649 Targ_PrintType(t->type); 2638 Targ_PrintType(t->type);
2650 fputc('\n', debug_file); 2639 fputc('\n', debug_file);
2651 Lst_ForEachS(t->commands, Targ_PrintCmd, NULL); 2640 Lst_ForEachS(t->commands, Targ_PrintCmd, NULL);
2652 fputc('\n', debug_file); 2641 fputc('\n', debug_file);
2653 return 0; 2642 return 0;
2654} 2643}
2655 2644
2656void 2645void
2657Suff_PrintAll(void) 2646Suff_PrintAll(void)
2658{ 2647{
2659 fprintf(debug_file, "#*** Suffixes:\n"); 2648 fprintf(debug_file, "#*** Suffixes:\n");
2660 Lst_ForEachS(sufflist, SuffPrintSuff, NULL); 2649 Lst_ForEachS(sufflist, SuffPrintSuff, NULL);
2661 2650
2662 fprintf(debug_file, "#*** Transformations:\n"); 2651 fprintf(debug_file, "#*** Transformations:\n");
2663 Lst_ForEachS(transforms, SuffPrintTrans, NULL); 2652 Lst_ForEachS(transforms, SuffPrintTrans, NULL);
2664} 2653}