Sat Aug 29 07:05:12 2020 UTC ()
make(1): rename confusing function ReadAllMakefiles

The old name implied that the function would read multiple files, which
was not the case.

The comment above that function was highly confusing.  It's not that the
function returns a boolean, but rather 0 or non-zero, and 0 means that
Lst_Find should stop searching.

One of the next refactorings will be to make Lst_Find return the first
list node for which the function returns TRUE.  This will reduce the
confusion about the several functions called SomethingP in suff.c.  The
P suffix means to return TRUE or FALSE, not 0 or non-zero.


(rillig)
diff -r1.320 -r1.321 src/usr.bin/make/main.c

cvs diff -r1.320 -r1.321 src/usr.bin/make/main.c (switch to unified diff)

--- src/usr.bin/make/main.c 2020/08/28 04:48:57 1.320
+++ src/usr.bin/make/main.c 2020/08/29 07:05:12 1.321
@@ -1,2200 +1,2189 @@ @@ -1,2200 +1,2189 @@
1/* $NetBSD: main.c,v 1.320 2020/08/28 04:48:57 rillig Exp $ */ 1/* $NetBSD: main.c,v 1.321 2020/08/29 07:05:12 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: main.c,v 1.320 2020/08/28 04:48:57 rillig Exp $"; 72static char rcsid[] = "$NetBSD: main.c,v 1.321 2020/08/29 07:05:12 rillig Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ 76__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
77 The Regents of the University of California. All rights reserved."); 77 The Regents of the University of California. All rights reserved.");
78#endif /* not lint */ 78#endif /* not lint */
79 79
80#ifndef lint 80#ifndef lint
81#if 0 81#if 0
82static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 82static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
83#else 83#else
84__RCSID("$NetBSD: main.c,v 1.320 2020/08/28 04:48:57 rillig Exp $"); 84__RCSID("$NetBSD: main.c,v 1.321 2020/08/29 07:05:12 rillig Exp $");
85#endif 85#endif
86#endif /* not lint */ 86#endif /* not lint */
87#endif 87#endif
88 88
89/*- 89/*-
90 * main.c -- 90 * main.c --
91 * The main file for this entire program. Exit routines etc 91 * The main file for this entire program. Exit routines etc
92 * reside here. 92 * reside here.
93 * 93 *
94 * Utility functions defined in this file: 94 * Utility functions defined in this file:
95 * Main_ParseArgLine Takes a line of arguments, breaks them and 95 * Main_ParseArgLine Takes a line of arguments, breaks them and
96 * treats them as if they were given when first 96 * treats them as if they were given when first
97 * invoked. Used by the parse module to implement 97 * invoked. Used by the parse module to implement
98 * the .MFLAGS target. 98 * the .MFLAGS target.
99 * 99 *
100 * Error Print a tagged error message. The global 100 * Error Print a tagged error message. The global
101 * MAKE variable must have been defined. This 101 * MAKE variable must have been defined. This
102 * takes a format string and optional arguments 102 * takes a format string and optional arguments
103 * for it. 103 * for it.
104 * 104 *
105 * Fatal Print an error message and exit. Also takes 105 * Fatal Print an error message and exit. Also takes
106 * a format string and arguments for it. 106 * a format string and arguments for it.
107 * 107 *
108 * Punt Aborts all jobs and exits with a message. Also 108 * Punt Aborts all jobs and exits with a message. Also
109 * takes a format string and arguments for it. 109 * takes a format string and arguments for it.
110 * 110 *
111 * Finish Finish things up by printing the number of 111 * Finish Finish things up by printing the number of
112 * errors which occurred, as passed to it, and 112 * errors which occurred, as passed to it, and
113 * exiting. 113 * exiting.
114 */ 114 */
115 115
116#include <sys/types.h> 116#include <sys/types.h>
117#include <sys/time.h> 117#include <sys/time.h>
118#include <sys/param.h> 118#include <sys/param.h>
119#include <sys/resource.h> 119#include <sys/resource.h>
120#include <sys/stat.h> 120#include <sys/stat.h>
121#ifdef MAKE_NATIVE 121#ifdef MAKE_NATIVE
122#include <sys/sysctl.h> 122#include <sys/sysctl.h>
123#endif 123#endif
124#include <sys/utsname.h> 124#include <sys/utsname.h>
125#include <sys/wait.h> 125#include <sys/wait.h>
126 126
127#include <ctype.h> 127#include <ctype.h>
128#include <errno.h> 128#include <errno.h>
129#include <signal.h> 129#include <signal.h>
130#include <stdarg.h> 130#include <stdarg.h>
131#include <stdio.h> 131#include <stdio.h>
132#include <stdlib.h> 132#include <stdlib.h>
133#include <time.h> 133#include <time.h>
134 134
135#include "make.h" 135#include "make.h"
136#include "hash.h" 136#include "hash.h"
137#include "dir.h" 137#include "dir.h"
138#include "job.h" 138#include "job.h"
139#include "pathnames.h" 139#include "pathnames.h"
140#include "trace.h" 140#include "trace.h"
141 141
142#ifdef USE_IOVEC 142#ifdef USE_IOVEC
143#include <sys/uio.h> 143#include <sys/uio.h>
144#endif 144#endif
145 145
146#ifndef DEFMAXLOCAL 146#ifndef DEFMAXLOCAL
147#define DEFMAXLOCAL DEFMAXJOBS 147#define DEFMAXLOCAL DEFMAXJOBS
148#endif /* DEFMAXLOCAL */ 148#endif /* DEFMAXLOCAL */
149 149
150Lst create; /* Targets to be made */ 150Lst create; /* Targets to be made */
151time_t now; /* Time at start of make */ 151time_t now; /* Time at start of make */
152GNode *DEFAULT; /* .DEFAULT node */ 152GNode *DEFAULT; /* .DEFAULT node */
153Boolean allPrecious; /* .PRECIOUS given on line by itself */ 153Boolean allPrecious; /* .PRECIOUS given on line by itself */
154Boolean deleteOnError; /* .DELETE_ON_ERROR: set */ 154Boolean deleteOnError; /* .DELETE_ON_ERROR: set */
155 155
156static Boolean noBuiltins; /* -r flag */ 156static Boolean noBuiltins; /* -r flag */
157static Lst makefiles; /* ordered list of makefiles to read */ 157static Lst makefiles; /* ordered list of makefiles to read */
158static int printVars; /* -[vV] argument */ 158static int printVars; /* -[vV] argument */
159#define COMPAT_VARS 1 159#define COMPAT_VARS 1
160#define EXPAND_VARS 2 160#define EXPAND_VARS 2
161static Lst variables; /* list of variables to print */ 161static Lst variables; /* list of variables to print */
162int maxJobs; /* -j argument */ 162int maxJobs; /* -j argument */
163static int maxJobTokens; /* -j argument */ 163static int maxJobTokens; /* -j argument */
164Boolean compatMake; /* -B argument */ 164Boolean compatMake; /* -B argument */
165int debug; /* -d argument */ 165int debug; /* -d argument */
166Boolean debugVflag; /* -dV */ 166Boolean debugVflag; /* -dV */
167Boolean noExecute; /* -n flag */ 167Boolean noExecute; /* -n flag */
168Boolean noRecursiveExecute; /* -N flag */ 168Boolean noRecursiveExecute; /* -N flag */
169Boolean keepgoing; /* -k flag */ 169Boolean keepgoing; /* -k flag */
170Boolean queryFlag; /* -q flag */ 170Boolean queryFlag; /* -q flag */
171Boolean touchFlag; /* -t flag */ 171Boolean touchFlag; /* -t flag */
172Boolean enterFlag; /* -w flag */ 172Boolean enterFlag; /* -w flag */
173Boolean enterFlagObj; /* -w and objdir != srcdir */ 173Boolean enterFlagObj; /* -w and objdir != srcdir */
174Boolean ignoreErrors; /* -i flag */ 174Boolean ignoreErrors; /* -i flag */
175Boolean beSilent; /* -s flag */ 175Boolean beSilent; /* -s flag */
176Boolean oldVars; /* variable substitution style */ 176Boolean oldVars; /* variable substitution style */
177Boolean checkEnvFirst; /* -e flag */ 177Boolean checkEnvFirst; /* -e flag */
178Boolean parseWarnFatal; /* -W flag */ 178Boolean parseWarnFatal; /* -W flag */
179static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */ 179static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
180Boolean varNoExportEnv; /* -X flag */ 180Boolean varNoExportEnv; /* -X flag */
181Boolean doing_depend; /* Set while reading .depend */ 181Boolean doing_depend; /* Set while reading .depend */
182static Boolean jobsRunning; /* TRUE if the jobs might be running */ 182static Boolean jobsRunning; /* TRUE if the jobs might be running */
183static const char * tracefile; 183static const char * tracefile;
184static void MainParseArgs(int, char **); 184static void MainParseArgs(int, char **);
185static int ReadMakefile(const void *, const void *); 185static int ReadMakefile(const void *, const void *);
186static void usage(void) MAKE_ATTR_DEAD; 186static void usage(void) MAKE_ATTR_DEAD;
187static void purge_cached_realpaths(void); 187static void purge_cached_realpaths(void);
188 188
189static Boolean ignorePWD; /* if we use -C, PWD is meaningless */ 189static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
190static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */ 190static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
191char curdir[MAXPATHLEN + 1]; /* Startup directory */ 191char curdir[MAXPATHLEN + 1]; /* Startup directory */
192char *progname; /* the program name */ 192char *progname; /* the program name */
193char *makeDependfile; 193char *makeDependfile;
194pid_t myPid; 194pid_t myPid;
195int makelevel; 195int makelevel;
196 196
197FILE *debug_file; 197FILE *debug_file;
198 198
199Boolean forceJobs = FALSE; 199Boolean forceJobs = FALSE;
200 200
201extern Lst parseIncPath; 201extern Lst parseIncPath;
202 202
203/* 203/*
204 * For compatibility with the POSIX version of MAKEFLAGS that includes 204 * For compatibility with the POSIX version of MAKEFLAGS that includes
205 * all the options with out -, convert flags to -f -l -a -g -s. 205 * all the options with out -, convert flags to -f -l -a -g -s.
206 */ 206 */
207static char * 207static char *
208explode(const char *flags) 208explode(const char *flags)
209{ 209{
210 size_t len; 210 size_t len;
211 char *nf, *st; 211 char *nf, *st;
212 const char *f; 212 const char *f;
213 213
214 if (flags == NULL) 214 if (flags == NULL)
215 return NULL; 215 return NULL;
216 216
217 for (f = flags; *f; f++) 217 for (f = flags; *f; f++)
218 if (!isalpha((unsigned char)*f)) 218 if (!isalpha((unsigned char)*f))
219 break; 219 break;
220 220
221 if (*f) 221 if (*f)
222 return bmake_strdup(flags); 222 return bmake_strdup(flags);
223 223
224 len = strlen(flags); 224 len = strlen(flags);
225 st = nf = bmake_malloc(len * 3 + 1); 225 st = nf = bmake_malloc(len * 3 + 1);
226 while (*flags) { 226 while (*flags) {
227 *nf++ = '-'; 227 *nf++ = '-';
228 *nf++ = *flags++; 228 *nf++ = *flags++;
229 *nf++ = ' '; 229 *nf++ = ' ';
230 } 230 }
231 *nf = '\0'; 231 *nf = '\0';
232 return st; 232 return st;
233} 233}
234 234
235static void 235static void
236parse_debug_options(const char *argvalue) 236parse_debug_options(const char *argvalue)
237{ 237{
238 const char *modules; 238 const char *modules;
239 const char *mode; 239 const char *mode;
240 char *fname; 240 char *fname;
241 int len; 241 int len;
242 242
243 for (modules = argvalue; *modules; ++modules) { 243 for (modules = argvalue; *modules; ++modules) {
244 switch (*modules) { 244 switch (*modules) {
245 case 'A': 245 case 'A':
246 debug = ~(0|DEBUG_LINT); 246 debug = ~(0|DEBUG_LINT);
247 break; 247 break;
248 case 'a': 248 case 'a':
249 debug |= DEBUG_ARCH; 249 debug |= DEBUG_ARCH;
250 break; 250 break;
251 case 'C': 251 case 'C':
252 debug |= DEBUG_CWD; 252 debug |= DEBUG_CWD;
253 break; 253 break;
254 case 'c': 254 case 'c':
255 debug |= DEBUG_COND; 255 debug |= DEBUG_COND;
256 break; 256 break;
257 case 'd': 257 case 'd':
258 debug |= DEBUG_DIR; 258 debug |= DEBUG_DIR;
259 break; 259 break;
260 case 'e': 260 case 'e':
261 debug |= DEBUG_ERROR; 261 debug |= DEBUG_ERROR;
262 break; 262 break;
263 case 'f': 263 case 'f':
264 debug |= DEBUG_FOR; 264 debug |= DEBUG_FOR;
265 break; 265 break;
266 case 'g': 266 case 'g':
267 if (modules[1] == '1') { 267 if (modules[1] == '1') {
268 debug |= DEBUG_GRAPH1; 268 debug |= DEBUG_GRAPH1;
269 ++modules; 269 ++modules;
270 } 270 }
271 else if (modules[1] == '2') { 271 else if (modules[1] == '2') {
272 debug |= DEBUG_GRAPH2; 272 debug |= DEBUG_GRAPH2;
273 ++modules; 273 ++modules;
274 } 274 }
275 else if (modules[1] == '3') { 275 else if (modules[1] == '3') {
276 debug |= DEBUG_GRAPH3; 276 debug |= DEBUG_GRAPH3;
277 ++modules; 277 ++modules;
278 } 278 }
279 break; 279 break;
280 case 'h': 280 case 'h':
281 debug |= DEBUG_HASH; 281 debug |= DEBUG_HASH;
282 break; 282 break;
283 case 'j': 283 case 'j':
284 debug |= DEBUG_JOB; 284 debug |= DEBUG_JOB;
285 break; 285 break;
286 case 'L': 286 case 'L':
287 debug |= DEBUG_LINT; 287 debug |= DEBUG_LINT;
288 break; 288 break;
289 case 'l': 289 case 'l':
290 debug |= DEBUG_LOUD; 290 debug |= DEBUG_LOUD;
291 break; 291 break;
292 case 'M': 292 case 'M':
293 debug |= DEBUG_META; 293 debug |= DEBUG_META;
294 break; 294 break;
295 case 'm': 295 case 'm':
296 debug |= DEBUG_MAKE; 296 debug |= DEBUG_MAKE;
297 break; 297 break;
298 case 'n': 298 case 'n':
299 debug |= DEBUG_SCRIPT; 299 debug |= DEBUG_SCRIPT;
300 break; 300 break;
301 case 'p': 301 case 'p':
302 debug |= DEBUG_PARSE; 302 debug |= DEBUG_PARSE;
303 break; 303 break;
304 case 's': 304 case 's':
305 debug |= DEBUG_SUFF; 305 debug |= DEBUG_SUFF;
306 break; 306 break;
307 case 't': 307 case 't':
308 debug |= DEBUG_TARG; 308 debug |= DEBUG_TARG;
309 break; 309 break;
310 case 'V': 310 case 'V':
311 debugVflag = TRUE; 311 debugVflag = TRUE;
312 break; 312 break;
313 case 'v': 313 case 'v':
314 debug |= DEBUG_VAR; 314 debug |= DEBUG_VAR;
315 break; 315 break;
316 case 'x': 316 case 'x':
317 debug |= DEBUG_SHELL; 317 debug |= DEBUG_SHELL;
318 break; 318 break;
319 case 'F': 319 case 'F':
320 if (debug_file != stdout && debug_file != stderr) 320 if (debug_file != stdout && debug_file != stderr)
321 fclose(debug_file); 321 fclose(debug_file);
322 if (*++modules == '+') { 322 if (*++modules == '+') {
323 modules++; 323 modules++;
324 mode = "a"; 324 mode = "a";
325 } else 325 } else
326 mode = "w"; 326 mode = "w";
327 if (strcmp(modules, "stdout") == 0) { 327 if (strcmp(modules, "stdout") == 0) {
328 debug_file = stdout; 328 debug_file = stdout;
329 goto debug_setbuf; 329 goto debug_setbuf;
330 } 330 }
331 if (strcmp(modules, "stderr") == 0) { 331 if (strcmp(modules, "stderr") == 0) {
332 debug_file = stderr; 332 debug_file = stderr;
333 goto debug_setbuf; 333 goto debug_setbuf;
334 } 334 }
335 len = strlen(modules); 335 len = strlen(modules);
336 fname = bmake_malloc(len + 20); 336 fname = bmake_malloc(len + 20);
337 memcpy(fname, modules, len + 1); 337 memcpy(fname, modules, len + 1);
338 /* Let the filename be modified by the pid */ 338 /* Let the filename be modified by the pid */
339 if (strcmp(fname + len - 3, ".%d") == 0) 339 if (strcmp(fname + len - 3, ".%d") == 0)
340 snprintf(fname + len - 2, 20, "%d", getpid()); 340 snprintf(fname + len - 2, 20, "%d", getpid());
341 debug_file = fopen(fname, mode); 341 debug_file = fopen(fname, mode);
342 if (!debug_file) { 342 if (!debug_file) {
343 fprintf(stderr, "Cannot open debug file %s\n", 343 fprintf(stderr, "Cannot open debug file %s\n",
344 fname); 344 fname);
345 usage(); 345 usage();
346 } 346 }
347 free(fname); 347 free(fname);
348 goto debug_setbuf; 348 goto debug_setbuf;
349 default: 349 default:
350 (void)fprintf(stderr, 350 (void)fprintf(stderr,
351 "%s: illegal argument to d option -- %c\n", 351 "%s: illegal argument to d option -- %c\n",
352 progname, *modules); 352 progname, *modules);
353 usage(); 353 usage();
354 } 354 }
355 } 355 }
356debug_setbuf: 356debug_setbuf:
357 /* 357 /*
358 * Make the debug_file unbuffered, and make 358 * Make the debug_file unbuffered, and make
359 * stdout line buffered (unless debugfile == stdout). 359 * stdout line buffered (unless debugfile == stdout).
360 */ 360 */
361 setvbuf(debug_file, NULL, _IONBF, 0); 361 setvbuf(debug_file, NULL, _IONBF, 0);
362 if (debug_file != stdout) { 362 if (debug_file != stdout) {
363 setvbuf(stdout, NULL, _IOLBF, 0); 363 setvbuf(stdout, NULL, _IOLBF, 0);
364 } 364 }
365} 365}
366 366
367/* 367/*
368 * does path contain any relative components 368 * does path contain any relative components
369 */ 369 */
370static Boolean 370static Boolean
371is_relpath(const char *path) 371is_relpath(const char *path)
372{ 372{
373 const char *cp; 373 const char *cp;
374 374
375 if (path[0] != '/') 375 if (path[0] != '/')
376 return TRUE; 376 return TRUE;
377 cp = path; 377 cp = path;
378 while ((cp = strstr(cp, "/.")) != NULL) { 378 while ((cp = strstr(cp, "/.")) != NULL) {
379 cp += 2; 379 cp += 2;
380 if (cp[0] == '/' || cp[0] == '\0') 380 if (cp[0] == '/' || cp[0] == '\0')
381 return TRUE; 381 return TRUE;
382 else if (cp[0] == '.') { 382 else if (cp[0] == '.') {
383 if (cp[1] == '/' || cp[1] == '\0') 383 if (cp[1] == '/' || cp[1] == '\0')
384 return TRUE; 384 return TRUE;
385 } 385 }
386 } 386 }
387 return FALSE; 387 return FALSE;
388} 388}
389 389
390/*- 390/*-
391 * MainParseArgs -- 391 * MainParseArgs --
392 * Parse a given argument vector. Called from main() and from 392 * Parse a given argument vector. Called from main() and from
393 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 393 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
394 * 394 *
395 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 395 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
396 * 396 *
397 * Results: 397 * Results:
398 * None 398 * None
399 * 399 *
400 * Side Effects: 400 * Side Effects:
401 * Various global and local flags will be set depending on the flags 401 * Various global and local flags will be set depending on the flags
402 * given 402 * given
403 */ 403 */
404static void 404static void
405MainParseArgs(int argc, char **argv) 405MainParseArgs(int argc, char **argv)
406{ 406{
407 char *p; 407 char *p;
408 int c = '?'; 408 int c = '?';
409 int arginc; 409 int arginc;
410 char *argvalue; 410 char *argvalue;
411 const char *getopt_def; 411 const char *getopt_def;
412 struct stat sa, sb; 412 struct stat sa, sb;
413 char *optscan; 413 char *optscan;
414 Boolean inOption, dashDash = FALSE; 414 Boolean inOption, dashDash = FALSE;
415 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ 415 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
416 416
417#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w" 417#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w"
418/* Can't actually use getopt(3) because rescanning is not portable */ 418/* Can't actually use getopt(3) because rescanning is not portable */
419 419
420 getopt_def = OPTFLAGS; 420 getopt_def = OPTFLAGS;
421rearg: 421rearg:
422 inOption = FALSE; 422 inOption = FALSE;
423 optscan = NULL; 423 optscan = NULL;
424 while(argc > 1) { 424 while(argc > 1) {
425 char *getopt_spec; 425 char *getopt_spec;
426 if(!inOption) 426 if(!inOption)
427 optscan = argv[1]; 427 optscan = argv[1];
428 c = *optscan++; 428 c = *optscan++;
429 arginc = 0; 429 arginc = 0;
430 if(inOption) { 430 if(inOption) {
431 if(c == '\0') { 431 if(c == '\0') {
432 ++argv; 432 ++argv;
433 --argc; 433 --argc;
434 inOption = FALSE; 434 inOption = FALSE;
435 continue; 435 continue;
436 } 436 }
437 } else { 437 } else {
438 if (c != '-' || dashDash) 438 if (c != '-' || dashDash)
439 break; 439 break;
440 inOption = TRUE; 440 inOption = TRUE;
441 c = *optscan++; 441 c = *optscan++;
442 } 442 }
443 /* '-' found at some earlier point */ 443 /* '-' found at some earlier point */
444 getopt_spec = strchr(getopt_def, c); 444 getopt_spec = strchr(getopt_def, c);
445 if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') { 445 if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
446 /* -<something> found, and <something> should have an arg */ 446 /* -<something> found, and <something> should have an arg */
447 inOption = FALSE; 447 inOption = FALSE;
448 arginc = 1; 448 arginc = 1;
449 argvalue = optscan; 449 argvalue = optscan;
450 if(*argvalue == '\0') { 450 if(*argvalue == '\0') {
451 if (argc < 3) 451 if (argc < 3)
452 goto noarg; 452 goto noarg;
453 argvalue = argv[2]; 453 argvalue = argv[2];
454 arginc = 2; 454 arginc = 2;
455 } 455 }
456 } else { 456 } else {
457 argvalue = NULL; 457 argvalue = NULL;
458 } 458 }
459 switch(c) { 459 switch(c) {
460 case '\0': 460 case '\0':
461 arginc = 1; 461 arginc = 1;
462 inOption = FALSE; 462 inOption = FALSE;
463 break; 463 break;
464 case 'B': 464 case 'B':
465 compatMake = TRUE; 465 compatMake = TRUE;
466 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); 466 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
467 Var_Set(MAKE_MODE, "compat", VAR_GLOBAL); 467 Var_Set(MAKE_MODE, "compat", VAR_GLOBAL);
468 break; 468 break;
469 case 'C': 469 case 'C':
470 if (chdir(argvalue) == -1) { 470 if (chdir(argvalue) == -1) {
471 (void)fprintf(stderr, 471 (void)fprintf(stderr,
472 "%s: chdir %s: %s\n", 472 "%s: chdir %s: %s\n",
473 progname, argvalue, 473 progname, argvalue,
474 strerror(errno)); 474 strerror(errno));
475 exit(1); 475 exit(1);
476 } 476 }
477 if (getcwd(curdir, MAXPATHLEN) == NULL) { 477 if (getcwd(curdir, MAXPATHLEN) == NULL) {
478 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno)); 478 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
479 exit(2); 479 exit(2);
480 } 480 }
481 if (!is_relpath(argvalue) && 481 if (!is_relpath(argvalue) &&
482 stat(argvalue, &sa) != -1 && 482 stat(argvalue, &sa) != -1 &&
483 stat(curdir, &sb) != -1 && 483 stat(curdir, &sb) != -1 &&
484 sa.st_ino == sb.st_ino && 484 sa.st_ino == sb.st_ino &&
485 sa.st_dev == sb.st_dev) 485 sa.st_dev == sb.st_dev)
486 strncpy(curdir, argvalue, MAXPATHLEN); 486 strncpy(curdir, argvalue, MAXPATHLEN);
487 ignorePWD = TRUE; 487 ignorePWD = TRUE;
488 break; 488 break;
489 case 'D': 489 case 'D':
490 if (argvalue == NULL || argvalue[0] == 0) goto noarg; 490 if (argvalue == NULL || argvalue[0] == 0) goto noarg;
491 Var_Set(argvalue, "1", VAR_GLOBAL); 491 Var_Set(argvalue, "1", VAR_GLOBAL);
492 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 492 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
493 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 493 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
494 break; 494 break;
495 case 'I': 495 case 'I':
496 if (argvalue == NULL) goto noarg; 496 if (argvalue == NULL) goto noarg;
497 Parse_AddIncludeDir(argvalue); 497 Parse_AddIncludeDir(argvalue);
498 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 498 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
499 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 499 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
500 break; 500 break;
501 case 'J': 501 case 'J':
502 if (argvalue == NULL) goto noarg; 502 if (argvalue == NULL) goto noarg;
503 if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) { 503 if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
504 (void)fprintf(stderr, 504 (void)fprintf(stderr,
505 "%s: internal error -- J option malformed (%s)\n", 505 "%s: internal error -- J option malformed (%s)\n",
506 progname, argvalue); 506 progname, argvalue);
507 usage(); 507 usage();
508 } 508 }
509 if ((fcntl(jp_0, F_GETFD, 0) < 0) || 509 if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
510 (fcntl(jp_1, F_GETFD, 0) < 0)) { 510 (fcntl(jp_1, F_GETFD, 0) < 0)) {
511#if 0 511#if 0
512 (void)fprintf(stderr, 512 (void)fprintf(stderr,
513 "%s: ###### warning -- J descriptors were closed!\n", 513 "%s: ###### warning -- J descriptors were closed!\n",
514 progname); 514 progname);
515 exit(2); 515 exit(2);
516#endif 516#endif
517 jp_0 = -1; 517 jp_0 = -1;
518 jp_1 = -1; 518 jp_1 = -1;
519 compatMake = TRUE; 519 compatMake = TRUE;
520 } else { 520 } else {
521 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); 521 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
522 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 522 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
523 } 523 }
524 break; 524 break;
525 case 'N': 525 case 'N':
526 noExecute = TRUE; 526 noExecute = TRUE;
527 noRecursiveExecute = TRUE; 527 noRecursiveExecute = TRUE;
528 Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); 528 Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
529 break; 529 break;
530 case 'S': 530 case 'S':
531 keepgoing = FALSE; 531 keepgoing = FALSE;
532 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 532 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
533 break; 533 break;
534 case 'T': 534 case 'T':
535 if (argvalue == NULL) goto noarg; 535 if (argvalue == NULL) goto noarg;
536 tracefile = bmake_strdup(argvalue); 536 tracefile = bmake_strdup(argvalue);
537 Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); 537 Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
538 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 538 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
539 break; 539 break;
540 case 'V': 540 case 'V':
541 case 'v': 541 case 'v':
542 if (argvalue == NULL) goto noarg; 542 if (argvalue == NULL) goto noarg;
543 printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS; 543 printVars = c == 'v' ? EXPAND_VARS : COMPAT_VARS;
544 Lst_Append(variables, argvalue); 544 Lst_Append(variables, argvalue);
545 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 545 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
546 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 546 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
547 break; 547 break;
548 case 'W': 548 case 'W':
549 parseWarnFatal = TRUE; 549 parseWarnFatal = TRUE;
550 break; 550 break;
551 case 'X': 551 case 'X':
552 varNoExportEnv = TRUE; 552 varNoExportEnv = TRUE;
553 Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); 553 Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
554 break; 554 break;
555 case 'd': 555 case 'd':
556 if (argvalue == NULL) goto noarg; 556 if (argvalue == NULL) goto noarg;
557 /* If '-d-opts' don't pass to children */ 557 /* If '-d-opts' don't pass to children */
558 if (argvalue[0] == '-') 558 if (argvalue[0] == '-')
559 argvalue++; 559 argvalue++;
560 else { 560 else {
561 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 561 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
562 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 562 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
563 } 563 }
564 parse_debug_options(argvalue); 564 parse_debug_options(argvalue);
565 break; 565 break;
566 case 'e': 566 case 'e':
567 checkEnvFirst = TRUE; 567 checkEnvFirst = TRUE;
568 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 568 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
569 break; 569 break;
570 case 'f': 570 case 'f':
571 if (argvalue == NULL) goto noarg; 571 if (argvalue == NULL) goto noarg;
572 Lst_Append(makefiles, argvalue); 572 Lst_Append(makefiles, argvalue);
573 break; 573 break;
574 case 'i': 574 case 'i':
575 ignoreErrors = TRUE; 575 ignoreErrors = TRUE;
576 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 576 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
577 break; 577 break;
578 case 'j': 578 case 'j':
579 if (argvalue == NULL) goto noarg; 579 if (argvalue == NULL) goto noarg;
580 forceJobs = TRUE; 580 forceJobs = TRUE;
581 maxJobs = strtol(argvalue, &p, 0); 581 maxJobs = strtol(argvalue, &p, 0);
582 if (*p != '\0' || maxJobs < 1) { 582 if (*p != '\0' || maxJobs < 1) {
583 (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n", 583 (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
584 progname); 584 progname);
585 exit(1); 585 exit(1);
586 } 586 }
587 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 587 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
588 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 588 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
589 Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL); 589 Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL);
590 maxJobTokens = maxJobs; 590 maxJobTokens = maxJobs;
591 break; 591 break;
592 case 'k': 592 case 'k':
593 keepgoing = TRUE; 593 keepgoing = TRUE;
594 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 594 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
595 break; 595 break;
596 case 'm': 596 case 'm':
597 if (argvalue == NULL) goto noarg; 597 if (argvalue == NULL) goto noarg;
598 /* look for magic parent directory search string */ 598 /* look for magic parent directory search string */
599 if (strncmp(".../", argvalue, 4) == 0) { 599 if (strncmp(".../", argvalue, 4) == 0) {
600 if (!Dir_FindHereOrAbove(curdir, argvalue+4, 600 if (!Dir_FindHereOrAbove(curdir, argvalue+4,
601 found_path, sizeof(found_path))) 601 found_path, sizeof(found_path)))
602 break; /* nothing doing */ 602 break; /* nothing doing */
603 (void)Dir_AddDir(sysIncPath, found_path); 603 (void)Dir_AddDir(sysIncPath, found_path);
604 } else { 604 } else {
605 (void)Dir_AddDir(sysIncPath, argvalue); 605 (void)Dir_AddDir(sysIncPath, argvalue);
606 } 606 }
607 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 607 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
608 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 608 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
609 break; 609 break;
610 case 'n': 610 case 'n':
611 noExecute = TRUE; 611 noExecute = TRUE;
612 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 612 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
613 break; 613 break;
614 case 'q': 614 case 'q':
615 queryFlag = TRUE; 615 queryFlag = TRUE;
616 /* Kind of nonsensical, wot? */ 616 /* Kind of nonsensical, wot? */
617 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 617 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
618 break; 618 break;
619 case 'r': 619 case 'r':
620 noBuiltins = TRUE; 620 noBuiltins = TRUE;
621 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 621 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
622 break; 622 break;
623 case 's': 623 case 's':
624 beSilent = TRUE; 624 beSilent = TRUE;
625 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 625 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
626 break; 626 break;
627 case 't': 627 case 't':
628 touchFlag = TRUE; 628 touchFlag = TRUE;
629 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 629 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
630 break; 630 break;
631 case 'w': 631 case 'w':
632 enterFlag = TRUE; 632 enterFlag = TRUE;
633 Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL); 633 Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL);
634 break; 634 break;
635 case '-': 635 case '-':
636 dashDash = TRUE; 636 dashDash = TRUE;
637 break; 637 break;
638 default: 638 default:
639 case '?': 639 case '?':
640 usage(); 640 usage();
641 } 641 }
642 argv += arginc; 642 argv += arginc;
643 argc -= arginc; 643 argc -= arginc;
644 } 644 }
645 645
646 oldVars = TRUE; 646 oldVars = TRUE;
647 647
648 /* 648 /*
649 * See if the rest of the arguments are variable assignments and 649 * See if the rest of the arguments are variable assignments and
650 * perform them if so. Else take them to be targets and stuff them 650 * perform them if so. Else take them to be targets and stuff them
651 * on the end of the "create" list. 651 * on the end of the "create" list.
652 */ 652 */
653 for (; argc > 1; ++argv, --argc) 653 for (; argc > 1; ++argv, --argc)
654 if (Parse_IsVar(argv[1])) { 654 if (Parse_IsVar(argv[1])) {
655 Parse_DoVar(argv[1], VAR_CMD); 655 Parse_DoVar(argv[1], VAR_CMD);
656 } else { 656 } else {
657 if (!*argv[1]) 657 if (!*argv[1])
658 Punt("illegal (null) argument."); 658 Punt("illegal (null) argument.");
659 if (*argv[1] == '-' && !dashDash) 659 if (*argv[1] == '-' && !dashDash)
660 goto rearg; 660 goto rearg;
661 Lst_Append(create, bmake_strdup(argv[1])); 661 Lst_Append(create, bmake_strdup(argv[1]));
662 } 662 }
663 663
664 return; 664 return;
665noarg: 665noarg:
666 (void)fprintf(stderr, "%s: option requires an argument -- %c\n", 666 (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
667 progname, c); 667 progname, c);
668 usage(); 668 usage();
669} 669}
670 670
671/*- 671/*-
672 * Main_ParseArgLine -- 672 * Main_ParseArgLine --
673 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 673 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
674 * is encountered and by main() when reading the .MAKEFLAGS envariable. 674 * is encountered and by main() when reading the .MAKEFLAGS envariable.
675 * Takes a line of arguments and breaks it into its 675 * Takes a line of arguments and breaks it into its
676 * component words and passes those words and the number of them to the 676 * component words and passes those words and the number of them to the
677 * MainParseArgs function. 677 * MainParseArgs function.
678 * The line should have all its leading whitespace removed. 678 * The line should have all its leading whitespace removed.
679 * 679 *
680 * Input: 680 * Input:
681 * line Line to fracture 681 * line Line to fracture
682 * 682 *
683 * Results: 683 * Results:
684 * None 684 * None
685 * 685 *
686 * Side Effects: 686 * Side Effects:
687 * Only those that come from the various arguments. 687 * Only those that come from the various arguments.
688 */ 688 */
689void 689void
690Main_ParseArgLine(const char *line) 690Main_ParseArgLine(const char *line)
691{ 691{
692 char **argv; /* Manufactured argument vector */ 692 char **argv; /* Manufactured argument vector */
693 size_t argc; /* Number of arguments in argv */ 693 size_t argc; /* Number of arguments in argv */
694 char *args; /* Space used by the args */ 694 char *args; /* Space used by the args */
695 char *p1; 695 char *p1;
696 const char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1); 696 const char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
697 char *buf; 697 char *buf;
698 698
699 if (line == NULL) 699 if (line == NULL)
700 return; 700 return;
701 for (; *line == ' '; ++line) 701 for (; *line == ' '; ++line)
702 continue; 702 continue;
703 if (!*line) 703 if (!*line)
704 return; 704 return;
705 705
706 buf = str_concat3(argv0, " ", line); 706 buf = str_concat3(argv0, " ", line);
707 free(p1); 707 free(p1);
708 708
709 argv = brk_string(buf, TRUE, &argc, &args); 709 argv = brk_string(buf, TRUE, &argc, &args);
710 if (argv == NULL) { 710 if (argv == NULL) {
711 Error("Unterminated quoted string [%s]", buf); 711 Error("Unterminated quoted string [%s]", buf);
712 free(buf); 712 free(buf);
713 return; 713 return;
714 } 714 }
715 free(buf); 715 free(buf);
716 MainParseArgs((int)argc, argv); 716 MainParseArgs((int)argc, argv);
717 717
718 free(args); 718 free(args);
719 free(argv); 719 free(argv);
720} 720}
721 721
722Boolean 722Boolean
723Main_SetObjdir(const char *fmt, ...) 723Main_SetObjdir(const char *fmt, ...)
724{ 724{
725 struct stat sb; 725 struct stat sb;
726 char *path; 726 char *path;
727 char buf[MAXPATHLEN + 1]; 727 char buf[MAXPATHLEN + 1];
728 char buf2[MAXPATHLEN + 1]; 728 char buf2[MAXPATHLEN + 1];
729 Boolean rc = FALSE; 729 Boolean rc = FALSE;
730 va_list ap; 730 va_list ap;
731 731
732 va_start(ap, fmt); 732 va_start(ap, fmt);
733 vsnprintf(path = buf, MAXPATHLEN, fmt, ap); 733 vsnprintf(path = buf, MAXPATHLEN, fmt, ap);
734 va_end(ap); 734 va_end(ap);
735 735
736 if (path[0] != '/') { 736 if (path[0] != '/') {
737 snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path); 737 snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path);
738 path = buf2; 738 path = buf2;
739 } 739 }
740 740
741 /* look for the directory and try to chdir there */ 741 /* look for the directory and try to chdir there */
742 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 742 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
743 if (chdir(path)) { 743 if (chdir(path)) {
744 (void)fprintf(stderr, "make warning: %s: %s.\n", 744 (void)fprintf(stderr, "make warning: %s: %s.\n",
745 path, strerror(errno)); 745 path, strerror(errno));
746 } else { 746 } else {
747 snprintf(objdir, sizeof objdir, "%s", path); 747 snprintf(objdir, sizeof objdir, "%s", path);
748 Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 748 Var_Set(".OBJDIR", objdir, VAR_GLOBAL);
749 setenv("PWD", objdir, 1); 749 setenv("PWD", objdir, 1);
750 Dir_InitDot(); 750 Dir_InitDot();
751 purge_cached_realpaths(); 751 purge_cached_realpaths();
752 rc = TRUE; 752 rc = TRUE;
753 if (enterFlag && strcmp(objdir, curdir) != 0) 753 if (enterFlag && strcmp(objdir, curdir) != 0)
754 enterFlagObj = TRUE; 754 enterFlagObj = TRUE;
755 } 755 }
756 } 756 }
757 757
758 return rc; 758 return rc;
759} 759}
760 760
761static Boolean 761static Boolean
762Main_SetVarObjdir(const char *var, const char *suffix) 762Main_SetVarObjdir(const char *var, const char *suffix)
763{ 763{
764 char *path_freeIt; 764 char *path_freeIt;
765 const char *path = Var_Value(var, VAR_CMD, &path_freeIt); 765 const char *path = Var_Value(var, VAR_CMD, &path_freeIt);
766 const char *xpath; 766 const char *xpath;
767 char *xpath_freeIt; 767 char *xpath_freeIt;
768 768
769 if (path == NULL || path[0] == '\0') { 769 if (path == NULL || path[0] == '\0') {
770 bmake_free(path_freeIt); 770 bmake_free(path_freeIt);
771 return FALSE; 771 return FALSE;
772 } 772 }
773 773
774 /* expand variable substitutions */ 774 /* expand variable substitutions */
775 xpath = path; 775 xpath = path;
776 xpath_freeIt = NULL; 776 xpath_freeIt = NULL;
777 if (strchr(path, '$') != 0) 777 if (strchr(path, '$') != 0)
778 xpath = xpath_freeIt = Var_Subst(path, VAR_GLOBAL, 778 xpath = xpath_freeIt = Var_Subst(path, VAR_GLOBAL,
779 VARE_WANTRES); 779 VARE_WANTRES);
780 780
781 (void)Main_SetObjdir("%s%s", xpath, suffix); 781 (void)Main_SetObjdir("%s%s", xpath, suffix);
782 782
783 bmake_free(xpath_freeIt); 783 bmake_free(xpath_freeIt);
784 bmake_free(path_freeIt); 784 bmake_free(path_freeIt);
785 return TRUE; 785 return TRUE;
786} 786}
787 787
788/*- 788/* Return 0 if reading the makefile failed, for Lst_Find. */
789 * ReadAllMakefiles -- 
790 * wrapper around ReadMakefile() to read all. 
791 * 
792 * Results: 
793 * TRUE if ok, FALSE on error 
794 */ 
795static int 789static int
796ReadAllMakefiles(const void *p, const void *q) 790ReadMakefileFailed(const void *p, const void *q)
797{ 791{
798 return ReadMakefile(p, q) == 0; 792 return ReadMakefile(p, q) == 0;
799} 793}
800 794
801int 795int
802str2Lst_Append(Lst lp, char *str, const char *sep) 796str2Lst_Append(Lst lp, char *str, const char *sep)
803{ 797{
804 char *cp; 798 char *cp;
805 int n; 799 int n;
806 800
807 if (!sep) 801 if (!sep)
808 sep = " \t"; 802 sep = " \t";
809 803
810 for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) { 804 for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
811 Lst_Append(lp, cp); 805 Lst_Append(lp, cp);
812 n++; 806 n++;
813 } 807 }
814 return n; 808 return n;
815} 809}
816 810
817#ifdef SIGINFO 811#ifdef SIGINFO
818/*ARGSUSED*/ 812/*ARGSUSED*/
819static void 813static void
820siginfo(int signo MAKE_ATTR_UNUSED) 814siginfo(int signo MAKE_ATTR_UNUSED)
821{ 815{
822 char dir[MAXPATHLEN]; 816 char dir[MAXPATHLEN];
823 char str[2 * MAXPATHLEN]; 817 char str[2 * MAXPATHLEN];
824 int len; 818 int len;
825 if (getcwd(dir, sizeof(dir)) == NULL) 819 if (getcwd(dir, sizeof(dir)) == NULL)
826 return; 820 return;
827 len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir); 821 len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
828 if (len > 0) 822 if (len > 0)
829 (void)write(STDERR_FILENO, str, (size_t)len); 823 (void)write(STDERR_FILENO, str, (size_t)len);
830} 824}
831#endif 825#endif
832 826
833/* 827/*
834 * Allow makefiles some control over the mode we run in. 828 * Allow makefiles some control over the mode we run in.
835 */ 829 */
836void 830void
837MakeMode(const char *mode) 831MakeMode(const char *mode)
838{ 832{
839 char *mp = NULL; 833 char *mp = NULL;
840 834
841 if (!mode) 835 if (!mode)
842 mode = mp = Var_Subst("${" MAKE_MODE ":tl}", 836 mode = mp = Var_Subst("${" MAKE_MODE ":tl}",
843 VAR_GLOBAL, VARE_WANTRES); 837 VAR_GLOBAL, VARE_WANTRES);
844 838
845 if (mode && *mode) { 839 if (mode && *mode) {
846 if (strstr(mode, "compat")) { 840 if (strstr(mode, "compat")) {
847 compatMake = TRUE; 841 compatMake = TRUE;
848 forceJobs = FALSE; 842 forceJobs = FALSE;
849 } 843 }
850#if USE_META 844#if USE_META
851 if (strstr(mode, "meta")) 845 if (strstr(mode, "meta"))
852 meta_mode_init(mode); 846 meta_mode_init(mode);
853#endif 847#endif
854 } 848 }
855 849
856 free(mp); 850 free(mp);
857} 851}
858 852
859static void 853static void
860doPrintVars(void) 854doPrintVars(void)
861{ 855{
862 LstNode ln; 856 LstNode ln;
863 Boolean expandVars; 857 Boolean expandVars;
864 858
865 if (printVars == EXPAND_VARS) 859 if (printVars == EXPAND_VARS)
866 expandVars = TRUE; 860 expandVars = TRUE;
867 else if (debugVflag) 861 else if (debugVflag)
868 expandVars = FALSE; 862 expandVars = FALSE;
869 else 863 else
870 expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE); 864 expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
871 865
872 for (ln = Lst_First(variables); ln != NULL; ln = Lst_Succ(ln)) { 866 for (ln = Lst_First(variables); ln != NULL; ln = Lst_Succ(ln)) {
873 char *var = Lst_Datum(ln); 867 char *var = Lst_Datum(ln);
874 const char *value; 868 const char *value;
875 char *p1; 869 char *p1;
876 870
877 if (strchr(var, '$')) { 871 if (strchr(var, '$')) {
878 value = p1 = Var_Subst(var, VAR_GLOBAL, VARE_WANTRES); 872 value = p1 = Var_Subst(var, VAR_GLOBAL, VARE_WANTRES);
879 } else if (expandVars) { 873 } else if (expandVars) {
880 char tmp[128]; 874 char tmp[128];
881 int len = snprintf(tmp, sizeof(tmp), "${%s}", var); 875 int len = snprintf(tmp, sizeof(tmp), "${%s}", var);
882 876
883 if (len >= (int)sizeof(tmp)) 877 if (len >= (int)sizeof(tmp))
884 Fatal("%s: variable name too big: %s", 878 Fatal("%s: variable name too big: %s",
885 progname, var); 879 progname, var);
886 value = p1 = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES); 880 value = p1 = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES);
887 } else { 881 } else {
888 value = Var_Value(var, VAR_GLOBAL, &p1); 882 value = Var_Value(var, VAR_GLOBAL, &p1);
889 } 883 }
890 printf("%s\n", value ? value : ""); 884 printf("%s\n", value ? value : "");
891 bmake_free(p1); 885 bmake_free(p1);
892 } 886 }
893} 887}
894 888
895static Boolean 889static Boolean
896runTargets(void) 890runTargets(void)
897{ 891{
898 Lst targs; /* target nodes to create -- passed to Make_Init */ 892 Lst targs; /* target nodes to create -- passed to Make_Init */
899 Boolean outOfDate; /* FALSE if all targets up to date */ 893 Boolean outOfDate; /* FALSE if all targets up to date */
900 894
901 /* 895 /*
902 * Have now read the entire graph and need to make a list of 896 * Have now read the entire graph and need to make a list of
903 * targets to create. If none was given on the command line, 897 * targets to create. If none was given on the command line,
904 * we consult the parsing module to find the main target(s) 898 * we consult the parsing module to find the main target(s)
905 * to create. 899 * to create.
906 */ 900 */
907 if (Lst_IsEmpty(create)) 901 if (Lst_IsEmpty(create))
908 targs = Parse_MainName(); 902 targs = Parse_MainName();
909 else 903 else
910 targs = Targ_FindList(create, TARG_CREATE); 904 targs = Targ_FindList(create, TARG_CREATE);
911 905
912 if (!compatMake) { 906 if (!compatMake) {
913 /* 907 /*
914 * Initialize job module before traversing the graph 908 * Initialize job module before traversing the graph
915 * now that any .BEGIN and .END targets have been read. 909 * now that any .BEGIN and .END targets have been read.
916 * This is done only if the -q flag wasn't given 910 * This is done only if the -q flag wasn't given
917 * (to prevent the .BEGIN from being executed should 911 * (to prevent the .BEGIN from being executed should
918 * it exist). 912 * it exist).
919 */ 913 */
920 if (!queryFlag) { 914 if (!queryFlag) {
921 Job_Init(); 915 Job_Init();
922 jobsRunning = TRUE; 916 jobsRunning = TRUE;
923 } 917 }
924 918
925 /* Traverse the graph, checking on all the targets */ 919 /* Traverse the graph, checking on all the targets */
926 outOfDate = Make_Run(targs); 920 outOfDate = Make_Run(targs);
927 } else { 921 } else {
928 /* 922 /*
929 * Compat_Init will take care of creating all the 923 * Compat_Init will take care of creating all the
930 * targets as well as initializing the module. 924 * targets as well as initializing the module.
931 */ 925 */
932 Compat_Run(targs); 926 Compat_Run(targs);
933 outOfDate = FALSE; 927 outOfDate = FALSE;
934 } 928 }
935 Lst_Free(targs); 929 Lst_Free(targs);
936 return outOfDate; 930 return outOfDate;
937} 931}
938 932
939/*- 933/*-
940 * main -- 934 * main --
941 * The main function, for obvious reasons. Initializes variables 935 * The main function, for obvious reasons. Initializes variables
942 * and a few modules, then parses the arguments give it in the 936 * and a few modules, then parses the arguments give it in the
943 * environment and on the command line. Reads the system makefile 937 * environment and on the command line. Reads the system makefile
944 * followed by either Makefile, makefile or the file given by the 938 * followed by either Makefile, makefile or the file given by the
945 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 939 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
946 * flags it has received by then uses either the Make or the Compat 940 * flags it has received by then uses either the Make or the Compat
947 * module to create the initial list of targets. 941 * module to create the initial list of targets.
948 * 942 *
949 * Results: 943 * Results:
950 * If -q was given, exits -1 if anything was out-of-date. Else it exits 944 * If -q was given, exits -1 if anything was out-of-date. Else it exits
951 * 0. 945 * 0.
952 * 946 *
953 * Side Effects: 947 * Side Effects:
954 * The program exits when done. Targets are created. etc. etc. etc. 948 * The program exits when done. Targets are created. etc. etc. etc.
955 */ 949 */
956int 950int
957main(int argc, char **argv) 951main(int argc, char **argv)
958{ 952{
959 Boolean outOfDate; /* FALSE if all targets up to date */ 953 Boolean outOfDate; /* FALSE if all targets up to date */
960 struct stat sb, sa; 954 struct stat sb, sa;
961 char *p1, *path; 955 char *p1, *path;
962 char mdpath[MAXPATHLEN]; 956 char mdpath[MAXPATHLEN];
963 const char *machine = getenv("MACHINE"); 957 const char *machine = getenv("MACHINE");
964 const char *machine_arch = getenv("MACHINE_ARCH"); 958 const char *machine_arch = getenv("MACHINE_ARCH");
965 char *syspath = getenv("MAKESYSPATH"); 959 char *syspath = getenv("MAKESYSPATH");
966 Lst sysMkPath; /* Path of sys.mk */ 960 Lst sysMkPath; /* Path of sys.mk */
967 char *cp = NULL, *start; 961 char *cp = NULL, *start;
968 /* avoid faults on read-only strings */ 962 /* avoid faults on read-only strings */
969 static char defsyspath[] = _PATH_DEFSYSPATH; 963 static char defsyspath[] = _PATH_DEFSYSPATH;
970 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ 964 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
971 struct timeval rightnow; /* to initialize random seed */ 965 struct timeval rightnow; /* to initialize random seed */
972 struct utsname utsname; 966 struct utsname utsname;
973 967
974 /* default to writing debug to stderr */ 968 /* default to writing debug to stderr */
975 debug_file = stderr; 969 debug_file = stderr;
976 970
977#ifdef SIGINFO 971#ifdef SIGINFO
978 (void)bmake_signal(SIGINFO, siginfo); 972 (void)bmake_signal(SIGINFO, siginfo);
979#endif 973#endif
980 /* 974 /*
981 * Set the seed to produce a different random sequence 975 * Set the seed to produce a different random sequence
982 * on each program execution. 976 * on each program execution.
983 */ 977 */
984 gettimeofday(&rightnow, NULL); 978 gettimeofday(&rightnow, NULL);
985 srandom(rightnow.tv_sec + rightnow.tv_usec); 979 srandom(rightnow.tv_sec + rightnow.tv_usec);
986 980
987 if ((progname = strrchr(argv[0], '/')) != NULL) 981 if ((progname = strrchr(argv[0], '/')) != NULL)
988 progname++; 982 progname++;
989 else 983 else
990 progname = argv[0]; 984 progname = argv[0];
991#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) 985#if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE))
992 /* 986 /*
993 * get rid of resource limit on file descriptors 987 * get rid of resource limit on file descriptors
994 */ 988 */
995 { 989 {
996 struct rlimit rl; 990 struct rlimit rl;
997 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 991 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
998 rl.rlim_cur != rl.rlim_max) { 992 rl.rlim_cur != rl.rlim_max) {
999 rl.rlim_cur = rl.rlim_max; 993 rl.rlim_cur = rl.rlim_max;
1000 (void)setrlimit(RLIMIT_NOFILE, &rl); 994 (void)setrlimit(RLIMIT_NOFILE, &rl);
1001 } 995 }
1002 } 996 }
1003#endif 997#endif
1004 998
1005 if (uname(&utsname) == -1) { 999 if (uname(&utsname) == -1) {
1006 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, 1000 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
1007 strerror(errno)); 1001 strerror(errno));
1008 exit(2); 1002 exit(2);
1009 } 1003 }
1010 1004
1011 /* 1005 /*
1012 * Get the name of this type of MACHINE from utsname 1006 * Get the name of this type of MACHINE from utsname
1013 * so we can share an executable for similar machines. 1007 * so we can share an executable for similar machines.
1014 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 1008 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
1015 * 1009 *
1016 * Note that both MACHINE and MACHINE_ARCH are decided at 1010 * Note that both MACHINE and MACHINE_ARCH are decided at
1017 * run-time. 1011 * run-time.
1018 */ 1012 */
1019 if (!machine) { 1013 if (!machine) {
1020#ifdef MAKE_NATIVE 1014#ifdef MAKE_NATIVE
1021 machine = utsname.machine; 1015 machine = utsname.machine;
1022#else 1016#else
1023#ifdef MAKE_MACHINE 1017#ifdef MAKE_MACHINE
1024 machine = MAKE_MACHINE; 1018 machine = MAKE_MACHINE;
1025#else 1019#else
1026 machine = "unknown"; 1020 machine = "unknown";
1027#endif 1021#endif
1028#endif 1022#endif
1029 } 1023 }
1030 1024
1031 if (!machine_arch) { 1025 if (!machine_arch) {
1032#ifdef MAKE_NATIVE 1026#ifdef MAKE_NATIVE
1033 static char machine_arch_buf[sizeof(utsname.machine)]; 1027 static char machine_arch_buf[sizeof(utsname.machine)];
1034 const int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1028 const int mib[2] = { CTL_HW, HW_MACHINE_ARCH };
1035 size_t len = sizeof(machine_arch_buf); 1029 size_t len = sizeof(machine_arch_buf);
1036 1030
1037 if (sysctl(mib, __arraycount(mib), machine_arch_buf, 1031 if (sysctl(mib, __arraycount(mib), machine_arch_buf,
1038 &len, NULL, 0) < 0) { 1032 &len, NULL, 0) < 0) {
1039 (void)fprintf(stderr, "%s: sysctl failed (%s).\n", progname, 1033 (void)fprintf(stderr, "%s: sysctl failed (%s).\n", progname,
1040 strerror(errno)); 1034 strerror(errno));
1041 exit(2); 1035 exit(2);
1042 } 1036 }
1043 1037
1044 machine_arch = machine_arch_buf; 1038 machine_arch = machine_arch_buf;
1045#else 1039#else
1046#ifndef MACHINE_ARCH 1040#ifndef MACHINE_ARCH
1047#ifdef MAKE_MACHINE_ARCH 1041#ifdef MAKE_MACHINE_ARCH
1048 machine_arch = MAKE_MACHINE_ARCH; 1042 machine_arch = MAKE_MACHINE_ARCH;
1049#else 1043#else
1050 machine_arch = "unknown"; 1044 machine_arch = "unknown";
1051#endif 1045#endif
1052#else 1046#else
1053 machine_arch = MACHINE_ARCH; 1047 machine_arch = MACHINE_ARCH;
1054#endif 1048#endif
1055#endif 1049#endif
1056 } 1050 }
1057 1051
1058 myPid = getpid(); /* remember this for vFork() */ 1052 myPid = getpid(); /* remember this for vFork() */
1059 1053
1060 /* 1054 /*
1061 * Just in case MAKEOBJDIR wants us to do something tricky. 1055 * Just in case MAKEOBJDIR wants us to do something tricky.
1062 */ 1056 */
1063 Var_Init(); /* Initialize the lists of variables for 1057 Var_Init(); /* Initialize the lists of variables for
1064 * parsing arguments */ 1058 * parsing arguments */
1065 Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL); 1059 Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL);
1066 Var_Set("MACHINE", machine, VAR_GLOBAL); 1060 Var_Set("MACHINE", machine, VAR_GLOBAL);
1067 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 1061 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL);
1068#ifdef MAKE_VERSION 1062#ifdef MAKE_VERSION
1069 Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL); 1063 Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL);
1070#endif 1064#endif
1071 Var_Set(".newline", "\n", VAR_GLOBAL); /* handy for :@ loops */ 1065 Var_Set(".newline", "\n", VAR_GLOBAL); /* handy for :@ loops */
1072 /* 1066 /*
1073 * This is the traditional preference for makefiles. 1067 * This is the traditional preference for makefiles.
1074 */ 1068 */
1075#ifndef MAKEFILE_PREFERENCE_LIST 1069#ifndef MAKEFILE_PREFERENCE_LIST
1076# define MAKEFILE_PREFERENCE_LIST "makefile Makefile" 1070# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
1077#endif 1071#endif
1078 Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST, 1072 Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
1079 VAR_GLOBAL); 1073 VAR_GLOBAL);
1080 Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL); 1074 Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL);
1081 1075
1082 create = Lst_Init(); 1076 create = Lst_Init();
1083 makefiles = Lst_Init(); 1077 makefiles = Lst_Init();
1084 printVars = 0; 1078 printVars = 0;
1085 debugVflag = FALSE; 1079 debugVflag = FALSE;
1086 variables = Lst_Init(); 1080 variables = Lst_Init();
1087 beSilent = FALSE; /* Print commands as executed */ 1081 beSilent = FALSE; /* Print commands as executed */
1088 ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 1082 ignoreErrors = FALSE; /* Pay attention to non-zero returns */
1089 noExecute = FALSE; /* Execute all commands */ 1083 noExecute = FALSE; /* Execute all commands */
1090 noRecursiveExecute = FALSE; /* Execute all .MAKE targets */ 1084 noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
1091 keepgoing = FALSE; /* Stop on error */ 1085 keepgoing = FALSE; /* Stop on error */
1092 allPrecious = FALSE; /* Remove targets when interrupted */ 1086 allPrecious = FALSE; /* Remove targets when interrupted */
1093 deleteOnError = FALSE; /* Historical default behavior */ 1087 deleteOnError = FALSE; /* Historical default behavior */
1094 queryFlag = FALSE; /* This is not just a check-run */ 1088 queryFlag = FALSE; /* This is not just a check-run */
1095 noBuiltins = FALSE; /* Read the built-in rules */ 1089 noBuiltins = FALSE; /* Read the built-in rules */
1096 touchFlag = FALSE; /* Actually update targets */ 1090 touchFlag = FALSE; /* Actually update targets */
1097 debug = 0; /* No debug verbosity, please. */ 1091 debug = 0; /* No debug verbosity, please. */
1098 jobsRunning = FALSE; 1092 jobsRunning = FALSE;
1099 1093
1100 maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */ 1094 maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */
1101 maxJobTokens = maxJobs; 1095 maxJobTokens = maxJobs;
1102 compatMake = FALSE; /* No compat mode */ 1096 compatMake = FALSE; /* No compat mode */
1103 ignorePWD = FALSE; 1097 ignorePWD = FALSE;
1104 1098
1105 /* 1099 /*
1106 * Initialize the parsing, directory and variable modules to prepare 1100 * Initialize the parsing, directory and variable modules to prepare
1107 * for the reading of inclusion paths and variable settings on the 1101 * for the reading of inclusion paths and variable settings on the
1108 * command line 1102 * command line
1109 */ 1103 */
1110 1104
1111 /* 1105 /*
1112 * Initialize various variables. 1106 * Initialize various variables.
1113 * MAKE also gets this name, for compatibility 1107 * MAKE also gets this name, for compatibility
1114 * .MAKEFLAGS gets set to the empty string just in case. 1108 * .MAKEFLAGS gets set to the empty string just in case.
1115 * MFLAGS also gets initialized empty, for compatibility. 1109 * MFLAGS also gets initialized empty, for compatibility.
1116 */ 1110 */
1117 Parse_Init(); 1111 Parse_Init();
1118 if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) { 1112 if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
1119 /* 1113 /*
1120 * Leave alone if it is an absolute path, or if it does 1114 * Leave alone if it is an absolute path, or if it does
1121 * not contain a '/' in which case we need to find it in 1115 * not contain a '/' in which case we need to find it in
1122 * the path, like execvp(3) and the shells do. 1116 * the path, like execvp(3) and the shells do.
1123 */ 1117 */
1124 p1 = argv[0]; 1118 p1 = argv[0];
1125 } else { 1119 } else {
1126 /* 1120 /*
1127 * A relative path, canonicalize it. 1121 * A relative path, canonicalize it.
1128 */ 1122 */
1129 p1 = cached_realpath(argv[0], mdpath); 1123 p1 = cached_realpath(argv[0], mdpath);
1130 if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) { 1124 if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
1131 p1 = argv[0]; /* realpath failed */ 1125 p1 = argv[0]; /* realpath failed */
1132 } 1126 }
1133 } 1127 }
1134 Var_Set("MAKE", p1, VAR_GLOBAL); 1128 Var_Set("MAKE", p1, VAR_GLOBAL);
1135 Var_Set(".MAKE", p1, VAR_GLOBAL); 1129 Var_Set(".MAKE", p1, VAR_GLOBAL);
1136 Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 1130 Var_Set(MAKEFLAGS, "", VAR_GLOBAL);
1137 Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL); 1131 Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL);
1138 Var_Set("MFLAGS", "", VAR_GLOBAL); 1132 Var_Set("MFLAGS", "", VAR_GLOBAL);
1139 Var_Set(".ALLTARGETS", "", VAR_GLOBAL); 1133 Var_Set(".ALLTARGETS", "", VAR_GLOBAL);
1140 /* some makefiles need to know this */ 1134 /* some makefiles need to know this */
1141 Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMD); 1135 Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMD);
1142 1136
1143 /* 1137 /*
1144 * Set some other useful macros 1138 * Set some other useful macros
1145 */ 1139 */
1146 { 1140 {
1147 char tmp[64], *ep; 1141 char tmp[64], *ep;
1148 1142
1149 makelevel = ((ep = getenv(MAKE_LEVEL_ENV)) && *ep) ? atoi(ep) : 0; 1143 makelevel = ((ep = getenv(MAKE_LEVEL_ENV)) && *ep) ? atoi(ep) : 0;
1150 if (makelevel < 0) 1144 if (makelevel < 0)
1151 makelevel = 0; 1145 makelevel = 0;
1152 snprintf(tmp, sizeof(tmp), "%d", makelevel); 1146 snprintf(tmp, sizeof(tmp), "%d", makelevel);
1153 Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL); 1147 Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL);
1154 snprintf(tmp, sizeof(tmp), "%u", myPid); 1148 snprintf(tmp, sizeof(tmp), "%u", myPid);
1155 Var_Set(".MAKE.PID", tmp, VAR_GLOBAL); 1149 Var_Set(".MAKE.PID", tmp, VAR_GLOBAL);
1156 snprintf(tmp, sizeof(tmp), "%u", getppid()); 1150 snprintf(tmp, sizeof(tmp), "%u", getppid());
1157 Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL); 1151 Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL);
1158 } 1152 }
1159 if (makelevel > 0) { 1153 if (makelevel > 0) {
1160 char pn[1024]; 1154 char pn[1024];
1161 snprintf(pn, sizeof(pn), "%s[%d]", progname, makelevel); 1155 snprintf(pn, sizeof(pn), "%s[%d]", progname, makelevel);
1162 progname = bmake_strdup(pn); 1156 progname = bmake_strdup(pn);
1163 } 1157 }
1164 1158
1165#ifdef USE_META 1159#ifdef USE_META
1166 meta_init(); 1160 meta_init();
1167#endif 1161#endif
1168 Dir_Init(); 1162 Dir_Init();
1169 1163
1170 /* 1164 /*
1171 * First snag any flags out of the MAKE environment variable. 1165 * First snag any flags out of the MAKE environment variable.
1172 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 1166 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
1173 * in a different format). 1167 * in a different format).
1174 */ 1168 */
1175#ifdef POSIX 1169#ifdef POSIX
1176 p1 = explode(getenv("MAKEFLAGS")); 1170 p1 = explode(getenv("MAKEFLAGS"));
1177 Main_ParseArgLine(p1); 1171 Main_ParseArgLine(p1);
1178 free(p1); 1172 free(p1);
1179#else 1173#else
1180 Main_ParseArgLine(getenv("MAKE")); 1174 Main_ParseArgLine(getenv("MAKE"));
1181#endif 1175#endif
1182 1176
1183 /* 1177 /*
1184 * Find where we are (now). 1178 * Find where we are (now).
1185 * We take care of PWD for the automounter below... 1179 * We take care of PWD for the automounter below...
1186 */ 1180 */
1187 if (getcwd(curdir, MAXPATHLEN) == NULL) { 1181 if (getcwd(curdir, MAXPATHLEN) == NULL) {
1188 (void)fprintf(stderr, "%s: getcwd: %s.\n", 1182 (void)fprintf(stderr, "%s: getcwd: %s.\n",
1189 progname, strerror(errno)); 1183 progname, strerror(errno));
1190 exit(2); 1184 exit(2);
1191 } 1185 }
1192 1186
1193 MainParseArgs(argc, argv); 1187 MainParseArgs(argc, argv);
1194 1188
1195 if (enterFlag) 1189 if (enterFlag)
1196 printf("%s: Entering directory `%s'\n", progname, curdir); 1190 printf("%s: Entering directory `%s'\n", progname, curdir);
1197 1191
1198 /* 1192 /*
1199 * Verify that cwd is sane. 1193 * Verify that cwd is sane.
1200 */ 1194 */
1201 if (stat(curdir, &sa) == -1) { 1195 if (stat(curdir, &sa) == -1) {
1202 (void)fprintf(stderr, "%s: %s: %s.\n", 1196 (void)fprintf(stderr, "%s: %s: %s.\n",
1203 progname, curdir, strerror(errno)); 1197 progname, curdir, strerror(errno));
1204 exit(2); 1198 exit(2);
1205 } 1199 }
1206 1200
1207 /* 1201 /*
1208 * All this code is so that we know where we are when we start up 1202 * All this code is so that we know where we are when we start up
1209 * on a different machine with pmake. 1203 * on a different machine with pmake.
1210 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX 1204 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
1211 * since the value of curdir can vary depending on how we got 1205 * since the value of curdir can vary depending on how we got
1212 * here. Ie sitting at a shell prompt (shell that provides $PWD) 1206 * here. Ie sitting at a shell prompt (shell that provides $PWD)
1213 * or via subdir.mk in which case its likely a shell which does 1207 * or via subdir.mk in which case its likely a shell which does
1214 * not provide it. 1208 * not provide it.
1215 * So, to stop it breaking this case only, we ignore PWD if 1209 * So, to stop it breaking this case only, we ignore PWD if
1216 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform. 1210 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
1217 */ 1211 */
1218#ifndef NO_PWD_OVERRIDE 1212#ifndef NO_PWD_OVERRIDE
1219 if (!ignorePWD) { 1213 if (!ignorePWD) {
1220 char *pwd, *ptmp1 = NULL, *ptmp2 = NULL; 1214 char *pwd, *ptmp1 = NULL, *ptmp2 = NULL;
1221 1215
1222 if ((pwd = getenv("PWD")) != NULL && 1216 if ((pwd = getenv("PWD")) != NULL &&
1223 Var_Value("MAKEOBJDIRPREFIX", VAR_CMD, &ptmp1) == NULL) { 1217 Var_Value("MAKEOBJDIRPREFIX", VAR_CMD, &ptmp1) == NULL) {
1224 const char *makeobjdir = Var_Value("MAKEOBJDIR", 1218 const char *makeobjdir = Var_Value("MAKEOBJDIR",
1225 VAR_CMD, &ptmp2); 1219 VAR_CMD, &ptmp2);
1226 1220
1227 if (makeobjdir == NULL || !strchr(makeobjdir, '$')) { 1221 if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
1228 if (stat(pwd, &sb) == 0 && 1222 if (stat(pwd, &sb) == 0 &&
1229 sa.st_ino == sb.st_ino && 1223 sa.st_ino == sb.st_ino &&
1230 sa.st_dev == sb.st_dev) 1224 sa.st_dev == sb.st_dev)
1231 (void)strncpy(curdir, pwd, MAXPATHLEN); 1225 (void)strncpy(curdir, pwd, MAXPATHLEN);
1232 } 1226 }
1233 } 1227 }
1234 bmake_free(ptmp1); 1228 bmake_free(ptmp1);
1235 bmake_free(ptmp2); 1229 bmake_free(ptmp2);
1236 } 1230 }
1237#endif 1231#endif
1238 Var_Set(".CURDIR", curdir, VAR_GLOBAL); 1232 Var_Set(".CURDIR", curdir, VAR_GLOBAL);
1239 1233
1240 /* 1234 /*
1241 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, 1235 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
1242 * MAKEOBJDIR is set in the environment, try only that value 1236 * MAKEOBJDIR is set in the environment, try only that value
1243 * and fall back to .CURDIR if it does not exist. 1237 * and fall back to .CURDIR if it does not exist.
1244 * 1238 *
1245 * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE, 1239 * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE,
1246 * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none 1240 * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
1247 * of these paths exist, just use .CURDIR. 1241 * of these paths exist, just use .CURDIR.
1248 */ 1242 */
1249 Dir_InitDir(curdir); 1243 Dir_InitDir(curdir);
1250 (void)Main_SetObjdir("%s", curdir); 1244 (void)Main_SetObjdir("%s", curdir);
1251 1245
1252 if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) && 1246 if (!Main_SetVarObjdir("MAKEOBJDIRPREFIX", curdir) &&
1253 !Main_SetVarObjdir("MAKEOBJDIR", "") && 1247 !Main_SetVarObjdir("MAKEOBJDIR", "") &&
1254 !Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) && 1248 !Main_SetObjdir("%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) &&
1255 !Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) && 1249 !Main_SetObjdir("%s.%s", _PATH_OBJDIR, machine) &&
1256 !Main_SetObjdir("%s", _PATH_OBJDIR)) 1250 !Main_SetObjdir("%s", _PATH_OBJDIR))
1257 (void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir); 1251 (void)Main_SetObjdir("%s%s", _PATH_OBJDIRPREFIX, curdir);
1258 1252
1259 /* 1253 /*
1260 * Initialize archive, target and suffix modules in preparation for 1254 * Initialize archive, target and suffix modules in preparation for
1261 * parsing the makefile(s) 1255 * parsing the makefile(s)
1262 */ 1256 */
1263 Arch_Init(); 1257 Arch_Init();
1264 Targ_Init(); 1258 Targ_Init();
1265 Suff_Init(); 1259 Suff_Init();
1266 Trace_Init(tracefile); 1260 Trace_Init(tracefile);
1267 1261
1268 DEFAULT = NULL; 1262 DEFAULT = NULL;
1269 (void)time(&now); 1263 (void)time(&now);
1270 1264
1271 Trace_Log(MAKESTART, NULL); 1265 Trace_Log(MAKESTART, NULL);
1272 1266
1273 /* 1267 /*
1274 * Set up the .TARGETS variable to contain the list of targets to be 1268 * Set up the .TARGETS variable to contain the list of targets to be
1275 * created. If none specified, make the variable empty -- the parser 1269 * created. If none specified, make the variable empty -- the parser
1276 * will fill the thing in with the default or .MAIN target. 1270 * will fill the thing in with the default or .MAIN target.
1277 */ 1271 */
1278 if (!Lst_IsEmpty(create)) { 1272 if (!Lst_IsEmpty(create)) {
1279 LstNode ln; 1273 LstNode ln;
1280 1274
1281 for (ln = Lst_First(create); ln != NULL; ln = Lst_Succ(ln)) { 1275 for (ln = Lst_First(create); ln != NULL; ln = Lst_Succ(ln)) {
1282 char *name = Lst_Datum(ln); 1276 char *name = Lst_Datum(ln);
1283 Var_Append(".TARGETS", name, VAR_GLOBAL); 1277 Var_Append(".TARGETS", name, VAR_GLOBAL);
1284 } 1278 }
1285 } else 1279 } else
1286 Var_Set(".TARGETS", "", VAR_GLOBAL); 1280 Var_Set(".TARGETS", "", VAR_GLOBAL);
1287 1281
1288 1282
1289 /* 1283 /*
1290 * If no user-supplied system path was given (through the -m option) 1284 * If no user-supplied system path was given (through the -m option)
1291 * add the directories from the DEFSYSPATH (more than one may be given 1285 * add the directories from the DEFSYSPATH (more than one may be given
1292 * as dir1:...:dirn) to the system include path. 1286 * as dir1:...:dirn) to the system include path.
1293 */ 1287 */
1294 if (syspath == NULL || *syspath == '\0') 1288 if (syspath == NULL || *syspath == '\0')
1295 syspath = defsyspath; 1289 syspath = defsyspath;
1296 else 1290 else
1297 syspath = bmake_strdup(syspath); 1291 syspath = bmake_strdup(syspath);
1298 1292
1299 for (start = syspath; *start != '\0'; start = cp) { 1293 for (start = syspath; *start != '\0'; start = cp) {
1300 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 1294 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1301 continue; 1295 continue;
1302 if (*cp == ':') { 1296 if (*cp == ':') {
1303 *cp++ = '\0'; 1297 *cp++ = '\0';
1304 } 1298 }
1305 /* look for magic parent directory search string */ 1299 /* look for magic parent directory search string */
1306 if (strncmp(".../", start, 4) != 0) { 1300 if (strncmp(".../", start, 4) != 0) {
1307 (void)Dir_AddDir(defIncPath, start); 1301 (void)Dir_AddDir(defIncPath, start);
1308 } else { 1302 } else {
1309 if (Dir_FindHereOrAbove(curdir, start+4, 1303 if (Dir_FindHereOrAbove(curdir, start+4,
1310 found_path, sizeof(found_path))) { 1304 found_path, sizeof(found_path))) {
1311 (void)Dir_AddDir(defIncPath, found_path); 1305 (void)Dir_AddDir(defIncPath, found_path);
1312 } 1306 }
1313 } 1307 }
1314 } 1308 }
1315 if (syspath != defsyspath) 1309 if (syspath != defsyspath)
1316 free(syspath); 1310 free(syspath);
1317 1311
1318 /* 1312 /*
1319 * Read in the built-in rules first, followed by the specified 1313 * Read in the built-in rules first, followed by the specified
1320 * makefile, if it was (makefile != NULL), or the default 1314 * makefile, if it was (makefile != NULL), or the default
1321 * makefile and Makefile, in that order, if it wasn't. 1315 * makefile and Makefile, in that order, if it wasn't.
1322 */ 1316 */
1323 if (!noBuiltins) { 1317 if (!noBuiltins) {
1324 LstNode ln; 1318 LstNode ln;
1325 1319
1326 sysMkPath = Lst_Init(); 1320 sysMkPath = Lst_Init();
1327 Dir_Expand(_PATH_DEFSYSMK, 1321 Dir_Expand(_PATH_DEFSYSMK,
1328 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath, 1322 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
1329 sysMkPath); 1323 sysMkPath);
1330 if (Lst_IsEmpty(sysMkPath)) 1324 if (Lst_IsEmpty(sysMkPath))
1331 Fatal("%s: no system rules (%s).", progname, 1325 Fatal("%s: no system rules (%s).", progname,
1332 _PATH_DEFSYSMK); 1326 _PATH_DEFSYSMK);
1333 ln = Lst_Find(sysMkPath, ReadMakefile, NULL); 1327 ln = Lst_Find(sysMkPath, ReadMakefile, NULL);
1334 if (ln == NULL) 1328 if (ln == NULL)
1335 Fatal("%s: cannot open %s.", progname, 1329 Fatal("%s: cannot open %s.", progname,
1336 (char *)Lst_Datum(ln)); 1330 (char *)Lst_Datum(ln));
1337 } 1331 }
1338 1332
1339 if (!Lst_IsEmpty(makefiles)) { 1333 if (!Lst_IsEmpty(makefiles)) {
1340 LstNode ln; 1334 LstNode ln;
1341 1335
1342 ln = Lst_Find(makefiles, ReadAllMakefiles, NULL); 1336 ln = Lst_Find(makefiles, ReadMakefileFailed, NULL);
1343 if (ln != NULL) 1337 if (ln != NULL)
1344 Fatal("%s: cannot open %s.", progname, 1338 Fatal("%s: cannot open %s.", progname,
1345 (char *)Lst_Datum(ln)); 1339 (char *)Lst_Datum(ln));
1346 } else { 1340 } else {
1347 p1 = Var_Subst("${" MAKEFILE_PREFERENCE "}", 1341 p1 = Var_Subst("${" MAKEFILE_PREFERENCE "}",
1348 VAR_CMD, VARE_WANTRES); 1342 VAR_CMD, VARE_WANTRES);
1349 if (p1) { 1343 if (p1) {
1350 (void)str2Lst_Append(makefiles, p1, NULL); 1344 (void)str2Lst_Append(makefiles, p1, NULL);
1351 (void)Lst_Find(makefiles, ReadMakefile, NULL); 1345 (void)Lst_Find(makefiles, ReadMakefile, NULL);
1352 free(p1); 1346 free(p1);
1353 } 1347 }
1354 } 1348 }
1355 1349
1356 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ 1350 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1357 if (!noBuiltins || !printVars) { 1351 if (!noBuiltins || !printVars) {
1358 makeDependfile = Var_Subst("${.MAKE.DEPENDFILE:T}", 1352 makeDependfile = Var_Subst("${.MAKE.DEPENDFILE:T}",
1359 VAR_CMD, VARE_WANTRES); 1353 VAR_CMD, VARE_WANTRES);
1360 doing_depend = TRUE; 1354 doing_depend = TRUE;
1361 (void)ReadMakefile(makeDependfile, NULL); 1355 (void)ReadMakefile(makeDependfile, NULL);
1362 doing_depend = FALSE; 1356 doing_depend = FALSE;
1363 } 1357 }
1364 1358
1365 if (enterFlagObj) 1359 if (enterFlagObj)
1366 printf("%s: Entering directory `%s'\n", progname, objdir); 1360 printf("%s: Entering directory `%s'\n", progname, objdir);
1367 1361
1368 MakeMode(NULL); 1362 MakeMode(NULL);
1369 1363
1370 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 1364 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
1371 bmake_free(p1); 1365 bmake_free(p1);
1372 1366
1373 if (!forceJobs && !compatMake && 1367 if (!forceJobs && !compatMake &&
1374 Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) { 1368 Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) {
1375 char *value; 1369 char *value;
1376 int n; 1370 int n;
1377 1371
1378 value = Var_Subst("${.MAKE.JOBS}", VAR_GLOBAL, VARE_WANTRES); 1372 value = Var_Subst("${.MAKE.JOBS}", VAR_GLOBAL, VARE_WANTRES);
1379 n = strtol(value, NULL, 0); 1373 n = strtol(value, NULL, 0);
1380 if (n < 1) { 1374 if (n < 1) {
1381 (void)fprintf(stderr, "%s: illegal value for .MAKE.JOBS -- must be positive integer!\n", 1375 (void)fprintf(stderr, "%s: illegal value for .MAKE.JOBS -- must be positive integer!\n",
1382 progname); 1376 progname);
1383 exit(1); 1377 exit(1);
1384 } 1378 }
1385 if (n != maxJobs) { 1379 if (n != maxJobs) {
1386 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 1380 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
1387 Var_Append(MAKEFLAGS, value, VAR_GLOBAL); 1381 Var_Append(MAKEFLAGS, value, VAR_GLOBAL);
1388 } 1382 }
1389 maxJobs = n; 1383 maxJobs = n;
1390 maxJobTokens = maxJobs; 1384 maxJobTokens = maxJobs;
1391 forceJobs = TRUE; 1385 forceJobs = TRUE;
1392 free(value); 1386 free(value);
1393 } 1387 }
1394 1388
1395 /* 1389 /*
1396 * Be compatible if user did not specify -j and did not explicitly 1390 * Be compatible if user did not specify -j and did not explicitly
1397 * turned compatibility on 1391 * turned compatibility on
1398 */ 1392 */
1399 if (!compatMake && !forceJobs) { 1393 if (!compatMake && !forceJobs) {
1400 compatMake = TRUE; 1394 compatMake = TRUE;
1401 } 1395 }
1402 1396
1403 if (!compatMake) 1397 if (!compatMake)
1404 Job_ServerStart(maxJobTokens, jp_0, jp_1); 1398 Job_ServerStart(maxJobTokens, jp_0, jp_1);
1405 if (DEBUG(JOB)) 1399 if (DEBUG(JOB))
1406 fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", 1400 fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1407 jp_0, jp_1, maxJobs, maxJobTokens, compatMake); 1401 jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
1408 1402
1409 if (!printVars) 1403 if (!printVars)
1410 Main_ExportMAKEFLAGS(TRUE); /* initial export */ 1404 Main_ExportMAKEFLAGS(TRUE); /* initial export */
1411 1405
1412 1406
1413 /* 1407 /*
1414 * For compatibility, look at the directories in the VPATH variable 1408 * For compatibility, look at the directories in the VPATH variable
1415 * and add them to the search path, if the variable is defined. The 1409 * and add them to the search path, if the variable is defined. The
1416 * variable's value is in the same format as the PATH envariable, i.e. 1410 * variable's value is in the same format as the PATH envariable, i.e.
1417 * <directory>:<directory>:<directory>... 1411 * <directory>:<directory>:<directory>...
1418 */ 1412 */
1419 if (Var_Exists("VPATH", VAR_CMD)) { 1413 if (Var_Exists("VPATH", VAR_CMD)) {
1420 char *vpath, savec; 1414 char *vpath, savec;
1421 /* 1415 /*
1422 * GCC stores string constants in read-only memory, but 1416 * GCC stores string constants in read-only memory, but
1423 * Var_Subst will want to write this thing, so store it 1417 * Var_Subst will want to write this thing, so store it
1424 * in an array 1418 * in an array
1425 */ 1419 */
1426 static char VPATH[] = "${VPATH}"; 1420 static char VPATH[] = "${VPATH}";
1427 1421
1428 vpath = Var_Subst(VPATH, VAR_CMD, VARE_WANTRES); 1422 vpath = Var_Subst(VPATH, VAR_CMD, VARE_WANTRES);
1429 path = vpath; 1423 path = vpath;
1430 do { 1424 do {
1431 /* skip to end of directory */ 1425 /* skip to end of directory */
1432 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 1426 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1433 continue; 1427 continue;
1434 /* Save terminator character so know when to stop */ 1428 /* Save terminator character so know when to stop */
1435 savec = *cp; 1429 savec = *cp;
1436 *cp = '\0'; 1430 *cp = '\0';
1437 /* Add directory to search path */ 1431 /* Add directory to search path */
1438 (void)Dir_AddDir(dirSearchPath, path); 1432 (void)Dir_AddDir(dirSearchPath, path);
1439 *cp = savec; 1433 *cp = savec;
1440 path = cp + 1; 1434 path = cp + 1;
1441 } while (savec == ':'); 1435 } while (savec == ':');
1442 free(vpath); 1436 free(vpath);
1443 } 1437 }
1444 1438
1445 /* 1439 /*
1446 * Now that all search paths have been read for suffixes et al, it's 1440 * Now that all search paths have been read for suffixes et al, it's
1447 * time to add the default search path to their lists... 1441 * time to add the default search path to their lists...
1448 */ 1442 */
1449 Suff_DoPaths(); 1443 Suff_DoPaths();
1450 1444
1451 /* 1445 /*
1452 * Propagate attributes through :: dependency lists. 1446 * Propagate attributes through :: dependency lists.
1453 */ 1447 */
1454 Targ_Propagate(); 1448 Targ_Propagate();
1455 1449
1456 /* print the initial graph, if the user requested it */ 1450 /* print the initial graph, if the user requested it */
1457 if (DEBUG(GRAPH1)) 1451 if (DEBUG(GRAPH1))
1458 Targ_PrintGraph(1); 1452 Targ_PrintGraph(1);
1459 1453
1460 /* print the values of any variables requested by the user */ 1454 /* print the values of any variables requested by the user */
1461 if (printVars) { 1455 if (printVars) {
1462 doPrintVars(); 1456 doPrintVars();
1463 outOfDate = FALSE; 1457 outOfDate = FALSE;
1464 } else { 1458 } else {
1465 outOfDate = runTargets(); 1459 outOfDate = runTargets();
1466 } 1460 }
1467 1461
1468#ifdef CLEANUP 1462#ifdef CLEANUP
1469 Lst_Free(variables); 1463 Lst_Free(variables);
1470 Lst_Free(makefiles); 1464 Lst_Free(makefiles);
1471 Lst_Destroy(create, free); 1465 Lst_Destroy(create, free);
1472#endif 1466#endif
1473 1467
1474 /* print the graph now it's been processed if the user requested it */ 1468 /* print the graph now it's been processed if the user requested it */
1475 if (DEBUG(GRAPH2)) 1469 if (DEBUG(GRAPH2))
1476 Targ_PrintGraph(2); 1470 Targ_PrintGraph(2);
1477 1471
1478 Trace_Log(MAKEEND, 0); 1472 Trace_Log(MAKEEND, 0);
1479 1473
1480 if (enterFlagObj) 1474 if (enterFlagObj)
1481 printf("%s: Leaving directory `%s'\n", progname, objdir); 1475 printf("%s: Leaving directory `%s'\n", progname, objdir);
1482 if (enterFlag) 1476 if (enterFlag)
1483 printf("%s: Leaving directory `%s'\n", progname, curdir); 1477 printf("%s: Leaving directory `%s'\n", progname, curdir);
1484 1478
1485#ifdef USE_META 1479#ifdef USE_META
1486 meta_finish(); 1480 meta_finish();
1487#endif 1481#endif
1488 Suff_End(); 1482 Suff_End();
1489 Targ_End(); 1483 Targ_End();
1490 Arch_End(); 1484 Arch_End();
1491 Var_End(); 1485 Var_End();
1492 Parse_End(); 1486 Parse_End();
1493 Dir_End(); 1487 Dir_End();
1494 Job_End(); 1488 Job_End();
1495 Trace_End(); 1489 Trace_End();
1496 1490
1497 return outOfDate ? 1 : 0; 1491 return outOfDate ? 1 : 0;
1498} 1492}
1499 1493
1500/*- 1494/* Open and parse the given makefile, with all its side effects.
1501 * ReadMakefile -- 
1502 * Open and parse the given makefile. 
1503 * 1495 *
1504 * Results: 1496 * Results:
1505 * 0 if ok. -1 if couldn't open file. 1497 * 0 if ok. -1 if couldn't open file.
1506 * 
1507 * Side Effects: 
1508 * lots 
1509 */ 1498 */
1510static int 1499static int
1511ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED) 1500ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
1512{ 1501{
1513 const char *fname = p; /* makefile to read */ 1502 const char *fname = p; /* makefile to read */
1514 int fd; 1503 int fd;
1515 char *name, *path = NULL; 1504 char *name, *path = NULL;
1516 1505
1517 if (!strcmp(fname, "-")) { 1506 if (!strcmp(fname, "-")) {
1518 Parse_File(NULL /*stdin*/, -1); 1507 Parse_File(NULL /*stdin*/, -1);
1519 Var_Set("MAKEFILE", "", VAR_INTERNAL); 1508 Var_Set("MAKEFILE", "", VAR_INTERNAL);
1520 } else { 1509 } else {
1521 /* if we've chdir'd, rebuild the path name */ 1510 /* if we've chdir'd, rebuild the path name */
1522 if (strcmp(curdir, objdir) && *fname != '/') { 1511 if (strcmp(curdir, objdir) && *fname != '/') {
1523 path = str_concat3(curdir, "/", fname); 1512 path = str_concat3(curdir, "/", fname);
1524 fd = open(path, O_RDONLY); 1513 fd = open(path, O_RDONLY);
1525 if (fd != -1) { 1514 if (fd != -1) {
1526 fname = path; 1515 fname = path;
1527 goto found; 1516 goto found;
1528 } 1517 }
1529 free(path); 1518 free(path);
1530 1519
1531 /* If curdir failed, try objdir (ala .depend) */ 1520 /* If curdir failed, try objdir (ala .depend) */
1532 path = str_concat3(objdir, "/", fname); 1521 path = str_concat3(objdir, "/", fname);
1533 fd = open(path, O_RDONLY); 1522 fd = open(path, O_RDONLY);
1534 if (fd != -1) { 1523 if (fd != -1) {
1535 fname = path; 1524 fname = path;
1536 goto found; 1525 goto found;
1537 } 1526 }
1538 } else { 1527 } else {
1539 fd = open(fname, O_RDONLY); 1528 fd = open(fname, O_RDONLY);
1540 if (fd != -1) 1529 if (fd != -1)
1541 goto found; 1530 goto found;
1542 } 1531 }
1543 /* look in -I and system include directories. */ 1532 /* look in -I and system include directories. */
1544 name = Dir_FindFile(fname, parseIncPath); 1533 name = Dir_FindFile(fname, parseIncPath);
1545 if (!name) 1534 if (!name)
1546 name = Dir_FindFile(fname, 1535 name = Dir_FindFile(fname,
1547 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); 1536 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1548 if (!name || (fd = open(name, O_RDONLY)) == -1) { 1537 if (!name || (fd = open(name, O_RDONLY)) == -1) {
1549 free(name); 1538 free(name);
1550 free(path); 1539 free(path);
1551 return -1; 1540 return -1;
1552 } 1541 }
1553 fname = name; 1542 fname = name;
1554 /* 1543 /*
1555 * set the MAKEFILE variable desired by System V fans -- the 1544 * set the MAKEFILE variable desired by System V fans -- the
1556 * placement of the setting here means it gets set to the last 1545 * placement of the setting here means it gets set to the last
1557 * makefile specified, as it is set by SysV make. 1546 * makefile specified, as it is set by SysV make.
1558 */ 1547 */
1559found: 1548found:
1560 if (!doing_depend) 1549 if (!doing_depend)
1561 Var_Set("MAKEFILE", fname, VAR_INTERNAL); 1550 Var_Set("MAKEFILE", fname, VAR_INTERNAL);
1562 Parse_File(fname, fd); 1551 Parse_File(fname, fd);
1563 } 1552 }
1564 free(path); 1553 free(path);
1565 return 0; 1554 return 0;
1566} 1555}
1567 1556
1568 1557
1569 1558
1570/*- 1559/*-
1571 * Cmd_Exec -- 1560 * Cmd_Exec --
1572 * Execute the command in cmd, and return the output of that command 1561 * Execute the command in cmd, and return the output of that command
1573 * in a string. In the output, newlines are replaced with spaces. 1562 * in a string. In the output, newlines are replaced with spaces.
1574 * 1563 *
1575 * Results: 1564 * Results:
1576 * A string containing the output of the command, or the empty string. 1565 * A string containing the output of the command, or the empty string.
1577 * *errfmt returns a format string describing the command failure, 1566 * *errfmt returns a format string describing the command failure,
1578 * if any, using a single %s conversion specification. 1567 * if any, using a single %s conversion specification.
1579 * 1568 *
1580 * Side Effects: 1569 * Side Effects:
1581 * The string must be freed by the caller. 1570 * The string must be freed by the caller.
1582 */ 1571 */
1583char * 1572char *
1584Cmd_Exec(const char *cmd, const char **errfmt) 1573Cmd_Exec(const char *cmd, const char **errfmt)
1585{ 1574{
1586 const char *args[4]; /* Args for invoking the shell */ 1575 const char *args[4]; /* Args for invoking the shell */
1587 int fds[2]; /* Pipe streams */ 1576 int fds[2]; /* Pipe streams */
1588 int cpid; /* Child PID */ 1577 int cpid; /* Child PID */
1589 int pid; /* PID from wait() */ 1578 int pid; /* PID from wait() */
1590 int status; /* command exit status */ 1579 int status; /* command exit status */
1591 Buffer buf; /* buffer to store the result */ 1580 Buffer buf; /* buffer to store the result */
1592 ssize_t bytes_read; 1581 ssize_t bytes_read;
1593 char *res; /* result */ 1582 char *res; /* result */
1594 size_t res_len; 1583 size_t res_len;
1595 char *cp; 1584 char *cp;
1596 int savederr; /* saved errno */ 1585 int savederr; /* saved errno */
1597 1586
1598 *errfmt = NULL; 1587 *errfmt = NULL;
1599 1588
1600 if (!shellName) 1589 if (!shellName)
1601 Shell_Init(); 1590 Shell_Init();
1602 /* 1591 /*
1603 * Set up arguments for shell 1592 * Set up arguments for shell
1604 */ 1593 */
1605 args[0] = shellName; 1594 args[0] = shellName;
1606 args[1] = "-c"; 1595 args[1] = "-c";
1607 args[2] = cmd; 1596 args[2] = cmd;
1608 args[3] = NULL; 1597 args[3] = NULL;
1609 1598
1610 /* 1599 /*
1611 * Open a pipe for fetching its output 1600 * Open a pipe for fetching its output
1612 */ 1601 */
1613 if (pipe(fds) == -1) { 1602 if (pipe(fds) == -1) {
1614 *errfmt = "Couldn't create pipe for \"%s\""; 1603 *errfmt = "Couldn't create pipe for \"%s\"";
1615 goto bad; 1604 goto bad;
1616 } 1605 }
1617 1606
1618 /* 1607 /*
1619 * Fork 1608 * Fork
1620 */ 1609 */
1621 switch (cpid = vFork()) { 1610 switch (cpid = vFork()) {
1622 case 0: 1611 case 0:
1623 /* 1612 /*
1624 * Close input side of pipe 1613 * Close input side of pipe
1625 */ 1614 */
1626 (void)close(fds[0]); 1615 (void)close(fds[0]);
1627 1616
1628 /* 1617 /*
1629 * Duplicate the output stream to the shell's output, then 1618 * Duplicate the output stream to the shell's output, then
1630 * shut the extra thing down. Note we don't fetch the error 1619 * shut the extra thing down. Note we don't fetch the error
1631 * stream...why not? Why? 1620 * stream...why not? Why?
1632 */ 1621 */
1633 (void)dup2(fds[1], 1); 1622 (void)dup2(fds[1], 1);
1634 (void)close(fds[1]); 1623 (void)close(fds[1]);
1635 1624
1636 Var_ExportVars(); 1625 Var_ExportVars();
1637 1626
1638 (void)execv(shellPath, UNCONST(args)); 1627 (void)execv(shellPath, UNCONST(args));
1639 _exit(1); 1628 _exit(1);
1640 /*NOTREACHED*/ 1629 /*NOTREACHED*/
1641 1630
1642 case -1: 1631 case -1:
1643 *errfmt = "Couldn't exec \"%s\""; 1632 *errfmt = "Couldn't exec \"%s\"";
1644 goto bad; 1633 goto bad;
1645 1634
1646 default: 1635 default:
1647 /* 1636 /*
1648 * No need for the writing half 1637 * No need for the writing half
1649 */ 1638 */
1650 (void)close(fds[1]); 1639 (void)close(fds[1]);
1651 1640
1652 savederr = 0; 1641 savederr = 0;
1653 Buf_Init(&buf, 0); 1642 Buf_Init(&buf, 0);
1654 1643
1655 do { 1644 do {
1656 char result[BUFSIZ]; 1645 char result[BUFSIZ];
1657 bytes_read = read(fds[0], result, sizeof(result)); 1646 bytes_read = read(fds[0], result, sizeof(result));
1658 if (bytes_read > 0) 1647 if (bytes_read > 0)
1659 Buf_AddBytes(&buf, result, (size_t)bytes_read); 1648 Buf_AddBytes(&buf, result, (size_t)bytes_read);
1660 } 1649 }
1661 while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR)); 1650 while (bytes_read > 0 || (bytes_read == -1 && errno == EINTR));
1662 if (bytes_read == -1) 1651 if (bytes_read == -1)
1663 savederr = errno; 1652 savederr = errno;
1664 1653
1665 /* 1654 /*
1666 * Close the input side of the pipe. 1655 * Close the input side of the pipe.
1667 */ 1656 */
1668 (void)close(fds[0]); 1657 (void)close(fds[0]);
1669 1658
1670 /* 1659 /*
1671 * Wait for the process to exit. 1660 * Wait for the process to exit.
1672 */ 1661 */
1673 while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) { 1662 while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) {
1674 JobReapChild(pid, status, FALSE); 1663 JobReapChild(pid, status, FALSE);
1675 continue; 1664 continue;
1676 } 1665 }
1677 res_len = Buf_Size(&buf); 1666 res_len = Buf_Size(&buf);
1678 res = Buf_Destroy(&buf, FALSE); 1667 res = Buf_Destroy(&buf, FALSE);
1679 1668
1680 if (savederr != 0) 1669 if (savederr != 0)
1681 *errfmt = "Couldn't read shell's output for \"%s\""; 1670 *errfmt = "Couldn't read shell's output for \"%s\"";
1682 1671
1683 if (WIFSIGNALED(status)) 1672 if (WIFSIGNALED(status))
1684 *errfmt = "\"%s\" exited on a signal"; 1673 *errfmt = "\"%s\" exited on a signal";
1685 else if (WEXITSTATUS(status) != 0) 1674 else if (WEXITSTATUS(status) != 0)
1686 *errfmt = "\"%s\" returned non-zero status"; 1675 *errfmt = "\"%s\" returned non-zero status";
1687 1676
1688 /* Convert newlines to spaces. A final newline is just stripped */ 1677 /* Convert newlines to spaces. A final newline is just stripped */
1689 if (res_len > 0 && res[res_len - 1] == '\n') 1678 if (res_len > 0 && res[res_len - 1] == '\n')
1690 res[res_len - 1] = '\0'; 1679 res[res_len - 1] = '\0';
1691 for (cp = res; *cp != '\0'; cp++) 1680 for (cp = res; *cp != '\0'; cp++)
1692 if (*cp == '\n') 1681 if (*cp == '\n')
1693 *cp = ' '; 1682 *cp = ' ';
1694 break; 1683 break;
1695 } 1684 }
1696 return res; 1685 return res;
1697bad: 1686bad:
1698 return bmake_strdup(""); 1687 return bmake_strdup("");
1699} 1688}
1700 1689
1701/*- 1690/*-
1702 * Error -- 1691 * Error --
1703 * Print an error message given its format. 1692 * Print an error message given its format.
1704 * 1693 *
1705 * Results: 1694 * Results:
1706 * None. 1695 * None.
1707 * 1696 *
1708 * Side Effects: 1697 * Side Effects:
1709 * The message is printed. 1698 * The message is printed.
1710 */ 1699 */
1711/* VARARGS */ 1700/* VARARGS */
1712void 1701void
1713Error(const char *fmt, ...) 1702Error(const char *fmt, ...)
1714{ 1703{
1715 va_list ap; 1704 va_list ap;
1716 FILE *err_file; 1705 FILE *err_file;
1717 1706
1718 err_file = debug_file; 1707 err_file = debug_file;
1719 if (err_file == stdout) 1708 if (err_file == stdout)
1720 err_file = stderr; 1709 err_file = stderr;
1721 (void)fflush(stdout); 1710 (void)fflush(stdout);
1722 for (;;) { 1711 for (;;) {
1723 va_start(ap, fmt); 1712 va_start(ap, fmt);
1724 fprintf(err_file, "%s: ", progname); 1713 fprintf(err_file, "%s: ", progname);
1725 (void)vfprintf(err_file, fmt, ap); 1714 (void)vfprintf(err_file, fmt, ap);
1726 va_end(ap); 1715 va_end(ap);
1727 (void)fprintf(err_file, "\n"); 1716 (void)fprintf(err_file, "\n");
1728 (void)fflush(err_file); 1717 (void)fflush(err_file);
1729 if (err_file == stderr) 1718 if (err_file == stderr)
1730 break; 1719 break;
1731 err_file = stderr; 1720 err_file = stderr;
1732 } 1721 }
1733} 1722}
1734 1723
1735/*- 1724/*-
1736 * Fatal -- 1725 * Fatal --
1737 * Produce a Fatal error message. If jobs are running, waits for them 1726 * Produce a Fatal error message. If jobs are running, waits for them
1738 * to finish. 1727 * to finish.
1739 * 1728 *
1740 * Results: 1729 * Results:
1741 * None 1730 * None
1742 * 1731 *
1743 * Side Effects: 1732 * Side Effects:
1744 * The program exits 1733 * The program exits
1745 */ 1734 */
1746/* VARARGS */ 1735/* VARARGS */
1747void 1736void
1748Fatal(const char *fmt, ...) 1737Fatal(const char *fmt, ...)
1749{ 1738{
1750 va_list ap; 1739 va_list ap;
1751 1740
1752 va_start(ap, fmt); 1741 va_start(ap, fmt);
1753 if (jobsRunning) 1742 if (jobsRunning)
1754 Job_Wait(); 1743 Job_Wait();
1755 1744
1756 (void)fflush(stdout); 1745 (void)fflush(stdout);
1757 (void)vfprintf(stderr, fmt, ap); 1746 (void)vfprintf(stderr, fmt, ap);
1758 va_end(ap); 1747 va_end(ap);
1759 (void)fprintf(stderr, "\n"); 1748 (void)fprintf(stderr, "\n");
1760 (void)fflush(stderr); 1749 (void)fflush(stderr);
1761 1750
1762 PrintOnError(NULL, NULL); 1751 PrintOnError(NULL, NULL);
1763 1752
1764 if (DEBUG(GRAPH2) || DEBUG(GRAPH3)) 1753 if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1765 Targ_PrintGraph(2); 1754 Targ_PrintGraph(2);
1766 Trace_Log(MAKEERROR, 0); 1755 Trace_Log(MAKEERROR, 0);
1767 exit(2); /* Not 1 so -q can distinguish error */ 1756 exit(2); /* Not 1 so -q can distinguish error */
1768} 1757}
1769 1758
1770/* 1759/*
1771 * Punt -- 1760 * Punt --
1772 * Major exception once jobs are being created. Kills all jobs, prints 1761 * Major exception once jobs are being created. Kills all jobs, prints
1773 * a message and exits. 1762 * a message and exits.
1774 * 1763 *
1775 * Results: 1764 * Results:
1776 * None 1765 * None
1777 * 1766 *
1778 * Side Effects: 1767 * Side Effects:
1779 * All children are killed indiscriminately and the program Lib_Exits 1768 * All children are killed indiscriminately and the program Lib_Exits
1780 */ 1769 */
1781/* VARARGS */ 1770/* VARARGS */
1782void 1771void
1783Punt(const char *fmt, ...) 1772Punt(const char *fmt, ...)
1784{ 1773{
1785 va_list ap; 1774 va_list ap;
1786 1775
1787 va_start(ap, fmt); 1776 va_start(ap, fmt);
1788 (void)fflush(stdout); 1777 (void)fflush(stdout);
1789 (void)fprintf(stderr, "%s: ", progname); 1778 (void)fprintf(stderr, "%s: ", progname);
1790 (void)vfprintf(stderr, fmt, ap); 1779 (void)vfprintf(stderr, fmt, ap);
1791 va_end(ap); 1780 va_end(ap);
1792 (void)fprintf(stderr, "\n"); 1781 (void)fprintf(stderr, "\n");
1793 (void)fflush(stderr); 1782 (void)fflush(stderr);
1794 1783
1795 PrintOnError(NULL, NULL); 1784 PrintOnError(NULL, NULL);
1796 1785
1797 DieHorribly(); 1786 DieHorribly();
1798} 1787}
1799 1788
1800/*- 1789/*-
1801 * DieHorribly -- 1790 * DieHorribly --
1802 * Exit without giving a message. 1791 * Exit without giving a message.
1803 * 1792 *
1804 * Results: 1793 * Results:
1805 * None 1794 * None
1806 * 1795 *
1807 * Side Effects: 1796 * Side Effects:
1808 * A big one... 1797 * A big one...
1809 */ 1798 */
1810void 1799void
1811DieHorribly(void) 1800DieHorribly(void)
1812{ 1801{
1813 if (jobsRunning) 1802 if (jobsRunning)
1814 Job_AbortAll(); 1803 Job_AbortAll();
1815 if (DEBUG(GRAPH2)) 1804 if (DEBUG(GRAPH2))
1816 Targ_PrintGraph(2); 1805 Targ_PrintGraph(2);
1817 Trace_Log(MAKEERROR, 0); 1806 Trace_Log(MAKEERROR, 0);
1818 exit(2); /* Not 1, so -q can distinguish error */ 1807 exit(2); /* Not 1, so -q can distinguish error */
1819} 1808}
1820 1809
1821/* 1810/*
1822 * Finish -- 1811 * Finish --
1823 * Called when aborting due to errors in child shell to signal 1812 * Called when aborting due to errors in child shell to signal
1824 * abnormal exit. 1813 * abnormal exit.
1825 * 1814 *
1826 * Results: 1815 * Results:
1827 * None 1816 * None
1828 * 1817 *
1829 * Side Effects: 1818 * Side Effects:
1830 * The program exits 1819 * The program exits
1831 */ 1820 */
1832void 1821void
1833Finish(int errors) 1822Finish(int errors)
1834 /* number of errors encountered in Make_Make */ 1823 /* number of errors encountered in Make_Make */
1835{ 1824{
1836 if (dieQuietly(NULL, -1)) 1825 if (dieQuietly(NULL, -1))
1837 exit(2); 1826 exit(2);
1838 Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 1827 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1839} 1828}
1840 1829
1841/* 1830/*
1842 * eunlink -- 1831 * eunlink --
1843 * Remove a file carefully, avoiding directories. 1832 * Remove a file carefully, avoiding directories.
1844 */ 1833 */
1845int 1834int
1846eunlink(const char *file) 1835eunlink(const char *file)
1847{ 1836{
1848 struct stat st; 1837 struct stat st;
1849 1838
1850 if (lstat(file, &st) == -1) 1839 if (lstat(file, &st) == -1)
1851 return -1; 1840 return -1;
1852 1841
1853 if (S_ISDIR(st.st_mode)) { 1842 if (S_ISDIR(st.st_mode)) {
1854 errno = EISDIR; 1843 errno = EISDIR;
1855 return -1; 1844 return -1;
1856 } 1845 }
1857 return unlink(file); 1846 return unlink(file);
1858} 1847}
1859 1848
1860/* 1849/*
1861 * execError -- 1850 * execError --
1862 * Print why exec failed, avoiding stdio. 1851 * Print why exec failed, avoiding stdio.
1863 */ 1852 */
1864void 1853void
1865execError(const char *af, const char *av) 1854execError(const char *af, const char *av)
1866{ 1855{
1867#ifdef USE_IOVEC 1856#ifdef USE_IOVEC
1868 int i = 0; 1857 int i = 0;
1869 struct iovec iov[8]; 1858 struct iovec iov[8];
1870#define IOADD(s) \ 1859#define IOADD(s) \
1871 (void)(iov[i].iov_base = UNCONST(s), \ 1860 (void)(iov[i].iov_base = UNCONST(s), \
1872 iov[i].iov_len = strlen(iov[i].iov_base), \ 1861 iov[i].iov_len = strlen(iov[i].iov_base), \
1873 i++) 1862 i++)
1874#else 1863#else
1875#define IOADD(void)write(2, s, strlen(s)) 1864#define IOADD(void)write(2, s, strlen(s))
1876#endif 1865#endif
1877 1866
1878 IOADD(progname); 1867 IOADD(progname);
1879 IOADD(": "); 1868 IOADD(": ");
1880 IOADD(af); 1869 IOADD(af);
1881 IOADD("("); 1870 IOADD("(");
1882 IOADD(av); 1871 IOADD(av);
1883 IOADD(") failed ("); 1872 IOADD(") failed (");
1884 IOADD(strerror(errno)); 1873 IOADD(strerror(errno));
1885 IOADD(")\n"); 1874 IOADD(")\n");
1886 1875
1887#ifdef USE_IOVEC 1876#ifdef USE_IOVEC
1888 while (writev(2, iov, 8) == -1 && errno == EAGAIN) 1877 while (writev(2, iov, 8) == -1 && errno == EAGAIN)
1889 continue; 1878 continue;
1890#endif 1879#endif
1891} 1880}
1892 1881
1893/* 1882/*
1894 * usage -- 1883 * usage --
1895 * exit with usage message 1884 * exit with usage message
1896 */ 1885 */
1897static void 1886static void
1898usage(void) 1887usage(void)
1899{ 1888{
1900 char *p; 1889 char *p;
1901 if ((p = strchr(progname, '[')) != NULL) 1890 if ((p = strchr(progname, '[')) != NULL)
1902 *p = '\0'; 1891 *p = '\0';
1903 1892
1904 (void)fprintf(stderr, 1893 (void)fprintf(stderr,
1905"usage: %s [-BeikNnqrstWwX] \n" 1894"usage: %s [-BeikNnqrstWwX] \n"
1906" [-C directory] [-D variable] [-d flags] [-f makefile]\n" 1895" [-C directory] [-D variable] [-d flags] [-f makefile]\n"
1907" [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n" 1896" [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n"
1908" [-V variable] [-v variable] [variable=value] [target ...]\n", 1897" [-V variable] [-v variable] [variable=value] [target ...]\n",
1909 progname); 1898 progname);
1910 exit(2); 1899 exit(2);
1911} 1900}
1912 1901
1913/* 1902/*
1914 * realpath(3) can get expensive, cache results... 1903 * realpath(3) can get expensive, cache results...
1915 */ 1904 */
1916static GNode *cached_realpaths = NULL; 1905static GNode *cached_realpaths = NULL;
1917 1906
1918static GNode * 1907static GNode *
1919get_cached_realpaths(void) 1908get_cached_realpaths(void)
1920{ 1909{
1921 1910
1922 if (!cached_realpaths) { 1911 if (!cached_realpaths) {
1923 cached_realpaths = Targ_NewGN("Realpath"); 1912 cached_realpaths = Targ_NewGN("Realpath");
1924#ifndef DEBUG_REALPATH_CACHE 1913#ifndef DEBUG_REALPATH_CACHE
1925 cached_realpaths->flags = INTERNAL; 1914 cached_realpaths->flags = INTERNAL;
1926#endif 1915#endif
1927 } 1916 }
1928 1917
1929 return cached_realpaths; 1918 return cached_realpaths;
1930} 1919}
1931 1920
1932/* purge any relative paths */ 1921/* purge any relative paths */
1933static void 1922static void
1934purge_cached_realpaths(void) 1923purge_cached_realpaths(void)
1935{ 1924{
1936 GNode *cache = get_cached_realpaths(); 1925 GNode *cache = get_cached_realpaths();
1937 Hash_Entry *he, *nhe; 1926 Hash_Entry *he, *nhe;
1938 Hash_Search hs; 1927 Hash_Search hs;
1939 1928
1940 he = Hash_EnumFirst(&cache->context, &hs); 1929 he = Hash_EnumFirst(&cache->context, &hs);
1941 while (he) { 1930 while (he) {
1942 nhe = Hash_EnumNext(&hs); 1931 nhe = Hash_EnumNext(&hs);
1943 if (he->name[0] != '/') { 1932 if (he->name[0] != '/') {
1944 if (DEBUG(DIR)) 1933 if (DEBUG(DIR))
1945 fprintf(stderr, "cached_realpath: purging %s\n", he->name); 1934 fprintf(stderr, "cached_realpath: purging %s\n", he->name);
1946 Hash_DeleteEntry(&cache->context, he); 1935 Hash_DeleteEntry(&cache->context, he);
1947 } 1936 }
1948 he = nhe; 1937 he = nhe;
1949 } 1938 }
1950} 1939}
1951 1940
1952char * 1941char *
1953cached_realpath(const char *pathname, char *resolved) 1942cached_realpath(const char *pathname, char *resolved)
1954{ 1943{
1955 GNode *cache; 1944 GNode *cache;
1956 const char *rp; 1945 const char *rp;
1957 char *cp; 1946 char *cp;
1958 1947
1959 if (!pathname || !pathname[0]) 1948 if (!pathname || !pathname[0])
1960 return NULL; 1949 return NULL;
1961 1950
1962 cache = get_cached_realpaths(); 1951 cache = get_cached_realpaths();
1963 1952
1964 if ((rp = Var_Value(pathname, cache, &cp)) != NULL) { 1953 if ((rp = Var_Value(pathname, cache, &cp)) != NULL) {
1965 /* a hit */ 1954 /* a hit */
1966 strncpy(resolved, rp, MAXPATHLEN); 1955 strncpy(resolved, rp, MAXPATHLEN);
1967 resolved[MAXPATHLEN - 1] = '\0'; 1956 resolved[MAXPATHLEN - 1] = '\0';
1968 } else if ((rp = realpath(pathname, resolved)) != NULL) { 1957 } else if ((rp = realpath(pathname, resolved)) != NULL) {
1969 Var_Set(pathname, rp, cache); 1958 Var_Set(pathname, rp, cache);
1970 } /* else should we negative-cache? */ 1959 } /* else should we negative-cache? */
1971 1960
1972 bmake_free(cp); 1961 bmake_free(cp);
1973 return rp ? resolved : NULL; 1962 return rp ? resolved : NULL;
1974} 1963}
1975 1964
1976int 1965int
1977PrintAddr(void *a, void *b) 1966PrintAddr(void *a, void *b)
1978{ 1967{
1979 printf("%lx ", (unsigned long) a); 1968 printf("%lx ", (unsigned long) a);
1980 return b ? 0 : 0; 1969 return b ? 0 : 0;
1981} 1970}
1982 1971
1983 1972
1984static int 1973static int
1985addErrorCMD(void *cmdp, void *gnp) 1974addErrorCMD(void *cmdp, void *gnp)
1986{ 1975{
1987 if (cmdp == NULL) 1976 if (cmdp == NULL)
1988 return 1; /* stop */ 1977 return 1; /* stop */
1989 Var_Append(".ERROR_CMD", cmdp, VAR_GLOBAL); 1978 Var_Append(".ERROR_CMD", cmdp, VAR_GLOBAL);
1990 return 0; 1979 return 0;
1991} 1980}
1992 1981
1993/* 1982/*
1994 * Return true if we should die without noise. 1983 * Return true if we should die without noise.
1995 * For example our failing child was a sub-make 1984 * For example our failing child was a sub-make
1996 * or failure happend elsewhere. 1985 * or failure happend elsewhere.
1997 */ 1986 */
1998int 1987int
1999dieQuietly(GNode *gn, int bf) 1988dieQuietly(GNode *gn, int bf)
2000{ 1989{
2001 static int quietly = -1; 1990 static int quietly = -1;
2002 1991
2003 if (quietly < 0) { 1992 if (quietly < 0) {
2004 if (DEBUG(JOB) || getBoolean(".MAKE.DIE_QUIETLY", 1) == 0) 1993 if (DEBUG(JOB) || getBoolean(".MAKE.DIE_QUIETLY", 1) == 0)
2005 quietly = 0; 1994 quietly = 0;
2006 else if (bf >= 0) 1995 else if (bf >= 0)
2007 quietly = bf; 1996 quietly = bf;
2008 else 1997 else
2009 quietly = (gn) ? ((gn->type & (OP_MAKE)) != 0) : 0; 1998 quietly = (gn) ? ((gn->type & (OP_MAKE)) != 0) : 0;
2010 } 1999 }
2011 return quietly; 2000 return quietly;
2012} 2001}
2013 2002
2014void 2003void
2015PrintOnError(GNode *gn, const char *s) 2004PrintOnError(GNode *gn, const char *s)
2016{ 2005{
2017 static GNode *en = NULL; 2006 static GNode *en = NULL;
2018 const char *expr; 2007 const char *expr;
2019 char *cp; 2008 char *cp;
2020 2009
2021 if (DEBUG(HASH)) { 2010 if (DEBUG(HASH)) {
2022 Targ_Stats(); 2011 Targ_Stats();
2023 Var_Stats(); 2012 Var_Stats();
2024 } 2013 }
2025 2014
2026 /* we generally want to keep quiet if a sub-make died */ 2015 /* we generally want to keep quiet if a sub-make died */
2027 if (dieQuietly(gn, -1)) 2016 if (dieQuietly(gn, -1))
2028 return; 2017 return;
2029 2018
2030 if (s) 2019 if (s)
2031 printf("%s", s); 2020 printf("%s", s);
2032 2021
2033 printf("\n%s: stopped in %s\n", progname, curdir); 2022 printf("\n%s: stopped in %s\n", progname, curdir);
2034 2023
2035 if (en) 2024 if (en)
2036 return; /* we've been here! */ 2025 return; /* we've been here! */
2037 if (gn) { 2026 if (gn) {
2038 /* 2027 /*
2039 * We can print this even if there is no .ERROR target. 2028 * We can print this even if there is no .ERROR target.
2040 */ 2029 */
2041 Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL); 2030 Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL);
2042 Var_Delete(".ERROR_CMD", VAR_GLOBAL); 2031 Var_Delete(".ERROR_CMD", VAR_GLOBAL);
2043 Lst_ForEach(gn->commands, addErrorCMD, gn); 2032 Lst_ForEach(gn->commands, addErrorCMD, gn);
2044 } 2033 }
2045 expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}"; 2034 expr = "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}";
2046 cp = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES); 2035 cp = Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES);
2047 if (cp) { 2036 if (cp) {
2048 if (*cp) 2037 if (*cp)
2049 printf("%s", cp); 2038 printf("%s", cp);
2050 free(cp); 2039 free(cp);
2051 } 2040 }
2052 fflush(stdout); 2041 fflush(stdout);
2053 2042
2054 /* 2043 /*
2055 * Finally, see if there is a .ERROR target, and run it if so. 2044 * Finally, see if there is a .ERROR target, and run it if so.
2056 */ 2045 */
2057 en = Targ_FindNode(".ERROR", TARG_NOCREATE); 2046 en = Targ_FindNode(".ERROR", TARG_NOCREATE);
2058 if (en) { 2047 if (en) {
2059 en->type |= OP_SPECIAL; 2048 en->type |= OP_SPECIAL;
2060 Compat_Make(en, en); 2049 Compat_Make(en, en);
2061 } 2050 }
2062} 2051}
2063 2052
2064void 2053void
2065Main_ExportMAKEFLAGS(Boolean first) 2054Main_ExportMAKEFLAGS(Boolean first)
2066{ 2055{
2067 static int once = 1; 2056 static int once = 1;
2068 const char *expr; 2057 const char *expr;
2069 char *s; 2058 char *s;
2070 2059
2071 if (once != first) 2060 if (once != first)
2072 return; 2061 return;
2073 once = 0; 2062 once = 0;
2074 2063
2075 expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}"; 2064 expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}";
2076 s = Var_Subst(expr, VAR_CMD, VARE_WANTRES); 2065 s = Var_Subst(expr, VAR_CMD, VARE_WANTRES);
2077 if (s != NULL && s[0] != '\0') { 2066 if (s != NULL && s[0] != '\0') {
2078#ifdef POSIX 2067#ifdef POSIX
2079 setenv("MAKEFLAGS", s, 1); 2068 setenv("MAKEFLAGS", s, 1);
2080#else 2069#else
2081 setenv("MAKE", s, 1); 2070 setenv("MAKE", s, 1);
2082#endif 2071#endif
2083 } 2072 }
2084} 2073}
2085 2074
2086char * 2075char *
2087getTmpdir(void) 2076getTmpdir(void)
2088{ 2077{
2089 static char *tmpdir = NULL; 2078 static char *tmpdir = NULL;
2090 2079
2091 if (!tmpdir) { 2080 if (!tmpdir) {
2092 struct stat st; 2081 struct stat st;
2093 2082
2094 /* 2083 /*
2095 * Honor $TMPDIR but only if it is valid. 2084 * Honor $TMPDIR but only if it is valid.
2096 * Ensure it ends with /. 2085 * Ensure it ends with /.
2097 */ 2086 */
2098 tmpdir = Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 2087 tmpdir = Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL,
2099 VARE_WANTRES); 2088 VARE_WANTRES);
2100 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) { 2089 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
2101 free(tmpdir); 2090 free(tmpdir);
2102 tmpdir = bmake_strdup(_PATH_TMP); 2091 tmpdir = bmake_strdup(_PATH_TMP);
2103 } 2092 }
2104 } 2093 }
2105 return tmpdir; 2094 return tmpdir;
2106} 2095}
2107 2096
2108/* 2097/*
2109 * Create and open a temp file using "pattern". 2098 * Create and open a temp file using "pattern".
2110 * If "fnamep" is provided set it to a copy of the filename created. 2099 * If "fnamep" is provided set it to a copy of the filename created.
2111 * Otherwise unlink the file once open. 2100 * Otherwise unlink the file once open.
2112 */ 2101 */
2113int 2102int
2114mkTempFile(const char *pattern, char **fnamep) 2103mkTempFile(const char *pattern, char **fnamep)
2115{ 2104{
2116 static char *tmpdir = NULL; 2105 static char *tmpdir = NULL;
2117 char tfile[MAXPATHLEN]; 2106 char tfile[MAXPATHLEN];
2118 int fd; 2107 int fd;
2119 2108
2120 if (!pattern) 2109 if (!pattern)
2121 pattern = TMPPAT; 2110 pattern = TMPPAT;
2122 if (!tmpdir) 2111 if (!tmpdir)
2123 tmpdir = getTmpdir(); 2112 tmpdir = getTmpdir();
2124 if (pattern[0] == '/') { 2113 if (pattern[0] == '/') {
2125 snprintf(tfile, sizeof(tfile), "%s", pattern); 2114 snprintf(tfile, sizeof(tfile), "%s", pattern);
2126 } else { 2115 } else {
2127 snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern); 2116 snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
2128 } 2117 }
2129 if ((fd = mkstemp(tfile)) < 0) 2118 if ((fd = mkstemp(tfile)) < 0)
2130 Punt("Could not create temporary file %s: %s", tfile, strerror(errno)); 2119 Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
2131 if (fnamep) { 2120 if (fnamep) {
2132 *fnamep = bmake_strdup(tfile); 2121 *fnamep = bmake_strdup(tfile);
2133 } else { 2122 } else {
2134 unlink(tfile); /* we just want the descriptor */ 2123 unlink(tfile); /* we just want the descriptor */
2135 } 2124 }
2136 return fd; 2125 return fd;
2137} 2126}
2138 2127
2139/* 2128/*
2140 * Convert a string representation of a boolean. 2129 * Convert a string representation of a boolean.
2141 * Anything that looks like "No", "False", "Off", "0" etc, 2130 * Anything that looks like "No", "False", "Off", "0" etc,
2142 * is FALSE, otherwise TRUE. 2131 * is FALSE, otherwise TRUE.
2143 */ 2132 */
2144Boolean 2133Boolean
2145s2Boolean(const char *s, Boolean bf) 2134s2Boolean(const char *s, Boolean bf)
2146{ 2135{
2147 if (s) { 2136 if (s) {
2148 switch(*s) { 2137 switch(*s) {
2149 case '\0': /* not set - the default wins */ 2138 case '\0': /* not set - the default wins */
2150 break; 2139 break;
2151 case '0': 2140 case '0':
2152 case 'F': 2141 case 'F':
2153 case 'f': 2142 case 'f':
2154 case 'N': 2143 case 'N':
2155 case 'n': 2144 case 'n':
2156 bf = FALSE; 2145 bf = FALSE;
2157 break; 2146 break;
2158 case 'O': 2147 case 'O':
2159 case 'o': 2148 case 'o':
2160 switch (s[1]) { 2149 switch (s[1]) {
2161 case 'F': 2150 case 'F':
2162 case 'f': 2151 case 'f':
2163 bf = FALSE; 2152 bf = FALSE;
2164 break; 2153 break;
2165 default: 2154 default:
2166 bf = TRUE; 2155 bf = TRUE;
2167 break; 2156 break;
2168 } 2157 }
2169 break; 2158 break;
2170 default: 2159 default:
2171 bf = TRUE; 2160 bf = TRUE;
2172 break; 2161 break;
2173 } 2162 }
2174 } 2163 }
2175 return bf; 2164 return bf;
2176} 2165}
2177 2166
2178/* 2167/*
2179 * Return a Boolean based on setting of a knob. 2168 * Return a Boolean based on setting of a knob.
2180 * 2169 *
2181 * If the knob is not set, the supplied default is the return value. 2170 * If the knob is not set, the supplied default is the return value.
2182 * If set, anything that looks or smells like "No", "False", "Off", "0" etc, 2171 * If set, anything that looks or smells like "No", "False", "Off", "0" etc,
2183 * is FALSE, otherwise TRUE. 2172 * is FALSE, otherwise TRUE.
2184 */ 2173 */
2185Boolean 2174Boolean
2186getBoolean(const char *name, Boolean bf) 2175getBoolean(const char *name, Boolean bf)
2187{ 2176{
2188 char tmp[64]; 2177 char tmp[64];
2189 char *cp; 2178 char *cp;
2190 2179
2191 if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) { 2180 if (snprintf(tmp, sizeof(tmp), "${%s:U:tl}", name) < (int)(sizeof(tmp))) {
2192 cp = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES); 2181 cp = Var_Subst(tmp, VAR_GLOBAL, VARE_WANTRES);
2193 2182
2194 if (cp) { 2183 if (cp) {
2195 bf = s2Boolean(cp, bf); 2184 bf = s2Boolean(cp, bf);
2196 free(cp); 2185 free(cp);
2197 } 2186 }
2198 } 2187 }
2199 return bf; 2188 return bf;
2200} 2189}