git: 129043849f62 - main - Merge bmake-20211212

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Sat, 18 Dec 2021 18:14:49 UTC
The branch main has been updated by sjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=129043849f62f9cfa72f6fae68417d9995860f3f

commit 129043849f62f9cfa72f6fae68417d9995860f3f
Merge: 7ed5694dd9b9 2935fe8237c8
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2021-12-18 18:09:14 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2021-12-18 18:09:14 +0000

    Merge bmake-20211212
    
    commit '2935fe8237c83c1dcb113dd5335733263e68e6fd'

 contrib/bmake/ChangeLog                            | 231 ++++++++
 contrib/bmake/FILES                                |  15 +-
 contrib/bmake/Makefile                             |  17 +-
 contrib/bmake/Makefile.config.in                   |   2 +-
 contrib/bmake/VERSION                              |   2 +-
 contrib/bmake/_strtol.h                            | 213 +++++++
 contrib/bmake/arch.c                               | 124 ++--
 contrib/bmake/bmake.1                              |  19 +-
 contrib/bmake/bmake.cat1                           |  12 +-
 contrib/bmake/boot-strap                           |  17 +-
 contrib/bmake/bsd.after-import.mk                  |   3 +-
 contrib/bmake/buf.c                                |  23 +-
 contrib/bmake/buf.h                                |   3 +-
 contrib/bmake/compat.c                             |  28 +-
 contrib/bmake/cond.c                               | 342 +++++------
 contrib/bmake/config.h.in                          |  46 ++
 contrib/bmake/configure                            | 481 ++++++++++++++--
 contrib/bmake/configure.in                         | 200 +++++--
 contrib/bmake/dir.c                                |  33 +-
 contrib/bmake/enum.c                               |  80 ---
 contrib/bmake/enum.h                               | 179 ------
 contrib/bmake/filemon/filemon_ktrace.c             |   3 +-
 contrib/bmake/for.c                                | 130 +++--
 contrib/bmake/hash.c                               |  15 +-
 contrib/bmake/hash.h                               |  11 +-
 contrib/bmake/import.sh                            |  13 +-
 contrib/bmake/job.c                                |  43 +-
 contrib/bmake/lst.h                                |   6 +-
 contrib/bmake/main.c                               |   8 +-
 contrib/bmake/make-bootstrap.sh.in                 |   2 +-
 contrib/bmake/make.1                               |  19 +-
 contrib/bmake/make.c                               | 140 +++--
 contrib/bmake/make.h                               |  87 +--
 contrib/bmake/meta.c                               |  50 +-
 contrib/bmake/metachar.c                           |   6 +-
 contrib/bmake/metachar.h                           |  10 +-
 contrib/bmake/mk/ChangeLog                         | 104 ++++
 contrib/bmake/mk/FILES                             |   1 +
 contrib/bmake/mk/auto.dep.mk                       |  52 +-
 contrib/bmake/mk/autoconf.mk                       |  23 +-
 contrib/bmake/mk/autodep.mk                        |   7 +-
 contrib/bmake/mk/compiler.mk                       |  10 +-
 contrib/bmake/mk/dep.mk                            |   4 +-
 contrib/bmake/mk/dirdeps.mk                        |  57 +-
 contrib/bmake/mk/doc.mk                            |   4 +-
 contrib/bmake/mk/dpadd.mk                          |   4 +-
 contrib/bmake/mk/final.mk                          |   4 +-
 contrib/bmake/mk/init.mk                           |   4 +-
 contrib/bmake/mk/install-mk                        |   4 +-
 contrib/bmake/mk/java.mk                           |   4 +-
 contrib/bmake/mk/ldorder.mk                        |   4 +-
 contrib/bmake/mk/lib.mk                            |   6 +-
 contrib/bmake/mk/man.mk                            |  54 +-
 contrib/bmake/mk/meta.autodep.mk                   |  12 +-
 contrib/bmake/mk/meta.stage.mk                     |  11 +-
 contrib/bmake/mk/meta.sys.mk                       |  26 +-
 contrib/bmake/mk/meta2deps.py                      |  29 +-
 contrib/bmake/mk/obj.mk                            |   4 +-
 contrib/bmake/mk/options.mk                        |  38 +-
 contrib/bmake/mk/own.mk                            |   6 +-
 contrib/bmake/mk/prlist.mk                         |   4 +-
 contrib/bmake/mk/prog.mk                           |   4 +-
 contrib/bmake/mk/stage-install.sh                  |  10 +-
 contrib/bmake/mk/sys.mk                            |   9 +-
 contrib/bmake/mk/sys.vars.mk                       |   4 +-
 contrib/bmake/mk/sys/SCO_SV.mk                     |  13 +
 contrib/bmake/mk/sys/UnixWare.mk                   |  24 +-
 contrib/bmake/nonints.h                            |   9 +-
 contrib/bmake/os.sh                                |   4 +-
 contrib/bmake/parse.c                              | 171 +++---
 contrib/bmake/sigact.h                             | 104 ++++
 contrib/bmake/sigaction.c                          | 397 +++++++++++++
 contrib/bmake/str.c                                |   9 +-
 contrib/bmake/str.h                                |  27 +-
 contrib/bmake/suff.c                               | 119 ++--
 contrib/bmake/targ.c                               |  83 +--
 contrib/bmake/trace.c                              |   6 +-
 contrib/bmake/unit-tests/Makefile                  |  75 ++-
 contrib/bmake/unit-tests/Makefile.config.in        |   4 +-
 contrib/bmake/unit-tests/cond-cmp-numeric.exp      |   4 +
 contrib/bmake/unit-tests/cond-cmp-numeric.mk       |  18 +-
 contrib/bmake/unit-tests/cond-cmp-string.mk        |   4 +-
 contrib/bmake/unit-tests/cond-eof.exp              |   3 -
 contrib/bmake/unit-tests/cond-eof.mk               |  12 +-
 contrib/bmake/unit-tests/cond-func-defined.mk      |   4 +-
 contrib/bmake/unit-tests/cond-func-empty.exp       |   4 +-
 contrib/bmake/unit-tests/cond-func-empty.mk        |  73 +--
 contrib/bmake/unit-tests/cond-func.exp             |   2 +-
 contrib/bmake/unit-tests/cond-op-and.exp           |   5 +-
 contrib/bmake/unit-tests/cond-op-and.mk            |  30 +-
 contrib/bmake/unit-tests/cond-op-or.exp            |   5 +-
 contrib/bmake/unit-tests/cond-op-or.mk             |  30 +-
 contrib/bmake/unit-tests/cond-op.exp               |  34 +-
 contrib/bmake/unit-tests/cond-op.mk                |  39 +-
 contrib/bmake/unit-tests/cond-short.mk             |  69 ++-
 contrib/bmake/unit-tests/cond-token-plain.exp      |  27 +-
 contrib/bmake/unit-tests/cond-token-plain.mk       |  35 +-
 contrib/bmake/unit-tests/deptgt-default.exp        |   1 +
 contrib/bmake/unit-tests/deptgt-default.mk         |  17 +-
 contrib/bmake/unit-tests/deptgt-makeflags.mk       |  29 +-
 contrib/bmake/unit-tests/directive-else.exp        |   6 +-
 contrib/bmake/unit-tests/directive-endif.exp       |   8 +-
 contrib/bmake/unit-tests/directive-export-impl.exp |   4 +-
 contrib/bmake/unit-tests/directive-for-escape.exp  |  63 +-
 contrib/bmake/unit-tests/directive-for-escape.mk   |  49 +-
 contrib/bmake/unit-tests/directive-for-if.exp      |   8 +
 contrib/bmake/unit-tests/directive-for-if.mk       |  86 +++
 contrib/bmake/unit-tests/directive-for-null.exp    |   2 +-
 contrib/bmake/unit-tests/directive-include.exp     |   3 +
 contrib/bmake/unit-tests/directive-include.mk      |  24 +-
 contrib/bmake/unit-tests/export.mk                 |   4 +-
 contrib/bmake/unit-tests/job-output-null.exp       |   6 +-
 contrib/bmake/unit-tests/job-output-null.mk        |  21 +-
 contrib/bmake/unit-tests/lint.exp                  |   2 +-
 contrib/bmake/unit-tests/objdir-writable.exp       |   2 +-
 contrib/bmake/unit-tests/objdir-writable.mk        |  11 +-
 contrib/bmake/unit-tests/opt-debug-errors-jobs.exp |  10 +
 contrib/bmake/unit-tests/opt-debug-errors-jobs.mk  |  14 +-
 contrib/bmake/unit-tests/opt-debug-graph1.exp      |   1 -
 contrib/bmake/unit-tests/opt-debug-graph2.exp      |   1 -
 contrib/bmake/unit-tests/opt-debug-graph3.exp      |   1 -
 contrib/bmake/unit-tests/opt-file.mk               |  12 +-
 contrib/bmake/unit-tests/opt-tracefile.exp         |  11 +
 contrib/bmake/unit-tests/opt-tracefile.mk          |  18 +-
 contrib/bmake/unit-tests/suff-main-several.exp     |   1 -
 contrib/bmake/unit-tests/suff-transform-debug.exp  |   1 -
 contrib/bmake/unit-tests/var-eval-short.exp        |  14 +-
 contrib/bmake/unit-tests/var-eval-short.mk         |  18 +-
 contrib/bmake/unit-tests/var-op-expand.exp         |   8 +-
 contrib/bmake/unit-tests/var-op-expand.mk          | 105 +++-
 contrib/bmake/unit-tests/vardebug.exp              |   4 +-
 contrib/bmake/unit-tests/varmisc.mk                |  12 +-
 contrib/bmake/unit-tests/varmod-assign.exp         |  12 -
 contrib/bmake/unit-tests/varmod-assign.mk          | 107 ++--
 contrib/bmake/unit-tests/varmod-defined.exp        |   2 +-
 contrib/bmake/unit-tests/varmod-defined.mk         |   5 +-
 contrib/bmake/unit-tests/varmod-gmtime.exp         |  10 +-
 contrib/bmake/unit-tests/varmod-indirect.exp       |   2 +-
 contrib/bmake/unit-tests/varmod-localtime.exp      |  10 +-
 contrib/bmake/unit-tests/varmod-localtime.mk       |   2 +-
 contrib/bmake/unit-tests/varmod-loop-delete.exp    |   4 +
 contrib/bmake/unit-tests/varmod-loop-delete.mk     |  33 ++
 contrib/bmake/unit-tests/varmod-loop-varname.exp   |  16 +-
 contrib/bmake/unit-tests/varmod-loop-varname.mk    |   7 +-
 contrib/bmake/unit-tests/varmod-loop.exp           |   6 +-
 contrib/bmake/unit-tests/varmod-loop.mk            |  10 +-
 contrib/bmake/unit-tests/varmod-order-numeric.exp  |   1 +
 contrib/bmake/unit-tests/varmod-order-numeric.mk   |  54 ++
 contrib/bmake/unit-tests/varmod-order-reverse.mk   |   9 +-
 contrib/bmake/unit-tests/varmod-order-shuffle.mk   |  19 +-
 contrib/bmake/unit-tests/varmod-order-string.exp   |   1 +
 contrib/bmake/unit-tests/varmod-order-string.mk    |  28 +
 contrib/bmake/unit-tests/varmod-order.exp          |  25 +-
 contrib/bmake/unit-tests/varmod-order.mk           |  91 ++-
 contrib/bmake/unit-tests/varmod-root.exp           |  10 -
 contrib/bmake/unit-tests/varmod-root.mk            |  37 +-
 contrib/bmake/unit-tests/varmod-select-words.mk    |   5 +-
 contrib/bmake/unit-tests/varmod-subst.mk           |  15 +-
 contrib/bmake/unit-tests/varmod-to-separator.exp   |   4 +-
 contrib/bmake/unit-tests/varmod-unique.mk          |  35 +-
 .../unit-tests/varname-dot-make-save_dollars.mk    | 130 ++++-
 contrib/bmake/unit-tests/varname-dot-suffixes.exp  |  39 ++
 contrib/bmake/unit-tests/varname-dot-suffixes.mk   | 104 ++++
 contrib/bmake/unit-tests/varname-empty.exp         |   4 -
 contrib/bmake/util.c                               |  82 ++-
 contrib/bmake/var.c                                | 631 ++++++++++++---------
 166 files changed, 4798 insertions(+), 1888 deletions(-)

