Wed Oct 28 01:47:11 2020 UTC ()
make(1): remove unused, undocumented .NOEXPORT


(rillig)
diff -r1.404 -r1.405 src/usr.bin/make/parse.c

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

--- src/usr.bin/make/parse.c 2020/10/28 01:43:01 1.404
+++ src/usr.bin/make/parse.c 2020/10/28 01:47:11 1.405
@@ -1,1161 +1,1160 @@ @@ -1,1161 +1,1160 @@
1/* $NetBSD: parse.c,v 1.404 2020/10/28 01:43:01 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.405 2020/10/28 01:47:11 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.404 2020/10/28 01:43:01 rillig Exp $"); 120MAKE_RCSID("$NetBSD: parse.c,v 1.405 2020/10/28 01:47:11 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 */ 128 char *fname; /* name of file */
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 char *(*nextbuf)(void *, size_t *); /* Function to get more data */ 140 char *(*nextbuf)(void *, size_t *); /* Function to get more data */
141 void *nextbuf_arg; /* Opaque arg for nextbuf() */ 141 void *nextbuf_arg; /* Opaque arg for nextbuf() */
142 struct loadedfile *lf; /* loadedfile object, if any */ 142 struct loadedfile *lf; /* loadedfile object, if any */
143} IFile; 143} IFile;
144 144
145/* 145/*
146 * Tokens for target attributes 146 * Tokens for target attributes
147 */ 147 */
148typedef enum ParseSpecial { 148typedef enum ParseSpecial {
149 SP_BEGIN, /* .BEGIN */ 149 SP_BEGIN, /* .BEGIN */
150 SP_DEFAULT, /* .DEFAULT */ 150 SP_DEFAULT, /* .DEFAULT */
151 SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */ 151 SP_DELETE_ON_ERROR, /* .DELETE_ON_ERROR */
152 SP_END, /* .END */ 152 SP_END, /* .END */
153 SP_ERROR, /* .ERROR */ 153 SP_ERROR, /* .ERROR */
154 SP_IGNORE, /* .IGNORE */ 154 SP_IGNORE, /* .IGNORE */
155 SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */ 155 SP_INCLUDES, /* .INCLUDES; not mentioned in the manual page */
156 SP_INTERRUPT, /* .INTERRUPT */ 156 SP_INTERRUPT, /* .INTERRUPT */
157 SP_LIBS, /* .LIBS; not mentioned in the manual page */ 157 SP_LIBS, /* .LIBS; not mentioned in the manual page */
158 SP_META, /* .META */ 158 SP_META, /* .META */
159 SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */ 159 SP_MFLAGS, /* .MFLAGS or .MAKEFLAGS */
160 SP_MAIN, /* .MAIN and we don't have anything user-specified to 160 SP_MAIN, /* .MAIN and we don't have anything user-specified to
161 * make */ 161 * make */
162 SP_NOEXPORT, /* .NOEXPORT; not mentioned in the manual page */ 
163 SP_NOMETA, /* .NOMETA */ 162 SP_NOMETA, /* .NOMETA */
164 SP_NOMETA_CMP, /* .NOMETA_CMP */ 163 SP_NOMETA_CMP, /* .NOMETA_CMP */
165 SP_NOPATH, /* .NOPATH */ 164 SP_NOPATH, /* .NOPATH */
166 SP_NOT, /* Not special */ 165 SP_NOT, /* Not special */
167 SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */ 166 SP_NOTPARALLEL, /* .NOTPARALLEL or .NO_PARALLEL */
168 SP_NULL, /* .NULL; not mentioned in the manual page */ 167 SP_NULL, /* .NULL; not mentioned in the manual page */
169 SP_OBJDIR, /* .OBJDIR */ 168 SP_OBJDIR, /* .OBJDIR */
170 SP_ORDER, /* .ORDER */ 169 SP_ORDER, /* .ORDER */
171 SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */ 170 SP_PARALLEL, /* .PARALLEL; not mentioned in the manual page */
172 SP_PATH, /* .PATH or .PATH.suffix */ 171 SP_PATH, /* .PATH or .PATH.suffix */
173 SP_PHONY, /* .PHONY */ 172 SP_PHONY, /* .PHONY */
174#ifdef POSIX 173#ifdef POSIX
175 SP_POSIX, /* .POSIX; not mentioned in the manual page */ 174 SP_POSIX, /* .POSIX; not mentioned in the manual page */
176#endif 175#endif
177 SP_PRECIOUS, /* .PRECIOUS */ 176 SP_PRECIOUS, /* .PRECIOUS */
178 SP_SHELL, /* .SHELL */ 177 SP_SHELL, /* .SHELL */
179 SP_SILENT, /* .SILENT */ 178 SP_SILENT, /* .SILENT */
180 SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */ 179 SP_SINGLESHELL, /* .SINGLESHELL; not mentioned in the manual page */
181 SP_STALE, /* .STALE */ 180 SP_STALE, /* .STALE */
182 SP_SUFFIXES, /* .SUFFIXES */ 181 SP_SUFFIXES, /* .SUFFIXES */
183 SP_WAIT, /* .WAIT */ 182 SP_WAIT, /* .WAIT */
184 SP_ATTRIBUTE /* Generic attribute */ 183 SP_ATTRIBUTE /* Generic attribute */
185} ParseSpecial; 184} ParseSpecial;
186 185
187typedef List SearchPathList; 186typedef List SearchPathList;
188typedef ListNode SearchPathListNode; 187typedef ListNode SearchPathListNode;
189 188
190/* result data */ 189/* result data */
191 190
192/* 191/*
193 * The main target to create. This is the first target on the first 192 * The main target to create. This is the first target on the first
194 * dependency line in the first makefile. 193 * dependency line in the first makefile.
195 */ 194 */
196static GNode *mainNode; 195static GNode *mainNode;
197 196
198/* eval state */ 197/* eval state */
199 198
200/* During parsing, the targets from the currently active dependency line, 199/* During parsing, the targets from the currently active dependency line,
201 * or NULL if the current line does not belong to a dependency line, for 200 * or NULL if the current line does not belong to a dependency line, for
202 * example because it is a variable assignment. 201 * example because it is a variable assignment.
203 * 202 *
204 * See unit-tests/deptgt.mk, keyword "parse.c:targets". */ 203 * See unit-tests/deptgt.mk, keyword "parse.c:targets". */
205static GNodeList *targets; 204static GNodeList *targets;
206 205
207#ifdef CLEANUP 206#ifdef CLEANUP
208/* All shell commands for all targets, in no particular order and possibly 207/* All shell commands for all targets, in no particular order and possibly
209 * with duplicates. Kept in a separate list since the commands from .USE or 208 * with duplicates. Kept in a separate list since the commands from .USE or
210 * .USEBEFORE nodes are shared with other GNodes, thereby giving up the 209 * .USEBEFORE nodes are shared with other GNodes, thereby giving up the
211 * easily understandable ownership over the allocated strings. */ 210 * easily understandable ownership over the allocated strings. */
212static StringList *targCmds; 211static StringList *targCmds;
213#endif 212#endif
214 213
215/* 214/*
216 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 215 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
217 * seen, then set to each successive source on the line. 216 * seen, then set to each successive source on the line.
218 */ 217 */
219static GNode *predecessor; 218static GNode *predecessor;
220 219
221/* parser state */ 220/* parser state */
222 221
223/* number of fatal errors */ 222/* number of fatal errors */
224static int fatals = 0; 223static int fatals = 0;
225 224
226/* 225/*
227 * Variables for doing includes 226 * Variables for doing includes
228 */ 227 */
229 228
230/* current file being read */ 229/* current file being read */
231static IFile *curFile; 230static IFile *curFile;
232 231
233/* The include chain of makefiles that leads to curFile. At the bottom of 232/* The include chain of makefiles that leads to curFile. At the bottom of
234 * the stack is the top-level makefile from the command line, and on top of 233 * the stack is the top-level makefile from the command line, and on top of
235 * this file, there are the included files or .for loops, up to but excluding 234 * this file, there are the included files or .for loops, up to but excluding
236 * curFile. 235 * curFile.
237 * 236 *
238 * This data could be used to print stack traces on parse errors. As of 237 * This data could be used to print stack traces on parse errors. As of
239 * 2020-09-14, this is not done though. It seems quite simple to print the 238 * 2020-09-14, this is not done though. It seems quite simple to print the
240 * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is 239 * tuples (fname:lineno:fromForLoop), from top to bottom. This simple idea is
241 * made complicated by the fact that the .for loops also use this stack for 240 * made complicated by the fact that the .for loops also use this stack for
242 * storing information. 241 * storing information.
243 * 242 *
244 * The lineno fields of the IFiles with fromForLoop == TRUE look confusing, 243 * The lineno fields of the IFiles with fromForLoop == TRUE look confusing,
245 * which is demonstrated by the test 'include-main.mk'. They seem sorted 244 * which is demonstrated by the test 'include-main.mk'. They seem sorted
246 * backwards since they tell the number of completely parsed lines, which for 245 * backwards since they tell the number of completely parsed lines, which for
247 * a .for loop is right after the terminating .endfor. To compensate for this 246 * a .for loop is right after the terminating .endfor. To compensate for this
248 * confusion, there is another field first_lineno pointing at the start of the 247 * confusion, there is another field first_lineno pointing at the start of the
249 * .for loop, 1-based for human consumption. 248 * .for loop, 1-based for human consumption.
250 * 249 *
251 * To make the stack trace intuitive, the entry below the first .for loop must 250 * To make the stack trace intuitive, the entry below the first .for loop must
252 * be ignored completely since neither its lineno nor its first_lineno is 251 * be ignored completely since neither its lineno nor its first_lineno is
253 * useful. Instead, the topmost .for loop needs to be printed twice, once 252 * useful. Instead, the topmost .for loop needs to be printed twice, once
254 * with its first_lineno and once with its lineno. 253 * with its first_lineno and once with its lineno.
255 * 254 *
256 * As of 2020-09-15, using the above rules, the stack trace for the .info line 255 * As of 2020-09-15, using the above rules, the stack trace for the .info line
257 * in include-subsub.mk would be: 256 * in include-subsub.mk would be:
258 * 257 *
259 * curFile: include-subsub.mk:4 258 * curFile: include-subsub.mk:4
260 * (lineno, from an .include) 259 * (lineno, from an .include)
261 * includes[4]: include-sub.mk:32 260 * includes[4]: include-sub.mk:32
262 * (lineno, from a .for loop below an .include) 261 * (lineno, from a .for loop below an .include)
263 * includes[4]: include-sub.mk:31 262 * includes[4]: include-sub.mk:31
264 * (first_lineno, from a .for loop, lineno == 32) 263 * (first_lineno, from a .for loop, lineno == 32)
265 * includes[3]: include-sub.mk:30 264 * includes[3]: include-sub.mk:30
266 * (first_lineno, from a .for loop, lineno == 33) 265 * (first_lineno, from a .for loop, lineno == 33)
267 * includes[2]: include-sub.mk:29 266 * includes[2]: include-sub.mk:29
268 * (first_lineno, from a .for loop, lineno == 34) 267 * (first_lineno, from a .for loop, lineno == 34)
269 * includes[1]: include-sub.mk:35 268 * includes[1]: include-sub.mk:35
270 * (not printed since it is below a .for loop) 269 * (not printed since it is below a .for loop)
271 * includes[0]: include-main.mk:27 270 * includes[0]: include-main.mk:27
272 */ 271 */
273static Vector /* of IFile pointer */ includes; 272static Vector /* of IFile pointer */ includes;
274 273
275static IFile * 274static IFile *
276GetInclude(size_t i) 275GetInclude(size_t i)
277{ 276{
278 return *((IFile **)Vector_Get(&includes, i)); 277 return *((IFile **)Vector_Get(&includes, i));
279} 278}
280 279
281/* include paths (lists of directories) */ 280/* include paths (lists of directories) */
282SearchPath *parseIncPath; /* dirs for "..." includes */ 281SearchPath *parseIncPath; /* dirs for "..." includes */
283SearchPath *sysIncPath; /* dirs for <...> includes */ 282SearchPath *sysIncPath; /* dirs for <...> includes */
284SearchPath *defIncPath; /* default for sysIncPath */ 283SearchPath *defIncPath; /* default for sysIncPath */
285 284
286/* parser tables */ 285/* parser tables */
287 286
288/* 287/*
289 * The parseKeywords table is searched using binary search when deciding 288 * The parseKeywords table is searched using binary search when deciding
290 * if a target or source is special. The 'spec' field is the ParseSpecial 289 * if a target or source is special. The 'spec' field is the ParseSpecial
291 * type of the keyword (SP_NOT if the keyword isn't special as a target) while 290 * type of the keyword (SP_NOT if the keyword isn't special as a target) while
292 * the 'op' field is the operator to apply to the list of targets if the 291 * the 'op' field is the operator to apply to the list of targets if the
293 * keyword is used as a source ("0" if the keyword isn't special as a source) 292 * keyword is used as a source ("0" if the keyword isn't special as a source)
294 */ 293 */
295static const struct { 294static const struct {
296 const char *name; /* Name of keyword */ 295 const char *name; /* Name of keyword */
297 ParseSpecial spec; /* Type when used as a target */ 296 ParseSpecial spec; /* Type when used as a target */
298 GNodeType op; /* Operator when used as a source */ 297 GNodeType op; /* Operator when used as a source */
299} parseKeywords[] = { 298} parseKeywords[] = {
300 { ".BEGIN", SP_BEGIN, 0 }, 299 { ".BEGIN", SP_BEGIN, 0 },
301 { ".DEFAULT", SP_DEFAULT, 0 }, 300 { ".DEFAULT", SP_DEFAULT, 0 },
302 { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, 0 }, 301 { ".DELETE_ON_ERROR", SP_DELETE_ON_ERROR, 0 },
303 { ".END", SP_END, 0 }, 302 { ".END", SP_END, 0 },
304 { ".ERROR", SP_ERROR, 0 }, 303 { ".ERROR", SP_ERROR, 0 },
305 { ".EXEC", SP_ATTRIBUTE, OP_EXEC }, 304 { ".EXEC", SP_ATTRIBUTE, OP_EXEC },
306 { ".IGNORE", SP_IGNORE, OP_IGNORE }, 305 { ".IGNORE", SP_IGNORE, OP_IGNORE },
307 { ".INCLUDES", SP_INCLUDES, 0 }, 306 { ".INCLUDES", SP_INCLUDES, 0 },
308 { ".INTERRUPT", SP_INTERRUPT, 0 }, 307 { ".INTERRUPT", SP_INTERRUPT, 0 },
309 { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE }, 308 { ".INVISIBLE", SP_ATTRIBUTE, OP_INVISIBLE },
310 { ".JOIN", SP_ATTRIBUTE, OP_JOIN }, 309 { ".JOIN", SP_ATTRIBUTE, OP_JOIN },
311 { ".LIBS", SP_LIBS, 0 }, 310 { ".LIBS", SP_LIBS, 0 },
312 { ".MADE", SP_ATTRIBUTE, OP_MADE }, 311 { ".MADE", SP_ATTRIBUTE, OP_MADE },
313 { ".MAIN", SP_MAIN, 0 }, 312 { ".MAIN", SP_MAIN, 0 },
314 { ".MAKE", SP_ATTRIBUTE, OP_MAKE }, 313 { ".MAKE", SP_ATTRIBUTE, OP_MAKE },
315 { ".MAKEFLAGS", SP_MFLAGS, 0 }, 314 { ".MAKEFLAGS", SP_MFLAGS, 0 },
316 { ".META", SP_META, OP_META }, 315 { ".META", SP_META, OP_META },
317 { ".MFLAGS", SP_MFLAGS, 0 }, 316 { ".MFLAGS", SP_MFLAGS, 0 },
318 { ".NOMETA", SP_NOMETA, OP_NOMETA }, 317 { ".NOMETA", SP_NOMETA, OP_NOMETA },
319 { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP }, 318 { ".NOMETA_CMP", SP_NOMETA_CMP, OP_NOMETA_CMP },
320 { ".NOPATH", SP_NOPATH, OP_NOPATH }, 319 { ".NOPATH", SP_NOPATH, OP_NOPATH },
321 { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN }, 320 { ".NOTMAIN", SP_ATTRIBUTE, OP_NOTMAIN },
322 { ".NOTPARALLEL", SP_NOTPARALLEL, 0 }, 321 { ".NOTPARALLEL", SP_NOTPARALLEL, 0 },
323 { ".NO_PARALLEL", SP_NOTPARALLEL, 0 }, 322 { ".NO_PARALLEL", SP_NOTPARALLEL, 0 },
324 { ".NULL", SP_NULL, 0 }, 323 { ".NULL", SP_NULL, 0 },
325 { ".OBJDIR", SP_OBJDIR, 0 }, 324 { ".OBJDIR", SP_OBJDIR, 0 },
326 { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL }, 325 { ".OPTIONAL", SP_ATTRIBUTE, OP_OPTIONAL },
327 { ".ORDER", SP_ORDER, 0 }, 326 { ".ORDER", SP_ORDER, 0 },
328 { ".PARALLEL", SP_PARALLEL, 0 }, 327 { ".PARALLEL", SP_PARALLEL, 0 },
329 { ".PATH", SP_PATH, 0 }, 328 { ".PATH", SP_PATH, 0 },
330 { ".PHONY", SP_PHONY, OP_PHONY }, 329 { ".PHONY", SP_PHONY, OP_PHONY },
331#ifdef POSIX 330#ifdef POSIX
332 { ".POSIX", SP_POSIX, 0 }, 331 { ".POSIX", SP_POSIX, 0 },
333#endif 332#endif
334 { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS }, 333 { ".PRECIOUS", SP_PRECIOUS, OP_PRECIOUS },
335 { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE }, 334 { ".RECURSIVE", SP_ATTRIBUTE, OP_MAKE },
336 { ".SHELL", SP_SHELL, 0 }, 335 { ".SHELL", SP_SHELL, 0 },
337 { ".SILENT", SP_SILENT, OP_SILENT }, 336 { ".SILENT", SP_SILENT, OP_SILENT },
338 { ".SINGLESHELL", SP_SINGLESHELL, 0 }, 337 { ".SINGLESHELL", SP_SINGLESHELL, 0 },
339 { ".STALE", SP_STALE, 0 }, 338 { ".STALE", SP_STALE, 0 },
340 { ".SUFFIXES", SP_SUFFIXES, 0 }, 339 { ".SUFFIXES", SP_SUFFIXES, 0 },
341 { ".USE", SP_ATTRIBUTE, OP_USE }, 340 { ".USE", SP_ATTRIBUTE, OP_USE },
342 { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE }, 341 { ".USEBEFORE", SP_ATTRIBUTE, OP_USEBEFORE },
343 { ".WAIT", SP_WAIT, 0 }, 342 { ".WAIT", SP_WAIT, 0 },
344}; 343};
345 344
346/* file loader */ 345/* file loader */
347 346
348struct loadedfile { 347struct loadedfile {
349 const char *path; /* name, for error reports */ 348 const char *path; /* name, for error reports */
350 char *buf; /* contents buffer */ 349 char *buf; /* contents buffer */
351 size_t len; /* length of contents */ 350 size_t len; /* length of contents */
352 size_t maplen; /* length of mmap area, or 0 */ 351 size_t maplen; /* length of mmap area, or 0 */
353 Boolean used; /* XXX: have we used the data yet */ 352 Boolean used; /* XXX: have we used the data yet */
354}; 353};
355 354
356static struct loadedfile * 355static struct loadedfile *
357loadedfile_create(const char *path) 356loadedfile_create(const char *path)
358{ 357{
359 struct loadedfile *lf; 358 struct loadedfile *lf;
360 359
361 lf = bmake_malloc(sizeof(*lf)); 360 lf = bmake_malloc(sizeof(*lf));
362 lf->path = path == NULL ? "(stdin)" : path; 361 lf->path = path == NULL ? "(stdin)" : path;
363 lf->buf = NULL; 362 lf->buf = NULL;
364 lf->len = 0; 363 lf->len = 0;
365 lf->maplen = 0; 364 lf->maplen = 0;
366 lf->used = FALSE; 365 lf->used = FALSE;
367 return lf; 366 return lf;
368} 367}
369 368
370static void 369static void
371loadedfile_destroy(struct loadedfile *lf) 370loadedfile_destroy(struct loadedfile *lf)
372{ 371{
373 if (lf->buf != NULL) { 372 if (lf->buf != NULL) {
374 if (lf->maplen > 0) { 373 if (lf->maplen > 0) {
375 munmap(lf->buf, lf->maplen); 374 munmap(lf->buf, lf->maplen);
376 } else { 375 } else {
377 free(lf->buf); 376 free(lf->buf);
378 } 377 }
379 } 378 }
380 free(lf); 379 free(lf);
381} 380}
382 381
383/* 382/*
384 * nextbuf() operation for loadedfile, as needed by the weird and twisted 383 * nextbuf() operation for loadedfile, as needed by the weird and twisted
385 * logic below. Once that's cleaned up, we can get rid of lf->used... 384 * logic below. Once that's cleaned up, we can get rid of lf->used...
386 */ 385 */
387static char * 386static char *
388loadedfile_nextbuf(void *x, size_t *len) 387loadedfile_nextbuf(void *x, size_t *len)
389{ 388{
390 struct loadedfile *lf = x; 389 struct loadedfile *lf = x;
391 390
392 if (lf->used) { 391 if (lf->used) {
393 return NULL; 392 return NULL;
394 } 393 }
395 lf->used = TRUE; 394 lf->used = TRUE;
396 *len = lf->len; 395 *len = lf->len;
397 return lf->buf; 396 return lf->buf;
398} 397}
399 398
400/* 399/*
401 * Try to get the size of a file. 400 * Try to get the size of a file.
402 */ 401 */
403static Boolean 402static Boolean
404load_getsize(int fd, size_t *ret) 403load_getsize(int fd, size_t *ret)
405{ 404{
406 struct stat st; 405 struct stat st;
407 406
408 if (fstat(fd, &st) < 0) { 407 if (fstat(fd, &st) < 0) {
409 return FALSE; 408 return FALSE;
410 } 409 }
411 410
412 if (!S_ISREG(st.st_mode)) { 411 if (!S_ISREG(st.st_mode)) {
413 return FALSE; 412 return FALSE;
414 } 413 }
415 414
416 /* 415 /*
417 * st_size is an off_t, which is 64 bits signed; *ret is 416 * st_size is an off_t, which is 64 bits signed; *ret is
418 * size_t, which might be 32 bits unsigned or 64 bits 417 * size_t, which might be 32 bits unsigned or 64 bits
419 * unsigned. Rather than being elaborate, just punt on 418 * unsigned. Rather than being elaborate, just punt on
420 * files that are more than 2^31 bytes. We should never 419 * files that are more than 2^31 bytes. We should never
421 * see a makefile that size in practice... 420 * see a makefile that size in practice...
422 * 421 *
423 * While we're at it reject negative sizes too, just in case. 422 * While we're at it reject negative sizes too, just in case.
424 */ 423 */
425 if (st.st_size < 0 || st.st_size > 0x7fffffff) { 424 if (st.st_size < 0 || st.st_size > 0x7fffffff) {
426 return FALSE; 425 return FALSE;
427 } 426 }
428 427
429 *ret = (size_t)st.st_size; 428 *ret = (size_t)st.st_size;
430 return TRUE; 429 return TRUE;
431} 430}
432 431
433/* 432/*
434 * Read in a file. 433 * Read in a file.
435 * 434 *
436 * Until the path search logic can be moved under here instead of 435 * Until the path search logic can be moved under here instead of
437 * being in the caller in another source file, we need to have the fd 436 * being in the caller in another source file, we need to have the fd
438 * passed in already open. Bleh. 437 * passed in already open. Bleh.
439 * 438 *
440 * If the path is NULL use stdin and (to insure against fd leaks) 439 * If the path is NULL use stdin and (to insure against fd leaks)
441 * assert that the caller passed in -1. 440 * assert that the caller passed in -1.
442 */ 441 */
443static struct loadedfile * 442static struct loadedfile *
444loadfile(const char *path, int fd) 443loadfile(const char *path, int fd)
445{ 444{
446 struct loadedfile *lf; 445 struct loadedfile *lf;
447 static unsigned long pagesize = 0; 446 static unsigned long pagesize = 0;
448 ssize_t result; 447 ssize_t result;
449 size_t bufpos; 448 size_t bufpos;
450 449
451 lf = loadedfile_create(path); 450 lf = loadedfile_create(path);
452 451
453 if (path == NULL) { 452 if (path == NULL) {
454 assert(fd == -1); 453 assert(fd == -1);
455 fd = STDIN_FILENO; 454 fd = STDIN_FILENO;
456 } else { 455 } else {
457#if 0 /* notyet */ 456#if 0 /* notyet */
458 fd = open(path, O_RDONLY); 457 fd = open(path, O_RDONLY);
459 if (fd < 0) { 458 if (fd < 0) {
460 ... 459 ...
461 Error("%s: %s", path, strerror(errno)); 460 Error("%s: %s", path, strerror(errno));
462 exit(1); 461 exit(1);
463 } 462 }
464#endif 463#endif
465 } 464 }
466 465
467 if (load_getsize(fd, &lf->len)) { 466 if (load_getsize(fd, &lf->len)) {
468 /* found a size, try mmap */ 467 /* found a size, try mmap */
469 if (pagesize == 0) 468 if (pagesize == 0)
470 pagesize = (unsigned long)sysconf(_SC_PAGESIZE); 469 pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
471 if (pagesize == 0 || pagesize == (unsigned long)-1) { 470 if (pagesize == 0 || pagesize == (unsigned long)-1) {
472 pagesize = 0x1000; 471 pagesize = 0x1000;
473 } 472 }
474 /* round size up to a page */ 473 /* round size up to a page */
475 lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize); 474 lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize);
476 475
477 /* 476 /*
478 * XXX hack for dealing with empty files; remove when 477 * XXX hack for dealing with empty files; remove when
479 * we're no longer limited by interfacing to the old 478 * we're no longer limited by interfacing to the old
480 * logic elsewhere in this file. 479 * logic elsewhere in this file.
481 */ 480 */
482 if (lf->maplen == 0) { 481 if (lf->maplen == 0) {
483 lf->maplen = pagesize; 482 lf->maplen = pagesize;
484 } 483 }
485 484
486 /* 485 /*
487 * FUTURE: remove PROT_WRITE when the parser no longer 486 * FUTURE: remove PROT_WRITE when the parser no longer
488 * needs to scribble on the input. 487 * needs to scribble on the input.
489 */ 488 */
490 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE, 489 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
491 MAP_FILE|MAP_COPY, fd, 0); 490 MAP_FILE|MAP_COPY, fd, 0);
492 if (lf->buf != MAP_FAILED) { 491 if (lf->buf != MAP_FAILED) {
493 /* succeeded */ 492 /* succeeded */
494 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') { 493 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
495 char *b = bmake_malloc(lf->len + 1); 494 char *b = bmake_malloc(lf->len + 1);
496 b[lf->len] = '\n'; 495 b[lf->len] = '\n';
497 memcpy(b, lf->buf, lf->len++); 496 memcpy(b, lf->buf, lf->len++);
498 munmap(lf->buf, lf->maplen); 497 munmap(lf->buf, lf->maplen);
499 lf->maplen = 0; 498 lf->maplen = 0;
500 lf->buf = b; 499 lf->buf = b;
501 } 500 }
502 goto done; 501 goto done;
503 } 502 }
504 } 503 }
505 504
506 /* cannot mmap; load the traditional way */ 505 /* cannot mmap; load the traditional way */
507 506
508 lf->maplen = 0; 507 lf->maplen = 0;
509 lf->len = 1024; 508 lf->len = 1024;
510 lf->buf = bmake_malloc(lf->len); 509 lf->buf = bmake_malloc(lf->len);
511 510
512 bufpos = 0; 511 bufpos = 0;
513 while (1) { 512 while (1) {
514 assert(bufpos <= lf->len); 513 assert(bufpos <= lf->len);
515 if (bufpos == lf->len) { 514 if (bufpos == lf->len) {
516 if (lf->len > SIZE_MAX/2) { 515 if (lf->len > SIZE_MAX/2) {
517 errno = EFBIG; 516 errno = EFBIG;
518 Error("%s: file too large", path); 517 Error("%s: file too large", path);
519 exit(1); 518 exit(1);
520 } 519 }
521 lf->len *= 2; 520 lf->len *= 2;
522 lf->buf = bmake_realloc(lf->buf, lf->len); 521 lf->buf = bmake_realloc(lf->buf, lf->len);
523 } 522 }
524 assert(bufpos < lf->len); 523 assert(bufpos < lf->len);
525 result = read(fd, lf->buf + bufpos, lf->len - bufpos); 524 result = read(fd, lf->buf + bufpos, lf->len - bufpos);
526 if (result < 0) { 525 if (result < 0) {
527 Error("%s: read error: %s", path, strerror(errno)); 526 Error("%s: read error: %s", path, strerror(errno));
528 exit(1); 527 exit(1);
529 } 528 }
530 if (result == 0) { 529 if (result == 0) {
531 break; 530 break;
532 } 531 }
533 bufpos += (size_t)result; 532 bufpos += (size_t)result;
534 } 533 }
535 assert(bufpos <= lf->len); 534 assert(bufpos <= lf->len);
536 lf->len = bufpos; 535 lf->len = bufpos;
537 536
538 /* truncate malloc region to actual length (maybe not useful) */ 537 /* truncate malloc region to actual length (maybe not useful) */
539 if (lf->len > 0) { 538 if (lf->len > 0) {
540 /* as for mmap case, ensure trailing \n */ 539 /* as for mmap case, ensure trailing \n */
541 if (lf->buf[lf->len - 1] != '\n') 540 if (lf->buf[lf->len - 1] != '\n')
542 lf->len++; 541 lf->len++;
543 lf->buf = bmake_realloc(lf->buf, lf->len); 542 lf->buf = bmake_realloc(lf->buf, lf->len);
544 lf->buf[lf->len - 1] = '\n'; 543 lf->buf[lf->len - 1] = '\n';
545 } 544 }
546 545
547done: 546done:
548 if (path != NULL) { 547 if (path != NULL) {
549 close(fd); 548 close(fd);
550 } 549 }
551 return lf; 550 return lf;
552} 551}
553 552
554/* old code */ 553/* old code */
555 554
556/* Check if the current character is escaped on the current line. */ 555/* Check if the current character is escaped on the current line. */
557static Boolean 556static Boolean
558ParseIsEscaped(const char *line, const char *c) 557ParseIsEscaped(const char *line, const char *c)
559{ 558{
560 Boolean active = FALSE; 559 Boolean active = FALSE;
561 for (;;) { 560 for (;;) {
562 if (line == c) 561 if (line == c)
563 return active; 562 return active;
564 if (*--c != '\\') 563 if (*--c != '\\')
565 return active; 564 return active;
566 active = !active; 565 active = !active;
567 } 566 }
568} 567}
569 568
570/* Add the filename and lineno to the GNode so that we remember where it 569/* Add the filename and lineno to the GNode so that we remember where it
571 * was first defined. */ 570 * was first defined. */
572static void 571static void
573ParseMark(GNode *gn) 572ParseMark(GNode *gn)
574{ 573{
575 gn->fname = curFile->fname; 574 gn->fname = curFile->fname;
576 gn->lineno = curFile->lineno; 575 gn->lineno = curFile->lineno;
577} 576}
578 577
579/* Look in the table of keywords for one matching the given string. 578/* Look in the table of keywords for one matching the given string.
580 * Return the index of the keyword, or -1 if it isn't there. */ 579 * Return the index of the keyword, or -1 if it isn't there. */
581static int 580static int
582ParseFindKeyword(const char *str) 581ParseFindKeyword(const char *str)
583{ 582{
584 int start, end, cur; 583 int start, end, cur;
585 int diff; 584 int diff;
586 585
587 start = 0; 586 start = 0;
588 end = sizeof parseKeywords / sizeof parseKeywords[0] - 1; 587 end = sizeof parseKeywords / sizeof parseKeywords[0] - 1;
589 588
590 do { 589 do {
591 cur = start + (end - start) / 2; 590 cur = start + (end - start) / 2;
592 diff = strcmp(str, parseKeywords[cur].name); 591 diff = strcmp(str, parseKeywords[cur].name);
593 592
594 if (diff == 0) { 593 if (diff == 0) {
595 return cur; 594 return cur;
596 } else if (diff < 0) { 595 } else if (diff < 0) {
597 end = cur - 1; 596 end = cur - 1;
598 } else { 597 } else {
599 start = cur + 1; 598 start = cur + 1;
600 } 599 }
601 } while (start <= end); 600 } while (start <= end);
602 return -1; 601 return -1;
603} 602}
604 603
605static void 604static void
606PrintLocation(FILE *f, const char *filename, size_t lineno) 605PrintLocation(FILE *f, const char *filename, size_t lineno)
607{ 606{
608 char dirbuf[MAXPATHLEN+1]; 607 char dirbuf[MAXPATHLEN+1];
609 const char *dir, *base; 608 const char *dir, *base;
610 char *dir_freeIt, *base_freeIt; 609 char *dir_freeIt, *base_freeIt;
611 610
612 if (*filename == '/' || strcmp(filename, "(stdin)") == 0) { 611 if (*filename == '/' || strcmp(filename, "(stdin)") == 0) {
613 (void)fprintf(f, "\"%s\" line %zu: ", filename, lineno); 612 (void)fprintf(f, "\"%s\" line %zu: ", filename, lineno);
614 return; 613 return;
615 } 614 }
616 615
617 /* Find out which makefile is the culprit. 616 /* Find out which makefile is the culprit.
618 * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */ 617 * We try ${.PARSEDIR} and apply realpath(3) if not absolute. */
619 618
620 dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &dir_freeIt); 619 dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &dir_freeIt);
621 if (dir == NULL) 620 if (dir == NULL)
622 dir = "."; 621 dir = ".";
623 if (*dir != '/') 622 if (*dir != '/')
624 dir = realpath(dir, dirbuf); 623 dir = realpath(dir, dirbuf);
625 624
626 base = Var_Value(".PARSEFILE", VAR_GLOBAL, &base_freeIt); 625 base = Var_Value(".PARSEFILE", VAR_GLOBAL, &base_freeIt);
627 if (base == NULL) { 626 if (base == NULL) {
628 const char *slash = strrchr(filename, '/'); 627 const char *slash = strrchr(filename, '/');
629 base = slash != NULL ? slash + 1 : filename; 628 base = slash != NULL ? slash + 1 : filename;
630 } 629 }
631 630
632 (void)fprintf(f, "\"%s/%s\" line %zu: ", dir, base, lineno); 631 (void)fprintf(f, "\"%s/%s\" line %zu: ", dir, base, lineno);
633 bmake_free(base_freeIt); 632 bmake_free(base_freeIt);
634 bmake_free(dir_freeIt); 633 bmake_free(dir_freeIt);
635} 634}
636 635
637/* Print a parse error message, including location information. 636/* Print a parse error message, including location information.
638 * 637 *
639 * Increment "fatals" if the level is PARSE_FATAL, and continue parsing 638 * Increment "fatals" if the level is PARSE_FATAL, and continue parsing
640 * until the end of the current top-level makefile, then exit (see 639 * until the end of the current top-level makefile, then exit (see
641 * Parse_File). */ 640 * Parse_File). */
642static void 641static void
643ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, 642ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno,
644 ParseErrorLevel type, const char *fmt, va_list ap) 643 ParseErrorLevel type, const char *fmt, va_list ap)
645{ 644{
646 static Boolean fatal_warning_error_printed = FALSE; 645 static Boolean fatal_warning_error_printed = FALSE;
647 646
648 (void)fprintf(f, "%s: ", progname); 647 (void)fprintf(f, "%s: ", progname);
649 648
650 if (cfname != NULL) 649 if (cfname != NULL)
651 PrintLocation(f, cfname, clineno); 650 PrintLocation(f, cfname, clineno);
652 if (type == PARSE_WARNING) 651 if (type == PARSE_WARNING)
653 (void)fprintf(f, "warning: "); 652 (void)fprintf(f, "warning: ");
654 (void)vfprintf(f, fmt, ap); 653 (void)vfprintf(f, fmt, ap);
655 (void)fprintf(f, "\n"); 654 (void)fprintf(f, "\n");
656 (void)fflush(f); 655 (void)fflush(f);
657 656
658 if (type == PARSE_INFO) 657 if (type == PARSE_INFO)
659 return; 658 return;
660 if (type == PARSE_FATAL || opts.parseWarnFatal) 659 if (type == PARSE_FATAL || opts.parseWarnFatal)
661 fatals++; 660 fatals++;
662 if (opts.parseWarnFatal && !fatal_warning_error_printed) { 661 if (opts.parseWarnFatal && !fatal_warning_error_printed) {
663 Error("parsing warnings being treated as errors"); 662 Error("parsing warnings being treated as errors");
664 fatal_warning_error_printed = TRUE; 663 fatal_warning_error_printed = TRUE;
665 } 664 }
666} 665}
667 666
668static void 667static void
669ParseErrorInternal(const char *cfname, size_t clineno, ParseErrorLevel type, 668ParseErrorInternal(const char *cfname, size_t clineno, ParseErrorLevel type,
670 const char *fmt, ...) 669 const char *fmt, ...)
671{ 670{
672 va_list ap; 671 va_list ap;
673 672
674 va_start(ap, fmt); 673 va_start(ap, fmt);
675 (void)fflush(stdout); 674 (void)fflush(stdout);
676 ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap); 675 ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap);
677 va_end(ap); 676 va_end(ap);
678 677
679 if (opts.debug_file != stderr && opts.debug_file != stdout) { 678 if (opts.debug_file != stderr && opts.debug_file != stdout) {
680 va_start(ap, fmt); 679 va_start(ap, fmt);
681 ParseVErrorInternal(opts.debug_file, cfname, clineno, type, 680 ParseVErrorInternal(opts.debug_file, cfname, clineno, type,
682 fmt, ap); 681 fmt, ap);
683 va_end(ap); 682 va_end(ap);
684 } 683 }
685} 684}
686 685
687/* External interface to ParseErrorInternal; uses the default filename and 686/* External interface to ParseErrorInternal; uses the default filename and
688 * line number. 687 * line number.
689 * 688 *
690 * Fmt is given without a trailing newline. */ 689 * Fmt is given without a trailing newline. */
691void 690void
692Parse_Error(ParseErrorLevel type, const char *fmt, ...) 691Parse_Error(ParseErrorLevel type, const char *fmt, ...)
693{ 692{
694 va_list ap; 693 va_list ap;
695 const char *fname; 694 const char *fname;
696 size_t lineno; 695 size_t lineno;
697 696
698 if (curFile == NULL) { 697 if (curFile == NULL) {
699 fname = NULL; 698 fname = NULL;
700 lineno = 0; 699 lineno = 0;
701 } else { 700 } else {
702 fname = curFile->fname; 701 fname = curFile->fname;
703 lineno = (size_t)curFile->lineno; 702 lineno = (size_t)curFile->lineno;
704 } 703 }
705 704
706 va_start(ap, fmt); 705 va_start(ap, fmt);
707 (void)fflush(stdout); 706 (void)fflush(stdout);
708 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); 707 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
709 va_end(ap); 708 va_end(ap);
710 709
711 if (opts.debug_file != stderr && opts.debug_file != stdout) { 710 if (opts.debug_file != stderr && opts.debug_file != stdout) {
712 va_start(ap, fmt); 711 va_start(ap, fmt);
713 ParseVErrorInternal(opts.debug_file, fname, lineno, type, 712 ParseVErrorInternal(opts.debug_file, fname, lineno, type,
714 fmt, ap); 713 fmt, ap);
715 va_end(ap); 714 va_end(ap);
716 } 715 }
717} 716}
718 717
719 718
720/* Parse a .info .warning or .error directive. 719/* Parse a .info .warning or .error directive.
721 * 720 *
722 * The input is the line minus the ".". We substitute variables, print the 721 * The input is the line minus the ".". We substitute variables, print the
723 * message and exit(1) (for .error) or just print a warning if the directive 722 * message and exit(1) (for .error) or just print a warning if the directive
724 * is malformed. 723 * is malformed.
725 */ 724 */
726static Boolean 725static Boolean
727ParseMessage(const char *directive) 726ParseMessage(const char *directive)
728{ 727{
729 const char *p = directive; 728 const char *p = directive;
730 int mtype = *p == 'i' ? PARSE_INFO : 729 int mtype = *p == 'i' ? PARSE_INFO :
731 *p == 'w' ? PARSE_WARNING : PARSE_FATAL; 730 *p == 'w' ? PARSE_WARNING : PARSE_FATAL;
732 char *arg; 731 char *arg;
733 732
734 while (ch_isalpha(*p)) 733 while (ch_isalpha(*p))
735 p++; 734 p++;
736 if (!ch_isspace(*p)) 735 if (!ch_isspace(*p))
737 return FALSE; /* missing argument */ 736 return FALSE; /* missing argument */
738 737
739 cpp_skip_whitespace(&p); 738 cpp_skip_whitespace(&p);
740 (void)Var_Subst(p, VAR_CMD, VARE_WANTRES, &arg); 739 (void)Var_Subst(p, VAR_CMD, VARE_WANTRES, &arg);
741 /* TODO: handle errors */ 740 /* TODO: handle errors */
742 741
743 Parse_Error(mtype, "%s", arg); 742 Parse_Error(mtype, "%s", arg);
744 free(arg); 743 free(arg);
745 744
746 if (mtype == PARSE_FATAL) { 745 if (mtype == PARSE_FATAL) {
747 PrintOnError(NULL, NULL); 746 PrintOnError(NULL, NULL);
748 exit(1); 747 exit(1);
749 } 748 }
750 return TRUE; 749 return TRUE;
751} 750}
752 751
753/* Add the child to the parent's children. 752/* Add the child to the parent's children.
754 * 753 *
755 * Additionally, add the parent to the child's parents, but only if the 754 * Additionally, add the parent to the child's parents, but only if the
756 * target is not special. An example for such a special target is .END, 755 * target is not special. An example for such a special target is .END,
757 * which does not need to be informed once the child target has been made. */ 756 * which does not need to be informed once the child target has been made. */
758static void 757static void
759LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial) 758LinkSource(GNode *pgn, GNode *cgn, Boolean isSpecial)
760{ 759{
761 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts)) 760 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty(pgn->cohorts))
762 pgn = pgn->cohorts->last->datum; 761 pgn = pgn->cohorts->last->datum;
763 762
764 Lst_Append(pgn->children, cgn); 763 Lst_Append(pgn->children, cgn);
765 pgn->unmade++; 764 pgn->unmade++;
766 765
767 /* Special targets like .END don't need any children. */ 766 /* Special targets like .END don't need any children. */
768 if (!isSpecial) 767 if (!isSpecial)
769 Lst_Append(cgn->parents, pgn); 768 Lst_Append(cgn->parents, pgn);
770 769
771 if (DEBUG(PARSE)) { 770 if (DEBUG(PARSE)) {
772 debug_printf("# %s: added child %s - %s\n", 771 debug_printf("# %s: added child %s - %s\n",
773 __func__, pgn->name, cgn->name); 772 __func__, pgn->name, cgn->name);
774 Targ_PrintNode(pgn, 0); 773 Targ_PrintNode(pgn, 0);
775 Targ_PrintNode(cgn, 0); 774 Targ_PrintNode(cgn, 0);
776 } 775 }
777} 776}
778 777
779/* Add the node to each target from the current dependency group. */ 778/* Add the node to each target from the current dependency group. */
780static void 779static void
781LinkToTargets(GNode *gn, Boolean isSpecial) 780LinkToTargets(GNode *gn, Boolean isSpecial)
782{ 781{
783 GNodeListNode *ln; 782 GNodeListNode *ln;
784 for (ln = targets->first; ln != NULL; ln = ln->next) 783 for (ln = targets->first; ln != NULL; ln = ln->next)
785 LinkSource(ln->datum, gn, isSpecial); 784 LinkSource(ln->datum, gn, isSpecial);
786} 785}
787 786
788static Boolean 787static Boolean
789TryApplyDependencyOperator(GNode *gn, GNodeType op) 788TryApplyDependencyOperator(GNode *gn, GNodeType op)
790{ 789{
791 /* 790 /*
792 * 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
793 * operator also defines a dependency, they must match. 792 * operator also defines a dependency, they must match.
794 */ 793 */
795 if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) && 794 if ((op & OP_OPMASK) && (gn->type & OP_OPMASK) &&
796 ((op & OP_OPMASK) != (gn->type & OP_OPMASK))) 795 ((op & OP_OPMASK) != (gn->type & OP_OPMASK)))
797 { 796 {
798 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 797 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
799 return FALSE; 798 return FALSE;
800 } 799 }
801 800
802 if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) { 801 if (op == OP_DOUBLEDEP && (gn->type & OP_OPMASK) == OP_DOUBLEDEP) {
803 /* 802 /*
804 * If the node was the object of a :: operator, we need to create a 803 * If the node was the object of a :: operator, we need to create a
805 * new instance of it for the children and commands on this dependency 804 * new instance of it for the children and commands on this dependency
806 * line. The new instance is placed on the 'cohorts' list of the 805 * line. The new instance is placed on the 'cohorts' list of the
807 * initial one (note the initial one is not on its own cohorts list) 806 * initial one (note the initial one is not on its own cohorts list)
808 * and the new instance is linked to all parents of the initial 807 * and the new instance is linked to all parents of the initial
809 * instance. 808 * instance.
810 */ 809 */
811 GNode *cohort; 810 GNode *cohort;
812 811
813 /* 812 /*
814 * Propagate copied bits to the initial node. They'll be propagated 813 * Propagate copied bits to the initial node. They'll be propagated
815 * back to the rest of the cohorts later. 814 * back to the rest of the cohorts later.
816 */ 815 */
817 gn->type |= op & ~OP_OPMASK; 816 gn->type |= op & ~OP_OPMASK;
818 817
819 cohort = Targ_NewInternalNode(gn->name); 818 cohort = Targ_NewInternalNode(gn->name);
820 if (doing_depend) 819 if (doing_depend)
821 ParseMark(cohort); 820 ParseMark(cohort);
822 /* 821 /*
823 * Make the cohort invisible as well to avoid duplicating it into 822 * Make the cohort invisible as well to avoid duplicating it into
824 * other variables. True, parents of this target won't tend to do 823 * other variables. True, parents of this target won't tend to do
825 * anything with their local variables, but better safe than 824 * anything with their local variables, but better safe than
826 * sorry. (I think this is pointless now, since the relevant list 825 * sorry. (I think this is pointless now, since the relevant list
827 * traversals will no longer see this node anyway. -mycroft) 826 * traversals will no longer see this node anyway. -mycroft)
828 */ 827 */
829 cohort->type = op | OP_INVISIBLE; 828 cohort->type = op | OP_INVISIBLE;
830 Lst_Append(gn->cohorts, cohort); 829 Lst_Append(gn->cohorts, cohort);
831 cohort->centurion = gn; 830 cohort->centurion = gn;
832 gn->unmade_cohorts++; 831 gn->unmade_cohorts++;
833 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", 832 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
834 (unsigned int)gn->unmade_cohorts % 1000000); 833 (unsigned int)gn->unmade_cohorts % 1000000);
835 } else { 834 } else {
836 /* 835 /*
837 * We don't want to nuke any previous flags (whatever they were) so we 836 * We don't want to nuke any previous flags (whatever they were) so we
838 * just OR the new operator into the old 837 * just OR the new operator into the old
839 */ 838 */
840 gn->type |= op; 839 gn->type |= op;
841 } 840 }
842 841
843 return TRUE; 842 return TRUE;
844} 843}
845 844
846static void 845static void
847ApplyDependencyOperator(GNodeType op) 846ApplyDependencyOperator(GNodeType op)
848{ 847{
849 GNodeListNode *ln; 848 GNodeListNode *ln;
850 for (ln = targets->first; ln != NULL; ln = ln->next) 849 for (ln = targets->first; ln != NULL; ln = ln->next)
851 if (!TryApplyDependencyOperator(ln->datum, op)) 850 if (!TryApplyDependencyOperator(ln->datum, op))
852 break; 851 break;
853} 852}
854 853
855static Boolean 854static Boolean
856ParseDoSrcKeyword(const char *src, ParseSpecial specType) 855ParseDoSrcKeyword(const char *src, ParseSpecial specType)
857{ 856{
858 static int wait_number = 0; 857 static int wait_number = 0;
859 char wait_src[16]; 858 char wait_src[16];
860 GNode *gn; 859 GNode *gn;
861 860
862 if (*src == '.' && ch_isupper(src[1])) { 861 if (*src == '.' && ch_isupper(src[1])) {
863 int keywd = ParseFindKeyword(src); 862 int keywd = ParseFindKeyword(src);
864 if (keywd != -1) { 863 if (keywd != -1) {
865 int op = parseKeywords[keywd].op; 864 int op = parseKeywords[keywd].op;
866 if (op != 0) { 865 if (op != 0) {
867 ApplyDependencyOperator(op); 866 ApplyDependencyOperator(op);
868 return TRUE; 867 return TRUE;
869 } 868 }
870 if (parseKeywords[keywd].spec == SP_WAIT) { 869 if (parseKeywords[keywd].spec == SP_WAIT) {
871 /* 870 /*
872 * We add a .WAIT node in the dependency list. 871 * We add a .WAIT node in the dependency list.
873 * After any dynamic dependencies (and filename globbing) 872 * After any dynamic dependencies (and filename globbing)
874 * have happened, it is given a dependency on the each 873 * have happened, it is given a dependency on the each
875 * previous child back to and previous .WAIT node. 874 * previous child back to and previous .WAIT node.
876 * The next child won't be scheduled until the .WAIT node 875 * The next child won't be scheduled until the .WAIT node
877 * is built. 876 * is built.
878 * We give each .WAIT node a unique name (mainly for diag). 877 * We give each .WAIT node a unique name (mainly for diag).
879 */ 878 */
880 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); 879 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
881 gn = Targ_NewInternalNode(wait_src); 880 gn = Targ_NewInternalNode(wait_src);
882 if (doing_depend) 881 if (doing_depend)
883 ParseMark(gn); 882 ParseMark(gn);
884 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; 883 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
885 LinkToTargets(gn, specType != SP_NOT); 884 LinkToTargets(gn, specType != SP_NOT);
886 return TRUE; 885 return TRUE;
887 } 886 }
888 } 887 }
889 } 888 }
890 return FALSE; 889 return FALSE;
891} 890}
892 891
893static void 892static void
894ParseDoSrcMain(const char *src) 893ParseDoSrcMain(const char *src)
895{ 894{
896 /* 895 /*
897 * If we have noted the existence of a .MAIN, it means we need 896 * If we have noted the existence of a .MAIN, it means we need
898 * to add the sources of said target to the list of things 897 * to add the sources of said target to the list of things
899 * to create. The string 'src' is likely to be free, so we 898 * to create. The string 'src' is likely to be free, so we
900 * must make a new copy of it. Note that this will only be 899 * must make a new copy of it. Note that this will only be
901 * invoked if the user didn't specify a target on the command 900 * invoked if the user didn't specify a target on the command
902 * line. This is to allow #ifmake's to succeed, or something... 901 * line. This is to allow #ifmake's to succeed, or something...
903 */ 902 */
904 Lst_Append(opts.create, bmake_strdup(src)); 903 Lst_Append(opts.create, bmake_strdup(src));
905 /* 904 /*
906 * Add the name to the .TARGETS variable as well, so the user can 905 * Add the name to the .TARGETS variable as well, so the user can
907 * employ that, if desired. 906 * employ that, if desired.
908 */ 907 */
909 Var_Append(".TARGETS", src, VAR_GLOBAL); 908 Var_Append(".TARGETS", src, VAR_GLOBAL);
910} 909}
911 910
912static void 911static void
913ParseDoSrcOrder(const char *src) 912ParseDoSrcOrder(const char *src)
914{ 913{
915 GNode *gn; 914 GNode *gn;
916 /* 915 /*
917 * Create proper predecessor/successor links between the previous 916 * Create proper predecessor/successor links between the previous
918 * source and the current one. 917 * source and the current one.
919 */ 918 */
920 gn = Targ_GetNode(src); 919 gn = Targ_GetNode(src);
921 if (doing_depend) 920 if (doing_depend)
922 ParseMark(gn); 921 ParseMark(gn);
923 if (predecessor != NULL) { 922 if (predecessor != NULL) {
924 Lst_Append(predecessor->order_succ, gn); 923 Lst_Append(predecessor->order_succ, gn);
925 Lst_Append(gn->order_pred, predecessor); 924 Lst_Append(gn->order_pred, predecessor);
926 if (DEBUG(PARSE)) { 925 if (DEBUG(PARSE)) {
927 debug_printf("# %s: added Order dependency %s - %s\n", 926 debug_printf("# %s: added Order dependency %s - %s\n",
928 __func__, predecessor->name, gn->name); 927 __func__, predecessor->name, gn->name);
929 Targ_PrintNode(predecessor, 0); 928 Targ_PrintNode(predecessor, 0);
930 Targ_PrintNode(gn, 0); 929 Targ_PrintNode(gn, 0);
931 } 930 }
932 } 931 }
933 /* 932 /*
934 * The current source now becomes the predecessor for the next one. 933 * The current source now becomes the predecessor for the next one.
935 */ 934 */
936 predecessor = gn; 935 predecessor = gn;
937} 936}
938 937
939static void 938static void
940ParseDoSrcOther(const char *src, GNodeType tOp, ParseSpecial specType) 939ParseDoSrcOther(const char *src, GNodeType tOp, ParseSpecial specType)
941{ 940{
942 GNode *gn; 941 GNode *gn;
943 942
944 /* 943 /*
945 * If the source is not an attribute, we need to find/create 944 * If the source is not an attribute, we need to find/create
946 * a node for it. After that we can apply any operator to it 945 * a node for it. After that we can apply any operator to it
947 * from a special target or link it to its parents, as 946 * from a special target or link it to its parents, as
948 * appropriate. 947 * appropriate.
949 * 948 *
950 * In the case of a source that was the object of a :: operator, 949 * In the case of a source that was the object of a :: operator,
951 * the attribute is applied to all of its instances (as kept in 950 * the attribute is applied to all of its instances (as kept in
952 * the 'cohorts' list of the node) or all the cohorts are linked 951 * the 'cohorts' list of the node) or all the cohorts are linked
953 * to all the targets. 952 * to all the targets.
954 */ 953 */
955 954
956 /* Find/create the 'src' node and attach to all targets */ 955 /* Find/create the 'src' node and attach to all targets */
957 gn = Targ_GetNode(src); 956 gn = Targ_GetNode(src);
958 if (doing_depend) 957 if (doing_depend)
959 ParseMark(gn); 958 ParseMark(gn);
960 if (tOp) { 959 if (tOp) {
961 gn->type |= tOp; 960 gn->type |= tOp;
962 } else { 961 } else {
963 LinkToTargets(gn, specType != SP_NOT); 962 LinkToTargets(gn, specType != SP_NOT);
964 } 963 }
965} 964}
966 965
967/* Given the name of a source in a dependency line, figure out if it is an 966/* Given the name of a source in a dependency line, figure out if it is an
968 * attribute (such as .SILENT) and apply it to the targets if it is. Else 967 * attribute (such as .SILENT) and apply it to the targets if it is. Else
969 * decide if there is some attribute which should be applied *to* the source 968 * decide if there is some attribute which should be applied *to* the source
970 * because of some special target (such as .PHONY) and apply it if so. 969 * because of some special target (such as .PHONY) and apply it if so.
971 * Otherwise, make the source a child of the targets in the list 'targets'. 970 * Otherwise, make the source a child of the targets in the list 'targets'.
972 * 971 *
973 * Input: 972 * Input:
974 * tOp operator (if any) from special targets 973 * tOp operator (if any) from special targets
975 * src name of the source to handle 974 * src name of the source to handle
976 */ 975 */
977static void 976static void
978ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType) 977ParseDoSrc(GNodeType tOp, const char *src, ParseSpecial specType)
979{ 978{
980 if (ParseDoSrcKeyword(src, specType)) 979 if (ParseDoSrcKeyword(src, specType))
981 return; 980 return;
982 981
983 if (specType == SP_MAIN) 982 if (specType == SP_MAIN)
984 ParseDoSrcMain(src); 983 ParseDoSrcMain(src);
985 else if (specType == SP_ORDER) 984 else if (specType == SP_ORDER)
986 ParseDoSrcOrder(src); 985 ParseDoSrcOrder(src);
987 else 986 else
988 ParseDoSrcOther(src, tOp, specType); 987 ParseDoSrcOther(src, tOp, specType);
989} 988}
990 989
991/* If we have yet to decide on a main target to make, in the absence of any 990/* If we have yet to decide on a main target to make, in the absence of any
992 * user input, we want the first target on the first dependency line that is 991 * user input, we want the first target on the first dependency line that is
993 * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made. */ 992 * actually a real target (i.e. isn't a .USE or .EXEC rule) to be made. */
994static void 993static void
995FindMainTarget(void) 994FindMainTarget(void)
996{ 995{
997 GNodeListNode *ln; 996 GNodeListNode *ln;
998 997
999 if (mainNode != NULL) 998 if (mainNode != NULL)
1000 return; 999 return;
1001 1000
1002 for (ln = targets->first; ln != NULL; ln = ln->next) { 1001 for (ln = targets->first; ln != NULL; ln = ln->next) {
1003 GNode *gn = ln->datum; 1002 GNode *gn = ln->datum;
1004 if (!(gn->type & OP_NOTARGET)) { 1003 if (!(gn->type & OP_NOTARGET)) {
1005 mainNode = gn; 1004 mainNode = gn;
1006 Targ_SetMain(gn); 1005 Targ_SetMain(gn);
1007 return; 1006 return;
1008 } 1007 }
1009 } 1008 }
1010} 1009}
1011 1010
1012/* 1011/*
1013 * We got to the end of the line while we were still looking at targets. 1012 * We got to the end of the line while we were still looking at targets.
1014 * 1013 *
1015 * Ending a dependency line without an operator is a Bozo no-no. As a 1014 * Ending a dependency line without an operator is a Bozo no-no. As a
1016 * heuristic, this is also often triggered by undetected conflicts from 1015 * heuristic, this is also often triggered by undetected conflicts from
1017 * cvs/rcs merges. 1016 * cvs/rcs merges.
1018 */ 1017 */
1019static void 1018static void
1020ParseErrorNoDependency(const char *lstart) 1019ParseErrorNoDependency(const char *lstart)
1021{ 1020{
1022 if ((strncmp(lstart, "<<<<<<", 6) == 0) || 1021 if ((strncmp(lstart, "<<<<<<", 6) == 0) ||
1023 (strncmp(lstart, "======", 6) == 0) || 1022 (strncmp(lstart, "======", 6) == 0) ||
1024 (strncmp(lstart, ">>>>>>", 6) == 0)) 1023 (strncmp(lstart, ">>>>>>", 6) == 0))
1025 Parse_Error(PARSE_FATAL, 1024 Parse_Error(PARSE_FATAL,
1026 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 1025 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1027 else if (lstart[0] == '.') { 1026 else if (lstart[0] == '.') {
1028 const char *dirstart = lstart + 1; 1027 const char *dirstart = lstart + 1;
1029 const char *dirend; 1028 const char *dirend;
1030 cpp_skip_whitespace(&dirstart); 1029 cpp_skip_whitespace(&dirstart);
1031 dirend = dirstart; 1030 dirend = dirstart;
1032 while (ch_isalnum(*dirend) || *dirend == '-') 1031 while (ch_isalnum(*dirend) || *dirend == '-')
1033 dirend++; 1032 dirend++;
1034 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"", 1033 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
1035 (int)(dirend - dirstart), dirstart); 1034 (int)(dirend - dirstart), dirstart);
1036 } else 1035 } else
1037 Parse_Error(PARSE_FATAL, "Need an operator"); 1036 Parse_Error(PARSE_FATAL, "Need an operator");
1038} 1037}
1039 1038
1040static void 1039static void
1041ParseDependencyTargetWord(/*const*/ char **pp, const char *lstart) 1040ParseDependencyTargetWord(/*const*/ char **pp, const char *lstart)
1042{ 1041{
1043 /*const*/ char *cp = *pp; 1042 /*const*/ char *cp = *pp;
1044 1043
1045 while (*cp != '\0') { 1044 while (*cp != '\0') {
1046 if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' || *cp == '(') && 1045 if ((ch_isspace(*cp) || *cp == '!' || *cp == ':' || *cp == '(') &&
1047 !ParseIsEscaped(lstart, cp)) 1046 !ParseIsEscaped(lstart, cp))
1048 break; 1047 break;
1049 1048
1050 if (*cp == '$') { 1049 if (*cp == '$') {
1051 /* 1050 /*
1052 * Must be a dynamic source (would have been expanded 1051 * Must be a dynamic source (would have been expanded
1053 * otherwise), so call the Var module to parse the puppy 1052 * otherwise), so call the Var module to parse the puppy
1054 * so we can safely advance beyond it...There should be 1053 * so we can safely advance beyond it...There should be
1055 * no errors in this, as they would have been discovered 1054 * no errors in this, as they would have been discovered
1056 * in the initial Var_Subst and we wouldn't be here. 1055 * in the initial Var_Subst and we wouldn't be here.
1057 */ 1056 */
1058 const char *nested_p = cp; 1057 const char *nested_p = cp;
1059 const char *nested_val; 1058 const char *nested_val;
1060 void *freeIt; 1059 void *freeIt;
1061 1060
1062 (void)Var_Parse(&nested_p, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES, 1061 (void)Var_Parse(&nested_p, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES,
1063 &nested_val, &freeIt); 1062 &nested_val, &freeIt);
1064 /* TODO: handle errors */ 1063 /* TODO: handle errors */
1065 free(freeIt); 1064 free(freeIt);
1066 cp += nested_p - cp; 1065 cp += nested_p - cp;
1067 } else 1066 } else
1068 cp++; 1067 cp++;
1069 } 1068 }
1070 1069
1071 *pp = cp; 1070 *pp = cp;
1072} 1071}
1073 1072
1074/* 1073/*
1075 * Certain special targets have special semantics: 1074 * Certain special targets have special semantics:
1076 * .PATH Have to set the dirSearchPath 1075 * .PATH Have to set the dirSearchPath
1077 * variable too 1076 * variable too
1078 * .MAIN Its sources are only used if 1077 * .MAIN Its sources are only used if
1079 * nothing has been specified to 1078 * nothing has been specified to
1080 * create. 1079 * create.
1081 * .DEFAULT Need to create a node to hang 1080 * .DEFAULT Need to create a node to hang
1082 * commands on, but we don't want 1081 * commands on, but we don't want
1083 * it in the graph, nor do we want 1082 * it in the graph, nor do we want
1084 * it to be the Main Target, so we 1083 * it to be the Main Target, so we
1085 * create it, set OP_NOTMAIN and 1084 * create it, set OP_NOTMAIN and
1086 * add it to the list, setting 1085 * add it to the list, setting
1087 * DEFAULT to the new node for 1086 * DEFAULT to the new node for
1088 * later use. We claim the node is 1087 * later use. We claim the node is
1089 * A transformation rule to make 1088 * A transformation rule to make
1090 * life easier later, when we'll 1089 * life easier later, when we'll
1091 * use Make_HandleUse to actually 1090 * use Make_HandleUse to actually
1092 * apply the .DEFAULT commands. 1091 * apply the .DEFAULT commands.
1093 * .PHONY The list of targets 1092 * .PHONY The list of targets
1094 * .NOPATH Don't search for file in the path 1093 * .NOPATH Don't search for file in the path
1095 * .STALE 1094 * .STALE
1096 * .BEGIN 1095 * .BEGIN
1097 * .END 1096 * .END
1098 * .ERROR 1097 * .ERROR
1099 * .DELETE_ON_ERROR 1098 * .DELETE_ON_ERROR
1100 * .INTERRUPT Are not to be considered the 1099 * .INTERRUPT Are not to be considered the
1101 * main target. 1100 * main target.
1102 * .NOTPARALLEL Make only one target at a time. 1101 * .NOTPARALLEL Make only one target at a time.
1103 * .SINGLESHELL Create a shell for each command. 1102 * .SINGLESHELL Create a shell for each command.
1104 * .ORDER Must set initial predecessor to NULL 1103 * .ORDER Must set initial predecessor to NULL
1105 */ 1104 */
1106static void 1105static void
1107ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType, 1106ParseDoDependencyTargetSpecial(ParseSpecial *inout_specType,
1108 const char *line, 1107 const char *line,
1109 SearchPathList **inout_paths) 1108 SearchPathList **inout_paths)
1110{ 1109{
1111 switch (*inout_specType) { 1110 switch (*inout_specType) {
1112 case SP_PATH: 1111 case SP_PATH:
1113 if (*inout_paths == NULL) { 1112 if (*inout_paths == NULL) {
1114 *inout_paths = Lst_New(); 1113 *inout_paths = Lst_New();
1115 } 1114 }
1116 Lst_Append(*inout_paths, dirSearchPath); 1115 Lst_Append(*inout_paths, dirSearchPath);
1117 break; 1116 break;
1118 case SP_MAIN: 1117 case SP_MAIN:
1119 if (!Lst_IsEmpty(opts.create)) { 1118 if (!Lst_IsEmpty(opts.create)) {
1120 *inout_specType = SP_NOT; 1119 *inout_specType = SP_NOT;
1121 } 1120 }
1122 break; 1121 break;
1123 case SP_BEGIN: 1122 case SP_BEGIN:
1124 case SP_END: 1123 case SP_END:
1125 case SP_STALE: 1124 case SP_STALE:
1126 case SP_ERROR: 1125 case SP_ERROR:
1127 case SP_INTERRUPT: { 1126 case SP_INTERRUPT: {
1128 GNode *gn = Targ_GetNode(line); 1127 GNode *gn = Targ_GetNode(line);
1129 if (doing_depend) 1128 if (doing_depend)
1130 ParseMark(gn); 1129 ParseMark(gn);
1131 gn->type |= OP_NOTMAIN|OP_SPECIAL; 1130 gn->type |= OP_NOTMAIN|OP_SPECIAL;
1132 Lst_Append(targets, gn); 1131 Lst_Append(targets, gn);
1133 break; 1132 break;
1134 } 1133 }
1135 case SP_DEFAULT: { 1134 case SP_DEFAULT: {
1136 GNode *gn = Targ_NewGN(".DEFAULT"); 1135 GNode *gn = Targ_NewGN(".DEFAULT");
1137 gn->type |= OP_NOTMAIN|OP_TRANSFORM; 1136 gn->type |= OP_NOTMAIN|OP_TRANSFORM;
1138 Lst_Append(targets, gn); 1137 Lst_Append(targets, gn);
1139 DEFAULT = gn; 1138 DEFAULT = gn;
1140 break; 1139 break;
1141 } 1140 }
1142 case SP_DELETE_ON_ERROR: 1141 case SP_DELETE_ON_ERROR:
1143 deleteOnError = TRUE; 1142 deleteOnError = TRUE;
1144 break; 1143 break;
1145 case SP_NOTPARALLEL: 1144 case SP_NOTPARALLEL:
1146 opts.maxJobs = 1; 1145 opts.maxJobs = 1;
1147 break; 1146 break;
1148 case SP_SINGLESHELL: 1147 case SP_SINGLESHELL:
1149 opts.compatMake = TRUE; 1148 opts.compatMake = TRUE;
1150 break; 1149 break;
1151 case SP_ORDER: 1150 case SP_ORDER:
1152 predecessor = NULL; 1151 predecessor = NULL;
1153 break; 1152 break;
1154 default: 1153 default:
1155 break; 1154 break;
1156 } 1155 }
1157} 1156}
1158 1157
1159/* 1158/*
1160 * .PATH<suffix> has to be handled specially. 1159 * .PATH<suffix> has to be handled specially.
1161 * Call on the suffix module to give us a path to modify. 1160 * Call on the suffix module to give us a path to modify.