Sun Dec 27 18:22:28 2020 UTC ()
make(1): skip variable expansion in ParseDependencyTargetWord

The goal of the code is just to skip over the variable expression, thus
there is no need to evaluate it.


(rillig)
diff -r1.518 -r1.519 src/usr.bin/make/parse.c

cvs diff -r1.518 -r1.519 src/usr.bin/make/parse.c (switch to unified diff)

--- src/usr.bin/make/parse.c 2020/12/27 11:47:04 1.518
+++ src/usr.bin/make/parse.c 2020/12/27 18:22:28 1.519
@@ -1,2088 +1,2087 @@ @@ -1,2088 +1,2087 @@
1/* $NetBSD: parse.c,v 1.518 2020/12/27 11:47:04 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.519 2020/12/27 18:22:28 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/* 71/*
72 * Parsing of makefiles. 72 * Parsing of makefiles.
73 * 73 *
74 * Parse_File is the main entry point and controls most of the other 74 * Parse_File is the main entry point and controls most of the other
75 * functions in this module. 75 * functions in this module.
76 * 76 *
77 * The directories for the .include "..." directive are kept in 77 * The directories for the .include "..." directive are kept in
78 * 'parseIncPath', while those for .include <...> are kept in 'sysIncPath'. 78 * 'parseIncPath', while those for .include <...> are kept in 'sysIncPath'.
79 * The targets currently being defined are kept in 'targets'. 79 * The targets currently being defined are kept in 'targets'.
80 * 80 *
81 * Interface: 81 * Interface:
82 * Parse_Init Initialize the module 82 * Parse_Init Initialize the module
83 * 83 *
84 * Parse_End Clean up the module 84 * Parse_End Clean up the module
85 * 85 *
86 * Parse_File Parse a top-level makefile. Included files are 86 * Parse_File Parse a top-level makefile. Included files are
87 * handled by Parse_include_file though. 87 * handled by Parse_include_file though.
88 * 88 *
89 * Parse_IsVar Return TRUE if the given line is a variable 89 * Parse_IsVar Return TRUE if the given line is a variable
90 * assignment. Used by MainParseArgs to determine if 90 * assignment. Used by MainParseArgs to determine if
91 * an argument is a target or a variable assignment. 91 * an argument is a target or a variable assignment.
92 * Used internally for pretty much the same thing. 92 * Used internally for pretty much the same thing.
93 * 93 *
94 * Parse_Error Report a parse error, a warning or an informational 94 * Parse_Error Report a parse error, a warning or an informational
95 * message. 95 * message.
96 * 96 *
97 * Parse_MainName Returns a list of the main target to create. 97 * Parse_MainName Returns a list of the main target to create.
98 */ 98 */
99 99
100#include <sys/types.h> 100#include <sys/types.h>
101#include <sys/mman.h> 101#include <sys/mman.h>
102#include <sys/stat.h> 102#include <sys/stat.h>
103#include <errno.h> 103#include <errno.h>
104#include <stdarg.h> 104#include <stdarg.h>
105#include <stdint.h> 105#include <stdint.h>
106 106
107#ifndef MAP_FILE 107#ifndef MAP_FILE
108#define MAP_FILE 0 108#define MAP_FILE 0
109#endif 109#endif
110#ifndef MAP_COPY 110#ifndef MAP_COPY
111#define MAP_COPY MAP_PRIVATE 111#define MAP_COPY MAP_PRIVATE
112#endif 112#endif
113 113
114#include "make.h" 114#include "make.h"
115#include "dir.h" 115#include "dir.h"
116#include "job.h" 116#include "job.h"
117#include "pathnames.h" 117#include "pathnames.h"
118 118
119/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */ 119/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
120MAKE_RCSID("$NetBSD: parse.c,v 1.518 2020/12/27 11:47:04 rillig Exp $"); 120MAKE_RCSID("$NetBSD: parse.c,v 1.519 2020/12/27 18:22:28 rillig Exp $");
121 121
122/* types and constants */ 122/* types and constants */
123 123
124/* 124/*
125 * Structure for a file being read ("included file") 125 * Structure for a file being read ("included file")
126 */ 126 */
127typedef struct IFile { 127typedef struct IFile {
128 char *fname; /* name of file (relative? absolute?) */ 128 char *fname; /* name of file (relative? absolute?) */
129 Boolean fromForLoop; /* simulated .include by the .for loop */ 129 Boolean fromForLoop; /* simulated .include by the .for loop */
130 int lineno; /* current line number in file */ 130 int lineno; /* current line number in file */
131 int first_lineno; /* line number of start of text */ 131 int first_lineno; /* line number of start of text */
132 unsigned int cond_depth; /* 'if' nesting when file opened */ 132 unsigned int cond_depth; /* 'if' nesting when file opened */
133 Boolean depending; /* state of doing_depend on EOF */ 133 Boolean depending; /* state of doing_depend on EOF */
134 134
135 /* The buffer from which the file's content is read. */ 135 /* The buffer from which the file's content is read. */
136 char *buf_freeIt; 136 char *buf_freeIt;
137 char *buf_ptr; /* next char to be read */ 137 char *buf_ptr; /* next char to be read */
138 char *buf_end; 138 char *buf_end;
139 139
140 /* Function to read more data, with a single opaque argument. */ 140 /* Function to read more data, with a single opaque argument. */
141 ReadMoreProc readMore; 141 ReadMoreProc readMore;
142 void *readMoreArg; 142 void *readMoreArg;
143 143
144 struct loadedfile *lf; /* loadedfile object, if any */ 144 struct loadedfile *lf; /* loadedfile object, if any */
145} IFile; 145} IFile;
146 146
147/* 147/*
148 * Tokens for target attributes 148 * Tokens for target attributes
149 */ 149 */
150typedef enum ParseSpecial { 150typedef enum ParseSpecial {
151 SP_ATTRIBUTE, /* Generic attribute */ 151 SP_ATTRIBUTE, /* Generic attribute */
152 SP_BEGIN, /* .BEGIN */ 152 SP_BEGIN, /* .BEGIN */
153 SP_DEFAULT, /* .DEFAULT */ 153 SP_DEFAULT, /* .DEFAULT */
154 SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */ 154 SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */
155 SP_END, /* .END */ 155 SP_END, /* .END */
156 SP_ERROR, /* .ERROR */ 156 SP_ERROR, /* .ERROR */
157 SP_IGNORE, /* .IGNORE */ 157 SP_IGNORE, /* .IGNORE */
158 SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */ 158 SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */
159 SP_INTERRUPT, /* .INTERRUPT */ 159 SP_INTERRUPT, /* .INTERRUPT */
160 SP_LIBS, /* .LIBS; not mentioned in the manual page */ 160 SP_LIBS, /* .LIBS; not mentioned in the manual page */
161 /* .MAIN and we don't have anything user-specified to make */ 161 /* .MAIN and we don't have anything user-specified to make */
162 SP_MAIN, 162 SP_MAIN,
163 SP_META, /* .META */ 163 SP_META, /* .META */
164 SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */ 164 SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */
165 SP_NOMETA, /* .NOMETA */ 165 SP_NOMETA, /* .NOMETA */
166 SP_NOMETA_CMP, /* .NOMETA_CMP */ 166 SP_NOMETA_CMP, /* .NOMETA_CMP */
167 SP_NOPATH, /* .NOPATH */ 167 SP_NOPATH, /* .NOPATH */
168 SP_NOT, /* Not special */ 168 SP_NOT, /* Not special */
169 SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */ 169 SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */
170 SP_NULL, /* .NULL; not mentioned in the manual page */ 170 SP_NULL, /* .NULL; not mentioned in the manual page */
171 SP_OBJDIR, /* .OBJDIR */ 171 SP_OBJDIR, /* .OBJDIR */
172 SP_ORDER, /* .ORDER */ 172 SP_ORDER, /* .ORDER */
173 SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */ 173 SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */
174 SP_PATH, /* .PATH or .PATH.suffix */ 174 SP_PATH, /* .PATH or .PATH.suffix */
175 SP_PHONY, /* .PHONY */ 175 SP_PHONY, /* .PHONY */
176#ifdef POSIX 176#ifdef POSIX
177 SP_POSIX, /* .POSIX; not mentioned in the manual page */ 177 SP_POSIX, /* .POSIX; not mentioned in the manual page */
178#endif 178#endif
179 SP_PRECIOUS, /* .PRECIOUS */ 179 SP_PRECIOUS, /* .PRECIOUS */
180 SP_SHELL, /* .SHELL */ 180 SP_SHELL, /* .SHELL */
181 SP_SILENT, /* .SILENT */ 181 SP_SILENT, /* .SILENT */
182 SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */ 182 SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */
183 SP_STALE, /* .STALE */ 183 SP_STALE, /* .STALE */
184 SP_SUFFIXES, /* .SUFFIXES */ 184 SP_SUFFIXES, /* .SUFFIXES */
185 SP_WAIT /* .WAIT */ 185 SP_WAIT /* .WAIT */
186} ParseSpecial; 186} ParseSpecial;
187 187
188typedef List SearchPathList; 188typedef List SearchPathList;
189typedef ListNode SearchPathListNode; 189typedef ListNode SearchPathListNode;
190 190
191/* result data */ 191/* result data */
192 192
193/* 193/*
194 * The main target to create. This is the first target on the first 194 * The main target to create. This is the first target on the first
195 * dependency line in the first makefile. 195 * dependency line in the first makefile.
196 */ 196 */
197static GNode *mainNode; 197static GNode *mainNode;
198 198
199/* eval state */ 199/* eval state */
200 200
201/* During parsing, the targets from the left-hand side of the currently 201/* During parsing, the targets from the left-hand side of the currently
202 * active dependency line, or NULL if the current line does not belong to a 202 * active dependency line, or NULL if the current line does not belong to a
203 * dependency line, for example because it is a variable assignment. 203 * dependency line, for example because it is a variable assignment.
204 * 204 *
205 * See unit-tests/deptgt.mk, keyword "parse.c:targets". */ 205 * See unit-tests/deptgt.mk, keyword "parse.c:targets". */
206static GNodeList *targets; 206static GNodeList *targets;
207 207
208#ifdef CLEANUP 208#ifdef CLEANUP
209/* All shell commands for all targets, in no particular order and possibly 209/* All shell commands for all targets, in no particular order and possibly
210 * with duplicates. Kept in a separate list since the commands from .USE or 210 * with duplicates. Kept in a separate list since the commands from .USE or
211 * .USEBEFORE nodes are shared with other GNodes, thereby giving up the 211 * .USEBEFORE nodes are shared with other GNodes, thereby giving up the
212 * easily understandable ownership over the allocated strings. */ 212 * easily understandable ownership over the allocated strings. */
213static StringList targCmds = LST_INIT; 213static StringList targCmds = LST_INIT;
214#endif 214#endif
215 215
216/* 216/*
217 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 217 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
218 * seen, then set to each successive source on the line. 218 * seen, then set to each successive source on the line.
219 */ 219 */
220static GNode *order_pred; 220static GNode *order_pred;
221 221
222/* parser state */ 222/* parser state */
223 223
224/* number of fatal errors */ 224/* number of fatal errors */
225static int fatals = 0; 225static int fatals = 0;
226 226
227/* 227/*
228 * Variables for doing includes 228 * Variables for doing includes
229 */ 229 */
230 230
231/* The include chain of makefiles. At the bottom is the top-level makefile 231/* The include chain of makefiles. At the bottom is the top-level makefile
232 * from the command line, and on top of that, there are the included files or 232 * from the command line, and on top of that, there are the included files or
233 * .for loops, up to and including the current file. 233 * .for loops, up to and including the current file.
234 * 234 *
235 * This data could be used to print stack traces on parse errors. As of 235 * This data could be used to print stack traces on parse errors. As of
236 * 2020-09-14, this is not done though. It seems quite simple to print the 236 * 2020-09-14, this is not done though. It seems quite simple to print the
237 * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is 237 * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is
238 * made complicated by the fact that the .for loops also use this stack for 238 * made complicated by the fact that the .for loops also use this stack for
239 * storing information. 239 * storing information.
240 * 240 *
241 * The lineno fields of the IFiles with fromForLoop == TRUE look confusing, 241 * The lineno fields of the IFiles with fromForLoop == TRUE look confusing,
242 * which is demonstrated by the test 'include-main.mk'. They seem sorted 242 * which is demonstrated by the test 'include-main.mk'. They seem sorted
243 * backwards since they tell the number of completely parsed lines, which for 243 * backwards since they tell the number of completely parsed lines, which for
244 * a .for loop is right after the terminating .endfor. To compensate for this 244 * a .for loop is right after the terminating .endfor. To compensate for this
245 * confusion, there is another field first_lineno pointing at the start of the 245 * confusion, there is another field first_lineno pointing at the start of the
246 * .for loop, 1-based for human consumption. 246 * .for loop, 1-based for human consumption.
247 * 247 *
248 * To make the stack trace intuitive, the entry below the first .for loop must 248 * To make the stack trace intuitive, the entry below the first .for loop must
249 * be ignored completely since neither its lineno nor its first_lineno is 249 * be ignored completely since neither its lineno nor its first_lineno is
250 * useful. Instead, the topmost of each chain of .for loop needs to be 250 * useful. Instead, the topmost of each chain of .for loop needs to be
251 * printed twice, once with its first_lineno and once with its lineno. 251 * printed twice, once with its first_lineno and once with its lineno.
252 * 252 *
253 * As of 2020-10-28, using the above rules, the stack trace for the .info line 253 * As of 2020-10-28, using the above rules, the stack trace for the .info line
254 * in include-subsub.mk would be: 254 * in include-subsub.mk would be:
255 * 255 *
256 * includes[5]: include-subsub.mk:4 256 * includes[5]: include-subsub.mk:4
257 * (lineno, from an .include) 257 * (lineno, from an .include)
258 * includes[4]: include-sub.mk:32 258 * includes[4]: include-sub.mk:32
259 * (lineno, from a .for loop below an .include) 259 * (lineno, from a .for loop below an .include)
260 * includes[4]: include-sub.mk:31 260 * includes[4]: include-sub.mk:31
261 * (first_lineno, from a .for loop, lineno == 32) 261 * (first_lineno, from a .for loop, lineno == 32)
262 * includes[3]: include-sub.mk:30 262 * includes[3]: include-sub.mk:30
263 * (first_lineno, from a .for loop, lineno == 33) 263 * (first_lineno, from a .for loop, lineno == 33)
264 * includes[2]: include-sub.mk:29 264 * includes[2]: include-sub.mk:29
265 * (first_lineno, from a .for loop, lineno == 34) 265 * (first_lineno, from a .for loop, lineno == 34)
266 * includes[1]: include-sub.mk:35 266 * includes[1]: include-sub.mk:35
267 * (not printed since it is below a .for loop) 267 * (not printed since it is below a .for loop)
268 * includes[0]: include-main.mk:27 268 * includes[0]: include-main.mk:27
269 */ 269 */
270static Vector /* of IFile */ includes; 270static Vector /* of IFile */ includes;
271 271
272static IFile * 272static IFile *
273GetInclude(size_t i) 273GetInclude(size_t i)
274{ 274{
275 return Vector_Get(&includes, i); 275 return Vector_Get(&includes, i);
276} 276}
277 277
278/* The file that is currently being read. */ 278/* The file that is currently being read. */
279static IFile * 279static IFile *
280CurFile(void) 280CurFile(void)
281{ 281{
282 return GetInclude(includes.len - 1); 282 return GetInclude(includes.len - 1);
283} 283}
284 284
285/* include paths */ 285/* include paths */
286SearchPath *parseIncPath; /* dirs for "..." includes */ 286SearchPath *parseIncPath; /* dirs for "..." includes */
287SearchPath *sysIncPath; /* dirs for <...> includes */ 287SearchPath *sysIncPath; /* dirs for <...> includes */
288SearchPath *defSysIncPath; /* default for sysIncPath */ 288SearchPath *defSysIncPath; /* default for sysIncPath */
289 289
290/* parser tables */ 290/* parser tables */
291 291
292/* 292/*
293 * The parseKeywords table is searched using binary search when deciding 293 * The parseKeywords table is searched using binary search when deciding
294 * if a target or source is special. The 'spec' field is the ParseSpecial 294 * if a target or source is special. The 'spec' field is the ParseSpecial
295 * type of the keyword (SP_NOT if the keyword isn't special as a target) while 295 * type of the keyword (SP_NOT if the keyword isn't special as a target) while
296 * the 'op' field is the operator to apply to the list of targets if the 296 * the 'op' field is the operator to apply to the list of targets if the
297 * keyword is used as a source ("0" if the keyword isn't special as a source) 297 * keyword is used as a source ("0" if the keyword isn't special as a source)
298 */ 298 */
299static const struct { 299static const struct {
300 const char *name; /* Name of keyword */ 300 const char *name; /* Name of keyword */
301 ParseSpecial spec; /* Type when used as a target */ 301 ParseSpecial spec; /* Type when used as a target */
302 GNodeType op; /* Operator when used as a source */ 302 GNodeType op; /* Operator when used as a source */
303} parseKeywords[] = { 303} parseKeywords[] = {
304 { ".BEGIN", SP_BEGIN, OP_NONE }, 304 { ".BEGIN", SP_BEGIN, OP_NONE },
305 { ".DEFAULT", SP_DEFAULT, OP_NONE }, 305 { ".DEFAULT", SP_DEFAULT, OP_NONE },
306 { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, OP_NONE }, 306 { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, OP_NONE },
307 { ".END", SP_END, OP_NONE }, 307 { ".END", SP_END, OP_NONE },
308 { ".ERROR", SP_ERROR, OP_NONE }, 308 { ".ERROR", SP_ERROR, OP_NONE },
309 { ".EXEC", SP_ATTRIBUTE, OP_EXEC }, 309 { ".EXEC", SP_ATTRIBUTE, OP_EXEC },
310 { ".IGNORE", SP_IGNORE, OP_IGNORE }, 310 { ".IGNORE", SP_IGNORE, OP_IGNORE },
311 { ".INCLUDES", SP_INCLUDES, OP_NONE }, 311 { ".INCLUDES", SP_INCLUDES, OP_NONE },
312 { ".INTERRUPT", SP_INTERRUPT, OP_NONE }, 312 { ".INTERRUPT", SP_INTERRUPT, OP_NONE },
313 { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE }, 313 { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE },
314 { ".JOIN", SP_ATTRIBUTE, OP_JOIN }, 314 { ".JOIN", SP_ATTRIBUTE, OP_JOIN },
315 { ".LIBS", SP_LIBS, OP_NONE }, 315 { ".LIBS", SP_LIBS, OP_NONE },
316 { ".MADE", SP_ATTRIBUTE, OP_MADE }, 316 { ".MADE", SP_ATTRIBUTE, OP_MADE },
317 { ".MAIN", SP_MAIN, OP_NONE }, 317 { ".MAIN", SP_MAIN, OP_NONE },
318 { ".MAKE", SP_ATTRIBUTE, OP_MAKE }, 318 { ".MAKE", SP_ATTRIBUTE, OP_MAKE },
319 { ".MAKEFLAGS", SP_MFLAGS, OP_NONE }, 319 { ".MAKEFLAGS", SP_MFLAGS, OP_NONE },
320 { ".META", SP_META, OP_META }, 320 { ".META", SP_META, OP_META },
321 { ".MFLAGS", SP_MFLAGS, OP_NONE }, 321 { ".MFLAGS", SP_MFLAGS, OP_NONE },
322 { ".NOMETA", SP_NOMETA, OP_NOMETA }, 322 { ".NOMETA", SP_NOMETA, OP_NOMETA },
323 { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP }, 323 { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP },
324 { ".NOPATH", SP_NOPATH, OP_NOPATH }, 324 { ".NOPATH", SP_NOPATH, OP_NOPATH },
325 { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN }, 325 { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN },
326 { ".NOTPARALLEL", SP_NOTPARALLEL, OP_NONE }, 326 { ".NOTPARALLEL", SP_NOTPARALLEL, OP_NONE },
327 { ".NO_PARALLEL", SP_NOTPARALLEL, OP_NONE }, 327 { ".NO_PARALLEL", SP_NOTPARALLEL, OP_NONE },
328 { ".NULL", SP_NULL, OP_NONE }, 328 { ".NULL", SP_NULL, OP_NONE },
329 { ".OBJDIR", SP_OBJDIR, OP_NONE }, 329 { ".OBJDIR", SP_OBJDIR, OP_NONE },
330 { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL }, 330 { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL },
331 { ".ORDER", SP_ORDER, OP_NONE }, 331 { ".ORDER", SP_ORDER, OP_NONE },
332 { ".PARALLEL", SP_PARALLEL, OP_NONE }, 332 { ".PARALLEL", SP_PARALLEL, OP_NONE },
333 { ".PATH", SP_PATH, OP_NONE }, 333 { ".PATH", SP_PATH, OP_NONE },
334 { ".PHONY", SP_PHONY, OP_PHONY }, 334 { ".PHONY", SP_PHONY, OP_PHONY },
335#ifdef POSIX 335#ifdef POSIX
336 { ".POSIX", SP_POSIX, OP_NONE }, 336 { ".POSIX", SP_POSIX, OP_NONE },
337#endif 337#endif
338 { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS }, 338 { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS },
339 { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE }, 339 { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE },
340 { ".SHELL", SP_SHELL, OP_NONE }, 340 { ".SHELL", SP_SHELL, OP_NONE },
341 { ".SILENT", SP_SILENT, OP_SILENT }, 341 { ".SILENT", SP_SILENT, OP_SILENT },
342 { ".SINGLESHELL", SP_SINGLESHELL, OP_NONE }, 342 { ".SINGLESHELL", SP_SINGLESHELL, OP_NONE },
343 { ".STALE", SP_STALE, OP_NONE }, 343 { ".STALE", SP_STALE, OP_NONE },
344 { ".SUFFIXES", SP_SUFFIXES, OP_NONE }, 344 { ".SUFFIXES", SP_SUFFIXES, OP_NONE },
345 { ".USE", SP_ATTRIBUTE, OP_USE }, 345 { ".USE", SP_ATTRIBUTE, OP_USE },
346 { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE }, 346 { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE },
347 { ".WAIT", SP_WAIT, OP_NONE }, 347 { ".WAIT", SP_WAIT, OP_NONE },
348}; 348};
349 349
350/* file loader */ 350/* file loader */
351 351
352struct loadedfile { 352struct loadedfile {
353 /* XXX: What is the lifetime of this path? Who manages the memory? */ 353 /* XXX: What is the lifetime of this path? Who manages the memory? */
354 const char *path; /* name, for error reports */ 354 const char *path; /* name, for error reports */
355 char *buf; /* contents buffer */ 355 char *buf; /* contents buffer */
356 size_t len; /* length of contents */ 356 size_t len; /* length of contents */
357 size_t maplen; /* length of mmap area, or 0 */ 357 size_t maplen; /* length of mmap area, or 0 */
358 Boolean used; /* XXX: have we used the data yet */ 358 Boolean used; /* XXX: have we used the data yet */
359}; 359};
360 360
361/* XXX: What is the lifetime of the path? Who manages the memory? */ 361/* XXX: What is the lifetime of the path? Who manages the memory? */
362static struct loadedfile * 362static struct loadedfile *
363loadedfile_create(const char *path) 363loadedfile_create(const char *path)
364{ 364{
365 struct loadedfile *lf; 365 struct loadedfile *lf;
366 366
367 lf = bmake_malloc(sizeof *lf); 367 lf = bmake_malloc(sizeof *lf);
368 lf->path = path == NULL ? "(stdin)" : path; 368 lf->path = path == NULL ? "(stdin)" : path;
369 lf->buf = NULL; 369 lf->buf = NULL;
370 lf->len = 0; 370 lf->len = 0;
371 lf->maplen = 0; 371 lf->maplen = 0;
372 lf->used = FALSE; 372 lf->used = FALSE;
373 return lf; 373 return lf;
374} 374}
375 375
376static void 376static void
377loadedfile_destroy(struct loadedfile *lf) 377loadedfile_destroy(struct loadedfile *lf)
378{ 378{
379 if (lf->buf != NULL) { 379 if (lf->buf != NULL) {
380 if (lf->maplen > 0) 380 if (lf->maplen > 0)
381 munmap(lf->buf, lf->maplen); 381 munmap(lf->buf, lf->maplen);
382 else 382 else
383 free(lf->buf); 383 free(lf->buf);
384 } 384 }
385 free(lf); 385 free(lf);
386} 386}
387 387
388/* 388/*
389 * readMore() operation for loadedfile, as needed by the weird and twisted 389 * readMore() operation for loadedfile, as needed by the weird and twisted
390 * logic below. Once that's cleaned up, we can get rid of lf->used. 390 * logic below. Once that's cleaned up, we can get rid of lf->used.
391 */ 391 */
392static char * 392static char *
393loadedfile_readMore(void *x, size_t *len) 393loadedfile_readMore(void *x, size_t *len)
394{ 394{
395 struct loadedfile *lf = x; 395 struct loadedfile *lf = x;
396 396
397 if (lf->used) 397 if (lf->used)
398 return NULL; 398 return NULL;
399 399
400 lf->used = TRUE; 400 lf->used = TRUE;
401 *len = lf->len; 401 *len = lf->len;
402 return lf->buf; 402 return lf->buf;
403} 403}
404 404
405/* 405/*
406 * Try to get the size of a file. 406 * Try to get the size of a file.
407 */ 407 */
408static Boolean 408static Boolean
409load_getsize(int fd, size_t *ret) 409load_getsize(int fd, size_t *ret)
410{ 410{
411 struct stat st; 411 struct stat st;
412 412
413 if (fstat(fd, &st) < 0) 413 if (fstat(fd, &st) < 0)
414 return FALSE; 414 return FALSE;
415 415
416 if (!S_ISREG(st.st_mode)) 416 if (!S_ISREG(st.st_mode))
417 return FALSE; 417 return FALSE;
418 418
419 /* 419 /*
420 * st_size is an off_t, which is 64 bits signed; *ret is 420 * st_size is an off_t, which is 64 bits signed; *ret is
421 * size_t, which might be 32 bits unsigned or 64 bits 421 * size_t, which might be 32 bits unsigned or 64 bits
422 * unsigned. Rather than being elaborate, just punt on 422 * unsigned. Rather than being elaborate, just punt on
423 * files that are more than 2^31 bytes. We should never 423 * files that are more than 2^31 bytes. We should never
424 * see a makefile that size in practice... 424 * see a makefile that size in practice...
425 * 425 *
426 * While we're at it reject negative sizes too, just in case. 426 * While we're at it reject negative sizes too, just in case.
427 */ 427 */
428 if (st.st_size < 0 || st.st_size > 0x7fffffff) 428 if (st.st_size < 0 || st.st_size > 0x7fffffff)
429 return FALSE; 429 return FALSE;
430 430
431 *ret = (size_t)st.st_size; 431 *ret = (size_t)st.st_size;
432 return TRUE; 432 return TRUE;
433} 433}
434 434
435static Boolean 435static Boolean
436loadedfile_mmap(struct loadedfile *lf, int fd) 436loadedfile_mmap(struct loadedfile *lf, int fd)
437{ 437{
438 static unsigned long pagesize = 0; 438 static unsigned long pagesize = 0;
439 439
440 if (!load_getsize(fd, &lf->len)) 440 if (!load_getsize(fd, &lf->len))
441 return FALSE; 441 return FALSE;
442 442
443 /* found a size, try mmap */ 443 /* found a size, try mmap */
444 if (pagesize == 0) 444 if (pagesize == 0)
445 pagesize = (unsigned long)sysconf(_SC_PAGESIZE); 445 pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
446 if (pagesize == 0 || pagesize == (unsigned long)-1) 446 if (pagesize == 0 || pagesize == (unsigned long)-1)
447 pagesize = 0x1000; 447 pagesize = 0x1000;
448 448
449 /* round size up to a page */ 449 /* round size up to a page */
450 lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize); 450 lf->maplen = pagesize * ((lf->len + pagesize - 1) / pagesize);
451 451
452 /* 452 /*
453 * XXX hack for dealing with empty files; remove when 453 * XXX hack for dealing with empty files; remove when
454 * we're no longer limited by interfacing to the old 454 * we're no longer limited by interfacing to the old
455 * logic elsewhere in this file. 455 * logic elsewhere in this file.
456 */ 456 */
457 if (lf->maplen == 0) 457 if (lf->maplen == 0)
458 lf->maplen = pagesize; 458 lf->maplen = pagesize;
459 459
460 /* 460 /*
461 * FUTURE: remove PROT_WRITE when the parser no longer 461 * FUTURE: remove PROT_WRITE when the parser no longer
462 * needs to scribble on the input. 462 * needs to scribble on the input.
463 */ 463 */
464 lf->buf = mmap(NULL, lf->maplen, PROT_READ | PROT_WRITE, 464 lf->buf = mmap(NULL, lf->maplen, PROT_READ | PROT_WRITE,
465 MAP_FILE | MAP_COPY, fd, 0); 465 MAP_FILE | MAP_COPY, fd, 0);
466 if (lf->buf == MAP_FAILED) 466 if (lf->buf == MAP_FAILED)
467 return FALSE; 467 return FALSE;
468 468
469 if (lf->len > 0 && lf->buf[lf->len - 1] != '\n') { 469 if (lf->len > 0 && lf->buf[lf->len - 1] != '\n') {
470 if (lf->len == lf->maplen) { 470 if (lf->len == lf->maplen) {
471 char *b = bmake_malloc(lf->len + 1); 471 char *b = bmake_malloc(lf->len + 1);
472 memcpy(b, lf->buf, lf->len); 472 memcpy(b, lf->buf, lf->len);
473 munmap(lf->buf, lf->maplen); 473 munmap(lf->buf, lf->maplen);
474 lf->maplen = 0; 474 lf->maplen = 0;
475 } 475 }
476 lf->buf[lf->len++] = '\n'; 476 lf->buf[lf->len++] = '\n';
477 } 477 }
478 478
479 return TRUE; 479 return TRUE;
480} 480}
481 481
482/* 482/*
483 * Read in a file. 483 * Read in a file.
484 * 484 *
485 * Until the path search logic can be moved under here instead of 485 * Until the path search logic can be moved under here instead of
486 * being in the caller in another source file, we need to have the fd 486 * being in the caller in another source file, we need to have the fd
487 * passed in already open. Bleh. 487 * passed in already open. Bleh.
488 * 488 *
489 * If the path is NULL, use stdin. 489 * If the path is NULL, use stdin.
490 */ 490 */
491static struct loadedfile * 491static struct loadedfile *
492loadfile(const char *path, int fd) 492loadfile(const char *path, int fd)
493{ 493{
494 struct loadedfile *lf; 494 struct loadedfile *lf;
495 ssize_t result; 495 ssize_t result;
496 size_t bufpos; 496 size_t bufpos;
497 497
498 lf = loadedfile_create(path); 498 lf = loadedfile_create(path);
499 499
500 if (path == NULL) { 500 if (path == NULL) {
501 assert(fd == -1); 501 assert(fd == -1);
502 fd = STDIN_FILENO; 502 fd = STDIN_FILENO;
503 } else { 503 } else {
504#if 0 /* notyet */ 504#if 0 /* notyet */
505 fd = open(path, O_RDONLY); 505 fd = open(path, O_RDONLY);
506 if (fd < 0) { 506 if (fd < 0) {
507 ... 507 ...
508 Error("%s: %s", path, strerror(errno)); 508 Error("%s: %s", path, strerror(errno));
509 exit(1); 509 exit(1);
510 } 510 }
511#endif 511#endif
512 } 512 }
513 513
514 if (loadedfile_mmap(lf, fd)) 514 if (loadedfile_mmap(lf, fd))
515 goto done; 515 goto done;
516 516
517 /* cannot mmap; load the traditional way */ 517 /* cannot mmap; load the traditional way */
518 518
519 lf->maplen = 0; 519 lf->maplen = 0;
520 lf->len = 1024; 520 lf->len = 1024;
521 lf->buf = bmake_malloc(lf->len); 521 lf->buf = bmake_malloc(lf->len);
522 522
523 bufpos = 0; 523 bufpos = 0;
524 for (;;) { 524 for (;;) {
525 assert(bufpos <= lf->len); 525 assert(bufpos <= lf->len);
526 if (bufpos == lf->len) { 526 if (bufpos == lf->len) {
527 if (lf->len > SIZE_MAX / 2) { 527 if (lf->len > SIZE_MAX / 2) {
528 errno = EFBIG; 528 errno = EFBIG;
529 Error("%s: file too large", path); 529 Error("%s: file too large", path);
530 exit(2); /* Not 1 so -q can distinguish error */ 530 exit(2); /* Not 1 so -q can distinguish error */
531 } 531 }
532 lf->len *= 2; 532 lf->len *= 2;
533 lf->buf = bmake_realloc(lf->buf, lf->len); 533 lf->buf = bmake_realloc(lf->buf, lf->len);
534 } 534 }
535 assert(bufpos < lf->len); 535 assert(bufpos < lf->len);
536 result = read(fd, lf->buf + bufpos, lf->len - bufpos); 536 result = read(fd, lf->buf + bufpos, lf->len - bufpos);
537 if (result < 0) { 537 if (result < 0) {
538 Error("%s: read error: %s", path, strerror(errno)); 538 Error("%s: read error: %s", path, strerror(errno));
539 exit(2); /* Not 1 so -q can distinguish error */ 539 exit(2); /* Not 1 so -q can distinguish error */
540 } 540 }
541 if (result == 0) 541 if (result == 0)
542 break; 542 break;
543 543
544 bufpos += (size_t)result; 544 bufpos += (size_t)result;
545 } 545 }
546 assert(bufpos <= lf->len); 546 assert(bufpos <= lf->len);
547 lf->len = bufpos; 547 lf->len = bufpos;
548 548
549 /* truncate malloc region to actual length (maybe not useful) */ 549 /* truncate malloc region to actual length (maybe not useful) */
550 if (lf->len > 0) { 550 if (lf->len > 0) {
551 /* as for mmap case, ensure trailing \n */ 551 /* as for mmap case, ensure trailing \n */
552 if (lf->buf[lf->len - 1] != '\n') 552 if (lf->buf[lf->len - 1] != '\n')
553 lf->len++; 553 lf->len++;
554 lf->buf = bmake_realloc(lf->buf, lf->len); 554 lf->buf = bmake_realloc(lf->buf, lf->len);
555 lf->buf[lf->len - 1] = '\n'; 555 lf->buf[lf->len - 1] = '\n';
556 } 556 }
557 557
558done: 558done:
559 if (path != NULL) 559 if (path != NULL)
560 close(fd); 560 close(fd);
561 561
562 return lf; 562 return lf;
563} 563}
564 564
565/* old code */ 565/* old code */
566 566
567/* Check if the current character is escaped on the current line. */ 567/* Check if the current character is escaped on the current line. */
568static Boolean 568static Boolean
569ParseIsEscaped(const char *line, const char *c) 569ParseIsEscaped(const char *line, const char *c)
570{ 570{
571 Boolean active = FALSE; 571 Boolean active = FALSE;
572 for (;;) { 572 for (;;) {
573 if (line == c) 573 if (line == c)
574 return active; 574 return active;
575 if (*--c != '\\') 575 if (*--c != '\\')
576 return active; 576 return active;
577 active = !active; 577 active = !active;
578 } 578 }
579} 579}
580 580
581/* Add the filename and lineno to the GNode so that we remember where it 581/* Add the filename and lineno to the GNode so that we remember where it
582 * was first defined. */ 582 * was first defined. */
583static void 583static void
584ParseMark(GNode *gn) 584ParseMark(GNode *gn)
585{ 585{
586 IFile *curFile = CurFile(); 586 IFile *curFile = CurFile();
587 gn->fname = curFile->fname; 587 gn->fname = curFile->fname;
588 gn->lineno = curFile->lineno; 588 gn->lineno = curFile->lineno;
589} 589}
590 590
591/* Look in the table of keywords for one matching the given string. 591/* Look in the table of keywords for one matching the given string.
592 * Return the index of the keyword, or -1 if it isn't there. */ 592 * Return the index of the keyword, or -1 if it isn't there. */
593static int 593static int
594ParseFindKeyword(const char *str) 594ParseFindKeyword(const char *str)
595{ 595{
596 int start = 0; 596 int start = 0;
597 int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1; 597 int end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
598 598
599 do { 599 do {
600 int curr = start + (end - start) / 2; 600 int curr = start + (end - start) / 2;
601 int diff = strcmp(str, parseKeywords[curr].name); 601 int diff = strcmp(str, parseKeywords[curr].name);
602 602
603 if (diff == 0) 603 if (diff == 0)
604 return curr; 604 return curr;
605 if (diff < 0) 605 if (diff < 0)
606 end = curr - 1; 606 end = curr - 1;
607 else 607 else
608 start = curr + 1; 608 start = curr + 1;
609 } while (start <= end); 609 } while (start <= end);
610 610
611 return -1; 611 return -1;
612} 612}
613 613
614static void 614static void
615PrintLocation(FILE *f, const char *fname, size_t lineno) 615PrintLocation(FILE *f, const char *fname, size_t lineno)
616{ 616{
617 char dirbuf[MAXPATHLEN + 1]; 617 char dirbuf[MAXPATHLEN + 1];
618 FStr dir, base; 618 FStr dir, base;
619 619
620 if (*fname == '/' || strcmp(fname, "(stdin)") == 0) { 620 if (*fname == '/' || strcmp(fname, "(stdin)") == 0) {
621 (void)fprintf(f, "\"%s\" line %u: ", fname, (unsigned)lineno); 621 (void)fprintf(f, "\"%s\" line %u: ", fname, (unsigned)lineno);
622 return; 622 return;
623 } 623 }
624 624
625 /* Find out which makefile is the culprit. 625 /* Find out which makefile is the culprit.
626 * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */ 626 * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */
627 627
628 dir = Var_Value(".PARSEDIR", VAR_GLOBAL); 628 dir = Var_Value(".PARSEDIR", VAR_GLOBAL);
629 if (dir.str == NULL) 629 if (dir.str == NULL)
630 dir.str = "."; 630 dir.str = ".";
631 if (dir.str[0] != '/') 631 if (dir.str[0] != '/')
632 dir.str = realpath(dir.str, dirbuf); 632 dir.str = realpath(dir.str, dirbuf);
633 633
634 base = Var_Value(".PARSEFILE", VAR_GLOBAL); 634 base = Var_Value(".PARSEFILE", VAR_GLOBAL);
635 if (base.str == NULL) 635 if (base.str == NULL)
636 base.str = str_basename(fname); 636 base.str = str_basename(fname);
637 637
638 (void)fprintf(f, "\"%s/%s\" line %u: ", 638 (void)fprintf(f, "\"%s/%s\" line %u: ",
639 dir.str, base.str, (unsigned)lineno); 639 dir.str, base.str, (unsigned)lineno);
640 640
641 FStr_Done(&base); 641 FStr_Done(&base);
642 FStr_Done(&dir); 642 FStr_Done(&dir);
643} 643}
644 644
645static void 645static void
646ParseVErrorInternal(FILE *f, const char *fname, size_t lineno, 646ParseVErrorInternal(FILE *f, const char *fname, size_t lineno,
647 ParseErrorLevel type, const char *fmt, va_list ap) 647 ParseErrorLevel type, const char *fmt, va_list ap)
648{ 648{
649 static Boolean fatal_warning_error_printed = FALSE; 649 static Boolean fatal_warning_error_printed = FALSE;
650 650
651 (void)fprintf(f, "%s: ", progname); 651 (void)fprintf(f, "%s: ", progname);
652 652
653 if (fname != NULL) 653 if (fname != NULL)
654 PrintLocation(f, fname, lineno); 654 PrintLocation(f, fname, lineno);
655 if (type == PARSE_WARNING) 655 if (type == PARSE_WARNING)
656 (void)fprintf(f, "warning: "); 656 (void)fprintf(f, "warning: ");
657 (void)vfprintf(f, fmt, ap); 657 (void)vfprintf(f, fmt, ap);
658 (void)fprintf(f, "\n"); 658 (void)fprintf(f, "\n");
659 (void)fflush(f); 659 (void)fflush(f);
660 660
661 if (type == PARSE_INFO) 661 if (type == PARSE_INFO)
662 return; 662 return;
663 if (type == PARSE_FATAL || opts.parseWarnFatal) 663 if (type == PARSE_FATAL || opts.parseWarnFatal)
664 fatals++; 664 fatals++;
665 if (opts.parseWarnFatal && !fatal_warning_error_printed) { 665 if (opts.parseWarnFatal && !fatal_warning_error_printed) {
666 Error("parsing warnings being treated as errors"); 666 Error("parsing warnings being treated as errors");
667 fatal_warning_error_printed = TRUE; 667 fatal_warning_error_printed = TRUE;
668 } 668 }
669} 669}
670 670
671static void 671static void
672ParseErrorInternal(const char *fname, size_t lineno, 672ParseErrorInternal(const char *fname, size_t lineno,
673 ParseErrorLevel type, const char *fmt, ...) 673 ParseErrorLevel type, const char *fmt, ...)
674{ 674{
675 va_list ap; 675 va_list ap;
676 676
677 (void)fflush(stdout); 677 (void)fflush(stdout);
678 va_start(ap, fmt); 678 va_start(ap, fmt);
679 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); 679 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
680 va_end(ap); 680 va_end(ap);
681 681
682 if (opts.debug_file != stderr && opts.debug_file != stdout) { 682 if (opts.debug_file != stderr && opts.debug_file != stdout) {
683 va_start(ap, fmt); 683 va_start(ap, fmt);
684 ParseVErrorInternal(opts.debug_file, fname, lineno, type, 684 ParseVErrorInternal(opts.debug_file, fname, lineno, type,
685 fmt, ap); 685 fmt, ap);
686 va_end(ap); 686 va_end(ap);
687 } 687 }
688} 688}
689 689
690/* Print a parse error message, including location information. 690/* Print a parse error message, including location information.
691 * 691 *
692 * If the level is PARSE_FATAL, continue parsing until the end of the 692 * If the level is PARSE_FATAL, continue parsing until the end of the
693 * current top-level makefile, then exit (see Parse_File). 693 * current top-level makefile, then exit (see Parse_File).
694 * 694 *
695 * Fmt is given without a trailing newline. */ 695 * Fmt is given without a trailing newline. */
696void 696void
697Parse_Error(ParseErrorLevel type, const char *fmt, ...) 697Parse_Error(ParseErrorLevel type, const char *fmt, ...)
698{ 698{
699 va_list ap; 699 va_list ap;
700 const char *fname; 700 const char *fname;
701 size_t lineno; 701 size_t lineno;
702 702
703 if (includes.len == 0) { 703 if (includes.len == 0) {
704 fname = NULL; 704 fname = NULL;
705 lineno = 0; 705 lineno = 0;
706 } else { 706 } else {
707 IFile *curFile = CurFile(); 707 IFile *curFile = CurFile();
708 fname = curFile->fname; 708 fname = curFile->fname;
709 lineno = (size_t)curFile->lineno; 709 lineno = (size_t)curFile->lineno;
710 } 710 }
711 711
712 va_start(ap, fmt); 712 va_start(ap, fmt);
713 (void)fflush(stdout); 713 (void)fflush(stdout);
714 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); 714 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
715 va_end(ap); 715 va_end(ap);
716 716
717 if (opts.debug_file != stderr && opts.debug_file != stdout) { 717 if (opts.debug_file != stderr && opts.debug_file != stdout) {
718 va_start(ap, fmt); 718 va_start(ap, fmt);
719 ParseVErrorInternal(opts.debug_file, fname, lineno, type, 719 ParseVErrorInternal(opts.debug_file, fname, lineno, type,
720 fmt, ap); 720 fmt, ap);
721 va_end(ap); 721 va_end(ap);
722 } 722 }
723} 723}
724 724
725 725
726/* Parse and handle a .info, .warning or .error directive. 726/* Parse and handle a .info, .warning or .error directive.
727 * For an .error directive, immediately exit. */ 727 * For an .error directive, immediately exit. */
728static void 728static void
729ParseMessage(ParseErrorLevel level, const char *levelName, const char *umsg) 729ParseMessage(ParseErrorLevel level, const char *levelName, const char *umsg)
730{ 730{
731 char *xmsg; 731 char *xmsg;
732 732
733 if (umsg[0] == '\0') { 733 if (umsg[0] == '\0') {
734 Parse_Error(PARSE_FATAL, "Missing argument for \".%s\"", 734 Parse_Error(PARSE_FATAL, "Missing argument for \".%s\"",
735 levelName); 735 levelName);
736 return; 736 return;
737 } 737 }
738 738
739 (void)Var_Subst(umsg, VAR_CMDLINE, VARE_WANTRES, &xmsg); 739 (void)Var_Subst(umsg, VAR_CMDLINE, VARE_WANTRES, &xmsg);
740 /* TODO: handle errors */ 740 /* TODO: handle errors */
741 741
742 Parse_Error(level, "%s", xmsg); 742 Parse_Error(level, "%s", xmsg);
743 free(xmsg); 743 free(xmsg);
744 744
745 if (level == PARSE_FATAL) { 745 if (level == PARSE_FATAL) {
746 PrintOnError(NULL, NULL); 746 PrintOnError(NULL, NULL);
747 exit(1); 747 exit(1);
748 } 748 }
749} 749}
750 750
751/* Add the child to the parent's children. 751/* Add the child to the parent's children.
752 * 752 *
753 * Additionally, add the parent to the child's parents, but only if the 753 * Additionally, add the parent to the child's parents, but only if the
754 * target is not special. An example for such a special target is .END, 754 * target is not special. An example for such a special target is .END,
755 * which does not need to be informed once the child target has been made. */ 755 * which does not need to be informed once the child target has been made. */
756static void 756static void
757LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial) 757LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial)
758{ 758{
759 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(&pgn->cohorts)) 759 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(&pgn->cohorts))
760 pgn = pgn->cohorts.last->datum; 760 pgn = pgn->cohorts.last->datum;
761 761
762 Lst_Append(&pgn->children, cgn); 762 Lst_Append(&pgn->children, cgn);
763 pgn->unmade++; 763 pgn->unmade++;
764 764
765 /* Special targets like .END don't need any children. */ 765 /* Special targets like .END don't need any children. */
766 if (!isSpecial) 766 if (!isSpecial)
767 Lst_Append(&cgn->parents, pgn); 767 Lst_Append(&cgn->parents, pgn);
768 768
769 if (DEBUG(PARSE)) { 769 if (DEBUG(PARSE)) {
770 debug_printf("# %s: added child %s - %s\n", 770 debug_printf("# %s: added child %s - %s\n",
771 __func__, pgn->name, cgn->name); 771 __func__, pgn->name, cgn->name);
772 Targ_PrintNode(pgn, 0); 772 Targ_PrintNode(pgn, 0);
773 Targ_PrintNode(cgn, 0); 773 Targ_PrintNode(cgn, 0);
774 } 774 }
775} 775}
776 776
777/* Add the node to each target from the current dependency group. */ 777/* Add the node to each target from the current dependency group. */
778static void 778static void
779LinkToTargets(GNode *gn, Boolean isSpecial) 779LinkToTargets(GNode *gn, Boolean isSpecial)
780{ 780{
781 GNodeListNode *ln; 781 GNodeListNode *ln;
782 782
783 for (ln = targets->first; ln != NULL; ln = ln->next) 783 for (ln = targets->first; ln != NULL; ln = ln->next)
784 LinkSource(ln->datum, gn, isSpecial); 784 LinkSource(ln->datum, gn, isSpecial);
785} 785}
786 786
787static Boolean 787static Boolean
788TryApplyDependencyOperator(GNode *gn, GNodeType op) 788TryApplyDependencyOperator(GNode *gn, GNodeType op)
789{ 789{
790 /* 790 /*
791 * If the node occurred on the left-hand side of a dependency and the 791 * If the node occurred on the left-hand side of a dependency and the
792 * operator also defines a dependency, they must match. 792 * operator also defines a dependency, they must match.
793 */ 793 */
794 if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) && 794 if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) &&
795 ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) { 795 ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) {
796 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", 796 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s",
797 gn->name); 797 gn->name);
798 return FALSE; 798 return FALSE;
799 } 799 }
800 800
801 if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 801 if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
802 /* 802 /*
803 * If the node was of the left-hand side of a '::' operator, 803 * If the node was of the left-hand side of a '::' operator,
804 * we need to create a new instance of it for the children 804 * we need to create a new instance of it for the children
805 * and commands on this dependency line since each of these 805 * and commands on this dependency line since each of these
806 * dependency groups has its own attributes and commands, 806 * dependency groups has its own attributes and commands,
807 * separate from the others. 807 * separate from the others.
808 * 808 *
809 * The new instance is placed on the 'cohorts' list of the 809 * The new instance is placed on the 'cohorts' list of the
810 * initial one (note the initial one is not on its own 810 * initial one (note the initial one is not on its own
811 * cohorts list) and the new instance is linked to all 811 * cohorts list) and the new instance is linked to all
812 * parents of the initial instance. 812 * parents of the initial instance.
813 */ 813 */
814 GNode *cohort; 814 GNode *cohort;
815 815
816 /* 816 /*
817 * Propagate copied bits to the initial node. They'll be 817 * Propagate copied bits to the initial node. They'll be
818 * propagated back to the rest of the cohorts later. 818 * propagated back to the rest of the cohorts later.
819 */ 819 */
820 gn->type |= op & ~OP_OPMASK; 820 gn->type |= op & ~OP_OPMASK;
821 821
822 cohort = Targ_NewInternalNode(gn->name); 822 cohort = Targ_NewInternalNode(gn->name);
823 if (doing_depend) 823 if (doing_depend)
824 ParseMark(cohort); 824 ParseMark(cohort);
825 /* 825 /*
826 * Make the cohort invisible as well to avoid duplicating it 826 * Make the cohort invisible as well to avoid duplicating it
827 * into other variables. True, parents of this target won't 827 * into other variables. True, parents of this target won't
828 * tend to do anything with their local variables, but better 828 * tend to do anything with their local variables, but better
829 * safe than sorry. 829 * safe than sorry.
830 * 830 *
831 * (I think this is pointless now, since the relevant list 831 * (I think this is pointless now, since the relevant list
832 * traversals will no longer see this node anyway. -mycroft) 832 * traversals will no longer see this node anyway. -mycroft)
833 */ 833 */
834 cohort->type = op | OP_INVISIBLE; 834 cohort->type = op | OP_INVISIBLE;
835 Lst_Append(&gn->cohorts, cohort); 835 Lst_Append(&gn->cohorts, cohort);
836 cohort->centurion = gn; 836 cohort->centurion = gn;
837 gn->unmade_cohorts++; 837 gn->unmade_cohorts++;
838 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", 838 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
839 (unsigned int)gn->unmade_cohorts % 1000000); 839 (unsigned int)gn->unmade_cohorts % 1000000);
840 } else { 840 } else {
841 /* 841 /*
842 * We don't want to nuke any previous flags (whatever they 842 * We don't want to nuke any previous flags (whatever they
843 * were) so we just OR the new operator into the old. 843 * were) so we just OR the new operator into the old.
844 */ 844 */
845 gn->type |= op; 845 gn->type |= op;
846 } 846 }
847 847
848 return TRUE; 848 return TRUE;
849} 849}
850 850
851static void 851static void
852ApplyDependencyOperator(GNodeType op) 852ApplyDependencyOperator(GNodeType op)
853{ 853{
854 GNodeListNode *ln; 854 GNodeListNode *ln;
855 855
856 for (ln = targets->first; ln != NULL; ln = ln->next) 856 for (ln = targets->first; ln != NULL; ln = ln->next)
857 if (!TryApplyDependencyOperator(ln->datum, op)) 857 if (!TryApplyDependencyOperator(ln->datum, op))
858 break; 858 break;
859} 859}
860 860
861/* 861/*
862 * We add a .WAIT node in the dependency list. After any dynamic dependencies 862 * We add a .WAIT node in the dependency list. After any dynamic dependencies
863 * (and filename globbing) have happened, it is given a dependency on each 863 * (and filename globbing) have happened, it is given a dependency on each
864 * previous child, back until the previous .WAIT node. The next child won't 864 * previous child, back until the previous .WAIT node. The next child won't
865 * be scheduled until the .WAIT node is built. 865 * be scheduled until the .WAIT node is built.
866 * 866 *
867 * We give each .WAIT node a unique name (mainly for diagnostics). 867 * We give each .WAIT node a unique name (mainly for diagnostics).
868 */ 868 */
869static void 869static void
870ParseDependencySourceWait(Boolean isSpecial) 870ParseDependencySourceWait(Boolean isSpecial)
871{ 871{
872 static int wait_number = 0; 872 static int wait_number = 0;
873 char wait_src[16]; 873 char wait_src[16];
874 GNode *gn; 874 GNode *gn;
875 875
876 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); 876 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
877 gn = Targ_NewInternalNode(wait_src); 877 gn = Targ_NewInternalNode(wait_src);
878 if (doing_depend) 878 if (doing_depend)
879 ParseMark(gn); 879 ParseMark(gn);
880 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; 880 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
881 LinkToTargets(gn, isSpecial); 881 LinkToTargets(gn, isSpecial);
882 882
883} 883}
884 884
885static Boolean 885static Boolean
886ParseDependencySourceKeyword(const char *src, ParseSpecial specType) 886ParseDependencySourceKeyword(const char *src, ParseSpecial specType)
887{ 887{
888 int keywd; 888 int keywd;
889 GNodeType op; 889 GNodeType op;
890 890
891 if (*src != '.' || !ch_isupper(src[1])) 891 if (*src != '.' || !ch_isupper(src[1]))
892 return FALSE; 892 return FALSE;
893 893
894 keywd = ParseFindKeyword(src); 894 keywd = ParseFindKeyword(src);
895 if (keywd == -1) 895 if (keywd == -1)
896 return FALSE; 896 return FALSE;
897 897
898 op = parseKeywords[keywd].op; 898 op = parseKeywords[keywd].op;
899 if (op != OP_NONE) { 899 if (op != OP_NONE) {
900 ApplyDependencyOperator(op); 900 ApplyDependencyOperator(op);
901 return TRUE; 901 return TRUE;
902 } 902 }
903 if (parseKeywords[keywd].spec == SP_WAIT) { 903 if (parseKeywords[keywd].spec == SP_WAIT) {
904 ParseDependencySourceWait(specType != SP_NOT); 904 ParseDependencySourceWait(specType != SP_NOT);
905 return TRUE; 905 return TRUE;
906 } 906 }
907 return FALSE; 907 return FALSE;
908} 908}
909 909
910static void 910static void
911ParseDependencySourceMain(const char *src) 911ParseDependencySourceMain(const char *src)
912{ 912{
913 /* 913 /*
914 * In a line like ".MAIN: source1 source2", it means we need to add 914 * In a line like ".MAIN: source1 source2", it means we need to add
915 * the sources of said target to the list of things to create. 915 * the sources of said target to the list of things to create.
916 * 916 *
917 * Note that this will only be invoked if the user didn't specify a 917 * Note that this will only be invoked if the user didn't specify a
918 * target on the command line and the .MAIN occurs for the first time. 918 * target on the command line and the .MAIN occurs for the first time.
919 * 919 *
920 * See ParseDoDependencyTargetSpecial, branch SP_MAIN. 920 * See ParseDoDependencyTargetSpecial, branch SP_MAIN.
921 * See unit-tests/cond-func-make-main.mk. 921 * See unit-tests/cond-func-make-main.mk.
922 */ 922 */
923 Lst_Append(&opts.create, bmake_strdup(src)); 923 Lst_Append(&opts.create, bmake_strdup(src));
924 /* 924 /*
925 * Add the name to the .TARGETS variable as well, so the user can 925 * Add the name to the .TARGETS variable as well, so the user can
926 * employ that, if desired. 926 * employ that, if desired.
927 */ 927 */
928 Var_Append(".TARGETS", src, VAR_GLOBAL); 928 Var_Append(".TARGETS", src, VAR_GLOBAL);
929} 929}
930 930
931static void 931static void
932ParseDependencySourceOrder(const char *src) 932ParseDependencySourceOrder(const char *src)
933{ 933{
934 GNode *gn; 934 GNode *gn;
935 /* 935 /*
936 * Create proper predecessor/successor links between the previous 936 * Create proper predecessor/successor links between the previous
937 * source and the current one. 937 * source and the current one.
938 */ 938 */
939 gn = Targ_GetNode(src); 939 gn = Targ_GetNode(src);
940 if (doing_depend) 940 if (doing_depend)
941 ParseMark(gn); 941 ParseMark(gn);
942 if (order_pred != NULL) { 942 if (order_pred != NULL) {
943 Lst_Append(&order_pred->order_succ, gn); 943 Lst_Append(&order_pred->order_succ, gn);
944 Lst_Append(&gn->order_pred, order_pred); 944 Lst_Append(&gn->order_pred, order_pred);
945 if (DEBUG(PARSE)) { 945 if (DEBUG(PARSE)) {
946 debug_printf("# %s: added Order dependency %s - %s\n", 946 debug_printf("# %s: added Order dependency %s - %s\n",
947 __func__, order_pred->name, gn->name); 947 __func__, order_pred->name, gn->name);
948 Targ_PrintNode(order_pred, 0); 948 Targ_PrintNode(order_pred, 0);
949 Targ_PrintNode(gn, 0); 949 Targ_PrintNode(gn, 0);
950 } 950 }
951 } 951 }
952 /* 952 /*
953 * The current source now becomes the predecessor for the next one. 953 * The current source now becomes the predecessor for the next one.
954 */ 954 */
955 order_pred = gn; 955 order_pred = gn;
956} 956}
957 957
958static void 958static void
959ParseDependencySourceOther(const char *src, GNodeType tOp, 959ParseDependencySourceOther(const char *src, GNodeType tOp,
960 ParseSpecial specType) 960 ParseSpecial specType)
961{ 961{
962 GNode *gn; 962 GNode *gn;
963 963
964 /* 964 /*
965 * If the source is not an attribute, we need to find/create 965 * If the source is not an attribute, we need to find/create
966 * a node for it. After that we can apply any operator to it 966 * a node for it. After that we can apply any operator to it
967 * from a special target or link it to its parents, as 967 * from a special target or link it to its parents, as
968 * appropriate. 968 * appropriate.
969 * 969 *
970 * In the case of a source that was the object of a :: operator, 970 * In the case of a source that was the object of a :: operator,
971 * the attribute is applied to all of its instances (as kept in 971 * the attribute is applied to all of its instances (as kept in
972 * the 'cohorts' list of the node) or all the cohorts are linked 972 * the 'cohorts' list of the node) or all the cohorts are linked
973 * to all the targets. 973 * to all the targets.
974 */ 974 */
975 975
976 /* Find/create the 'src' node and attach to all targets */ 976 /* Find/create the 'src' node and attach to all targets */
977 gn = Targ_GetNode(src); 977 gn = Targ_GetNode(src);
978 if (doing_depend) 978 if (doing_depend)
979 ParseMark(gn); 979 ParseMark(gn);
980 if (tOp != OP_NONE) 980 if (tOp != OP_NONE)
981 gn->type |= tOp; 981 gn->type |= tOp;
982 else 982 else
983 LinkToTargets(gn, specType != SP_NOT); 983 LinkToTargets(gn, specType != SP_NOT);
984} 984}
985 985
986/* 986/*
987 * Given the name of a source in a dependency line, figure out if it is an 987 * Given the name of a source in a dependency line, figure out if it is an
988 * attribute (such as .SILENT) and apply it to the targets if it is. Else 988 * attribute (such as .SILENT) and apply it to the targets if it is. Else
989 * decide if there is some attribute which should be applied *to* the source 989 * decide if there is some attribute which should be applied *to* the source
990 * because of some special target (such as .PHONY) and apply it if so. 990 * because of some special target (such as .PHONY) and apply it if so.
991 * Otherwise, make the source a child of the targets in the list 'targets'. 991 * Otherwise, make the source a child of the targets in the list 'targets'.
992 * 992 *
993 * Input: 993 * Input:
994 * tOp operator (if any) from special targets 994 * tOp operator (if any) from special targets
995 * src name of the source to handle 995 * src name of the source to handle
996 */ 996 */
997static void 997static void
998ParseDependencySource(GNodeType tOp, const char *src, ParseSpecial specType) 998ParseDependencySource(GNodeType tOp, const char *src, ParseSpecial specType)
999{ 999{
1000 if (ParseDependencySourceKeyword(src, specType)) 1000 if (ParseDependencySourceKeyword(src, specType))
1001 return; 1001 return;
1002 1002
1003 if (specType == SP_MAIN) 1003 if (specType == SP_MAIN)
1004 ParseDependencySourceMain(src); 1004 ParseDependencySourceMain(src);
1005 else if (specType == SP_ORDER) 1005 else if (specType == SP_ORDER)
1006 ParseDependencySourceOrder(src); 1006 ParseDependencySourceOrder(src);
1007 else 1007 else
1008 ParseDependencySourceOther(src, tOp, specType); 1008 ParseDependencySourceOther(src, tOp, specType);
1009} 1009}
1010 1010
1011/* 1011/*
1012 * If we have yet to decide on a main target to make, in the absence of any 1012 * If we have yet to decide on a main target to make, in the absence of any
1013 * user input, we want the first target on the first dependency line that is 1013 * user input, we want the first target on the first dependency line that is
1014 * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made. 1014 * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made.
1015 */ 1015 */
1016static void 1016static void
1017FindMainTarget(void) 1017FindMainTarget(void)
1018{ 1018{
1019 GNodeListNode *ln; 1019 GNodeListNode *ln;
1020 1020
1021 if (mainNode != NULL) 1021 if (mainNode != NULL)
1022 return; 1022 return;
1023 1023
1024 for (ln = targets->first; ln != NULL; ln = ln->next) { 1024 for (ln = targets->first; ln != NULL; ln = ln->next) {
1025 GNode *gn = ln->datum; 1025 GNode *gn = ln->datum;
1026 if (!(gn->type & OP_NOTARGET)) { 1026 if (!(gn->type & OP_NOTARGET)) {
1027 DEBUG1(MAKE, "Setting main node to \"%s\"\n", gn->name); 1027 DEBUG1(MAKE, "Setting main node to \"%s\"\n", gn->name);
1028 mainNode = gn; 1028 mainNode = gn;
1029 Targ_SetMain(gn); 1029 Targ_SetMain(gn);
1030 return; 1030 return;
1031 } 1031 }
1032 } 1032 }
1033} 1033}
1034 1034
1035/* 1035/*
1036 * We got to the end of the line while we were still looking at targets. 1036 * We got to the end of the line while we were still looking at targets.
1037 * 1037 *
1038 * Ending a dependency line without an operator is a Bozo no-no. As a 1038 * Ending a dependency line without an operator is a Bozo no-no. As a
1039 * heuristic, this is also often triggered by undetected conflicts from 1039 * heuristic, this is also often triggered by undetected conflicts from
1040 * cvs/rcs merges. 1040 * cvs/rcs merges.
1041 */ 1041 */
1042static void 1042static void
1043ParseErrorNoDependency(const char *lstart) 1043ParseErrorNoDependency(const char *lstart)
1044{ 1044{
1045 if ((strncmp(lstart, "<<<<<<", 6) == 0) || 1045 if ((strncmp(lstart, "<<<<<<", 6) == 0) ||
1046 (strncmp(lstart, "======", 6) == 0) || 1046 (strncmp(lstart, "======", 6) == 0) ||
1047 (strncmp(lstart, ">>>>>>", 6) == 0)) 1047 (strncmp(lstart, ">>>>>>", 6) == 0))
1048 Parse_Error(PARSE_FATAL, 1048 Parse_Error(PARSE_FATAL,
1049 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 1049 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1050 else if (lstart[0] == '.') { 1050 else if (lstart[0] == '.') {
1051 const char *dirstart = lstart + 1; 1051 const char *dirstart = lstart + 1;
1052 const char *dirend; 1052 const char *dirend;
1053 cpp_skip_whitespace(&dirstart); 1053 cpp_skip_whitespace(&dirstart);
1054 dirend = dirstart; 1054 dirend = dirstart;
1055 while (ch_isalnum(*dirend) || *dirend == '-') 1055 while (ch_isalnum(*dirend) || *dirend == '-')
1056 dirend++; 1056 dirend++;
1057 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"", 1057 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
1058 (int)(dirend - dirstart), dirstart); 1058 (int)(dirend - dirstart), dirstart);
1059 } else 1059 } else
1060 Parse_Error(PARSE_FATAL, "Need an operator"); 1060 Parse_Error(PARSE_FATAL, "Need an operator");
1061} 1061}
1062 1062
1063static void 1063static void
1064ParseDependencyTargetWord(const char **pp, const char *lstart) 1064ParseDependencyTargetWord(const char **pp, const char *lstart)
1065{ 1065{
1066 const char *cp = *pp; 1066 const char *cp = *pp;
1067 1067
1068 while (*cp != '\0') { 1068 while (*cp != '\0') {
1069 if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' || 1069 if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' ||
1070 *cp == '(') && 1070 *cp == '(') &&
1071 !ParseIsEscaped(lstart, cp)) 1071 !ParseIsEscaped(lstart, cp))
1072 break; 1072 break;
1073 1073
1074 if (*cp == '$') { 1074 if (*cp == '$') {
1075 /* 1075 /*
1076 * Must be a dynamic source (would have been expanded 1076 * Must be a dynamic source (would have been expanded
1077 * otherwise), so call the Var module to parse the 1077 * otherwise), so call the Var module to parse the
1078 * puppy so we can safely advance beyond it. 1078 * puppy so we can safely advance beyond it.
1079 * 1079 *
1080 * There should be no errors in this, as they would 1080 * There should be no errors in this, as they would
1081 * have been discovered in the initial Var_Subst and 1081 * have been discovered in the initial Var_Subst and
1082 * we wouldn't be here. 1082 * we wouldn't be here.
1083 */ 1083 */
1084 const char *nested_p = cp; 1084 const char *nested_p = cp;
1085 FStr nested_val; 1085 FStr nested_val;
1086 1086
1087 /* XXX: Why VARE_WANTRES? */ 1087 (void)Var_Parse(&nested_p, VAR_CMDLINE, VARE_NONE,
1088 (void)Var_Parse(&nested_p, VAR_CMDLINE, 1088 &nested_val);
1089 VARE_WANTRES | VARE_UNDEFERR, &nested_val); 
1090 /* TODO: handle errors */ 1089 /* TODO: handle errors */
1091 FStr_Done(&nested_val); 1090 FStr_Done(&nested_val);
1092 cp += nested_p - cp; 1091 cp += nested_p - cp;
1093 } else 1092 } else
1094 cp++; 1093 cp++;
1095 } 1094 }
1096 1095
1097 *pp = cp; 1096 *pp = cp;
1098} 1097}
1099 1098
1100/* Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER. */ 1099/* Handle special targets like .PATH, .DEFAULT, .BEGIN, .ORDER. */
1101static void 1100static void
1102ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType, 1101ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType,
1103 const char *line, /* XXX: bad name */ 1102 const char *line, /* XXX: bad name */
1104 SearchPathList **inout_paths) 1103 SearchPathList **inout_paths)
1105{ 1104{
1106 switch (*inout_specType) { 1105 switch (*inout_specType) {
1107 case SP_PATH: 1106 case SP_PATH:
1108 if (*inout_paths == NULL) 1107 if (*inout_paths == NULL)
1109 *inout_paths = Lst_New(); 1108 *inout_paths = Lst_New();
1110 Lst_Append(*inout_paths, &dirSearchPath); 1109 Lst_Append(*inout_paths, &dirSearchPath);
1111 break; 1110 break;
1112 case SP_MAIN: 1111 case SP_MAIN:
1113 /* 1112 /*
1114 * Allow targets from the command line to override the 1113 * Allow targets from the command line to override the
1115 * .MAIN node. 1114 * .MAIN node.
1116 */ 1115 */
1117 if (!Lst_IsEmpty(&opts.create)) 1116 if (!Lst_IsEmpty(&opts.create))
1118 *inout_specType = SP_NOT; 1117 *inout_specType = SP_NOT;
1119 break; 1118 break;
1120 case SP_BEGIN: 1119 case SP_BEGIN:
1121 case SP_END: 1120 case SP_END:
1122 case SP_STALE: 1121 case SP_STALE:
1123 case SP_ERROR: 1122 case SP_ERROR:
1124 case SP_INTERRUPT: { 1123 case SP_INTERRUPT: {
1125 GNode *gn = Targ_GetNode(line); 1124 GNode *gn = Targ_GetNode(line);
1126 if (doing_depend) 1125 if (doing_depend)
1127 ParseMark(gn); 1126 ParseMark(gn);
1128 gn->type |= OP_NOTMAIN | OP_SPECIAL; 1127 gn->type |= OP_NOTMAIN | OP_SPECIAL;
1129 Lst_Append(targets, gn); 1128 Lst_Append(targets, gn);
1130 break; 1129 break;
1131 } 1130 }
1132 case SP_DEFAULT: { 1131 case SP_DEFAULT: {
1133 /* 1132 /*
1134 * Need to create a node to hang commands on, but we don't 1133 * Need to create a node to hang commands on, but we don't
1135 * want it in the graph, nor do we want it to be the Main 1134 * want it in the graph, nor do we want it to be the Main
1136 * Target. We claim the node is a transformation rule to make 1135 * Target. We claim the node is a transformation rule to make
1137 * life easier later, when we'll use Make_HandleUse to 1136 * life easier later, when we'll use Make_HandleUse to
1138 * actually apply the .DEFAULT commands. 1137 * actually apply the .DEFAULT commands.
1139 */ 1138 */
1140 GNode *gn = GNode_New(".DEFAULT"); 1139 GNode *gn = GNode_New(".DEFAULT");
1141 gn->type |= OP_NOTMAIN | OP_TRANSFORM; 1140 gn->type |= OP_NOTMAIN | OP_TRANSFORM;
1142 Lst_Append(targets, gn); 1141 Lst_Append(targets, gn);
1143 defaultNode = gn; 1142 defaultNode = gn;
1144 break; 1143 break;
1145 } 1144 }
1146 case SP_DELETE_ON_ERROR: 1145 case SP_DELETE_ON_ERROR:
1147 deleteOnError = TRUE; 1146 deleteOnError = TRUE;
1148 break; 1147 break;
1149 case SP_NOTPARALLEL: 1148 case SP_NOTPARALLEL:
1150 opts.maxJobs = 1; 1149 opts.maxJobs = 1;
1151 break; 1150 break;
1152 case SP_SINGLESHELL: 1151 case SP_SINGLESHELL:
1153 opts.compatMake = TRUE; 1152 opts.compatMake = TRUE;
1154 break; 1153 break;
1155 case SP_ORDER: 1154 case SP_ORDER:
1156 order_pred = NULL; 1155 order_pred = NULL;
1157 break; 1156 break;
1158 default: 1157 default:
1159 break; 1158 break;
1160 } 1159 }
1161} 1160}
1162 1161
1163/* 1162/*
1164 * .PATH<suffix> has to be handled specially. 1163 * .PATH<suffix> has to be handled specially.
1165 * Call on the suffix module to give us a path to modify. 1164 * Call on the suffix module to give us a path to modify.
1166 */ 1165 */
1167static Boolean 1166static Boolean
1168ParseDoDependencyTargetPath(const char *line, /* XXX: bad name */ 1167ParseDoDependencyTargetPath(const char *line, /* XXX: bad name */
1169 SearchPathList **inout_paths) 1168 SearchPathList **inout_paths)
1170{ 1169{
1171 SearchPath *path; 1170 SearchPath *path;
1172 1171
1173 path = Suff_GetPath(&line[5]); 1172 path = Suff_GetPath(&line[5]);
1174 if (path == NULL) { 1173 if (path == NULL) {
1175 Parse_Error(PARSE_FATAL, 1174 Parse_Error(PARSE_FATAL,
1176 "Suffix '%s' not defined (yet)", &line[5]); 1175 "Suffix '%s' not defined (yet)", &line[5]);
1177 return FALSE; 1176 return FALSE;
1178 } 1177 }
1179 1178
1180 if (*inout_paths == NULL) 1179 if (*inout_paths == NULL)
1181 *inout_paths = Lst_New(); 1180 *inout_paths = Lst_New();
1182 Lst_Append(*inout_paths, path); 1181 Lst_Append(*inout_paths, path);
1183 1182
1184 return TRUE; 1183 return TRUE;
1185} 1184}
1186 1185
1187/* 1186/*
1188 * See if it's a special target and if so set specType to match it. 1187 * See if it's a special target and if so set specType to match it.
1189 */ 1188 */
1190static Boolean 1189static Boolean
1191ParseDoDependencyTarget(const char *line, /* XXX: bad name */ 1190ParseDoDependencyTarget(const char *line, /* XXX: bad name */
1192 ParseSpecial *inout_specType, 1191 ParseSpecial *inout_specType,
1193 GNodeType *out_tOp, SearchPathList **inout_paths) 1192 GNodeType *out_tOp, SearchPathList **inout_paths)
1194{ 1193{
1195 int keywd; 1194 int keywd;
1196 1195
1197 if (!(line[0] == '.' && ch_isupper(line[1]))) 1196 if (!(line[0] == '.' && ch_isupper(line[1])))
1198 return TRUE; 1197 return TRUE;
1199 1198
1200 /* 1199 /*
1201 * See if the target is a special target that must have it 1200 * See if the target is a special target that must have it
1202 * or its sources handled specially. 1201 * or its sources handled specially.
1203 */ 1202 */
1204 keywd = ParseFindKeyword(line); 1203 keywd = ParseFindKeyword(line);
1205 if (keywd != -1) { 1204 if (keywd != -1) {
1206 if (*inout_specType == SP_PATH && 1205 if (*inout_specType == SP_PATH &&
1207 parseKeywords[keywd].spec != SP_PATH) { 1206 parseKeywords[keywd].spec != SP_PATH) {
1208 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 1207 Parse_Error(PARSE_FATAL, "Mismatched special targets");
1209 return FALSE; 1208 return FALSE;
1210 } 1209 }
1211 1210
1212 *inout_specType = parseKeywords[keywd].spec; 1211 *inout_specType = parseKeywords[keywd].spec;
1213 *out_tOp = parseKeywords[keywd].op; 1212 *out_tOp = parseKeywords[keywd].op;
1214 1213
1215 ParseDoDependencyTargetSpecial(inout_specType, line, 1214 ParseDoDependencyTargetSpecial(inout_specType, line,
1216 inout_paths); 1215 inout_paths);
1217 1216
1218 } else if (strncmp(line, ".PATH", 5) == 0) { 1217 } else if (strncmp(line, ".PATH", 5) == 0) {
1219 *inout_specType = SP_PATH; 1218 *inout_specType = SP_PATH;
1220 if (!ParseDoDependencyTargetPath(line, inout_paths)) 1219 if (!ParseDoDependencyTargetPath(line, inout_paths))
1221 return FALSE; 1220 return FALSE;
1222 } 1221 }
1223 return TRUE; 1222 return TRUE;
1224} 1223}
1225 1224
1226static void 1225static void
1227ParseDoDependencyTargetMundane(char *line, /* XXX: bad name */ 1226ParseDoDependencyTargetMundane(char *line, /* XXX: bad name */
1228 StringList *curTargs) 1227 StringList *curTargs)
1229{ 1228{
1230 if (Dir_HasWildcards(line)) { 1229 if (Dir_HasWildcards(line)) {
1231 /* 1230 /*
1232 * Targets are to be sought only in the current directory, 1231 * Targets are to be sought only in the current directory,
1233 * so create an empty path for the thing. Note we need to 1232 * so create an empty path for the thing. Note we need to
1234 * use Dir_Destroy in the destruction of the path as the 1233 * use Dir_Destroy in the destruction of the path as the
1235 * Dir module could have added a directory to the path... 1234 * Dir module could have added a directory to the path...
1236 */ 1235 */
1237 SearchPath *emptyPath = SearchPath_New(); 1236 SearchPath *emptyPath = SearchPath_New();
1238 1237
1239 Dir_Expand(line, emptyPath, curTargs); 1238 Dir_Expand(line, emptyPath, curTargs);
1240 1239
1241 SearchPath_Free(emptyPath); 1240 SearchPath_Free(emptyPath);
1242 } else { 1241 } else {
1243 /* 1242 /*
1244 * No wildcards, but we want to avoid code duplication, 1243 * No wildcards, but we want to avoid code duplication,
1245 * so create a list with the word on it. 1244 * so create a list with the word on it.
1246 */ 1245 */
1247 Lst_Append(curTargs, line); 1246 Lst_Append(curTargs, line);
1248 } 1247 }
1249 1248
1250 /* Apply the targets. */ 1249 /* Apply the targets. */
1251 1250
1252 while (!Lst_IsEmpty(curTargs)) { 1251 while (!Lst_IsEmpty(curTargs)) {
1253 char *targName = Lst_Dequeue(curTargs); 1252 char *targName = Lst_Dequeue(curTargs);
1254 GNode *gn = Suff_IsTransform(targName) 1253 GNode *gn = Suff_IsTransform(targName)
1255 ? Suff_AddTransform(targName) 1254 ? Suff_AddTransform(targName)
1256 : Targ_GetNode(targName); 1255 : Targ_GetNode(targName);
1257 if (doing_depend) 1256 if (doing_depend)
1258 ParseMark(gn); 1257 ParseMark(gn);
1259 1258
1260 Lst_Append(targets, gn); 1259 Lst_Append(targets, gn);
1261 } 1260 }
1262} 1261}
1263 1262
1264static void 1263static void
1265ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart) 1264ParseDoDependencyTargetExtraWarn(char **pp, const char *lstart)
1266{ 1265{
1267 Boolean warning = FALSE; 1266 Boolean warning = FALSE;
1268 char *cp = *pp; 1267 char *cp = *pp;
1269 1268
1270 while (*cp != '\0') { 1269 while (*cp != '\0') {
1271 if (!ParseIsEscaped(lstart, cp) && (*cp == '!' || *cp == ':')) 1270 if (!ParseIsEscaped(lstart, cp) && (*cp == '!' || *cp == ':'))
1272 break; 1271 break;
1273 if (ParseIsEscaped(lstart, cp) || (*cp != ' ' && *cp != '\t')) 1272 if (ParseIsEscaped(lstart, cp) || (*cp != ' ' && *cp != '\t'))
1274 warning = TRUE; 1273 warning = TRUE;
1275 cp++; 1274 cp++;
1276 } 1275 }
1277 if (warning) 1276 if (warning)
1278 Parse_Error(PARSE_WARNING, "Extra target ignored"); 1277 Parse_Error(PARSE_WARNING, "Extra target ignored");
1279 1278
1280 *pp = cp; 1279 *pp = cp;
1281} 1280}
1282 1281
1283static void 1282static void
1284ParseDoDependencyCheckSpec(ParseSpecial specType) 1283ParseDoDependencyCheckSpec(ParseSpecial specType)
1285{ 1284{
1286 switch (specType) { 1285 switch (specType) {
1287 default: 1286 default:
1288 Parse_Error(PARSE_WARNING, 1287 Parse_Error(PARSE_WARNING,
1289 "Special and mundane targets don't mix. " 1288 "Special and mundane targets don't mix. "
1290 "Mundane ones ignored"); 1289 "Mundane ones ignored");
1291 break; 1290 break;
1292 case SP_DEFAULT: 1291 case SP_DEFAULT:
1293 case SP_STALE: 1292 case SP_STALE:
1294 case SP_BEGIN: 1293 case SP_BEGIN:
1295 case SP_END: 1294 case SP_END:
1296 case SP_ERROR: 1295 case SP_ERROR:
1297 case SP_INTERRUPT: 1296 case SP_INTERRUPT:
1298 /* 1297 /*
1299 * These create nodes on which to hang commands, so targets 1298 * These create nodes on which to hang commands, so targets
1300 * shouldn't be empty. 1299 * shouldn't be empty.
1301 */ 1300 */
1302 case SP_NOT: 1301 case SP_NOT:
1303 /* Nothing special here -- targets can be empty if it wants. */ 1302 /* Nothing special here -- targets can be empty if it wants. */
1304 break; 1303 break;
1305 } 1304 }
1306} 1305}
1307 1306
1308static Boolean 1307static Boolean
1309ParseDoDependencyParseOp(char **pp, const char *lstart, GNodeType *out_op) 1308ParseDoDependencyParseOp(char **pp, const char *lstart, GNodeType *out_op)
1310{ 1309{
1311 const char *cp = *pp; 1310 const char *cp = *pp;
1312 1311
1313 if (*cp == '!') { 1312 if (*cp == '!') {
1314 *out_op = OP_FORCE; 1313 *out_op = OP_FORCE;
1315 (*pp)++; 1314 (*pp)++;
1316 return TRUE; 1315 return TRUE;
1317 } 1316 }
1318 1317
1319 if (*cp == ':') { 1318 if (*cp == ':') {
1320 if (cp[1] == ':') { 1319 if (cp[1] == ':') {
1321 *out_op = OP_DOUBLEDEP; 1320 *out_op = OP_DOUBLEDEP;
1322 (*pp) += 2; 1321 (*pp) += 2;
1323 } else { 1322 } else {
1324 *out_op = OP_DEPENDS; 1323 *out_op = OP_DEPENDS;
1325 (*pp)++; 1324 (*pp)++;
1326 } 1325 }
1327 return TRUE; 1326 return TRUE;
1328 } 1327 }
1329 1328
1330 { 1329 {
1331 const char *msg = lstart[0] == '.' 1330 const char *msg = lstart[0] == '.'
1332 ? "Unknown directive" : "Missing dependency operator"; 1331 ? "Unknown directive" : "Missing dependency operator";
1333 Parse_Error(PARSE_FATAL, "%s", msg); 1332 Parse_Error(PARSE_FATAL, "%s", msg);
1334 return FALSE; 1333 return FALSE;
1335 } 1334 }
1336} 1335}
1337 1336
1338static void 1337static void
1339ClearPaths(SearchPathList *paths) 1338ClearPaths(SearchPathList *paths)
1340{ 1339{
1341 if (paths != NULL) { 1340 if (paths != NULL) {
1342 SearchPathListNode *ln; 1341 SearchPathListNode *ln;
1343 for (ln = paths->first; ln != NULL; ln = ln->next) 1342 for (ln = paths->first; ln != NULL; ln = ln->next)
1344 SearchPath_Clear(ln->datum); 1343 SearchPath_Clear(ln->datum);
1345 } 1344 }
1346 1345
1347 Dir_SetPATH(); 1346 Dir_SetPATH();
1348} 1347}
1349 1348
1350static void 1349static void
1351ParseDoDependencySourcesEmpty(ParseSpecial specType, SearchPathList *paths) 1350ParseDoDependencySourcesEmpty(ParseSpecial specType, SearchPathList *paths)
1352{ 1351{
1353 switch (specType) { 1352 switch (specType) {
1354 case SP_SUFFIXES: 1353 case SP_SUFFIXES:
1355 Suff_ClearSuffixes(); 1354 Suff_ClearSuffixes();
1356 break; 1355 break;
1357 case SP_PRECIOUS: 1356 case SP_PRECIOUS:
1358 allPrecious = TRUE; 1357 allPrecious = TRUE;
1359 break; 1358 break;
1360 case SP_IGNORE: 1359 case SP_IGNORE:
1361 opts.ignoreErrors = TRUE; 1360 opts.ignoreErrors = TRUE;
1362 break; 1361 break;
1363 case SP_SILENT: 1362 case SP_SILENT:
1364 opts.beSilent = TRUE; 1363 opts.beSilent = TRUE;
1365 break; 1364 break;
1366 case SP_PATH: 1365 case SP_PATH:
1367 ClearPaths(paths); 1366 ClearPaths(paths);
1368 break; 1367 break;
1369#ifdef POSIX 1368#ifdef POSIX
1370 case SP_POSIX: 1369 case SP_POSIX:
1371 Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1370 Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1372 break; 1371 break;
1373#endif 1372#endif
1374 default: 1373 default:
1375 break; 1374 break;
1376 } 1375 }
1377} 1376}
1378 1377
1379static void 1378static void
1380AddToPaths(const char *dir, SearchPathList *paths) 1379AddToPaths(const char *dir, SearchPathList *paths)
1381{ 1380{
1382 if (paths != NULL) { 1381 if (paths != NULL) {
1383 SearchPathListNode *ln; 1382 SearchPathListNode *ln;
1384 for (ln = paths->first; ln != NULL; ln = ln->next) 1383 for (ln = paths->first; ln != NULL; ln = ln->next)
1385 (void)Dir_AddDir(ln->datum, dir); 1384 (void)Dir_AddDir(ln->datum, dir);
1386 } 1385 }
1387} 1386}
1388 1387
1389/* 1388/*
1390 * If the target was one that doesn't take files as its sources 1389 * If the target was one that doesn't take files as its sources
1391 * but takes something like suffixes, we take each 1390 * but takes something like suffixes, we take each
1392 * space-separated word on the line as a something and deal 1391 * space-separated word on the line as a something and deal
1393 * with it accordingly. 1392 * with it accordingly.
1394 * 1393 *
1395 * If the target was .SUFFIXES, we take each source as a 1394 * If the target was .SUFFIXES, we take each source as a
1396 * suffix and add it to the list of suffixes maintained by the 1395 * suffix and add it to the list of suffixes maintained by the
1397 * Suff module. 1396 * Suff module.
1398 * 1397 *
1399 * If the target was a .PATH, we add the source as a directory 1398 * If the target was a .PATH, we add the source as a directory
1400 * to search on the search path. 1399 * to search on the search path.
1401 * 1400 *
1402 * If it was .INCLUDES, the source is taken to be the suffix of 1401 * If it was .INCLUDES, the source is taken to be the suffix of
1403 * files which will be #included and whose search path should 1402 * files which will be #included and whose search path should
1404 * be present in the .INCLUDES variable. 1403 * be present in the .INCLUDES variable.
1405 * 1404 *
1406 * If it was .LIBS, the source is taken to be the suffix of 1405 * If it was .LIBS, the source is taken to be the suffix of
1407 * files which are considered libraries and whose search path 1406 * files which are considered libraries and whose search path
1408 * should be present in the .LIBS variable. 1407 * should be present in the .LIBS variable.
1409 * 1408 *
1410 * If it was .NULL, the source is the suffix to use when a file 1409 * If it was .NULL, the source is the suffix to use when a file
1411 * has no valid suffix. 1410 * has no valid suffix.
1412 * 1411 *
1413 * If it was .OBJDIR, the source is a new definition for .OBJDIR, 1412 * If it was .OBJDIR, the source is a new definition for .OBJDIR,
1414 * and will cause make to do a new chdir to that path. 1413 * and will cause make to do a new chdir to that path.
1415 */ 1414 */
1416static void 1415static void
1417ParseDoDependencySourceSpecial(ParseSpecial specType, char *word, 1416ParseDoDependencySourceSpecial(ParseSpecial specType, char *word,
1418 SearchPathList *paths) 1417 SearchPathList *paths)
1419{ 1418{
1420 switch (specType) { 1419 switch (specType) {
1421 case SP_SUFFIXES: 1420 case SP_SUFFIXES:
1422 Suff_AddSuffix(word, &mainNode); 1421 Suff_AddSuffix(word, &mainNode);
1423 break; 1422 break;
1424 case SP_PATH: 1423 case SP_PATH:
1425 AddToPaths(word, paths); 1424 AddToPaths(word, paths);
1426 break; 1425 break;
1427 case SP_INCLUDES: 1426 case SP_INCLUDES:
1428 Suff_AddInclude(word); 1427 Suff_AddInclude(word);
1429 break; 1428 break;
1430 case SP_LIBS: 1429 case SP_LIBS:
1431 Suff_AddLib(word); 1430 Suff_AddLib(word);
1432 break; 1431 break;
1433 case SP_NULL: 1432 case SP_NULL:
1434 Suff_SetNull(word); 1433 Suff_SetNull(word);
1435 break; 1434 break;
1436 case SP_OBJDIR: 1435 case SP_OBJDIR:
1437 Main_SetObjdir(FALSE, "%s", word); 1436 Main_SetObjdir(FALSE, "%s", word);
1438 break; 1437 break;
1439 default: 1438 default:
1440 break; 1439 break;
1441 } 1440 }
1442} 1441}
1443 1442
1444static Boolean 1443static Boolean
1445ParseDoDependencyTargets(char **inout_cp, 1444ParseDoDependencyTargets(char **inout_cp,
1446 char **inout_line, 1445 char **inout_line,
1447 const char *lstart, 1446 const char *lstart,
1448 ParseSpecial *inout_specType, 1447 ParseSpecial *inout_specType,
1449 GNodeType *inout_tOp, 1448 GNodeType *inout_tOp,
1450 SearchPathList **inout_paths, 1449 SearchPathList **inout_paths,
1451 StringList *curTargs) 1450 StringList *curTargs)
1452{ 1451{
1453 char *cp; 1452 char *cp;
1454 char *tgt = *inout_line; 1453 char *tgt = *inout_line;
1455 char savec; 1454 char savec;
1456 const char *p; 1455 const char *p;
1457 1456
1458 for (;;) { 1457 for (;;) {
1459 /* 1458 /*
1460 * Here LINE points to the beginning of the next word, and 1459 * Here LINE points to the beginning of the next word, and
1461 * LSTART points to the actual beginning of the line. 1460 * LSTART points to the actual beginning of the line.
1462 */ 1461 */
1463 1462
1464 /* Find the end of the next word. */ 1463 /* Find the end of the next word. */
1465 cp = tgt; 1464 cp = tgt;
1466 p = cp; 1465 p = cp;
1467 ParseDependencyTargetWord(&p, lstart); 1466 ParseDependencyTargetWord(&p, lstart);
1468 cp += p - cp; 1467 cp += p - cp;
1469 1468
1470 /* 1469 /*
1471 * If the word is followed by a left parenthesis, it's the 1470 * If the word is followed by a left parenthesis, it's the
1472 * name of an object file inside an archive (ar file). 1471 * name of an object file inside an archive (ar file).
1473 */ 1472 */
1474 if (!ParseIsEscaped(lstart, cp) && *cp == '(') { 1473 if (!ParseIsEscaped(lstart, cp) && *cp == '(') {
1475 /* 1474 /*
1476 * Archives must be handled specially to make sure the 1475 * Archives must be handled specially to make sure the
1477 * OP_ARCHV flag is set in their 'type' field, for one 1476 * OP_ARCHV flag is set in their 'type' field, for one
1478 * thing, and because things like "archive(file1.o 1477 * thing, and because things like "archive(file1.o
1479 * file2.o file3.o)" are permissible. 1478 * file2.o file3.o)" are permissible.
1480 * 1479 *
1481 * Arch_ParseArchive will set 'line' to be the first 1480 * Arch_ParseArchive will set 'line' to be the first
1482 * non-blank after the archive-spec. It creates/finds 1481 * non-blank after the archive-spec. It creates/finds
1483 * nodes for the members and places them on the given 1482 * nodes for the members and places them on the given
1484 * list, returning TRUE if all went well and FALSE if 1483 * list, returning TRUE if all went well and FALSE if
1485 * there was an error in the specification. On error, 1484 * there was an error in the specification. On error,
1486 * line should remain untouched. 1485 * line should remain untouched.
1487 */ 1486 */
1488 if (!Arch_ParseArchive(&tgt, targets, VAR_CMDLINE)) { 1487 if (!Arch_ParseArchive(&tgt, targets, VAR_CMDLINE)) {
1489 Parse_Error(PARSE_FATAL, 1488 Parse_Error(PARSE_FATAL,
1490 "Error in archive specification: \"%s\"", 1489 "Error in archive specification: \"%s\"",
1491 tgt); 1490 tgt);
1492 return FALSE; 1491 return FALSE;
1493 } 1492 }
1494 1493
1495 cp = tgt; 1494 cp = tgt;
1496 continue; 1495 continue;
1497 } 1496 }
1498 1497
1499 if (*cp == '\0') { 1498 if (*cp == '\0') {
1500 ParseErrorNoDependency(lstart); 1499 ParseErrorNoDependency(lstart);
1501 return FALSE; 1500 return FALSE;
1502 } 1501 }
1503 1502
1504 /* Insert a null terminator. */ 1503 /* Insert a null terminator. */
1505 savec = *cp; 1504 savec = *cp;
1506 *cp = '\0'; 1505 *cp = '\0';
1507 1506
1508 if (!ParseDoDependencyTarget(tgt, inout_specType, inout_tOp, 1507 if (!ParseDoDependencyTarget(tgt, inout_specType, inout_tOp,
1509 inout_paths)) 1508 inout_paths))
1510 return FALSE; 1509 return FALSE;
1511 1510
1512 /* 1511 /*
1513 * Have word in line. Get or create its node and stick it at 1512 * Have word in line. Get or create its node and stick it at
1514 * the end of the targets list 1513 * the end of the targets list
1515 */ 1514 */
1516 if (*inout_specType == SP_NOT && *tgt != '\0') 1515 if (*inout_specType == SP_NOT && *tgt != '\0')
1517 ParseDoDependencyTargetMundane(tgt, curTargs); 1516 ParseDoDependencyTargetMundane(tgt, curTargs);
1518 else if (*inout_specType == SP_PATH && *tgt != '.' && 1517 else if (*inout_specType == SP_PATH && *tgt != '.' &&
1519 *tgt != '\0') 1518 *tgt != '\0')
1520 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", 1519 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored",
1521 tgt); 1520 tgt);
1522 1521
1523 /* Don't need the inserted null terminator any more. */ 1522 /* Don't need the inserted null terminator any more. */
1524 *cp = savec; 1523 *cp = savec;
1525 1524
1526 /* 1525 /*
1527 * If it is a special type and not .PATH, it's the only target 1526 * If it is a special type and not .PATH, it's the only target
1528 * we allow on this line. 1527 * we allow on this line.
1529 */ 1528 */
1530 if (*inout_specType != SP_NOT && *inout_specType != SP_PATH) 1529 if (*inout_specType != SP_NOT && *inout_specType != SP_PATH)
1531 ParseDoDependencyTargetExtraWarn(&cp, lstart); 1530 ParseDoDependencyTargetExtraWarn(&cp, lstart);
1532 else 1531 else
1533 pp_skip_whitespace(&cp); 1532 pp_skip_whitespace(&cp);
1534 1533
1535 tgt = cp; 1534 tgt = cp;
1536 if (*tgt == '\0') 1535 if (*tgt == '\0')
1537 break; 1536 break;
1538 if ((*tgt == '!' || *tgt == ':') && 1537 if ((*tgt == '!' || *tgt == ':') &&
1539 !ParseIsEscaped(lstart, tgt)) 1538 !ParseIsEscaped(lstart, tgt))
1540 break; 1539 break;
1541 } 1540 }
1542 1541
1543 *inout_cp = cp; 1542 *inout_cp = cp;
1544 *inout_line = tgt; 1543 *inout_line = tgt;
1545 return TRUE; 1544 return TRUE;
1546} 1545}
1547 1546
1548static void 1547static void
1549ParseDoDependencySourcesSpecial(char *start, char *end, 1548ParseDoDependencySourcesSpecial(char *start, char *end,
1550 ParseSpecial specType, SearchPathList *paths) 1549 ParseSpecial specType, SearchPathList *paths)
1551{ 1550{
1552 char savec; 1551 char savec;
1553 1552
1554 while (*start != '\0') { 1553 while (*start != '\0') {
1555 while (*end != '\0' && !ch_isspace(*end)) 1554 while (*end != '\0' && !ch_isspace(*end))
1556 end++; 1555 end++;
1557 savec = *end; 1556 savec = *end;
1558 *end = '\0'; 1557 *end = '\0';
1559 ParseDoDependencySourceSpecial(specType, start, paths); 1558 ParseDoDependencySourceSpecial(specType, start, paths);
1560 *end = savec; 1559 *end = savec;
1561 if (savec != '\0') 1560 if (savec != '\0')
1562 end++; 1561 end++;
1563 pp_skip_whitespace(&end); 1562 pp_skip_whitespace(&end);
1564 start = end; 1563 start = end;
1565 } 1564 }
1566} 1565}
1567 1566
1568static Boolean 1567static Boolean
1569ParseDoDependencySourcesMundane(char *start, char *end, 1568ParseDoDependencySourcesMundane(char *start, char *end,
1570 ParseSpecial specType, GNodeType tOp) 1569 ParseSpecial specType, GNodeType tOp)
1571{ 1570{
1572 while (*start != '\0') { 1571 while (*start != '\0') {
1573 /* 1572 /*
1574 * The targets take real sources, so we must beware of archive 1573 * The targets take real sources, so we must beware of archive
1575 * specifications (i.e. things with left parentheses in them) 1574 * specifications (i.e. things with left parentheses in them)
1576 * and handle them accordingly. 1575 * and handle them accordingly.
1577 */ 1576 */
1578 for (; *end != '\0' && !ch_isspace(*end); end++) { 1577 for (; *end != '\0' && !ch_isspace(*end); end++) {
1579 if (*end == '(' && end > start && end[-1] != '$') { 1578 if (*end == '(' && end > start && end[-1] != '$') {
1580 /* 1579 /*
1581 * Only stop for a left parenthesis if it 1580 * Only stop for a left parenthesis if it
1582 * isn't at the start of a word (that'll be 1581 * isn't at the start of a word (that'll be
1583 * for variable changes later) and isn't 1582 * for variable changes later) and isn't
1584 * preceded by a dollar sign (a dynamic 1583 * preceded by a dollar sign (a dynamic
1585 * source). 1584 * source).
1586 */ 1585 */
1587 break; 1586 break;
1588 } 1587 }
1589 } 1588 }
1590 1589
1591 if (*end == '(') { 1590 if (*end == '(') {
1592 GNodeList sources = LST_INIT; 1591 GNodeList sources = LST_INIT;
1593 if (!Arch_ParseArchive(&start, &sources, VAR_CMDLINE)) { 1592 if (!Arch_ParseArchive(&start, &sources, VAR_CMDLINE)) {
1594 Parse_Error(PARSE_FATAL, 1593 Parse_Error(PARSE_FATAL,
1595 "Error in source archive spec \"%s\"", 1594 "Error in source archive spec \"%s\"",
1596 start); 1595 start);
1597 return FALSE; 1596 return FALSE;
1598 } 1597 }
1599 1598
1600 while (!Lst_IsEmpty(&sources)) { 1599 while (!Lst_IsEmpty(&sources)) {
1601 GNode *gn = Lst_Dequeue(&sources); 1600 GNode *gn = Lst_Dequeue(&sources);
1602 ParseDependencySource(tOp, gn->name, specType); 1601 ParseDependencySource(tOp, gn->name, specType);
1603 } 1602 }
1604 Lst_Done(&sources); 1603 Lst_Done(&sources);
1605 end = start; 1604 end = start;
1606 } else { 1605 } else {
1607 if (*end != '\0') { 1606 if (*end != '\0') {
1608 *end = '\0'; 1607 *end = '\0';
1609 end++; 1608 end++;
1610 } 1609 }
1611 1610
1612 ParseDependencySource(tOp, start, specType); 1611 ParseDependencySource(tOp, start, specType);
1613 } 1612 }
1614 pp_skip_whitespace(&end); 1613 pp_skip_whitespace(&end);
1615 start = end; 1614 start = end;
1616 } 1615 }
1617 return TRUE; 1616 return TRUE;
1618} 1617}
1619 1618
1620/* Parse a dependency line consisting of targets, followed by a dependency 1619/* Parse a dependency line consisting of targets, followed by a dependency
1621 * operator, optionally followed by sources. 1620 * operator, optionally followed by sources.
1622 * 1621 *
1623 * The nodes of the sources are linked as children to the nodes of the 1622 * The nodes of the sources are linked as children to the nodes of the
1624 * targets. Nodes are created as necessary. 1623 * targets. Nodes are created as necessary.
1625 * 1624 *
1626 * The operator is applied to each node in the global 'targets' list, 1625 * The operator is applied to each node in the global 'targets' list,
1627 * which is where the nodes found for the targets are kept, by means of 1626 * which is where the nodes found for the targets are kept, by means of
1628 * the ParseDoOp function. 1627 * the ParseDoOp function.
1629 * 1628 *
1630 * The sources are parsed in much the same way as the targets, except 1629 * The sources are parsed in much the same way as the targets, except
1631 * that they are expanded using the wildcarding scheme of the C-Shell, 1630 * that they are expanded using the wildcarding scheme of the C-Shell,
1632 * and a target is created for each expanded word. Each of the resulting 1631 * and a target is created for each expanded word. Each of the resulting
1633 * nodes is then linked to each of the targets as one of its children. 1632 * nodes is then linked to each of the targets as one of its children.
1634 * 1633 *
1635 * Certain targets and sources such as .PHONY or .PRECIOUS are handled 1634 * Certain targets and sources such as .PHONY or .PRECIOUS are handled
1636 * specially. These are the ones detailed by the specType variable. 1635 * specially. These are the ones detailed by the specType variable.
1637 * 1636 *
1638 * The storing of transformation rules such as '.c.o' is also taken care of 1637 * The storing of transformation rules such as '.c.o' is also taken care of
1639 * here. A target is recognized as a transformation rule by calling 1638 * here. A target is recognized as a transformation rule by calling
1640 * Suff_IsTransform. If it is a transformation rule, its node is gotten 1639 * Suff_IsTransform. If it is a transformation rule, its node is gotten
1641 * from the suffix module via Suff_AddTransform rather than the standard 1640 * from the suffix module via Suff_AddTransform rather than the standard
1642 * Targ_FindNode in the target module. 1641 * Targ_FindNode in the target module.
1643 * 1642 *
1644 * Upon return, the value of the line is unspecified. 1643 * Upon return, the value of the line is unspecified.
1645 */ 1644 */
1646static void 1645static void
1647ParseDoDependency(char *line) 1646ParseDoDependency(char *line)
1648{ 1647{
1649 char *cp; /* our current position */ 1648 char *cp; /* our current position */
1650 GNodeType op; /* the operator on the line */ 1649 GNodeType op; /* the operator on the line */
1651 SearchPathList *paths; /* search paths to alter when parsing 1650 SearchPathList *paths; /* search paths to alter when parsing
1652 * a list of .PATH targets */ 1651 * a list of .PATH targets */
1653 GNodeType tOp; /* operator from special target */ 1652 GNodeType tOp; /* operator from special target */
1654 /* target names to be found and added to the targets list */ 1653 /* target names to be found and added to the targets list */
1655 StringList curTargs = LST_INIT; 1654 StringList curTargs = LST_INIT;
1656 char *lstart = line; 1655 char *lstart = line;
1657 1656
1658 /* 1657 /*
1659 * specType contains the SPECial TYPE of the current target. It is 1658 * specType contains the SPECial TYPE of the current target. It is
1660 * SP_NOT if the target is unspecial. If it *is* special, however, the 1659 * SP_NOT if the target is unspecial. If it *is* special, however, the
1661 * children are linked as children of the parent but not vice versa. 1660 * children are linked as children of the parent but not vice versa.
1662 */ 1661 */
1663 ParseSpecial specType = SP_NOT; 1662 ParseSpecial specType = SP_NOT;
1664 1663
1665 DEBUG1(PARSE, "ParseDoDependency(%s)\n", line); 1664 DEBUG1(PARSE, "ParseDoDependency(%s)\n", line);
1666 tOp = OP_NONE; 1665 tOp = OP_NONE;
1667 1666
1668 paths = NULL; 1667 paths = NULL;
1669 1668
1670 /* 1669 /*
1671 * First, grind through the targets. 1670 * First, grind through the targets.
1672 */ 1671 */
1673 /* XXX: don't use line as an iterator variable */ 1672 /* XXX: don't use line as an iterator variable */
1674 if (!ParseDoDependencyTargets(&cp, &line, lstart, &specType, &tOp, 1673 if (!ParseDoDependencyTargets(&cp, &line, lstart, &specType, &tOp,
1675 &paths, &curTargs)) 1674 &paths, &curTargs))
1676 goto out; 1675 goto out;
1677 1676
1678 /* 1677 /*
1679 * Don't need the list of target names anymore. 1678 * Don't need the list of target names anymore.
1680 * The targets themselves are now in the global variable 'targets'. 1679 * The targets themselves are now in the global variable 'targets'.
1681 */ 1680 */
1682 Lst_Done(&curTargs); 1681 Lst_Done(&curTargs);
1683 Lst_Init(&curTargs); 1682 Lst_Init(&curTargs);
1684 1683
1685 if (!Lst_IsEmpty(targets)) 1684 if (!Lst_IsEmpty(targets))
1686 ParseDoDependencyCheckSpec(specType); 1685 ParseDoDependencyCheckSpec(specType);
1687 1686
1688 /* 1687 /*
1689 * Have now parsed all the target names. Must parse the operator next. 1688 * Have now parsed all the target names. Must parse the operator next.
1690 */ 1689 */
1691 if (!ParseDoDependencyParseOp(&cp, lstart, &op)) 1690 if (!ParseDoDependencyParseOp(&cp, lstart, &op))
1692 goto out; 1691 goto out;
1693 1692
1694 /* 1693 /*
1695 * Apply the operator to the target. This is how we remember which 1694 * Apply the operator to the target. This is how we remember which
1696 * operator a target was defined with. It fails if the operator 1695 * operator a target was defined with. It fails if the operator
1697 * used isn't consistent across all references. 1696 * used isn't consistent across all references.
1698 */ 1697 */
1699 ApplyDependencyOperator(op); 1698 ApplyDependencyOperator(op);
1700 1699
1701 /* 1700 /*
1702 * Onward to the sources. 1701 * Onward to the sources.
1703 * 1702 *
1704 * LINE will now point to the first source word, if any, or the 1703 * LINE will now point to the first source word, if any, or the
1705 * end of the string if not. 1704 * end of the string if not.
1706 */ 1705 */
1707 pp_skip_whitespace(&cp); 1706 pp_skip_whitespace(&cp);
1708 line = cp; /* XXX: 'line' is an inappropriate name */ 1707 line = cp; /* XXX: 'line' is an inappropriate name */
1709 1708
1710 /* 1709 /*
1711 * Several special targets take different actions if present with no 1710 * Several special targets take different actions if present with no
1712 * sources: 1711 * sources:
1713 * a .SUFFIXES line with no sources clears out all old suffixes 1712 * a .SUFFIXES line with no sources clears out all old suffixes
1714 * a .PRECIOUS line makes all targets precious 1713 * a .PRECIOUS line makes all targets precious
1715 * a .IGNORE line ignores errors for all targets 1714 * a .IGNORE line ignores errors for all targets
1716 * a .SILENT line creates silence when making all targets 1715 * a .SILENT line creates silence when making all targets
1717 * a .PATH removes all directories from the search path(s). 1716 * a .PATH removes all directories from the search path(s).
1718 */ 1717 */
1719 if (line[0] == '\0') { 1718 if (line[0] == '\0') {
1720 ParseDoDependencySourcesEmpty(specType, paths); 1719 ParseDoDependencySourcesEmpty(specType, paths);
1721 } else if (specType == SP_MFLAGS) { 1720 } else if (specType == SP_MFLAGS) {
1722 /* 1721 /*
1723 * Call on functions in main.c to deal with these arguments and 1722 * Call on functions in main.c to deal with these arguments and
1724 * set the initial character to a null-character so the loop to 1723 * set the initial character to a null-character so the loop to
1725 * get sources won't get anything 1724 * get sources won't get anything
1726 */ 1725 */
1727 Main_ParseArgLine(line); 1726 Main_ParseArgLine(line);
1728 *line = '\0'; 1727 *line = '\0';
1729 } else if (specType == SP_SHELL) { 1728 } else if (specType == SP_SHELL) {
1730 if (!Job_ParseShell(line)) { 1729 if (!Job_ParseShell(line)) {
1731 Parse_Error(PARSE_FATAL, 1730 Parse_Error(PARSE_FATAL,
1732 "improper shell specification"); 1731 "improper shell specification");
1733 goto out; 1732 goto out;
1734 } 1733 }
1735 *line = '\0'; 1734 *line = '\0';
1736 } else if (specType == SP_NOTPARALLEL || specType == SP_SINGLESHELL || 1735 } else if (specType == SP_NOTPARALLEL || specType == SP_SINGLESHELL ||
1737 specType == SP_DELETE_ON_ERROR) { 1736 specType == SP_DELETE_ON_ERROR) {
1738 *line = '\0'; 1737 *line = '\0';
1739 } 1738 }
1740 1739
1741 /* Now go for the sources. */ 1740 /* Now go for the sources. */
1742 if (specType == SP_SUFFIXES || specType == SP_PATH || 1741 if (specType == SP_SUFFIXES || specType == SP_PATH ||
1743 specType == SP_INCLUDES || specType == SP_LIBS || 1742 specType == SP_INCLUDES || specType == SP_LIBS ||
1744 specType == SP_NULL || specType == SP_OBJDIR) { 1743 specType == SP_NULL || specType == SP_OBJDIR) {
1745 ParseDoDependencySourcesSpecial(line, cp, specType, paths); 1744 ParseDoDependencySourcesSpecial(line, cp, specType, paths);
1746 if (paths != NULL) { 1745 if (paths != NULL) {
1747 Lst_Free(paths); 1746 Lst_Free(paths);
1748 paths = NULL; 1747 paths = NULL;
1749 } 1748 }
1750 if (specType == SP_PATH) 1749 if (specType == SP_PATH)
1751 Dir_SetPATH(); 1750 Dir_SetPATH();
1752 } else { 1751 } else {
1753 assert(paths == NULL); 1752 assert(paths == NULL);
1754 if (!ParseDoDependencySourcesMundane(line, cp, specType, tOp)) 1753 if (!ParseDoDependencySourcesMundane(line, cp, specType, tOp))
1755 goto out; 1754 goto out;
1756 } 1755 }
1757 1756
1758 FindMainTarget(); 1757 FindMainTarget();
1759 1758
1760out: 1759out:
1761 if (paths != NULL) 1760 if (paths != NULL)
1762 Lst_Free(paths); 1761 Lst_Free(paths);
1763 Lst_Done(&curTargs); 1762 Lst_Done(&curTargs);
1764} 1763}
1765 1764
1766typedef struct VarAssignParsed { 1765typedef struct VarAssignParsed {
1767 const char *nameStart; /* unexpanded */ 1766 const char *nameStart; /* unexpanded */
1768 const char *nameEnd; /* before operator adjustment */ 1767 const char *nameEnd; /* before operator adjustment */
1769 const char *eq; /* the '=' of the assignment operator */ 1768 const char *eq; /* the '=' of the assignment operator */
1770} VarAssignParsed; 1769} VarAssignParsed;
1771 1770
1772/* 1771/*
1773 * Determine the assignment operator and adjust the end of the variable 1772 * Determine the assignment operator and adjust the end of the variable
1774 * name accordingly. 1773 * name accordingly.
1775 */ 1774 */
1776static void 1775static void
1777AdjustVarassignOp(const VarAssignParsed *pvar, const char *value, 1776AdjustVarassignOp(const VarAssignParsed *pvar, const char *value,
1778 VarAssign *out_var) 1777 VarAssign *out_var)
1779{ 1778{
1780 const char *op = pvar->eq; 1779 const char *op = pvar->eq;
1781 const char *const name = pvar->nameStart; 1780 const char *const name = pvar->nameStart;
1782 VarAssignOp type; 1781 VarAssignOp type;
1783 1782
1784 if (op > name && op[-1] == '+') { 1783 if (op > name && op[-1] == '+') {
1785 type = VAR_APPEND; 1784 type = VAR_APPEND;
1786 op--; 1785 op--;
1787 1786
1788 } else if (op > name && op[-1] == '?') { 1787 } else if (op > name && op[-1] == '?') {
1789 op--; 1788 op--;
1790 type = VAR_DEFAULT; 1789 type = VAR_DEFAULT;
1791 1790
1792 } else if (op > name && op[-1] == ':') { 1791 } else if (op > name && op[-1] == ':') {
1793 op--; 1792 op--;
1794 type = VAR_SUBST; 1793 type = VAR_SUBST;
1795 1794
1796 } else if (op > name && op[-1] == '!') { 1795 } else if (op > name && op[-1] == '!') {
1797 op--; 1796 op--;
1798 type = VAR_SHELL; 1797 type = VAR_SHELL;
1799 1798
1800 } else { 1799 } else {
1801 type = VAR_NORMAL; 1800 type = VAR_NORMAL;
1802#ifdef SUNSHCMD 1801#ifdef SUNSHCMD
1803 while (op > name && ch_isspace(op[-1])) 1802 while (op > name && ch_isspace(op[-1]))
1804 op--; 1803 op--;
1805 1804
1806 if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' && 1805 if (op >= name + 3 && op[-3] == ':' && op[-2] == 's' &&
1807 op[-1] == 'h') { 1806 op[-1] == 'h') {
1808 type = VAR_SHELL; 1807 type = VAR_SHELL;
1809 op -= 3; 1808 op -= 3;
1810 } 1809 }
1811#endif 1810#endif
1812 } 1811 }
1813 1812
1814 { 1813 {
1815 const char *nameEnd = pvar->nameEnd < op ? pvar->nameEnd : op; 1814 const char *nameEnd = pvar->nameEnd < op ? pvar->nameEnd : op;
1816 out_var->varname = bmake_strsedup(pvar->nameStart, nameEnd); 1815 out_var->varname = bmake_strsedup(pvar->nameStart, nameEnd);
1817 out_var->op = type; 1816 out_var->op = type;
1818 out_var->value = value; 1817 out_var->value = value;
1819 } 1818 }
1820} 1819}
1821 1820
1822/* 1821/*
1823 * Parse a variable assignment, consisting of a single-word variable name, 1822 * Parse a variable assignment, consisting of a single-word variable name,
1824 * optional whitespace, an assignment operator, optional whitespace and the 1823 * optional whitespace, an assignment operator, optional whitespace and the
1825 * variable value. 1824 * variable value.
1826 * 1825 *
1827 * Note: There is a lexical ambiguity with assignment modifier characters 1826 * Note: There is a lexical ambiguity with assignment modifier characters
1828 * in variable names. This routine interprets the character before the = 1827 * in variable names. This routine interprets the character before the =
1829 * as a modifier. Therefore, an assignment like 1828 * as a modifier. Therefore, an assignment like
1830 * C++=/usr/bin/CC 1829 * C++=/usr/bin/CC
1831 * is interpreted as "C+ +=" instead of "C++ =". 1830 * is interpreted as "C+ +=" instead of "C++ =".
1832 * 1831 *
1833 * Used for both lines in a file and command line arguments. 1832 * Used for both lines in a file and command line arguments.
1834 */ 1833 */
1835Boolean 1834Boolean
1836Parse_IsVar(const char *p, VarAssign *out_var) 1835Parse_IsVar(const char *p, VarAssign *out_var)
1837{ 1836{
1838 VarAssignParsed pvar; 1837 VarAssignParsed pvar;
1839 const char *firstSpace = NULL; 1838 const char *firstSpace = NULL;
1840 int level = 0; 1839 int level = 0;
1841 1840
1842 cpp_skip_hspace(&p); /* Skip to variable name */ 1841 cpp_skip_hspace(&p); /* Skip to variable name */
1843 1842
1844 /* 1843 /*
1845 * During parsing, the '+' of the '+=' operator is initially parsed 1844 * During parsing, the '+' of the '+=' operator is initially parsed
1846 * as part of the variable name. It is later corrected, as is the 1845 * as part of the variable name. It is later corrected, as is the
1847 * ':sh' modifier. Of these two (nameEnd and op), the earlier one 1846 * ':sh' modifier. Of these two (nameEnd and op), the earlier one
1848 * determines the actual end of the variable name. 1847 * determines the actual end of the variable name.
1849 */ 1848 */
1850 pvar.nameStart = p; 1849 pvar.nameStart = p;
1851#ifdef CLEANUP 1850#ifdef CLEANUP
1852 pvar.nameEnd = NULL; 1851 pvar.nameEnd = NULL;
1853 pvar.eq = NULL; 1852 pvar.eq = NULL;
1854#endif 1853#endif
1855 1854
1856 /* 1855 /*
1857 * Scan for one of the assignment operators outside a variable 1856 * Scan for one of the assignment operators outside a variable
1858 * expansion. 1857 * expansion.
1859 */ 1858 */
1860 while (*p != '\0') { 1859 while (*p != '\0') {
1861 char ch = *p++; 1860 char ch = *p++;
1862 if (ch == '(' || ch == '{') { 1861 if (ch == '(' || ch == '{') {
1863 level++; 1862 level++;
1864 continue; 1863 continue;
1865 } 1864 }
1866 if (ch == ')' || ch == '}') { 1865 if (ch == ')' || ch == '}') {
1867 level--; 1866 level--;
1868 continue; 1867 continue;
1869 } 1868 }
1870 1869
1871 if (level != 0) 1870 if (level != 0)
1872 continue; 1871 continue;
1873 1872
1874 if (ch == ' ' || ch == '\t') 1873 if (ch == ' ' || ch == '\t')
1875 if (firstSpace == NULL) 1874 if (firstSpace == NULL)
1876 firstSpace = p - 1; 1875 firstSpace = p - 1;
1877 while (ch == ' ' || ch == '\t') 1876 while (ch == ' ' || ch == '\t')
1878 ch = *p++; 1877 ch = *p++;
1879 1878
1880#ifdef SUNSHCMD 1879#ifdef SUNSHCMD
1881 if (ch == ':' && p[0] == 's' && p[1] == 'h') { 1880 if (ch == ':' && p[0] == 's' && p[1] == 'h') {
1882 p += 2; 1881 p += 2;
1883 continue; 1882 continue;
1884 } 1883 }
1885#endif 1884#endif
1886 if (ch == '=') { 1885 if (ch == '=') {
1887 pvar.eq = p - 1; 1886 pvar.eq = p - 1;
1888 pvar.nameEnd = firstSpace != NULL ? firstSpace : p - 1; 1887 pvar.nameEnd = firstSpace != NULL ? firstSpace : p - 1;
1889 cpp_skip_whitespace(&p); 1888 cpp_skip_whitespace(&p);
1890 AdjustVarassignOp(&pvar, p, out_var); 1889 AdjustVarassignOp(&pvar, p, out_var);
1891 return TRUE; 1890 return TRUE;
1892 } 1891 }
1893 if (*p == '=' && 1892 if (*p == '=' &&
1894 (ch == '+' || ch == ':' || ch == '?' || ch == '!')) { 1893 (ch == '+' || ch == ':' || ch == '?' || ch == '!')) {
1895 pvar.eq = p; 1894 pvar.eq = p;
1896 pvar.nameEnd = firstSpace != NULL ? firstSpace : p; 1895 pvar.nameEnd = firstSpace != NULL ? firstSpace : p;
1897 p++; 1896 p++;
1898 cpp_skip_whitespace(&p); 1897 cpp_skip_whitespace(&p);
1899 AdjustVarassignOp(&pvar, p, out_var); 1898 AdjustVarassignOp(&pvar, p, out_var);
1900 return TRUE; 1899 return TRUE;
1901 } 1900 }
1902 if (firstSpace != NULL) 1901 if (firstSpace != NULL)
1903 return FALSE; 1902 return FALSE;
1904 } 1903 }
1905 1904
1906 return FALSE; 1905 return FALSE;
1907} 1906}
1908 1907
1909/* 1908/*
1910 * Check for syntax errors such as unclosed expressions or unknown modifiers. 1909 * Check for syntax errors such as unclosed expressions or unknown modifiers.
1911 */ 1910 */
1912static void 1911static void
1913VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt) 1912VarCheckSyntax(VarAssignOp type, const char *uvalue, GNode *ctxt)
1914{ 1913{
1915 if (opts.strict) { 1914 if (opts.strict) {
1916 if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) { 1915 if (type != VAR_SUBST && strchr(uvalue, '$') != NULL) {
1917 char *expandedValue; 1916 char *expandedValue;
1918 1917
1919 (void)Var_Subst(uvalue, ctxt, VARE_NONE, 1918 (void)Var_Subst(uvalue, ctxt, VARE_NONE,
1920 &expandedValue); 1919 &expandedValue);
1921 /* TODO: handle errors */ 1920 /* TODO: handle errors */
1922 free(expandedValue); 1921 free(expandedValue);
1923 } 1922 }
1924 } 1923 }
1925} 1924}
1926 1925
1927static void 1926static void
1928VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt, 1927VarAssign_EvalSubst(const char *name, const char *uvalue, GNode *ctxt,
1929 FStr *out_avalue) 1928 FStr *out_avalue)
1930{ 1929{
1931 const char *avalue; 1930 const char *avalue;
1932 char *evalue; 1931 char *evalue;
1933 Boolean savedPreserveUndefined = preserveUndefined; 1932 Boolean savedPreserveUndefined = preserveUndefined;
1934 1933
1935 /* TODO: Can this assignment to preserveUndefined be moved further down 1934 /* TODO: Can this assignment to preserveUndefined be moved further down
1936 * to the actually interesting Var_Subst call, without affecting any 1935 * to the actually interesting Var_Subst call, without affecting any
1937 * edge cases? 1936 * edge cases?
1938 * 1937 *
1939 * It might affect the implicit expansion of the variable name in the 1938 * It might affect the implicit expansion of the variable name in the
1940 * Var_Exists and Var_Set calls, even though it's unlikely that anyone 1939 * Var_Exists and Var_Set calls, even though it's unlikely that anyone
1941 * cared about this edge case when adding this code. In addition, 1940 * cared about this edge case when adding this code. In addition,
1942 * variable assignments should not refer to any undefined variables in 1941 * variable assignments should not refer to any undefined variables in
1943 * the variable name. */ 1942 * the variable name. */
1944 preserveUndefined = TRUE; 1943 preserveUndefined = TRUE;
1945 1944
1946 /* 1945 /*
1947 * make sure that we set the variable the first time to nothing 1946 * make sure that we set the variable the first time to nothing
1948 * so that it gets substituted! 1947 * so that it gets substituted!
1949 */ 1948 */
1950 if (!Var_Exists(name, ctxt)) 1949 if (!Var_Exists(name, ctxt))
1951 Var_Set(name, "", ctxt); 1950 Var_Set(name, "", ctxt);
1952 1951
1953 (void)Var_Subst(uvalue, ctxt, VARE_WANTRES | VARE_KEEP_DOLLAR, &evalue); 1952 (void)Var_Subst(uvalue, ctxt, VARE_WANTRES | VARE_KEEP_DOLLAR, &evalue);
1954 /* TODO: handle errors */ 1953 /* TODO: handle errors */
1955 preserveUndefined = savedPreserveUndefined; 1954 preserveUndefined = savedPreserveUndefined;
1956 avalue = evalue; 1955 avalue = evalue;
1957 Var_Set(name, avalue, ctxt); 1956 Var_Set(name, avalue, ctxt);
1958 1957
1959 *out_avalue = (FStr){ avalue, evalue }; 1958 *out_avalue = (FStr){ avalue, evalue };
1960} 1959}
1961 1960
1962static void 1961static void
1963VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt, 1962VarAssign_EvalShell(const char *name, const char *uvalue, GNode *ctxt,
1964 FStr *out_avalue) 1963 FStr *out_avalue)
1965{ 1964{
1966 FStr cmd; 1965 FStr cmd;
1967 const char *errfmt; 1966 const char *errfmt;
1968 char *cmdOut; 1967 char *cmdOut;
1969 1968
1970 cmd = FStr_InitRefer(uvalue); 1969 cmd = FStr_InitRefer(uvalue);
1971 if (strchr(cmd.str, '$') != NULL) { 1970 if (strchr(cmd.str, '$') != NULL) {
1972 char *expanded; 1971 char *expanded;
1973 (void)Var_Subst(cmd.str, VAR_CMDLINE, 1972 (void)Var_Subst(cmd.str, VAR_CMDLINE,
1974 VARE_WANTRES | VARE_UNDEFERR, &expanded); 1973 VARE_WANTRES | VARE_UNDEFERR, &expanded);
1975 /* TODO: handle errors */ 1974 /* TODO: handle errors */
1976 cmd = FStr_InitOwn(expanded); 1975 cmd = FStr_InitOwn(expanded);
1977 } 1976 }
1978 1977
1979 cmdOut = Cmd_Exec(cmd.str, &errfmt); 1978 cmdOut = Cmd_Exec(cmd.str, &errfmt);
1980 Var_Set(name, cmdOut, ctxt); 1979 Var_Set(name, cmdOut, ctxt);
1981 *out_avalue = FStr_InitOwn(cmdOut); 1980 *out_avalue = FStr_InitOwn(cmdOut);
1982 1981
1983 if (errfmt != NULL) 1982 if (errfmt != NULL)
1984 Parse_Error(PARSE_WARNING, errfmt, cmd.str); 1983 Parse_Error(PARSE_WARNING, errfmt, cmd.str);
1985 1984
1986 FStr_Done(&cmd); 1985 FStr_Done(&cmd);
1987} 1986}
1988 1987
1989/* Perform a variable assignment. 1988/* Perform a variable assignment.
1990 * 1989 *
1991 * The actual value of the variable is returned in *out_avalue and 1990 * The actual value of the variable is returned in *out_avalue and
1992 * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ 1991 * *out_avalue_freeIt. Especially for VAR_SUBST and VAR_SHELL this can differ
1993 * from the literal value. 1992 * from the literal value.
1994 * 1993 *
1995 * Return whether the assignment was actually done. The assignment is only 1994 * Return whether the assignment was actually done. The assignment is only
1996 * skipped if the operator is '?=' and the variable already exists. */ 1995 * skipped if the operator is '?=' and the variable already exists. */
1997static Boolean 1996static Boolean
1998VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue, 1997VarAssign_Eval(const char *name, VarAssignOp op, const char *uvalue,
1999 GNode *ctxt, FStr *out_TRUE_avalue) 1998 GNode *ctxt, FStr *out_TRUE_avalue)
2000{ 1999{
2001 FStr avalue = FStr_InitRefer(uvalue); 2000 FStr avalue = FStr_InitRefer(uvalue);
2002 2001
2003 if (op == VAR_APPEND) 2002 if (op == VAR_APPEND)
2004 Var_Append(name, uvalue, ctxt); 2003 Var_Append(name, uvalue, ctxt);
2005 else if (op == VAR_SUBST) 2004 else if (op == VAR_SUBST)
2006 VarAssign_EvalSubst(name, uvalue, ctxt, &avalue); 2005 VarAssign_EvalSubst(name, uvalue, ctxt, &avalue);
2007 else if (op == VAR_SHELL) 2006 else if (op == VAR_SHELL)
2008 VarAssign_EvalShell(name, uvalue, ctxt, &avalue); 2007 VarAssign_EvalShell(name, uvalue, ctxt, &avalue);
2009 else { 2008 else {
2010 if (op == VAR_DEFAULT && Var_Exists(name, ctxt)) 2009 if (op == VAR_DEFAULT && Var_Exists(name, ctxt))
2011 return FALSE; 2010 return FALSE;
2012 2011
2013 /* Normal assignment -- just do it. */ 2012 /* Normal assignment -- just do it. */
2014 Var_Set(name, uvalue, ctxt); 2013 Var_Set(name, uvalue, ctxt);
2015 } 2014 }
2016 2015
2017 *out_TRUE_avalue = avalue; 2016 *out_TRUE_avalue = avalue;
2018 return TRUE; 2017 return TRUE;
2019} 2018}
2020 2019
2021static void 2020static void
2022VarAssignSpecial(const char *name, const char *avalue) 2021VarAssignSpecial(const char *name, const char *avalue)
2023{ 2022{
2024 if (strcmp(name, MAKEOVERRIDES) == 0) 2023 if (strcmp(name, MAKEOVERRIDES) == 0)
2025 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ 2024 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */
2026 else if (strcmp(name, ".CURDIR") == 0) { 2025 else if (strcmp(name, ".CURDIR") == 0) {
2027 /* 2026 /*
2028 * Someone is being (too?) clever... 2027 * Someone is being (too?) clever...
2029 * Let's pretend they know what they are doing and 2028 * Let's pretend they know what they are doing and
2030 * re-initialize the 'cur' CachedDir. 2029 * re-initialize the 'cur' CachedDir.
2031 */ 2030 */
2032 Dir_InitCur(avalue); 2031 Dir_InitCur(avalue);
2033 Dir_SetPATH(); 2032 Dir_SetPATH();
2034 } else if (strcmp(name, MAKE_JOB_PREFIX) == 0) 2033 } else if (strcmp(name, MAKE_JOB_PREFIX) == 0)
2035 Job_SetPrefix(); 2034 Job_SetPrefix();
2036 else if (strcmp(name, MAKE_EXPORTED) == 0) 2035 else if (strcmp(name, MAKE_EXPORTED) == 0)
2037 Var_ExportVars(avalue); 2036 Var_ExportVars(avalue);
2038} 2037}
2039 2038
2040/* Perform the variable variable assignment in the given context. */ 2039/* Perform the variable variable assignment in the given context. */
2041void 2040void
2042Parse_DoVar(VarAssign *var, GNode *ctxt) 2041Parse_DoVar(VarAssign *var, GNode *ctxt)
2043{ 2042{
2044 FStr avalue; /* actual value (maybe expanded) */ 2043 FStr avalue; /* actual value (maybe expanded) */
2045 2044
2046 VarCheckSyntax(var->op, var->value, ctxt); 2045 VarCheckSyntax(var->op, var->value, ctxt);
2047 if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, &avalue)) { 2046 if (VarAssign_Eval(var->varname, var->op, var->value, ctxt, &avalue)) {
2048 VarAssignSpecial(var->varname, avalue.str); 2047 VarAssignSpecial(var->varname, avalue.str);
2049 FStr_Done(&avalue); 2048 FStr_Done(&avalue);
2050 } 2049 }
2051 2050
2052 free(var->varname); 2051 free(var->varname);
2053} 2052}
2054 2053
2055 2054
2056/* See if the command possibly calls a sub-make by using the variable 2055/* See if the command possibly calls a sub-make by using the variable
2057 * expressions ${.MAKE}, ${MAKE} or the plain word "make". */ 2056 * expressions ${.MAKE}, ${MAKE} or the plain word "make". */
2058static Boolean 2057static Boolean
2059MaybeSubMake(const char *cmd) 2058MaybeSubMake(const char *cmd)
2060{ 2059{
2061 const char *start; 2060 const char *start;
2062 2061
2063 for (start = cmd; *start != '\0'; start++) { 2062 for (start = cmd; *start != '\0'; start++) {
2064 const char *p = start; 2063 const char *p = start;
2065 char endc; 2064 char endc;
2066 2065
2067 /* XXX: What if progname != "make"? */ 2066 /* XXX: What if progname != "make"? */
2068 if (p[0] == 'm' && p[1] == 'a' && p[2] == 'k' && p[3] == 'e') 2067 if (p[0] == 'm' && p[1] == 'a' && p[2] == 'k' && p[3] == 'e')
2069 if (start == cmd || !ch_isalnum(p[-1])) 2068 if (start == cmd || !ch_isalnum(p[-1]))
2070 if (!ch_isalnum(p[4])) 2069 if (!ch_isalnum(p[4]))
2071 return TRUE; 2070 return TRUE;
2072 2071
2073 if (*p != '$') 2072 if (*p != '$')
2074 continue; 2073 continue;
2075 p++; 2074 p++;
2076 2075
2077 if (*p == '{') 2076 if (*p == '{')
2078 endc = '}'; 2077 endc = '}';
2079 else if (*p == '(') 2078 else if (*p == '(')
2080 endc = ')'; 2079 endc = ')';
2081 else 2080 else
2082 continue; 2081 continue;
2083 p++; 2082 p++;
2084 2083
2085 if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */ 2084 if (*p == '.') /* Accept either ${.MAKE} or ${MAKE}. */
2086 p++; 2085 p++;
2087 2086
2088 if (p[0] == 'M' && p[1] == 'A' && p[2] == 'K' && p[3] == 'E') 2087 if (p[0] == 'M' && p[1] == 'A' && p[2] == 'K' && p[3] == 'E')