diff --cc contrib/bmake/Makefile
index 38ccb8a6a636,000000000000..82d9db52af76
mode 100644,000000..100644
--- a/contrib/bmake/Makefile
+++ b/contrib/bmake/Makefile
@@@ -1,220 -1,0 +1,221 @@@
- #	$Id: Makefile,v 1.114 2020/11/13 21:47:25 sjg Exp $
++#	$Id: Makefile,v 1.117 2021/12/04 18:51:30 sjg Exp $
 +
 +PROG=	bmake
 +
 +SRCS= \
 +	arch.c \
 +	buf.c \
 +	compat.c \
 +	cond.c \
 +	dir.c \
- 	enum.c \
 +	for.c \
 +	hash.c \
 +	job.c \
 +	lst.c \
 +	main.c \
 +	make.c \
 +	make_malloc.c \
 +	meta.c \
 +	metachar.c \
 +	parse.c \
 +	str.c \
 +	suff.c \
 +	targ.c \
 +	trace.c \
 +	util.c \
 +	var.c
 +
 +.-include "VERSION"
 +.-include "Makefile.inc"
 +
 +# this file gets generated by configure
 +.-include "Makefile.config"
 +
 +.if !empty(LIBOBJS)
 +SRCS+= ${LIBOBJS:T:.o=.c}
 +.endif
 +
 +# just in case
 +prefix?= /usr
 +srcdir?= ${.CURDIR}
 +
 +DEFAULT_SYS_PATH?= ${prefix}/share/mk
 +
 +CPPFLAGS+= -DUSE_META
 +CFLAGS+= ${CPPFLAGS}
 +CFLAGS+= -D_PATH_DEFSYSPATH=\"${DEFAULT_SYS_PATH}\"
 +CFLAGS+= -I. -I${srcdir} ${XDEFS} -DMAKE_NATIVE
 +CFLAGS+= ${COPTS.${.ALLSRC:M*.c:T:u}}
 +COPTS.main.c+= "-DMAKE_VERSION=\"${_MAKE_VERSION}\""
 +
 +.for x in FORCE_MACHINE FORCE_MACHINE_ARCH
 +.ifdef $x
 +COPTS.main.c+= "-D$x=\"${$x}\""
 +.endif
 +.endfor
 +
 +# meta mode can be useful even without filemon
 +# should be set by now
 +USE_FILEMON ?= no
 +.if ${USE_FILEMON:tl} != "no"
 +.PATH:	${srcdir}/filemon
 +SRCS+=	filemon_${USE_FILEMON}.c
 +COPTS.meta.c+= -DUSE_FILEMON -DUSE_FILEMON_${USE_FILEMON:tu}
 +COPTS.job.c+= ${COPTS.meta.c}
 +
 +.if ${USE_FILEMON} == "dev"
 +FILEMON_H ?= /usr/include/dev/filemon/filemon.h
 +.if exists(${FILEMON_H}) && ${FILEMON_H:T} == "filemon.h"
 +COPTS.filemon_dev.c += -DHAVE_FILEMON_H -I${FILEMON_H:H}
 +.endif
 +.endif				# USE_FILEMON == dev
 +
 +.endif				# USE_FILEMON
 +
 +.PATH:	${srcdir}
 +
 +.if make(obj) || make(clean)
 +SUBDIR+= unit-tests
 +.endif
 +
 +# start-delete1 for bsd.after-import.mk
 +# we skip a lot of this when building as part of FreeBSD etc.
 +
 +# list of OS's which are derrived from BSD4.4
 +BSD44_LIST= NetBSD FreeBSD OpenBSD DragonFly MirBSD Bitrig
 +# we are...
 +OS := ${.MAKE.OS:U${uname -s:L:sh}}
 +# are we 4.4BSD ?
 +isBSD44:=${BSD44_LIST:M${OS}}
 +
 +.if ${isBSD44} == ""
 +MANTARGET= cat
 +INSTALL?=${srcdir}/install-sh
