Tue Jul 28 18:15:11 2020 UTC ()
make(1): when parsing an unknown directive, print the directive name


(rillig)
diff -r1.239 -r1.240 src/usr.bin/make/parse.c
diff -r1.2 -r1.3 src/usr.bin/make/unit-tests/directives.exp

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

--- src/usr.bin/make/parse.c 2020/07/28 16:42:22 1.239
+++ src/usr.bin/make/parse.c 2020/07/28 18:15:11 1.240
@@ -1,2291 +1,2300 @@ @@ -1,2291 +1,2300 @@
1/* $NetBSD: parse.c,v 1.239 2020/07/28 16:42:22 rillig Exp $ */ 1/* $NetBSD: parse.c,v 1.240 2020/07/28 18:15: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#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: parse.c,v 1.239 2020/07/28 16:42:22 rillig Exp $"; 72static char rcsid[] = "$NetBSD: parse.c,v 1.240 2020/07/28 18:15:11 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76#if 0 76#if 0
77static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94"; 77static char sccsid[] = "@(#)parse.c 8.3 (Berkeley) 3/19/94";
78#else 78#else
79__RCSID("$NetBSD: parse.c,v 1.239 2020/07/28 16:42:22 rillig Exp $"); 79__RCSID("$NetBSD: parse.c,v 1.240 2020/07/28 18:15:11 rillig Exp $");
80#endif 80#endif
81#endif /* not lint */ 81#endif /* not lint */
82#endif 82#endif
83 83
84/*- 84/*-
85 * parse.c -- 85 * parse.c --
86 * Functions to parse a makefile. 86 * Functions to parse a makefile.
87 * 87 *
88 * One function, Parse_Init, must be called before any functions 88 * One function, Parse_Init, must be called before any functions
89 * in this module are used. After that, the function Parse_File is the 89 * in this module are used. After that, the function Parse_File is the
90 * main entry point and controls most of the other functions in this 90 * main entry point and controls most of the other functions in this
91 * module. 91 * module.
92 * 92 *
93 * Most important structures are kept in Lsts. Directories for 93 * Most important structures are kept in Lsts. Directories for
94 * the .include "..." function are kept in the 'parseIncPath' Lst, while 94 * the .include "..." function are kept in the 'parseIncPath' Lst, while
95 * those for the .include <...> are kept in the 'sysIncPath' Lst. The 95 * those for the .include <...> are kept in the 'sysIncPath' Lst. The
96 * targets currently being defined are kept in the 'targets' Lst. 96 * targets currently being defined are kept in the 'targets' Lst.
97 * 97 *
98 * The variables 'fname' and 'lineno' are used to track the name 98 * The variables 'fname' and 'lineno' are used to track the name
99 * of the current file and the line number in that file so that error 99 * of the current file and the line number in that file so that error
100 * messages can be more meaningful. 100 * messages can be more meaningful.
101 * 101 *
102 * Interface: 102 * Interface:
103 * Parse_Init Initialization function which must be 103 * Parse_Init Initialization function which must be
104 * called before anything else in this module 104 * called before anything else in this module
105 * is used. 105 * is used.
106 * 106 *
107 * Parse_End Cleanup the module 107 * Parse_End Cleanup the module
108 * 108 *
109 * Parse_File Function used to parse a makefile. It must 109 * Parse_File Function used to parse a makefile. It must
110 * be given the name of the file, which should 110 * be given the name of the file, which should
111 * already have been opened, and a function 111 * already have been opened, and a function
112 * to call to read a character from the file. 112 * to call to read a character from the file.
113 * 113 *
114 * Parse_IsVar Returns TRUE if the given line is a 114 * Parse_IsVar Returns TRUE if the given line is a
115 * variable assignment. Used by MainParseArgs 115 * variable assignment. Used by MainParseArgs
116 * to determine if an argument is a target 116 * to determine if an argument is a target
117 * or a variable assignment. Used internally 117 * or a variable assignment. Used internally
118 * for pretty much the same thing... 118 * for pretty much the same thing...
119 * 119 *
120 * Parse_Error Function called when an error occurs in 120 * Parse_Error Function called when an error occurs in
121 * parsing. Used by the variable and 121 * parsing. Used by the variable and
122 * conditional modules. 122 * conditional modules.
123 * Parse_MainName Returns a Lst of the main target to create. 123 * Parse_MainName Returns a Lst of the main target to create.
124 */ 124 */
125 125
126#include <sys/types.h> 126#include <sys/types.h>
127#include <sys/mman.h> 127#include <sys/mman.h>
128#include <sys/stat.h> 128#include <sys/stat.h>
129#include <assert.h> 129#include <assert.h>
130#include <ctype.h> 130#include <ctype.h>
131#include <errno.h> 131#include <errno.h>
132#include <stdarg.h> 132#include <stdarg.h>
133#include <stdio.h> 133#include <stdio.h>
134#include <stdint.h> 134#include <stdint.h>
135 135
136#ifndef MAP_FILE 136#ifndef MAP_FILE
137#define MAP_FILE 0 137#define MAP_FILE 0
138#endif 138#endif
139#ifndef MAP_COPY 139#ifndef MAP_COPY
140#define MAP_COPY MAP_PRIVATE 140#define MAP_COPY MAP_PRIVATE
141#endif 141#endif
142 142
143#include "make.h" 143#include "make.h"
144#include "hash.h" 144#include "hash.h"
145#include "dir.h" 145#include "dir.h"
146#include "job.h" 146#include "job.h"
147#include "buf.h" 147#include "buf.h"
148#include "pathnames.h" 148#include "pathnames.h"
149 149
150//////////////////////////////////////////////////////////// 150////////////////////////////////////////////////////////////
151// types and constants 151// types and constants
152 152
153/* 153/*
154 * Structure for a file being read ("included file") 154 * Structure for a file being read ("included file")
155 */ 155 */
156typedef struct IFile { 156typedef struct IFile {
157 char *fname; /* name of file */ 157 char *fname; /* name of file */
158 int lineno; /* current line number in file */ 158 int lineno; /* current line number in file */
159 int first_lineno; /* line number of start of text */ 159 int first_lineno; /* line number of start of text */
160 int cond_depth; /* 'if' nesting when file opened */ 160 int cond_depth; /* 'if' nesting when file opened */
161 Boolean depending; /* state of doing_depend on EOF */ 161 Boolean depending; /* state of doing_depend on EOF */
162 char *P_str; /* point to base of string buffer */ 162 char *P_str; /* point to base of string buffer */
163 char *P_ptr; /* point to next char of string buffer */ 163 char *P_ptr; /* point to next char of string buffer */
164 char *P_end; /* point to the end of string buffer */ 164 char *P_end; /* point to the end of string buffer */
165 char *(*nextbuf)(void *, size_t *); /* Function to get more data */ 165 char *(*nextbuf)(void *, size_t *); /* Function to get more data */
166 void *nextbuf_arg; /* Opaque arg for nextbuf() */ 166 void *nextbuf_arg; /* Opaque arg for nextbuf() */
167 struct loadedfile *lf; /* loadedfile object, if any */ 167 struct loadedfile *lf; /* loadedfile object, if any */
168} IFile; 168} IFile;
169 169
170 170
171/* 171/*
172 * These values are returned by ParseEOF to tell Parse_File whether to 172 * These values are returned by ParseEOF to tell Parse_File whether to
173 * CONTINUE parsing, i.e. it had only reached the end of an include file, 173 * CONTINUE parsing, i.e. it had only reached the end of an include file,
174 * or if it's DONE. 174 * or if it's DONE.
175 */ 175 */
176#define CONTINUE 1 176#define CONTINUE 1
177#define DONE 0 177#define DONE 0
178 178
179/* 179/*
180 * Tokens for target attributes 180 * Tokens for target attributes
181 */ 181 */
182typedef enum { 182typedef enum {
183 Begin, /* .BEGIN */ 183 Begin, /* .BEGIN */
184 Default, /* .DEFAULT */ 184 Default, /* .DEFAULT */
185 DeleteOnError, /* .DELETE_ON_ERROR */ 185 DeleteOnError, /* .DELETE_ON_ERROR */
186 End, /* .END */ 186 End, /* .END */
187 dotError, /* .ERROR */ 187 dotError, /* .ERROR */
188 Ignore, /* .IGNORE */ 188 Ignore, /* .IGNORE */
189 Includes, /* .INCLUDES */ 189 Includes, /* .INCLUDES */
190 Interrupt, /* .INTERRUPT */ 190 Interrupt, /* .INTERRUPT */
191 Libs, /* .LIBS */ 191 Libs, /* .LIBS */
192 Meta, /* .META */ 192 Meta, /* .META */
193 MFlags, /* .MFLAGS or .MAKEFLAGS */ 193 MFlags, /* .MFLAGS or .MAKEFLAGS */
194 Main, /* .MAIN and we don't have anything user-specified to 194 Main, /* .MAIN and we don't have anything user-specified to
195 * make */ 195 * make */
196 NoExport, /* .NOEXPORT */ 196 NoExport, /* .NOEXPORT */
197 NoMeta, /* .NOMETA */ 197 NoMeta, /* .NOMETA */
198 NoMetaCmp, /* .NOMETA_CMP */ 198 NoMetaCmp, /* .NOMETA_CMP */
199 NoPath, /* .NOPATH */ 199 NoPath, /* .NOPATH */
200 Not, /* Not special */ 200 Not, /* Not special */
201 NotParallel, /* .NOTPARALLEL */ 201 NotParallel, /* .NOTPARALLEL */
202 Null, /* .NULL */ 202 Null, /* .NULL */
203 ExObjdir, /* .OBJDIR */ 203 ExObjdir, /* .OBJDIR */
204 Order, /* .ORDER */ 204 Order, /* .ORDER */
205 Parallel, /* .PARALLEL */ 205 Parallel, /* .PARALLEL */
206 ExPath, /* .PATH */ 206 ExPath, /* .PATH */
207 Phony, /* .PHONY */ 207 Phony, /* .PHONY */
208#ifdef POSIX 208#ifdef POSIX
209 Posix, /* .POSIX */ 209 Posix, /* .POSIX */
210#endif 210#endif
211 Precious, /* .PRECIOUS */ 211 Precious, /* .PRECIOUS */
212 ExShell, /* .SHELL */ 212 ExShell, /* .SHELL */
213 Silent, /* .SILENT */ 213 Silent, /* .SILENT */
214 SingleShell, /* .SINGLESHELL */ 214 SingleShell, /* .SINGLESHELL */
215 Stale, /* .STALE */ 215 Stale, /* .STALE */
216 Suffixes, /* .SUFFIXES */ 216 Suffixes, /* .SUFFIXES */
217 Wait, /* .WAIT */ 217 Wait, /* .WAIT */
218 Attribute /* Generic attribute */ 218 Attribute /* Generic attribute */
219} ParseSpecial; 219} ParseSpecial;
220 220
221/* 221/*
222 * Other tokens 222 * Other tokens
223 */ 223 */
224#define LPAREN '(' 224#define LPAREN '('
225#define RPAREN ')' 225#define RPAREN ')'
226 226
227 227
228//////////////////////////////////////////////////////////// 228////////////////////////////////////////////////////////////
229// result data 229// result data
230 230
231/* 231/*
232 * The main target to create. This is the first target on the first 232 * The main target to create. This is the first target on the first
233 * dependency line in the first makefile. 233 * dependency line in the first makefile.
234 */ 234 */
235static GNode *mainNode; 235static GNode *mainNode;
236 236
237//////////////////////////////////////////////////////////// 237////////////////////////////////////////////////////////////
238// eval state 238// eval state
239 239
240/* targets we're working on */ 240/* targets we're working on */
241static Lst targets; 241static Lst targets;
242 242
243#ifdef CLEANUP 243#ifdef CLEANUP
244/* command lines for targets */ 244/* command lines for targets */
245static Lst targCmds; 245static Lst targCmds;
246#endif 246#endif
247 247
248/* 248/*
249 * specType contains the SPECial TYPE of the current target. It is 249 * specType contains the SPECial TYPE of the current target. It is
250 * Not if the target is unspecial. If it *is* special, however, the children 250 * Not if the target is unspecial. If it *is* special, however, the children
251 * are linked as children of the parent but not vice versa. This variable is 251 * are linked as children of the parent but not vice versa. This variable is
252 * set in ParseDoDependency 252 * set in ParseDoDependency
253 */ 253 */
254static ParseSpecial specType; 254static ParseSpecial specType;
255 255
256/* 256/*
257 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER 257 * Predecessor node for handling .ORDER. Initialized to NULL when .ORDER
258 * seen, then set to each successive source on the line. 258 * seen, then set to each successive source on the line.
259 */ 259 */
260static GNode *predecessor; 260static GNode *predecessor;
261 261
262//////////////////////////////////////////////////////////// 262////////////////////////////////////////////////////////////
263// parser state 263// parser state
264 264
265/* true if currently in a dependency line or its commands */ 265/* true if currently in a dependency line or its commands */
266static Boolean inLine; 266static Boolean inLine;
267 267
268/* number of fatal errors */ 268/* number of fatal errors */
269static int fatals = 0; 269static int fatals = 0;
270 270
271/* 271/*
272 * Variables for doing includes 272 * Variables for doing includes
273 */ 273 */
274 274
275/* current file being read */ 275/* current file being read */
276static IFile *curFile; 276static IFile *curFile;
277 277
278/* stack of IFiles generated by .includes */ 278/* stack of IFiles generated by .includes */
279static Lst includes; 279static Lst includes;
280 280
281/* include paths (lists of directories) */ 281/* include paths (lists of directories) */
282Lst parseIncPath; /* dirs for "..." includes */ 282Lst parseIncPath; /* dirs for "..." includes */
283Lst sysIncPath; /* dirs for <...> includes */ 283Lst sysIncPath; /* dirs for <...> includes */
284Lst defIncPath; /* default for sysIncPath */ 284Lst defIncPath; /* default for sysIncPath */
285 285
286//////////////////////////////////////////////////////////// 286////////////////////////////////////////////////////////////
287// parser tables 287// parser tables
288 288
289/* 289/*
290 * The parseKeywords table is searched using binary search when deciding 290 * The parseKeywords table is searched using binary search when deciding
291 * if a target or source is special. The 'spec' field is the ParseSpecial 291 * if a target or source is special. The 'spec' field is the ParseSpecial
292 * type of the keyword ("Not" if the keyword isn't special as a target) while 292 * type of the keyword ("Not" if the keyword isn't special as a target) while
293 * the 'op' field is the operator to apply to the list of targets if the 293 * the 'op' field is the operator to apply to the list of targets if the
294 * keyword is used as a source ("0" if the keyword isn't special as a source) 294 * keyword is used as a source ("0" if the keyword isn't special as a source)
295 */ 295 */
296static const struct { 296static const struct {
297 const char *name; /* Name of keyword */ 297 const char *name; /* Name of keyword */
298 ParseSpecial spec; /* Type when used as a target */ 298 ParseSpecial spec; /* Type when used as a target */
299 int op; /* Operator when used as a source */ 299 int op; /* Operator when used as a source */
300} parseKeywords[] = { 300} parseKeywords[] = {
301{ ".BEGIN", Begin, 0 }, 301{ ".BEGIN", Begin, 0 },
302{ ".DEFAULT", Default, 0 }, 302{ ".DEFAULT", Default, 0 },
303{ ".DELETE_ON_ERROR", DeleteOnError, 0 }, 303{ ".DELETE_ON_ERROR", DeleteOnError, 0 },
304{ ".END", End, 0 }, 304{ ".END", End, 0 },
305{ ".ERROR", dotError, 0 }, 305{ ".ERROR", dotError, 0 },
306{ ".EXEC", Attribute, OP_EXEC }, 306{ ".EXEC", Attribute, OP_EXEC },
307{ ".IGNORE", Ignore, OP_IGNORE }, 307{ ".IGNORE", Ignore, OP_IGNORE },
308{ ".INCLUDES", Includes, 0 }, 308{ ".INCLUDES", Includes, 0 },
309{ ".INTERRUPT", Interrupt, 0 }, 309{ ".INTERRUPT", Interrupt, 0 },
310{ ".INVISIBLE", Attribute, OP_INVISIBLE }, 310{ ".INVISIBLE", Attribute, OP_INVISIBLE },
311{ ".JOIN", Attribute, OP_JOIN }, 311{ ".JOIN", Attribute, OP_JOIN },
312{ ".LIBS", Libs, 0 }, 312{ ".LIBS", Libs, 0 },
313{ ".MADE", Attribute, OP_MADE }, 313{ ".MADE", Attribute, OP_MADE },
314{ ".MAIN", Main, 0 }, 314{ ".MAIN", Main, 0 },
315{ ".MAKE", Attribute, OP_MAKE }, 315{ ".MAKE", Attribute, OP_MAKE },
316{ ".MAKEFLAGS", MFlags, 0 }, 316{ ".MAKEFLAGS", MFlags, 0 },
317{ ".META", Meta, OP_META }, 317{ ".META", Meta, OP_META },
318{ ".MFLAGS", MFlags, 0 }, 318{ ".MFLAGS", MFlags, 0 },
319{ ".NOMETA", NoMeta, OP_NOMETA }, 319{ ".NOMETA", NoMeta, OP_NOMETA },
320{ ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP }, 320{ ".NOMETA_CMP", NoMetaCmp, OP_NOMETA_CMP },
321{ ".NOPATH", NoPath, OP_NOPATH }, 321{ ".NOPATH", NoPath, OP_NOPATH },
322{ ".NOTMAIN", Attribute, OP_NOTMAIN }, 322{ ".NOTMAIN", Attribute, OP_NOTMAIN },
323{ ".NOTPARALLEL", NotParallel, 0 }, 323{ ".NOTPARALLEL", NotParallel, 0 },
324{ ".NO_PARALLEL", NotParallel, 0 }, 324{ ".NO_PARALLEL", NotParallel, 0 },
325{ ".NULL", Null, 0 }, 325{ ".NULL", Null, 0 },
326{ ".OBJDIR", ExObjdir, 0 }, 326{ ".OBJDIR", ExObjdir, 0 },
327{ ".OPTIONAL", Attribute, OP_OPTIONAL }, 327{ ".OPTIONAL", Attribute, OP_OPTIONAL },
328{ ".ORDER", Order, 0 }, 328{ ".ORDER", Order, 0 },
329{ ".PARALLEL", Parallel, 0 }, 329{ ".PARALLEL", Parallel, 0 },
330{ ".PATH", ExPath, 0 }, 330{ ".PATH", ExPath, 0 },
331{ ".PHONY", Phony, OP_PHONY }, 331{ ".PHONY", Phony, OP_PHONY },
332#ifdef POSIX 332#ifdef POSIX
333{ ".POSIX", Posix, 0 }, 333{ ".POSIX", Posix, 0 },
334#endif 334#endif
335{ ".PRECIOUS", Precious, OP_PRECIOUS }, 335{ ".PRECIOUS", Precious, OP_PRECIOUS },
336{ ".RECURSIVE", Attribute, OP_MAKE }, 336{ ".RECURSIVE", Attribute, OP_MAKE },
337{ ".SHELL", ExShell, 0 }, 337{ ".SHELL", ExShell, 0 },
338{ ".SILENT", Silent, OP_SILENT }, 338{ ".SILENT", Silent, OP_SILENT },
339{ ".SINGLESHELL", SingleShell, 0 }, 339{ ".SINGLESHELL", SingleShell, 0 },
340{ ".STALE", Stale, 0 }, 340{ ".STALE", Stale, 0 },
341{ ".SUFFIXES", Suffixes, 0 }, 341{ ".SUFFIXES", Suffixes, 0 },
342{ ".USE", Attribute, OP_USE }, 342{ ".USE", Attribute, OP_USE },
343{ ".USEBEFORE", Attribute, OP_USEBEFORE }, 343{ ".USEBEFORE", Attribute, OP_USEBEFORE },
344{ ".WAIT", Wait, 0 }, 344{ ".WAIT", Wait, 0 },
345}; 345};
346 346
347//////////////////////////////////////////////////////////// 347////////////////////////////////////////////////////////////
348// local functions 348// local functions
349 349
350static int ParseIsEscaped(const char *, const char *); 350static int ParseIsEscaped(const char *, const char *);
351static void ParseErrorInternal(const char *, size_t, int, const char *, ...) 351static void ParseErrorInternal(const char *, size_t, int, const char *, ...)
352 MAKE_ATTR_PRINTFLIKE(4,5); 352 MAKE_ATTR_PRINTFLIKE(4,5);
353static void ParseVErrorInternal(FILE *, const char *, size_t, int, const char *, va_list) 353static void ParseVErrorInternal(FILE *, const char *, size_t, int, const char *, va_list)
354 MAKE_ATTR_PRINTFLIKE(5, 0); 354 MAKE_ATTR_PRINTFLIKE(5, 0);
355static int ParseFindKeyword(const char *); 355static int ParseFindKeyword(const char *);
356static int ParseLinkSrc(void *, void *); 356static int ParseLinkSrc(void *, void *);
357static int ParseDoOp(void *, void *); 357static int ParseDoOp(void *, void *);
358static void ParseDoSrc(int, const char *); 358static void ParseDoSrc(int, const char *);
359static int ParseFindMain(void *, void *); 359static int ParseFindMain(void *, void *);
360static int ParseAddDir(void *, void *); 360static int ParseAddDir(void *, void *);
361static int ParseClearPath(void *, void *); 361static int ParseClearPath(void *, void *);
362static void ParseDoDependency(char *); 362static void ParseDoDependency(char *);
363static int ParseAddCmd(void *, void *); 363static int ParseAddCmd(void *, void *);
364static void ParseHasCommands(void *); 364static void ParseHasCommands(void *);
365static void ParseDoInclude(char *); 365static void ParseDoInclude(char *);
366static void ParseSetParseFile(const char *); 366static void ParseSetParseFile(const char *);
367static void ParseSetIncludedFile(void); 367static void ParseSetIncludedFile(void);
368#ifdef GMAKEEXPORT 368#ifdef GMAKEEXPORT
369static void ParseGmakeExport(char *); 369static void ParseGmakeExport(char *);
370#endif 370#endif
371static int ParseEOF(void); 371static int ParseEOF(void);
372static char *ParseReadLine(void); 372static char *ParseReadLine(void);
373static void ParseFinishLine(void); 373static void ParseFinishLine(void);
374static void ParseMark(GNode *); 374static void ParseMark(GNode *);
375 375
376//////////////////////////////////////////////////////////// 376////////////////////////////////////////////////////////////
377// file loader 377// file loader
378 378
379struct loadedfile { 379struct loadedfile {
380 const char *path; /* name, for error reports */ 380 const char *path; /* name, for error reports */
381 char *buf; /* contents buffer */ 381 char *buf; /* contents buffer */
382 size_t len; /* length of contents */ 382 size_t len; /* length of contents */
383 size_t maplen; /* length of mmap area, or 0 */ 383 size_t maplen; /* length of mmap area, or 0 */
384 Boolean used; /* XXX: have we used the data yet */ 384 Boolean used; /* XXX: have we used the data yet */
385}; 385};
386 386
387/* 387/*
388 * Constructor/destructor for loadedfile 388 * Constructor/destructor for loadedfile
389 */ 389 */
390static struct loadedfile * 390static struct loadedfile *
391loadedfile_create(const char *path) 391loadedfile_create(const char *path)
392{ 392{
393 struct loadedfile *lf; 393 struct loadedfile *lf;
394 394
395 lf = bmake_malloc(sizeof(*lf)); 395 lf = bmake_malloc(sizeof(*lf));
396 lf->path = (path == NULL ? "(stdin)" : path); 396 lf->path = (path == NULL ? "(stdin)" : path);
397 lf->buf = NULL; 397 lf->buf = NULL;
398 lf->len = 0; 398 lf->len = 0;
399 lf->maplen = 0; 399 lf->maplen = 0;
400 lf->used = FALSE; 400 lf->used = FALSE;
401 return lf; 401 return lf;
402} 402}
403 403
404static void 404static void
405loadedfile_destroy(struct loadedfile *lf) 405loadedfile_destroy(struct loadedfile *lf)
406{ 406{
407 if (lf->buf != NULL) { 407 if (lf->buf != NULL) {
408 if (lf->maplen > 0) { 408 if (lf->maplen > 0) {
409 munmap(lf->buf, lf->maplen); 409 munmap(lf->buf, lf->maplen);
410 } else { 410 } else {
411 free(lf->buf); 411 free(lf->buf);
412 } 412 }
413 } 413 }
414 free(lf); 414 free(lf);
415} 415}
416 416
417/* 417/*
418 * nextbuf() operation for loadedfile, as needed by the weird and twisted 418 * nextbuf() operation for loadedfile, as needed by the weird and twisted
419 * logic below. Once that's cleaned up, we can get rid of lf->used... 419 * logic below. Once that's cleaned up, we can get rid of lf->used...
420 */ 420 */
421static char * 421static char *
422loadedfile_nextbuf(void *x, size_t *len) 422loadedfile_nextbuf(void *x, size_t *len)
423{ 423{
424 struct loadedfile *lf = x; 424 struct loadedfile *lf = x;
425 425
426 if (lf->used) { 426 if (lf->used) {
427 return NULL; 427 return NULL;
428 } 428 }
429 lf->used = TRUE; 429 lf->used = TRUE;
430 *len = lf->len; 430 *len = lf->len;
431 return lf->buf; 431 return lf->buf;
432} 432}
433 433
434/* 434/*
435 * Try to get the size of a file. 435 * Try to get the size of a file.
436 */ 436 */
437static ReturnStatus 437static ReturnStatus
438load_getsize(int fd, size_t *ret) 438load_getsize(int fd, size_t *ret)
439{ 439{
440 struct stat st; 440 struct stat st;
441 441
442 if (fstat(fd, &st) < 0) { 442 if (fstat(fd, &st) < 0) {
443 return FAILURE; 443 return FAILURE;
444 } 444 }
445 445
446 if (!S_ISREG(st.st_mode)) { 446 if (!S_ISREG(st.st_mode)) {
447 return FAILURE; 447 return FAILURE;
448 } 448 }
449 449
450 /* 450 /*
451 * st_size is an off_t, which is 64 bits signed; *ret is 451 * st_size is an off_t, which is 64 bits signed; *ret is
452 * size_t, which might be 32 bits unsigned or 64 bits 452 * size_t, which might be 32 bits unsigned or 64 bits
453 * unsigned. Rather than being elaborate, just punt on 453 * unsigned. Rather than being elaborate, just punt on
454 * files that are more than 2^31 bytes. We should never 454 * files that are more than 2^31 bytes. We should never
455 * see a makefile that size in practice... 455 * see a makefile that size in practice...
456 * 456 *
457 * While we're at it reject negative sizes too, just in case. 457 * While we're at it reject negative sizes too, just in case.
458 */ 458 */
459 if (st.st_size < 0 || st.st_size > 0x7fffffff) { 459 if (st.st_size < 0 || st.st_size > 0x7fffffff) {
460 return FAILURE; 460 return FAILURE;
461 } 461 }
462 462
463 *ret = (size_t) st.st_size; 463 *ret = (size_t) st.st_size;
464 return SUCCESS; 464 return SUCCESS;
465} 465}
466 466
467/* 467/*
468 * Read in a file. 468 * Read in a file.
469 * 469 *
470 * Until the path search logic can be moved under here instead of 470 * Until the path search logic can be moved under here instead of
471 * being in the caller in another source file, we need to have the fd 471 * being in the caller in another source file, we need to have the fd
472 * passed in already open. Bleh. 472 * passed in already open. Bleh.
473 * 473 *
474 * If the path is NULL use stdin and (to insure against fd leaks) 474 * If the path is NULL use stdin and (to insure against fd leaks)
475 * assert that the caller passed in -1. 475 * assert that the caller passed in -1.
476 */ 476 */
477static struct loadedfile * 477static struct loadedfile *
478loadfile(const char *path, int fd) 478loadfile(const char *path, int fd)
479{ 479{
480 struct loadedfile *lf; 480 struct loadedfile *lf;
481 static long pagesize = 0; 481 static long pagesize = 0;
482 ssize_t result; 482 ssize_t result;
483 size_t bufpos; 483 size_t bufpos;
484 484
485 lf = loadedfile_create(path); 485 lf = loadedfile_create(path);
486 486
487 if (path == NULL) { 487 if (path == NULL) {
488 assert(fd == -1); 488 assert(fd == -1);
489 fd = STDIN_FILENO; 489 fd = STDIN_FILENO;
490 } else { 490 } else {
491#if 0 /* notyet */ 491#if 0 /* notyet */
492 fd = open(path, O_RDONLY); 492 fd = open(path, O_RDONLY);
493 if (fd < 0) { 493 if (fd < 0) {
494 ... 494 ...
495 Error("%s: %s", path, strerror(errno)); 495 Error("%s: %s", path, strerror(errno));
496 exit(1); 496 exit(1);
497 } 497 }
498#endif 498#endif
499 } 499 }
500 500
501 if (load_getsize(fd, &lf->len) == SUCCESS) { 501 if (load_getsize(fd, &lf->len) == SUCCESS) {
502 /* found a size, try mmap */ 502 /* found a size, try mmap */
503 if (pagesize == 0) 503 if (pagesize == 0)
504 pagesize = sysconf(_SC_PAGESIZE); 504 pagesize = sysconf(_SC_PAGESIZE);
505 if (pagesize <= 0) { 505 if (pagesize <= 0) {
506 pagesize = 0x1000; 506 pagesize = 0x1000;
507 } 507 }
508 /* round size up to a page */ 508 /* round size up to a page */
509 lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize); 509 lf->maplen = pagesize * ((lf->len + pagesize - 1)/pagesize);
510 510
511 /* 511 /*
512 * XXX hack for dealing with empty files; remove when 512 * XXX hack for dealing with empty files; remove when
513 * we're no longer limited by interfacing to the old 513 * we're no longer limited by interfacing to the old
514 * logic elsewhere in this file. 514 * logic elsewhere in this file.
515 */ 515 */
516 if (lf->maplen == 0) { 516 if (lf->maplen == 0) {
517 lf->maplen = pagesize; 517 lf->maplen = pagesize;
518 } 518 }
519 519
520 /* 520 /*
521 * FUTURE: remove PROT_WRITE when the parser no longer 521 * FUTURE: remove PROT_WRITE when the parser no longer
522 * needs to scribble on the input. 522 * needs to scribble on the input.
523 */ 523 */
524 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE, 524 lf->buf = mmap(NULL, lf->maplen, PROT_READ|PROT_WRITE,
525 MAP_FILE|MAP_COPY, fd, 0); 525 MAP_FILE|MAP_COPY, fd, 0);
526 if (lf->buf != MAP_FAILED) { 526 if (lf->buf != MAP_FAILED) {
527 /* succeeded */ 527 /* succeeded */
528 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') { 528 if (lf->len == lf->maplen && lf->buf[lf->len - 1] != '\n') {
529 char *b = bmake_malloc(lf->len + 1); 529 char *b = bmake_malloc(lf->len + 1);
530 b[lf->len] = '\n'; 530 b[lf->len] = '\n';
531 memcpy(b, lf->buf, lf->len++); 531 memcpy(b, lf->buf, lf->len++);
532 munmap(lf->buf, lf->maplen); 532 munmap(lf->buf, lf->maplen);
533 lf->maplen = 0; 533 lf->maplen = 0;
534 lf->buf = b; 534 lf->buf = b;
535 } 535 }
536 goto done; 536 goto done;
537 } 537 }
538 } 538 }
539 539
540 /* cannot mmap; load the traditional way */ 540 /* cannot mmap; load the traditional way */
541 541
542 lf->maplen = 0; 542 lf->maplen = 0;
543 lf->len = 1024; 543 lf->len = 1024;
544 lf->buf = bmake_malloc(lf->len); 544 lf->buf = bmake_malloc(lf->len);
545 545
546 bufpos = 0; 546 bufpos = 0;
547 while (1) { 547 while (1) {
548 assert(bufpos <= lf->len); 548 assert(bufpos <= lf->len);
549 if (bufpos == lf->len) { 549 if (bufpos == lf->len) {
550 if (lf->len > SIZE_MAX/2) { 550 if (lf->len > SIZE_MAX/2) {
551 errno = EFBIG; 551 errno = EFBIG;
552 Error("%s: file too large", path); 552 Error("%s: file too large", path);
553 exit(1); 553 exit(1);
554 } 554 }
555 lf->len *= 2; 555 lf->len *= 2;
556 lf->buf = bmake_realloc(lf->buf, lf->len); 556 lf->buf = bmake_realloc(lf->buf, lf->len);
557 } 557 }
558 assert(bufpos < lf->len); 558 assert(bufpos < lf->len);
559 result = read(fd, lf->buf + bufpos, lf->len - bufpos); 559 result = read(fd, lf->buf + bufpos, lf->len - bufpos);
560 if (result < 0) { 560 if (result < 0) {
561 Error("%s: read error: %s", path, strerror(errno)); 561 Error("%s: read error: %s", path, strerror(errno));
562 exit(1); 562 exit(1);
563 } 563 }
564 if (result == 0) { 564 if (result == 0) {
565 break; 565 break;
566 } 566 }
567 bufpos += result; 567 bufpos += result;
568 } 568 }
569 assert(bufpos <= lf->len); 569 assert(bufpos <= lf->len);
570 lf->len = bufpos; 570 lf->len = bufpos;
571 571
572 /* truncate malloc region to actual length (maybe not useful) */ 572 /* truncate malloc region to actual length (maybe not useful) */
573 if (lf->len > 0) { 573 if (lf->len > 0) {
574 /* as for mmap case, ensure trailing \n */ 574 /* as for mmap case, ensure trailing \n */
575 if (lf->buf[lf->len - 1] != '\n') 575 if (lf->buf[lf->len - 1] != '\n')
576 lf->len++; 576 lf->len++;
577 lf->buf = bmake_realloc(lf->buf, lf->len); 577 lf->buf = bmake_realloc(lf->buf, lf->len);
578 lf->buf[lf->len - 1] = '\n'; 578 lf->buf[lf->len - 1] = '\n';
579 } 579 }
580 580
581done: 581done:
582 if (path != NULL) { 582 if (path != NULL) {
583 close(fd); 583 close(fd);
584 } 584 }
585 return lf; 585 return lf;
586} 586}
587 587
588//////////////////////////////////////////////////////////// 588////////////////////////////////////////////////////////////
589// old code 589// old code
590 590
591/*- 591/*-
592 *---------------------------------------------------------------------- 592 *----------------------------------------------------------------------
593 * ParseIsEscaped -- 593 * ParseIsEscaped --
594 * Check if the current character is escaped on the current line 594 * Check if the current character is escaped on the current line
595 * 595 *
596 * Results: 596 * Results:
597 * 0 if the character is not backslash escaped, 1 otherwise 597 * 0 if the character is not backslash escaped, 1 otherwise
598 * 598 *
599 * Side Effects: 599 * Side Effects:
600 * None 600 * None
601 *---------------------------------------------------------------------- 601 *----------------------------------------------------------------------
602 */ 602 */
603static int 603static int
604ParseIsEscaped(const char *line, const char *c) 604ParseIsEscaped(const char *line, const char *c)
605{ 605{
606 int active = 0; 606 int active = 0;
607 for (;;) { 607 for (;;) {
608 if (line == c) 608 if (line == c)
609 return active; 609 return active;
610 if (*--c != '\\') 610 if (*--c != '\\')
611 return active; 611 return active;
612 active = !active; 612 active = !active;
613 } 613 }
614} 614}
615 615
616/*- 616/*-
617 *---------------------------------------------------------------------- 617 *----------------------------------------------------------------------
618 * ParseFindKeyword -- 618 * ParseFindKeyword --
619 * Look in the table of keywords for one matching the given string. 619 * Look in the table of keywords for one matching the given string.
620 * 620 *
621 * Input: 621 * Input:
622 * str String to find 622 * str String to find
623 * 623 *
624 * Results: 624 * Results:
625 * The index of the keyword, or -1 if it isn't there. 625 * The index of the keyword, or -1 if it isn't there.
626 * 626 *
627 * Side Effects: 627 * Side Effects:
628 * None 628 * None
629 *---------------------------------------------------------------------- 629 *----------------------------------------------------------------------
630 */ 630 */
631static int 631static int
632ParseFindKeyword(const char *str) 632ParseFindKeyword(const char *str)
633{ 633{
634 int start, end, cur; 634 int start, end, cur;
635 int diff; 635 int diff;
636 636
637 start = 0; 637 start = 0;
638 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1; 638 end = (sizeof(parseKeywords)/sizeof(parseKeywords[0])) - 1;
639 639
640 do { 640 do {
641 cur = start + ((end - start) / 2); 641 cur = start + ((end - start) / 2);
642 diff = strcmp(str, parseKeywords[cur].name); 642 diff = strcmp(str, parseKeywords[cur].name);
643 643
644 if (diff == 0) { 644 if (diff == 0) {
645 return cur; 645 return cur;
646 } else if (diff < 0) { 646 } else if (diff < 0) {
647 end = cur - 1; 647 end = cur - 1;
648 } else { 648 } else {
649 start = cur + 1; 649 start = cur + 1;
650 } 650 }
651 } while (start <= end); 651 } while (start <= end);
652 return -1; 652 return -1;
653} 653}
654 654
655/*- 655/*-
656 * ParseVErrorInternal -- 656 * ParseVErrorInternal --
657 * Error message abort function for parsing. Prints out the context 657 * Error message abort function for parsing. Prints out the context
658 * of the error (line number and file) as well as the message with 658 * of the error (line number and file) as well as the message with
659 * two optional arguments. 659 * two optional arguments.
660 * 660 *
661 * Results: 661 * Results:
662 * None 662 * None
663 * 663 *
664 * Side Effects: 664 * Side Effects:
665 * "fatals" is incremented if the level is PARSE_FATAL. 665 * "fatals" is incremented if the level is PARSE_FATAL.
666 */ 666 */
667/* VARARGS */ 667/* VARARGS */
668static void 668static void
669ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type, 669ParseVErrorInternal(FILE *f, const char *cfname, size_t clineno, int type,
670 const char *fmt, va_list ap) 670 const char *fmt, va_list ap)
671{ 671{
672 static Boolean fatal_warning_error_printed = FALSE; 672 static Boolean fatal_warning_error_printed = FALSE;
673 char dirbuf[MAXPATHLEN+1]; 673 char dirbuf[MAXPATHLEN+1];
674 674
675 (void)fprintf(f, "%s: ", progname); 675 (void)fprintf(f, "%s: ", progname);
676 676
677 if (cfname != NULL) { 677 if (cfname != NULL) {
678 (void)fprintf(f, "\""); 678 (void)fprintf(f, "\"");
679 if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) { 679 if (*cfname != '/' && strcmp(cfname, "(stdin)") != 0) {
680 char *cp, *cp2; 680 char *cp, *cp2;
681 const char *dir, *fname; 681 const char *dir, *fname;
682 682
683 /* 683 /*
684 * Nothing is more annoying than not knowing 684 * Nothing is more annoying than not knowing
685 * which Makefile is the culprit; we try ${.PARSEDIR} 685 * which Makefile is the culprit; we try ${.PARSEDIR}
686 * and apply realpath(3) if not absolute. 686 * and apply realpath(3) if not absolute.
687 */ 687 */
688 dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp); 688 dir = Var_Value(".PARSEDIR", VAR_GLOBAL, &cp);
689 if (dir == NULL) 689 if (dir == NULL)
690 dir = "."; 690 dir = ".";
691 if (*dir != '/') { 691 if (*dir != '/') {
692 dir = realpath(dir, dirbuf); 692 dir = realpath(dir, dirbuf);
693 } 693 }
694 fname = Var_Value(".PARSEFILE", VAR_GLOBAL, &cp2); 694 fname = Var_Value(".PARSEFILE", VAR_GLOBAL, &cp2);
695 if (fname == NULL) { 695 if (fname == NULL) {
696 if ((fname = strrchr(cfname, '/'))) 696 if ((fname = strrchr(cfname, '/')))
697 fname++; 697 fname++;
698 else 698 else
699 fname = cfname; 699 fname = cfname;
700 } 700 }
701 (void)fprintf(f, "%s/%s", dir, fname); 701 (void)fprintf(f, "%s/%s", dir, fname);
702 free(cp2); 702 free(cp2);
703 free(cp); 703 free(cp);
704 } else 704 } else
705 (void)fprintf(f, "%s", cfname); 705 (void)fprintf(f, "%s", cfname);
706 706
707 (void)fprintf(f, "\" line %d: ", (int)clineno); 707 (void)fprintf(f, "\" line %d: ", (int)clineno);
708 } 708 }
709 if (type == PARSE_WARNING) 709 if (type == PARSE_WARNING)
710 (void)fprintf(f, "warning: "); 710 (void)fprintf(f, "warning: ");
711 (void)vfprintf(f, fmt, ap); 711 (void)vfprintf(f, fmt, ap);
712 (void)fprintf(f, "\n"); 712 (void)fprintf(f, "\n");
713 (void)fflush(f); 713 (void)fflush(f);
714 if (type == PARSE_INFO) 714 if (type == PARSE_INFO)
715 return; 715 return;
716 if (type == PARSE_FATAL || parseWarnFatal) 716 if (type == PARSE_FATAL || parseWarnFatal)
717 fatals += 1; 717 fatals += 1;
718 if (parseWarnFatal && !fatal_warning_error_printed) { 718 if (parseWarnFatal && !fatal_warning_error_printed) {
719 Error("parsing warnings being treated as errors"); 719 Error("parsing warnings being treated as errors");
720 fatal_warning_error_printed = TRUE; 720 fatal_warning_error_printed = TRUE;
721 } 721 }
722} 722}
723 723
724/*- 724/*-
725 * ParseErrorInternal -- 725 * ParseErrorInternal --
726 * Error function 726 * Error function
727 * 727 *
728 * Results: 728 * Results:
729 * None 729 * None
730 * 730 *
731 * Side Effects: 731 * Side Effects:
732 * None 732 * None
733 */ 733 */
734/* VARARGS */ 734/* VARARGS */
735static void 735static void
736ParseErrorInternal(const char *cfname, size_t clineno, int type, 736ParseErrorInternal(const char *cfname, size_t clineno, int type,
737 const char *fmt, ...) 737 const char *fmt, ...)
738{ 738{
739 va_list ap; 739 va_list ap;
740 740
741 va_start(ap, fmt); 741 va_start(ap, fmt);
742 (void)fflush(stdout); 742 (void)fflush(stdout);
743 ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap); 743 ParseVErrorInternal(stderr, cfname, clineno, type, fmt, ap);
744 va_end(ap); 744 va_end(ap);
745 745
746 if (debug_file != stderr && debug_file != stdout) { 746 if (debug_file != stderr && debug_file != stdout) {
747 va_start(ap, fmt); 747 va_start(ap, fmt);
748 ParseVErrorInternal(debug_file, cfname, clineno, type, fmt, ap); 748 ParseVErrorInternal(debug_file, cfname, clineno, type, fmt, ap);
749 va_end(ap); 749 va_end(ap);
750 } 750 }
751} 751}
752 752
753/*- 753/*-
754 * Parse_Error -- 754 * Parse_Error --
755 * External interface to ParseErrorInternal; uses the default filename 755 * External interface to ParseErrorInternal; uses the default filename
756 * Line number. 756 * Line number.
757 * 757 *
758 * Results: 758 * Results:
759 * None 759 * None
760 * 760 *
761 * Side Effects: 761 * Side Effects:
762 * None 762 * None
763 */ 763 */
764/* VARARGS */ 764/* VARARGS */
765void 765void
766Parse_Error(int type, const char *fmt, ...) 766Parse_Error(int type, const char *fmt, ...)
767{ 767{
768 va_list ap; 768 va_list ap;
769 const char *fname; 769 const char *fname;
770 size_t lineno; 770 size_t lineno;
771 771
772 if (curFile == NULL) { 772 if (curFile == NULL) {
773 fname = NULL; 773 fname = NULL;
774 lineno = 0; 774 lineno = 0;
775 } else { 775 } else {
776 fname = curFile->fname; 776 fname = curFile->fname;
777 lineno = curFile->lineno; 777 lineno = curFile->lineno;
778 } 778 }
779 779
780 va_start(ap, fmt); 780 va_start(ap, fmt);
781 (void)fflush(stdout); 781 (void)fflush(stdout);
782 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap); 782 ParseVErrorInternal(stderr, fname, lineno, type, fmt, ap);
783 va_end(ap); 783 va_end(ap);
784 784
785 if (debug_file != stderr && debug_file != stdout) { 785 if (debug_file != stderr && debug_file != stdout) {
786 va_start(ap, fmt); 786 va_start(ap, fmt);
787 ParseVErrorInternal(debug_file, fname, lineno, type, fmt, ap); 787 ParseVErrorInternal(debug_file, fname, lineno, type, fmt, ap);
788 va_end(ap); 788 va_end(ap);
789 } 789 }
790} 790}
791 791
792 792
793/* 793/*
794 * ParseMessage 794 * ParseMessage
795 * Parse a .info .warning or .error directive 795 * Parse a .info .warning or .error directive
796 * 796 *
797 * The input is the line minus the ".". We substitute 797 * The input is the line minus the ".". We substitute
798 * variables, print the message and exit(1) (for .error) or just print 798 * variables, print the message and exit(1) (for .error) or just print
799 * a warning if the directive is malformed. 799 * a warning if the directive is malformed.
800 */ 800 */
801static Boolean 801static Boolean
802ParseMessage(char *line) 802ParseMessage(char *line)
803{ 803{
804 int mtype; 804 int mtype;
805 805
806 switch(*line) { 806 switch(*line) {
807 case 'i': 807 case 'i':
808 mtype = PARSE_INFO; 808 mtype = PARSE_INFO;
809 break; 809 break;
810 case 'w': 810 case 'w':
811 mtype = PARSE_WARNING; 811 mtype = PARSE_WARNING;
812 break; 812 break;
813 case 'e': 813 case 'e':
814 mtype = PARSE_FATAL; 814 mtype = PARSE_FATAL;
815 break; 815 break;
816 default: 816 default:
817 Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line); 817 Parse_Error(PARSE_WARNING, "invalid syntax: \".%s\"", line);
818 return FALSE; 818 return FALSE;
819 } 819 }
820 820
821 while (isalpha((unsigned char)*line)) 821 while (isalpha((unsigned char)*line))
822 line++; 822 line++;
823 if (!isspace((unsigned char)*line)) 823 if (!isspace((unsigned char)*line))
824 return FALSE; /* not for us */ 824 return FALSE; /* not for us */
825 while (isspace((unsigned char)*line)) 825 while (isspace((unsigned char)*line))
826 line++; 826 line++;
827 827
828 line = Var_Subst(line, VAR_CMD, VARE_WANTRES); 828 line = Var_Subst(line, VAR_CMD, VARE_WANTRES);
829 Parse_Error(mtype, "%s", line); 829 Parse_Error(mtype, "%s", line);
830 free(line); 830 free(line);
831 831
832 if (mtype == PARSE_FATAL) { 832 if (mtype == PARSE_FATAL) {
833 /* Terminate immediately. */ 833 /* Terminate immediately. */
834 exit(1); 834 exit(1);
835 } 835 }
836 return TRUE; 836 return TRUE;
837} 837}
838 838
839/*- 839/*-
840 *--------------------------------------------------------------------- 840 *---------------------------------------------------------------------
841 * ParseLinkSrc -- 841 * ParseLinkSrc --
842 * Link the parent node to its new child. Used in a Lst_ForEach by 842 * Link the parent node to its new child. Used in a Lst_ForEach by
843 * ParseDoDependency. If the specType isn't 'Not', the parent 843 * ParseDoDependency. If the specType isn't 'Not', the parent
844 * isn't linked as a parent of the child. 844 * isn't linked as a parent of the child.
845 * 845 *
846 * Input: 846 * Input:
847 * pgnp The parent node 847 * pgnp The parent node
848 * cgpn The child node 848 * cgpn The child node
849 * 849 *
850 * Results: 850 * Results:
851 * Always = 0 851 * Always = 0
852 * 852 *
853 * Side Effects: 853 * Side Effects:
854 * New elements are added to the parents list of cgn and the 854 * New elements are added to the parents list of cgn and the
855 * children list of cgn. the unmade field of pgn is updated 855 * children list of cgn. the unmade field of pgn is updated
856 * to reflect the additional child. 856 * to reflect the additional child.
857 *--------------------------------------------------------------------- 857 *---------------------------------------------------------------------
858 */ 858 */
859static int 859static int
860ParseLinkSrc(void *pgnp, void *cgnp) 860ParseLinkSrc(void *pgnp, void *cgnp)
861{ 861{
862 GNode *pgn = (GNode *)pgnp; 862 GNode *pgn = (GNode *)pgnp;
863 GNode *cgn = (GNode *)cgnp; 863 GNode *cgn = (GNode *)cgnp;
864 864
865 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (pgn->cohorts)) 865 if ((pgn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (pgn->cohorts))
866 pgn = (GNode *)Lst_Datum(Lst_Last(pgn->cohorts)); 866 pgn = (GNode *)Lst_Datum(Lst_Last(pgn->cohorts));
867 (void)Lst_AtEnd(pgn->children, cgn); 867 (void)Lst_AtEnd(pgn->children, cgn);
868 if (specType == Not) 868 if (specType == Not)
869 (void)Lst_AtEnd(cgn->parents, pgn); 869 (void)Lst_AtEnd(cgn->parents, pgn);
870 pgn->unmade += 1; 870 pgn->unmade += 1;
871 if (DEBUG(PARSE)) { 871 if (DEBUG(PARSE)) {
872 fprintf(debug_file, "# %s: added child %s - %s\n", __func__, 872 fprintf(debug_file, "# %s: added child %s - %s\n", __func__,
873 pgn->name, cgn->name); 873 pgn->name, cgn->name);
874 Targ_PrintNode(pgn, 0); 874 Targ_PrintNode(pgn, 0);
875 Targ_PrintNode(cgn, 0); 875 Targ_PrintNode(cgn, 0);
876 } 876 }
877 return 0; 877 return 0;
878} 878}
879 879
880/*- 880/*-
881 *--------------------------------------------------------------------- 881 *---------------------------------------------------------------------
882 * ParseDoOp -- 882 * ParseDoOp --
883 * Apply the parsed operator to the given target node. Used in a 883 * Apply the parsed operator to the given target node. Used in a
884 * Lst_ForEach call by ParseDoDependency once all targets have 884 * Lst_ForEach call by ParseDoDependency once all targets have
885 * been found and their operator parsed. If the previous and new 885 * been found and their operator parsed. If the previous and new
886 * operators are incompatible, a major error is taken. 886 * operators are incompatible, a major error is taken.
887 * 887 *
888 * Input: 888 * Input:
889 * gnp The node to which the operator is to be applied 889 * gnp The node to which the operator is to be applied
890 * opp The operator to apply 890 * opp The operator to apply
891 * 891 *
892 * Results: 892 * Results:
893 * Always 0 893 * Always 0
894 * 894 *
895 * Side Effects: 895 * Side Effects:
896 * The type field of the node is altered to reflect any new bits in 896 * The type field of the node is altered to reflect any new bits in
897 * the op. 897 * the op.
898 *--------------------------------------------------------------------- 898 *---------------------------------------------------------------------
899 */ 899 */
900static int 900static int
901ParseDoOp(void *gnp, void *opp) 901ParseDoOp(void *gnp, void *opp)
902{ 902{
903 GNode *gn = (GNode *)gnp; 903 GNode *gn = (GNode *)gnp;
904 int op = *(int *)opp; 904 int op = *(int *)opp;
905 /* 905 /*
906 * If the dependency mask of the operator and the node don't match and 906 * If the dependency mask of the operator and the node don't match and
907 * the node has actually had an operator applied to it before, and 907 * the node has actually had an operator applied to it before, and
908 * the operator actually has some dependency information in it, complain. 908 * the operator actually has some dependency information in it, complain.
909 */ 909 */
910 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) && 910 if (((op & OP_OPMASK) != (gn->type & OP_OPMASK)) &&
911 !OP_NOP(gn->type) && !OP_NOP(op)) 911 !OP_NOP(gn->type) && !OP_NOP(op))
912 { 912 {
913 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name); 913 Parse_Error(PARSE_FATAL, "Inconsistent operator for %s", gn->name);
914 return 1; 914 return 1;
915 } 915 }
916 916
917 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) { 917 if ((op == OP_DOUBLEDEP) && ((gn->type & OP_OPMASK) == OP_DOUBLEDEP)) {
918 /* 918 /*
919 * If the node was the object of a :: operator, we need to create a 919 * If the node was the object of a :: operator, we need to create a
920 * new instance of it for the children and commands on this dependency 920 * new instance of it for the children and commands on this dependency
921 * line. The new instance is placed on the 'cohorts' list of the 921 * line. The new instance is placed on the 'cohorts' list of the
922 * initial one (note the initial one is not on its own cohorts list) 922 * initial one (note the initial one is not on its own cohorts list)
923 * and the new instance is linked to all parents of the initial 923 * and the new instance is linked to all parents of the initial
924 * instance. 924 * instance.
925 */ 925 */
926 GNode *cohort; 926 GNode *cohort;
927 927
928 /* 928 /*
929 * Propagate copied bits to the initial node. They'll be propagated 929 * Propagate copied bits to the initial node. They'll be propagated
930 * back to the rest of the cohorts later. 930 * back to the rest of the cohorts later.
931 */ 931 */
932 gn->type |= op & ~OP_OPMASK; 932 gn->type |= op & ~OP_OPMASK;
933 933
934 cohort = Targ_FindNode(gn->name, TARG_NOHASH); 934 cohort = Targ_FindNode(gn->name, TARG_NOHASH);
935 if (doing_depend) 935 if (doing_depend)
936 ParseMark(cohort); 936 ParseMark(cohort);
937 /* 937 /*
938 * Make the cohort invisible as well to avoid duplicating it into 938 * Make the cohort invisible as well to avoid duplicating it into
939 * other variables. True, parents of this target won't tend to do 939 * other variables. True, parents of this target won't tend to do
940 * anything with their local variables, but better safe than 940 * anything with their local variables, but better safe than
941 * sorry. (I think this is pointless now, since the relevant list 941 * sorry. (I think this is pointless now, since the relevant list
942 * traversals will no longer see this node anyway. -mycroft) 942 * traversals will no longer see this node anyway. -mycroft)
943 */ 943 */
944 cohort->type = op | OP_INVISIBLE; 944 cohort->type = op | OP_INVISIBLE;
945 (void)Lst_AtEnd(gn->cohorts, cohort); 945 (void)Lst_AtEnd(gn->cohorts, cohort);
946 cohort->centurion = gn; 946 cohort->centurion = gn;
947 gn->unmade_cohorts += 1; 947 gn->unmade_cohorts += 1;
948 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d", 948 snprintf(cohort->cohort_num, sizeof cohort->cohort_num, "#%d",
949 gn->unmade_cohorts); 949 gn->unmade_cohorts);
950 } else { 950 } else {
951 /* 951 /*
952 * We don't want to nuke any previous flags (whatever they were) so we 952 * We don't want to nuke any previous flags (whatever they were) so we
953 * just OR the new operator into the old 953 * just OR the new operator into the old
954 */ 954 */
955 gn->type |= op; 955 gn->type |= op;
956 } 956 }
957 957
958 return 0; 958 return 0;
959} 959}
960 960
961/*- 961/*-
962 *--------------------------------------------------------------------- 962 *---------------------------------------------------------------------
963 * ParseDoSrc -- 963 * ParseDoSrc --
964 * Given the name of a source, figure out if it is an attribute 964 * Given the name of a source, figure out if it is an attribute
965 * and apply it to the targets if it is. Else decide if there is 965 * and apply it to the targets if it is. Else decide if there is
966 * some attribute which should be applied *to* the source because 966 * some attribute which should be applied *to* the source because
967 * of some special target and apply it if so. Otherwise, make the 967 * of some special target and apply it if so. Otherwise, make the
968 * source be a child of the targets in the list 'targets' 968 * source be a child of the targets in the list 'targets'
969 * 969 *
970 * Input: 970 * Input:
971 * tOp operator (if any) from special targets 971 * tOp operator (if any) from special targets
972 * src name of the source to handle 972 * src name of the source to handle
973 * 973 *
974 * Results: 974 * Results:
975 * None 975 * None
976 * 976 *
977 * Side Effects: 977 * Side Effects:
978 * Operator bits may be added to the list of targets or to the source. 978 * Operator bits may be added to the list of targets or to the source.
979 * The targets may have a new source added to their lists of children. 979 * The targets may have a new source added to their lists of children.
980 *--------------------------------------------------------------------- 980 *---------------------------------------------------------------------
981 */ 981 */
982static void 982static void
983ParseDoSrc(int tOp, const char *src) 983ParseDoSrc(int tOp, const char *src)
984{ 984{
985 GNode *gn = NULL; 985 GNode *gn = NULL;
986 static int wait_number = 0; 986 static int wait_number = 0;
987 char wait_src[16]; 987 char wait_src[16];
988 988
989 if (*src == '.' && isupper ((unsigned char)src[1])) { 989 if (*src == '.' && isupper ((unsigned char)src[1])) {
990 int keywd = ParseFindKeyword(src); 990 int keywd = ParseFindKeyword(src);
991 if (keywd != -1) { 991 if (keywd != -1) {
992 int op = parseKeywords[keywd].op; 992 int op = parseKeywords[keywd].op;
993 if (op != 0) { 993 if (op != 0) {
994 Lst_ForEach(targets, ParseDoOp, &op); 994 Lst_ForEach(targets, ParseDoOp, &op);
995 return; 995 return;
996 } 996 }
997 if (parseKeywords[keywd].spec == Wait) { 997 if (parseKeywords[keywd].spec == Wait) {
998 /* 998 /*
999 * We add a .WAIT node in the dependency list. 999 * We add a .WAIT node in the dependency list.
1000 * After any dynamic dependencies (and filename globbing) 1000 * After any dynamic dependencies (and filename globbing)
1001 * have happened, it is given a dependency on the each 1001 * have happened, it is given a dependency on the each
1002 * previous child back to and previous .WAIT node. 1002 * previous child back to and previous .WAIT node.
1003 * The next child won't be scheduled until the .WAIT node 1003 * The next child won't be scheduled until the .WAIT node
1004 * is built. 1004 * is built.
1005 * We give each .WAIT node a unique name (mainly for diag). 1005 * We give each .WAIT node a unique name (mainly for diag).
1006 */ 1006 */
1007 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number); 1007 snprintf(wait_src, sizeof wait_src, ".WAIT_%u", ++wait_number);
1008 gn = Targ_FindNode(wait_src, TARG_NOHASH); 1008 gn = Targ_FindNode(wait_src, TARG_NOHASH);
1009 if (doing_depend) 1009 if (doing_depend)
1010 ParseMark(gn); 1010 ParseMark(gn);
1011 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN; 1011 gn->type = OP_WAIT | OP_PHONY | OP_DEPENDS | OP_NOTMAIN;
1012 Lst_ForEach(targets, ParseLinkSrc, gn); 1012 Lst_ForEach(targets, ParseLinkSrc, gn);
1013 return; 1013 return;
1014 } 1014 }
1015 } 1015 }
1016 } 1016 }
1017 1017
1018 switch (specType) { 1018 switch (specType) {
1019 case Main: 1019 case Main:
1020 /* 1020 /*
1021 * If we have noted the existence of a .MAIN, it means we need 1021 * If we have noted the existence of a .MAIN, it means we need
1022 * to add the sources of said target to the list of things 1022 * to add the sources of said target to the list of things
1023 * to create. The string 'src' is likely to be free, so we 1023 * to create. The string 'src' is likely to be free, so we
1024 * must make a new copy of it. Note that this will only be 1024 * must make a new copy of it. Note that this will only be
1025 * invoked if the user didn't specify a target on the command 1025 * invoked if the user didn't specify a target on the command
1026 * line. This is to allow #ifmake's to succeed, or something... 1026 * line. This is to allow #ifmake's to succeed, or something...
1027 */ 1027 */
1028 (void)Lst_AtEnd(create, bmake_strdup(src)); 1028 (void)Lst_AtEnd(create, bmake_strdup(src));
1029 /* 1029 /*
1030 * Add the name to the .TARGETS variable as well, so the user can 1030 * Add the name to the .TARGETS variable as well, so the user can
1031 * employ that, if desired. 1031 * employ that, if desired.
1032 */ 1032 */
1033 Var_Append(".TARGETS", src, VAR_GLOBAL); 1033 Var_Append(".TARGETS", src, VAR_GLOBAL);
1034 return; 1034 return;
1035 1035
1036 case Order: 1036 case Order:
1037 /* 1037 /*
1038 * Create proper predecessor/successor links between the previous 1038 * Create proper predecessor/successor links between the previous
1039 * source and the current one. 1039 * source and the current one.
1040 */ 1040 */
1041 gn = Targ_FindNode(src, TARG_CREATE); 1041 gn = Targ_FindNode(src, TARG_CREATE);
1042 if (doing_depend) 1042 if (doing_depend)
1043 ParseMark(gn); 1043 ParseMark(gn);
1044 if (predecessor != NULL) { 1044 if (predecessor != NULL) {
1045 (void)Lst_AtEnd(predecessor->order_succ, gn); 1045 (void)Lst_AtEnd(predecessor->order_succ, gn);
1046 (void)Lst_AtEnd(gn->order_pred, predecessor); 1046 (void)Lst_AtEnd(gn->order_pred, predecessor);
1047 if (DEBUG(PARSE)) { 1047 if (DEBUG(PARSE)) {
1048 fprintf(debug_file, "# %s: added Order dependency %s - %s\n", 1048 fprintf(debug_file, "# %s: added Order dependency %s - %s\n",
1049 __func__, predecessor->name, gn->name); 1049 __func__, predecessor->name, gn->name);
1050 Targ_PrintNode(predecessor, 0); 1050 Targ_PrintNode(predecessor, 0);
1051 Targ_PrintNode(gn, 0); 1051 Targ_PrintNode(gn, 0);
1052 } 1052 }
1053 } 1053 }
1054 /* 1054 /*
1055 * The current source now becomes the predecessor for the next one. 1055 * The current source now becomes the predecessor for the next one.
1056 */ 1056 */
1057 predecessor = gn; 1057 predecessor = gn;
1058 break; 1058 break;
1059 1059
1060 default: 1060 default:
1061 /* 1061 /*
1062 * If the source is not an attribute, we need to find/create 1062 * If the source is not an attribute, we need to find/create
1063 * a node for it. After that we can apply any operator to it 1063 * a node for it. After that we can apply any operator to it
1064 * from a special target or link it to its parents, as 1064 * from a special target or link it to its parents, as
1065 * appropriate. 1065 * appropriate.
1066 * 1066 *
1067 * In the case of a source that was the object of a :: operator, 1067 * In the case of a source that was the object of a :: operator,
1068 * the attribute is applied to all of its instances (as kept in 1068 * the attribute is applied to all of its instances (as kept in
1069 * the 'cohorts' list of the node) or all the cohorts are linked 1069 * the 'cohorts' list of the node) or all the cohorts are linked
1070 * to all the targets. 1070 * to all the targets.
1071 */ 1071 */
1072 1072
1073 /* Find/create the 'src' node and attach to all targets */ 1073 /* Find/create the 'src' node and attach to all targets */
1074 gn = Targ_FindNode(src, TARG_CREATE); 1074 gn = Targ_FindNode(src, TARG_CREATE);
1075 if (doing_depend) 1075 if (doing_depend)
1076 ParseMark(gn); 1076 ParseMark(gn);
1077 if (tOp) { 1077 if (tOp) {
1078 gn->type |= tOp; 1078 gn->type |= tOp;
1079 } else { 1079 } else {
1080 Lst_ForEach(targets, ParseLinkSrc, gn); 1080 Lst_ForEach(targets, ParseLinkSrc, gn);
1081 } 1081 }
1082 break; 1082 break;
1083 } 1083 }
1084} 1084}
1085 1085
1086/*- 1086/*-
1087 *----------------------------------------------------------------------- 1087 *-----------------------------------------------------------------------
1088 * ParseFindMain -- 1088 * ParseFindMain --
1089 * Find a real target in the list and set it to be the main one. 1089 * Find a real target in the list and set it to be the main one.
1090 * Called by ParseDoDependency when a main target hasn't been found 1090 * Called by ParseDoDependency when a main target hasn't been found
1091 * yet. 1091 * yet.
1092 * 1092 *
1093 * Input: 1093 * Input:
1094 * gnp Node to examine 1094 * gnp Node to examine
1095 * 1095 *
1096 * Results: 1096 * Results:
1097 * 0 if main not found yet, 1 if it is. 1097 * 0 if main not found yet, 1 if it is.
1098 * 1098 *
1099 * Side Effects: 1099 * Side Effects:
1100 * mainNode is changed and Targ_SetMain is called. 1100 * mainNode is changed and Targ_SetMain is called.
1101 * 1101 *
1102 *----------------------------------------------------------------------- 1102 *-----------------------------------------------------------------------
1103 */ 1103 */
1104static int 1104static int
1105ParseFindMain(void *gnp, void *dummy MAKE_ATTR_UNUSED) 1105ParseFindMain(void *gnp, void *dummy MAKE_ATTR_UNUSED)
1106{ 1106{
1107 GNode *gn = (GNode *)gnp; 1107 GNode *gn = (GNode *)gnp;
1108 if ((gn->type & OP_NOTARGET) == 0) { 1108 if ((gn->type & OP_NOTARGET) == 0) {
1109 mainNode = gn; 1109 mainNode = gn;
1110 Targ_SetMain(gn); 1110 Targ_SetMain(gn);
1111 return 1; 1111 return 1;
1112 } else { 1112 } else {
1113 return 0; 1113 return 0;
1114 } 1114 }
1115} 1115}
1116 1116
1117/*- 1117/*-
1118 *----------------------------------------------------------------------- 1118 *-----------------------------------------------------------------------
1119 * ParseAddDir -- 1119 * ParseAddDir --
1120 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going 1120 * Front-end for Dir_AddDir to make sure Lst_ForEach keeps going
1121 * 1121 *
1122 * Results: 1122 * Results:
1123 * === 0 1123 * === 0
1124 * 1124 *
1125 * Side Effects: 1125 * Side Effects:
1126 * See Dir_AddDir. 1126 * See Dir_AddDir.
1127 * 1127 *
1128 *----------------------------------------------------------------------- 1128 *-----------------------------------------------------------------------
1129 */ 1129 */
1130static int 1130static int
1131ParseAddDir(void *path, void *name) 1131ParseAddDir(void *path, void *name)
1132{ 1132{
1133 (void)Dir_AddDir((Lst) path, (char *)name); 1133 (void)Dir_AddDir((Lst) path, (char *)name);
1134 return 0; 1134 return 0;
1135} 1135}
1136 1136
1137/*- 1137/*-
1138 *----------------------------------------------------------------------- 1138 *-----------------------------------------------------------------------
1139 * ParseClearPath -- 1139 * ParseClearPath --
1140 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going 1140 * Front-end for Dir_ClearPath to make sure Lst_ForEach keeps going
1141 * 1141 *
1142 * Results: 1142 * Results:
1143 * === 0 1143 * === 0
1144 * 1144 *
1145 * Side Effects: 1145 * Side Effects:
1146 * See Dir_ClearPath 1146 * See Dir_ClearPath
1147 * 1147 *
1148 *----------------------------------------------------------------------- 1148 *-----------------------------------------------------------------------
1149 */ 1149 */
1150static int 1150static int
1151ParseClearPath(void *path, void *dummy MAKE_ATTR_UNUSED) 1151ParseClearPath(void *path, void *dummy MAKE_ATTR_UNUSED)
1152{ 1152{
1153 Dir_ClearPath((Lst) path); 1153 Dir_ClearPath((Lst) path);
1154 return 0; 1154 return 0;
1155} 1155}
1156 1156
1157/*- 1157/*-
1158 *--------------------------------------------------------------------- 1158 *---------------------------------------------------------------------
1159 * ParseDoDependency -- 1159 * ParseDoDependency --
1160 * Parse the dependency line in line. 1160 * Parse the dependency line in line.
1161 * 1161 *
1162 * Input: 1162 * Input:
1163 * line the line to parse 1163 * line the line to parse
1164 * 1164 *
1165 * Results: 1165 * Results:
1166 * None 1166 * None
1167 * 1167 *
1168 * Side Effects: 1168 * Side Effects:
1169 * The nodes of the sources are linked as children to the nodes of the 1169 * The nodes of the sources are linked as children to the nodes of the
1170 * targets. Some nodes may be created. 1170 * targets. Some nodes may be created.
1171 * 1171 *
1172 * We parse a dependency line by first extracting words from the line and 1172 * We parse a dependency line by first extracting words from the line and
1173 * finding nodes in the list of all targets with that name. This is done 1173 * finding nodes in the list of all targets with that name. This is done
1174 * until a character is encountered which is an operator character. Currently 1174 * until a character is encountered which is an operator character. Currently
1175 * these are only ! and :. At this point the operator is parsed and the 1175 * these are only ! and :. At this point the operator is parsed and the
1176 * pointer into the line advanced until the first source is encountered. 1176 * pointer into the line advanced until the first source is encountered.
1177 * The parsed operator is applied to each node in the 'targets' list, 1177 * The parsed operator is applied to each node in the 'targets' list,
1178 * which is where the nodes found for the targets are kept, by means of 1178 * which is where the nodes found for the targets are kept, by means of
1179 * the ParseDoOp function. 1179 * the ParseDoOp function.
1180 * The sources are read in much the same way as the targets were except 1180 * The sources are read in much the same way as the targets were except
1181 * that now they are expanded using the wildcarding scheme of the C-Shell 1181 * that now they are expanded using the wildcarding scheme of the C-Shell
1182 * and all instances of the resulting words in the list of all targets 1182 * and all instances of the resulting words in the list of all targets
1183 * are found. Each of the resulting nodes is then linked to each of the 1183 * are found. Each of the resulting nodes is then linked to each of the
1184 * targets as one of its children. 1184 * targets as one of its children.
1185 * Certain targets are handled specially. These are the ones detailed 1185 * Certain targets are handled specially. These are the ones detailed
1186 * by the specType variable. 1186 * by the specType variable.
1187 * The storing of transformation rules is also taken care of here. 1187 * The storing of transformation rules is also taken care of here.
1188 * A target is recognized as a transformation rule by calling 1188 * A target is recognized as a transformation rule by calling
1189 * Suff_IsTransform. If it is a transformation rule, its node is gotten 1189 * Suff_IsTransform. If it is a transformation rule, its node is gotten
1190 * from the suffix module via Suff_AddTransform rather than the standard 1190 * from the suffix module via Suff_AddTransform rather than the standard
1191 * Targ_FindNode in the target module. 1191 * Targ_FindNode in the target module.
1192 *--------------------------------------------------------------------- 1192 *---------------------------------------------------------------------
1193 */ 1193 */
1194static void 1194static void
1195ParseDoDependency(char *line) 1195ParseDoDependency(char *line)
1196{ 1196{
1197 char *cp; /* our current position */ 1197 char *cp; /* our current position */
1198 GNode *gn = NULL; /* a general purpose temporary node */ 1198 GNode *gn = NULL; /* a general purpose temporary node */
1199 int op; /* the operator on the line */ 1199 int op; /* the operator on the line */
1200 char savec; /* a place to save a character */ 1200 char savec; /* a place to save a character */
1201 Lst paths; /* List of search paths to alter when parsing 1201 Lst paths; /* List of search paths to alter when parsing
1202 * a list of .PATH targets */ 1202 * a list of .PATH targets */
1203 int tOp; /* operator from special target */ 1203 int tOp; /* operator from special target */
1204 Lst sources; /* list of archive source names after 1204 Lst sources; /* list of archive source names after
1205 * expansion */ 1205 * expansion */
1206 Lst curTargs; /* list of target names to be found and added 1206 Lst curTargs; /* list of target names to be found and added
1207 * to the targets list */ 1207 * to the targets list */
1208 char *lstart = line; 1208 char *lstart = line;
1209 1209
1210 if (DEBUG(PARSE)) 1210 if (DEBUG(PARSE))
1211 fprintf(debug_file, "ParseDoDependency(%s)\n", line); 1211 fprintf(debug_file, "ParseDoDependency(%s)\n", line);
1212 tOp = 0; 1212 tOp = 0;
1213 1213
1214 specType = Not; 1214 specType = Not;
1215 paths = NULL; 1215 paths = NULL;
1216 1216
1217 curTargs = Lst_Init(FALSE); 1217 curTargs = Lst_Init(FALSE);
1218 1218
1219 /* 1219 /*
1220 * First, grind through the targets. 1220 * First, grind through the targets.
1221 */ 1221 */
1222 1222
1223 do { 1223 do {
1224 /* 1224 /*
1225 * Here LINE points to the beginning of the next word, and 1225 * Here LINE points to the beginning of the next word, and
1226 * LSTART points to the actual beginning of the line. 1226 * LSTART points to the actual beginning of the line.
1227 */ 1227 */
1228 1228
1229 /* Find the end of the next word. */ 1229 /* Find the end of the next word. */
1230 for (cp = line; *cp && (ParseIsEscaped(lstart, cp) || 1230 for (cp = line; *cp && (ParseIsEscaped(lstart, cp) ||
1231 !(isspace((unsigned char)*cp) || 1231 !(isspace((unsigned char)*cp) ||
1232 *cp == '!' || *cp == ':' || *cp == LPAREN)); 1232 *cp == '!' || *cp == ':' || *cp == LPAREN));
1233 cp++) { 1233 cp++) {
1234 if (*cp == '$') { 1234 if (*cp == '$') {
1235 /* 1235 /*
1236 * Must be a dynamic source (would have been expanded 1236 * Must be a dynamic source (would have been expanded
1237 * otherwise), so call the Var module to parse the puppy 1237 * otherwise), so call the Var module to parse the puppy
1238 * so we can safely advance beyond it...There should be 1238 * so we can safely advance beyond it...There should be
1239 * no errors in this, as they would have been discovered 1239 * no errors in this, as they would have been discovered
1240 * in the initial Var_Subst and we wouldn't be here. 1240 * in the initial Var_Subst and we wouldn't be here.
1241 */ 1241 */
1242 int length; 1242 int length;
1243 void *freeIt; 1243 void *freeIt;
1244 1244
1245 (void)Var_Parse(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES, 1245 (void)Var_Parse(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES,
1246 &length, &freeIt); 1246 &length, &freeIt);
1247 free(freeIt); 1247 free(freeIt);
1248 cp += length-1; 1248 cp += length-1;
1249 } 1249 }
1250 } 1250 }
1251 1251
1252 /* 1252 /*
1253 * If the word is followed by a left parenthesis, it's the 1253 * If the word is followed by a left parenthesis, it's the
1254 * name of an object file inside an archive (ar file). 1254 * name of an object file inside an archive (ar file).
1255 */ 1255 */
1256 if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) { 1256 if (!ParseIsEscaped(lstart, cp) && *cp == LPAREN) {
1257 /* 1257 /*
1258 * Archives must be handled specially to make sure the OP_ARCHV 1258 * Archives must be handled specially to make sure the OP_ARCHV
1259 * flag is set in their 'type' field, for one thing, and because 1259 * flag is set in their 'type' field, for one thing, and because
1260 * things like "archive(file1.o file2.o file3.o)" are permissible. 1260 * things like "archive(file1.o file2.o file3.o)" are permissible.
1261 * Arch_ParseArchive will set 'line' to be the first non-blank 1261 * Arch_ParseArchive will set 'line' to be the first non-blank
1262 * after the archive-spec. It creates/finds nodes for the members 1262 * after the archive-spec. It creates/finds nodes for the members
1263 * and places them on the given list, returning SUCCESS if all 1263 * and places them on the given list, returning SUCCESS if all
1264 * went well and FAILURE if there was an error in the 1264 * went well and FAILURE if there was an error in the
1265 * specification. On error, line should remain untouched. 1265 * specification. On error, line should remain untouched.
1266 */ 1266 */
1267 if (Arch_ParseArchive(&line, targets, VAR_CMD) != SUCCESS) { 1267 if (Arch_ParseArchive(&line, targets, VAR_CMD) != SUCCESS) {
1268 Parse_Error(PARSE_FATAL, 1268 Parse_Error(PARSE_FATAL,
1269 "Error in archive specification: \"%s\"", line); 1269 "Error in archive specification: \"%s\"", line);
1270 goto out; 1270 goto out;
1271 } else { 1271 } else {
1272 /* Done with this word; on to the next. */ 1272 /* Done with this word; on to the next. */
1273 cp = line; 1273 cp = line;
1274 continue; 1274 continue;
1275 } 1275 }
1276 } 1276 }
1277 1277
1278 if (!*cp) { 1278 if (!*cp) {
1279 /* 1279 /*
1280 * We got to the end of the line while we were still 1280 * We got to the end of the line while we were still
1281 * looking at targets. 1281 * looking at targets.
1282 * 1282 *
1283 * Ending a dependency line without an operator is a Bozo 1283 * Ending a dependency line without an operator is a Bozo
1284 * no-no. As a heuristic, this is also often triggered by 1284 * no-no. As a heuristic, this is also often triggered by
1285 * undetected conflicts from cvs/rcs merges. 1285 * undetected conflicts from cvs/rcs merges.
1286 */ 1286 */
1287 if ((strncmp(line, "<<<<<<", 6) == 0) || 1287 if ((strncmp(line, "<<<<<<", 6) == 0) ||
1288 (strncmp(line, "======", 6) == 0) || 1288 (strncmp(line, "======", 6) == 0) ||
1289 (strncmp(line, ">>>>>>", 6) == 0)) 1289 (strncmp(line, ">>>>>>", 6) == 0))
1290 Parse_Error(PARSE_FATAL, 1290 Parse_Error(PARSE_FATAL,
1291 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts"); 1291 "Makefile appears to contain unresolved cvs/rcs/??? merge conflicts");
1292 else 1292 else if (lstart[0] == '.') {
 1293 const char *dirstart = lstart + 1;
 1294 while (isspace((unsigned char)*dirstart))
 1295 dirstart++;
 1296 const char *dirend = dirstart;
 1297 while (isalnum((unsigned char)*dirend) || *dirend == '-')
 1298 dirend++;
 1299 Parse_Error(PARSE_FATAL, "Unknown directive \"%.*s\"",
 1300 (int)(dirend - dirstart), dirstart);
 1301 } else
1293 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" 1302 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive"
1294 : "Need an operator"); 1303 : "Need an operator");
1295 goto out; 1304 goto out;
1296 } 1305 }
1297 1306
1298 /* Insert a null terminator. */ 1307 /* Insert a null terminator. */
1299 savec = *cp; 1308 savec = *cp;
1300 *cp = '\0'; 1309 *cp = '\0';
1301 1310
1302 /* 1311 /*
1303 * Got the word. See if it's a special target and if so set 1312 * Got the word. See if it's a special target and if so set
1304 * specType to match it. 1313 * specType to match it.
1305 */ 1314 */
1306 if (*line == '.' && isupper ((unsigned char)line[1])) { 1315 if (*line == '.' && isupper ((unsigned char)line[1])) {
1307 /* 1316 /*
1308 * See if the target is a special target that must have it 1317 * See if the target is a special target that must have it
1309 * or its sources handled specially. 1318 * or its sources handled specially.
1310 */ 1319 */
1311 int keywd = ParseFindKeyword(line); 1320 int keywd = ParseFindKeyword(line);
1312 if (keywd != -1) { 1321 if (keywd != -1) {
1313 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) { 1322 if (specType == ExPath && parseKeywords[keywd].spec != ExPath) {
1314 Parse_Error(PARSE_FATAL, "Mismatched special targets"); 1323 Parse_Error(PARSE_FATAL, "Mismatched special targets");
1315 goto out; 1324 goto out;
1316 } 1325 }
1317 1326
1318 specType = parseKeywords[keywd].spec; 1327 specType = parseKeywords[keywd].spec;
1319 tOp = parseKeywords[keywd].op; 1328 tOp = parseKeywords[keywd].op;
1320 1329
1321 /* 1330 /*
1322 * Certain special targets have special semantics: 1331 * Certain special targets have special semantics:
1323 * .PATH Have to set the dirSearchPath 1332 * .PATH Have to set the dirSearchPath
1324 * variable too 1333 * variable too
1325 * .MAIN Its sources are only used if 1334 * .MAIN Its sources are only used if
1326 * nothing has been specified to 1335 * nothing has been specified to
1327 * create. 1336 * create.
1328 * .DEFAULT Need to create a node to hang 1337 * .DEFAULT Need to create a node to hang
1329 * commands on, but we don't want 1338 * commands on, but we don't want
1330 * it in the graph, nor do we want 1339 * it in the graph, nor do we want
1331 * it to be the Main Target, so we 1340 * it to be the Main Target, so we
1332 * create it, set OP_NOTMAIN and 1341 * create it, set OP_NOTMAIN and
1333 * add it to the list, setting 1342 * add it to the list, setting
1334 * DEFAULT to the new node for 1343 * DEFAULT to the new node for
1335 * later use. We claim the node is 1344 * later use. We claim the node is
1336 * A transformation rule to make 1345 * A transformation rule to make
1337 * life easier later, when we'll 1346 * life easier later, when we'll
1338 * use Make_HandleUse to actually 1347 * use Make_HandleUse to actually
1339 * apply the .DEFAULT commands. 1348 * apply the .DEFAULT commands.
1340 * .PHONY The list of targets 1349 * .PHONY The list of targets
1341 * .NOPATH Don't search for file in the path 1350 * .NOPATH Don't search for file in the path
1342 * .STALE 1351 * .STALE
1343 * .BEGIN 1352 * .BEGIN
1344 * .END 1353 * .END
1345 * .ERROR 1354 * .ERROR
1346 * .DELETE_ON_ERROR 1355 * .DELETE_ON_ERROR
1347 * .INTERRUPT Are not to be considered the 1356 * .INTERRUPT Are not to be considered the
1348 * main target. 1357 * main target.
1349 * .NOTPARALLEL Make only one target at a time. 1358 * .NOTPARALLEL Make only one target at a time.
1350 * .SINGLESHELL Create a shell for each command. 1359 * .SINGLESHELL Create a shell for each command.
1351 * .ORDER Must set initial predecessor to NULL 1360 * .ORDER Must set initial predecessor to NULL
1352 */ 1361 */
1353 switch (specType) { 1362 switch (specType) {
1354 case ExPath: 1363 case ExPath:
1355 if (paths == NULL) { 1364 if (paths == NULL) {
1356 paths = Lst_Init(FALSE); 1365 paths = Lst_Init(FALSE);
1357 } 1366 }
1358 (void)Lst_AtEnd(paths, dirSearchPath); 1367 (void)Lst_AtEnd(paths, dirSearchPath);
1359 break; 1368 break;
1360 case Main: 1369 case Main:
1361 if (!Lst_IsEmpty(create)) { 1370 if (!Lst_IsEmpty(create)) {
1362 specType = Not; 1371 specType = Not;
1363 } 1372 }
1364 break; 1373 break;
1365 case Begin: 1374 case Begin:
1366 case End: 1375 case End:
1367 case Stale: 1376 case Stale:
1368 case dotError: 1377 case dotError:
1369 case Interrupt: 1378 case Interrupt:
1370 gn = Targ_FindNode(line, TARG_CREATE); 1379 gn = Targ_FindNode(line, TARG_CREATE);
1371 if (doing_depend) 1380 if (doing_depend)
1372 ParseMark(gn); 1381 ParseMark(gn);
1373 gn->type |= OP_NOTMAIN|OP_SPECIAL; 1382 gn->type |= OP_NOTMAIN|OP_SPECIAL;
1374 (void)Lst_AtEnd(targets, gn); 1383 (void)Lst_AtEnd(targets, gn);
1375 break; 1384 break;
1376 case Default: 1385 case Default:
1377 gn = Targ_NewGN(".DEFAULT"); 1386 gn = Targ_NewGN(".DEFAULT");
1378 gn->type |= (OP_NOTMAIN|OP_TRANSFORM); 1387 gn->type |= (OP_NOTMAIN|OP_TRANSFORM);
1379 (void)Lst_AtEnd(targets, gn); 1388 (void)Lst_AtEnd(targets, gn);
1380 DEFAULT = gn; 1389 DEFAULT = gn;
1381 break; 1390 break;
1382 case DeleteOnError: 1391 case DeleteOnError:
1383 deleteOnError = TRUE; 1392 deleteOnError = TRUE;
1384 break; 1393 break;
1385 case NotParallel: 1394 case NotParallel:
1386 maxJobs = 1; 1395 maxJobs = 1;
1387 break; 1396 break;
1388 case SingleShell: 1397 case SingleShell:
1389 compatMake = TRUE; 1398 compatMake = TRUE;
1390 break; 1399 break;
1391 case Order: 1400 case Order:
1392 predecessor = NULL; 1401 predecessor = NULL;
1393 break; 1402 break;
1394 default: 1403 default:
1395 break; 1404 break;
1396 } 1405 }
1397 } else if (strncmp(line, ".PATH", 5) == 0) { 1406 } else if (strncmp(line, ".PATH", 5) == 0) {
1398 /* 1407 /*
1399 * .PATH<suffix> has to be handled specially. 1408 * .PATH<suffix> has to be handled specially.
1400 * Call on the suffix module to give us a path to 1409 * Call on the suffix module to give us a path to
1401 * modify. 1410 * modify.
1402 */ 1411 */
1403 Lst path; 1412 Lst path;
1404 1413
1405 specType = ExPath; 1414 specType = ExPath;
1406 path = Suff_GetPath(&line[5]); 1415 path = Suff_GetPath(&line[5]);
1407 if (path == NULL) { 1416 if (path == NULL) {
1408 Parse_Error(PARSE_FATAL, 1417 Parse_Error(PARSE_FATAL,
1409 "Suffix '%s' not defined (yet)", 1418 "Suffix '%s' not defined (yet)",
1410 &line[5]); 1419 &line[5]);
1411 goto out; 1420 goto out;
1412 } else { 1421 } else {
1413 if (paths == NULL) { 1422 if (paths == NULL) {
1414 paths = Lst_Init(FALSE); 1423 paths = Lst_Init(FALSE);
1415 } 1424 }
1416 (void)Lst_AtEnd(paths, path); 1425 (void)Lst_AtEnd(paths, path);
1417 } 1426 }
1418 } 1427 }
1419 } 1428 }
1420 1429
1421 /* 1430 /*
1422 * Have word in line. Get or create its node and stick it at 1431 * Have word in line. Get or create its node and stick it at
1423 * the end of the targets list 1432 * the end of the targets list
1424 */ 1433 */
1425 if ((specType == Not) && (*line != '\0')) { 1434 if ((specType == Not) && (*line != '\0')) {
1426 if (Dir_HasWildcards(line)) { 1435 if (Dir_HasWildcards(line)) {
1427 /* 1436 /*
1428 * Targets are to be sought only in the current directory, 1437 * Targets are to be sought only in the current directory,
1429 * so create an empty path for the thing. Note we need to 1438 * so create an empty path for the thing. Note we need to
1430 * use Dir_Destroy in the destruction of the path as the 1439 * use Dir_Destroy in the destruction of the path as the
1431 * Dir module could have added a directory to the path... 1440 * Dir module could have added a directory to the path...
1432 */ 1441 */
1433 Lst emptyPath = Lst_Init(FALSE); 1442 Lst emptyPath = Lst_Init(FALSE);
1434 1443
1435 Dir_Expand(line, emptyPath, curTargs); 1444 Dir_Expand(line, emptyPath, curTargs);
1436 1445
1437 Lst_Destroy(emptyPath, Dir_Destroy); 1446 Lst_Destroy(emptyPath, Dir_Destroy);
1438 } else { 1447 } else {
1439 /* 1448 /*
1440 * No wildcards, but we want to avoid code duplication, 1449 * No wildcards, but we want to avoid code duplication,
1441 * so create a list with the word on it. 1450 * so create a list with the word on it.
1442 */ 1451 */
1443 (void)Lst_AtEnd(curTargs, line); 1452 (void)Lst_AtEnd(curTargs, line);
1444 } 1453 }
1445 1454
1446 /* Apply the targets. */ 1455 /* Apply the targets. */
1447 1456
1448 while(!Lst_IsEmpty(curTargs)) { 1457 while(!Lst_IsEmpty(curTargs)) {
1449 char *targName = (char *)Lst_DeQueue(curTargs); 1458 char *targName = (char *)Lst_DeQueue(curTargs);
1450 1459
1451 if (!Suff_IsTransform (targName)) { 1460 if (!Suff_IsTransform (targName)) {
1452 gn = Targ_FindNode(targName, TARG_CREATE); 1461 gn = Targ_FindNode(targName, TARG_CREATE);
1453 } else { 1462 } else {
1454 gn = Suff_AddTransform(targName); 1463 gn = Suff_AddTransform(targName);
1455 } 1464 }
1456 if (doing_depend) 1465 if (doing_depend)
1457 ParseMark(gn); 1466 ParseMark(gn);
1458 1467
1459 (void)Lst_AtEnd(targets, gn); 1468 (void)Lst_AtEnd(targets, gn);
1460 } 1469 }
1461 } else if (specType == ExPath && *line != '.' && *line != '\0') { 1470 } else if (specType == ExPath && *line != '.' && *line != '\0') {
1462 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line); 1471 Parse_Error(PARSE_WARNING, "Extra target (%s) ignored", line);
1463 } 1472 }
1464 1473
1465 /* Don't need the inserted null terminator any more. */ 1474 /* Don't need the inserted null terminator any more. */
1466 *cp = savec; 1475 *cp = savec;
1467 1476
1468 /* 1477 /*
1469 * If it is a special type and not .PATH, it's the only target we 1478 * If it is a special type and not .PATH, it's the only target we
1470 * allow on this line... 1479 * allow on this line...
1471 */ 1480 */
1472 if (specType != Not && specType != ExPath) { 1481 if (specType != Not && specType != ExPath) {
1473 Boolean warning = FALSE; 1482 Boolean warning = FALSE;
1474 1483
1475 while (*cp && (ParseIsEscaped(lstart, cp) || 1484 while (*cp && (ParseIsEscaped(lstart, cp) ||
1476 ((*cp != '!') && (*cp != ':')))) { 1485 ((*cp != '!') && (*cp != ':')))) {
1477 if (ParseIsEscaped(lstart, cp) || 1486 if (ParseIsEscaped(lstart, cp) ||
1478 (*cp != ' ' && *cp != '\t')) { 1487 (*cp != ' ' && *cp != '\t')) {
1479 warning = TRUE; 1488 warning = TRUE;
1480 } 1489 }
1481 cp++; 1490 cp++;
1482 } 1491 }
1483 if (warning) { 1492 if (warning) {
1484 Parse_Error(PARSE_WARNING, "Extra target ignored"); 1493 Parse_Error(PARSE_WARNING, "Extra target ignored");
1485 } 1494 }
1486 } else { 1495 } else {
1487 while (*cp && isspace ((unsigned char)*cp)) { 1496 while (*cp && isspace ((unsigned char)*cp)) {
1488 cp++; 1497 cp++;
1489 } 1498 }
1490 } 1499 }
1491 line = cp; 1500 line = cp;
1492 } while (*line && (ParseIsEscaped(lstart, line) || 1501 } while (*line && (ParseIsEscaped(lstart, line) ||
1493 ((*line != '!') && (*line != ':')))); 1502 ((*line != '!') && (*line != ':'))));
1494 1503
1495 /* 1504 /*
1496 * Don't need the list of target names anymore... 1505 * Don't need the list of target names anymore...
1497 */ 1506 */
1498 Lst_Destroy(curTargs, NULL); 1507 Lst_Destroy(curTargs, NULL);
1499 curTargs = NULL; 1508 curTargs = NULL;
1500 1509
1501 if (!Lst_IsEmpty(targets)) { 1510 if (!Lst_IsEmpty(targets)) {
1502 switch(specType) { 1511 switch(specType) {
1503 default: 1512 default:
1504 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored"); 1513 Parse_Error(PARSE_WARNING, "Special and mundane targets don't mix. Mundane ones ignored");
1505 break; 1514 break;
1506 case Default: 1515 case Default:
1507 case Stale: 1516 case Stale:
1508 case Begin: 1517 case Begin:
1509 case End: 1518 case End:
1510 case dotError: 1519 case dotError:
1511 case Interrupt: 1520 case Interrupt:
1512 /* 1521 /*
1513 * These four create nodes on which to hang commands, so 1522 * These four create nodes on which to hang commands, so
1514 * targets shouldn't be empty... 1523 * targets shouldn't be empty...
1515 */ 1524 */
1516 case Not: 1525 case Not:
1517 /* 1526 /*
1518 * Nothing special here -- targets can be empty if it wants. 1527 * Nothing special here -- targets can be empty if it wants.
1519 */ 1528 */
1520 break; 1529 break;
1521 } 1530 }
1522 } 1531 }
1523 1532
1524 /* 1533 /*
1525 * Have now parsed all the target names. Must parse the operator next. The 1534 * Have now parsed all the target names. Must parse the operator next. The
1526 * result is left in op . 1535 * result is left in op .
1527 */ 1536 */
1528 if (*cp == '!') { 1537 if (*cp == '!') {
1529 op = OP_FORCE; 1538 op = OP_FORCE;
1530 } else if (*cp == ':') { 1539 } else if (*cp == ':') {
1531 if (cp[1] == ':') { 1540 if (cp[1] == ':') {
1532 op = OP_DOUBLEDEP; 1541 op = OP_DOUBLEDEP;
1533 cp++; 1542 cp++;
1534 } else { 1543 } else {
1535 op = OP_DEPENDS; 1544 op = OP_DEPENDS;
1536 } 1545 }
1537 } else { 1546 } else {
1538 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive" 1547 Parse_Error(PARSE_FATAL, lstart[0] == '.' ? "Unknown directive"
1539 : "Missing dependency operator"); 1548 : "Missing dependency operator");
1540 goto out; 1549 goto out;
1541 } 1550 }
1542 1551
1543 /* Advance beyond the operator */ 1552 /* Advance beyond the operator */
1544 cp++; 1553 cp++;
1545 1554
1546 /* 1555 /*
1547 * Apply the operator to the target. This is how we remember which 1556 * Apply the operator to the target. This is how we remember which
1548 * operator a target was defined with. It fails if the operator 1557 * operator a target was defined with. It fails if the operator
1549 * used isn't consistent across all references. 1558 * used isn't consistent across all references.
1550 */ 1559 */
1551 Lst_ForEach(targets, ParseDoOp, &op); 1560 Lst_ForEach(targets, ParseDoOp, &op);
1552 1561
1553 /* 1562 /*
1554 * Onward to the sources. 1563 * Onward to the sources.
1555 * 1564 *
1556 * LINE will now point to the first source word, if any, or the 1565 * LINE will now point to the first source word, if any, or the
1557 * end of the string if not. 1566 * end of the string if not.
1558 */ 1567 */
1559 while (*cp && isspace ((unsigned char)*cp)) { 1568 while (*cp && isspace ((unsigned char)*cp)) {
1560 cp++; 1569 cp++;
1561 } 1570 }
1562 line = cp; 1571 line = cp;
1563 1572
1564 /* 1573 /*
1565 * Several special targets take different actions if present with no 1574 * Several special targets take different actions if present with no
1566 * sources: 1575 * sources:
1567 * a .SUFFIXES line with no sources clears out all old suffixes 1576 * a .SUFFIXES line with no sources clears out all old suffixes
1568 * a .PRECIOUS line makes all targets precious 1577 * a .PRECIOUS line makes all targets precious
1569 * a .IGNORE line ignores errors for all targets 1578 * a .IGNORE line ignores errors for all targets
1570 * a .SILENT line creates silence when making all targets 1579 * a .SILENT line creates silence when making all targets
1571 * a .PATH removes all directories from the search path(s). 1580 * a .PATH removes all directories from the search path(s).
1572 */ 1581 */
1573 if (!*line) { 1582 if (!*line) {
1574 switch (specType) { 1583 switch (specType) {
1575 case Suffixes: 1584 case Suffixes:
1576 Suff_ClearSuffixes(); 1585 Suff_ClearSuffixes();
1577 break; 1586 break;
1578 case Precious: 1587 case Precious:
1579 allPrecious = TRUE; 1588 allPrecious = TRUE;
1580 break; 1589 break;
1581 case Ignore: 1590 case Ignore:
1582 ignoreErrors = TRUE; 1591 ignoreErrors = TRUE;
1583 break; 1592 break;
1584 case Silent: 1593 case Silent:
1585 beSilent = TRUE; 1594 beSilent = TRUE;
1586 break; 1595 break;
1587 case ExPath: 1596 case ExPath:
1588 Lst_ForEach(paths, ParseClearPath, NULL); 1597 Lst_ForEach(paths, ParseClearPath, NULL);
1589 Dir_SetPATH(); 1598 Dir_SetPATH();
1590 break; 1599 break;
1591#ifdef POSIX 1600#ifdef POSIX
1592 case Posix: 1601 case Posix:
1593 Var_Set("%POSIX", "1003.2", VAR_GLOBAL); 1602 Var_Set("%POSIX", "1003.2", VAR_GLOBAL);
1594 break; 1603 break;
1595#endif 1604#endif
1596 default: 1605 default:
1597 break; 1606 break;
1598 } 1607 }
1599 } else if (specType == MFlags) { 1608 } else if (specType == MFlags) {
1600 /* 1609 /*
1601 * Call on functions in main.c to deal with these arguments and 1610 * Call on functions in main.c to deal with these arguments and
1602 * set the initial character to a null-character so the loop to 1611 * set the initial character to a null-character so the loop to
1603 * get sources won't get anything 1612 * get sources won't get anything
1604 */ 1613 */
1605 Main_ParseArgLine(line); 1614 Main_ParseArgLine(line);
1606 *line = '\0'; 1615 *line = '\0';
1607 } else if (specType == ExShell) { 1616 } else if (specType == ExShell) {
1608 if (Job_ParseShell(line) != SUCCESS) { 1617 if (Job_ParseShell(line) != SUCCESS) {
1609 Parse_Error(PARSE_FATAL, "improper shell specification"); 1618 Parse_Error(PARSE_FATAL, "improper shell specification");
1610 goto out; 1619 goto out;
1611 } 1620 }
1612 *line = '\0'; 1621 *line = '\0';
1613 } else if ((specType == NotParallel) || (specType == SingleShell) || 1622 } else if ((specType == NotParallel) || (specType == SingleShell) ||
1614 (specType == DeleteOnError)) { 1623 (specType == DeleteOnError)) {
1615 *line = '\0'; 1624 *line = '\0';
1616 } 1625 }
1617 1626
1618 /* 1627 /*
1619 * NOW GO FOR THE SOURCES 1628 * NOW GO FOR THE SOURCES
1620 */ 1629 */
1621 if ((specType == Suffixes) || (specType == ExPath) || 1630 if ((specType == Suffixes) || (specType == ExPath) ||
1622 (specType == Includes) || (specType == Libs) || 1631 (specType == Includes) || (specType == Libs) ||
1623 (specType == Null) || (specType == ExObjdir)) 1632 (specType == Null) || (specType == ExObjdir))
1624 { 1633 {
1625 while (*line) { 1634 while (*line) {
1626 /* 1635 /*
1627 * If the target was one that doesn't take files as its sources 1636 * If the target was one that doesn't take files as its sources
1628 * but takes something like suffixes, we take each 1637 * but takes something like suffixes, we take each
1629 * space-separated word on the line as a something and deal 1638 * space-separated word on the line as a something and deal
1630 * with it accordingly. 1639 * with it accordingly.
1631 * 1640 *
1632 * If the target was .SUFFIXES, we take each source as a 1641 * If the target was .SUFFIXES, we take each source as a
1633 * suffix and add it to the list of suffixes maintained by the 1642 * suffix and add it to the list of suffixes maintained by the
1634 * Suff module. 1643 * Suff module.
1635 * 1644 *
1636 * If the target was a .PATH, we add the source as a directory 1645 * If the target was a .PATH, we add the source as a directory
1637 * to search on the search path. 1646 * to search on the search path.
1638 * 1647 *
1639 * If it was .INCLUDES, the source is taken to be the suffix of 1648 * If it was .INCLUDES, the source is taken to be the suffix of
1640 * files which will be #included and whose search path should 1649 * files which will be #included and whose search path should
1641 * be present in the .INCLUDES variable. 1650 * be present in the .INCLUDES variable.
1642 * 1651 *
1643 * If it was .LIBS, the source is taken to be the suffix of 1652 * If it was .LIBS, the source is taken to be the suffix of
1644 * files which are considered libraries and whose search path 1653 * files which are considered libraries and whose search path
1645 * should be present in the .LIBS variable. 1654 * should be present in the .LIBS variable.
1646 * 1655 *
1647 * If it was .NULL, the source is the suffix to use when a file 1656 * If it was .NULL, the source is the suffix to use when a file
1648 * has no valid suffix. 1657 * has no valid suffix.
1649 * 1658 *
1650 * If it was .OBJDIR, the source is a new definition for .OBJDIR, 1659 * If it was .OBJDIR, the source is a new definition for .OBJDIR,
1651 * and will cause make to do a new chdir to that path. 1660 * and will cause make to do a new chdir to that path.
1652 */ 1661 */
1653 while (*cp && !isspace ((unsigned char)*cp)) { 1662 while (*cp && !isspace ((unsigned char)*cp)) {
1654 cp++; 1663 cp++;
1655 } 1664 }
1656 savec = *cp; 1665 savec = *cp;
1657 *cp = '\0'; 1666 *cp = '\0';
1658 switch (specType) { 1667 switch (specType) {
1659 case Suffixes: 1668 case Suffixes:
1660 Suff_AddSuffix(line, &mainNode); 1669 Suff_AddSuffix(line, &mainNode);
1661 break; 1670 break;
1662 case ExPath: 1671 case ExPath:
1663 Lst_ForEach(paths, ParseAddDir, line); 1672 Lst_ForEach(paths, ParseAddDir, line);
1664 break; 1673 break;
1665 case Includes: 1674 case Includes:
1666 Suff_AddInclude(line); 1675 Suff_AddInclude(line);
1667 break; 1676 break;
1668 case Libs: 1677 case Libs:
1669 Suff_AddLib(line); 1678 Suff_AddLib(line);
1670 break; 1679 break;
1671 case Null: 1680 case Null:
1672 Suff_SetNull(line); 1681 Suff_SetNull(line);
1673 break; 1682 break;
1674 case ExObjdir: 1683 case ExObjdir:
1675 Main_SetObjdir("%s", line); 1684 Main_SetObjdir("%s", line);
1676 break; 1685 break;
1677 default: 1686 default:
1678 break; 1687 break;
1679 } 1688 }
1680 *cp = savec; 1689 *cp = savec;
1681 if (savec != '\0') { 1690 if (savec != '\0') {
1682 cp++; 1691 cp++;
1683 } 1692 }
1684 while (*cp && isspace ((unsigned char)*cp)) { 1693 while (*cp && isspace ((unsigned char)*cp)) {
1685 cp++; 1694 cp++;
1686 } 1695 }
1687 line = cp; 1696 line = cp;
1688 } 1697 }
1689 if (paths) { 1698 if (paths) {
1690 Lst_Destroy(paths, NULL); 1699 Lst_Destroy(paths, NULL);
1691 paths = NULL; 1700 paths = NULL;
1692 } 1701 }
1693 if (specType == ExPath) 1702 if (specType == ExPath)
1694 Dir_SetPATH(); 1703 Dir_SetPATH();
1695 } else { 1704 } else {
1696 assert(paths == NULL); 1705 assert(paths == NULL);
1697 while (*line) { 1706 while (*line) {
1698 /* 1707 /*
1699 * The targets take real sources, so we must beware of archive 1708 * The targets take real sources, so we must beware of archive
1700 * specifications (i.e. things with left parentheses in them) 1709 * specifications (i.e. things with left parentheses in them)
1701 * and handle them accordingly. 1710 * and handle them accordingly.
1702 */ 1711 */
1703 for (; *cp && !isspace ((unsigned char)*cp); cp++) { 1712 for (; *cp && !isspace ((unsigned char)*cp); cp++) {
1704 if ((*cp == LPAREN) && (cp > line) && (cp[-1] != '$')) { 1713 if ((*cp == LPAREN) && (cp > line) && (cp[-1] != '$')) {
1705 /* 1714 /*
1706 * Only stop for a left parenthesis if it isn't at the 1715 * Only stop for a left parenthesis if it isn't at the
1707 * start of a word (that'll be for variable changes 1716 * start of a word (that'll be for variable changes
1708 * later) and isn't preceded by a dollar sign (a dynamic 1717 * later) and isn't preceded by a dollar sign (a dynamic
1709 * source). 1718 * source).
1710 */ 1719 */
1711 break; 1720 break;
1712 } 1721 }
1713 } 1722 }
1714 1723
1715 if (*cp == LPAREN) { 1724 if (*cp == LPAREN) {
1716 sources = Lst_Init(FALSE); 1725 sources = Lst_Init(FALSE);
1717 if (Arch_ParseArchive(&line, sources, VAR_CMD) != SUCCESS) { 1726 if (Arch_ParseArchive(&line, sources, VAR_CMD) != SUCCESS) {
1718 Parse_Error(PARSE_FATAL, 1727 Parse_Error(PARSE_FATAL,
1719 "Error in source archive spec \"%s\"", line); 1728 "Error in source archive spec \"%s\"", line);
1720 goto out; 1729 goto out;
1721 } 1730 }
1722 1731
1723 while (!Lst_IsEmpty (sources)) { 1732 while (!Lst_IsEmpty (sources)) {
1724 gn = (GNode *)Lst_DeQueue(sources); 1733 gn = (GNode *)Lst_DeQueue(sources);
1725 ParseDoSrc(tOp, gn->name); 1734 ParseDoSrc(tOp, gn->name);
1726 } 1735 }
1727 Lst_Destroy(sources, NULL); 1736 Lst_Destroy(sources, NULL);
1728 cp = line; 1737 cp = line;
1729 } else { 1738 } else {
1730 if (*cp) { 1739 if (*cp) {
1731 *cp = '\0'; 1740 *cp = '\0';
1732 cp += 1; 1741 cp += 1;
1733 } 1742 }
1734 1743
1735 ParseDoSrc(tOp, line); 1744 ParseDoSrc(tOp, line);
1736 } 1745 }
1737 while (*cp && isspace ((unsigned char)*cp)) { 1746 while (*cp && isspace ((unsigned char)*cp)) {
1738 cp++; 1747 cp++;
1739 } 1748 }
1740 line = cp; 1749 line = cp;
1741 } 1750 }
1742 } 1751 }
1743 1752
1744 if (mainNode == NULL) { 1753 if (mainNode == NULL) {
1745 /* 1754 /*
1746 * If we have yet to decide on a main target to make, in the 1755 * If we have yet to decide on a main target to make, in the
1747 * absence of any user input, we want the first target on 1756 * absence of any user input, we want the first target on
1748 * the first dependency line that is actually a real target 1757 * the first dependency line that is actually a real target
1749 * (i.e. isn't a .USE or .EXEC rule) to be made. 1758 * (i.e. isn't a .USE or .EXEC rule) to be made.
1750 */ 1759 */
1751 Lst_ForEach(targets, ParseFindMain, NULL); 1760 Lst_ForEach(targets, ParseFindMain, NULL);
1752 } 1761 }
1753 1762
1754out: 1763out:
1755 if (paths) 1764 if (paths)
1756 Lst_Destroy(paths, NULL); 1765 Lst_Destroy(paths, NULL);
1757 if (curTargs) 1766 if (curTargs)
1758 Lst_Destroy(curTargs, NULL); 1767 Lst_Destroy(curTargs, NULL);
1759} 1768}
1760 1769
1761/*- 1770/*-
1762 *--------------------------------------------------------------------- 1771 *---------------------------------------------------------------------
1763 * Parse_IsVar -- 1772 * Parse_IsVar --
1764 * Return TRUE if the passed line is a variable assignment. A variable 1773 * Return TRUE if the passed line is a variable assignment. A variable
1765 * assignment consists of a single word followed by optional whitespace 1774 * assignment consists of a single word followed by optional whitespace
1766 * followed by either a += or an = operator. 1775 * followed by either a += or an = operator.
1767 * This function is used both by the Parse_File function and main when 1776 * This function is used both by the Parse_File function and main when
1768 * parsing the command-line arguments. 1777 * parsing the command-line arguments.
1769 * 1778 *
1770 * Input: 1779 * Input:
1771 * line the line to check 1780 * line the line to check
1772 * 1781 *
1773 * Results: 1782 * Results:
1774 * TRUE if it is. FALSE if it ain't 1783 * TRUE if it is. FALSE if it ain't
1775 * 1784 *
1776 * Side Effects: 1785 * Side Effects:
1777 * none 1786 * none
1778 *--------------------------------------------------------------------- 1787 *---------------------------------------------------------------------
1779 */ 1788 */
1780Boolean 1789Boolean
1781Parse_IsVar(char *line) 1790Parse_IsVar(char *line)
1782{ 1791{
1783 Boolean wasSpace = FALSE; /* set TRUE if found a space */ 1792 Boolean wasSpace = FALSE; /* set TRUE if found a space */
1784 char ch; 1793 char ch;
1785 int level = 0; 1794 int level = 0;
1786#define ISEQOPERATOR(c) \ 1795#define ISEQOPERATOR(c) \
1787 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!')) 1796 (((c) == '+') || ((c) == ':') || ((c) == '?') || ((c) == '!'))
1788 1797
1789 /* 1798 /*
1790 * Skip to variable name 1799 * Skip to variable name
1791 */ 1800 */
1792 for (;(*line == ' ') || (*line == '\t'); line++) 1801 for (;(*line == ' ') || (*line == '\t'); line++)
1793 continue; 1802 continue;
1794 1803
1795 /* Scan for one of the assignment operators outside a variable expansion */ 1804 /* Scan for one of the assignment operators outside a variable expansion */
1796 while ((ch = *line++) != 0) { 1805 while ((ch = *line++) != 0) {
1797 if (ch == '(' || ch == '{') { 1806 if (ch == '(' || ch == '{') {
1798 level++; 1807 level++;
1799 continue; 1808 continue;
1800 } 1809 }
1801 if (ch == ')' || ch == '}') { 1810 if (ch == ')' || ch == '}') {
1802 level--; 1811 level--;
1803 continue; 1812 continue;
1804 } 1813 }
1805 if (level != 0) 1814 if (level != 0)
1806 continue; 1815 continue;
1807 while (ch == ' ' || ch == '\t') { 1816 while (ch == ' ' || ch == '\t') {
1808 ch = *line++; 1817 ch = *line++;
1809 wasSpace = TRUE; 1818 wasSpace = TRUE;
1810 } 1819 }
1811#ifdef SUNSHCMD 1820#ifdef SUNSHCMD
1812 if (ch == ':' && strncmp(line, "sh", 2) == 0) { 1821 if (ch == ':' && strncmp(line, "sh", 2) == 0) {
1813 line += 2; 1822 line += 2;
1814 continue; 1823 continue;
1815 } 1824 }
1816#endif 1825#endif
1817 if (ch == '=') 1826 if (ch == '=')
1818 return TRUE; 1827 return TRUE;
1819 if (*line == '=' && ISEQOPERATOR(ch)) 1828 if (*line == '=' && ISEQOPERATOR(ch))
1820 return TRUE; 1829 return TRUE;
1821 if (wasSpace) 1830 if (wasSpace)
1822 return FALSE; 1831 return FALSE;
1823 } 1832 }
1824 1833
1825 return FALSE; 1834 return FALSE;
1826} 1835}
1827 1836
1828/*- 1837/*-
1829 *--------------------------------------------------------------------- 1838 *---------------------------------------------------------------------
1830 * Parse_DoVar -- 1839 * Parse_DoVar --
1831 * Take the variable assignment in the passed line and do it in the 1840 * Take the variable assignment in the passed line and do it in the
1832 * global context. 1841 * global context.
1833 * 1842 *
1834 * Note: There is a lexical ambiguity with assignment modifier characters 1843 * Note: There is a lexical ambiguity with assignment modifier characters
1835 * in variable names. This routine interprets the character before the = 1844 * in variable names. This routine interprets the character before the =
1836 * as a modifier. Therefore, an assignment like 1845 * as a modifier. Therefore, an assignment like
1837 * C++=/usr/bin/CC 1846 * C++=/usr/bin/CC
1838 * is interpreted as "C+ +=" instead of "C++ =". 1847 * is interpreted as "C+ +=" instead of "C++ =".
1839 * 1848 *
1840 * Input: 1849 * Input:
1841 * line a line guaranteed to be a variable assignment. 1850 * line a line guaranteed to be a variable assignment.
1842 * This reduces error checks 1851 * This reduces error checks
1843 * ctxt Context in which to do the assignment 1852 * ctxt Context in which to do the assignment
1844 * 1853 *
1845 * Results: 1854 * Results:
1846 * none 1855 * none
1847 * 1856 *
1848 * Side Effects: 1857 * Side Effects:
1849 * the variable structure of the given variable name is altered in the 1858 * the variable structure of the given variable name is altered in the
1850 * global context. 1859 * global context.
1851 *--------------------------------------------------------------------- 1860 *---------------------------------------------------------------------
1852 */ 1861 */
1853void 1862void
1854Parse_DoVar(char *line, GNode *ctxt) 1863Parse_DoVar(char *line, GNode *ctxt)
1855{ 1864{
1856 char *cp; /* pointer into line */ 1865 char *cp; /* pointer into line */
1857 enum { 1866 enum {
1858 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL 1867 VAR_SUBST, VAR_APPEND, VAR_SHELL, VAR_NORMAL
1859 } type; /* Type of assignment */ 1868 } type; /* Type of assignment */
1860 char *opc; /* ptr to operator character to 1869 char *opc; /* ptr to operator character to
1861 * null-terminate the variable name */ 1870 * null-terminate the variable name */
1862 Boolean freeCp = FALSE; /* TRUE if cp needs to be freed, 1871 Boolean freeCp = FALSE; /* TRUE if cp needs to be freed,
1863 * i.e. if any variable expansion was 1872 * i.e. if any variable expansion was
1864 * performed */ 1873 * performed */
1865 int depth; 1874 int depth;
1866 1875
1867 /* 1876 /*
1868 * Skip to variable name 1877 * Skip to variable name
1869 */ 1878 */
1870 while ((*line == ' ') || (*line == '\t')) { 1879 while ((*line == ' ') || (*line == '\t')) {
1871 line++; 1880 line++;
1872 } 1881 }
1873 1882
1874 /* 1883 /*
1875 * Skip to operator character, nulling out whitespace as we go 1884 * Skip to operator character, nulling out whitespace as we go
1876 * XXX Rather than counting () and {} we should look for $ and 1885 * XXX Rather than counting () and {} we should look for $ and
1877 * then expand the variable. 1886 * then expand the variable.
1878 */ 1887 */
1879 for (depth = 0, cp = line + 1; depth > 0 || *cp != '='; cp++) { 1888 for (depth = 0, cp = line + 1; depth > 0 || *cp != '='; cp++) {
1880 if (*cp == '(' || *cp == '{') { 1889 if (*cp == '(' || *cp == '{') {
1881 depth++; 1890 depth++;
1882 continue; 1891 continue;
1883 } 1892 }
1884 if (*cp == ')' || *cp == '}') { 1893 if (*cp == ')' || *cp == '}') {
1885 depth--; 1894 depth--;
1886 continue; 1895 continue;
1887 } 1896 }
1888 if (depth == 0 && isspace ((unsigned char)*cp)) { 1897 if (depth == 0 && isspace ((unsigned char)*cp)) {
1889 *cp = '\0'; 1898 *cp = '\0';
1890 } 1899 }
1891 } 1900 }
1892 opc = cp-1; /* operator is the previous character */ 1901 opc = cp-1; /* operator is the previous character */
1893 *cp++ = '\0'; /* nuke the = */ 1902 *cp++ = '\0'; /* nuke the = */
1894 1903
1895 /* 1904 /*
1896 * Check operator type 1905 * Check operator type
1897 */ 1906 */
1898 switch (*opc) { 1907 switch (*opc) {
1899 case '+': 1908 case '+':
1900 type = VAR_APPEND; 1909 type = VAR_APPEND;
1901 *opc = '\0'; 1910 *opc = '\0';
1902 break; 1911 break;
1903 1912
1904 case '?': 1913 case '?':
1905 /* 1914 /*
1906 * If the variable already has a value, we don't do anything. 1915 * If the variable already has a value, we don't do anything.
1907 */ 1916 */
1908 *opc = '\0'; 1917 *opc = '\0';
1909 if (Var_Exists(line, ctxt)) { 1918 if (Var_Exists(line, ctxt)) {
1910 return; 1919 return;
1911 } else { 1920 } else {
1912 type = VAR_NORMAL; 1921 type = VAR_NORMAL;
1913 } 1922 }
1914 break; 1923 break;
1915 1924
1916 case ':': 1925 case ':':
1917 type = VAR_SUBST; 1926 type = VAR_SUBST;
1918 *opc = '\0'; 1927 *opc = '\0';
1919 break; 1928 break;
1920 1929
1921 case '!': 1930 case '!':
1922 type = VAR_SHELL; 1931 type = VAR_SHELL;
1923 *opc = '\0'; 1932 *opc = '\0';
1924 break; 1933 break;
1925 1934
1926 default: 1935 default:
1927#ifdef SUNSHCMD 1936#ifdef SUNSHCMD
1928 while (opc > line && *opc != ':') 1937 while (opc > line && *opc != ':')
1929 opc--; 1938 opc--;
1930 1939
1931 if (strncmp(opc, ":sh", 3) == 0) { 1940 if (strncmp(opc, ":sh", 3) == 0) {
1932 type = VAR_SHELL; 1941 type = VAR_SHELL;
1933 *opc = '\0'; 1942 *opc = '\0';
1934 break; 1943 break;
1935 } 1944 }
1936#endif 1945#endif
1937 type = VAR_NORMAL; 1946 type = VAR_NORMAL;
1938 break; 1947 break;
1939 } 1948 }
1940 1949
1941 while (isspace((unsigned char)*cp)) 1950 while (isspace((unsigned char)*cp))
1942 cp++; 1951 cp++;
1943 1952
1944 if (type == VAR_APPEND) { 1953 if (type == VAR_APPEND) {
1945 Var_Append(line, cp, ctxt); 1954 Var_Append(line, cp, ctxt);
1946 } else if (type == VAR_SUBST) { 1955 } else if (type == VAR_SUBST) {
1947 /* 1956 /*
1948 * Allow variables in the old value to be undefined, but leave their 1957 * Allow variables in the old value to be undefined, but leave their
1949 * invocation alone -- this is done by forcing oldVars to be false. 1958 * invocation alone -- this is done by forcing oldVars to be false.
1950 * XXX: This can cause recursive variables, but that's not hard to do, 1959 * XXX: This can cause recursive variables, but that's not hard to do,
1951 * and this allows someone to do something like 1960 * and this allows someone to do something like
1952 * 1961 *
1953 * CFLAGS = $(.INCLUDES) 1962 * CFLAGS = $(.INCLUDES)
1954 * CFLAGS := -I.. $(CFLAGS) 1963 * CFLAGS := -I.. $(CFLAGS)
1955 * 1964 *
1956 * And not get an error. 1965 * And not get an error.
1957 */ 1966 */
1958 Boolean oldOldVars = oldVars; 1967 Boolean oldOldVars = oldVars;
1959 1968
1960 oldVars = FALSE; 1969 oldVars = FALSE;
1961 1970
1962 /* 1971 /*
1963 * make sure that we set the variable the first time to nothing 1972 * make sure that we set the variable the first time to nothing
1964 * so that it gets substituted! 1973 * so that it gets substituted!
1965 */ 1974 */
1966 if (!Var_Exists(line, ctxt)) 1975 if (!Var_Exists(line, ctxt))
1967 Var_Set(line, "", ctxt); 1976 Var_Set(line, "", ctxt);
1968 1977
1969 cp = Var_Subst(cp, ctxt, VARE_WANTRES|VARE_ASSIGN); 1978 cp = Var_Subst(cp, ctxt, VARE_WANTRES|VARE_ASSIGN);
1970 oldVars = oldOldVars; 1979 oldVars = oldOldVars;
1971 freeCp = TRUE; 1980 freeCp = TRUE;
1972 1981
1973 Var_Set(line, cp, ctxt); 1982 Var_Set(line, cp, ctxt);
1974 } else if (type == VAR_SHELL) { 1983 } else if (type == VAR_SHELL) {
1975 char *res; 1984 char *res;
1976 const char *error; 1985 const char *error;
1977 1986
1978 if (strchr(cp, '$') != NULL) { 1987 if (strchr(cp, '$') != NULL) {
1979 /* 1988 /*
1980 * There's a dollar sign in the command, so perform variable 1989 * There's a dollar sign in the command, so perform variable
1981 * expansion on the whole thing. The resulting string will need 1990 * expansion on the whole thing. The resulting string will need
1982 * freeing when we're done. 1991 * freeing when we're done.
1983 */ 1992 */
1984 cp = Var_Subst(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES); 1993 cp = Var_Subst(cp, VAR_CMD, VARE_UNDEFERR|VARE_WANTRES);
1985 freeCp = TRUE; 1994 freeCp = TRUE;
1986 } 1995 }
1987 1996
1988 res = Cmd_Exec(cp, &error); 1997 res = Cmd_Exec(cp, &error);
1989 Var_Set(line, res, ctxt); 1998 Var_Set(line, res, ctxt);
1990 free(res); 1999 free(res);
1991 2000
1992 if (error) 2001 if (error)
1993 Parse_Error(PARSE_WARNING, error, cp); 2002 Parse_Error(PARSE_WARNING, error, cp);
1994 } else { 2003 } else {
1995 /* 2004 /*
1996 * Normal assignment -- just do it. 2005 * Normal assignment -- just do it.
1997 */ 2006 */
1998 Var_Set(line, cp, ctxt); 2007 Var_Set(line, cp, ctxt);
1999 } 2008 }
2000 if (strcmp(line, MAKEOVERRIDES) == 0) 2009 if (strcmp(line, MAKEOVERRIDES) == 0)
2001 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */ 2010 Main_ExportMAKEFLAGS(FALSE); /* re-export MAKEFLAGS */
2002 else if (strcmp(line, ".CURDIR") == 0) { 2011 else if (strcmp(line, ".CURDIR") == 0) {
2003 /* 2012 /*
2004 * Somone is being (too?) clever... 2013 * Somone is being (too?) clever...
2005 * Let's pretend they know what they are doing and 2014 * Let's pretend they know what they are doing and
2006 * re-initialize the 'cur' Path. 2015 * re-initialize the 'cur' Path.
2007 */ 2016 */
2008 Dir_InitCur(cp); 2017 Dir_InitCur(cp);
2009 Dir_SetPATH(); 2018 Dir_SetPATH();
2010 } else if (strcmp(line, MAKE_JOB_PREFIX) == 0) { 2019 } else if (strcmp(line, MAKE_JOB_PREFIX) == 0) {
2011 Job_SetPrefix(); 2020 Job_SetPrefix();
2012 } else if (strcmp(line, MAKE_EXPORTED) == 0) { 2021 } else if (strcmp(line, MAKE_EXPORTED) == 0) {
2013 Var_Export(cp, 0); 2022 Var_Export(cp, 0);
2014 } 2023 }
2015 if (freeCp) 2024 if (freeCp)
2016 free(cp); 2025 free(cp);
2017} 2026}
2018 2027
2019 2028
2020/* 2029/*
2021 * ParseMaybeSubMake -- 2030 * ParseMaybeSubMake --
2022 * Scan the command string to see if it a possible submake node 2031 * Scan the command string to see if it a possible submake node
2023 * Input: 2032 * Input:
2024 * cmd the command to scan 2033 * cmd the command to scan
2025 * Results: 2034 * Results:
2026 * TRUE if the command is possibly a submake, FALSE if not. 2035 * TRUE if the command is possibly a submake, FALSE if not.
2027 */ 2036 */
2028static Boolean 2037static Boolean
2029ParseMaybeSubMake(const char *cmd) 2038ParseMaybeSubMake(const char *cmd)
2030{ 2039{
2031 size_t i; 2040 size_t i;
2032 static struct { 2041 static struct {
2033 const char *name; 2042 const char *name;
2034 size_t len; 2043 size_t len;
2035 } vals[] = { 2044 } vals[] = {
2036#define MKV(A) { A, sizeof(A) - 1 } 2045#define MKV(A) { A, sizeof(A) - 1 }
2037 MKV("${MAKE}"), 2046 MKV("${MAKE}"),
2038 MKV("${.MAKE}"), 2047 MKV("${.MAKE}"),
2039 MKV("$(MAKE)"), 2048 MKV("$(MAKE)"),
2040 MKV("$(.MAKE)"), 2049 MKV("$(.MAKE)"),
2041 MKV("make"), 2050 MKV("make"),
2042 }; 2051 };
2043 for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) { 2052 for (i = 0; i < sizeof(vals)/sizeof(vals[0]); i++) {
2044 char *ptr; 2053 char *ptr;
2045 if ((ptr = strstr(cmd, vals[i].name)) == NULL) 2054 if ((ptr = strstr(cmd, vals[i].name)) == NULL)
2046 continue; 2055 continue;
2047 if ((ptr == cmd || !isalnum((unsigned char)ptr[-1])) 2056 if ((ptr == cmd || !isalnum((unsigned char)ptr[-1]))
2048 && !isalnum((unsigned char)ptr[vals[i].len])) 2057 && !isalnum((unsigned char)ptr[vals[i].len]))
2049 return TRUE; 2058 return TRUE;
2050 } 2059 }
2051 return FALSE; 2060 return FALSE;
2052} 2061}
2053 2062
2054/*- 2063/*-
2055 * ParseAddCmd -- 2064 * ParseAddCmd --
2056 * Lst_ForEach function to add a command line to all targets 2065 * Lst_ForEach function to add a command line to all targets
2057 * 2066 *
2058 * Input: 2067 * Input:
2059 * gnp the node to which the command is to be added 2068 * gnp the node to which the command is to be added
2060 * cmd the command to add 2069 * cmd the command to add
2061 * 2070 *
2062 * Results: 2071 * Results:
2063 * Always 0 2072 * Always 0
2064 * 2073 *
2065 * Side Effects: 2074 * Side Effects:
2066 * A new element is added to the commands list of the node, 2075 * A new element is added to the commands list of the node,
2067 * and the node can be marked as a submake node if the command is 2076 * and the node can be marked as a submake node if the command is
2068 * determined to be that. 2077 * determined to be that.
2069 */ 2078 */
2070static int 2079static int
2071ParseAddCmd(void *gnp, void *cmd) 2080ParseAddCmd(void *gnp, void *cmd)
2072{ 2081{
2073 GNode *gn = (GNode *)gnp; 2082 GNode *gn = (GNode *)gnp;
2074 2083
2075 /* Add to last (ie current) cohort for :: targets */ 2084 /* Add to last (ie current) cohort for :: targets */
2076 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts)) 2085 if ((gn->type & OP_DOUBLEDEP) && !Lst_IsEmpty (gn->cohorts))
2077 gn = (GNode *)Lst_Datum(Lst_Last(gn->cohorts)); 2086 gn = (GNode *)Lst_Datum(Lst_Last(gn->cohorts));
2078 2087
2079 /* if target already supplied, ignore commands */ 2088 /* if target already supplied, ignore commands */
2080 if (!(gn->type & OP_HAS_COMMANDS)) { 2089 if (!(gn->type & OP_HAS_COMMANDS)) {
2081 (void)Lst_AtEnd(gn->commands, cmd); 2090 (void)Lst_AtEnd(gn->commands, cmd);
2082 if (ParseMaybeSubMake(cmd)) 2091 if (ParseMaybeSubMake(cmd))
2083 gn->type |= OP_SUBMAKE; 2092 gn->type |= OP_SUBMAKE;
2084 ParseMark(gn); 2093 ParseMark(gn);
2085 } else { 2094 } else {
2086#ifdef notyet 2095#ifdef notyet
2087 /* XXX: We cannot do this until we fix the tree */ 2096 /* XXX: We cannot do this until we fix the tree */
2088 (void)Lst_AtEnd(gn->commands, cmd); 2097 (void)Lst_AtEnd(gn->commands, cmd);
2089 Parse_Error(PARSE_WARNING, 2098 Parse_Error(PARSE_WARNING,
2090 "overriding commands for target \"%s\"; " 2099 "overriding commands for target \"%s\"; "
2091 "previous commands defined at %s: %d ignored", 2100 "previous commands defined at %s: %d ignored",
2092 gn->name, gn->fname, gn->lineno); 2101 gn->name, gn->fname, gn->lineno);
2093#else 2102#else
2094 Parse_Error(PARSE_WARNING, 2103 Parse_Error(PARSE_WARNING,
2095 "duplicate script for target \"%s\" ignored", 2104 "duplicate script for target \"%s\" ignored",
2096 gn->name); 2105 gn->name);
2097 ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING, 2106 ParseErrorInternal(gn->fname, gn->lineno, PARSE_WARNING,
2098 "using previous script for \"%s\" defined here", 2107 "using previous script for \"%s\" defined here",
2099 gn->name); 2108 gn->name);
2100#endif 2109#endif
2101 } 2110 }
2102 return 0; 2111 return 0;
2103} 2112}
2104 2113
2105/*- 2114/*-
2106 *----------------------------------------------------------------------- 2115 *-----------------------------------------------------------------------
2107 * ParseHasCommands -- 2116 * ParseHasCommands --
2108 * Callback procedure for Parse_File when destroying the list of 2117 * Callback procedure for Parse_File when destroying the list of
2109 * targets on the last dependency line. Marks a target as already 2118 * targets on the last dependency line. Marks a target as already
2110 * having commands if it does, to keep from having shell commands 2119 * having commands if it does, to keep from having shell commands
2111 * on multiple dependency lines. 2120 * on multiple dependency lines.
2112 * 2121 *
2113 * Input: 2122 * Input:
2114 * gnp Node to examine 2123 * gnp Node to examine
2115 * 2124 *
2116 * Results: 2125 * Results:
2117 * None 2126 * None
2118 * 2127 *
2119 * Side Effects: 2128 * Side Effects:
2120 * OP_HAS_COMMANDS may be set for the target. 2129 * OP_HAS_COMMANDS may be set for the target.
2121 * 2130 *
2122 *----------------------------------------------------------------------- 2131 *-----------------------------------------------------------------------
2123 */ 2132 */
2124static void 2133static void
2125ParseHasCommands(void *gnp) 2134ParseHasCommands(void *gnp)
2126{ 2135{
2127 GNode *gn = (GNode *)gnp; 2136 GNode *gn = (GNode *)gnp;
2128 if (!Lst_IsEmpty(gn->commands)) { 2137 if (!Lst_IsEmpty(gn->commands)) {
2129 gn->type |= OP_HAS_COMMANDS; 2138 gn->type |= OP_HAS_COMMANDS;
2130 } 2139 }
2131} 2140}
2132 2141
2133/*- 2142/*-
2134 *----------------------------------------------------------------------- 2143 *-----------------------------------------------------------------------
2135 * Parse_AddIncludeDir -- 2144 * Parse_AddIncludeDir --
2136 * Add a directory to the path searched for included makefiles 2145 * Add a directory to the path searched for included makefiles
2137 * bracketed by double-quotes. Used by functions in main.c 2146 * bracketed by double-quotes. Used by functions in main.c
2138 * 2147 *
2139 * Input: 2148 * Input:
2140 * dir The name of the directory to add 2149 * dir The name of the directory to add
2141 * 2150 *
2142 * Results: 2151 * Results:
2143 * None. 2152 * None.
2144 * 2153 *
2145 * Side Effects: 2154 * Side Effects:
2146 * The directory is appended to the list. 2155 * The directory is appended to the list.
2147 * 2156 *
2148 *----------------------------------------------------------------------- 2157 *-----------------------------------------------------------------------
2149 */ 2158 */
2150void 2159void
2151Parse_AddIncludeDir(char *dir) 2160Parse_AddIncludeDir(char *dir)
2152{ 2161{
2153 (void)Dir_AddDir(parseIncPath, dir); 2162 (void)Dir_AddDir(parseIncPath, dir);
2154} 2163}
2155 2164
2156/*- 2165/*-
2157 *--------------------------------------------------------------------- 2166 *---------------------------------------------------------------------
2158 * ParseDoInclude -- 2167 * ParseDoInclude --
2159 * Push to another file. 2168 * Push to another file.
2160 * 2169 *
2161 * The input is the line minus the `.'. A file spec is a string 2170 * The input is the line minus the `.'. A file spec is a string
2162 * enclosed in <> or "". The former is looked for only in sysIncPath. 2171 * enclosed in <> or "". The former is looked for only in sysIncPath.
2163 * The latter in . and the directories specified by -I command line 2172 * The latter in . and the directories specified by -I command line
2164 * options 2173 * options
2165 * 2174 *
2166 * Results: 2175 * Results:
2167 * None 2176 * None
2168 * 2177 *
2169 * Side Effects: 2178 * Side Effects:
2170 * A structure is added to the includes Lst and readProc, lineno, 2179 * A structure is added to the includes Lst and readProc, lineno,
2171 * fname and curFILE are altered for the new file 2180 * fname and curFILE are altered for the new file
2172 *--------------------------------------------------------------------- 2181 *---------------------------------------------------------------------
2173 */ 2182 */
2174 2183
2175static void 2184static void
2176Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent) 2185Parse_include_file(char *file, Boolean isSystem, Boolean depinc, int silent)
2177{ 2186{
2178 struct loadedfile *lf; 2187 struct loadedfile *lf;
2179 char *fullname; /* full pathname of file */ 2188 char *fullname; /* full pathname of file */
2180 char *newName; 2189 char *newName;
2181 char *prefEnd, *incdir; 2190 char *prefEnd, *incdir;
2182 int fd; 2191 int fd;
2183 int i; 2192 int i;
2184 2193
2185 /* 2194 /*
2186 * Now we know the file's name and its search path, we attempt to 2195 * Now we know the file's name and its search path, we attempt to
2187 * find the durn thing. A return of NULL indicates the file don't 2196 * find the durn thing. A return of NULL indicates the file don't
2188 * exist. 2197 * exist.
2189 */ 2198 */
2190 fullname = file[0] == '/' ? bmake_strdup(file) : NULL; 2199 fullname = file[0] == '/' ? bmake_strdup(file) : NULL;
2191 2200
2192 if (fullname == NULL && !isSystem) { 2201 if (fullname == NULL && !isSystem) {
2193 /* 2202 /*
2194 * Include files contained in double-quotes are first searched for 2203 * Include files contained in double-quotes are first searched for
2195 * relative to the including file's location. We don't want to 2204 * relative to the including file's location. We don't want to
2196 * cd there, of course, so we just tack on the old file's 2205 * cd there, of course, so we just tack on the old file's
2197 * leading path components and call Dir_FindFile to see if 2206 * leading path components and call Dir_FindFile to see if
2198 * we can locate the beast. 2207 * we can locate the beast.
2199 */ 2208 */
2200 2209
2201 incdir = bmake_strdup(curFile->fname); 2210 incdir = bmake_strdup(curFile->fname);
2202 prefEnd = strrchr(incdir, '/'); 2211 prefEnd = strrchr(incdir, '/');
2203 if (prefEnd != NULL) { 2212 if (prefEnd != NULL) {
2204 *prefEnd = '\0'; 2213 *prefEnd = '\0';
2205 /* Now do lexical processing of leading "../" on the filename */ 2214 /* Now do lexical processing of leading "../" on the filename */
2206 for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) { 2215 for (i = 0; strncmp(file + i, "../", 3) == 0; i += 3) {
2207 prefEnd = strrchr(incdir + 1, '/'); 2216 prefEnd = strrchr(incdir + 1, '/');
2208 if (prefEnd == NULL || strcmp(prefEnd, "/..") == 0) 2217 if (prefEnd == NULL || strcmp(prefEnd, "/..") == 0)
2209 break; 2218 break;
2210 *prefEnd = '\0'; 2219 *prefEnd = '\0';
2211 } 2220 }
2212 newName = str_concat(incdir, file + i, STR_ADDSLASH); 2221 newName = str_concat(incdir, file + i, STR_ADDSLASH);
2213 fullname = Dir_FindFile(newName, parseIncPath); 2222 fullname = Dir_FindFile(newName, parseIncPath);
2214 if (fullname == NULL) 2223 if (fullname == NULL)
2215 fullname = Dir_FindFile(newName, dirSearchPath); 2224 fullname = Dir_FindFile(newName, dirSearchPath);
2216 free(newName); 2225 free(newName);
2217 } 2226 }
2218 free(incdir); 2227 free(incdir);
2219 2228
2220 if (fullname == NULL) { 2229 if (fullname == NULL) {
2221 /* 2230 /*
2222 * Makefile wasn't found in same directory as included makefile. 2231 * Makefile wasn't found in same directory as included makefile.
2223 * Search for it first on the -I search path, 2232 * Search for it first on the -I search path,
2224 * then on the .PATH search path, if not found in a -I directory. 2233 * then on the .PATH search path, if not found in a -I directory.
2225 * If we have a suffix specific path we should use that. 2234 * If we have a suffix specific path we should use that.
2226 */ 2235 */
2227 char *suff; 2236 char *suff;
2228 Lst suffPath = NULL; 2237 Lst suffPath = NULL;
2229 2238
2230 if ((suff = strrchr(file, '.'))) { 2239 if ((suff = strrchr(file, '.'))) {
2231 suffPath = Suff_GetPath(suff); 2240 suffPath = Suff_GetPath(suff);
2232 if (suffPath != NULL) { 2241 if (suffPath != NULL) {
2233 fullname = Dir_FindFile(file, suffPath); 2242 fullname = Dir_FindFile(file, suffPath);
2234 } 2243 }
2235 } 2244 }
2236 if (fullname == NULL) { 2245 if (fullname == NULL) {
2237 fullname = Dir_FindFile(file, parseIncPath); 2246 fullname = Dir_FindFile(file, parseIncPath);
2238 if (fullname == NULL) { 2247 if (fullname == NULL) {
2239 fullname = Dir_FindFile(file, dirSearchPath); 2248 fullname = Dir_FindFile(file, dirSearchPath);
2240 } 2249 }
2241 } 2250 }
2242 } 2251 }
2243 } 2252 }
2244 2253
2245 /* Looking for a system file or file still not found */ 2254 /* Looking for a system file or file still not found */
2246 if (fullname == NULL) { 2255 if (fullname == NULL) {
2247 /* 2256 /*
2248 * Look for it on the system path 2257 * Look for it on the system path
2249 */ 2258 */
2250 fullname = Dir_FindFile(file, 2259 fullname = Dir_FindFile(file,
2251 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); 2260 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
2252 } 2261 }
2253 2262
2254 if (fullname == NULL) { 2263 if (fullname == NULL) {
2255 if (!silent) 2264 if (!silent)
2256 Parse_Error(PARSE_FATAL, "Could not find %s", file); 2265 Parse_Error(PARSE_FATAL, "Could not find %s", file);
2257 return; 2266 return;
2258 } 2267 }
2259 2268
2260 /* Actually open the file... */ 2269 /* Actually open the file... */
2261 fd = open(fullname, O_RDONLY); 2270 fd = open(fullname, O_RDONLY);
2262 if (fd == -1) { 2271 if (fd == -1) {
2263 if (!silent) 2272 if (!silent)
2264 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname); 2273 Parse_Error(PARSE_FATAL, "Cannot open %s", fullname);
2265 free(fullname); 2274 free(fullname);
2266 return; 2275 return;
2267 } 2276 }
2268 2277
2269 /* load it */ 2278 /* load it */
2270 lf = loadfile(fullname, fd); 2279 lf = loadfile(fullname, fd);
2271 2280
2272 ParseSetIncludedFile(); 2281 ParseSetIncludedFile();
2273 /* Start reading from this file next */ 2282 /* Start reading from this file next */
2274 Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf); 2283 Parse_SetInput(fullname, 0, -1, loadedfile_nextbuf, lf);
2275 curFile->lf = lf; 2284 curFile->lf = lf;
2276 if (depinc) 2285 if (depinc)
2277 doing_depend = depinc; /* only turn it on */ 2286 doing_depend = depinc; /* only turn it on */
2278} 2287}
2279 2288
2280static void 2289static void
2281ParseDoInclude(char *line) 2290ParseDoInclude(char *line)
2282{ 2291{
2283 char endc; /* the character which ends the file spec */ 2292 char endc; /* the character which ends the file spec */
2284 char *cp; /* current position in file spec */ 2293 char *cp; /* current position in file spec */
2285 int silent = (*line != 'i') ? 1 : 0; 2294 int silent = (*line != 'i') ? 1 : 0;
2286 char *file = &line[7 + silent]; 2295 char *file = &line[7 + silent];
2287 2296
2288 /* Skip to delimiter character so we know where to look */ 2297 /* Skip to delimiter character so we know where to look */
2289 while (*file == ' ' || *file == '\t') 2298 while (*file == ' ' || *file == '\t')
2290 file++; 2299 file++;
2291 2300

cvs diff -r1.2 -r1.3 src/usr.bin/make/unit-tests/Attic/directives.exp (switch to unified diff)

--- src/usr.bin/make/unit-tests/Attic/directives.exp 2020/07/28 17:47:57 1.2
+++ src/usr.bin/make/unit-tests/Attic/directives.exp 2020/07/28 18:15:11 1.3
@@ -1,37 +1,37 @@ @@ -1,37 +1,37 @@
1make: "directives.mk" line 10: begin .export tests 1make: "directives.mk" line 10: begin .export tests
2make: "directives.mk" line 11: Unknown directive 2make: "directives.mk" line 11: Unknown directive "expor"
3make: "directives.mk" line 20: begin .export-env tests 3make: "directives.mk" line 20: begin .export-env tests
4make: "directives.mk" line 30: begin .export-literal tests 4make: "directives.mk" line 30: begin .export-literal tests
5make: "directives.mk" line 40: begin .info tests 5make: "directives.mk" line 40: begin .info tests
6make: "directives.mk" line 41: Unknown directive 6make: "directives.mk" line 41: Unknown directive "inf"
7make: "directives.mk" line 42: Unknown directive 7make: "directives.mk" line 42: Unknown directive "info"
8make: "directives.mk" line 43: message 8make: "directives.mk" line 43: message
9make: "directives.mk" line 44: indented message 9make: "directives.mk" line 44: indented message
10make: "directives.mk" line 45: Unknown directive 10make: "directives.mk" line 45: Unknown directive "information"
11make: "directives.mk" line 46: message 11make: "directives.mk" line 46: message
12make: "directives.mk" line 50: begin .undef tests 12make: "directives.mk" line 50: begin .undef tests
13make: "directives.mk" line 51: Unknown directive 13make: "directives.mk" line 51: Unknown directive "unde"
14make: "directives.mk" line 60: begin .unexport tests 14make: "directives.mk" line 60: begin .unexport tests
15make: "directives.mk" line 61: Unknown directive 15make: "directives.mk" line 61: Unknown directive "unexpor"
16make: "directives.mk" line 70: begin .unexport-env tests 16make: "directives.mk" line 70: begin .unexport-env tests
17make: "directives.mk" line 80: begin .warning tests 17make: "directives.mk" line 80: begin .warning tests
18make: "directives.mk" line 81: Unknown directive 18make: "directives.mk" line 81: Unknown directive "warn"
19make: "directives.mk" line 82: Unknown directive 19make: "directives.mk" line 82: Unknown directive "warnin"
20make: "directives.mk" line 83: Unknown directive 20make: "directives.mk" line 83: Unknown directive "warning"
21make: "directives.mk" line 84: warning: message 21make: "directives.mk" line 84: warning: message
22make: "directives.mk" line 85: Unknown directive 22make: "directives.mk" line 85: Unknown directive "warnings"
23make: "directives.mk" line 86: warning: messages 23make: "directives.mk" line 86: warning: messages
24make: "directives.mk" line 90: begin .elif misspellings tests, part 1 24make: "directives.mk" line 90: begin .elif misspellings tests, part 1
25make: "directives.mk" line 100: begin .elif misspellings tests, part 2 25make: "directives.mk" line 100: begin .elif misspellings tests, part 2
26make: "directives.mk" line 110: begin .elif misspellings tests, part 3 26make: "directives.mk" line 110: begin .elif misspellings tests, part 3
27make: "directives.mk" line 120: which branch is taken on misspelling after false? 27make: "directives.mk" line 120: which branch is taken on misspelling after false?
28make: "directives.mk" line 127: else taken 28make: "directives.mk" line 127: else taken
29make: "directives.mk" line 130: which branch is taken on misspelling after true? 29make: "directives.mk" line 130: which branch is taken on misspelling after true?
30make: "directives.mk" line 132: Unknown directive 30make: "directives.mk" line 132: Unknown directive "elsif"
31make: "directives.mk" line 133: 1 taken 31make: "directives.mk" line 133: 1 taken
32make: "directives.mk" line 134: Unknown directive 32make: "directives.mk" line 134: Unknown directive "elsif"
33make: "directives.mk" line 135: 2 taken 33make: "directives.mk" line 135: 2 taken
34make: "directives.mk" line 140: end of the tests 34make: "directives.mk" line 140: end of the tests
35make: Fatal errors encountered -- cannot continue 35make: Fatal errors encountered -- cannot continue
36make: stopped in unit-tests 36make: stopped in unit-tests
37exit status 1 37exit status 1