svn commit: r367863 - in head: contrib/bmake contrib/bmake/filemon contrib/bmake/missing contrib/bmake/mk contrib/bmake/unit-tests usr.bin/bmake usr.bin/bmake/unit-tests

Simon J. Gerraty sjg at FreeBSD.org
Fri Nov 20 06:02:33 UTC 2020


Author: sjg
Date: Fri Nov 20 06:02:31 2020
New Revision: 367863
URL: https://svnweb.freebsd.org/changeset/base/367863

Log:
  Merge bmake-20201117
  
  o allow env var MAKE_OBJDIR_CHECK_WRITABLE=no to skip writable
    checks in InitObjdir.  Explicit .OBJDIR target always allows
    read-only directory.
  
  o More code cleanup and refactoring.
  
  o More unit tests
  
  MFC after:	1 week

Added:
  head/contrib/bmake/missing/
     - copied from r367861, vendor/NetBSD/bmake/dist/missing/
  head/contrib/bmake/unit-tests/cmd-errors-lint.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmd-errors-lint.exp
  head/contrib/bmake/unit-tests/cmd-errors-lint.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmd-errors-lint.mk
  head/contrib/bmake/unit-tests/cmd-errors.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmd-errors.exp
  head/contrib/bmake/unit-tests/cmd-errors.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmd-errors.mk
  head/contrib/bmake/unit-tests/cmdline-undefined.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmdline-undefined.exp
  head/contrib/bmake/unit-tests/cmdline-undefined.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cmdline-undefined.mk
  head/contrib/bmake/unit-tests/cond-op-and-lint.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cond-op-and-lint.exp
  head/contrib/bmake/unit-tests/cond-op-and-lint.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cond-op-and-lint.mk
  head/contrib/bmake/unit-tests/cond-op-or-lint.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cond-op-or-lint.exp
  head/contrib/bmake/unit-tests/cond-op-or-lint.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/cond-op-or-lint.mk
  head/contrib/bmake/unit-tests/directive-if-nested.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/directive-if-nested.exp
  head/contrib/bmake/unit-tests/directive-if-nested.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/directive-if-nested.mk
  head/contrib/bmake/unit-tests/gnode-submake.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/gnode-submake.exp
  head/contrib/bmake/unit-tests/gnode-submake.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/gnode-submake.mk
  head/contrib/bmake/unit-tests/job-flags.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/job-flags.exp
  head/contrib/bmake/unit-tests/job-flags.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/job-flags.mk
  head/contrib/bmake/unit-tests/objdir-writable.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/objdir-writable.exp
  head/contrib/bmake/unit-tests/objdir-writable.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/objdir-writable.mk
  head/contrib/bmake/unit-tests/opt-touch-jobs.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/opt-touch-jobs.exp
  head/contrib/bmake/unit-tests/opt-touch-jobs.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/opt-touch-jobs.mk
  head/contrib/bmake/unit-tests/suff-self.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/suff-self.exp
  head/contrib/bmake/unit-tests/suff-self.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/suff-self.mk
  head/contrib/bmake/unit-tests/varparse-errors.exp
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/varparse-errors.exp
  head/contrib/bmake/unit-tests/varparse-errors.mk
     - copied unchanged from r367861, vendor/NetBSD/bmake/dist/unit-tests/varparse-errors.mk
Deleted:
  head/contrib/bmake/unit-tests/directives.exp
  head/contrib/bmake/unit-tests/directives.mk
  head/contrib/bmake/unit-tests/varshell.exp
  head/contrib/bmake/unit-tests/varshell.mk