- .if (${MACHINE} == "sun386")
++.if ${MACHINE} == "sun386"
 +# even I don't have one of these anymore :-)
 +CFLAGS+= -DPORTAR
- .elif (${MACHINE} != "sunos")
++.elif ${OS} != "SunOS"
++# assume the worst
 +SRCS+= sigcompat.c
 +CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
 +.endif
 +.else
 +MANTARGET?= man
 +.endif
 +
 +# turn this on by default - ignored if we are root
 +WITH_INSTALL_AS_USER=
 +
 +# suppress with -DWITHOUT_*
 +OPTIONS_DEFAULT_YES+= \
 +	AUTOCONF_MK \
 +	INSTALL_MK \
 +	PROG_LINK
 +
 +OPTIONS_DEFAULT_NO+= \
 +	PROG_VERSION
 +
 +# process options now
 +.include <own.mk>
 +
 +.if ${MK_PROG_VERSION} == "yes"
 +PROG_NAME= ${PROG}-${_MAKE_VERSION}
 +.if ${MK_PROG_LINK} == "yes"
 +SYMLINKS+= ${PROG_NAME} ${BINDIR}/${PROG}
 +.endif
 +.endif
 +
 +EXTRACT_MAN=no
 +# end-delete1
 +
 +MAN= ${PROG}.1
 +MAN1= ${MAN}
 +
