git: 9f45a3c8c82f - main - Merge bmake-20220204
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 05 Feb 2022 20:29:17 UTC
The branch main has been updated by sjg:
URL: https://cgit.FreeBSD.org/src/commit/?id=9f45a3c8c82ffead7044ae836d9257113c630d3b
commit 9f45a3c8c82ffead7044ae836d9257113c630d3b
Merge: e515b9b44c20 cdde9e894dee
Author: Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2022-02-05 20:26:16 +0000
Commit: Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2022-02-05 20:26:16 +0000
Merge bmake-20220204
contrib/bmake/ChangeLog | 155 ++
contrib/bmake/FILES | 41 +-
contrib/bmake/VERSION | 2 +-
contrib/bmake/arch.c | 90 +-
contrib/bmake/bmake.1 | 51 +-
contrib/bmake/bmake.cat1 | 39 +-
contrib/bmake/buf.c | 15 +-
contrib/bmake/buf.h | 19 +-
contrib/bmake/compat.c | 93 +-
contrib/bmake/cond.c | 429 +++---
contrib/bmake/dir.c | 21 +-
contrib/bmake/dir.h | 14 +-
contrib/bmake/filemon/filemon.h | 4 +-
contrib/bmake/for.c | 228 ++-
contrib/bmake/hash.c | 80 +-
contrib/bmake/hash.h | 24 +-
contrib/bmake/job.c | 99 +-
contrib/bmake/job.h | 34 +-
contrib/bmake/lst.h | 20 +-
contrib/bmake/main.c | 548 +++----
contrib/bmake/make.1 | 51 +-
contrib/bmake/make.c | 32 +-
contrib/bmake/make.h | 672 ++++++--
contrib/bmake/make_malloc.c | 12 +-
contrib/bmake/make_malloc.h | 26 +-
contrib/bmake/meta.c | 172 ++-
contrib/bmake/meta.h | 8 +-
contrib/bmake/metachar.h | 12 +-
contrib/bmake/mk/ChangeLog | 57 +
contrib/bmake/mk/FILES | 1 +
contrib/bmake/mk/cc-wrap.mk | 61 +
contrib/bmake/mk/dirdeps.mk | 101 +-
contrib/bmake/mk/host-target.mk | 7 +-
contrib/bmake/mk/init.mk | 8 +-
contrib/bmake/mk/install-mk | 4 +-
contrib/bmake/mk/meta2deps.py | 38 +-
contrib/bmake/mk/meta2deps.sh | 29 +-
contrib/bmake/mk/mk-files.txt | 93 +-
contrib/bmake/mk/sys.clean-env.mk | 6 +-
contrib/bmake/nonints.h | 348 -----
contrib/bmake/parse.c | 1608 ++++++++------------
contrib/bmake/str.c | 29 +-
contrib/bmake/str.h | 46 +-
contrib/bmake/suff.c | 66 +-
contrib/bmake/targ.c | 40 +-
contrib/bmake/trace.c | 17 +-
contrib/bmake/unit-tests/Makefile | 30 +-
contrib/bmake/unit-tests/comment.mk | 6 +-
contrib/bmake/unit-tests/cond-func-empty.mk | 17 +-
contrib/bmake/unit-tests/cond-func.exp | 10 +-
contrib/bmake/unit-tests/cond-func.mk | 20 +-
contrib/bmake/unit-tests/cond-op-parentheses.exp | 7 +-
contrib/bmake/unit-tests/cond-op-parentheses.mk | 36 +-
contrib/bmake/unit-tests/cond-short.mk | 12 +-
contrib/bmake/unit-tests/cond-token-number.exp | 2 +-
contrib/bmake/unit-tests/cond-token-number.mk | 15 +-
contrib/bmake/unit-tests/cond-token-plain.exp | 3 +-
contrib/bmake/unit-tests/cond-token-plain.mk | 49 +-
contrib/bmake/unit-tests/cond-token-string.exp | 4 +-
contrib/bmake/unit-tests/dep-duplicate.exp | 4 +
contrib/bmake/unit-tests/dep-duplicate.mk | 27 +
contrib/bmake/unit-tests/dep-op-missing.exp | 4 +
contrib/bmake/unit-tests/dep-op-missing.mk | 13 +
contrib/bmake/unit-tests/dep-wildcards.exp | 2 +
contrib/bmake/unit-tests/dep.exp | 6 +-
contrib/bmake/unit-tests/dep.mk | 16 +-
contrib/bmake/unit-tests/depsrc-meta.exp | 2 +
contrib/bmake/unit-tests/depsrc-meta.mk | 19 +-
contrib/bmake/unit-tests/depsrc-use.mk | 7 +-
contrib/bmake/unit-tests/depsrc-usebefore.mk | 7 +-
contrib/bmake/unit-tests/depsrc.exp | 1 +
contrib/bmake/unit-tests/depsrc.mk | 14 +-
contrib/bmake/unit-tests/deptgt-error.exp | 10 +-
contrib/bmake/unit-tests/deptgt-error.mk | 22 +-
contrib/bmake/unit-tests/deptgt-ignore.exp | 12 +-
contrib/bmake/unit-tests/deptgt-ignore.mk | 30 +-
contrib/bmake/unit-tests/deptgt-interrupt.exp | 3 +-
contrib/bmake/unit-tests/deptgt-interrupt.mk | 9 +-
contrib/bmake/unit-tests/deptgt-main.exp | 1 +
contrib/bmake/unit-tests/deptgt-main.mk | 27 +-
contrib/bmake/unit-tests/deptgt-notparallel.exp | 8 +
contrib/bmake/unit-tests/deptgt-notparallel.mk | 18 +-
contrib/bmake/unit-tests/deptgt-order.exp | 7 +
contrib/bmake/unit-tests/deptgt-order.mk | 4 +-
contrib/bmake/unit-tests/deptgt-path-suffix.exp | 5 +-
contrib/bmake/unit-tests/deptgt-path-suffix.mk | 10 +-
contrib/bmake/unit-tests/deptgt.exp | 13 +-
contrib/bmake/unit-tests/deptgt.mk | 11 +-
contrib/bmake/unit-tests/directive-dinclude.exp | 5 +-
contrib/bmake/unit-tests/directive-dinclude.mk | 25 +-
contrib/bmake/unit-tests/directive-elifdef.mk | 21 +-
contrib/bmake/unit-tests/directive-elifndef.mk | 23 +-
contrib/bmake/unit-tests/directive-export-impl.exp | 16 +-
contrib/bmake/unit-tests/directive-for-escape.exp | 102 +-
contrib/bmake/unit-tests/directive-for-escape.mk | 62 +-
.../unit-tests/directive-for-generating-endif.exp | 2 +-
contrib/bmake/unit-tests/directive-for.exp | 18 +
contrib/bmake/unit-tests/directive-for.mk | 81 +-
.../bmake/unit-tests/directive-hyphen-include.exp | 5 +-
.../bmake/unit-tests/directive-hyphen-include.mk | 22 +-
contrib/bmake/unit-tests/directive-if.exp | 23 +-
contrib/bmake/unit-tests/directive-if.mk | 15 +-
contrib/bmake/unit-tests/directive-ifdef.exp | 3 -
contrib/bmake/unit-tests/directive-ifdef.mk | 44 +-
contrib/bmake/unit-tests/directive-ifmake.exp | 6 +-
contrib/bmake/unit-tests/directive-ifmake.mk | 39 +-
contrib/bmake/unit-tests/directive-include.exp | 2 +
contrib/bmake/unit-tests/directive-include.mk | 33 +-
contrib/bmake/unit-tests/directive-info.exp | 2 +-
contrib/bmake/unit-tests/directive-info.mk | 13 +-
contrib/bmake/unit-tests/directive-sinclude.exp | 5 +-
contrib/bmake/unit-tests/directive-sinclude.mk | 18 +-
contrib/bmake/unit-tests/directive-undef.exp | 2 +-
contrib/bmake/unit-tests/directive-unexport-env.mk | 5 +-
contrib/bmake/unit-tests/directive-warning.exp | 16 +-
contrib/bmake/unit-tests/directive-warning.mk | 9 +-
contrib/bmake/unit-tests/directive.exp | 10 +-
contrib/bmake/unit-tests/directive.mk | 22 +-
contrib/bmake/unit-tests/envfirst.mk | 44 -
contrib/bmake/unit-tests/hanoi-include.mk | 6 +-
contrib/bmake/unit-tests/include-main.exp | 12 +-
contrib/bmake/unit-tests/include-main.mk | 4 +-
contrib/bmake/unit-tests/include-sub.mk | 10 +-
contrib/bmake/unit-tests/meta-cmd-cmp.exp | 16 +
contrib/bmake/unit-tests/meta-cmd-cmp.mk | 36 +-
contrib/bmake/unit-tests/modts.exp | 14 -
contrib/bmake/unit-tests/modts.mk | 47 -
contrib/bmake/unit-tests/modword.exp | 126 --
contrib/bmake/unit-tests/modword.mk | 161 --
contrib/bmake/unit-tests/opt-debug-cond.exp | 5 +
contrib/bmake/unit-tests/opt-debug-cond.mk | 22 +-
contrib/bmake/unit-tests/opt-debug-curdir.mk | 10 +-
contrib/bmake/unit-tests/opt-debug-file.exp | 13 +-
contrib/bmake/unit-tests/opt-debug-file.mk | 48 +-
contrib/bmake/unit-tests/opt-debug-hash.exp | 7 +-
contrib/bmake/unit-tests/opt-debug-hash.mk | 9 +-
contrib/bmake/unit-tests/opt-debug-parse.exp | 25 +
contrib/bmake/unit-tests/opt-debug-parse.mk | 34 +-
contrib/bmake/unit-tests/opt-debug-var.exp | 6 +
contrib/bmake/unit-tests/opt-debug-var.mk | 30 +-
contrib/bmake/unit-tests/opt-debug-x-trace.exp | 2 +
contrib/bmake/unit-tests/opt-debug-x-trace.mk | 10 +-
contrib/bmake/unit-tests/opt-define.mk | 30 +-
contrib/bmake/unit-tests/opt-env.exp | 6 +-
contrib/bmake/unit-tests/opt-env.mk | 45 +-
contrib/bmake/unit-tests/opt-jobs-internal.exp | 7 +-
contrib/bmake/unit-tests/opt-jobs-internal.mk | 11 +-
contrib/bmake/unit-tests/opt-raw.mk | 16 +-
contrib/bmake/unit-tests/opt-silent.exp | 2 +
contrib/bmake/unit-tests/opt-silent.mk | 8 +-
.../unit-tests/{var-class.exp => opt-version.exp} | 1 +
contrib/bmake/unit-tests/opt-version.mk | 12 +
contrib/bmake/unit-tests/opt-where-am-i.exp | 3 +
contrib/bmake/unit-tests/opt-where-am-i.mk | 14 +-
contrib/bmake/unit-tests/parse.exp | 5 +
contrib/bmake/unit-tests/parse.mk | 14 +
contrib/bmake/unit-tests/posix.mk | 7 +-
contrib/bmake/unit-tests/sh.mk | 5 +-
contrib/bmake/unit-tests/suff-incomplete.exp | 12 +-
contrib/bmake/unit-tests/suff-main-several.exp | 30 +-
contrib/bmake/unit-tests/suff-rebuild.exp | 22 +-
contrib/bmake/unit-tests/var-class-cmdline.exp | 4 -
contrib/bmake/unit-tests/var-class-global.mk | 8 -
contrib/bmake/unit-tests/var-class-local.exp | 5 -
contrib/bmake/unit-tests/var-class-local.mk | 45 -
contrib/bmake/unit-tests/var-class.mk | 9 -
contrib/bmake/unit-tests/var-eval-short.exp | 16 +-
contrib/bmake/unit-tests/var-eval-short.mk | 11 +-
contrib/bmake/unit-tests/var-op-expand.mk | 4 +-
contrib/bmake/unit-tests/var-op-shell.exp | 12 +-
contrib/bmake/unit-tests/var-op-shell.mk | 15 +-
contrib/bmake/unit-tests/var-op-sunsh.mk | 49 +-
contrib/bmake/unit-tests/var-recursive.exp | 7 +
contrib/bmake/unit-tests/var-recursive.mk | 16 +-
contrib/bmake/unit-tests/var-scope-cmdline.exp | 4 +
.../{var-class-cmdline.mk => var-scope-cmdline.mk} | 2 +-
.../unit-tests/{envfirst.exp => var-scope-env.exp} | 0
.../{var-class-env.mk => var-scope-env.mk} | 2 +-
.../{var-class-env.exp => var-scope-global.exp} | 0
contrib/bmake/unit-tests/var-scope-global.mk | 18 +
...class-global.exp => var-scope-local-legacy.exp} | 0
...s-local-legacy.mk => var-scope-local-legacy.mk} | 2 +-
contrib/bmake/unit-tests/var-scope-local.exp | 21 +
contrib/bmake/unit-tests/var-scope-local.mk | 200 +++
.../{var-class-local-legacy.exp => var-scope.exp} | 0
contrib/bmake/unit-tests/var-scope.mk | 9 +
contrib/bmake/unit-tests/varmod-assign-shell.exp | 14 +
contrib/bmake/unit-tests/varmod-assign-shell.mk | 36 +
contrib/bmake/unit-tests/varmod-ifelse.mk | 6 +-
contrib/bmake/unit-tests/varmod-indirect.exp | 12 +-
contrib/bmake/unit-tests/varmod-indirect.mk | 6 +-
contrib/bmake/unit-tests/varmod-loop.exp | 6 +-
contrib/bmake/unit-tests/varmod-order-numeric.mk | 7 +-
contrib/bmake/unit-tests/varmod-order.mk | 16 +-
contrib/bmake/unit-tests/varmod-quote-dollar.exp | 1 +
contrib/bmake/unit-tests/varmod-quote-dollar.mk | 6 +-
contrib/bmake/unit-tests/varmod-select-words.exp | 125 ++
contrib/bmake/unit-tests/varmod-select-words.mk | 162 +-
contrib/bmake/unit-tests/varmod-shell.exp | 10 +
contrib/bmake/unit-tests/varmod-shell.mk | 10 +-
contrib/bmake/unit-tests/varmod-sun-shell.exp | 11 +
contrib/bmake/unit-tests/varmod-sun-shell.mk | 7 +-
contrib/bmake/unit-tests/varmod-to-separator.exp | 26 +-
contrib/bmake/unit-tests/varmod-to-separator.mk | 93 +-
contrib/bmake/unit-tests/varname-dot-make-jobs.exp | 7 +
contrib/bmake/unit-tests/varname-dot-make-jobs.mk | 24 +-
contrib/bmake/unit-tests/varname-dot-make-pid.mk | 18 +-
contrib/bmake/unit-tests/varname-dot-make-ppid.mk | 25 +-
contrib/bmake/unit-tests/varname-dot-shell.exp | 12 +-
contrib/bmake/unit-tests/varname-dot-suffixes.mk | 6 +-
contrib/bmake/unit-tests/varname-empty.exp | 1 +
contrib/bmake/unit-tests/varname-makeflags.mk | 20 +-
contrib/bmake/unit-tests/varname.mk | 44 +-
contrib/bmake/unit-tests/varparse-errors.exp | 6 +
contrib/bmake/unit-tests/varparse-errors.mk | 22 +-
contrib/bmake/unit-tests/varquote.mk | 6 +-
contrib/bmake/util.c | 43 +-
contrib/bmake/var.c | 692 ++++-----
218 files changed, 5441 insertions(+), 4167 deletions(-)
diff --cc contrib/bmake/job.c
index f90c35bb6d49,000000000000..0dd202394e4d
mode 100644,000000..100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@@ -1,3067 -1,0 +1,3068 @@@
- /* $NetBSD: job.c,v 1.440 2021/11/28 19:51:06 rillig Exp $ */
++/* $NetBSD: job.c,v 1.451 2022/02/04 23:22:19 rillig Exp $ */
+
+/*
+ * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1988, 1989 by Adam de Boor
+ * Copyright (c) 1989 by Berkeley Softworks
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Adam de Boor.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * job.c --
+ * handle the creation etc. of our child processes.
+ *
+ * Interface:
+ * Job_Init Called to initialize this module. In addition,
+ * the .BEGIN target is made including all of its
+ * dependencies before this function returns.
+ * Hence, the makefiles must have been parsed
+ * before this function is called.
+ *
+ * Job_End Clean up any memory used.
+ *
+ * Job_Make Start the creation of the given target.
+ *
+ * Job_CatchChildren
+ * Check for and handle the termination of any
+ * children. This must be called reasonably
+ * frequently to keep the whole make going at
+ * a decent clip, since job table entries aren't
+ * removed until their process is caught this way.
+ *
+ * Job_CatchOutput
+ * Print any output our children have produced.
+ * Should also be called fairly frequently to
+ * keep the user informed of what's going on.
+ * If no output is waiting, it will block for
+ * a time given by the SEL_* constants, below,
+ * or until output is ready.
+ *
+ * Job_ParseShell Given a special dependency line with target '.SHELL',
+ * define the shell that is used for the creation
+ * commands in jobs mode.
+ *
+ * Job_Finish Perform any final processing which needs doing.
+ * This includes the execution of any commands
+ * which have been/were attached to the .END
+ * target. It should only be called when the
+ * job table is empty.
+ *
+ * Job_AbortAll Abort all currently running jobs. Do not handle
+ * output or do anything for the jobs, just kill them.
+ * Should only be called in an emergency.
+ *
+ * Job_CheckCommands
+ * Verify that the commands for a target are
+ * ok. Provide them if necessary and possible.
+ *
+ * Job_Touch Update a target without really updating it.
+ *
+ * Job_Wait Wait for all currently-running jobs to finish.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include "wait.h"
+
+#include <errno.h>
+#if !defined(USE_SELECT) && defined(HAVE_POLL_H)
+#include <poll.h>
+#else
+#ifndef USE_SELECT /* no poll.h */
+# define USE_SELECT
+#endif
+#if defined(HAVE_SYS_SELECT_H)
+# include <sys/select.h>
+#endif
+#endif
+#include <signal.h>
+#include <utime.h>
+#if defined(HAVE_SYS_SOCKET_H)
+# include <sys/socket.h>
+#endif
+
+#include "make.h"
+#include "dir.h"
+#include "job.h"
+#include "pathnames.h"
+#include "trace.h"
+
+/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
- MAKE_RCSID("$NetBSD: job.c,v 1.440 2021/11/28 19:51:06 rillig Exp $");
++MAKE_RCSID("$NetBSD: job.c,v 1.451 2022/02/04 23:22:19 rillig Exp $");
+
+/*
+ * A shell defines how the commands are run. All commands for a target are
+ * written into a single file, which is then given to the shell to execute
+ * the commands from it. The commands are written to the file using a few
+ * templates for echo control and error control.
+ *
+ * The name of the shell is the basename for the predefined shells, such as
+ * "sh", "csh", "bash". For custom shells, it is the full pathname, and its
+ * basename is used to select the type of shell; the longest match wins.
+ * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh.
+ *
+ * The echoing of command lines is controlled using hasEchoCtl, echoOff,
+ * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it
+ * still outputs something, but this something is not interesting, therefore
+ * it is filtered out using noPrint and noPrintLen.
+ *
+ * The error checking for individual commands is controlled using hasErrCtl,
+ * errOn, errOff and runChkTmpl.
+ *
+ * In case a shell doesn't have error control, echoTmpl is a printf template
+ * for echoing the command, should echoing be on; runIgnTmpl is another
+ * printf template for executing the command while ignoring the return
+ * status. Finally runChkTmpl is a printf template for running the command and
+ * causing the shell to exit on error. If any of these strings are empty when
+ * hasErrCtl is false, the command will be executed anyway as is, and if it
+ * causes an error, so be it. Any templates set up to echo the command will
+ * escape any '$ ` \ "' characters in the command string to avoid unwanted
+ * shell code injection, the escaped command is safe to use in double quotes.
+ *
+ * The command-line flags "echo" and "exit" also control the behavior. The
+ * "echo" flag causes the shell to start echoing commands right away. The
+ * "exit" flag causes the shell to exit when an error is detected in one of
+ * the commands.
+ */
+typedef struct Shell {
+
+ /*
+ * The name of the shell. For Bourne and C shells, this is used only
+ * to find the shell description when used as the single source of a
+ * .SHELL target. For user-defined shells, this is the full path of
+ * the shell.
+ */
+ const char *name;
+
+ bool hasEchoCtl; /* whether both echoOff and echoOn are there */
+ const char *echoOff; /* command to turn echoing off */
+ const char *echoOn; /* command to turn echoing back on */
+ const char *noPrint; /* text to skip when printing output from the
+ * shell. This is usually the same as echoOff */
+ size_t noPrintLen; /* length of noPrint command */
+
+ bool hasErrCtl; /* whether error checking can be controlled
+ * for individual commands */
+ const char *errOn; /* command to turn on error checking */
+ const char *errOff; /* command to turn off error checking */
+
+ const char *echoTmpl; /* template to echo a command */
- const char *runIgnTmpl; /* template to run a command
- * without error checking */
- const char *runChkTmpl; /* template to run a command
- * with error checking */
++ const char *runIgnTmpl; /* template to run a command without error
++ * checking */
++ const char *runChkTmpl; /* template to run a command with error
++ * checking */
+
- /* string literal that results in a newline character when it appears
- * outside of any 'quote' or "quote" characters */
++ /*
++ * A string literal that results in a newline character when it
++ * occurs outside of any 'quote' or "quote" characters.
++ */
+ const char *newline;
+ char commentChar; /* character used by shell for comment lines */
+
+ const char *echoFlag; /* shell flag to echo commands */
+ const char *errFlag; /* shell flag to exit on error */
+} Shell;
+
+typedef struct CommandFlags {
+ /* Whether to echo the command before or instead of running it. */
+ bool echo;
+
+ /* Run the command even in -n or -N mode. */
+ bool always;
+
+ /*
+ * true if we turned error checking off before writing the command to
+ * the commands file and need to turn it back on
+ */
+ bool ignerr;
+} CommandFlags;
+
+/*
+ * Write shell commands to a file.
+ *
+ * TODO: keep track of whether commands are echoed.
+ * TODO: keep track of whether error checking is active.
+ */
+typedef struct ShellWriter {
+ FILE *f;
+
+ /* we've sent 'set -x' */
+ bool xtraced;
+
+} ShellWriter;
+
+/*
+ * FreeBSD: traditionally .MAKE is not required to
+ * pass jobs queue to sub-makes.
+ * Use .MAKE.ALWAYS_PASS_JOB_QUEUE=no to disable.
+ */
+#define MAKE_ALWAYS_PASS_JOB_QUEUE "${.MAKE.ALWAYS_PASS_JOB_QUEUE:U}"
+static bool Always_pass_job_queue = true;
+/*
+ * FreeBSD: aborting entire parallel make isn't always
+ * desired. When doing tinderbox for example, failure of
+ * one architecture should not stop all.
+ * We still want to bail on interrupt though.
+ */
+#define MAKE_JOB_ERROR_TOKEN "${MAKE_JOB_ERROR_TOKEN:U}"
+static bool Job_error_token = true;
+
+/*
+ * error handling variables
+ */
+static int job_errors = 0; /* number of errors reported */
+static enum { /* Why is the make aborting? */
+ ABORT_NONE,
+ ABORT_ERROR, /* Aborted because of an error */
+ ABORT_INTERRUPT, /* Aborted because it was interrupted */
+ ABORT_WAIT /* Waiting for jobs to finish */
+} aborting = ABORT_NONE;
+#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
+
+/*
+ * this tracks the number of tokens currently "out" to build jobs.
+ */
+int jobTokensRunning = 0;
+
+typedef enum JobStartResult {
+ JOB_RUNNING, /* Job is running */
+ JOB_ERROR, /* Error in starting the job */
+ JOB_FINISHED /* The job is already finished */
+} JobStartResult;
+
+/*
+ * Descriptions for various shells.
+ *
+ * The build environment may set DEFSHELL_INDEX to one of
+ * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
+ * select one of the predefined shells as the default shell.
+ *
+ * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
+ * name or the full path of a sh-compatible shell, which will be used as
+ * the default shell.
+ *
+ * ".SHELL" lines in Makefiles can choose the default shell from the
+ * set defined here, or add additional shells.
+ */
+
+#ifdef DEFSHELL_CUSTOM
+#define DEFSHELL_INDEX_CUSTOM 0
+#define DEFSHELL_INDEX_SH 1
+#define DEFSHELL_INDEX_KSH 2
+#define DEFSHELL_INDEX_CSH 3
+#else /* !DEFSHELL_CUSTOM */
+#define DEFSHELL_INDEX_SH 0
+#define DEFSHELL_INDEX_KSH 1
+#define DEFSHELL_INDEX_CSH 2
+#endif /* !DEFSHELL_CUSTOM */
+
+#ifndef DEFSHELL_INDEX
+#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
+#endif /* !DEFSHELL_INDEX */
+
+static Shell shells[] = {
+#ifdef DEFSHELL_CUSTOM
+ /*
+ * An sh-compatible shell with a non-standard name.
+ *
+ * Keep this in sync with the "sh" description below, but avoid
+ * non-portable features that might not be supplied by all
+ * sh-compatible shells.
+ */
+ {
+ DEFSHELL_CUSTOM, /* .name */
+ false, /* .hasEchoCtl */
+ "", /* .echoOff */
+ "", /* .echoOn */
+ "", /* .noPrint */
+ 0, /* .noPrintLen */
+ false, /* .hasErrCtl */
+ "", /* .errOn */
+ "", /* .errOff */
+ "echo \"%s\"\n", /* .echoTmpl */
+ "%s\n", /* .runIgnTmpl */
+ "{ %s \n} || exit $?\n", /* .runChkTmpl */
+ "'\n'", /* .newline */
+ '#', /* .commentChar */
+ "", /* .echoFlag */
+ "", /* .errFlag */
+ },
+#endif /* DEFSHELL_CUSTOM */
+ /*
+ * SH description. Echo control is also possible and, under
+ * sun UNIX anyway, one can even control error checking.
+ */
+ {
+ "sh", /* .name */
+ false, /* .hasEchoCtl */
+ "", /* .echoOff */
+ "", /* .echoOn */
+ "", /* .noPrint */
+ 0, /* .noPrintLen */
+ false, /* .hasErrCtl */
+ "", /* .errOn */
+ "", /* .errOff */
+ "echo \"%s\"\n", /* .echoTmpl */
+ "%s\n", /* .runIgnTmpl */
+ "{ %s \n} || exit $?\n", /* .runChkTmpl */
+ "'\n'", /* .newline */
+ '#', /* .commentChar*/
+#if defined(MAKE_NATIVE) && defined(__NetBSD__)
+ /* XXX: -q is not really echoFlag, it's more like noEchoInSysFlag. */
+ "q", /* .echoFlag */
+#else
+ "", /* .echoFlag */
+#endif
+ "", /* .errFlag */
+ },
+ /*
+ * KSH description.
+ */
+ {
+ "ksh", /* .name */
+ true, /* .hasEchoCtl */
+ "set +v", /* .echoOff */
+ "set -v", /* .echoOn */
+ "set +v", /* .noPrint */
+ 6, /* .noPrintLen */
+ false, /* .hasErrCtl */
+ "", /* .errOn */
+ "", /* .errOff */
+ "echo \"%s\"\n", /* .echoTmpl */
+ "%s\n", /* .runIgnTmpl */
+ "{ %s \n} || exit $?\n", /* .runChkTmpl */
+ "'\n'", /* .newline */
+ '#', /* .commentChar */
+ "v", /* .echoFlag */
+ "", /* .errFlag */
+ },
+ /*
+ * CSH description. The csh can do echo control by playing
+ * with the setting of the 'echo' shell variable. Sadly,
+ * however, it is unable to do error control nicely.
+ */
+ {
+ "csh", /* .name */
+ true, /* .hasEchoCtl */
+ "unset verbose", /* .echoOff */
+ "set verbose", /* .echoOn */
+ "unset verbose", /* .noPrint */
+ 13, /* .noPrintLen */
+ false, /* .hasErrCtl */
+ "", /* .errOn */
+ "", /* .errOff */
+ "echo \"%s\"\n", /* .echoTmpl */
+ "csh -c \"%s || exit 0\"\n", /* .runIgnTmpl */
+ "", /* .runChkTmpl */
+ "'\\\n'", /* .newline */
+ '#', /* .commentChar */
+ "v", /* .echoFlag */
+ "e", /* .errFlag */
+ }
+};
+
+/*
+ * This is the shell to which we pass all commands in the Makefile.
+ * It is set by the Job_ParseShell function.
+ */
+static Shell *shell = &shells[DEFSHELL_INDEX];
+const char *shellPath = NULL; /* full pathname of executable image */
+const char *shellName = NULL; /* last component of shellPath */
+char *shellErrFlag = NULL;
+static char *shell_freeIt = NULL; /* Allocated memory for custom .SHELL */
+
+
+static Job *job_table; /* The structures that describe them */
+static Job *job_table_end; /* job_table + maxJobs */
+static unsigned int wantToken; /* we want a token */
+static bool lurking_children = false;
+static bool make_suspended = false; /* Whether we've seen a SIGTSTP (etc) */
+
+/*
+ * Set of descriptors of pipes connected to
+ * the output channels of children
+ */
+static struct pollfd *fds = NULL;
+static Job **jobByFdIndex = NULL;
+static nfds_t fdsLen = 0;
+static void watchfd(Job *);
+static void clearfd(Job *);
+static bool readyfd(Job *);
+
- static char *targPrefix = NULL; /* To identify a job change in the output. */
++static char *targPrefix = NULL; /* To identify a job change in the output. */
+static Job tokenWaitJob; /* token wait pseudo-job */
+
+static Job childExitJob; /* child exit pseudo-job */
+#define CHILD_EXIT "."
+#define DO_JOB_RESUME "R"
+
+enum {
+ npseudojobs = 2 /* number of pseudo-jobs */
+};
+
+static sigset_t caught_signals; /* Set of signals we handle */
+static volatile sig_atomic_t caught_sigchld;
+
+static void CollectOutput(Job *, bool);
+static void JobInterrupt(bool, int) MAKE_ATTR_DEAD;
+static void JobRestartJobs(void);
+static void JobSigReset(void);
+
+static void
+SwitchOutputTo(GNode *gn)
+{
+ /* The node for which output was most recently produced. */
+ static GNode *lastNode = NULL;
+
+ if (gn == lastNode)
+ return;
+ lastNode = gn;
+
+ if (opts.maxJobs != 1 && targPrefix != NULL && targPrefix[0] != '\0')
+ (void)fprintf(stdout, "%s %s ---\n", targPrefix, gn->name);
+}
+
+static unsigned
+nfds_per_job(void)
+{
+#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
+ if (useMeta)
+ return 2;
+#endif
+ return 1;
+}
+
+void
+Job_FlagsToString(const Job *job, char *buf, size_t bufsize)
+{
+ snprintf(buf, bufsize, "%c%c%c",
+ job->ignerr ? 'i' : '-',
+ !job->echo ? 's' : '-',
+ job->special ? 'S' : '-');
+}
+
+static void
+DumpJobs(const char *where)
+{
+ Job *job;
+ char flags[4];
+
+ debug_printf("job table @ %s\n", where);
+ for (job = job_table; job < job_table_end; job++) {
+ Job_FlagsToString(job, flags, sizeof flags);
+ debug_printf("job %d, status %d, flags %s, pid %d\n",
+ (int)(job - job_table), job->status, flags, job->pid);
+ }
+}
+
+/*
+ * Delete the target of a failed, interrupted, or otherwise
+ * unsuccessful job unless inhibited by .PRECIOUS.
+ */
+static void
+JobDeleteTarget(GNode *gn)
+{
+ const char *file;
+
+ if (gn->type & OP_JOIN)
+ return;
+ if (gn->type & OP_PHONY)
+ return;
- if (Targ_Precious(gn))
++ if (GNode_IsPrecious(gn))
+ return;
+ if (opts.noExecute)
+ return;
+
+ file = GNode_Path(gn);
- if (eunlink(file) != -1)
++ if (unlink_file(file))
+ Error("*** %s removed", file);
+}
+
+/*
+ * JobSigLock/JobSigUnlock
+ *
+ * Signal lock routines to get exclusive access. Currently used to
+ * protect `jobs' and `stoppedJobs' list manipulations.
+ */
+static void
+JobSigLock(sigset_t *omaskp)
+{
+ if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) {
+ Punt("JobSigLock: sigprocmask: %s", strerror(errno));
+ sigemptyset(omaskp);
+ }
+}
+
+static void
+JobSigUnlock(sigset_t *omaskp)
+{
+ (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
+}
+
+static void
+JobCreatePipe(Job *job, int minfd)
+{
+ int i, fd, flags;
+ int pipe_fds[2];
+
+ if (pipe(pipe_fds) == -1)
+ Punt("Cannot create pipe: %s", strerror(errno));
+
+ for (i = 0; i < 2; i++) {
+ /* Avoid using low numbered fds */
+ fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
+ if (fd != -1) {
+ close(pipe_fds[i]);
+ pipe_fds[i] = fd;
+ }
+ }
+
+ job->inPipe = pipe_fds[0];
+ job->outPipe = pipe_fds[1];
+
+ /* Set close-on-exec flag for both */
+ if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
+ Punt("Cannot set close-on-exec: %s", strerror(errno));
+ if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
+ Punt("Cannot set close-on-exec: %s", strerror(errno));
+
+ /*
+ * We mark the input side of the pipe non-blocking; we poll(2) the
+ * pipe when we're waiting for a job token, but we might lose the
+ * race for the token when a new one becomes available, so the read
+ * from the pipe should not block.
+ */
+ flags = fcntl(job->inPipe, F_GETFL, 0);
+ if (flags == -1)
+ Punt("Cannot get flags: %s", strerror(errno));
+ flags |= O_NONBLOCK;
+ if (fcntl(job->inPipe, F_SETFL, flags) == -1)
+ Punt("Cannot set flags: %s", strerror(errno));
+}
+
+/* Pass the signal to each running job. */
+static void
+JobCondPassSig(int signo)
+{
+ Job *job;
+
+ DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo);
+
+ for (job = job_table; job < job_table_end; job++) {
+ if (job->status != JOB_ST_RUNNING)
+ continue;
+ DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n",
+ signo, job->pid);
+ KILLPG(job->pid, signo);
+ }
+}
+
+/*
+ * SIGCHLD handler.
+ *
+ * Sends a token on the child exit pipe to wake us up from select()/poll().
+ */
+/*ARGSUSED*/
+static void
+JobChildSig(int signo MAKE_ATTR_UNUSED)
+{
+ caught_sigchld = 1;
+ while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 &&
+ errno == EAGAIN)
+ continue;
+}
+
+
+/* Resume all stopped jobs. */
+/*ARGSUSED*/
+static void
+JobContinueSig(int signo MAKE_ATTR_UNUSED)
+{
+ /*
+ * Defer sending SIGCONT to our stopped children until we return
+ * from the signal handler.
+ */
+ while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
+ errno == EAGAIN)
+ continue;
+}
+
+/*
+ * Pass a signal on to all jobs, then resend to ourselves.
+ * We die by the same signal.
+ */
+MAKE_ATTR_DEAD static void
+JobPassSig_int(int signo)
+{
+ /* Run .INTERRUPT target then exit */
+ JobInterrupt(true, signo);
+}
+
+/*
+ * Pass a signal on to all jobs, then resend to ourselves.
+ * We die by the same signal.
+ */
+MAKE_ATTR_DEAD static void
+JobPassSig_term(int signo)
+{
+ /* Dont run .INTERRUPT target then exit */
+ JobInterrupt(false, signo);
+}
+
+static void
+JobPassSig_suspend(int signo)
+{
+ sigset_t nmask, omask;
+ struct sigaction act;
+
+ /* Suppress job started/continued messages */
+ make_suspended = true;
+
+ /* Pass the signal onto every job */
+ JobCondPassSig(signo);
+
+ /*
+ * Send ourselves the signal now we've given the message to everyone
+ * else. Note we block everything else possible while we're getting
+ * the signal. This ensures that all our jobs get continued when we
+ * wake up before we take any other signal.
+ */
+ sigfillset(&nmask);
+ sigdelset(&nmask, signo);
+ (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
+
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ (void)sigaction(signo, &act, NULL);
+
+ DEBUG1(JOB, "JobPassSig passing signal %d to self.\n", signo);
+
+ (void)kill(getpid(), signo);
+
+ /*
+ * We've been continued.
+ *
+ * A whole host of signals continue to happen!
+ * SIGCHLD for any processes that actually suspended themselves.
+ * SIGCHLD for any processes that exited while we were alseep.
+ * The SIGCONT that actually caused us to wakeup.
+ *
+ * Since we defer passing the SIGCONT on to our children until
+ * the main processing loop, we can be sure that all the SIGCHLD
+ * events will have happened by then - and that the waitpid() will
+ * collect the child 'suspended' events.
+ * For correct sequencing we just need to ensure we process the
+ * waitpid() before passing on the SIGCONT.
+ *
+ * In any case nothing else is needed here.
+ */
+
+ /* Restore handler and signal mask */
+ act.sa_handler = JobPassSig_suspend;
+ (void)sigaction(signo, &act, NULL);
+ (void)sigprocmask(SIG_SETMASK, &omask, NULL);
+}
+
+static Job *
+JobFindPid(int pid, JobStatus status, bool isJobs)
+{
+ Job *job;
*** 2892 LINES SKIPPED ***