Modified:
  head/contrib/bmake/ChangeLog
  head/contrib/bmake/FILES
  head/contrib/bmake/Makefile
  head/contrib/bmake/Makefile.config.in
  head/contrib/bmake/VERSION
  head/contrib/bmake/arch.c
  head/contrib/bmake/bmake.1
  head/contrib/bmake/bmake.cat1
  head/contrib/bmake/boot-strap
  head/contrib/bmake/buf.c
  head/contrib/bmake/buf.h
  head/contrib/bmake/compat.c
  head/contrib/bmake/cond.c
  head/contrib/bmake/configure
  head/contrib/bmake/configure.in
  head/contrib/bmake/dir.c
  head/contrib/bmake/dir.h
  head/contrib/bmake/filemon/filemon_dev.c
  head/contrib/bmake/filemon/filemon_ktrace.c
  head/contrib/bmake/for.c
  head/contrib/bmake/hash.c
  head/contrib/bmake/hash.h
  head/contrib/bmake/job.c
  head/contrib/bmake/job.h
  head/contrib/bmake/lst.c
  head/contrib/bmake/lst.h
  head/contrib/bmake/main.c
  head/contrib/bmake/make-bootstrap.sh.in
  head/contrib/bmake/make.1
  head/contrib/bmake/make.c
  head/contrib/bmake/make.h
  head/contrib/bmake/make_malloc.h
  head/contrib/bmake/meta.c
  head/contrib/bmake/metachar.h
  head/contrib/bmake/mk/ChangeLog
  head/contrib/bmake/mk/install-mk
  head/contrib/bmake/mk/meta.autodep.mk
  head/contrib/bmake/mk/meta2deps.sh
  head/contrib/bmake/nonints.h
  head/contrib/bmake/parse.c
  head/contrib/bmake/str.c
  head/contrib/bmake/suff.c
  head/contrib/bmake/targ.c
  head/contrib/bmake/unit-tests/Makefile
  head/contrib/bmake/unit-tests/archive-suffix.mk
  head/contrib/bmake/unit-tests/archive.mk
  head/contrib/bmake/unit-tests/cmd-interrupt.mk
  head/contrib/bmake/unit-tests/cmdline.mk
  head/contrib/bmake/unit-tests/comment.mk
  head/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp
  head/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk
  head/contrib/bmake/unit-tests/cond-cmp-numeric.exp
  head/contrib/bmake/unit-tests/cond-cmp-numeric.mk
  head/contrib/bmake/unit-tests/cond-cmp-string.exp
  head/contrib/bmake/unit-tests/cond-cmp-string.mk
  head/contrib/bmake/unit-tests/cond-cmp-unary.exp
  head/contrib/bmake/unit-tests/cond-cmp-unary.mk
  head/contrib/bmake/unit-tests/cond-func-commands.mk
  head/contrib/bmake/unit-tests/cond-func-defined.exp
  head/contrib/bmake/unit-tests/cond-func-defined.mk
  head/contrib/bmake/unit-tests/cond-func-empty.exp
  head/contrib/bmake/unit-tests/cond-func-empty.mk
  head/contrib/bmake/unit-tests/cond-func.exp
  head/contrib/bmake/unit-tests/cond-func.mk
  head/contrib/bmake/unit-tests/cond-late.mk
  head/contrib/bmake/unit-tests/cond-op-not.exp
  head/contrib/bmake/unit-tests/cond-op-not.mk
  head/contrib/bmake/unit-tests/cond-op-parentheses.exp
  head/contrib/bmake/unit-tests/cond-op-parentheses.mk
  head/contrib/bmake/unit-tests/cond-op.exp
  head/contrib/bmake/unit-tests/cond-op.mk
  head/contrib/bmake/unit-tests/cond-short.mk
  head/contrib/bmake/unit-tests/cond-token-number.exp
  head/contrib/bmake/unit-tests/cond-token-number.mk
  head/contrib/bmake/unit-tests/cond-token-plain.mk
  head/contrib/bmake/unit-tests/cond-token-string.exp
  head/contrib/bmake/unit-tests/cond-token-string.mk
  head/contrib/bmake/unit-tests/cond-token-var.exp
  head/contrib/bmake/unit-tests/cond-token-var.mk
  head/contrib/bmake/unit-tests/cond-undef-lint.exp
  head/contrib/bmake/unit-tests/cond-undef-lint.mk
  head/contrib/bmake/unit-tests/cond1.exp
  head/contrib/bmake/unit-tests/cond1.mk
  head/contrib/bmake/unit-tests/dep-double-colon.mk
  head/contrib/bmake/unit-tests/dep-exclam.mk
  head/contrib/bmake/unit-tests/depsrc-ignore.mk
  head/contrib/bmake/unit-tests/depsrc-make.mk
  head/contrib/bmake/unit-tests/depsrc-optional.exp
  head/contrib/bmake/unit-tests/depsrc-optional.mk
  head/contrib/bmake/unit-tests/depsrc-precious.mk
  head/contrib/bmake/unit-tests/depsrc-usebefore.mk
  head/contrib/bmake/unit-tests/depsrc.mk
  head/contrib/bmake/unit-tests/deptgt-begin.exp
  head/contrib/bmake/unit-tests/deptgt-begin.mk
  head/contrib/bmake/unit-tests/deptgt-error.mk
  head/contrib/bmake/unit-tests/deptgt-ignore.mk
  head/contrib/bmake/unit-tests/deptgt-interrupt.mk
  head/contrib/bmake/unit-tests/deptgt-main.mk
  head/contrib/bmake/unit-tests/deptgt-makeflags.exp
  head/contrib/bmake/unit-tests/deptgt-makeflags.mk
  head/contrib/bmake/unit-tests/deptgt-silent.exp
  head/contrib/bmake/unit-tests/deptgt-silent.mk
  head/contrib/bmake/unit-tests/deptgt.exp
  head/contrib/bmake/unit-tests/deptgt.mk
  head/contrib/bmake/unit-tests/dir.mk
  head/contrib/bmake/unit-tests/directive-elif.exp
  head/contrib/bmake/unit-tests/directive-elif.mk
  head/contrib/bmake/unit-tests/directive-else.exp
  head/contrib/bmake/unit-tests/directive-else.mk
  head/contrib/bmake/unit-tests/directive-endif.mk
  head/contrib/bmake/unit-tests/directive-export-env.mk
  head/contrib/bmake/unit-tests/directive-export-gmake.mk
  head/contrib/bmake/unit-tests/directive-export-literal.mk
  head/contrib/bmake/unit-tests/directive-export.exp
  head/contrib/bmake/unit-tests/directive-export.mk
  head/contrib/bmake/unit-tests/directive-for.exp
  head/contrib/bmake/unit-tests/directive-for.mk
  head/contrib/bmake/unit-tests/directive-if.exp
  head/contrib/bmake/unit-tests/directive-if.mk
  head/contrib/bmake/unit-tests/directive-ifdef.exp
  head/contrib/bmake/unit-tests/directive-ifdef.mk
  head/contrib/bmake/unit-tests/directive-ifmake.exp
  head/contrib/bmake/unit-tests/directive-ifmake.mk
  head/contrib/bmake/unit-tests/directive-include.exp
  head/contrib/bmake/unit-tests/directive-include.mk
  head/contrib/bmake/unit-tests/directive-info.exp
  head/contrib/bmake/unit-tests/directive-info.mk
  head/contrib/bmake/unit-tests/directive-sinclude.mk
  head/contrib/bmake/unit-tests/directive-undef.exp
  head/contrib/bmake/unit-tests/directive-undef.mk
  head/contrib/bmake/unit-tests/directive-unexport-env.mk
  head/contrib/bmake/unit-tests/directive-unexport.exp
  head/contrib/bmake/unit-tests/directive-unexport.mk
  head/contrib/bmake/unit-tests/directive-warning.exp
  head/contrib/bmake/unit-tests/directive-warning.mk
  head/contrib/bmake/unit-tests/directive.exp
  head/contrib/bmake/unit-tests/directive.mk
  head/contrib/bmake/unit-tests/dollar.exp
  head/contrib/bmake/unit-tests/dollar.mk
  head/contrib/bmake/unit-tests/envfirst.mk
  head/contrib/bmake/unit-tests/error.exp
  head/contrib/bmake/unit-tests/error.mk
  head/contrib/bmake/unit-tests/escape.mk
  head/contrib/bmake/unit-tests/forloop.exp
  head/contrib/bmake/unit-tests/forloop.mk
  head/contrib/bmake/unit-tests/forsubst.mk
  head/contrib/bmake/unit-tests/include-sub.mk
  head/contrib/bmake/unit-tests/moderrs.mk
  head/contrib/bmake/unit-tests/modmisc.mk
  head/contrib/bmake/unit-tests/modts.mk
  head/contrib/bmake/unit-tests/modword.mk
  head/contrib/bmake/unit-tests/opt-chdir.exp
  head/contrib/bmake/unit-tests/opt-chdir.mk
  head/contrib/bmake/unit-tests/opt-debug-jobs.exp
  head/contrib/bmake/unit-tests/opt-debug-jobs.mk
  head/contrib/bmake/unit-tests/opt-ignore.mk
  head/contrib/bmake/unit-tests/opt-keep-going.mk
  head/contrib/bmake/unit-tests/opt-no-action.mk
  head/contrib/bmake/unit-tests/opt-query.mk
  head/contrib/bmake/unit-tests/opt-touch.exp
  head/contrib/bmake/unit-tests/opt-touch.mk
  head/contrib/bmake/unit-tests/opt-var-expanded.mk
  head/contrib/bmake/unit-tests/opt-var-literal.mk
  head/contrib/bmake/unit-tests/opt-warnings-as-errors.exp
  head/contrib/bmake/unit-tests/opt-warnings-as-errors.mk
  head/contrib/bmake/unit-tests/opt.exp
  head/contrib/bmake/unit-tests/opt.mk
  head/contrib/bmake/unit-tests/order.mk
  head/contrib/bmake/unit-tests/recursive.exp
  head/contrib/bmake/unit-tests/recursive.mk
  head/contrib/bmake/unit-tests/sh-leading-at.exp
  head/contrib/bmake/unit-tests/sh-leading-at.mk
  head/contrib/bmake/unit-tests/sh-leading-hyphen.mk
  head/contrib/bmake/unit-tests/sh-leading-plus.mk
  head/contrib/bmake/unit-tests/sh-meta-chars.mk
  head/contrib/bmake/unit-tests/use-inference.mk
  head/contrib/bmake/unit-tests/var-class-local.exp
  head/contrib/bmake/unit-tests/var-class-local.mk
  head/contrib/bmake/unit-tests/var-op-assign.exp
  head/contrib/bmake/unit-tests/var-op-assign.mk
  head/contrib/bmake/unit-tests/var-op-expand.exp
  head/contrib/bmake/unit-tests/var-op-expand.mk
  head/contrib/bmake/unit-tests/var-op-shell.exp
  head/contrib/bmake/unit-tests/var-op-shell.mk
  head/contrib/bmake/unit-tests/var-op-sunsh.mk
  head/contrib/bmake/unit-tests/vardebug.exp
  head/contrib/bmake/unit-tests/varmisc.mk
  head/contrib/bmake/unit-tests/varmod-defined.exp
  head/contrib/bmake/unit-tests/varmod-defined.mk
  head/contrib/bmake/unit-tests/varmod-exclam-shell.mk
  head/contrib/bmake/unit-tests/varmod-ifelse.exp
  head/contrib/bmake/unit-tests/varmod-ifelse.mk
  head/contrib/bmake/unit-tests/varmod-loop.exp
  head/contrib/bmake/unit-tests/varmod-loop.mk
  head/contrib/bmake/unit-tests/varmod-match.mk
  head/contrib/bmake/unit-tests/varmod-order-shuffle.mk
  head/contrib/bmake/unit-tests/varmod-shell.exp
  head/contrib/bmake/unit-tests/varmod-shell.mk
  head/contrib/bmake/unit-tests/varmod-subst.exp
  head/contrib/bmake/unit-tests/varmod-subst.mk
  head/contrib/bmake/unit-tests/varmod-to-abs.exp
  head/contrib/bmake/unit-tests/varmod-to-abs.mk
  head/contrib/bmake/unit-tests/varmod-to-lower.mk
  head/contrib/bmake/unit-tests/varmod-to-separator.mk
  head/contrib/bmake/unit-tests/varmod-undefined.mk
  head/contrib/bmake/unit-tests/varmod.exp
  head/contrib/bmake/unit-tests/varmod.mk
  head/contrib/bmake/unit-tests/varname-dot-shell.exp
  head/contrib/bmake/unit-tests/varname-empty.exp
  head/contrib/bmake/unit-tests/varname-makefile.exp
  head/contrib/bmake/unit-tests/varname-makefile.mk
  head/contrib/bmake/unit-tests/varname-vpath.exp
  head/contrib/bmake/unit-tests/varname-vpath.mk
  head/contrib/bmake/unit-tests/varname.exp
  head/contrib/bmake/unit-tests/varname.mk
  head/contrib/bmake/unit-tests/varparse-undef-partial.mk
  head/contrib/bmake/util.c
  head/contrib/bmake/var.c
  head/usr.bin/bmake/Makefile
  head/usr.bin/bmake/Makefile.config
  head/usr.bin/bmake/config.h
  head/usr.bin/bmake/unit-tests/Makefile
