Mon Aug 31 05:56:02 2020 UTC ()
make(1): fix unbalanced Lst_Open/Lst_Close in SuffFindCmds

This bug had been there since the initial import of make, on 1993-03-21.
It just never broke the build because of the missing assertion.

https://mail-index.netbsd.org/tech-toolchain/2020/08/30/msg003847.html

The error message "cd: can't cd to include" that I got when I first
applied the fix was unrelated.  It was caused by an extra directory
"include" in src/tools/compat that didn't belong there.  With that
directory removed, running "./build.sh -j8 tools" succeeds as expected.


(rillig)
diff -r1.59 -r1.60 src/usr.bin/make/lst.c
diff -r1.140 -r1.141 src/usr.bin/make/suff.c

cvs diff -r1.59 -r1.60 src/usr.bin/make/lst.c (switch to unified diff)

--- src/usr.bin/make/lst.c 2020/08/30 21:20:06 1.59
+++ src/usr.bin/make/lst.c 2020/08/31 05:56:02 1.60
@@ -1,638 +1,633 @@ @@ -1,638 +1,633 @@
1/* $NetBSD: lst.c,v 1.59 2020/08/30 21:20:06 rillig Exp $ */ 1/* $NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35#include <stdint.h> 35#include <stdint.h>
36 36
37#include "make.h" 37#include "make.h"
38 38
39#ifndef MAKE_NATIVE 39#ifndef MAKE_NATIVE
40static char rcsid[] = "$NetBSD: lst.c,v 1.59 2020/08/30 21:20:06 rillig Exp $"; 40static char rcsid[] = "$NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 rillig Exp $";
41#else 41#else
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43#ifndef lint 43#ifndef lint
44__RCSID("$NetBSD: lst.c,v 1.59 2020/08/30 21:20:06 rillig Exp $"); 44__RCSID("$NetBSD: lst.c,v 1.60 2020/08/31 05:56:02 rillig Exp $");
45#endif /* not lint */ 45#endif /* not lint */
46#endif 46#endif
47 47
48struct ListNode { 48struct ListNode {
49 struct ListNode *prev; /* previous element in list */ 49 struct ListNode *prev; /* previous element in list */
50 struct ListNode *next; /* next in list */ 50 struct ListNode *next; /* next in list */
51 uint8_t useCount; /* Count of functions using the node. 51 uint8_t useCount; /* Count of functions using the node.
52 * node may not be deleted until count 52 * node may not be deleted until count
53 * goes to 0 */ 53 * goes to 0 */
54 Boolean deleted; /* List node should be removed when done */ 54 Boolean deleted; /* List node should be removed when done */
55 union { 55 union {
56 void *datum; /* datum associated with this element */ 56 void *datum; /* datum associated with this element */
57 const GNode *gnode; /* alias, just for debugging */ 57 const GNode *gnode; /* alias, just for debugging */
58 const char *str; /* alias, just for debugging */ 58 const char *str; /* alias, just for debugging */
59 }; 59 };
60}; 60};
61 61
62typedef enum { 62typedef enum {
63 Head, Middle, Tail, Unknown 63 Head, Middle, Tail, Unknown
64} Where; 64} Where;
65 65
66struct List { 66struct List {
67 LstNode first; /* first node in list */ 67 LstNode first; /* first node in list */
68 LstNode last; /* last node in list */ 68 LstNode last; /* last node in list */
69 69
70 /* fields for sequential access */ 70 /* fields for sequential access */
71 Boolean isOpen; /* true if list has been Lst_Open'ed */ 71 Boolean isOpen; /* true if list has been Lst_Open'ed */
72 Where lastAccess; /* Where in the list the last access was */ 72 Where lastAccess; /* Where in the list the last access was */
73 LstNode curr; /* current node, if open. NULL if 73 LstNode curr; /* current node, if open. NULL if
74 * *just* opened */ 74 * *just* opened */
75 LstNode prev; /* Previous node, if open. Used by Lst_Remove */ 75 LstNode prev; /* Previous node, if open. Used by Lst_Remove */
76}; 76};
77 77
78/* Allocate and initialize a list node. 78/* Allocate and initialize a list node.
79 * 79 *
80 * The fields 'prev' and 'next' must be initialized by the caller. 80 * The fields 'prev' and 'next' must be initialized by the caller.
81 */ 81 */
82static LstNode 82static LstNode
83LstNodeNew(void *datum) 83LstNodeNew(void *datum)
84{ 84{
85 LstNode node = bmake_malloc(sizeof *node); 85 LstNode node = bmake_malloc(sizeof *node);
86 node->useCount = 0; 86 node->useCount = 0;
87 node->deleted = FALSE; 87 node->deleted = FALSE;
88 node->datum = datum; 88 node->datum = datum;
89 return node; 89 return node;
90} 90}
91 91
92static Boolean 92static Boolean
93LstIsEmpty(Lst list) 93LstIsEmpty(Lst list)
94{ 94{
95 return list->first == NULL; 95 return list->first == NULL;
96} 96}
97 97
98/* Create and initialize a new, empty list. */ 98/* Create and initialize a new, empty list. */
99Lst 99Lst
100Lst_Init(void) 100Lst_Init(void)
101{ 101{
102 Lst list = bmake_malloc(sizeof *list); 102 Lst list = bmake_malloc(sizeof *list);
103 103
104 list->first = NULL; 104 list->first = NULL;
105 list->last = NULL; 105 list->last = NULL;
106 list->isOpen = FALSE; 106 list->isOpen = FALSE;
107 list->lastAccess = Unknown; 107 list->lastAccess = Unknown;
108 108
109 return list; 109 return list;
110} 110}
111 111
112/* Duplicate an entire list, usually by copying the datum pointers. 112/* Duplicate an entire list, usually by copying the datum pointers.
113 * If copyProc is given, that function is used to create the new datum from the 113 * If copyProc is given, that function is used to create the new datum from the
114 * old datum, usually by creating a copy of it. */ 114 * old datum, usually by creating a copy of it. */
115Lst 115Lst
116Lst_Copy(Lst list, LstCopyProc copyProc) 116Lst_Copy(Lst list, LstCopyProc copyProc)
117{ 117{
118 Lst newList; 118 Lst newList;
119 LstNode node; 119 LstNode node;
120 120
121 assert(list != NULL); 121 assert(list != NULL);
122 122
123 newList = Lst_Init(); 123 newList = Lst_Init();
124 124
125 for (node = list->first; node != NULL; node = node->next) { 125 for (node = list->first; node != NULL; node = node->next) {
126 void *datum = copyProc != NULL ? copyProc(node->datum) : node->datum; 126 void *datum = copyProc != NULL ? copyProc(node->datum) : node->datum;
127 Lst_Append(newList, datum); 127 Lst_Append(newList, datum);
128 } 128 }
129 129
130 return newList; 130 return newList;
131} 131}
132 132
133/* Free a list and all its nodes. The list data itself are not freed though. */ 133/* Free a list and all its nodes. The list data itself are not freed though. */
134void 134void
135Lst_Free(Lst list) 135Lst_Free(Lst list)
136{ 136{
137 LstNode node; 137 LstNode node;
138 LstNode next; 138 LstNode next;
139 139
140 assert(list != NULL); 140 assert(list != NULL);
141 141
142 for (node = list->first; node != NULL; node = next) { 142 for (node = list->first; node != NULL; node = next) {
143 next = node->next; 143 next = node->next;
144 free(node); 144 free(node);
145 } 145 }
146 146
147 free(list); 147 free(list);
148} 148}
149 149
150/* Destroy a list and free all its resources. The freeProc is called with the 150/* Destroy a list and free all its resources. The freeProc is called with the
151 * datum from each node in turn before the node is freed. */ 151 * datum from each node in turn before the node is freed. */
152void 152void
153Lst_Destroy(Lst list, LstFreeProc freeProc) 153Lst_Destroy(Lst list, LstFreeProc freeProc)
154{ 154{
155 LstNode node; 155 LstNode node;
156 LstNode next; 156 LstNode next;
157 157
158 assert(list != NULL); 158 assert(list != NULL);
159 assert(freeProc != NULL); 159 assert(freeProc != NULL);
160 160
161 for (node = list->first; node != NULL; node = next) { 161 for (node = list->first; node != NULL; node = next) {
162 next = node->next; 162 next = node->next;
163 freeProc(node->datum); 163 freeProc(node->datum);
164 free(node); 164 free(node);
165 } 165 }
166 166
167 free(list); 167 free(list);
168} 168}
169 169
170/* 170/*
171 * Functions to modify a list 171 * Functions to modify a list
172 */ 172 */
173 173
174/* Insert a new node with the given piece of data before the given node in the 174/* Insert a new node with the given piece of data before the given node in the
175 * given list. */ 175 * given list. */
176void 176void
177Lst_InsertBefore(Lst list, LstNode node, void *datum) 177Lst_InsertBefore(Lst list, LstNode node, void *datum)
178{ 178{
179 LstNode newNode; 179 LstNode newNode;
180 180
181 assert(list != NULL); 181 assert(list != NULL);
182 assert(!LstIsEmpty(list)); 182 assert(!LstIsEmpty(list));
183 assert(node != NULL); 183 assert(node != NULL);
184 assert(datum != NULL); 184 assert(datum != NULL);
185 185
186 newNode = LstNodeNew(datum); 186 newNode = LstNodeNew(datum);
187 newNode->prev = node->prev; 187 newNode->prev = node->prev;
188 newNode->next = node; 188 newNode->next = node;
189 189
190 if (node->prev != NULL) { 190 if (node->prev != NULL) {
191 node->prev->next = newNode; 191 node->prev->next = newNode;
192 } 192 }
193 node->prev = newNode; 193 node->prev = newNode;
194 194
195 if (node == list->first) { 195 if (node == list->first) {
196 list->first = newNode; 196 list->first = newNode;
197 } 197 }
198} 198}
199 199
200/* Add a piece of data at the start of the given list. */ 200/* Add a piece of data at the start of the given list. */
201void 201void
202Lst_Prepend(Lst list, void *datum) 202Lst_Prepend(Lst list, void *datum)
203{ 203{
204 LstNode node; 204 LstNode node;
205 205
206 assert(list != NULL); 206 assert(list != NULL);
207 assert(datum != NULL); 207 assert(datum != NULL);
208 208
209 node = LstNodeNew(datum); 209 node = LstNodeNew(datum);
210 node->prev = NULL; 210 node->prev = NULL;
211 node->next = list->first; 211 node->next = list->first;
212 212
213 if (list->first == NULL) { 213 if (list->first == NULL) {
214 list->first = node; 214 list->first = node;
215 list->last = node; 215 list->last = node;
216 } else { 216 } else {
217 list->first->prev = node; 217 list->first->prev = node;
218 list->first = node; 218 list->first = node;
219 } 219 }
220} 220}
221 221
222/* Add a piece of data at the end of the given list. */ 222/* Add a piece of data at the end of the given list. */
223void 223void
224Lst_Append(Lst list, void *datum) 224Lst_Append(Lst list, void *datum)
225{ 225{
226 LstNode node; 226 LstNode node;
227 227
228 assert(list != NULL); 228 assert(list != NULL);
229 assert(datum != NULL); 229 assert(datum != NULL);
230 230
231 node = LstNodeNew(datum); 231 node = LstNodeNew(datum);
232 node->prev = list->last; 232 node->prev = list->last;
233 node->next = NULL; 233 node->next = NULL;
234 234
235 if (list->last == NULL) { 235 if (list->last == NULL) {
236 list->first = node; 236 list->first = node;
237 list->last = node; 237 list->last = node;
238 } else { 238 } else {
239 list->last->next = node; 239 list->last->next = node;
240 list->last = node; 240 list->last = node;
241 } 241 }
242} 242}
243 243
244/* Remove the given node from the given list. 244/* Remove the given node from the given list.
245 * The datum stored in the node must be freed by the caller, if necessary. */ 245 * The datum stored in the node must be freed by the caller, if necessary. */
246void 246void
247Lst_Remove(Lst list, LstNode node) 247Lst_Remove(Lst list, LstNode node)
248{ 248{
249 assert(list != NULL); 249 assert(list != NULL);
250 assert(node != NULL); 250 assert(node != NULL);
251 251
252 /* 252 /*
253 * unlink it from the list 253 * unlink it from the list
254 */ 254 */
255 if (node->next != NULL) { 255 if (node->next != NULL) {
256 node->next->prev = node->prev; 256 node->next->prev = node->prev;
257 } 257 }
258 if (node->prev != NULL) { 258 if (node->prev != NULL) {
259 node->prev->next = node->next; 259 node->prev->next = node->next;
260 } 260 }
261 261
262 /* 262 /*
263 * if either the first or last of the list point to this node, 263 * if either the first or last of the list point to this node,
264 * adjust them accordingly 264 * adjust them accordingly
265 */ 265 */
266 if (list->first == node) { 266 if (list->first == node) {
267 list->first = node->next; 267 list->first = node->next;
268 } 268 }
269 if (list->last == node) { 269 if (list->last == node) {
270 list->last = node->prev; 270 list->last = node->prev;
271 } 271 }
272 272
273 /* 273 /*
274 * Sequential access stuff. If the node we're removing is the current 274 * Sequential access stuff. If the node we're removing is the current
275 * node in the list, reset the current node to the previous one. If the 275 * node in the list, reset the current node to the previous one. If the
276 * previous one was non-existent (prev == NULL), we set the 276 * previous one was non-existent (prev == NULL), we set the
277 * end to be Unknown, since it is. 277 * end to be Unknown, since it is.
278 */ 278 */
279 if (list->isOpen && list->curr == node) { 279 if (list->isOpen && list->curr == node) {
280 list->curr = list->prev; 280 list->curr = list->prev;
281 if (list->curr == NULL) { 281 if (list->curr == NULL) {
282 list->lastAccess = Unknown; 282 list->lastAccess = Unknown;
283 } 283 }
284 } 284 }
285 285
286 /* 286 /*
287 * note that the datum is unmolested. The caller must free it as 287 * note that the datum is unmolested. The caller must free it as
288 * necessary and as expected. 288 * necessary and as expected.
289 */ 289 */
290 if (node->useCount == 0) { 290 if (node->useCount == 0) {
291 free(node); 291 free(node);
292 } else { 292 } else {
293 node->deleted = TRUE; 293 node->deleted = TRUE;
294 } 294 }
295} 295}
296 296
297/* Replace the datum in the given node with the new datum. */ 297/* Replace the datum in the given node with the new datum. */
298void 298void
299LstNode_Set(LstNode node, void *datum) 299LstNode_Set(LstNode node, void *datum)
300{ 300{
301 assert(node != NULL); 301 assert(node != NULL);
302 assert(datum != NULL); 302 assert(datum != NULL);
303 303
304 node->datum = datum; 304 node->datum = datum;
305} 305}
306 306
307/* Replace the datum in the given node to NULL. */ 307/* Replace the datum in the given node to NULL. */
308void 308void
309LstNode_SetNull(LstNode node) 309LstNode_SetNull(LstNode node)
310{ 310{
311 assert(node != NULL); 311 assert(node != NULL);
312 312
313 node->datum = NULL; 313 node->datum = NULL;
314} 314}
315 315
316 316
317/* 317/*
318 * Node-specific functions 318 * Node-specific functions
319 */ 319 */
320 320
321/* Return the first node from the given list, or NULL if the list is empty. */ 321/* Return the first node from the given list, or NULL if the list is empty. */
322LstNode 322LstNode
323Lst_First(Lst list) 323Lst_First(Lst list)
324{ 324{
325 assert(list != NULL); 325 assert(list != NULL);
326 326
327 return list->first; 327 return list->first;
328} 328}
329 329
330/* Return the last node from the given list, or NULL if the list is empty. */ 330/* Return the last node from the given list, or NULL if the list is empty. */
331LstNode 331LstNode
332Lst_Last(Lst list) 332Lst_Last(Lst list)
333{ 333{
334 assert(list != NULL); 334 assert(list != NULL);
335 335
336 return list->last; 336 return list->last;
337} 337}
338 338
339/* Return the successor to the given node on its list, or NULL. */ 339/* Return the successor to the given node on its list, or NULL. */
340LstNode 340LstNode
341LstNode_Next(LstNode node) 341LstNode_Next(LstNode node)
342{ 342{
343 assert(node != NULL); 343 assert(node != NULL);
344 344
345 return node->next; 345 return node->next;
346} 346}
347 347
348/* Return the predecessor to the given node on its list, or NULL. */ 348/* Return the predecessor to the given node on its list, or NULL. */
349LstNode 349LstNode
350LstNode_Prev(LstNode node) 350LstNode_Prev(LstNode node)
351{ 351{
352 assert(node != NULL); 352 assert(node != NULL);
353 return node->prev; 353 return node->prev;
354} 354}
355 355
356/* Return the datum stored in the given node. */ 356/* Return the datum stored in the given node. */
357void * 357void *
358LstNode_Datum(LstNode node) 358LstNode_Datum(LstNode node)
359{ 359{
360 assert(node != NULL); 360 assert(node != NULL);
361 return node->datum; 361 return node->datum;
362} 362}
363 363
364 364
365/* 365/*
366 * Functions for entire lists 366 * Functions for entire lists
367 */ 367 */
368 368
369/* Return TRUE if the given list is empty. */ 369/* Return TRUE if the given list is empty. */
370Boolean 370Boolean
371Lst_IsEmpty(Lst list) 371Lst_IsEmpty(Lst list)
372{ 372{
373 assert(list != NULL); 373 assert(list != NULL);
374 374
375 return LstIsEmpty(list); 375 return LstIsEmpty(list);
376} 376}
377 377
378/* Return the first node from the list for which the match function returns 378/* Return the first node from the list for which the match function returns
379 * TRUE, or NULL if none of the nodes matched. */ 379 * TRUE, or NULL if none of the nodes matched. */
380LstNode 380LstNode
381Lst_Find(Lst list, LstFindProc match, const void *matchArgs) 381Lst_Find(Lst list, LstFindProc match, const void *matchArgs)
382{ 382{
383 return Lst_FindFrom(list, Lst_First(list), match, matchArgs); 383 return Lst_FindFrom(list, Lst_First(list), match, matchArgs);
384} 384}
385 385
386/* Return the first node from the list, starting at the given node, for which 386/* Return the first node from the list, starting at the given node, for which
387 * the match function returns TRUE, or NULL if none of the nodes matches. 387 * the match function returns TRUE, or NULL if none of the nodes matches.
388 * 388 *
389 * The start node may be NULL, in which case nothing is found. This allows 389 * The start node may be NULL, in which case nothing is found. This allows
390 * for passing Lst_First or LstNode_Next as the start node. */ 390 * for passing Lst_First or LstNode_Next as the start node. */
391LstNode 391LstNode
392Lst_FindFrom(Lst list, LstNode node, LstFindProc match, const void *matchArgs) 392Lst_FindFrom(Lst list, LstNode node, LstFindProc match, const void *matchArgs)
393{ 393{
394 LstNode tln; 394 LstNode tln;
395 395
396 assert(list != NULL); 396 assert(list != NULL);
397 assert(match != NULL); 397 assert(match != NULL);
398 398
399 for (tln = node; tln != NULL; tln = tln->next) { 399 for (tln = node; tln != NULL; tln = tln->next) {
400 if (match(tln->datum, matchArgs)) 400 if (match(tln->datum, matchArgs))
401 return tln; 401 return tln;
402 } 402 }
403 403
404 return NULL; 404 return NULL;
405} 405}
406 406
407/* Return the first node that contains the given datum, or NULL. */ 407/* Return the first node that contains the given datum, or NULL. */
408LstNode 408LstNode
409Lst_FindDatum(Lst list, const void *datum) 409Lst_FindDatum(Lst list, const void *datum)
410{ 410{
411 LstNode node; 411 LstNode node;
412 412
413 assert(list != NULL); 413 assert(list != NULL);
414 assert(datum != NULL); 414 assert(datum != NULL);
415 415
416 for (node = list->first; node != NULL; node = node->next) { 416 for (node = list->first; node != NULL; node = node->next) {
417 if (node->datum == datum) { 417 if (node->datum == datum) {
418 return node; 418 return node;
419 } 419 }
420 } 420 }
421 421
422 return NULL; 422 return NULL;
423} 423}
424 424
425/* Apply the given function to each element of the given list. The function 425/* Apply the given function to each element of the given list. The function
426 * should return 0 if traversal should continue and non-zero if it should 426 * should return 0 if traversal should continue and non-zero if it should
427 * abort. */ 427 * abort. */
428int 428int
429Lst_ForEach(Lst list, LstActionProc proc, void *procData) 429Lst_ForEach(Lst list, LstActionProc proc, void *procData)
430{ 430{
431 if (LstIsEmpty(list)) 431 if (LstIsEmpty(list))
432 return 0; /* XXX: Document what this value means. */ 432 return 0; /* XXX: Document what this value means. */
433 return Lst_ForEachFrom(list, Lst_First(list), proc, procData); 433 return Lst_ForEachFrom(list, Lst_First(list), proc, procData);
434} 434}
435 435
436/* Apply the given function to each element of the given list, starting from 436/* Apply the given function to each element of the given list, starting from
437 * the given node. The function should return 0 if traversal should continue, 437 * the given node. The function should return 0 if traversal should continue,
438 * and non-zero if it should abort. */ 438 * and non-zero if it should abort. */
439int 439int
440Lst_ForEachFrom(Lst list, LstNode node, 440Lst_ForEachFrom(Lst list, LstNode node,
441 LstActionProc proc, void *procData) 441 LstActionProc proc, void *procData)
442{ 442{
443 LstNode tln = node; 443 LstNode tln = node;
444 LstNode next; 444 LstNode next;
445 Boolean done; 445 Boolean done;
446 int result; 446 int result;
447 447
448 assert(list != NULL); 448 assert(list != NULL);
449 assert(node != NULL); 449 assert(node != NULL);
450 assert(proc != NULL); 450 assert(proc != NULL);
451 451
452 do { 452 do {
453 /* 453 /*
454 * Take care of having the current element deleted out from under 454 * Take care of having the current element deleted out from under
455 * us. 455 * us.
456 */ 456 */
457 457
458 next = tln->next; 458 next = tln->next;
459 459
460 /* 460 /*
461 * We're done with the traversal if 461 * We're done with the traversal if
462 * - the next node to examine doesn't exist and 462 * - the next node to examine doesn't exist and
463 * - nothing's been added after the current node (check this 463 * - nothing's been added after the current node (check this
464 * after proc() has been called). 464 * after proc() has been called).
465 */ 465 */
466 done = next == NULL; 466 done = next == NULL;
467 467
468 tln->useCount++; 468 tln->useCount++;
469 result = (*proc)(tln->datum, procData); 469 result = (*proc)(tln->datum, procData);
470 tln->useCount--; 470 tln->useCount--;
471 471
472 /* 472 /*
473 * Now check whether a node has been added. 473 * Now check whether a node has been added.
474 * Note: this doesn't work if this node was deleted before 474 * Note: this doesn't work if this node was deleted before
475 * the new node was added. 475 * the new node was added.
476 */ 476 */
477 if (next != tln->next) { 477 if (next != tln->next) {
478 next = tln->next; 478 next = tln->next;
479 done = 0; 479 done = 0;
480 } 480 }
481 481
482 if (tln->deleted) { 482 if (tln->deleted) {
483 free((char *)tln); 483 free((char *)tln);
484 } 484 }
485 tln = next; 485 tln = next;
486 } while (!result && !LstIsEmpty(list) && !done); 486 } while (!result && !LstIsEmpty(list) && !done);
487 487
488 return result; 488 return result;
489} 489}
490 490
491/* Move all nodes from list2 to the end of list1. 491/* Move all nodes from list2 to the end of list1.
492 * List2 is destroyed and freed. */ 492 * List2 is destroyed and freed. */
493void 493void
494Lst_MoveAll(Lst list1, Lst list2) 494Lst_MoveAll(Lst list1, Lst list2)
495{ 495{
496 assert(list1 != NULL); 496 assert(list1 != NULL);
497 assert(list2 != NULL); 497 assert(list2 != NULL);
498 498
499 if (list2->first != NULL) { 499 if (list2->first != NULL) {
500 list2->first->prev = list1->last; 500 list2->first->prev = list1->last;
501 if (list1->last != NULL) { 501 if (list1->last != NULL) {
502 list1->last->next = list2->first; 502 list1->last->next = list2->first;
503 } else { 503 } else {
504 list1->first = list2->first; 504 list1->first = list2->first;
505 } 505 }
506 list1->last = list2->last; 506 list1->last = list2->last;
507 } 507 }
508 free(list2); 508 free(list2);
509} 509}
510 510
511/* Copy the element data from src to the start of dst. */ 511/* Copy the element data from src to the start of dst. */
512void 512void
513Lst_PrependAll(Lst dst, Lst src) 513Lst_PrependAll(Lst dst, Lst src)
514{ 514{
515 LstNode node; 515 LstNode node;
516 for (node = src->last; node != NULL; node = node->prev) 516 for (node = src->last; node != NULL; node = node->prev)
517 Lst_Prepend(dst, node->datum); 517 Lst_Prepend(dst, node->datum);
518} 518}
519 519
520/* Copy the element data from src to the end of dst. */ 520/* Copy the element data from src to the end of dst. */
521void 521void
522Lst_AppendAll(Lst dst, Lst src) 522Lst_AppendAll(Lst dst, Lst src)
523{ 523{
524 LstNode node; 524 LstNode node;
525 for (node = src->first; node != NULL; node = node->next) 525 for (node = src->first; node != NULL; node = node->next)
526 Lst_Append(dst, node->datum); 526 Lst_Append(dst, node->datum);
527} 527}
528 528
529/* 529/*
530 * these functions are for dealing with a list as a table, of sorts. 530 * these functions are for dealing with a list as a table, of sorts.
531 * An idea of the "current element" is kept and used by all the functions 531 * An idea of the "current element" is kept and used by all the functions
532 * between Lst_Open() and Lst_Close(). 532 * between Lst_Open() and Lst_Close().
533 * 533 *
534 * The sequential functions access the list in a slightly different way. 534 * The sequential functions access the list in a slightly different way.
535 * CurPtr points to their idea of the current node in the list and they 535 * CurPtr points to their idea of the current node in the list and they
536 * access the list based on it. 536 * access the list based on it.
537 */ 537 */
538 538
539/* Open a list for sequential access. A list can still be searched, etc., 539/* Open a list for sequential access. A list can still be searched, etc.,
540 * without confusing these functions. */ 540 * without confusing these functions. */
541void 541void
542Lst_Open(Lst list) 542Lst_Open(Lst list)
543{ 543{
544 assert(list != NULL); 544 assert(list != NULL);
545 545 assert(!list->isOpen);
546 /* XXX: This assertion fails for NetBSD's "build.sh -j1 tools", somewhere 
547 * between "dependall ===> compat" and "dependall ===> binstall". 
548 * Building without the "-j1" succeeds though. */ 
549 if (DEBUG(LINT) && list->isOpen) 
550 Parse_Error(PARSE_WARNING, "Internal inconsistency: list opened twice"); 
551 546
552 list->isOpen = TRUE; 547 list->isOpen = TRUE;
553 list->lastAccess = LstIsEmpty(list) ? Head : Unknown; 548 list->lastAccess = LstIsEmpty(list) ? Head : Unknown;
554 list->curr = NULL; 549 list->curr = NULL;
555} 550}
556 551
557/* Return the next node for the given list, or NULL if the end has been 552/* Return the next node for the given list, or NULL if the end has been
558 * reached. */ 553 * reached. */
559LstNode 554LstNode
560Lst_Next(Lst list) 555Lst_Next(Lst list)
561{ 556{
562 LstNode node; 557 LstNode node;
563 558
564 assert(list != NULL); 559 assert(list != NULL);
565 assert(list->isOpen); 560 assert(list->isOpen);
566 561
567 list->prev = list->curr; 562 list->prev = list->curr;
568 563
569 if (list->curr == NULL) { 564 if (list->curr == NULL) {
570 if (list->lastAccess == Unknown) { 565 if (list->lastAccess == Unknown) {
571 /* 566 /*
572 * If we're just starting out, lastAccess will be Unknown. 567 * If we're just starting out, lastAccess will be Unknown.
573 * Then we want to start this thing off in the right 568 * Then we want to start this thing off in the right
574 * direction -- at the start with lastAccess being Middle. 569 * direction -- at the start with lastAccess being Middle.
575 */ 570 */
576 list->curr = node = list->first; 571 list->curr = node = list->first;
577 list->lastAccess = Middle; 572 list->lastAccess = Middle;
578 } else { 573 } else {
579 node = NULL; 574 node = NULL;
580 list->lastAccess = Tail; 575 list->lastAccess = Tail;
581 } 576 }
582 } else { 577 } else {
583 node = list->curr->next; 578 node = list->curr->next;
584 list->curr = node; 579 list->curr = node;
585 580
586 if (node == list->first || node == NULL) { 581 if (node == list->first || node == NULL) {
587 /* 582 /*
588 * If back at the front, then we've hit the end... 583 * If back at the front, then we've hit the end...
589 */ 584 */
590 list->lastAccess = Tail; 585 list->lastAccess = Tail;
591 } else { 586 } else {
592 /* 587 /*
593 * Reset to Middle if gone past first. 588 * Reset to Middle if gone past first.
594 */ 589 */
595 list->lastAccess = Middle; 590 list->lastAccess = Middle;
596 } 591 }
597 } 592 }
598 593
599 return node; 594 return node;
600} 595}
601 596
602/* Close a list which was opened for sequential access. */ 597/* Close a list which was opened for sequential access. */
603void 598void
604Lst_Close(Lst list) 599Lst_Close(Lst list)
605{ 600{
606 assert(list != NULL); 601 assert(list != NULL);
607 assert(list->isOpen); 602 assert(list->isOpen);
608 603
609 list->isOpen = FALSE; 604 list->isOpen = FALSE;
610 list->lastAccess = Unknown; 605 list->lastAccess = Unknown;
611} 606}
612 607
613 608
614/* 609/*
615 * for using the list as a queue 610 * for using the list as a queue
616 */ 611 */
617 612
618/* Add the datum to the tail of the given list. */ 613/* Add the datum to the tail of the given list. */
619void 614void
620Lst_Enqueue(Lst list, void *datum) 615Lst_Enqueue(Lst list, void *datum)
621{ 616{
622 Lst_Append(list, datum); 617 Lst_Append(list, datum);
623} 618}
624 619
625/* Remove and return the datum at the head of the given list. */ 620/* Remove and return the datum at the head of the given list. */
626void * 621void *
627Lst_Dequeue(Lst list) 622Lst_Dequeue(Lst list)
628{ 623{
629 void *datum; 624 void *datum;
630 625
631 assert(list != NULL); 626 assert(list != NULL);
632 assert(!LstIsEmpty(list)); 627 assert(!LstIsEmpty(list));
633 628
634 datum = list->first->datum; 629 datum = list->first->datum;
635 Lst_Remove(list, list->first); 630 Lst_Remove(list, list->first);
636 assert(datum != NULL); 631 assert(datum != NULL);
637 return datum; 632 return datum;
638} 633}

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

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