Wed Nov 4 13:22:15 2020 UTC ()
make(1): rename MAKEFILE_PREFERENCE for consistency

The names of the other special variables are all prefixed with MAKE_.


(rillig)
diff -r1.423 -r1.424 src/usr.bin/make/main.c
diff -r1.184 -r1.185 src/usr.bin/make/make.h

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

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

cvs diff -r1.184 -r1.185 src/usr.bin/make/make.h (switch to unified diff)

--- src/usr.bin/make/make.h 2020/11/04 13:04:56 1.184
+++ src/usr.bin/make/make.h 2020/11/04 13:22:15 1.185
@@ -1,732 +1,732 @@ @@ -1,732 +1,732 @@
1/* $NetBSD: make.h,v 1.184 2020/11/04 13:04:56 rillig Exp $ */ 1/* $NetBSD: make.h,v 1.185 2020/11/04 13:22:15 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 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 34 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
35 */ 35 */
36 36
37/* 37/*
38 * Copyright (c) 1989 by Berkeley Softworks 38 * Copyright (c) 1989 by Berkeley Softworks
39 * All rights reserved. 39 * All rights reserved.
40 * 40 *
41 * This code is derived from software contributed to Berkeley by 41 * This code is derived from software contributed to Berkeley by
42 * Adam de Boor. 42 * Adam de Boor.
43 * 43 *
44 * Redistribution and use in source and binary forms, with or without 44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions 45 * modification, are permitted provided that the following conditions
46 * are met: 46 * are met:
47 * 1. Redistributions of source code must retain the above copyright 47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer. 48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright 49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the 50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution. 51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software 52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement: 53 * must display the following acknowledgement:
54 * This product includes software developed by the University of 54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors. 55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors 56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software 57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission. 58 * without specific prior written permission.
59 * 59 *
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
70 * SUCH DAMAGE. 70 * SUCH DAMAGE.
71 * 71 *
72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95 72 * from: @(#)make.h 8.3 (Berkeley) 6/13/95
73 */ 73 */
74 74
75/*- 75/*-
76 * make.h -- 76 * make.h --
77 * The global definitions for pmake 77 * The global definitions for pmake
78 */ 78 */
79 79
80#ifndef MAKE_MAKE_H 80#ifndef MAKE_MAKE_H
81#define MAKE_MAKE_H 81#define MAKE_MAKE_H
82 82
83#include <sys/types.h> 83#include <sys/types.h>
84#include <sys/param.h> 84#include <sys/param.h>
85#include <sys/stat.h> 85#include <sys/stat.h>
86 86
87#include <assert.h> 87#include <assert.h>
88#include <ctype.h> 88#include <ctype.h>
89#include <fcntl.h> 89#include <fcntl.h>
90#include <stdarg.h> 90#include <stdarg.h>
91#include <stdio.h> 91#include <stdio.h>
92#include <stdlib.h> 92#include <stdlib.h>
93#include <string.h> 93#include <string.h>
94#include <unistd.h> 94#include <unistd.h>
95 95
96#ifdef BSD4_4 96#ifdef BSD4_4
97# include <sys/cdefs.h> 97# include <sys/cdefs.h>
98#endif 98#endif
99 99
100#ifndef FD_CLOEXEC 100#ifndef FD_CLOEXEC
101#define FD_CLOEXEC 1 101#define FD_CLOEXEC 1
102#endif 102#endif
103 103
104#if defined(__GNUC__) 104#if defined(__GNUC__)
105#define MAKE_GNUC_PREREQ(x, y) \ 105#define MAKE_GNUC_PREREQ(x, y) \
106 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ 106 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \
107 (__GNUC__ > (x))) 107 (__GNUC__ > (x)))
108#else /* defined(__GNUC__) */ 108#else /* defined(__GNUC__) */
109#define MAKE_GNUC_PREREQ(x, y) 0 109#define MAKE_GNUC_PREREQ(x, y) 0
110#endif /* defined(__GNUC__) */ 110#endif /* defined(__GNUC__) */
111 111
112#if MAKE_GNUC_PREREQ(2, 7) 112#if MAKE_GNUC_PREREQ(2, 7)
113#define MAKE_ATTR_UNUSED __attribute__((__unused__)) 113#define MAKE_ATTR_UNUSED __attribute__((__unused__))
114#else 114#else
115#define MAKE_ATTR_UNUSED /* delete */ 115#define MAKE_ATTR_UNUSED /* delete */
116#endif 116#endif
117 117
118#if MAKE_GNUC_PREREQ(2, 5) 118#if MAKE_GNUC_PREREQ(2, 5)
119#define MAKE_ATTR_DEAD __attribute__((__noreturn__)) 119#define MAKE_ATTR_DEAD __attribute__((__noreturn__))
120#elif defined(__GNUC__) 120#elif defined(__GNUC__)
121#define MAKE_ATTR_DEAD __volatile 121#define MAKE_ATTR_DEAD __volatile
122#else 122#else
123#define MAKE_ATTR_DEAD /* delete */ 123#define MAKE_ATTR_DEAD /* delete */
124#endif 124#endif
125 125
126#if MAKE_GNUC_PREREQ(2, 7) 126#if MAKE_GNUC_PREREQ(2, 7)
127#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \ 127#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) \
128 __attribute__((__format__ (__printf__, fmtarg, firstvararg))) 128 __attribute__((__format__ (__printf__, fmtarg, firstvararg)))
129#else 129#else
130#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */ 130#define MAKE_ATTR_PRINTFLIKE(fmtarg, firstvararg) /* delete */
131#endif 131#endif
132 132
133/* 133/*
134 * A boolean type is defined as an integer, not an enum, for historic reasons. 134 * A boolean type is defined as an integer, not an enum, for historic reasons.
135 * The only allowed values are the constants TRUE and FALSE (1 and 0). 135 * The only allowed values are the constants TRUE and FALSE (1 and 0).
136 */ 136 */
137 137
138#ifdef USE_DOUBLE_BOOLEAN 138#ifdef USE_DOUBLE_BOOLEAN
139/* During development, to find type mismatches in function declarations. */ 139/* During development, to find type mismatches in function declarations. */
140typedef double Boolean; 140typedef double Boolean;
141#define TRUE 1.0 141#define TRUE 1.0
142#define FALSE 0.0 142#define FALSE 0.0
143#elif defined(USE_UCHAR_BOOLEAN) 143#elif defined(USE_UCHAR_BOOLEAN)
144/* During development, to find code that depends on the exact value of TRUE or 144/* During development, to find code that depends on the exact value of TRUE or
145 * that stores other values in Boolean variables. */ 145 * that stores other values in Boolean variables. */
146typedef unsigned char Boolean; 146typedef unsigned char Boolean;
147#define TRUE ((unsigned char)0xFF) 147#define TRUE ((unsigned char)0xFF)
148#define FALSE ((unsigned char)0x00) 148#define FALSE ((unsigned char)0x00)
149#elif defined(USE_CHAR_BOOLEAN) 149#elif defined(USE_CHAR_BOOLEAN)
150/* During development, to find code that uses a boolean as array index, via 150/* During development, to find code that uses a boolean as array index, via
151 * -Wchar-subscripts. */ 151 * -Wchar-subscripts. */
152typedef char Boolean; 152typedef char Boolean;
153#define TRUE ((char)-1) 153#define TRUE ((char)-1)
154#define FALSE ((char)0x00) 154#define FALSE ((char)0x00)
155#elif defined(USE_ENUM_BOOLEAN) 155#elif defined(USE_ENUM_BOOLEAN)
156typedef enum Boolean { FALSE, TRUE } Boolean; 156typedef enum Boolean { FALSE, TRUE } Boolean;
157#else 157#else
158typedef int Boolean; 158typedef int Boolean;
159#ifndef TRUE 159#ifndef TRUE
160#define TRUE 1 160#define TRUE 1
161#endif 161#endif
162#ifndef FALSE 162#ifndef FALSE
163#define FALSE 0 163#define FALSE 0
164#endif 164#endif
165#endif 165#endif
166 166
167#include "lst.h" 167#include "lst.h"
168#include "enum.h" 168#include "enum.h"
169#include "hash.h" 169#include "hash.h"
170#include "config.h" 170#include "config.h"
171#include "buf.h" 171#include "buf.h"
172#include "make_malloc.h" 172#include "make_malloc.h"
173 173
174typedef enum GNodeMade { 174typedef enum GNodeMade {
175 UNMADE, /* Not examined yet */ 175 UNMADE, /* Not examined yet */
176 DEFERRED, /* Examined once (building child) */ 176 DEFERRED, /* Examined once (building child) */
177 REQUESTED, /* on toBeMade list */ 177 REQUESTED, /* on toBeMade list */
178 BEINGMADE, /* Target is already being made. 178 BEINGMADE, /* Target is already being made.
179 * Indicates a cycle in the graph. */ 179 * Indicates a cycle in the graph. */
180 MADE, /* Was out-of-date and has been made */ 180 MADE, /* Was out-of-date and has been made */
181 UPTODATE, /* Was already up-to-date */ 181 UPTODATE, /* Was already up-to-date */
182 ERROR, /* An error occurred while it was being 182 ERROR, /* An error occurred while it was being
183 * made (used only in compat mode) */ 183 * made (used only in compat mode) */
184 ABORTED /* The target was aborted due to an error 184 ABORTED /* The target was aborted due to an error
185 * making an inferior (compat). */ 185 * making an inferior (compat). */
186} GNodeMade; 186} GNodeMade;
187 187
188/* The OP_ constants are used when parsing a dependency line as a way of 188/* The OP_ constants are used when parsing a dependency line as a way of
189 * communicating to other parts of the program the way in which a target 189 * communicating to other parts of the program the way in which a target
190 * should be made. 190 * should be made.
191 * 191 *
192 * Some of the OP_ constants can be combined, others cannot. */ 192 * Some of the OP_ constants can be combined, others cannot. */
193typedef enum GNodeType { 193typedef enum GNodeType {
194 /* The dependency operator ':' is the most common one. The commands of 194 /* The dependency operator ':' is the most common one. The commands of
195 * this node are executed if any child is out-of-date. */ 195 * this node are executed if any child is out-of-date. */
196 OP_DEPENDS = 1 << 0, 196 OP_DEPENDS = 1 << 0,
197 /* The dependency operator '!' always executes its commands, even if 197 /* The dependency operator '!' always executes its commands, even if
198 * its children are up-to-date. */ 198 * its children are up-to-date. */
199 OP_FORCE = 1 << 1, 199 OP_FORCE = 1 << 1,
200 /* The dependency operator '::' behaves like ':', except that it allows 200 /* The dependency operator '::' behaves like ':', except that it allows
201 * multiple dependency groups to be defined. Each of these groups is 201 * multiple dependency groups to be defined. Each of these groups is
202 * executed on its own, independently from the others. */ 202 * executed on its own, independently from the others. */
203 OP_DOUBLEDEP = 1 << 2, 203 OP_DOUBLEDEP = 1 << 2,
204 204
205 /* Matches the dependency operators ':', '!' and '::'. */ 205 /* Matches the dependency operators ':', '!' and '::'. */
206 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP, 206 OP_OPMASK = OP_DEPENDS|OP_FORCE|OP_DOUBLEDEP,
207 207
208 /* Don't care if the target doesn't exist and can't be created */ 208 /* Don't care if the target doesn't exist and can't be created */
209 OP_OPTIONAL = 1 << 3, 209 OP_OPTIONAL = 1 << 3,
210 /* Use associated commands for parents */ 210 /* Use associated commands for parents */
211 OP_USE = 1 << 4, 211 OP_USE = 1 << 4,
212 /* Target is never out of date, but always execute commands anyway. 212 /* Target is never out of date, but always execute commands anyway.
213 * Its time doesn't matter, so it has none...sort of */ 213 * Its time doesn't matter, so it has none...sort of */
214 OP_EXEC = 1 << 5, 214 OP_EXEC = 1 << 5,
215 /* Ignore non-zero exit status from shell commands when creating the node */ 215 /* Ignore non-zero exit status from shell commands when creating the node */
216 OP_IGNORE = 1 << 6, 216 OP_IGNORE = 1 << 6,
217 /* Don't remove the target when interrupted */ 217 /* Don't remove the target when interrupted */
218 OP_PRECIOUS = 1 << 7, 218 OP_PRECIOUS = 1 << 7,
219 /* Don't echo commands when executed */ 219 /* Don't echo commands when executed */
220 OP_SILENT = 1 << 8, 220 OP_SILENT = 1 << 8,
221 /* Target is a recursive make so its commands should always be executed 221 /* Target is a recursive make so its commands should always be executed
222 * when it is out of date, regardless of the state of the -n or -t flags */ 222 * when it is out of date, regardless of the state of the -n or -t flags */
223 OP_MAKE = 1 << 9, 223 OP_MAKE = 1 << 9,
224 /* Target is out-of-date only if any of its children was out-of-date */ 224 /* Target is out-of-date only if any of its children was out-of-date */
225 OP_JOIN = 1 << 10, 225 OP_JOIN = 1 << 10,
226 /* Assume the children of the node have been already made */ 226 /* Assume the children of the node have been already made */
227 OP_MADE = 1 << 11, 227 OP_MADE = 1 << 11,
228 /* Special .BEGIN, .END, .INTERRUPT */ 228 /* Special .BEGIN, .END, .INTERRUPT */
229 OP_SPECIAL = 1 << 12, 229 OP_SPECIAL = 1 << 12,
230 /* Like .USE, only prepend commands */ 230 /* Like .USE, only prepend commands */
231 OP_USEBEFORE = 1 << 13, 231 OP_USEBEFORE = 1 << 13,
232 /* The node is invisible to its parents. I.e. it doesn't show up in the 232 /* The node is invisible to its parents. I.e. it doesn't show up in the
233 * parents' local variables. */ 233 * parents' local variables. */
234 OP_INVISIBLE = 1 << 14, 234 OP_INVISIBLE = 1 << 14,
235 /* The node is exempt from normal 'main target' processing in parse.c */ 235 /* The node is exempt from normal 'main target' processing in parse.c */
236 OP_NOTMAIN = 1 << 15, 236 OP_NOTMAIN = 1 << 15,
237 /* Not a file target; run always */ 237 /* Not a file target; run always */
238 OP_PHONY = 1 << 16, 238 OP_PHONY = 1 << 16,
239 /* Don't search for file in the path */ 239 /* Don't search for file in the path */
240 OP_NOPATH = 1 << 17, 240 OP_NOPATH = 1 << 17,
241 /* .WAIT phony node */ 241 /* .WAIT phony node */
242 OP_WAIT = 1 << 18, 242 OP_WAIT = 1 << 18,
243 /* .NOMETA do not create a .meta file */ 243 /* .NOMETA do not create a .meta file */
244 OP_NOMETA = 1 << 19, 244 OP_NOMETA = 1 << 19,
245 /* .META we _do_ want a .meta file */ 245 /* .META we _do_ want a .meta file */
246 OP_META = 1 << 20, 246 OP_META = 1 << 20,
247 /* Do not compare commands in .meta file */ 247 /* Do not compare commands in .meta file */
248 OP_NOMETA_CMP = 1 << 21, 248 OP_NOMETA_CMP = 1 << 21,
249 /* Possibly a submake node */ 249 /* Possibly a submake node */
250 OP_SUBMAKE = 1 << 22, 250 OP_SUBMAKE = 1 << 22,
251 251
252 /* Attributes applied by PMake */ 252 /* Attributes applied by PMake */
253 253
254 /* The node is a transformation rule */ 254 /* The node is a transformation rule */
255 OP_TRANSFORM = 1 << 31, 255 OP_TRANSFORM = 1 << 31,
256 /* Target is a member of an archive */ 256 /* Target is a member of an archive */
257 /* XXX: How does this differ from OP_ARCHV? */ 257 /* XXX: How does this differ from OP_ARCHV? */
258 OP_MEMBER = 1 << 30, 258 OP_MEMBER = 1 << 30,
259 /* The node is a library, 259 /* The node is a library,
260 * its name has the form "-l<libname>" */ 260 * its name has the form "-l<libname>" */
261 OP_LIB = 1 << 29, 261 OP_LIB = 1 << 29,
262 /* The node is an archive member, 262 /* The node is an archive member,
263 * its name has the form "archive(member)" */ 263 * its name has the form "archive(member)" */
264 /* XXX: How does this differ from OP_MEMBER? */ 264 /* XXX: How does this differ from OP_MEMBER? */
265 OP_ARCHV = 1 << 28, 265 OP_ARCHV = 1 << 28,
266 /* Target has all the commands it should. Used when parsing to catch 266 /* Target has all the commands it should. Used when parsing to catch
267 * multiple command groups for a target. Only applies to the dependency 267 * multiple command groups for a target. Only applies to the dependency
268 * operators ':' and '!', but not to '::'. */ 268 * operators ':' and '!', but not to '::'. */
269 OP_HAS_COMMANDS = 1 << 27, 269 OP_HAS_COMMANDS = 1 << 27,
270 /* The special command "..." has been seen. All further commands from 270 /* The special command "..." has been seen. All further commands from
271 * this node will be saved on the .END node instead, to be executed at 271 * this node will be saved on the .END node instead, to be executed at
272 * the very end. */ 272 * the very end. */
273 OP_SAVE_CMDS = 1 << 26, 273 OP_SAVE_CMDS = 1 << 26,
274 /* Already processed by Suff_FindDeps */ 274 /* Already processed by Suff_FindDeps */
275 OP_DEPS_FOUND = 1 << 25, 275 OP_DEPS_FOUND = 1 << 25,
276 /* Node found while expanding .ALLSRC */ 276 /* Node found while expanding .ALLSRC */
277 OP_MARK = 1 << 24, 277 OP_MARK = 1 << 24,
278 278
279 OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM 279 OP_NOTARGET = OP_NOTMAIN | OP_USE | OP_EXEC | OP_TRANSFORM
280} GNodeType; 280} GNodeType;
281 281
282typedef enum GNodeFlags { 282typedef enum GNodeFlags {
283 REMAKE = 0x0001, /* this target needs to be (re)made */ 283 REMAKE = 0x0001, /* this target needs to be (re)made */
284 CHILDMADE = 0x0002, /* children of this target were made */ 284 CHILDMADE = 0x0002, /* children of this target were made */
285 FORCE = 0x0004, /* children don't exist, and we pretend made */ 285 FORCE = 0x0004, /* children don't exist, and we pretend made */
286 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */ 286 DONE_WAIT = 0x0008, /* Set by Make_ProcessWait() */
287 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */ 287 DONE_ORDER = 0x0010, /* Build requested by .ORDER processing */
288 FROM_DEPEND = 0x0020, /* Node created from .depend */ 288 FROM_DEPEND = 0x0020, /* Node created from .depend */
289 DONE_ALLSRC = 0x0040, /* We do it once only */ 289 DONE_ALLSRC = 0x0040, /* We do it once only */
290 CYCLE = 0x1000, /* Used by MakePrintStatus */ 290 CYCLE = 0x1000, /* Used by MakePrintStatus */
291 DONECYCLE = 0x2000, /* Used by MakePrintStatus */ 291 DONECYCLE = 0x2000, /* Used by MakePrintStatus */
292 INTERNAL = 0x4000 /* Internal use only */ 292 INTERNAL = 0x4000 /* Internal use only */
293} GNodeFlags; 293} GNodeFlags;
294 294
295typedef struct List StringList; 295typedef struct List StringList;
296typedef struct ListNode StringListNode; 296typedef struct ListNode StringListNode;
297 297
298typedef struct List GNodeList; 298typedef struct List GNodeList;
299typedef struct ListNode GNodeListNode; 299typedef struct ListNode GNodeListNode;
300 300
301typedef struct List /* of CachedDir */ SearchPath; 301typedef struct List /* of CachedDir */ SearchPath;
302 302
303/* A graph node represents a target that can possibly be made, including its 303/* A graph node represents a target that can possibly be made, including its
304 * relation to other targets and a lot of other details. */ 304 * relation to other targets and a lot of other details. */
305typedef struct GNode { 305typedef struct GNode {
306 /* The target's name, such as "clean" or "make.c" */ 306 /* The target's name, such as "clean" or "make.c" */
307 char *name; 307 char *name;
308 /* The unexpanded name of a .USE node */ 308 /* The unexpanded name of a .USE node */
309 char *uname; 309 char *uname;
310 /* The full pathname of the file belonging to the target. 310 /* The full pathname of the file belonging to the target.
311 * XXX: What about .PHONY targets? These don't have an associated path. */ 311 * XXX: What about .PHONY targets? These don't have an associated path. */
312 char *path; 312 char *path;
313 313
314 /* The type of operator used to define the sources (see the OP flags below). 314 /* The type of operator used to define the sources (see the OP flags below).
315 * XXX: This looks like a wild mixture of type and flags. */ 315 * XXX: This looks like a wild mixture of type and flags. */
316 GNodeType type; 316 GNodeType type;
317 GNodeFlags flags; 317 GNodeFlags flags;
318 318
319 /* The state of processing on this node */ 319 /* The state of processing on this node */
320 GNodeMade made; 320 GNodeMade made;
321 int unmade; /* The number of unmade children */ 321 int unmade; /* The number of unmade children */
322 322
323 /* The modification time; 0 means the node does not have a corresponding 323 /* The modification time; 0 means the node does not have a corresponding
324 * file; see Make_OODate. */ 324 * file; see Make_OODate. */
325 time_t mtime; 325 time_t mtime;
326 struct GNode *youngestChild; 326 struct GNode *youngestChild;
327 327
328 /* The GNodes for which this node is an implied source. May be empty. 328 /* The GNodes for which this node is an implied source. May be empty.
329 * For example, when there is an inference rule for .c.o, the node for 329 * For example, when there is an inference rule for .c.o, the node for
330 * file.c has the node for file.o in this list. */ 330 * file.c has the node for file.o in this list. */
331 GNodeList *implicitParents; 331 GNodeList *implicitParents;
332 332
333 /* Other nodes of the same name, for the '::' operator. */ 333 /* Other nodes of the same name, for the '::' operator. */
334 GNodeList *cohorts; 334 GNodeList *cohorts;
335 335
336 /* The nodes that depend on this one, or in other words, the nodes for 336 /* The nodes that depend on this one, or in other words, the nodes for
337 * which this is a source. */ 337 * which this is a source. */
338 GNodeList *parents; 338 GNodeList *parents;
339 /* The nodes on which this one depends. */ 339 /* The nodes on which this one depends. */
340 GNodeList *children; 340 GNodeList *children;
341 341
342 /* .ORDER nodes we need made. The nodes that must be made (if they're 342 /* .ORDER nodes we need made. The nodes that must be made (if they're
343 * made) before this node can be made, but that do not enter into the 343 * made) before this node can be made, but that do not enter into the
344 * datedness of this node. */ 344 * datedness of this node. */
345 GNodeList *order_pred; 345 GNodeList *order_pred;
346 /* .ORDER nodes who need us. The nodes that must be made (if they're made 346 /* .ORDER nodes who need us. The nodes that must be made (if they're made
347 * at all) after this node is made, but that do not depend on this node, 347 * at all) after this node is made, but that do not depend on this node,
348 * in the normal sense. */ 348 * in the normal sense. */
349 GNodeList *order_succ; 349 GNodeList *order_succ;
350 350
351 /* The "#n" suffix for this cohort, or "" for other nodes */ 351 /* The "#n" suffix for this cohort, or "" for other nodes */
352 char cohort_num[8]; 352 char cohort_num[8];
353 /* The number of unmade instances on the cohorts list */ 353 /* The number of unmade instances on the cohorts list */
354 int unmade_cohorts; 354 int unmade_cohorts;
355 /* Pointer to the first instance of a '::' node; only set when on a 355 /* Pointer to the first instance of a '::' node; only set when on a
356 * cohorts list */ 356 * cohorts list */
357 struct GNode *centurion; 357 struct GNode *centurion;
358 358
359 /* Last time (sequence number) we tried to make this node */ 359 /* Last time (sequence number) we tried to make this node */
360 unsigned int checked_seqno; 360 unsigned int checked_seqno;
361 361
362 /* The "local" variables that are specific to this target and this target 362 /* The "local" variables that are specific to this target and this target
363 * only, such as $@, $<, $?. 363 * only, such as $@, $<, $?.
364 * 364 *
365 * Also used for the global variable scopes VAR_GLOBAL, VAR_CMDLINE, 365 * Also used for the global variable scopes VAR_GLOBAL, VAR_CMDLINE,
366 * VAR_INTERNAL, which contain variables with arbitrary names. */ 366 * VAR_INTERNAL, which contain variables with arbitrary names. */
367 HashTable /* of Var pointer */ context; 367 HashTable /* of Var pointer */ context;
368 368
369 /* The commands to be given to a shell to create this target. */ 369 /* The commands to be given to a shell to create this target. */
370 StringList *commands; 370 StringList *commands;
371 371
372 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone 372 /* Suffix for the node (determined by Suff_FindDeps and opaque to everyone
373 * but the Suff module) */ 373 * but the Suff module) */
374 struct Suff *suffix; 374 struct Suff *suffix;
375 375
376 /* filename where the GNode got defined */ 376 /* filename where the GNode got defined */
377 const char *fname; 377 const char *fname;
378 /* line number where the GNode got defined */ 378 /* line number where the GNode got defined */
379 int lineno; 379 int lineno;
380} GNode; 380} GNode;
381 381
382/* 382/*
383 * Error levels for parsing. PARSE_FATAL means the process cannot continue 383 * Error levels for parsing. PARSE_FATAL means the process cannot continue
384 * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO 384 * once the top-level makefile has been parsed. PARSE_WARNING and PARSE_INFO
385 * mean it can. 385 * mean it can.
386 */ 386 */
387typedef enum ParseErrorLevel { 387typedef enum ParseErrorLevel {
388 PARSE_FATAL = 1, 388 PARSE_FATAL = 1,
389 PARSE_WARNING, 389 PARSE_WARNING,
390 PARSE_INFO 390 PARSE_INFO
391} ParseErrorLevel; 391} ParseErrorLevel;
392 392
393/* 393/*
394 * Values returned by Cond_EvalLine and Cond_EvalCondition. 394 * Values returned by Cond_EvalLine and Cond_EvalCondition.
395 */ 395 */
396typedef enum CondEvalResult { 396typedef enum CondEvalResult {
397 COND_PARSE, /* Parse the next lines */ 397 COND_PARSE, /* Parse the next lines */
398 COND_SKIP, /* Skip the next lines */ 398 COND_SKIP, /* Skip the next lines */
399 COND_INVALID /* Not a conditional statement */ 399 COND_INVALID /* Not a conditional statement */
400} CondEvalResult; 400} CondEvalResult;
401 401
402/* 402/*
403 * Definitions for the "local" variables. Used only for clarity. 403 * Definitions for the "local" variables. Used only for clarity.
404 */ 404 */
405#define TARGET "@" /* Target of dependency */ 405#define TARGET "@" /* Target of dependency */
406#define OODATE "?" /* All out-of-date sources */ 406#define OODATE "?" /* All out-of-date sources */
407#define ALLSRC ">" /* All sources */ 407#define ALLSRC ">" /* All sources */
408#define IMPSRC "<" /* Source implied by transformation */ 408#define IMPSRC "<" /* Source implied by transformation */
409#define PREFIX "*" /* Common prefix */ 409#define PREFIX "*" /* Common prefix */
410#define ARCHIVE "!" /* Archive in "archive(member)" syntax */ 410#define ARCHIVE "!" /* Archive in "archive(member)" syntax */
411#define MEMBER "%" /* Member in "archive(member)" syntax */ 411#define MEMBER "%" /* Member in "archive(member)" syntax */
412 412
413/* 413/*
414 * Global Variables 414 * Global Variables
415 */ 415 */
416extern SearchPath *dirSearchPath; 416extern SearchPath *dirSearchPath;
417 /* The list of directories to search when 417 /* The list of directories to search when
418 * looking for targets */ 418 * looking for targets */
419extern Boolean allPrecious; /* True if every target is precious */ 419extern Boolean allPrecious; /* True if every target is precious */
420extern Boolean deleteOnError; /* True if failed targets should be deleted */ 420extern Boolean deleteOnError; /* True if failed targets should be deleted */
421extern Boolean doing_depend; /* TRUE if processing .depend */ 421extern Boolean doing_depend; /* TRUE if processing .depend */
422 422
423extern GNode *DEFAULT; /* .DEFAULT rule */ 423extern GNode *DEFAULT; /* .DEFAULT rule */
424 424
425extern GNode *VAR_INTERNAL; /* Variables defined internally by make 425extern GNode *VAR_INTERNAL; /* Variables defined internally by make
426 * which should not override those set by 426 * which should not override those set by
427 * makefiles. 427 * makefiles.
428 */ 428 */
429extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g 429extern GNode *VAR_GLOBAL; /* Variables defined in a global context, e.g
430 * in the Makefile itself */ 430 * in the Makefile itself */
431extern GNode *VAR_CMDLINE; /* Variables defined on the command line */ 431extern GNode *VAR_CMDLINE; /* Variables defined on the command line */
432extern char var_Error[]; /* Value returned by Var_Parse when an error 432extern char var_Error[]; /* Value returned by Var_Parse when an error
433 * is encountered. It actually points to 433 * is encountered. It actually points to
434 * an empty string, so naive callers needn't 434 * an empty string, so naive callers needn't
435 * worry about it. */ 435 * worry about it. */
436 436
437extern time_t now; /* The time at the start of this whole 437extern time_t now; /* The time at the start of this whole
438 * process */ 438 * process */
439 439
440/* 440/*
441 * If FALSE (the default behavior), undefined subexpressions in a variable 441 * If FALSE (the default behavior), undefined subexpressions in a variable
442 * expression are discarded. If TRUE (only during variable assignments using 442 * expression are discarded. If TRUE (only during variable assignments using
443 * the ':=' assignment operator, in the top-level expansion), they are 443 * the ':=' assignment operator, in the top-level expansion), they are
444 * preserved and possibly expanded later when the variable from the 444 * preserved and possibly expanded later when the variable from the
445 * subexpression has been defined. 445 * subexpression has been defined.
446 * 446 *
447 * Example for a ':=' assignment: 447 * Example for a ':=' assignment:
448 * CFLAGS = $(.INCLUDES) 448 * CFLAGS = $(.INCLUDES)
449 * CFLAGS := -I.. $(CFLAGS) 449 * CFLAGS := -I.. $(CFLAGS)
450 * # If .INCLUDES (an undocumented special variable, by the way) is 450 * # If .INCLUDES (an undocumented special variable, by the way) is
451 * # still undefined, the updated CFLAGS becomes "-I.. $(.INCLUDES)". 451 * # still undefined, the updated CFLAGS becomes "-I.. $(.INCLUDES)".
452 */ 452 */
453extern Boolean preserveUndefined; 453extern Boolean preserveUndefined;
454 454
455extern SearchPath *sysIncPath; /* The system include path. */ 455extern SearchPath *sysIncPath; /* The system include path. */
456extern SearchPath *defSysIncPath; /* The default system include path. */ 456extern SearchPath *defSysIncPath; /* The default system include path. */
457 457
458extern char curdir[]; /* Startup directory */ 458extern char curdir[]; /* Startup directory */
459extern char *progname; /* The program name */ 459extern char *progname; /* The program name */
460extern char *makeDependfile; /* .depend */ 460extern char *makeDependfile; /* .depend */
461extern char **savedEnv; /* if we replaced environ this will be non-NULL */ 461extern char **savedEnv; /* if we replaced environ this will be non-NULL */
462 462
463extern int makelevel; 463extern int makelevel;
464 464
465/* 465/*
466 * We cannot vfork() in a child of vfork(). 466 * We cannot vfork() in a child of vfork().
467 * Most systems do not enforce this but some do. 467 * Most systems do not enforce this but some do.
468 */ 468 */
469#define vFork() ((getpid() == myPid) ? vfork() : fork()) 469#define vFork() ((getpid() == myPid) ? vfork() : fork())
470extern pid_t myPid; 470extern pid_t myPid;
471 471
472#define MAKEFLAGS ".MAKEFLAGS" 472#define MAKEFLAGS ".MAKEFLAGS"
473#define MAKEOVERRIDES ".MAKEOVERRIDES" 473#define MAKEOVERRIDES ".MAKEOVERRIDES"
474#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */ 474#define MAKE_JOB_PREFIX ".MAKE.JOB.PREFIX" /* prefix for job target output */
475#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */ 475#define MAKE_EXPORTED ".MAKE.EXPORTED" /* variables we export */
476#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all makefiles already loaded */ 476#define MAKE_MAKEFILES ".MAKE.MAKEFILES" /* all makefiles already loaded */
477#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */ 477#define MAKE_LEVEL ".MAKE.LEVEL" /* recursion level */
478#define MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE" 478#define MAKE_MAKEFILE_PREFERENCE ".MAKE.MAKEFILE_PREFERENCE"
479#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */ 479#define MAKE_DEPENDFILE ".MAKE.DEPENDFILE" /* .depend */
480#define MAKE_MODE ".MAKE.MODE" 480#define MAKE_MODE ".MAKE.MODE"
481#ifndef MAKE_LEVEL_ENV 481#ifndef MAKE_LEVEL_ENV
482# define MAKE_LEVEL_ENV "MAKELEVEL" 482# define MAKE_LEVEL_ENV "MAKELEVEL"
483#endif 483#endif
484 484
485typedef enum DebugFlags { 485typedef enum DebugFlags {
486 DEBUG_ARCH = 1 << 0, 486 DEBUG_ARCH = 1 << 0,
487 DEBUG_COND = 1 << 1, 487 DEBUG_COND = 1 << 1,
488 DEBUG_DIR = 1 << 2, 488 DEBUG_DIR = 1 << 2,
489 DEBUG_GRAPH1 = 1 << 3, 489 DEBUG_GRAPH1 = 1 << 3,
490 DEBUG_GRAPH2 = 1 << 4, 490 DEBUG_GRAPH2 = 1 << 4,
491 DEBUG_JOB = 1 << 5, 491 DEBUG_JOB = 1 << 5,
492 DEBUG_MAKE = 1 << 6, 492 DEBUG_MAKE = 1 << 6,
493 DEBUG_SUFF = 1 << 7, 493 DEBUG_SUFF = 1 << 7,
494 DEBUG_TARG = 1 << 8, 494 DEBUG_TARG = 1 << 8,
495 DEBUG_VAR = 1 << 9, 495 DEBUG_VAR = 1 << 9,
496 DEBUG_FOR = 1 << 10, 496 DEBUG_FOR = 1 << 10,
497 DEBUG_SHELL = 1 << 11, 497 DEBUG_SHELL = 1 << 11,
498 DEBUG_ERROR = 1 << 12, 498 DEBUG_ERROR = 1 << 12,
499 DEBUG_LOUD = 1 << 13, 499 DEBUG_LOUD = 1 << 13,
500 DEBUG_META = 1 << 14, 500 DEBUG_META = 1 << 14,
501 DEBUG_HASH = 1 << 15, 501 DEBUG_HASH = 1 << 15,
502 502
503 DEBUG_GRAPH3 = 1 << 16, 503 DEBUG_GRAPH3 = 1 << 16,
504 DEBUG_SCRIPT = 1 << 17, 504 DEBUG_SCRIPT = 1 << 17,
505 DEBUG_PARSE = 1 << 18, 505 DEBUG_PARSE = 1 << 18,
506 DEBUG_CWD = 1 << 19, 506 DEBUG_CWD = 1 << 19,
507 507
508 DEBUG_LINT = 1 << 20 508 DEBUG_LINT = 1 << 20
509} DebugFlags; 509} DebugFlags;
510 510
511#define CONCAT(a,b) a##b 511#define CONCAT(a,b) a##b
512 512
513#define DEBUG(module) (opts.debug & CONCAT(DEBUG_,module)) 513#define DEBUG(module) (opts.debug & CONCAT(DEBUG_,module))
514 514
515void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); 515void debug_printf(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
516 516
517#define DEBUG0(module, text) \ 517#define DEBUG0(module, text) \
518 if (!DEBUG(module)) (void)0; \ 518 if (!DEBUG(module)) (void)0; \
519 else debug_printf("%s", text) 519 else debug_printf("%s", text)
520 520
521#define DEBUG1(module, fmt, arg1) \ 521#define DEBUG1(module, fmt, arg1) \
522 if (!DEBUG(module)) (void)0; \ 522 if (!DEBUG(module)) (void)0; \
523 else debug_printf(fmt, arg1) 523 else debug_printf(fmt, arg1)
524 524
525#define DEBUG2(module, fmt, arg1, arg2) \ 525#define DEBUG2(module, fmt, arg1, arg2) \
526 if (!DEBUG(module)) (void)0; \ 526 if (!DEBUG(module)) (void)0; \
527 else debug_printf(fmt, arg1, arg2) 527 else debug_printf(fmt, arg1, arg2)
528 528
529#define DEBUG3(module, fmt, arg1, arg2, arg3) \ 529#define DEBUG3(module, fmt, arg1, arg2, arg3) \
530 if (!DEBUG(module)) (void)0; \ 530 if (!DEBUG(module)) (void)0; \
531 else debug_printf(fmt, arg1, arg2, arg3) 531 else debug_printf(fmt, arg1, arg2, arg3)
532 532
533#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \ 533#define DEBUG4(module, fmt, arg1, arg2, arg3, arg4) \
534 if (!DEBUG(module)) (void)0; \ 534 if (!DEBUG(module)) (void)0; \
535 else debug_printf(fmt, arg1, arg2, arg3, arg4) 535 else debug_printf(fmt, arg1, arg2, arg3, arg4)
536 536
537#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \ 537#define DEBUG5(module, fmt, arg1, arg2, arg3, arg4, arg5) \
538 if (!DEBUG(module)) (void)0; \ 538 if (!DEBUG(module)) (void)0; \
539 else debug_printf(fmt, arg1, arg2, arg3, arg4, arg5) 539 else debug_printf(fmt, arg1, arg2, arg3, arg4, arg5)
540 540
541typedef enum PrintVarsMode { 541typedef enum PrintVarsMode {
542 COMPAT_VARS = 1, 542 COMPAT_VARS = 1,
543 EXPAND_VARS 543 EXPAND_VARS
544} PrintVarsMode; 544} PrintVarsMode;
545 545
546/* Command line options */ 546/* Command line options */
547typedef struct CmdOpts { 547typedef struct CmdOpts {
548 /* -B: whether we are make compatible */ 548 /* -B: whether we are make compatible */
549 Boolean compatMake; 549 Boolean compatMake;
550 550
551 /* -d: debug control: There is one bit per module. It is up to the 551 /* -d: debug control: There is one bit per module. It is up to the
552 * module what debug information to print. */ 552 * module what debug information to print. */
553 DebugFlags debug; 553 DebugFlags debug;
554 554
555 /* -df: debug output is written here - default stderr */ 555 /* -df: debug output is written here - default stderr */
556 FILE *debug_file; 556 FILE *debug_file;
557 557
558 /* -dV: for the -V option, print unexpanded variable values */ 558 /* -dV: for the -V option, print unexpanded variable values */
559 Boolean debugVflag; 559 Boolean debugVflag;
560 560
561 /* -e: check environment variables before global variables */ 561 /* -e: check environment variables before global variables */
562 Boolean checkEnvFirst; 562 Boolean checkEnvFirst;
563 563
564 /* -f: the makefiles to read */ 564 /* -f: the makefiles to read */
565 StringList *makefiles; 565 StringList *makefiles;
566 566
567 /* -i: if true, ignore all errors from shell commands */ 567 /* -i: if true, ignore all errors from shell commands */
568 Boolean ignoreErrors; 568 Boolean ignoreErrors;
569 569
570 /* -j: the maximum number of jobs that can run in parallel; 570 /* -j: the maximum number of jobs that can run in parallel;
571 * this is coordinated with the submakes */ 571 * this is coordinated with the submakes */
572 int maxJobs; 572 int maxJobs;
573 573
574 /* -k: if true, continue on unaffected portions of the graph when an 574 /* -k: if true, continue on unaffected portions of the graph when an
575 * error occurs in one portion */ 575 * error occurs in one portion */
576 Boolean keepgoing; 576 Boolean keepgoing;
577 577
578 /* -N: execute no commands from the targets */ 578 /* -N: execute no commands from the targets */
579 Boolean noRecursiveExecute; 579 Boolean noRecursiveExecute;
580 580
581 /* -n: execute almost no commands from the targets */ 581 /* -n: execute almost no commands from the targets */
582 Boolean noExecute; 582 Boolean noExecute;
583 583
584 /* -q: if true, we aren't supposed to really make anything, just see if 584 /* -q: if true, we aren't supposed to really make anything, just see if
585 * the targets are out-of-date */ 585 * the targets are out-of-date */
586 Boolean queryFlag; 586 Boolean queryFlag;
587 587
588 /* -r: raw mode, without loading the builtin rules. */ 588 /* -r: raw mode, without loading the builtin rules. */
589 Boolean noBuiltins; 589 Boolean noBuiltins;
590 590
591 /* -s: don't echo the shell commands before executing them */ 591 /* -s: don't echo the shell commands before executing them */
592 Boolean beSilent; 592 Boolean beSilent;
593 593
594 /* -t: touch the targets if they are out-of-date, but don't actually 594 /* -t: touch the targets if they are out-of-date, but don't actually
595 * make them */ 595 * make them */
596 Boolean touchFlag; 596 Boolean touchFlag;
597 597
598 /* -[Vv]: print expanded or unexpanded selected variables */ 598 /* -[Vv]: print expanded or unexpanded selected variables */
599 PrintVarsMode printVars; 599 PrintVarsMode printVars;
600 /* -[Vv]: the variables to print */ 600 /* -[Vv]: the variables to print */
601 StringList *variables; 601 StringList *variables;
602 602
603 /* -W: if true, makefile parsing warnings are treated as errors */ 603 /* -W: if true, makefile parsing warnings are treated as errors */
604 Boolean parseWarnFatal; 604 Boolean parseWarnFatal;
605 605
606 /* -w: print Entering and Leaving for submakes */ 606 /* -w: print Entering and Leaving for submakes */
607 Boolean enterFlag; 607 Boolean enterFlag;
608 608
609 /* -X: if true, do not export variables set on the command line to the 609 /* -X: if true, do not export variables set on the command line to the
610 * environment. */ 610 * environment. */
611 Boolean varNoExportEnv; 611 Boolean varNoExportEnv;
612 612
613 /* The target names specified on the command line. 613 /* The target names specified on the command line.
614 * Used to resolve .if make(...) statements. */ 614 * Used to resolve .if make(...) statements. */
615 StringList *create; 615 StringList *create;
616 616
617} CmdOpts; 617} CmdOpts;
618 618
619extern CmdOpts opts; 619extern CmdOpts opts;
620 620
621#include "nonints.h" 621#include "nonints.h"
622 622
623void Make_TimeStamp(GNode *, GNode *); 623void Make_TimeStamp(GNode *, GNode *);
624Boolean Make_OODate(GNode *); 624Boolean Make_OODate(GNode *);
625void Make_ExpandUse(GNodeList *); 625void Make_ExpandUse(GNodeList *);
626time_t Make_Recheck(GNode *); 626time_t Make_Recheck(GNode *);
627void Make_HandleUse(GNode *, GNode *); 627void Make_HandleUse(GNode *, GNode *);
628void Make_Update(GNode *); 628void Make_Update(GNode *);
629void Make_DoAllVar(GNode *); 629void Make_DoAllVar(GNode *);
630Boolean Make_Run(GNodeList *); 630Boolean Make_Run(GNodeList *);
631int dieQuietly(GNode *, int); 631int dieQuietly(GNode *, int);
632void PrintOnError(GNode *, const char *); 632void PrintOnError(GNode *, const char *);
633void Main_ExportMAKEFLAGS(Boolean); 633void Main_ExportMAKEFLAGS(Boolean);
634Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2); 634Boolean Main_SetObjdir(const char *, ...) MAKE_ATTR_PRINTFLIKE(1, 2);
635int mkTempFile(const char *, char **); 635int mkTempFile(const char *, char **);
636int str2Lst_Append(StringList *, char *, const char *); 636int str2Lst_Append(StringList *, char *, const char *);
637void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *); 637void GNode_FprintDetails(FILE *, const char *, const GNode *, const char *);
638Boolean GNode_ShouldExecute(GNode *gn); 638Boolean GNode_ShouldExecute(GNode *gn);
639 639
640/* See if the node was seen on the left-hand side of a dependency operator. */ 640/* See if the node was seen on the left-hand side of a dependency operator. */
641static MAKE_ATTR_UNUSED Boolean 641static MAKE_ATTR_UNUSED Boolean
642GNode_IsTarget(const GNode *gn) 642GNode_IsTarget(const GNode *gn)
643{ 643{
644 return (gn->type & OP_OPMASK) != 0; 644 return (gn->type & OP_OPMASK) != 0;
645} 645}
646 646
647static MAKE_ATTR_UNUSED const char * 647static MAKE_ATTR_UNUSED const char *
648GNode_Path(const GNode *gn) 648GNode_Path(const GNode *gn)
649{ 649{
650 return gn->path != NULL ? gn->path : gn->name; 650 return gn->path != NULL ? gn->path : gn->name;
651} 651}
652 652
653static MAKE_ATTR_UNUSED const char * 653static MAKE_ATTR_UNUSED const char *
654GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); } 654GNode_VarTarget(GNode *gn) { return Var_ValueDirect(TARGET, gn); }
655static MAKE_ATTR_UNUSED const char * 655static MAKE_ATTR_UNUSED const char *
656GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); } 656GNode_VarOodate(GNode *gn) { return Var_ValueDirect(OODATE, gn); }
657static MAKE_ATTR_UNUSED const char * 657static MAKE_ATTR_UNUSED const char *
658GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); } 658GNode_VarAllsrc(GNode *gn) { return Var_ValueDirect(ALLSRC, gn); }
659static MAKE_ATTR_UNUSED const char * 659static MAKE_ATTR_UNUSED const char *
660GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); } 660GNode_VarImpsrc(GNode *gn) { return Var_ValueDirect(IMPSRC, gn); }
661static MAKE_ATTR_UNUSED const char * 661static MAKE_ATTR_UNUSED const char *
662GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); } 662GNode_VarPrefix(GNode *gn) { return Var_ValueDirect(PREFIX, gn); }
663static MAKE_ATTR_UNUSED const char * 663static MAKE_ATTR_UNUSED const char *
664GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); } 664GNode_VarArchive(GNode *gn) { return Var_ValueDirect(ARCHIVE, gn); }
665static MAKE_ATTR_UNUSED const char * 665static MAKE_ATTR_UNUSED const char *
666GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); } 666GNode_VarMember(GNode *gn) { return Var_ValueDirect(MEMBER, gn); }
667 667
668#ifdef __GNUC__ 668#ifdef __GNUC__
669#define UNCONST(ptr) ({ \ 669#define UNCONST(ptr) ({ \
670 union __unconst { \ 670 union __unconst { \
671 const void *__cp; \ 671 const void *__cp; \
672 void *__p; \ 672 void *__p; \
673 } __d; \ 673 } __d; \
674 __d.__cp = ptr, __d.__p; }) 674 __d.__cp = ptr, __d.__p; })
675#else 675#else
676#define UNCONST(ptr) (void *)(ptr) 676#define UNCONST(ptr) (void *)(ptr)
677#endif 677#endif
678 678
679/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */ 679/* At least GNU/Hurd systems lack hardcoded MAXPATHLEN/PATH_MAX */
680#include <limits.h> 680#include <limits.h>
681#ifndef MAXPATHLEN 681#ifndef MAXPATHLEN
682#define MAXPATHLEN 4096 682#define MAXPATHLEN 4096
683#endif 683#endif
684#ifndef PATH_MAX 684#ifndef PATH_MAX
685#define PATH_MAX MAXPATHLEN 685#define PATH_MAX MAXPATHLEN
686#endif 686#endif
687 687
688#if defined(SYSV) 688#if defined(SYSV)
689#define KILLPG(pid, sig) kill(-(pid), (sig)) 689#define KILLPG(pid, sig) kill(-(pid), (sig))
690#else 690#else
691#define KILLPG(pid, sig) killpg((pid), (sig)) 691#define KILLPG(pid, sig) killpg((pid), (sig))
692#endif 692#endif
693 693
694static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch) 694static inline MAKE_ATTR_UNUSED Boolean ch_isalnum(char ch)
695{ return isalnum((unsigned char)ch) != 0; } 695{ return isalnum((unsigned char)ch) != 0; }
696static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch) 696static inline MAKE_ATTR_UNUSED Boolean ch_isalpha(char ch)
697{ return isalpha((unsigned char)ch) != 0; } 697{ return isalpha((unsigned char)ch) != 0; }
698static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch) 698static inline MAKE_ATTR_UNUSED Boolean ch_isdigit(char ch)
699{ return isdigit((unsigned char)ch) != 0; } 699{ return isdigit((unsigned char)ch) != 0; }
700static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch) 700static inline MAKE_ATTR_UNUSED Boolean ch_isspace(char ch)
701{ return isspace((unsigned char)ch) != 0; } 701{ return isspace((unsigned char)ch) != 0; }
702static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch) 702static inline MAKE_ATTR_UNUSED Boolean ch_isupper(char ch)
703{ return isupper((unsigned char)ch) != 0; } 703{ return isupper((unsigned char)ch) != 0; }
704static inline MAKE_ATTR_UNUSED char ch_tolower(char ch) 704static inline MAKE_ATTR_UNUSED char ch_tolower(char ch)
705{ return (char)tolower((unsigned char)ch); } 705{ return (char)tolower((unsigned char)ch); }
706static inline MAKE_ATTR_UNUSED char ch_toupper(char ch) 706static inline MAKE_ATTR_UNUSED char ch_toupper(char ch)
707{ return (char)toupper((unsigned char)ch); } 707{ return (char)toupper((unsigned char)ch); }
708 708
709static inline MAKE_ATTR_UNUSED void 709static inline MAKE_ATTR_UNUSED void
710cpp_skip_whitespace(const char **pp) 710cpp_skip_whitespace(const char **pp)
711{ 711{
712 while (ch_isspace(**pp)) 712 while (ch_isspace(**pp))
713 (*pp)++; 713 (*pp)++;
714} 714}
715 715
716static inline MAKE_ATTR_UNUSED void 716static inline MAKE_ATTR_UNUSED void
717pp_skip_whitespace(char **pp) 717pp_skip_whitespace(char **pp)
718{ 718{
719 while (ch_isspace(**pp)) 719 while (ch_isspace(**pp))
720 (*pp)++; 720 (*pp)++;
721} 721}
722 722
723#ifdef MAKE_NATIVE 723#ifdef MAKE_NATIVE
724# include <sys/cdefs.h> 724# include <sys/cdefs.h>
725# ifndef lint 725# ifndef lint
726# define MAKE_RCSID(id) __RCSID(id) 726# define MAKE_RCSID(id) __RCSID(id)
727# endif 727# endif
728#else 728#else
729# define MAKE_RCSID(id) static volatile char rcsid[] = id 729# define MAKE_RCSID(id) static volatile char rcsid[] = id
730#endif 730#endif
731 731
732#endif /* MAKE_MAKE_H */ 732#endif /* MAKE_MAKE_H */