Directory Properties:
  head/contrib/bmake/   (props changed)

Modified: head/contrib/bmake/ChangeLog
==============================================================================
--- head/contrib/bmake/ChangeLog	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/ChangeLog	Fri Nov 20 06:02:31 2020	(r367863)
@@ -1,3 +1,78 @@
+2020-11-17  Simon J Gerraty  <sjg at beast.crufty.net>
+
+	* VERSION (_MAKE_VERSION): 20201117
+	Merge with NetBSD make, pick up
+	o fix some unit-tests when dash is .SHELL
+	o rename Targ_NewGN to GNode_New
+	o make some GNode functions const
+	o main.c: call Targ_Init before Var_Init
+	cleanup PrintOnError, getTmpdir and ParseBoolean
+	o var.c: fix error message of failed :!cmd! modifier
+
+2020-11-14  Simon J Gerraty  <sjg at beast.crufty.net>
+
+	* VERSION (_MAKE_VERSION): 20201114
+	Merge with NetBSD make, pick up
+	o replace a few HashTable_CreateEntry with HashTable_Set
+	o clean up cached_stats
+	o rename DEFAULT to defaultNode
+	o remove redundant struct make_stat
+	o cond.c: in lint mode, check for ".else <cond>"
+	use bitset for IfState
+	replace large switch with if-else in Cond_EvalLine
+	o job.c: clean up JobExec, JobStart, JobDoOutput
+	use stderr for error message about failed touch
+	clean up Job_Touch
+	replace macro DBPRINTF with JobPrintln
+	rename JobState to JobStatus
+	main.c: switch cache for realpath from GNode to HashTable
+	clean up Fatal
+	clean up InitDefSysIncPath
+	use progname instead of hard-coded 'make' in warning
+	rename Main_SetVarObjdir to SetVarObjdir
+	make.1: document the -S option
+	make.c: fix debug output for GNode details
+	use symbolic names in debug output of GNodes
+
+2020-11-12  Simon J Gerraty  <sjg at beast.crufty.net>
+
+	* configure.in: fix --with-force-machine-arch
+
+	* VERSION (_MAKE_VERSION): 20201112
+	Merge with NetBSD make, pick up
+	o allow env var MAKE_OBJDIR_CHECK_WRITABLE=no to skip writable
+	checks in InitObjdir.  Explicit .OBJDIR target always allows
+	read-only directory.
+	o cond.c: clean up Cond_EvalLine
+
+2020-11-11  Simon J Gerraty  <sjg at beast.crufty.net>
+
+	* VERSION (_MAKE_VERSION): 20201111
+	Merge with NetBSD make, pick up
+	o more unit-tests
+	o style cleanup
+	remove redundant parentheses from sizeof operator
+	replace character literal 0 with '\0'.
+	replace pointer literal 0 with NULL.
+	remove redundant parentheses.
+	replace (expr & mask) == 0 with !(expr & mask).
+	use strict typing in conditions of the form !var
+	o rename Make_OODate to GNode_IsOODate
+	o rename Make_TimeStamp to GNode_UpdateYoungestChild
+	o rename Var_Set_with_flags to Var_SetWithFlags
+	o rename dieQuietly to shouldDieQuietly
+	o buf.c: make API of Buf_Init simpler
+	o compat.c: clean up Compat_Make, Compat_RunCommand,
+	CompatDeleteTarget and CompatInterrupt
+	o cond.c: in lint mode, only allow '&&' and '||', not '&' and '|'
+	clean up CondParser_Comparison
+	o main.c: rename getBoolean and s2Boolean
+	rename MAKEFILE_PREFERENCE for consistency
+	o parse.c: replace strstr in ParseMaybeSubMake with optimized code
+	o var.c: rename VARE_ASSIGN to VARE_KEEP_DOLLAR
+	replace emptyString with allocated empty string
+	error out on unclosed expressions after the colon
+
 2020-11-01  Simon J Gerraty  <sjg at beast.crufty.net>
 
 	* VERSION (_MAKE_VERSION): 20201101

Modified: head/contrib/bmake/FILES
==============================================================================
--- head/contrib/bmake/FILES	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/FILES	Fri Nov 20 06:02:31 2020	(r367863)
@@ -75,8 +75,14 @@ unit-tests/archive-suffix.exp
 unit-tests/archive-suffix.mk
 unit-tests/archive.exp
 unit-tests/archive.mk
+unit-tests/cmd-errors-lint.exp
+unit-tests/cmd-errors-lint.mk
+unit-tests/cmd-errors.exp
+unit-tests/cmd-errors.mk
 unit-tests/cmd-interrupt.exp
 unit-tests/cmd-interrupt.mk
+unit-tests/cmdline-undefined.exp
+unit-tests/cmdline-undefined.mk
 unit-tests/cmdline.exp
 unit-tests/cmdline.mk
 unit-tests/comment.exp
@@ -115,10 +121,14 @@ unit-tests/cond-func.exp
 unit-tests/cond-func.mk
 unit-tests/cond-late.exp
 unit-tests/cond-late.mk