- .if (${PROG} != "make")
++.if ${PROG} != "make"
 +CLEANFILES+= my.history
 +.if make(${MAN}) || !exists(${srcdir}/${MAN})
 +my.history:
 +	@(echo ".Nm"; \
 +	echo "is derived from NetBSD"; \
 +	echo ".Xr make 1 ."; \
 +	echo "It uses autoconf to facilitate portability to other platforms."; \
 +	echo ".Pp") > $@
 +
 +.NOPATH: ${MAN}
 +${MAN}:	make.1 my.history
 +	@echo making $@
 +	@sed \
 +	-e '/^.Dt/s/MAKE/${PROG:tu}/' \
 +	-e 's/^.Nx/NetBSD/' \
 +	-e '/^.Nm/s/make/${PROG}/' \
 +	-e '/^.Sh HISTORY/rmy.history' \
 +	-e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
 +
 +all beforeinstall: ${MAN}
 +_mfromdir=.
 +.endif
 +.endif
 +
 +MANTARGET?= cat
 +MANDEST?= ${MANDIR}/${MANTARGET}1
 +
 +.if ${MANTARGET} == "cat"
 +_mfromdir=${srcdir}
 +.endif
 +
 +.include <prog.mk>
 +
 +CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H
 +COPTS.var.c += -Wno-cast-qual
 +COPTS.job.c += -Wno-format-nonliteral
 +COPTS.parse.c += -Wno-format-nonliteral
 +COPTS.var.c += -Wno-format-nonliteral
 +
 +# Force these
 +SHAREDIR= ${SHAREDIR.bmake:U${prefix}/share}
 +BINDIR= ${BINDIR.bmake:U${prefix}/bin}
 +MANDIR= ${MANDIR.bmake:U${SHAREDIR}/man}
 +
 +.if !exists(.depend)
 +${OBJS}: config.h
 +.endif
 +
 +# start-delete2 for bsd.after-import.mk
 +
 +# make sure that MAKE_VERSION gets updated.
 +main.o: ${srcdir}/VERSION
 +
 +.if ${MK_AUTOCONF_MK} == "yes"
 +CONFIGURE_DEPS += ${.CURDIR}/VERSION
 +# we do not need or want the generated makefile
 +CONFIGURE_ARGS += --without-makefile