+unit-tests/cond-op-and-lint.exp
+unit-tests/cond-op-and-lint.mk
 unit-tests/cond-op-and.exp
 unit-tests/cond-op-and.mk
 unit-tests/cond-op-not.exp
 unit-tests/cond-op-not.mk
+unit-tests/cond-op-or-lint.exp
+unit-tests/cond-op-or-lint.mk
 unit-tests/cond-op-or.exp
 unit-tests/cond-op-or.mk
 unit-tests/cond-op-parentheses.exp
@@ -287,6 +297,8 @@ unit-tests/directive-for.exp
 unit-tests/directive-for.mk
 unit-tests/directive-hyphen-include.exp
 unit-tests/directive-hyphen-include.mk
+unit-tests/directive-if-nested.exp
+unit-tests/directive-if-nested.mk
 unit-tests/directive-if.exp
 unit-tests/directive-if.mk
 unit-tests/directive-ifdef.exp
@@ -315,8 +327,6 @@ unit-tests/directive-warning.exp
 unit-tests/directive-warning.mk
 unit-tests/directive.exp
 unit-tests/directive.mk
-unit-tests/directives.exp
-unit-tests/directives.mk
 unit-tests/dollar.exp
 unit-tests/dollar.mk
 unit-tests/doterror.exp
@@ -341,6 +351,8 @@ unit-tests/forloop.exp
 unit-tests/forloop.mk
 unit-tests/forsubst.exp
 unit-tests/forsubst.mk
+unit-tests/gnode-submake.exp
+unit-tests/gnode-submake.mk
 unit-tests/hanoi-include.exp
 unit-tests/hanoi-include.mk
 unit-tests/impsrc.exp
@@ -349,6 +361,8 @@ unit-tests/include-main.exp
 unit-tests/include-main.mk
 unit-tests/include-sub.mk
 unit-tests/include-subsub.mk
+unit-tests/job-flags.exp
+unit-tests/job-flags.mk
 unit-tests/job-output-long-lines.exp
 unit-tests/job-output-long-lines.mk
 unit-tests/lint.exp
@@ -365,6 +379,8 @@ unit-tests/modts.exp
 unit-tests/modts.mk
 unit-tests/modword.exp
 unit-tests/modword.mk
+unit-tests/objdir-writable.exp
+unit-tests/objdir-writable.mk
 unit-tests/opt-backwards.exp
 unit-tests/opt-backwards.mk
 unit-tests/opt-chdir.exp
@@ -447,6 +463,8 @@ unit-tests/opt-raw.exp
 unit-tests/opt-raw.mk
 unit-tests/opt-silent.exp
 unit-tests/opt-silent.mk
+unit-tests/opt-touch-jobs.exp
+unit-tests/opt-touch-jobs.mk
 unit-tests/opt-touch.exp
 unit-tests/opt-touch.mk
 unit-tests/opt-tracefile.exp
@@ -517,6 +535,8 @@ unit-tests/suff-main.exp
 unit-tests/suff-main.mk
 unit-tests/suff-rebuild.exp
 unit-tests/suff-rebuild.mk
+unit-tests/suff-self.exp
+unit-tests/suff-self.mk
 unit-tests/suff-transform-endless.exp
 unit-tests/suff-transform-endless.mk
 unit-tests/suff-transform-expand.exp
@@ -737,14 +757,14 @@ unit-tests/varname.exp
 unit-tests/varname.mk
 unit-tests/varparse-dynamic.exp
 unit-tests/varparse-dynamic.mk
+unit-tests/varparse-errors.exp
+unit-tests/varparse-errors.mk
 unit-tests/varparse-mod.exp
 unit-tests/varparse-mod.mk
 unit-tests/varparse-undef-partial.exp
 unit-tests/varparse-undef-partial.mk
 unit-tests/varquote.exp
 unit-tests/varquote.mk
-unit-tests/varshell.exp
-unit-tests/varshell.mk
 util.c
 var.c
 wait.h

Modified: head/contrib/bmake/Makefile
==============================================================================
--- head/contrib/bmake/Makefile	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/Makefile	Fri Nov 20 06:02:31 2020	(r367863)
@@ -1,4 +1,4 @@
-#	$Id: Makefile,v 1.113 2020/10/26 17:55:09 sjg Exp $
+#	$Id: Makefile,v 1.114 2020/11/13 21:47:25 sjg Exp $
 
 PROG=	bmake
 
@@ -48,6 +48,12 @@ 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

Modified: head/contrib/bmake/Makefile.config.in
==============================================================================
--- head/contrib/bmake/Makefile.config.in	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/Makefile.config.in	Fri Nov 20 06:02:31 2020	(r367863)
@@ -5,8 +5,8 @@ _MAKE_VERSION?=@_MAKE_VERSION@
 prefix?= @prefix@
 srcdir= @srcdir@
 CC?= @CC@
-MACHINE?= @machine@
-MACHINE_ARCH?= @machine_arch@
+ at force_machine@MACHINE?= @machine@
+ at force_machine_arch@MACHINE_ARCH?= @machine_arch@
 DEFAULT_SYS_PATH?= @default_sys_path@
 
 CPPFLAGS+= @CPPFLAGS@

Modified: head/contrib/bmake/VERSION
==============================================================================
--- head/contrib/bmake/VERSION	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/VERSION	Fri Nov 20 06:02:31 2020	(r367863)
@@ -1,2 +1,2 @@
 # keep this compatible with sh and make
-_MAKE_VERSION=20201101
+_MAKE_VERSION=20201117

Modified: head/contrib/bmake/arch.c
==============================================================================
--- head/contrib/bmake/arch.c	Fri Nov 20 05:46:27 2020	(r367862)
+++ head/contrib/bmake/arch.c	Fri Nov 20 06:02:31 2020	(r367863)
@@ -1,4 +1,4 @@
-/*	$NetBSD: arch.c,v 1.151 2020/10/31 18:41:07 rillig Exp $	*/
+/*	$NetBSD: arch.c,v 1.177 2020/11/14 21:29:44 rillig Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -68,38 +68,38 @@
  * SUCH DAMAGE.
  */
 
-/*-
- * arch.c --
- *	Functions to manipulate libraries, archives and their members.
+/* Manipulate libraries, archives and their members.
  *
- *	Once again, cacheing/hashing comes into play in the manipulation
- * of archives. The first time an archive is referenced, all of its members'
- * headers are read and hashed and the archive closed again. All hashed
- * archives are kept on a list which is searched each time an archive member
- * is referenced.
+ * The first time an archive is referenced, all of its members' headers are
+ * read and cached and the archive closed again.  All cached archives are kept
+ * on a list which is searched each time an archive member is referenced.
  *
  * The interface to this module is:
+ *
+ *	Arch_Init	Initialize this module.
+ *
+ *	Arch_End	Clean up this module.
+ *
  *	Arch_ParseArchive
- *			Given an archive specification, return a list
- *			of GNode's, one for each member in the spec.
- *			FALSE is returned if the specification is
- *			invalid for some reason.
+ *			Parse an archive specification such as
+ *			"archive.a(member1 member2)".
  *
  *	Arch_Touch	Alter the modification time of the archive
  *			member described by the given node to be
- *			the current time.
+ *			the time when make was started.
  *
  *	Arch_TouchLib	Update the modification time of the library
  *			described by the given node. This is special
  *			because it also updates the modification time
  *			of the library's table of contents.
  *
- *	Arch_MTime	Find the modification time of a member of
- *			an archive *in the archive*. The time is also
- *			placed in the member's GNode. Returns the
- *			modification time.
+ *	Arch_UpdateMTime
+ *			Find the modification time of a member of
+ *			an archive *in the archive* and place it in the
+ *			member's GNode.
  *
- *	Arch_MemTime	Find the modification time of a member of
+ *	Arch_UpdateMemberMTime
+ *			Find the modification time of a member of
  *			an archive. Called when the member doesn't
  *			already exist. Looks in the archive for the
  *			modification time. Returns the modification
@@ -109,12 +109,7 @@
  *			library name in the GNode should be in
  *			-l<name> format.
  *
- *	Arch_LibOODate	Special function to decide if a library node
- *			is out-of-date.
- *
- *	Arch_Init	Initialize this module.
- *
- *	Arch_End	Clean up this module.
+ *	Arch_LibOODate	Decide if a library node is out-of-date.
  */
 
 #ifdef HAVE_CONFIG_H
@@ -151,17 +146,8 @@ struct ar_hdr {
 #include "dir.h"
 
 /*	"@(#)arch.c	8.2 (Berkeley) 1/2/94"	*/
-MAKE_RCSID("$NetBSD: arch.c,v 1.151 2020/10/31 18:41:07 rillig Exp $");
+MAKE_RCSID("$NetBSD: arch.c,v 1.177 2020/11/14 21:29:44 rillig Exp $");
 
-#ifdef TARGET_MACHINE
-#undef MAKE_MACHINE
-#define MAKE_MACHINE TARGET_MACHINE
-#endif
-#ifdef TARGET_MACHINE_ARCH
-#undef MAKE_MACHINE_ARCH
-#define MAKE_MACHINE_ARCH TARGET_MACHINE_ARCH
-#endif
-
 typedef struct List ArchList;
 typedef struct ListNode ArchListNode;
 
@@ -230,39 +216,37 @@ ArchFree(void *ap)
 #endif
 
 
-/*-
- *-----------------------------------------------------------------------
- * Arch_ParseArchive --
- *	Parse the archive specification in the given line and find/create
- *	the nodes for the specified archive members, placing their nodes
- *	on the given list.
+/*
+ * Parse an archive specification such as "archive.a(member1 member2.${EXT})",
+ * adding nodes for the expanded members to nodeLst.  Nodes are created as
+ * necessary.
  *
  * Input:
- *	linePtr		Pointer to start of specification
- *	nodeLst		Lst on which to place the nodes
- *	ctxt		Context in which to expand variables
+ *	pp		The start of the specification.
+ *	nodeLst		The list on which to place the nodes.
+ *	ctxt		The context in which to expand variables.
  *
- * Results:
- *	TRUE if it was a valid specification. The linePtr is updated
- *	to point to the first non-space after the archive spec. The
- *	nodes for the members are placed on the given list.
- *-----------------------------------------------------------------------
+ * Output:
+ *	return		TRUE if it was a valid specification.
+ *	*pp		Points to the first non-space after the archive spec.
+ *	*nodeLst	Nodes for the members have been added.
  */
 Boolean
-Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, GNode *ctxt)
+Arch_ParseArchive(char **pp, GNodeList *nodeLst, GNode *ctxt)
 {
     char *cp;			/* Pointer into line */
     GNode *gn;			/* New node */
     char *libName;		/* Library-part of specification */
+    char *libName_freeIt = NULL;
     char *memName;		/* Member-part of specification */
     char saveChar;		/* Ending delimiter of member-name */
-    Boolean subLibName;		/* TRUE if libName should have/had
-				 * variable substitution performed on it */
+    Boolean expandLibName;	/* Whether the parsed libName contains
+				 * variable expressions that need to be
+				 * expanded */
 
-    libName = *linePtr;
+    libName = *pp;
+    expandLibName = FALSE;
 
-    subLibName = FALSE;
-
     for (cp = libName; *cp != '(' && *cp != '\0';) {
 	if (*cp == '$') {
 	    /*
@@ -274,7 +258,8 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	    const char *result;
 	    Boolean isError;
 
-	    (void)Var_Parse(&nested_p, ctxt, VARE_UNDEFERR|VARE_WANTRES,
+	    /* XXX: is expanded twice: once here and once below */
+	    (void)Var_Parse(&nested_p, ctxt, VARE_WANTRES | VARE_UNDEFERR,
 			    &result, &result_freeIt);
 	    /* TODO: handle errors */
 	    isError = result == var_Error;
@@ -282,16 +267,17 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	    if (isError)
 		return FALSE;
 
-	    subLibName = TRUE;
+	    expandLibName = TRUE;
 	    cp += nested_p - cp;
 	} else
 	    cp++;
     }
 
     *cp++ = '\0';
-    if (subLibName) {
-	(void)Var_Subst(libName, ctxt, VARE_UNDEFERR|VARE_WANTRES, &libName);
+    if (expandLibName) {
+	(void)Var_Subst(libName, ctxt, VARE_WANTRES | VARE_UNDEFERR, &libName);
 	/* TODO: handle errors */
+	libName_freeIt = libName;
     }
 
 
@@ -317,7 +303,7 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 		Boolean isError;
 		const char *nested_p = cp;
 
-		(void)Var_Parse(&nested_p, ctxt, VARE_UNDEFERR|VARE_WANTRES,
+		(void)Var_Parse(&nested_p, ctxt, VARE_WANTRES | VARE_UNDEFERR,
 				&result, &freeIt);
 		/* TODO: handle errors */
 		isError = result == var_Error;
@@ -339,7 +325,7 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	 * so it's better to return failure than allow such things to happen
 	 */
 	if (*cp == '\0') {
-	    printf("No closing parenthesis in archive specification\n");
+	    Parse_Error(PARSE_FATAL, "No closing parenthesis in archive specification");
 	    return FALSE;
 	}
 
@@ -370,7 +356,7 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	    char *sacrifice;
 	    char *oldMemName = memName;
 
-	    (void)Var_Subst(memName, ctxt, VARE_UNDEFERR|VARE_WANTRES,
+	    (void)Var_Subst(memName, ctxt, VARE_WANTRES | VARE_UNDEFERR,
 			    &memName);
 	    /* TODO: handle errors */
 
@@ -381,7 +367,8 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	     */
 	    buf = sacrifice = str_concat4(libName, "(", memName, ")");
 
-	    if (strchr(memName, '$') && strcmp(memName, oldMemName) == 0) {
+	    if (strchr(memName, '$') != NULL &&
+		strcmp(memName, oldMemName) == 0) {
 		/*
 		 * Must contain dynamic sources, so we can't deal with it now.
 		 * Just create an ARCHV node for the thing and let
@@ -437,17 +424,12 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
 	*cp = saveChar;
     }
 
-    /*
-     * If substituted libName, free it now, since we need it no longer.
-     */
-    if (subLibName) {
-	free(libName);
-    }
+    free(libName_freeIt);
 
     cp++;			/* skip the ')' */
-    /* We promised that linePtr would be set up at the next non-space. */
+    /* We promised that pp would be set up at the next non-space. */
     pp_skip_whitespace(&cp);
-    *linePtr = cp;
+    *pp = cp;
     return TRUE;
 }
 
@@ -457,15 +439,17 @@ Arch_ParseArchive(char **linePtr, GNodeList *nodeLst, 
  * Input:
  *	archive		Path to the archive
  *	member		Name of member; only its basename is used.
- *	hash		TRUE if archive should be hashed if not already so.
+ *	addToCache	TRUE if archive should be cached if not already so.
  *
  * Results:
- *	The ar_hdr for the member.
+ *	The ar_hdr for the member, or NULL.
+ *
+ * See ArchFindMember for an almost identical copy of this code.
  */
 static struct ar_hdr *
-ArchStatMember(const char *archive, const char *member, Boolean hash)
+ArchStatMember(const char *archive, const char *member, Boolean addToCache)
 {
-#define AR_MAX_NAME_LEN (sizeof(arh.AR_NAME) - 1)
+#define AR_MAX_NAME_LEN (sizeof arh.AR_NAME - 1)
     FILE *arch;			/* Stream to archive */
     size_t size;		/* Size of archive member */
     char magic[SARMAG];
@@ -484,8 +468,8 @@ ArchStatMember(const char *archive, const char *member
 	member = lastSlash + 1;
 
     for (ln = archives->first; ln != NULL; ln = ln->next) {
-	const Arch *archPtr = ln->datum;
-	if (strcmp(archPtr->name, archive) == 0)
+	const Arch *a = ln->datum;
+	if (strcmp(a->name, archive) == 0)
 	    break;
     }
 
@@ -505,17 +489,17 @@ ArchStatMember(const char *archive, const char *member
 	    if (len > AR_MAX_NAME_LEN) {
 		len = AR_MAX_NAME_LEN;
 		snprintf(copy, sizeof copy, "%s", member);
+		hdr = HashTable_FindValue(&ar->members, copy);
 	    }
-	    hdr = HashTable_FindValue(&ar->members, copy);
 	    return hdr;
 	}
     }
 
-    if (!hash) {
+    if (!addToCache) {
 	/*
-	 * Caller doesn't want the thing hashed, just use ArchFindMember
+	 * Caller doesn't want the thing cached, just use ArchFindMember
 	 * to read the header for the member out and close down the stream
-	 * again. Since the archive is not to be hashed, we assume there's
+	 * again. Since the archive is not to be cached, we assume there's
 	 * no need to allocate extra room for the header we're returning,
 	 * so just declare it static.
 	 */
@@ -541,98 +525,92 @@ ArchStatMember(const char *archive, const char *member
      * We use the ARMAG string to make sure this is an archive we
      * can handle...
      */
-    if ((fread(magic, SARMAG, 1, arch) != 1) ||
-	(strncmp(magic, ARMAG, SARMAG) != 0)) {
-	fclose(arch);
+    if (fread(magic, SARMAG, 1, arch) != 1 ||
+	strncmp(magic, ARMAG, SARMAG) != 0) {
+	(void)fclose(arch);
 	return NULL;
     }
 
-    ar = bmake_malloc(sizeof(Arch));
+    ar = bmake_malloc(sizeof *ar);
     ar->name = bmake_strdup(archive);
     ar->fnametab = NULL;
     ar->fnamesize = 0;
     HashTable_Init(&ar->members);
     memName[AR_MAX_NAME_LEN] = '\0';
 
-    while (fread((char *)&arh, sizeof(struct ar_hdr), 1, arch) == 1) {
-	if (strncmp(arh.AR_FMAG, ARFMAG, sizeof(arh.AR_FMAG)) != 0) {
-	    /*
-	     * The header is bogus, so the archive is bad
-	     * and there's no way we can recover...
-	     */
+    while (fread(&arh, sizeof arh, 1, arch) == 1) {
+	char *nameend;
+
+	/* If the header is bogus, there's no way we can recover. */
+	if (strncmp(arh.AR_FMAG, ARFMAG, sizeof arh.AR_FMAG) != 0)
 	    goto badarch;
-	} else {
-	    char *nameend;
 
-	    /*
-	     * We need to advance the stream's pointer to the start of the
-	     * next header. Files are padded with newlines to an even-byte
-	     * boundary, so we need to extract the size of the file from the
-	     * 'size' field of the header and round it up during the seek.
-	     */
-	    arh.AR_SIZE[sizeof(arh.AR_SIZE) - 1] = '\0';
-	    size = (size_t)strtol(arh.ar_size, NULL, 10);
+	/*
+	 * We need to advance the stream's pointer to the start of the
+	 * next header. Files are padded with newlines to an even-byte
+	 * boundary, so we need to extract the size of the file from the
+	 * 'size' field of the header and round it up during the seek.
+	 */
+	arh.AR_SIZE[sizeof arh.AR_SIZE - 1] = '\0';
+	size = (size_t)strtol(arh.AR_SIZE, NULL, 10);
 
-	    memcpy(memName, arh.AR_NAME, sizeof(arh.AR_NAME));
-	    nameend = memName + AR_MAX_NAME_LEN;
-	    while (*nameend == ' ') {
-		nameend--;
-	    }
-	    nameend[1] = '\0';
+	memcpy(memName, arh.AR_NAME, sizeof arh.AR_NAME);
+	nameend = memName + AR_MAX_NAME_LEN;
+	while (nameend > memName && *nameend == ' ')
+	    nameend--;
+	nameend[1] = '\0';
 
 #ifdef SVR4ARCHIVES
+	/*
+	 * svr4 names are slash terminated. Also svr4 extended AR format.
+	 */
+	if (memName[0] == '/') {
 	    /*
-	     * svr4 names are slash terminated. Also svr4 extended AR format.
+	     * svr4 magic mode; handle it
 	     */
-	    if (memName[0] == '/') {
-		/*
-		 * svr4 magic mode; handle it
-		 */
-		switch (ArchSVR4Entry(ar, memName, size, arch)) {
-		case -1:	/* Invalid data */
-		    goto badarch;
-		case 0:		/* List of files entry */
-		    continue;
-		default:	/* Got the entry */
-		    break;
-		}
-	    } else {
-		if (nameend[0] == '/')
-		    nameend[0] = '\0';
+	    switch (ArchSVR4Entry(ar, memName, size, arch)) {
+	    case -1:	/* Invalid data */
+		goto badarch;
+	    case 0:		/* List of files entry */
+		continue;
+	    default:	/* Got the entry */
+		break;
 	    }
+	} else {
+	    if (nameend[0] == '/')
+		nameend[0] = '\0';
+	}
 #endif
 
 #ifdef AR_EFMT1
-	    /*
-	     * BSD 4.4 extended AR format: #1/<namelen>, with name as the
-	     * first <namelen> bytes of the file
-	     */
-	    if (strncmp(memName, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
-		ch_isdigit(memName[sizeof(AR_EFMT1) - 1])) {
+	/*
+	 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
+	 * first <namelen> bytes of the file
+	 */
+	if (strncmp(memName, AR_EFMT1, sizeof AR_EFMT1 - 1) == 0 &&
+	    ch_isdigit(memName[sizeof AR_EFMT1 - 1])) {
 
-		int elen = atoi(&memName[sizeof(AR_EFMT1) - 1]);
+	    int elen = atoi(memName + sizeof AR_EFMT1 - 1);
 
-		if ((unsigned int)elen > MAXPATHLEN)
-		    goto badarch;
-		if (fread(memName, (size_t)elen, 1, arch) != 1)
-		    goto badarch;
-		memName[elen] = '\0';
-		if (fseek(arch, -elen, SEEK_CUR) != 0)
-		    goto badarch;
-		if (DEBUG(ARCH) || DEBUG(MAKE)) {
-		    debug_printf("ArchStat: Extended format entry for %s\n",
-				 memName);
-		}
-	    }
+	    if ((unsigned int)elen > MAXPATHLEN)
+		goto badarch;
+	    if (fread(memName, (size_t)elen, 1, arch) != 1)
+		goto badarch;
+	    memName[elen] = '\0';
+	    if (fseek(arch, -elen, SEEK_CUR) != 0)
+		goto badarch;
+	    if (DEBUG(ARCH) || DEBUG(MAKE))
+		debug_printf("ArchStatMember: Extended format entry for %s\n",
+			     memName);
+	}
 #endif
 
-	    {
-		HashEntry *he;
-		he = HashTable_CreateEntry(&ar->members, memName, NULL);
-		HashEntry_Set(he, bmake_malloc(sizeof(struct ar_hdr)));
-		memcpy(HashEntry_Get(he), &arh, sizeof(struct ar_hdr));
-	    }
+	{
+	    struct ar_hdr *cached_hdr = bmake_malloc(sizeof *cached_hdr);
+	    memcpy(cached_hdr, &arh, sizeof arh);
+	    HashTable_Set(&ar->members, memName, cached_hdr);
 	}
+
 	if (fseek(arch, ((long)size + 1) & ~1, SEEK_CUR) != 0)
 	    goto badarch;
     }
@@ -643,7 +621,7 @@ ArchStatMember(const char *archive, const char *member
 
     /*
      * Now that the archive has been read and cached, we can look into
-     * the hash table to find the desired member's header.
+     * the addToCache table to find the desired member's header.
      */
     return HashTable_FindValue(&ar->members, member);
 
@@ -674,15 +652,15 @@ badarch:
  *-----------------------------------------------------------------------
  */
 static int
-ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE *arch)
+ArchSVR4Entry(Arch *ar, char *inout_name, size_t size, FILE *arch)
 {
 #define ARLONGNAMES1 "//"
 #define ARLONGNAMES2 "/ARFILENAMES"
     size_t entry;
     char *ptr, *eptr;
 
-    if (strncmp(name, ARLONGNAMES1, sizeof(ARLONGNAMES1) - 1) == 0 ||
-	strncmp(name, ARLONGNAMES2, sizeof(ARLONGNAMES2) - 1) == 0) {
+    if (strncmp(inout_name, ARLONGNAMES1, sizeof ARLONGNAMES1 - 1) == 0 ||
+	strncmp(inout_name, ARLONGNAMES2, sizeof ARLONGNAMES2 - 1) == 0) {
 
 	if (ar->fnametab != NULL) {
 	    DEBUG0(ARCH, "Attempted to redefine an SVR4 name table\n");
@@ -711,51 +689,74 @@ ArchSVR4Entry(Arch *ar, char *name, size_t size, FILE 
 	return 0;
     }
 
-    if (name[1] == ' ' || name[1] == '\0')
+    if (inout_name[1] == ' ' || inout_name[1] == '\0')
 	return 2;
 
-    entry = (size_t)strtol(&name[1], &eptr, 0);
-    if ((*eptr != ' ' && *eptr != '\0') || eptr == &name[1]) {
-	DEBUG1(ARCH, "Could not parse SVR4 name %s\n", name);
+    entry = (size_t)strtol(&inout_name[1], &eptr, 0);
+    if ((*eptr != ' ' && *eptr != '\0') || eptr == &inout_name[1]) {
+	DEBUG1(ARCH, "Could not parse SVR4 name %s\n", inout_name);
 	return 2;
     }
     if (entry >= ar->fnamesize) {
 	DEBUG2(ARCH, "SVR4 entry offset %s is greater than %lu\n",
-	       name, (unsigned long)ar->fnamesize);
+	       inout_name, (unsigned long)ar->fnamesize);
 	return 2;
     }
 
-    DEBUG2(ARCH, "Replaced %s with %s\n", name, &ar->fnametab[entry]);
+    DEBUG2(ARCH, "Replaced %s with %s\n", inout_name, &ar->fnametab[entry]);
 
-    snprintf(name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]);
+    snprintf(inout_name, MAXPATHLEN + 1, "%s", &ar->fnametab[entry]);
     return 1;
 }
 #endif
 
 
-/*-
- *-----------------------------------------------------------------------
- * ArchFindMember --
- *	Locate a member of an archive, given the path of the archive and
- *	the path of the desired member. If the archive is to be modified,
- *	the mode should be "r+", if not, it should be "r".
- *	The passed struct ar_hdr structure is filled in.
+static Boolean
+ArchiveMember_HasName(const struct ar_hdr *hdr,
+		      const char *name, size_t namelen)
+{
+    const size_t ar_name_len = sizeof hdr->AR_NAME;
+    const char *ar_name = hdr->AR_NAME;
+
+    if (strncmp(ar_name, name, namelen) != 0)
+	return FALSE;
+
+    if (namelen >= ar_name_len)
+	return namelen == ar_name_len;
+
+    /* hdr->AR_NAME is space-padded to the right. */
+    if (ar_name[namelen] == ' ')
+	return TRUE;
+
+    /* In archives created by GNU binutils 2.27, the member names end with
+     * a slash. */
+    if (ar_name[namelen] == '/' &&
+	(namelen == ar_name_len || ar_name[namelen + 1] == ' '))
+	return TRUE;
+
+    return FALSE;
+}
+
+/* Locate a member of an archive, given the path of the archive and the path
+ * of the desired member.
  *
  * Input:
  *	archive		Path to the archive
  *	member		Name of member. If it is a path, only the last
  *			component is used.
- *	arhPtr		Pointer to header structure to be filled in
- *	mode		The mode for opening the stream
+ *	out_arh		Archive header to be filled in
+ *	mode		"r" for read-only access, "r+" for read-write access
  *
- * Results:
- *	An FILE *, opened for reading and writing, positioned at the
- *	start of the member's struct ar_hdr, or NULL if the member was
- *	nonexistent. The current struct ar_hdr for member.
- *-----------------------------------------------------------------------
+ * Output:
+ *	return		The archive file, positioned at the start of the
+ *			member's struct ar_hdr, or NULL if the member doesn't
+ *			exist.
+ *	*out_arh	The current struct ar_hdr for member.
+ *
+ * See ArchStatMember for an almost identical copy of this code.
  */
 static FILE *
-ArchFindMember(const char *archive, const char *member, struct ar_hdr *arhPtr,
+ArchFindMember(const char *archive, const char *member, struct ar_hdr *out_arh,
 	       const char *mode)
 {
     FILE *arch;			/* Stream to archive */
@@ -772,8 +773,8 @@ ArchFindMember(const char *archive, const char *member
      * We use the ARMAG string to make sure this is an archive we
      * can handle...
      */
-    if ((fread(magic, SARMAG, 1, arch) != 1) ||
-	(strncmp(magic, ARMAG, SARMAG) != 0)) {
+    if (fread(magic, SARMAG, 1, arch) != 1 ||
+	strncmp(magic, ARMAG, SARMAG) != 0) {
 	fclose(arch);
 	return NULL;
     }
@@ -787,13 +788,13 @@ ArchFindMember(const char *archive, const char *member
 	member = lastSlash + 1;
 
     len = tlen = strlen(member);
-    if (len > sizeof(arhPtr->AR_NAME)) {
-	tlen = sizeof(arhPtr->AR_NAME);
+    if (len > sizeof out_arh->AR_NAME) {
+	tlen = sizeof out_arh->AR_NAME;
     }
 
-    while (fread((char *)arhPtr, sizeof(struct ar_hdr), 1, arch) == 1) {
+    while (fread(out_arh, sizeof *out_arh, 1, arch) == 1) {
 
-	if (strncmp(arhPtr->AR_FMAG, ARFMAG, sizeof(arhPtr->AR_FMAG)) != 0) {
+	if (strncmp(out_arh->AR_FMAG, ARFMAG, sizeof out_arh->AR_FMAG) != 0) {
 	    /*
 	     * The header is bogus, so the archive is bad
 	     * and there's no way we can recover...
@@ -802,25 +803,21 @@ ArchFindMember(const char *archive, const char *member
 	    return NULL;
 	}
 
-	if (strncmp(member, arhPtr->AR_NAME, tlen) == 0) {
-	    /*
-	     * If the member's name doesn't take up the entire 'name' field,
-	     * we have to be careful of matching prefixes. Names are space-
-	     * padded to the right, so if the character in 'name' at the end
-	     * of the matched string is anything but a space, this isn't the
-	     * member we sought.
-	     */
-	    if (tlen != sizeof arhPtr->AR_NAME && arhPtr->AR_NAME[tlen] != ' ')
-		goto skip;
+	DEBUG5(ARCH, "Reading archive %s member %.*s mtime %.*s\n",
+	       archive,
+	       (int)sizeof out_arh->AR_NAME, out_arh->AR_NAME,
+	       (int)sizeof out_arh->ar_date, out_arh->ar_date);
 
+	if (ArchiveMember_HasName(out_arh, member, len)) {
 	    /*
-	     * To make life easier, we reposition the file at the start
+	     * To make life easier for callers that want to update the
+	     * archive, we reposition the file at the start
 	     * of the header we just read before we return the stream.
 	     * In a more general situation, it might be better to leave
 	     * the file at the actual member, rather than its header, but
-	     * not here...
+	     * not here.
 	     */
-	    if (fseek(arch, -(long)sizeof(struct ar_hdr), SEEK_CUR) != 0) {
+	    if (fseek(arch, -(long)sizeof *out_arh, SEEK_CUR) != 0) {
 		fclose(arch);
 		return NULL;
 	    }
@@ -832,10 +829,10 @@ ArchFindMember(const char *archive, const char *member
 	 * BSD 4.4 extended AR format: #1/<namelen>, with name as the
 	 * first <namelen> bytes of the file
 	 */
-	if (strncmp(arhPtr->AR_NAME, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0 &&
-	    ch_isdigit(arhPtr->AR_NAME[sizeof(AR_EFMT1) - 1]))
+	if (strncmp(out_arh->AR_NAME, AR_EFMT1, sizeof AR_EFMT1 - 1) == 0 &&
+	    ch_isdigit(out_arh->AR_NAME[sizeof AR_EFMT1 - 1]))
 	{
-	    int elen = atoi(&arhPtr->AR_NAME[sizeof(AR_EFMT1) - 1]);
+	    int elen = atoi(&out_arh->AR_NAME[sizeof AR_EFMT1 - 1]);
 	    char ename[MAXPATHLEN + 1];
 
 	    if ((unsigned int)elen > MAXPATHLEN) {
@@ -847,9 +844,9 @@ ArchFindMember(const char *archive, const char *member
 		return NULL;
 	    }
 	    ename[elen] = '\0';
-	    if (DEBUG(ARCH) || DEBUG(MAKE)) {
-		debug_printf("ArchFind: Extended format entry for %s\n", ename);
-	    }
+	    if (DEBUG(ARCH) || DEBUG(MAKE))
+		debug_printf("ArchFindMember: Extended format entry for %s\n",
+			     ename);
 	    if (strncmp(ename, member, len) == 0) {
 		/* Found as extended name */
 		if (fseek(arch, -(long)sizeof(struct ar_hdr) - elen,
@@ -866,7 +863,6 @@ ArchFindMember(const char *archive, const char *member
 	}
 #endif
 
-skip:
 	/*
 	 * This isn't the member we're after, so we need to advance the
 	 * stream's pointer to the start of the next header. Files are
@@ -874,113 +870,89 @@ skip:
 	 * extract the size of the file from the 'size' field of the
 	 * header and round it up during the seek.
 	 */
-	arhPtr->ar_size[sizeof(arhPtr->ar_size) - 1] = '\0';
-	size = (int)strtol(arhPtr->ar_size, NULL, 10);
+	out_arh->AR_SIZE[sizeof out_arh->AR_SIZE - 1] = '\0';
+	size = (int)strtol(out_arh->AR_SIZE, NULL, 10);
 	if (fseek(arch, (size + 1) & ~1, SEEK_CUR) != 0) {
 	    fclose(arch);
 	    return NULL;
 	}
     }
 
-    /*
-     * We've looked everywhere, but the member is not to be found. Close the
-     * archive and return NULL -- an error.
-     */
     fclose(arch);
     return NULL;
 }
 
-/*-
- *-----------------------------------------------------------------------
- * Arch_Touch --
- *	Touch a member of an archive.
- *	The modification time of the entire archive is also changed.
- *	For a library, this could necessitate the re-ranlib'ing of the
- *	whole thing.
+/* Touch a member of an archive, on disk.
+ * The GNode's modification time is left as-is.
  *
+ * The st_mtime of the entire archive is also changed.
+ * For a library, it may be required to run ranlib after this.
+ *
  * Input:
  *	gn		Node of member to touch
  *
  * Results:
  *	The 'time' field of the member's header is updated.
- *-----------------------------------------------------------------------
  */
 void
 Arch_Touch(GNode *gn)
 {
-    FILE *arch;		/* Stream open to archive, positioned properly */
-    struct ar_hdr arh;	/* Current header describing member */
+    FILE *f;
+    struct ar_hdr arh;
 
-    arch = ArchFindMember(GNode_VarArchive(gn), GNode_VarMember(gn),
-			  &arh, "r+");
+    f = ArchFindMember(GNode_VarArchive(gn), GNode_VarMember(gn), &arh, "r+");
+    if (f == NULL)
+	return;
 
-    snprintf(arh.AR_DATE, sizeof(arh.AR_DATE), "%-12ld", (long)now);
-
-    if (arch != NULL) {
-	(void)fwrite((char *)&arh, sizeof(struct ar_hdr), 1, arch);
-	fclose(arch);
-    }
+    snprintf(arh.ar_date, sizeof arh.ar_date, "%-ld", (unsigned long)now);
+    (void)fwrite(&arh, sizeof arh, 1, f);
+    fclose(f);			/* TODO: handle errors */
 }
 
 /* Given a node which represents a library, touch the thing, making sure that
- * the table of contents also is touched.
+ * the table of contents is also touched.
  *
  * Both the modification time of the library and of the RANLIBMAG member are
- * set to 'now'.
- *
- * Input:
- *	gn		The node of the library to touch
- */
+ * set to 'now'. */
 void
-Arch_TouchLib(GNode *gn)
+Arch_TouchLib(GNode *gn MAKE_ATTR_UNUSED)
 {
 #ifdef RANLIBMAG

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list