++AUTOCONF_GENERATED_MAKEFILE = Makefile.config
 +.include <autoconf.mk>
 +.endif
- SHARE_MK?=${SHAREDIR}/mk
- MKSRC=${srcdir}/mk
- INSTALL?=${srcdir}/install-sh
++SHARE_MK ?= ${SHAREDIR}/mk
++MKSRC = ${srcdir}/mk
++INSTALL ?= ${srcdir}/install-sh
 +
 +.if ${MK_INSTALL_MK} == "yes"
 +install: install-mk
 +.endif
 +
 +beforeinstall:
 +	test -d ${DESTDIR}${BINDIR} || ${INSTALL} -m 775 -d ${DESTDIR}${BINDIR}
 +	test -d ${DESTDIR}${MANDEST} || ${INSTALL} -m 775 -d ${DESTDIR}${MANDEST}
 +
 +install-mk:
 +.if exists(${MKSRC}/install-mk)
 +	test -d ${DESTDIR}${SHARE_MK} || ${INSTALL} -m 775 -d ${DESTDIR}${SHARE_MK}
 +	sh ${MKSRC}/install-mk -v -m 644 ${DESTDIR}${SHARE_MK}
 +.else
 +	@echo need to unpack mk.tar.gz under ${srcdir} or set MKSRC; false
 +.endif
 +# end-delete2
 +
 +# A simple unit-test driver to help catch regressions
 +TEST_MAKE ?= ${.OBJDIR}/${PROG:T}
 +accept test:
 +	cd ${.CURDIR}/unit-tests && \
 +	MAKEFLAGS= ${TEST_MAKE} -r -m / ${.TARGET} ${TESTS:DTESTS=${TESTS:Q}}
 +
diff --cc contrib/bmake/_strtol.h
index 000000000000,51c71490ae57..51c71490ae57
mode 000000,100644..100644
--- a/contrib/bmake/_strtol.h
+++ b/contrib/bmake/_strtol.h
diff --cc contrib/bmake/job.c
index e4b77477e816,000000000000..f90c35bb6d49
mode 100644,000000..100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@@ -1,3050 -1,0 +1,3067 @@@
- /*	$NetBSD: job.c,v 1.435 2021/06/16 09:47:51 rillig Exp $	*/
++/*	$NetBSD: job.c,v 1.440 2021/11/28 19:51:06 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.435 2021/06/16 09:47:51 rillig Exp $");
++MAKE_RCSID("$NetBSD: job.c,v 1.440 2021/11/28 19:51:06 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 */
 +
 +	/* string literal that results in a newline character when it appears
 +	 * 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 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))
 +		return;
 +	if (opts.noExecute)
 +		return;
 +
 +	file = GNode_Path(gn);
 +	if (eunlink(file) != -1)
 +		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));
*** 2587 LINES SKIPPED ***