aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2025-01-30 23:38:13 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2025-01-30 23:38:13 +0000
commit5ad769f660f3d00853bc739f82d9bc62f6a682cb (patch)
treea94dff53cb23983ddf617d2f22dccc33f6f1a27c
parent84691af93185c692058ba55fa81a04103f5bf71b (diff)
Intersting/relevant changes since bmake-20240711 ChangeLog since bmake-20240711 2025-01-25 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250125 Merge with NetBSD make, sync up below change. * unit-tests/Makefile: remove $TMPDIR via .END to avoid failure in test on NFS - since the temp file for the target script is open and thus gets renamed by the server rather than removed. 2025-01-20 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250120 Merge with NetBSD make, pick up o use FORK_FUNCTION so it can be forced to fork when doing coverage. o main.c: avoid memory allocation in error path after exec failure. 2025-01-16 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250116 Merge with NetBSD make, pick up o clarify that undefined expressions are allowed in dependencies o simplify code for evaluating the '!=' variable assignment 2025-01-11 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250111 Merge with NetBSD make, pick up o replace "Malformed conditional" with "Variable is undefined" when appropriate 2025-01-10 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250110 Merge with NetBSD make, pick up o job.c: remove some unnecessary layers in job handling o unit-tests: test expressions based on undefined variables 2025-01-01 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20250101 Merge with NetBSD make, pick up o var.c: reduce pointer indirections when unexporting a variable 2024-12-12 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241212 * mk/ updates 2024-11-24 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241124 Merge with NetBSD make, pick up o var.c: fix confusing error message when overriding a read-only variable 2024-11-22 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241122 Merge with NetBSD make, pick up o unit-tests/Makefile: optimize running of tests skip extra cat in 99% of cases. 2024-11-15 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241114 Merge with NetBSD make, pick up o make.1: note that MAKEOBJPREFIX should be absolute path also that it can be set via makefile if suitable care taken. 2024-11-10 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241110 Merge with NetBSD make, pick up o make: allow .../ (search here and above) in .MAKE.MAKEFILE_PREFERENCE and -f argument. 2024-11-03 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20241101 Merge with NetBSD make, pick up o parse.c: report filename:linenumber in parse debug output 2024-09-21 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240921 Merge with NetBSD make, pick up o make.1: Only list the defaults for MAKEFILE_PREFERENCE once. * Makefile: use genfiles.mk to generate ${MAN} so that it can be tuned for local site. Ensure MAN is defined before including Makefile.inc * Makefile: use MK_GEN_MAN to make it easier to control whether we generate ${MAN} 2024-09-16 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240909 * arch.c: fix NetBSD PR 58597 2024-09-01 Simon J Gerraty <sjg@beast.crufty.net> * Makefile: use SUBDIR.${MK_TESTS} so that we skip unit-tests for obj and clean when FreeBSD is building WITHOUT_TESTS * VERSION (_MAKE_VERSION): 20240901 Merge with NetBSD make, pick up o reduce line length in error messages o var.c: simplify printing of an evaluation stack element 2024-08-29 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240828 Merge with NetBSD make, pick up o add more context to error message about recursive variables o treat recursive variables non-fatally - continue parsing to end of makefile 2024-08-12 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240808 Merge with NetBSD make, pick up o improve some error messages for better clarify and readability 2024-07-22 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240722 Merge with NetBSD make, pick up o job.c: remove dead code 2024-07-21 Simon J Gerraty <sjg@beast.crufty.net> * VERSION (_MAKE_VERSION): 20240720 Merge with NetBSD make, pick up o compat.c: do not run commands that have parse or evaluation errors. o var.c: remove wrong error message about an undefined variable mk/ChangeLog since bmake-20240711 2025-01-10 Simon J Gerraty <sjg@beast.crufty.net> * rust.mk: use RUST_LIBS and RUST_PROGS 2025-01-01 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20250101 * use W flag to :S and :C rather than :tW 2024-12-16 Simon J Gerraty <sjg@beast.crufty.net> * rust.mk: add RUSTFLAGS if needed 2024-12-12 Simon J Gerraty <sjg@beast.crufty.net> * init.mk (OBJS_SRCS_FILTER): apply this as ${OBJS_SRCS_FILTER:ts:} as we do in FreeBSD. 2024-12-03 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20241202 * setopts.sh: needed by newlog.sh 2024-11-22 Simon J Gerraty <sjg@beast.crufty.net> * meta.sys.mk: add META_MODE_XTRAS to META_MODE to make it easier to add things like 'env' when debugging. * install-mk (MK_VERSION): 20241122 * rust.mk: rename CARGO* to RUST_CARGO* so I don't feel like this makefile should be renamed to cargo.mk 2024-11-11 Simon J Gerraty <sjg@beast.crufty.net> * dirdeps.mk: add DIRDEPS_CACHED_ENV to dirdeps-cached and DIRDEP_USE_EPILOGUE to _DIRDEP_USE 2024-10-30 Simon J Gerraty <sjg@beast.crufty.net> * meta.sys.mk: if MK_META_ERROR_TARGET is yes and NEWLOG_SH is set, and ERROR_LOGDIR already exists, hook _rotateErrorLog to .BEGIN target. 2024-10-27 Simon J Gerraty <sjg@beast.crufty.net> * options.mk: add support for DEBUG_OPTIONS (similar to DEBUG_DIRDEPS) to allow us to see where options get set. Eg. DEBUG_OPTIONS="STAGING*" gives: bmake[1]: "mk/options.mk" line 89: sys.mk: MK_STAGING=yes (MK_DIRDEPS_BUILD=no) bmake[1]: "mk/options.mk" line 66: local.init.mk: MK_STAGING=yes bmake[1]: "mk/options.mk" line 66: local.init.mk: MK_STAGING_PROG=no bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_MAN=yes (MK_STAGING=yes) bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_PROG=no (MK_STAGING=yes) bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_RUST=no (MK_STAGING_PROG=no) * own.mk: fix setting of STAGE_OBJTOP (normally set by sys.dirdeps.mk) 2024-10-26 Simon J Gerraty <sjg@beast.crufty.net> * rust.mk: add some documentation and support for staging 2024-10-25 Simon J Gerraty <sjg@beast.crufty.net> * rust.mk: a means of integrating Rust projects into a larger build. 2024-10-18 Simon J Gerraty <sjg@beast.crufty.net> * dirdeps-targets.mk: if DEBUG_DIRDEPS_TARGETS and we found STATIC_DIRDEPS_CACHE, report its relative path. 2024-09-30 Simon J Gerraty <sjg@beast.crufty.net> * dirdeps.mk: tweak the debug message for "Loading" a Makefile.depend file, always report what the actual makefile is with the DIRDEP it is for. Remove the redundant "Looking" message. 2024-09-26 Simon J Gerraty <sjg@beast.crufty.net> * meta2deps.py: when raising AssertionError include meta file name with $SB trimmed if possible. 2024-09-23 Simon J Gerraty <sjg@beast.crufty.net> * meta2deps.py: replace assert() with raise AssertionError when we detect missing eXits, to ensure a meaningful message gets into log. 2024-09-21 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20240921 * FILES: add genfiles.mk 2024-09-20 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20240920 * cython.mk: Get PYTHON_VERSION from PYTHON 2024-08-31 Simon J Gerraty <sjg@beast.crufty.net> * subdir.mk: add ${SUBDIR.yes} - allows for SUBDIR.${MK_*} and handle subdir with '-' in its name. 2024-08-23 Simon J Gerraty <sjg@beast.crufty.net> * install-mk (MK_VERSION): 20240820 * links.mk: Allow a filter to be applied to SYMLINKS etc. It is up to [BUILD_][SYM]LINKS_FILTER to do something sane. Also only claim we are making a symlink if the value changed.
-rw-r--r--ChangeLog139
-rw-r--r--FILES2
-rw-r--r--Makefile139
-rw-r--r--VERSION2
-rw-r--r--arch.c9
-rw-r--r--bmake.147
-rw-r--r--bmake.cat134
-rw-r--r--bsd.after-import.mk5
-rw-r--r--compat.c13
-rw-r--r--cond.c29
-rw-r--r--job.c84
-rw-r--r--job.h4
-rw-r--r--main.c44
-rw-r--r--make.135
-rw-r--r--make.h21
-rw-r--r--mk/ChangeLog117
-rw-r--r--mk/FILES3
-rw-r--r--mk/README10
-rw-r--r--mk/cython.mk43
-rw-r--r--mk/dirdeps-targets.mk5
-rw-r--r--mk/dirdeps.mk20
-rw-r--r--mk/gendirdeps.mk4
-rw-r--r--mk/genfiles.mk26
-rw-r--r--mk/init.mk11
-rw-r--r--[-rwxr-xr-x]mk/install-mk4
-rw-r--r--mk/lib.mk14
-rw-r--r--mk/links.mk34
-rw-r--r--mk/meta.sys.mk13
-rwxr-xr-xmk/meta2deps.py16
-rw-r--r--mk/options.mk8
-rw-r--r--mk/own.mk7
-rw-r--r--mk/prog.mk12
-rw-r--r--mk/rust.mk203
-rw-r--r--mk/setopts.sh175
-rw-r--r--mk/subdir.mk10
-rw-r--r--mk/sys.mk3
-rw-r--r--mk/sys.vars.mk7
-rw-r--r--[-rwxr-xr-x]os.sh8
-rw-r--r--parse.c49
-rw-r--r--suff.c6
-rw-r--r--unit-tests/Makefile23
-rw-r--r--unit-tests/archive.exp12
-rw-r--r--unit-tests/archive.mk20
-rw-r--r--unit-tests/cmd-errors-jobs.exp76
-rw-r--r--unit-tests/cmd-errors-jobs.mk123
-rw-r--r--unit-tests/cmd-errors-lint.exp14
-rw-r--r--unit-tests/cmd-errors-lint.mk17
-rw-r--r--unit-tests/cmd-errors.exp14
-rw-r--r--unit-tests/cmd-errors.mk17
-rwxr-xr-xunit-tests/cmd-interrupt.exp1
-rwxr-xr-xunit-tests/cmd-interrupt.mk24
-rw-r--r--unit-tests/cmdline.exp4
-rw-r--r--unit-tests/cmdline.mk8
-rw-r--r--unit-tests/cond-cmp-numeric-eq.exp4
-rwxr-xr-xunit-tests/cond-cmp-numeric-eq.mk6
-rw-r--r--unit-tests/cond-cmp-numeric.exp2
-rw-r--r--unit-tests/cond-cmp-numeric.mk4
-rw-r--r--unit-tests/cond-cmp-string.exp8
-rw-r--r--unit-tests/cond-cmp-string.mk10
-rw-r--r--unit-tests/cond-eof.exp6
-rw-r--r--unit-tests/cond-eof.mk8
-rw-r--r--unit-tests/cond-func-commands.mk7
-rw-r--r--unit-tests/cond-func-defined.exp4
-rw-r--r--unit-tests/cond-func-defined.mk11
-rw-r--r--unit-tests/cond-func-empty.exp3
-rw-r--r--unit-tests/cond-func-empty.mk9
-rw-r--r--unit-tests/cond-func-exists.mk7
-rw-r--r--unit-tests/cond-func-make.mk7
-rw-r--r--unit-tests/cond-func-target.mk7
-rw-r--r--unit-tests/cond-func.exp9
-rw-r--r--unit-tests/cond-func.mk17
-rw-r--r--unit-tests/cond-late.exp4
-rw-r--r--unit-tests/cond-late.mk4
-rw-r--r--unit-tests/cond-op-and.exp6
-rw-r--r--unit-tests/cond-op-and.mk8
-rw-r--r--unit-tests/cond-op-not.exp2
-rw-r--r--unit-tests/cond-op-not.mk4
-rw-r--r--unit-tests/cond-op-or.exp6
-rw-r--r--unit-tests/cond-op-or.mk8
-rw-r--r--unit-tests/cond-op-parentheses.exp6
-rw-r--r--unit-tests/cond-op-parentheses.mk8
-rw-r--r--unit-tests/cond-op.exp14
-rw-r--r--unit-tests/cond-op.mk16
-rw-r--r--unit-tests/cond-token-number.exp8
-rw-r--r--unit-tests/cond-token-number.mk10
-rw-r--r--unit-tests/cond-token-plain.exp12
-rw-r--r--unit-tests/cond-token-plain.mk14
-rw-r--r--unit-tests/cond-token-string.exp20
-rw-r--r--unit-tests/cond-token-string.mk7
-rw-r--r--unit-tests/cond-token-var.exp22
-rw-r--r--unit-tests/cond-token-var.mk65
-rwxr-xr-xunit-tests/cond-undef-lint.exp10
-rwxr-xr-xunit-tests/cond-undef-lint.mk21
-rwxr-xr-xunit-tests/dep-var.exp8
-rwxr-xr-xunit-tests/dep-var.mk20
-rw-r--r--unit-tests/deptgt-makeflags.exp2
-rw-r--r--unit-tests/deptgt-order.exp4
-rw-r--r--unit-tests/deptgt.exp28
-rw-r--r--unit-tests/deptgt.mk12
-rw-r--r--unit-tests/directive-export-impl.exp38
-rw-r--r--unit-tests/directive-for-errors.exp3
-rw-r--r--unit-tests/directive-for-errors.mk4
-rw-r--r--unit-tests/directive-for-escape.exp12
-rw-r--r--unit-tests/directive-for-escape.mk6
-rwxr-xr-xunit-tests/directive-for.exp3
-rwxr-xr-xunit-tests/directive-for.mk4
-rw-r--r--unit-tests/directive-if-nested.mk4
-rw-r--r--unit-tests/directive-if.exp2
-rw-r--r--unit-tests/directive-if.mk4
-rwxr-xr-xunit-tests/directive-include-fatal.exp2
-rwxr-xr-xunit-tests/directive-include-fatal.mk4
-rw-r--r--unit-tests/directive-include-guard.exp6
-rw-r--r--unit-tests/directive-include-guard.mk26
-rwxr-xr-xunit-tests/directive-include.exp3
-rwxr-xr-xunit-tests/directive-include.mk6
-rw-r--r--unit-tests/directive-undef.exp3
-rw-r--r--unit-tests/directive-undef.mk4
-rw-r--r--unit-tests/include-main.exp4
-rwxr-xr-xunit-tests/lint.exp6
-rw-r--r--unit-tests/moderrs.exp233
-rw-r--r--unit-tests/moderrs.mk175
-rw-r--r--unit-tests/opt-debug-lint.exp15
-rw-r--r--unit-tests/opt-debug-lint.mk10
-rw-r--r--unit-tests/opt-debug-parse.exp14
-rw-r--r--unit-tests/opt-debug-var.exp8
-rw-r--r--unit-tests/opt-debug-var.mk19
-rw-r--r--unit-tests/suff-incomplete.exp12
-rw-r--r--unit-tests/suff-main-several.exp30
-rw-r--r--unit-tests/suff-rebuild.exp22
-rw-r--r--unit-tests/suff.exp146
-rw-r--r--unit-tests/suff.mk41
-rw-r--r--unit-tests/var-eval-short.exp12
-rw-r--r--unit-tests/var-eval-short.mk5
-rw-r--r--unit-tests/var-op-expand.exp8
-rw-r--r--unit-tests/var-op-expand.mk6
-rw-r--r--unit-tests/var-op-shell.exp6
-rw-r--r--unit-tests/var-op-shell.mk11
-rw-r--r--unit-tests/var-recursive.exp41
-rw-r--r--unit-tests/var-recursive.mk77
-rw-r--r--unit-tests/vardebug.exp51
-rw-r--r--unit-tests/vardebug.mk21
-rw-r--r--unit-tests/varmisc.exp45
-rw-r--r--unit-tests/varmisc.mk30
-rw-r--r--unit-tests/varmod-assign-shell.exp2
-rw-r--r--unit-tests/varmod-assign-shell.mk4
-rw-r--r--unit-tests/varmod-assign.exp38
-rw-r--r--unit-tests/varmod-assign.mk27
-rw-r--r--unit-tests/varmod-edge.exp29
-rw-r--r--unit-tests/varmod-edge.mk20
-rw-r--r--unit-tests/varmod-gmtime.exp20
-rw-r--r--unit-tests/varmod-gmtime.mk17
-rw-r--r--unit-tests/varmod-hash.exp15
-rw-r--r--unit-tests/varmod-hash.mk9
-rw-r--r--unit-tests/varmod-ifelse.exp63
-rw-r--r--unit-tests/varmod-ifelse.mk28
-rw-r--r--unit-tests/varmod-indirect.exp22
-rw-r--r--unit-tests/varmod-indirect.mk10
-rw-r--r--unit-tests/varmod-localtime.exp20
-rw-r--r--unit-tests/varmod-localtime.mk17
-rw-r--r--unit-tests/varmod-loop-delete.exp4
-rw-r--r--unit-tests/varmod-loop-delete.mk4
-rw-r--r--unit-tests/varmod-loop-varname.exp16
-rw-r--r--unit-tests/varmod-loop-varname.mk14
-rw-r--r--unit-tests/varmod-loop.exp10
-rwxr-xr-xunit-tests/varmod-match-escape.exp29
-rwxr-xr-xunit-tests/varmod-match-escape.mk8
-rw-r--r--unit-tests/varmod-match.exp31
-rw-r--r--unit-tests/varmod-match.mk23
-rw-r--r--unit-tests/varmod-mtime.exp23
-rw-r--r--unit-tests/varmod-mtime.mk19
-rw-r--r--unit-tests/varmod-order.exp49
-rw-r--r--unit-tests/varmod-order.mk43
-rw-r--r--unit-tests/varmod-range.exp22
-rw-r--r--unit-tests/varmod-range.mk19
-rw-r--r--unit-tests/varmod-select-words.exp60
-rw-r--r--unit-tests/varmod-select-words.mk66
-rw-r--r--unit-tests/varmod-shell.exp6
-rw-r--r--unit-tests/varmod-shell.mk8
-rw-r--r--unit-tests/varmod-subst-regex.exp73
-rw-r--r--unit-tests/varmod-subst-regex.mk16
-rw-r--r--unit-tests/varmod-subst.exp5
-rw-r--r--unit-tests/varmod-subst.mk3
-rw-r--r--unit-tests/varmod-sun-shell.exp4
-rw-r--r--unit-tests/varmod-sun-shell.mk6
-rw-r--r--unit-tests/varmod-sysv.exp8
-rw-r--r--unit-tests/varmod-sysv.mk8
-rw-r--r--unit-tests/varmod-to-separator.exp52
-rw-r--r--unit-tests/varmod-to-separator.mk41
-rw-r--r--unit-tests/varmod.exp65
-rw-r--r--unit-tests/varmod.mk48
-rw-r--r--unit-tests/varname-dot-make-level.exp10
-rw-r--r--unit-tests/varname-dot-make-level.mk9
-rwxr-xr-xunit-tests/varname-dot-shell.exp30
-rw-r--r--unit-tests/varname-dot-suffixes.exp14
-rw-r--r--unit-tests/varname.exp8
-rw-r--r--unit-tests/varname.mk6
-rw-r--r--unit-tests/varparse-dynamic.exp4
-rw-r--r--unit-tests/varparse-dynamic.mk6
-rw-r--r--unit-tests/varparse-errors.exp64
-rw-r--r--unit-tests/varparse-errors.mk44
-rw-r--r--var.c149
201 files changed, 3152 insertions, 1744 deletions
diff --git a/ChangeLog b/ChangeLog
index 12774bb5598c..212b0fcfaacb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,142 @@
+2025-01-25 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250125
+ Merge with NetBSD make, sync up below change.
+
+ * unit-tests/Makefile: remove $TMPDIR via .END
+ to avoid failure in test on NFS - since the temp file for the
+ target script is open and thus gets renamed by the server rather
+ than removed.
+
+2025-01-20 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250120
+ Merge with NetBSD make, pick up
+ o use FORK_FUNCTION so it can be forced to fork when doing coverage.
+ o main.c: avoid memory allocation in error path after exec failure.
+
+2025-01-16 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250116
+ Merge with NetBSD make, pick up
+ o clarify that undefined expressions are allowed in dependencies
+ o simplify code for evaluating the '!=' variable assignment
+
+2025-01-11 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250111
+ Merge with NetBSD make, pick up
+ o replace "Malformed conditional" with "Variable is undefined"
+ when appropriate
+
+2025-01-10 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250110
+ Merge with NetBSD make, pick up
+ o job.c: remove some unnecessary layers in job handling
+ o unit-tests: test expressions based on undefined variables
+
+2025-01-01 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20250101
+ Merge with NetBSD make, pick up
+ o var.c: reduce pointer indirections when unexporting a variable
+
+2024-12-12 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241212
+ * mk/ updates
+
+2024-11-24 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241124
+ Merge with NetBSD make, pick up
+ o var.c: fix confusing error message when overriding a read-only
+ variable
+
+2024-11-22 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241122
+ Merge with NetBSD make, pick up
+ o unit-tests/Makefile: optimize running of tests skip extra cat
+ in 99% of cases.
+
+2024-11-15 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241114
+ Merge with NetBSD make, pick up
+ o make.1: note that MAKEOBJPREFIX should be absolute path
+ also that it can be set via makefile if suitable care taken.
+
+2024-11-10 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241110
+ Merge with NetBSD make, pick up
+ o make: allow .../ (search here and above) in
+ .MAKE.MAKEFILE_PREFERENCE and -f argument.
+
+2024-11-03 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20241101
+ Merge with NetBSD make, pick up
+ o parse.c: report filename:linenumber in parse debug output
+
+2024-09-21 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240921
+ Merge with NetBSD make, pick up
+ o make.1: Only list the defaults for MAKEFILE_PREFERENCE once.
+
+ * Makefile: use genfiles.mk to generate ${MAN}
+ so that it can be tuned for local site.
+ Ensure MAN is defined before including Makefile.inc
+
+ * Makefile: use MK_GEN_MAN to make it easier to control whether we
+ generate ${MAN}
+
+2024-09-16 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240909
+
+ * arch.c: fix NetBSD PR 58597
+
+2024-09-01 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * Makefile: use SUBDIR.${MK_TESTS} so that we skip
+ unit-tests for obj and clean when FreeBSD is building WITHOUT_TESTS
+
+ * VERSION (_MAKE_VERSION): 20240901
+ Merge with NetBSD make, pick up
+ o reduce line length in error messages
+ o var.c: simplify printing of an evaluation stack element
+
+2024-08-29 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240828
+ Merge with NetBSD make, pick up
+ o add more context to error message about recursive variables
+ o treat recursive variables non-fatally - continue parsing to end
+ of makefile
+
+2024-08-12 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240808
+ Merge with NetBSD make, pick up
+ o improve some error messages for better clarify and readability
+
+2024-07-22 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240722
+ Merge with NetBSD make, pick up
+ o job.c: remove dead code
+
+2024-07-21 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * VERSION (_MAKE_VERSION): 20240720
+ Merge with NetBSD make, pick up
+ o compat.c: do not run commands that have parse or evaluation errors.
+ o var.c: remove wrong error message about an undefined variable
+
2024-07-13 Simon J Gerraty <sjg@beast.crufty.net>
* cleanup redundant differences from NetBSD make
diff --git a/FILES b/FILES
index bfe95a9b6b47..c8937c610a4d 100644
--- a/FILES
+++ b/FILES
@@ -593,6 +593,8 @@ unit-tests/shell-ksh.exp
unit-tests/shell-ksh.mk
unit-tests/shell-sh.exp
unit-tests/shell-sh.mk
+unit-tests/suff.exp
+unit-tests/suff.mk
unit-tests/suff-add-later.exp
unit-tests/suff-add-later.mk
unit-tests/suff-clear-regular.exp
diff --git a/Makefile b/Makefile
index 65730df7e3df..939b71c5e12c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
-# $Id: Makefile,v 1.127 2024/03/19 16:03:23 sjg Exp $
+# $Id: Makefile,v 1.132 2024/09/22 19:56:26 sjg Exp $
-PROG= bmake
+PROG = bmake
-SRCS= \
+SRCS = \
arch.c \
buf.c \
compat.c \
@@ -25,6 +25,11 @@ SRCS= \
util.c \
var.c
+.MAIN: all
+
+MAN = ${PROG}.1
+SRCS.${MAN} = ${srcdir}/make.1
+
.-include "VERSION"
.-include "Makefile.inc"
@@ -32,25 +37,26 @@ SRCS= \
.-include "Makefile.config"
.if !empty(LIBOBJS)
-SRCS+= ${LIBOBJS:T:.o=.c}
+SRCS += ${LIBOBJS:T:.o=.c}
.endif
# just in case
-prefix?= /usr
-srcdir?= ${.CURDIR}
+prefix ?= /usr
+srcdir ?= ${.PARSEDIR}
+srcdir := ${srcdir}
-DEFAULT_SYS_PATH?= ${prefix}/share/mk
+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}\""
+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_MAKE_OS FORCE_MACHINE FORCE_MACHINE_ARCH
.ifdef $x
-COPTS.main.c+= "-D$x=\"${$x}\""
+COPTS.main.c += "-D$x=\"${$x}\""
.endif
.endfor
@@ -60,8 +66,8 @@ 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}
+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
@@ -76,65 +82,82 @@ COPTS.filemon_ktrace.c += -Wno-error=unused-parameter
.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
+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}}
+isBSD44 := ${BSD44_LIST:M${OS}}
.if ${isBSD44} == "" && ${OS:NCygwin:NDarwin:NLinux} != ""
-MANTARGET?= cat
+MANTARGET ?= cat
.if ${MACHINE} == "sun386"
# even I don't have one of these anymore :-)
-CFLAGS+= -DPORTAR
+CFLAGS += -DPORTAR
.elif ${OS} != "SunOS"
# assume the worst
-SRCS+= sigcompat.c
-CFLAGS+= -DSIGNAL_FLAGS=SA_RESTART
+SRCS += sigcompat.c
+CFLAGS += -DSIGNAL_FLAGS=SA_RESTART
.endif
.else
-MANTARGET?= man
+MANTARGET ?= man
.endif
# turn this on by default - ignored if we are root
-WITH_INSTALL_AS_USER=
+WITH_INSTALL_AS_USER =
# suppress with -DWITHOUT_*
-OPTIONS_DEFAULT_YES+= \
+OPTIONS_DEFAULT_YES += \
AUTOCONF_MK \
INSTALL_MK \
- PROG_LINK
+ PROG_LINK \
+ TESTS \
+
+OPTIONS_DEFAULT_NO += \
+ GEN_MAN \
+ PROG_VERSION \
-OPTIONS_DEFAULT_NO+= \
- PROG_VERSION
+.if ${PROG} != "make" || ${srcdir} != ${.CURDIR} || !exists(${srcdir}/${MAN})
+WITH_GEN_MAN = 1
+.endif
# process options now
.include <own.mk>
.if ${MK_PROG_VERSION} == "yes"
-PROG_NAME= ${PROG}-${_MAKE_VERSION}
+PROG_NAME = ${PROG}-${_MAKE_VERSION}
.if ${MK_PROG_LINK} == "yes"
-SYMLINKS+= ${PROG_NAME} ${BINDIR}/${PROG}
+SYMLINKS += ${PROG_NAME} ${BINDIR}/${PROG}
.endif
.endif
EXTRACT_MAN=no
# end-delete1
-MAN= ${PROG}.1
-MAN1= ${MAN}
+.if make(obj) || make(clean)
+SUBDIR.${MK_TESTS} += unit-tests
+.endif
+
+MAN1 = ${MAN}
+
+.if ${MK_GEN_MAN:Uno} == "yes"
+
+# we use this to generate ${MAN}
+.include <${srcdir}/mk/genfiles.mk>
.if ${PROG} != "make"
-CLEANFILES+= my.history
-.if make(${MAN}) || !exists(${srcdir}/${MAN})
+CLEANFILES += my.history
+SED_CMDS.${MAN} += \
+ -e '/^.Dt/s/MAKE/${PROG:tu}/' \
+ -e '/^.Nm/s/make/${PROG}/' \
+
+.endif
+
+.if ${CLEANFILES:U:Mmy.history} != ""
+${MAN}: my.history
my.history:
@(echo ".Nm"; \
echo "is derived from NetBSD"; \
@@ -142,40 +165,46 @@ my.history:
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}/' \
+SED_CMDS.${MAN} += \
-e '/^.Sh HISTORY/rmy.history' \
- -e '/^.Sh HISTORY/,$$s,^.Nm,make,' ${srcdir}/make.1 > $@
+ -e '/^.Sh HISTORY/,/BUGS/s,^.Nm,make,' \
-all beforeinstall: ${MAN}
-_mfromdir=.
.endif
+
+.if ${.MAKE.OS:N*BSD} != ""
+# assume .Nx is not supported
+SED_CMDS.${MAN} += -e 's/^\.Nx/NetBSD/'
+.endif
+
+# watch out for a late change of PROG
+.if !empty(SRCS.${MAN})
+.NOPATH: ${MAN}
+${MAN}: ${SRCS.${MAN}} _GENFILES_USE
+
+all man beforeinstall: ${MAN}
+_mfromdir=.
.endif
+.endif # MK_GEN_MAN
-MANTARGET?= cat
-MANDEST?= ${MANDIR}/${MANTARGET}1
+MANTARGET ?= cat
+MANDEST ?= ${MANDIR}/${MANTARGET}1
.if ${MANTARGET} == "cat"
-_mfromdir=${srcdir}
+_mfromdir = ${srcdir}
.endif
.include <prog.mk>
-CPPFLAGS+= -DMAKE_NATIVE -DHAVE_CONFIG_H
+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}
+SHAREDIR = ${SHAREDIR.bmake:U${prefix}/share}
+BINDIR = ${BINDIR.bmake:U${prefix}/bin}
+MANDIR = ${MANDIR.bmake:U${SHAREDIR}/man}
${OBJS}: config.h
diff --git a/VERSION b/VERSION
index f55bfabc9103..9d1a987f65d6 100644
--- a/VERSION
+++ b/VERSION
@@ -1,2 +1,2 @@
# keep this compatible with sh and make
-_MAKE_VERSION=20240711
+_MAKE_VERSION=20250125
diff --git a/arch.c b/arch.c
index 00c72261707f..77ac7f3c5707 100644
--- a/arch.c
+++ b/arch.c
@@ -1,4 +1,4 @@
-/* $NetBSD: arch.c,v 1.221 2024/07/07 07:50:57 rillig Exp $ */
+/* $NetBSD: arch.c,v 1.222 2024/08/06 17:46:01 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -147,7 +147,7 @@ struct ar_hdr {
#include "dir.h"
/* "@(#)arch.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: arch.c,v 1.221 2024/07/07 07:50:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: arch.c,v 1.222 2024/08/06 17:46:01 rillig Exp $");
typedef struct List ArchList;
typedef struct ListNode ArchListNode;
@@ -314,8 +314,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
if (*cp == '\0') {
Parse_Error(PARSE_FATAL,
- "No closing parenthesis "
- "in archive specification");
+ "Missing ')' in archive specification");
return false;
}
@@ -416,7 +415,7 @@ Arch_ParseArchive(char **pp, GNodeList *gns, GNode *scope)
static struct ar_hdr *
ArchStatMember(const char *archive, const char *member, bool addToCache)
{
-#define AR_MAX_NAME_LEN (sizeof arh.ar_name - 1)
+#define AR_MAX_NAME_LEN (sizeof arh.AR_NAME - 1)
FILE *arch;
size_t size; /* Size of archive member */
char magic[SARMAG];
diff --git a/bmake.1 b/bmake.1
index f7cc15b16c41..eef2d799b960 100644
--- a/bmake.1
+++ b/bmake.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.378 2024/07/01 21:02:26 sjg Exp $
+.\" $NetBSD: make.1,v 1.381 2024/11/14 19:30:13 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd July 1, 2024
+.Dd November 14, 2024
.Dt BMAKE 1
.Os
.Sh NAME
@@ -60,10 +60,11 @@ If no
.Fl f Ar makefile
option is given,
.Nm
-tries to open
-.Sq Pa makefile
-then
-.Sq Pa Makefile
+looks for the makefiles listed in
+.Va .MAKE.MAKEFILE_PREFERENCE
+(default
+.Sq Pa makefile ,
+.Sq Pa Makefile )
in order to find the specifications.
If the file
.Sq Pa .depend
@@ -233,15 +234,20 @@ so the actual commands are printed as they are executed.
.It Fl e
Let environment variables override global variables within makefiles.
.It Fl f Ar makefile
-Specify a makefile to read instead of the default
-.Pa makefile
-or
-.Pa Makefile .
+Specify a makefile to read instead of one of the defaults listed in
+.Va .MAKE.MAKEFILE_PREFERENCE .
If
.Ar makefile
is
.Ql \&- ,
standard input is read.
+If
+.Ar makefile
+starts with the string
+.Ql \&.../ ,
+.Nm
+searches for the specified path in the rest of the argument
+in the current directory and its parents.
Multiple makefiles may be specified, and are read in the order specified.
.It Fl I Ar directory
Specify a directory in which to search for makefiles and included makefiles.
@@ -1159,6 +1165,7 @@ to help debug.
.It Va MAKEOBJDIRPREFIX
Used to create files in a separate directory, see
.Va .OBJDIR .
+It should be an absolute path.
.It Va .MAKE.OS
The name of the operating system, see
.Xr uname 1 .
@@ -2636,12 +2643,18 @@ and
.Ev MAKEOBJDIRPREFIX
and
.Ev MAKEOBJDIR
-may only be set in the environment or on the command line to
+should be set in the environment or on the command line to
.Nm
and not as makefile variables;
see the description of
.Sq Va .OBJDIR
for more details.
+It is possible to set these via makefile variables but unless done
+very early and the
+.Sq Ic .OBJDIR
+target is used to reset
+.Sq Va .OBJDIR ,
+there may be unexpected side effects.
.Sh FILES
.Bl -tag -width /usr/share/mk -compact
.It .depend
@@ -2663,13 +2676,13 @@ An incomplete list of changes in older versions of
.Nm :
.Pp
The way that .for loop variables are substituted changed after
-NetBSD 5.0
+.Nx 5.0
so that they still appear to be variable expansions.
In particular this stops them being treated as syntax, and removes some
obscure problems using them in .if statements.
.Pp
The way that parallel makes are scheduled changed in
-NetBSD 4.0
+.Nx 4.0
so that .ORDER and .WAIT apply recursively to the dependent nodes.
The algorithms used may change again in the future.
.Ss Other make dialects
@@ -2767,21 +2780,21 @@ does not exist ... unless someone creates an
file).
.Sh BUGS
The
-make
+.Nm
syntax is difficult to parse.
For instance, finding the end of a variable's use should involve scanning
each of the modifiers, using the correct terminator for each field.
In many places
-make
+.Nm
just counts {} and () in order to find the end of a variable expansion.
.Pp
There is no way of escaping a space character in a filename.
.Pp
In jobs mode, when a target fails;
-make
+.Nm
will put an error token into the job token pool.
This will cause all other instances of
-make
+.Nm
using that token pool to abort the build and exit with error code 6.
Sometimes the attempt to suppress a cascade of unnecessary errors,
can result in a seemingly unexplained
diff --git a/bmake.cat1 b/bmake.cat1
index f46f6681320a..8a1909e684ed 100644
--- a/bmake.cat1
+++ b/bmake.cat1
@@ -13,9 +13,9 @@ DDEESSCCRRIIPPTTIIOONN
bbmmaakkee is a program designed to simplify the maintenance of other
programs. Its input is a list of specifications as to the files upon
which programs and other files depend. If no --ff _m_a_k_e_f_i_l_e option is
- given, bbmmaakkee tries to open `_m_a_k_e_f_i_l_e' then `_M_a_k_e_f_i_l_e' in order to find
- the specifications. If the file `_._d_e_p_e_n_d' exists, it is read, see
- mkdep(1).
+ given, bbmmaakkee looks for the makefiles listed in _._M_A_K_E_._M_A_K_E_F_I_L_E___P_R_E_F_E_R_E_N_C_E
+ (default `_m_a_k_e_f_i_l_e', `_M_a_k_e_f_i_l_e') in order to find the specifications. If
+ the file `_._d_e_p_e_n_d' exists, it is read, see mkdep(1).
This manual page is intended as a reference document only. For a more
thorough description of bbmmaakkee and makefiles, please refer to _P_M_a_k_e _- _A
@@ -138,9 +138,12 @@ DDEESSCCRRIIPPTTIIOONN
makefiles.
--ff _m_a_k_e_f_i_l_e
- Specify a makefile to read instead of the default _m_a_k_e_f_i_l_e or
- _M_a_k_e_f_i_l_e. If _m_a_k_e_f_i_l_e is `-', standard input is read. Multiple
- makefiles may be specified, and are read in the order specified.
+ Specify a makefile to read instead of one of the defaults listed
+ in _._M_A_K_E_._M_A_K_E_F_I_L_E___P_R_E_F_E_R_E_N_C_E. If _m_a_k_e_f_i_l_e is `-', standard input
+ is read. If _m_a_k_e_f_i_l_e starts with the string `.../', bbmmaakkee
+ searches for the specified path in the rest of the argument in
+ the current directory and its parents. Multiple makefiles may be
+ specified, and are read in the order specified.
--II _d_i_r_e_c_t_o_r_y
Specify a directory in which to search for makefiles and included
@@ -765,7 +768,8 @@ VVAARRIIAABBLLEE AASSSSIIGGNNMMEENNTTSS
debug.
_M_A_K_E_O_B_J_D_I_R_P_R_E_F_I_X
- Used to create files in a separate directory, see _._O_B_J_D_I_R.
+ Used to create files in a separate directory, see _._O_B_J_D_I_R. It
+ should be an absolute path.
_._M_A_K_E_._O_S
The name of the operating system, see uname(1). It is read-only.
@@ -1691,9 +1695,11 @@ EENNVVIIRROONNMMEENNTT
MACHINE_ARCH, MAKE, MAKEFLAGS, MAKEOBJDIR, MAKEOBJDIRPREFIX, MAKESYSPATH,
PWD, and TMPDIR.
- MAKEOBJDIRPREFIX and MAKEOBJDIR may only be set in the environment or on
+ MAKEOBJDIRPREFIX and MAKEOBJDIR should be set in the environment or on
the command line to bbmmaakkee and not as makefile variables; see the
- description of `_._O_B_J_D_I_R' for more details.
+ description of `_._O_B_J_D_I_R' for more details. It is possible to set these
+ via makefile variables but unless done very early and the `..OOBBJJDDIIRR'
+ target is used to reset `_._O_B_J_D_I_R', there may be unexpected side effects.
FFIILLEESS
.depend list of dependencies
@@ -1774,17 +1780,17 @@ HHIISSTTOORRYY
_F_R_C file).
BBUUGGSS
- The make syntax is difficult to parse. For instance, finding the end of
+ The bbmmaakkee syntax is difficult to parse. For instance, finding the end of
a variable's use should involve scanning each of the modifiers, using the
- correct terminator for each field. In many places make just counts {}
+ correct terminator for each field. In many places bbmmaakkee just counts {}
and () in order to find the end of a variable expansion.
There is no way of escaping a space character in a filename.
- In jobs mode, when a target fails; make will put an error token into the
- job token pool. This will cause all other instances of make using that
+ In jobs mode, when a target fails; bbmmaakkee will put an error token into the
+ job token pool. This will cause all other instances of bbmmaakkee using that
token pool to abort the build and exit with error code 6. Sometimes the
attempt to suppress a cascade of unnecessary errors, can result in a
seemingly unexplained `*** Error code 6'
-FreeBSD 14.1-RELEASE July 1, 2024 FreeBSD 14.1-RELEASE
+FreeBSD 14.1-RELEASE-p5 November 14, 2024 FreeBSD 14.1-RELEASE-p5
diff --git a/bsd.after-import.mk b/bsd.after-import.mk
index 418caeaa58a6..f2948b855753 100644
--- a/bsd.after-import.mk
+++ b/bsd.after-import.mk
@@ -1,4 +1,4 @@
-# $Id: bsd.after-import.mk,v 1.18 2023/09/18 05:29:23 sjg Exp $
+# $Id: bsd.after-import.mk,v 1.19 2024/09/21 22:44:55 sjg Exp $
# This makefile is for use when integrating bmake into a BSD build
# system. Use this makefile after importing bmake.
@@ -61,8 +61,7 @@ MAKEFILE_SED = sed -e '/^MACHINE/d' \
-e '/include.*VERSION/d' \
-e '/^CC=/s,=,?=,' \
-e '/^PROG/ { s,=,?=,;s,bmake,$${.CURDIR:T},; }' \
- -e 's,^.-include,.sinclude,' \
- -e '/^\..*include *</ { s,<,<bsd.,;/autoconf/d; }' \
+ -e '/^\..*include *</ { s,<\([a-z]\),<bsd.\1,;/autoconf/d; }' \
-e 's,${SRCTOP},$${SRCTOP},g'
# These are the simple files we want to capture
diff --git a/compat.c b/compat.c
index 23ece245c8a6..0da929e35b82 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
-/* $NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $ */
+/* $NetBSD: compat.c,v 1.262 2025/01/19 10:57:10 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -94,7 +94,7 @@
#include "pathnames.h"
/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: compat.c,v 1.260 2024/07/11 20:09:16 sjg Exp $");
+MAKE_RCSID("$NetBSD: compat.c,v 1.262 2025/01/19 10:57:10 rillig Exp $");
static GNode *curTarg = NULL;
static pid_t compatChild;
@@ -206,7 +206,7 @@ UseShell(const char *cmd MAKE_ATTR_UNUSED)
static int
Compat_Spawn(const char **av)
{
- int pid = vfork();
+ int pid = FORK_FUNCTION();
if (pid < 0)
Fatal("Could not fork");
@@ -251,13 +251,18 @@ Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
const char *cmd = cmdp;
char cmd_file[MAXPATHLEN];
size_t cmd_len;
+ int parseErrorsBefore;
silent = (gn->type & OP_SILENT) != OP_NONE;
errCheck = !(gn->type & OP_IGNORE);
doIt = false;
+ parseErrorsBefore = parseErrors;
cmdStart = Var_SubstInTarget(cmd, gn);
- /* TODO: handle errors */
+ if (parseErrors != parseErrorsBefore) {
+ free(cmdStart);
+ return false;
+ }
if (cmdStart[0] == '\0') {
free(cmdStart);
diff --git a/cond.c b/cond.c
index 58c0069555e1..a724ba7ecf26 100644
--- a/cond.c
+++ b/cond.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.366 2024/07/06 21:21:09 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.371 2025/01/11 21:21:33 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -91,7 +91,7 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: cond.c,v 1.366 2024/07/06 21:21:09 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.371 2025/01/11 21:21:33 rillig Exp $");
/*
* Conditional expressions conform to this grammar:
@@ -221,13 +221,7 @@ ParseWord(const char **pp, bool doEval)
if ((ch == '&' || ch == '|') && depth == 0)
break;
if (ch == '$') {
- VarEvalMode emode = doEval
- ? VARE_EVAL_DEFINED
- : VARE_PARSE;
- /*
- * TODO: make Var_Parse complain about undefined
- * variables.
- */
+ VarEvalMode emode = doEval ? VARE_EVAL : VARE_PARSE;
FStr nestedVal = Var_Parse(&p, SCOPE_CMDLINE, emode);
/* TODO: handle errors */
Buf_AddStr(&word, nestedVal.str);
@@ -242,7 +236,6 @@ ParseWord(const char **pp, bool doEval)
p++;
}
- cpp_skip_hspace(&p);
*pp = p;
return Buf_DoneData(&word);
@@ -252,12 +245,14 @@ ParseWord(const char **pp, bool doEval)
static char *
ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func)
{
- const char *p = *pp;
+ const char *p = *pp, *argStart, *argEnd;
char *res;
p++; /* skip the '(' */
cpp_skip_hspace(&p);
+ argStart = p;
res = ParseWord(&p, doEval);
+ argEnd = p;
cpp_skip_hspace(&p);
if (*p++ != ')') {
@@ -266,7 +261,8 @@ ParseFuncArg(CondParser *par, const char **pp, bool doEval, const char *func)
len++;
Parse_Error(PARSE_FATAL,
- "Missing closing parenthesis for %.*s()", len, func);
+ "Missing ')' after argument '%.*s' for '%.*s'",
+ (int)(argEnd - argStart), argStart, len, func);
par->printedError = true;
free(res);
return NULL;
@@ -397,7 +393,7 @@ CondParser_StringExpr(CondParser *par, const char *start,
bool atStart; /* true means an expression outside quotes */
emode = doEval && quoted ? VARE_EVAL
- : doEval ? VARE_EVAL_DEFINED
+ : doEval ? VARE_EVAL_DEFINED_LOUD
: VARE_PARSE;
p = par->p;
@@ -734,6 +730,7 @@ CondParser_ComparisonOrLeaf(CondParser *par, bool doEval)
*/
arg = ParseWord(&p, doEval);
assert(arg[0] != '\0');
+ cpp_skip_hspace(&p);
if (*p == '=' || *p == '!' || *p == '<' || *p == '>') {
free(arg);
@@ -922,6 +919,7 @@ CondEvalExpression(const char *cond, bool plain,
{
CondParser par;
CondResult rval;
+ int parseErrorsBefore = parseErrors;
cpp_skip_hspace(&cond);
@@ -938,8 +936,9 @@ CondEvalExpression(const char *cond, bool plain,
if (par.curr != TOK_EOF)
rval = CR_ERROR;
- if (rval == CR_ERROR && eprint && !par.printedError)
- Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
+ if (rval == CR_ERROR && eprint && !par.printedError
+ && parseErrors == parseErrorsBefore)
+ Parse_Error(PARSE_FATAL, "Malformed conditional '%s'", cond);
return rval;
}
diff --git a/job.c b/job.c
index 8571bb87f326..0bbef4d3da6f 100644
--- a/job.c
+++ b/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.480 2024/07/07 07:50:57 rillig Exp $ */
+/* $NetBSD: job.c,v 1.485 2025/01/19 10:57:10 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -154,7 +154,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.480 2024/07/07 07:50:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.485 2025/01/19 10:57:10 rillig Exp $");
/*
* A shell defines how the commands are run. All commands for a target are
@@ -270,12 +270,6 @@ static enum { /* Why is the make aborting? */
/* 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.
*
@@ -1280,7 +1274,7 @@ TouchRegular(GNode *gn)
}
/*
- * Touch the given target. Called by JobStart when the -t flag was given.
+ * Touch the given target. Called by Job_Make when the -t flag was given.
*
* The modification date of the file is changed.
* If the file did not exist, it is created.
@@ -1435,9 +1429,9 @@ JobExec(Job *job, char **argv)
Var_ReexportVars(job->node);
- cpid = vfork();
+ cpid = FORK_FUNCTION();
if (cpid == -1)
- Punt("Cannot vfork: %s", strerror(errno));
+ Punt("Cannot fork: %s", strerror(errno));
if (cpid == 0) {
/* Child */
@@ -1628,22 +1622,8 @@ JobWriteShellCommands(Job *job, GNode *gn, bool *out_run)
*out_run = JobWriteCommands(job);
}
-/*
- * Start a target-creation process going for the target described by gn.
- *
- * Results:
- * JOB_ERROR if there was an error in the commands, JOB_FINISHED
- * if there isn't actually anything left to do for the job and
- * JOB_RUNNING if the job has been started.
- *
- * Details:
- * A new Job node is created and added to the list of running
- * jobs. PMake is forked and a child shell created.
- *
- * NB: The return value is ignored by everyone.
- */
-static JobStartResult
-JobStart(GNode *gn, bool special)
+void
+Job_Make(GNode *gn)
{
Job *job; /* new job descriptor */
char *argv[10]; /* Argument vector to shell */
@@ -1655,14 +1635,14 @@ JobStart(GNode *gn, bool special)
break;
}
if (job >= job_table_end)
- Punt("JobStart no job slots vacant");
+ Punt("Job_Make no job slots vacant");
memset(job, 0, sizeof *job);
job->node = gn;
job->tailCmds = NULL;
job->status = JOB_ST_SET_UP;
- job->special = special || gn->type & OP_SPECIAL;
+ job->special = (gn->type & OP_SPECIAL) != OP_NONE;
job->ignerr = opts.ignoreErrors || gn->type & OP_IGNORE;
job->echo = !(opts.silent || gn->type & OP_SILENT);
@@ -1695,6 +1675,8 @@ JobStart(GNode *gn, bool special)
* virtual targets.
*/
+ int parseErrorsBefore;
+
/*
* We're serious here, but if the commands were bogus, we're
* also dead...
@@ -1704,7 +1686,10 @@ JobStart(GNode *gn, bool special)
DieHorribly();
}
+ parseErrorsBefore = parseErrors;
JobWriteShellCommands(job, gn, &run);
+ if (parseErrors != parseErrorsBefore)
+ run = false;
(void)fflush(job->cmdFILE);
} else if (!GNode_ShouldExecute(gn)) {
/*
@@ -1742,7 +1727,7 @@ JobStart(GNode *gn, bool special)
Make_Update(job->node);
}
job->status = JOB_ST_FREE;
- return cmdsOK ? JOB_FINISHED : JOB_ERROR;
+ return;
}
/*
@@ -1755,7 +1740,6 @@ JobStart(GNode *gn, bool special)
JobCreatePipe(job, 3);
JobExec(job, argv);
- return JOB_RUNNING;
}
/*
@@ -1953,31 +1937,12 @@ again:
static void
JobRun(GNode *targ)
{
-#if 0
- /*
- * Unfortunately it is too complicated to run .BEGIN, .END, and
- * .INTERRUPT job in the parallel job module. As of 2020-09-25,
- * unit-tests/deptgt-end-jobs.mk hangs in an endless loop.
- *
- * Running these jobs in compat mode also guarantees that these
- * jobs do not overlap with other unrelated jobs.
- */
- GNodeList lst = LST_INIT;
- Lst_Append(&lst, targ);
- (void)Make_Run(&lst);
- Lst_Done(&lst);
- JobStart(targ, true);
- while (jobTokensRunning != 0) {
- Job_CatchOutput();
- }
-#else
+ /* Don't let these special jobs overlap with other unrelated jobs. */
Compat_Make(targ, targ);
- /* XXX: Replace with GNode_IsError(gn) */
- if (targ->made == ERROR) {
+ if (GNode_IsError(targ)) {
PrintOnError(targ, "\n\nStop.\n");
exit(1);
}
-#endif
}
/*
@@ -2133,16 +2098,6 @@ Job_CatchOutput(void)
}
}
-/*
- * Start the creation of a target. Basically a front-end for JobStart used by
- * the Make module.
- */
-void
-Job_Make(GNode *gn)
-{
- (void)JobStart(gn, false);
-}
-
static void
InitShellNameAndPath(void)
{
@@ -2921,11 +2876,6 @@ Job_RunTarget(const char *target, const char *fname)
Var_Set(gn, ALLSRC, fname);
JobRun(gn);
- /* XXX: Replace with GNode_IsError(gn) */
- if (gn->made == ERROR) {
- PrintOnError(gn, "\n\nStop.\n");
- exit(1);
- }
return true;
}
diff --git a/job.h b/job.h
index 085aa04e8e44..4182dd6268d5 100644
--- a/job.h
+++ b/job.h
@@ -1,4 +1,4 @@
-/* $NetBSD: job.h,v 1.80 2024/07/07 07:50:57 rillig Exp $ */
+/* $NetBSD: job.h,v 1.81 2025/01/03 04:51:42 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -119,7 +119,7 @@ typedef enum JobStatus {
JOB_ST_SET_UP = 1, /* Job is allocated but otherwise invalid */
/* XXX: What about the 2? */
JOB_ST_RUNNING = 3, /* Job is running, pid valid */
- JOB_ST_FINISHED = 4 /* Job is done (ie after SIGCHILD) */
+ JOB_ST_FINISHED = 4 /* Job is done (ie after SIGCHLD) */
} JobStatus;
/*
diff --git a/main.c b/main.c
index c1adf521296d..0b48b2d59389 100644
--- a/main.c
+++ b/main.c
@@ -1,4 +1,4 @@
-/* $NetBSD: main.c,v 1.632 2024/07/11 20:09:16 sjg Exp $ */
+/* $NetBSD: main.c,v 1.638 2025/01/19 12:59:39 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -111,7 +111,7 @@
#include "trace.h"
/* "@(#)main.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: main.c,v 1.632 2024/07/11 20:09:16 sjg Exp $");
+MAKE_RCSID("$NetBSD: main.c,v 1.638 2025/01/19 12:59:39 rillig Exp $");
#if defined(MAKE_NATIVE)
__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 "
"The Regents of the University of California. "
@@ -1414,7 +1414,8 @@ main_Init(int argc, char **argv)
/* Set some other useful variables. */
{
- char buf[64], *ep = getenv(MAKE_LEVEL_ENV);
+ char buf[64];
+ const char *ep = getenv(MAKE_LEVEL_ENV);
makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0;
if (makelevel < 0)
@@ -1658,6 +1659,20 @@ ReadMakefile(const char *fname)
Parse_File("(stdin)", -1);
Var_Set(SCOPE_INTERNAL, "MAKEFILE", "");
} else {
+ if (strncmp(fname, ".../", 4) == 0) {
+ name = Dir_FindHereOrAbove(curdir, fname + 4);
+ if (name != NULL) {
+ /* Dir_FindHereOrAbove returns dirname */
+ path = str_concat3(name, "/",
+ str_basename(fname));
+ free(name);
+ fd = open(path, O_RDONLY);
+ if (fd != -1) {
+ fname = path;
+ goto found;
+ }
+ }
+ }
/* if we've chdir'd, rebuild the path name */
if (strcmp(curdir, objdir) != 0 && *fname != '/') {
path = str_concat3(curdir, "/", fname);
@@ -1787,7 +1802,7 @@ Cmd_Exec(const char *cmd, char **error)
Var_ReexportVars(SCOPE_GLOBAL);
- switch (cpid = vfork()) {
+ switch (cpid = FORK_FUNCTION()) {
case 0:
(void)close(pipefds[0]);
(void)dup2(pipefds[1], STDOUT_FILENO);
@@ -1998,23 +2013,14 @@ write_all(int fd, const void *data, size_t n)
/* Print why exec failed, avoiding stdio. */
void MAKE_ATTR_DEAD
-execDie(const char *af, const char *av)
+execDie(const char *func, const char *arg)
{
- Buffer buf;
+ char msg[1024];
+ int len;
- Buf_Init(&buf);
- Buf_AddStr(&buf, progname);
- Buf_AddStr(&buf, ": ");
- Buf_AddStr(&buf, af);
- Buf_AddStr(&buf, "(");
- Buf_AddStr(&buf, av);
- Buf_AddStr(&buf, ") failed (");
- Buf_AddStr(&buf, strerror(errno));
- Buf_AddStr(&buf, ")\n");
-
- write_all(STDERR_FILENO, buf.data, buf.len);
-
- Buf_Done(&buf);
+ len = snprintf(msg, sizeof(msg), "%s: %s(%s) failed (%s)\n",
+ progname, func, arg, strerror(errno));
+ write_all(STDERR_FILENO, msg, (size_t)len);
_exit(1);
}
diff --git a/make.1 b/make.1
index 58875d4afa18..386fee8f46f0 100644
--- a/make.1
+++ b/make.1
@@ -1,4 +1,4 @@
-.\" $NetBSD: make.1,v 1.378 2024/07/01 21:02:26 sjg Exp $
+.\" $NetBSD: make.1,v 1.381 2024/11/14 19:30:13 sjg Exp $
.\"
.\" Copyright (c) 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -29,7 +29,7 @@
.\"
.\" from: @(#)make.1 8.4 (Berkeley) 3/19/94
.\"
-.Dd July 1, 2024
+.Dd November 14, 2024
.Dt MAKE 1
.Os
.Sh NAME
@@ -60,10 +60,11 @@ If no
.Fl f Ar makefile
option is given,
.Nm
-tries to open
-.Sq Pa makefile
-then
-.Sq Pa Makefile
+looks for the makefiles listed in
+.Va .MAKE.MAKEFILE_PREFERENCE
+(default
+.Sq Pa makefile ,
+.Sq Pa Makefile )
in order to find the specifications.
If the file
.Sq Pa .depend
@@ -233,15 +234,20 @@ so the actual commands are printed as they are executed.
.It Fl e
Let environment variables override global variables within makefiles.
.It Fl f Ar makefile
-Specify a makefile to read instead of the default
-.Pa makefile
-or
-.Pa Makefile .
+Specify a makefile to read instead of one of the defaults listed in
+.Va .MAKE.MAKEFILE_PREFERENCE .
If
.Ar makefile
is
.Ql \&- ,
standard input is read.
+If
+.Ar makefile
+starts with the string
+.Ql \&.../ ,
+.Nm
+searches for the specified path in the rest of the argument
+in the current directory and its parents.
Multiple makefiles may be specified, and are read in the order specified.
.It Fl I Ar directory
Specify a directory in which to search for makefiles and included makefiles.
@@ -1159,6 +1165,7 @@ to help debug.
.It Va MAKEOBJDIRPREFIX
Used to create files in a separate directory, see
.Va .OBJDIR .
+It should be an absolute path.
.It Va .MAKE.OS
The name of the operating system, see
.Xr uname 1 .
@@ -2636,12 +2643,18 @@ and
.Ev MAKEOBJDIRPREFIX
and
.Ev MAKEOBJDIR
-may only be set in the environment or on the command line to
+should be set in the environment or on the command line to
.Nm
and not as makefile variables;
see the description of
.Sq Va .OBJDIR
for more details.
+It is possible to set these via makefile variables but unless done
+very early and the
+.Sq Ic .OBJDIR
+target is used to reset
+.Sq Va .OBJDIR ,
+there may be unexpected side effects.
.Sh FILES
.Bl -tag -width /usr/share/mk -compact
.It .depend
diff --git a/make.h b/make.h
index 0023da6b2167..05714ddfd151 100644
--- a/make.h
+++ b/make.h
@@ -1,4 +1,4 @@
-/* $NetBSD: make.h,v 1.344 2024/07/11 20:09:16 sjg Exp $ */
+/* $NetBSD: make.h,v 1.349 2025/01/19 10:57:10 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -183,6 +183,15 @@ typedef unsigned char bool;
#define false 0
#endif
+/*
+ * In code coverage mode with gcc>=12, calling vfork/exec does not mark any
+ * further code from the parent process as covered. gcc-10.5.0 is fine, as
+ * are fork/exec calls, as well as posix_spawn.
+ */
+#ifndef FORK_FUNCTION
+#define FORK_FUNCTION vfork
+#endif
+
#include "lst.h"
#include "make_malloc.h"
#include "str.h"
@@ -716,7 +725,7 @@ typedef struct CmdOpts {
*/
DebugFlags debug;
- /* -df: debug output is written here - default stderr */
+ /* -dF: debug output is written here - default stderr */
FILE *debug_file;
/*
@@ -985,6 +994,12 @@ typedef enum VarEvalMode {
* Parse and evaluate the expression. It is an error if a
* subexpression evaluates to undefined.
*/
+ VARE_EVAL_DEFINED_LOUD,
+
+ /*
+ * Parse and evaluate the expression. It is a silent error if a
+ * subexpression evaluates to undefined.
+ */
VARE_EVAL_DEFINED,
/*
@@ -1064,7 +1079,7 @@ void Global_Append(const char *, const char *);
void Global_Delete(const char *);
void Global_Set_ReadOnly(const char *, const char *);
-const char *EvalStack_Details(void);
+void EvalStack_PrintDetails(void);
/* util.c */
typedef void (*SignalProc)(int);
diff --git a/mk/ChangeLog b/mk/ChangeLog
index 0e521d9ecce6..4274d9d3483b 100644
--- a/mk/ChangeLog
+++ b/mk/ChangeLog
@@ -1,3 +1,120 @@
+2025-01-10 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * rust.mk: use RUST_LIBS and RUST_PROGS
+
+2025-01-01 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20250101
+
+ * use W flag to :S and :C rather than :tW
+
+2024-12-16 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * rust.mk: add RUSTFLAGS if needed
+
+2024-12-12 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * init.mk (OBJS_SRCS_FILTER): apply this as
+ ${OBJS_SRCS_FILTER:ts:} as we do in FreeBSD.
+
+2024-12-03 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20241202
+
+ * setopts.sh: needed by newlog.sh
+
+2024-11-22 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * meta.sys.mk: add META_MODE_XTRAS to META_MODE to make it
+ easier to add things like 'env' when debugging.
+
+ * install-mk (MK_VERSION): 20241122
+
+ * rust.mk: rename CARGO* to RUST_CARGO* so I don't feel
+ like this makefile should be renamed to cargo.mk
+
+2024-11-11 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * dirdeps.mk: add DIRDEPS_CACHED_ENV to dirdeps-cached and
+ DIRDEP_USE_EPILOGUE to _DIRDEP_USE
+
+2024-10-30 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * meta.sys.mk: if MK_META_ERROR_TARGET is yes and NEWLOG_SH is
+ set, and ERROR_LOGDIR already exists, hook _rotateErrorLog to
+ .BEGIN target.
+
+2024-10-27 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * options.mk: add support for DEBUG_OPTIONS (similar to
+ DEBUG_DIRDEPS) to allow us to see where options get set.
+ Eg. DEBUG_OPTIONS="STAGING*" gives:
+
+ bmake[1]: "mk/options.mk" line 89: sys.mk: MK_STAGING=yes (MK_DIRDEPS_BUILD=no)
+ bmake[1]: "mk/options.mk" line 66: local.init.mk: MK_STAGING=yes
+ bmake[1]: "mk/options.mk" line 66: local.init.mk: MK_STAGING_PROG=no
+ bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_MAN=yes (MK_STAGING=yes)
+ bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_PROG=no (MK_STAGING=yes)
+ bmake[1]: "mk/options.mk" line 89: own.mk: MK_STAGING_RUST=no (MK_STAGING_PROG=no)
+
+ * own.mk: fix setting of STAGE_OBJTOP (normally set by sys.dirdeps.mk)
+
+2024-10-26 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * rust.mk: add some documentation and support for staging
+
+2024-10-25 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * rust.mk: a means of integrating Rust projects into a larger build.
+
+2024-10-18 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * dirdeps-targets.mk: if DEBUG_DIRDEPS_TARGETS and we found
+ STATIC_DIRDEPS_CACHE, report its relative path.
+
+2024-09-30 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * dirdeps.mk: tweak the debug message for "Loading" a
+ Makefile.depend file, always report what the actual makefile is
+ with the DIRDEP it is for.
+ Remove the redundant "Looking" message.
+
+2024-09-26 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * meta2deps.py: when raising AssertionError include meta file name
+ with $SB trimmed if possible.
+
+2024-09-23 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * meta2deps.py: replace assert() with raise AssertionError when we
+ detect missing eXits, to ensure a meaningful message gets into
+ log.
+
+2024-09-21 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20240921
+
+ * FILES: add genfiles.mk
+
+2024-09-20 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20240920
+
+ * cython.mk: Get PYTHON_VERSION from PYTHON
+
+2024-08-31 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * subdir.mk: add ${SUBDIR.yes} - allows for SUBDIR.${MK_*}
+ and handle subdir with '-' in its name.
+
+2024-08-23 Simon J Gerraty <sjg@beast.crufty.net>
+
+ * install-mk (MK_VERSION): 20240820
+
+ * links.mk: Allow a filter to be applied to SYMLINKS etc.
+ It is up to [BUILD_][SYM]LINKS_FILTER to do something sane.
+ Also only claim we are making a symlink if the value changed.
+
2024-06-22 Simon J Gerraty <sjg@beast.crufty.net>
* install-mk (MK_VERSION): 20240616
diff --git a/mk/FILES b/mk/FILES
index 39ac101d36f4..85d8b15dbd44 100644
--- a/mk/FILES
+++ b/mk/FILES
@@ -15,6 +15,7 @@ doc.mk
dpadd.mk
files.mk
final.mk
+genfiles.mk
host-target.mk
host.libnames.mk
inc.mk
@@ -42,7 +43,9 @@ prlist.mk
prog.mk
progs.mk
rst2htm.mk
+rust.mk
scripts.mk
+setopts.sh
srctop.mk
stage-install.sh
subdir.mk
diff --git a/mk/README b/mk/README
index 161426cfcd0c..7ffc3653c09d 100644
--- a/mk/README
+++ b/mk/README
@@ -1,9 +1,9 @@
-# $Id: README,v 1.2 2020/08/19 17:51:53 sjg Exp $
+# $Id: README,v 1.3 2024/12/10 22:15:02 sjg Exp $
-This directory contains some macro's derrived from the NetBSD bsd.*.mk
-macros. They have the same names but without the bsd., separate macro
-files are needed to ensure we can make them do what we want for
-builing things outside of /usr/src. Nearly all the comments below
+This directory contains some makefiles derrived from the NetBSD bsd.*.mk
+ones. They have the same names but without the bsd., separate
+makefiles are needed to ensure we can make them do what we want for
+building things outside of /usr/src. Nearly all the comments below
apply.
# $NetBSD: bsd.README,v 1.18 1997/01/13 00:54:23 mark Exp $
diff --git a/mk/cython.mk b/mk/cython.mk
index 3c28eb0a4525..8eda318e187c 100644
--- a/mk/cython.mk
+++ b/mk/cython.mk
@@ -1,9 +1,9 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# RCSid:
-# $Id: cython.mk,v 1.9 2024/02/17 17:26:57 sjg Exp $
+# $Id: cython.mk,v 1.10 2024/09/20 06:16:41 sjg Exp $
#
-# @(#) Copyright (c) 2014, Simon J. Gerraty
+# @(#) Copyright (c) 2014-2024, Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
@@ -19,24 +19,29 @@
# pyprefix is where python bits are
# which may not be where we want to put ours (prefix)
.if exists(/usr/pkg/include)
-pyprefix?= /usr/pkg
+pyprefix ?= /usr/pkg
.endif
-pyprefix?= /usr/local
+pyprefix ?= /usr/local
-PYTHON_VERSION?= 2.7
-PYTHON_H?= ${pyprefix}/include/python${PYTHON_VERSION}/Python.h
-PYVERSION:= ${PYTHON_VERSION:C,\..*,,}
+PYTHON ?= python3
+.if empty(PYTHON_VERSION)
+PYTHON_VERSION != ${PYTHON} --version | sed 's,Python \([2-9]\.[0-9][0-9]*\).*,\1,'
+.export PYTHON_VERSION
+.endif
+PYTHON_H ?= ${pyprefix}/include/python${PYTHON_VERSION}/Python.h
+PYVERSION := ${PYTHON_VERSION:C,\..*,,}
CFLAGS+= -I${PYTHON_H:H}
# conf.host_target() is limited to uname -m rather than uname -p
-_HOST_MACHINE!= uname -m
+# so we cannot assume it will always match HOST_TARGET
+_HOST_MACHINE != uname -m
.if ${HOST_TARGET:M*${_HOST_MACHINE}} == ""
-PY_HOST_TARGET:= ${HOST_TARGET:S,${_HOST_ARCH:U${uname -p:L:sh}}$,${_HOST_MACHINE},}
+PY_HOST_TARGET := ${HOST_TARGET:S,${_HOST_ARCH:U${uname -p:L:sh}}$,${_HOST_MACHINE},}
.endif
-COMPILE.c?= ${CC} -c ${CFLAGS}
-PICO?= .pico
+COMPILE.c ?= ${CC} -c ${CFLAGS}
+PICO ?= .pico
.SUFFIXES: ${PICO} .c
@@ -47,25 +52,25 @@ PICO?= .pico
.if !empty(CYTHON_MODULE_NAME)
CYTHON_MODULE = ${CYTHON_MODULE_NAME}${CYTHON_PYVERSION}.so
-CYTHON_SRCS?= ${CYTHON_MODULE_NAME}.pyx
+CYTHON_SRCS ?= ${CYTHON_MODULE_NAME}.pyx
# this is where we save generated src
-CYTHON_SAVEGENDIR?= ${.CURDIR}/gen
+CYTHON_SAVEGENDIR ?= ${.CURDIR}/gen
# set this empty if you don't want to handle multiple versions
.if !defined(CYTHON_PYVERSION)
-CYTHON_PYVERSION:= ${PYVERSION}
+CYTHON_PYVERSION := ${PYVERSION}
.endif
-CYTHON_GENSRCS= ${CYTHON_SRCS:R:S,$,${CYTHON_PYVERSION}.c,}
-SRCS+= ${CYTHON_GENSRCS}
+CYTHON_GENSRCS = ${CYTHON_SRCS:R:S,$,${CYTHON_PYVERSION}.c,}
+SRCS += ${CYTHON_GENSRCS}
.SUFFIXES: .pyx .c .So
-CYTHON?= ${pyprefix}/bin/cython
+CYTHON ?= ${pyprefix}/bin/cython
# if we don't have cython we can use pre-generated srcs
-.if ${type ${CYTHON} 2> /dev/null || echo:L:sh:M/*} == ""
+.if empty(CYTHON) || !exists(${CYTHON})
.PATH: ${CYTHON_SAVEGENDIR}
.else
@@ -98,6 +103,6 @@ install-cython-module: ${CYTHON_MODULE}
${INSTALL} -d ${DESTDIR}${MODULE_BINDIR}
${INSTALL} -m 755 ${.ALLSRC} ${DESTDIR}${MODULE_BINDIR}
-CLEANFILES+= *${PICO} ${CYTHON_MODULE}
+CLEANFILES += *${PICO} ${CYTHON_MODULE}
.endif
diff --git a/mk/dirdeps-targets.mk b/mk/dirdeps-targets.mk
index 9e3fb814fada..a8a547c0ce9b 100644
--- a/mk/dirdeps-targets.mk
+++ b/mk/dirdeps-targets.mk
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: BSD-2-Clause
#
# RCSid:
-# $Id: dirdeps-targets.mk,v 1.27 2024/02/25 19:12:13 sjg Exp $
+# $Id: dirdeps-targets.mk,v 1.28 2024/10/19 00:47:38 sjg Exp $
#
# @(#) Copyright (c) 2019-2020 Simon J. Gerraty
#
@@ -160,6 +160,9 @@ MK_DIRDEPS_CACHE = yes
.endfor
.if defined(STATIC_DIRDEPS_CACHE)
.export STATIC_DIRDEPS_CACHE
+.if !empty(DEBUG_DIRDEPS_TARGETS)
+.info STATIC_DIRDEPS_CACHE=${STATIC_DIRDEPS_CACHE:S,${SRCTOP}/,,}
+.endif
.endif
.endif
diff --git a/mk/dirdeps.mk b/mk/dirdeps.mk
index 2a9d2ac92102..b281d15ec346 100644
--- a/mk/dirdeps.mk
+++ b/mk/dirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: dirdeps.mk,v 1.170 2024/06/24 02:21:00 sjg Exp $
+# $Id: dirdeps.mk,v 1.175 2025/01/05 01:16:19 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -152,7 +152,7 @@
# any other DIRDEP.
#
# This allows for adding TESTS to the build, such that the build
-# if any test fails, but without the risk of introducing
+# will fail if any test fails, but without the risk of introducing
# circular dependencies.
now_utc ?= ${%s:L:localtime}
@@ -445,6 +445,7 @@ _DIRDEP_USE: .USE .MAKE
TARGET_SPEC=${.TARGET:E} \
MACHINE=${.TARGET:E} \
${DIRDEP_MAKE} -C ${DIRDEP_DIR} ${DIRDEP_TARGETS} || exit 1; \
+ ${DIRDEP_USE_EPILOGUE} \
break; \
done
@@ -568,7 +569,7 @@ BUILD_DIRDEPS = no
dirdeps: dirdeps-cached
dirdeps-cached: ${DIRDEPS_CACHE} .MAKE
@echo "${TRACER}Using ${DIRDEPS_CACHE}"
- @MAKELEVEL=${.MAKE.LEVEL} \
+ @${DIRDEPS_CACHED_ENV} MAKELEVEL=${.MAKE.LEVEL} \
TARGET_SPEC=${TARGET_SPEC} \
${TARGET_SPEC_VARS:@v@$v=${$v}@} \
${.MAKE} -C ${_CURDIR} -f ${DIRDEPS_CACHE} \
@@ -606,10 +607,10 @@ ${DIRDEPS_CACHE}: .META .NOMETA_CMP
BUILD_DIRDEPS_CACHE=yes \
.MAKE.DEPENDFILE=.none \
${"${DEBUG_DIRDEPS:Nno}":?DEBUG_DIRDEPS='${DEBUG_DIRDEPS}':} \
- ${.MAKEFLAGS:tW:S,-D ,-D,g:tw:M*WITH*} \
- ${.MAKEFLAGS:tW:S,-d ,-d,g:tw:M-d*} \
+ ${.MAKEFLAGS:S,-D ,-D,gW:M*WITH*} \
+ ${.MAKEFLAGS:S,-d ,-d,gW:M-d*} \
3>&1 1>&2 | sed 's,${SRCTOP},_{SRCTOP},g;s,_{SRCTOP}/_{SRCTOP},_{SRCTOP},g;s,_{,$${,g' >> ${.TARGET}.new && \
- mv ${.TARGET}.new ${.TARGET}
+ { ${BUILD_DIRDEPS_EPILOGUE} mv ${.TARGET}.new ${.TARGET}; }
.endif
.endif
@@ -887,16 +888,13 @@ _m := ${.MAKE.DEPENDFILE_PREFERENCE:T:S;${TARGET_SPEC}$;${d:E};:C;${MACHINE}((,.
.if !empty(_m)
# M_dep_qual_fixes isn't geared to Makefile.depend
_qm := ${_m:C;(\.depend)$;\1.${d:E};:${M_dep_qual_fixes.${d:E}:U${M_dep_qual_fixes}:ts:}}
-.if ${_debug_search}
-.info Looking for ${_qm}
-.endif
# set this "just in case"
# we can skip :tA since we computed the path above
DEP_RELDIR := ${_m:H:S,^${SRCTOP}/,,}
# and reset this
DIRDEPS =
-.if ${_debug_reldir} && ${_qm} != ${_m}
-.info loading ${_m:S,${SRCTOP}/,,} for ${_dr}
+.if ${_debug_search} || ${_debug_reldir}
+.info Loading ${_m:S,${SRCTOP}/,,} for ${_dr}
.endif
.include <${_m}>
.else
diff --git a/mk/gendirdeps.mk b/mk/gendirdeps.mk
index 5d54aa232152..53e736da3391 100644
--- a/mk/gendirdeps.mk
+++ b/mk/gendirdeps.mk
@@ -1,4 +1,4 @@
-# $Id: gendirdeps.mk,v 1.50 2023/11/04 16:47:34 sjg Exp $
+# $Id: gendirdeps.mk,v 1.51 2025/01/05 01:16:19 sjg Exp $
# SPDX-License-Identifier: BSD-2-Clause
#
@@ -237,7 +237,7 @@ dir_list != cd ${_OBJDIR} && \
sed ${GENDIRDEPS_SEDCMDS}
.if ${dir_list:M*ERROR\:*} != ""
-.warning ${dir_list:tW:C,.*(ERROR),\1,}
+.warning ${dir_list:C,.*(ERROR),\1,W}
.warning Skipping ${_DEPENDFILE:S,${SRCTOP}/,,}
# we are not going to update anything
.else
diff --git a/mk/genfiles.mk b/mk/genfiles.mk
new file mode 100644
index 000000000000..d35e8be74763
--- /dev/null
+++ b/mk/genfiles.mk
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# $Id: genfiles.mk,v 1.3 2024/09/21 21:14:19 sjg Exp $
+#
+# @(#) Copyright (c) 2024, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# Pipe the sources though egrep -v if EXCLUDES.${.TARGET} is defined
+# and/or sed if SED_CMDS.${.TARGET} is defined
+# Note: this works best in meta mode as any change to EXCLUDES or
+# SED_CMDS will make the target out-of-date.
+_GENFILES_USE: .USE
+ @cat ${SRCS.${.TARGET}:U${.ALLSRC:u}} \
+ ${EXCLUDES.${.TARGET}:D| ${EGREP:Uegrep} -v '${EXCLUDS.${.TARGET}:ts|}'} \
+ ${SED_CMDS.${.TARGET}:D| ${SED:Used} ${SED_CMDS.${.TARGET}}} \
+ > ${.TARGET}
diff --git a/mk/init.mk b/mk/init.mk
index b6619721c943..acccf8d5cf6b 100644
--- a/mk/init.mk
+++ b/mk/init.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: init.mk,v 1.38 2024/04/09 17:18:24 sjg Exp $
+# $Id: init.mk,v 1.39 2024/12/12 19:56:36 sjg Exp $
#
# @(#) Copyright (c) 2002-2024, Simon J. Gerraty
#
@@ -41,7 +41,14 @@ PICO ?= .pico
# SRCS which do not end up in OBJS
NO_OBJS_SRCS_SUFFIXES ?= .h ${CCM_SUFFIXES} .sh
-OBJS_SRCS_FILTER += ${NO_OBJS_SRCS_SUFFIXES:@x@N*$x@:ts:}
+OBJS_SRCS_PRE_FILTER += ${NO_OBJS_SRCS_SUFFIXES:@x@N*$x@}
+# makefiles that actually *want* .o's in subdirs
+# (it can be useful if multiple SRCS have same basename)
+# can just set OBJS_SRCS_FILTER =
+# we apply this as ${OBJS_SRCS_FILTER:ts:}
+OBJS_SRCS_FILTER ?= T
+OBJS_SRCS_FILTER += ${OBJS_SRCS_PRE_FILTER}
+OBJS_SRCS_FILTER += R
.if defined(PROG_CXX) || ${SRCS:Uno:${CXX_SUFFIXES:S,^,N*,:ts:}} != ${SRCS:Uno:N/}
_CCLINK ?= ${CXX}
diff --git a/mk/install-mk b/mk/install-mk
index bb150e3041a3..b455832b7726 100755..100644
--- a/mk/install-mk
+++ b/mk/install-mk
@@ -59,7 +59,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: install-mk,v 1.255 2024/06/24 02:21:00 sjg Exp $
+# $Id: install-mk,v 1.262 2025/01/05 01:16:19 sjg Exp $
#
# @(#) Copyright (c) 1994-2024 Simon J. Gerraty
#
@@ -74,7 +74,7 @@
# sjg@crufty.net
#
-MK_VERSION=20240616
+MK_VERSION=20250101
OWNER=
GROUP=
MODE=444
diff --git a/mk/lib.mk b/mk/lib.mk
index 95f95118c028..3f6a749a12d1 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -1,4 +1,4 @@
-# $Id: lib.mk,v 1.84 2024/02/19 00:06:19 sjg Exp $
+# $Id: lib.mk,v 1.85 2024/12/12 19:56:36 sjg Exp $
# should be set properly in sys.mk
_this ?= ${.PARSEFILE:S,bsd.,,}
@@ -395,13 +395,15 @@ realbuild: ${_LIBS}
all: _SUBDIRUSE
-OBJS_SRCS = ${SRCS:${OBJS_SRCS_FILTER}}
-
-.for s in ${OBJS_SRCS:M*/*}
-${.o ${PICO} .po .lo:L:@o@${s:T:R}$o@}: $s
+.for s in ${SRCS:${OBJS_SRCS_PRE_FILTER:ts:}:M*/*}
+${.o .po .lo:L:@o@${s:${OBJS_SRCS_FILTER:ts:}}$o@}: $s
.endfor
-OBJS+= ${OBJS_SRCS:T:R:S/$/.o/g}
+OBJS_SRCS = ${SRCS:${OBJS_SRCS_FILTER:ts:}}
+.if !empty(OBJS_SRCS)
+OBJS+= ${OBJS_SRCS:S/$/.o/g}
+.endif
+
.NOPATH: ${OBJS}
.if ${MK_LIBTOOL} == "yes"
diff --git a/mk/links.mk b/mk/links.mk
index cbf9685ccd37..dfcedec7a434 100644
--- a/mk/links.mk
+++ b/mk/links.mk
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: links.mk,v 1.8 2024/02/17 17:26:57 sjg Exp $
+# $Id: links.mk,v 1.10 2024/08/23 21:24:27 sjg Exp $
#
-# @(#) Copyright (c) 2005, Simon J. Gerraty
+# @(#) Copyright (c) 2005-2024, Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
@@ -16,37 +16,37 @@
#
# some platforms need something special
-LN?= ln
-ECHO?= echo
+LN ?= ln
+ECHO ?= echo
-LINKS?=
-SYMLINKS?=
+LINKS ?=
+SYMLINKS ?=
-__SYMLINK_SCRIPT= \
- ${ECHO} "$$t -> $$l"; \
+__SYMLINK_SCRIPT = \
case `'ls' -l $$t 2> /dev/null` in \
*"> $$l") ;; \
*) \
+ ${ECHO} "$$t -> $$l"; \
mkdir -p `dirname $$t`; \
rm -f $$t; \
${LN} -s $$l $$t;; \
esac
-__LINK_SCRIPT= \
+__LINK_SCRIPT = \
${ECHO} "$$t -> $$l"; \
mkdir -p `dirname $$t`; \
rm -f $$t; \
${LN} $$l $$t
-_SYMLINKS_SCRIPT= \
+_SYMLINKS_SCRIPT = \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=${DESTDIR}$$1; shift; \
${__SYMLINK_SCRIPT}; \
done; :;
-_LINKS_SCRIPT= \
+_LINKS_SCRIPT = \
while test $$\# -ge 2; do \
l=${DESTDIR}$$1; shift; \
t=${DESTDIR}$$1; shift; \
@@ -54,21 +54,21 @@ _LINKS_SCRIPT= \
done; :;
_SYMLINKS_USE: .USE
- @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_SYMLINKS_SCRIPT}
+ @set ${$@_SYMLINKS:U${SYMLINKS}:${SYMLINKS_FILTER:U:ts:}}; ${_SYMLINKS_SCRIPT}
_LINKS_USE: .USE
- @set ${$@_LINKS:U${LINKS}}; ${_LINKS_SCRIPT}
+ @set ${$@_LINKS:U${LINKS}:${LINKS_FILTER:U:ts:}}; ${_LINKS_SCRIPT}
# sometimes we want to ensure DESTDIR is ignored
-_BUILD_SYMLINKS_SCRIPT= \
+_BUILD_SYMLINKS_SCRIPT = \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=$$1; shift; \
${__SYMLINK_SCRIPT}; \
done; :;
-_BUILD_LINKS_SCRIPT= \
+_BUILD_LINKS_SCRIPT = \
while test $$\# -ge 2; do \
l=$$1; shift; \
t=$$1; shift; \
@@ -76,7 +76,7 @@ _BUILD_LINKS_SCRIPT= \
done; :;
_BUILD_SYMLINKS_USE: .USE
- @set ${$@_SYMLINKS:U${SYMLINKS}}; ${_BUILD_SYMLINKS_SCRIPT}
+ @set ${$@_SYMLINKS:U${SYMLINKS}:${BUILD_SYMLINKS_FILTER:U:ts:}}; ${_BUILD_SYMLINKS_SCRIPT}
_BUILD_LINKS_USE: .USE
- @set ${$@_LINKS:U${LINKS}}; ${_BUILD_LINKS_SCRIPT}
+ @set ${$@_LINKS:U${LINKS}:${BUILD_LINKS_FILTER:U:ts:}}; ${_BUILD_LINKS_SCRIPT}
diff --git a/mk/meta.sys.mk b/mk/meta.sys.mk
index 6e4216ab5383..1104204dc8c9 100644
--- a/mk/meta.sys.mk
+++ b/mk/meta.sys.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: meta.sys.mk,v 1.54 2024/03/10 15:53:51 sjg Exp $
+# $Id: meta.sys.mk,v 1.56 2024/11/22 23:51:48 sjg Exp $
#
# @(#) Copyright (c) 2010-2023, Simon J. Gerraty
@@ -40,6 +40,11 @@ META_MODE += nofilemon
MKDEP_MK ?= auto.dep.mk
.endif
+# META_MODE_XTRAS makes it easier to add things like 'env'
+# from the command line when debugging
+# :U avoids problems from := below
+META_MODE += ${META_MODE_XTRAS:U}
+
.MAKE.MODE ?= ${META_MODE}
_filemon := ${.MAKE.PATH_FILEMON:U/dev/filemon}
@@ -101,6 +106,12 @@ SB = ${SRCTOP:H}
ERROR_LOGDIR ?= ${SB}/error
meta_error_log = ${ERROR_LOGDIR}/meta-${.MAKE.PID}.log
+.if ${.MAKE.LEVEL} == 0 && !empty(NEWLOG_SH) && exists(${ERROR_LOGDIR})
+.BEGIN: _rotateErrorLog
+_rotateErrorLog: .NOMETA .NOTMAIN
+ @${NEWLOG_SH} -d -S -n ${ERROR_LOG_GENS:U4} ${ERROR_LOGDIR}
+.endif
+
.ERROR: _metaError
# We are interested here in the target(s) that caused the build to fail.
# We want to ignore targets that were "aborted" due to failure
diff --git a/mk/meta2deps.py b/mk/meta2deps.py
index f188d0f01de8..44c752d0e7eb 100755
--- a/mk/meta2deps.py
+++ b/mk/meta2deps.py
@@ -39,7 +39,7 @@ We only pay attention to a subset of the information in the
SPDX-License-Identifier: BSD-2-Clause
RCSid:
- $Id: meta2deps.py,v 1.47 2024/02/17 17:26:57 sjg Exp $
+ $Id: meta2deps.py,v 1.50 2024/09/27 00:08:36 sjg Exp $
Copyright (c) 2011-2020, Simon J. Gerraty
Copyright (c) 2011-2017, Juniper Networks, Inc.
@@ -294,6 +294,7 @@ class MetaFile:
if not _objroot in self.objroots:
self.objroots.append(_objroot)
+ self.sb = conf.get('SB', '')
# we want the longest match
self.srctops.sort(reverse=True)
self.objroots.sort(reverse=True)
@@ -461,6 +462,10 @@ class MetaFile:
if self.curdir:
self.seenit(self.curdir) # we ignore this
+ if self.sb and self.name.startswith(self.sb):
+ error_name = self.name.replace(self.sb+'/','')
+ else:
+ error_name = self.name
interesting = '#CEFLRVX'
for line in f:
self.line += 1
@@ -550,9 +555,9 @@ class MetaFile:
self.parse_path(path, cwd, w[0], w)
if version == 0:
- raise AssertionError('missing filemon data')
+ raise AssertionError('missing filemon data: {}'.format(error_name))
if not eof_token:
- raise AssertionError('truncated filemon data')
+ raise AssertionError('truncated filemon data: {}'.format(error_name))
setid_pids = []
# self.pids should be empty!
@@ -570,7 +575,8 @@ class MetaFile:
print("ERROR: missing eXit for {} pid {}".format(path, pid))
for pid in setid_pids:
del self.pids[pid]
- assert(len(self.pids) == 0)
+ if len(self.pids) > 0:
+ raise AssertionError('bad filemon data - missing eXits: {}'.format(error_name))
if not file:
f.close()
@@ -714,6 +720,8 @@ def main(argv, klass=MetaFile, xopts='', xoptf=None):
'EXCLUDES': [],
}
+ conf['SB'] = os.getenv('SB', '')
+
try:
machine = os.environ['MACHINE']
if machine:
diff --git a/mk/options.mk b/mk/options.mk
index 363fc53baf14..07a6e0e340b2 100644
--- a/mk/options.mk
+++ b/mk/options.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: options.mk,v 1.20 2024/02/17 17:26:57 sjg Exp $
+# $Id: options.mk,v 1.22 2024/10/27 17:33:03 sjg Exp $
#
# @(#) Copyright (c) 2012, Simon J. Gerraty
#
@@ -62,6 +62,9 @@ ${OPTION_PREFIX}${o:H} ?= no
${OPTION_PREFIX}${o:H} ?= yes
.endif
.endif
+.if defined(DEBUG_OPTIONS) && ${DEBUG_OPTIONS:@x@${o:H:M$x}@} != ""
+.info ${.INCLUDEDFROMFILE}: ${OPTION_PREFIX}${o:H}=${${OPTION_PREFIX}${o:H}}
+.endif
.endfor
# OPTIONS_DEFAULT_DEPENDENT += FOO_UTILS/FOO
@@ -82,6 +85,9 @@ ${OPTION_PREFIX}${o:H} ?= no
.else
${OPTION_PREFIX}${o:H} ?= ${${OPTION_PREFIX}${o:T}}
.endif
+.if defined(DEBUG_OPTIONS) && ${DEBUG_OPTIONS:@x@${o:H:M$x}@} != ""
+.info ${.INCLUDEDFROMFILE}: ${OPTION_PREFIX}${o:H}=${${OPTION_PREFIX}${o:H}} (${OPTION_PREFIX}${o:T}=${${OPTION_PREFIX}${o:T}})
+.endif
.endfor
# allow displaying/describing set options
diff --git a/mk/own.mk b/mk/own.mk
index 72b2f70d4bbe..f3014f9e7adf 100644
--- a/mk/own.mk
+++ b/mk/own.mk
@@ -1,4 +1,4 @@
-# $Id: own.mk,v 1.48 2024/04/09 21:52:52 sjg Exp $
+# $Id: own.mk,v 1.51 2024/11/12 17:40:13 sjg Exp $
# should be set properly in sys.mk
_this ?= ${.PARSEFILE:S,bsd.,,}
@@ -71,6 +71,7 @@ OPTIONS_DEFAULT_NO+= DPADD_MK
# process options
OPTIONS_DEFAULT_NO+= \
+ DEBUG \
INSTALL_AS_USER \
GPROF \
PROG_LDORDER_MK \
@@ -96,6 +97,7 @@ OPTIONS_DEFAULT_YES+= \
OPTIONS_DEFAULT_DEPENDENT+= \
CATPAGES/MAN \
+ DEBUG_RUST/DEBUG \
LDORDER_MK/PROG_LDORDER_MK \
OBJDIRS/OBJ \
PICINSTALL/LINKLIB \
@@ -103,6 +105,7 @@ OPTIONS_DEFAULT_DEPENDENT+= \
PROFILE/LINKLIB \
STAGING_MAN/STAGING \
STAGING_PROG/STAGING \
+ STAGING_RUST/STAGING_PROG \
.include <options.mk>
@@ -248,7 +251,7 @@ TARGET_SPEC_VARS_REV = ${TARGET_SPEC_VARS}
.endif
.if ${MK_STAGING} == "yes"
STAGE_ROOT?= ${OBJROOT}/stage
-STAGE_OBJTOP?= ${STAGE_ROOT}/${TARGET_SPEC_VARS_REV:ts/}
+STAGE_OBJTOP?= ${STAGE_ROOT}/${TARGET_SPEC_VARS_REV:@v@${$v}@:ts/}
.endif
.endif
diff --git a/mk/prog.mk b/mk/prog.mk
index aac2a4d3da28..119645c49859 100644
--- a/mk/prog.mk
+++ b/mk/prog.mk
@@ -1,4 +1,4 @@
-# $Id: prog.mk,v 1.44 2024/02/19 00:06:19 sjg Exp $
+# $Id: prog.mk,v 1.45 2024/12/12 19:56:36 sjg Exp $
# should be set properly in sys.mk
_this ?= ${.PARSEFILE:S,bsd.,,}
@@ -98,12 +98,14 @@ SRCS = ${PROG}.c
.endif
SRCS ?= ${PROG}.c
-OBJS_SRCS = ${SRCS:${OBJS_SRCS_FILTER}}
-.for s in ${OBJS_SRCS:M*/*}
-${.o .po .lo:L:@o@${s:T:R}$o@}: $s
+
+.for s in ${SRCS:${OBJS_SRCS_PRE_FILTER:ts:}:M*/*}
+${.o .po .lo:L:@o@${s:${OBJS_SRCS_FILTER:ts:}}$o@}: $s
.endfor
+
+OBJS_SRCS = ${SRCS:${OBJS_SRCS_FILTER:ts:}}
.if !empty(OBJS_SRCS)
-OBJS+= ${OBJS_SRCS:T:R:S/$/.o/g}
+OBJS+= ${OBJS_SRCS:S/$/.o/g}
LOBJS+= ${LSRCS:.c=.ln} ${SRCS:M*.c:.c=.ln}
.endif
diff --git a/mk/rust.mk b/mk/rust.mk
new file mode 100644
index 000000000000..5fc340239c30
--- /dev/null
+++ b/mk/rust.mk
@@ -0,0 +1,203 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# RCSid:
+# $Id: rust.mk,v 1.37 2025/01/11 03:17:36 sjg Exp $
+#
+# @(#) Copyright (c) 2024, Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+##
+# This makefile is used when a build includes one or more Rust projects.
+#
+# We first include local.rust.mk to allow for customization.
+# You can get very fancy - the logic/functionality here is minimal but
+# can be extended via local.rust.mk
+#
+# If RUST_PROJECT_DIR (where we find Cargo.toml) is not set, we will
+# make it ${.CURDIR:C,/src.*,,} actually we use
+# ${SRCTOP}/${RELDIR:C,/src.*,,} to ensure we don't confuse ${SRCTOP}
+# with ${RUST_PROJECT_DIR}/src.
+#
+# If ${.OBJDIR} is not ${.CURDIR} we will default CARGO_TARGET_DIR
+# to ${.OBJDIR}.
+#
+# First, if ${.CURDIR} is a subdir of ${RUST_PROJECT_DIR} (will happen
+# if an Emacs user does 'M-x compile' while visiting a src file) we
+# will need to adjust ${.OBJDIR} (and hence CARGO_TARGET_DIR).
+#
+# We assume that RUST_CARGO will be used to build Rust projects,
+# so we default RUST_CARGO_PROJECT_DIR to ${RUST_PROJECT_DIR} and
+# provide a _CARGO_USE that we automatically associate with
+# targets named 'cargo.*' the default is 'cargo.build'.
+#
+# _CARGO_USE will chdir to ${RUST_CARGO_PROJECT_DIR} and run
+# ${RUST_CARGO} with ENV, FLAGS and ARGS variables derived from
+# ${.TARGET:E:tu} so in the case of 'cargo.build' we get:
+# RUST_CARGO_BUILD_ENV, RUST_CARGO_BUILD_FLAGS and RUST_CARGO_BUILD_ARGS
+#
+# _CARGO_USE will "just work" for additional targets like
+# 'cargo.test', 'cargo.clippy', ... which will run '${RUST_CARGO} test',
+# '${RUST_CARGO} clippy' etc.
+#
+# If MK_META_MODE is "yes" 'cargo.build' will touch ${.TARGET}
+# so the default make rules will not consider it always out-of-date.
+# In META MODE, 'bmake' will know if anything changed that should
+# cause the target to be re-built.
+#
+# If MK_STAGING_RUST is "yes" we will stage the binary we
+# built to a suitable location under ${STAGE_OBJTOP}.
+#
+
+all:
+.MAIN: all
+
+# allow for customization
+.-include <local.rust.mk>
+
+RUST_CARGO ?= cargo
+RUSTC ?= rustc
+.if ${.CURDIR} == ${SRCTOP}
+RELDIR ?= .
+.else
+RELDIR ?= ${.CURDIR:S,${SRCTOP}/,,}
+.endif
+.if empty(RUST_PROJECT_DIR)
+# we want this set correctly from anywhere within
+# using RELDIR avoids confusing ${SRCTOP} with ${RUST_PROJECT_DIR}/src
+RUST_PROJECT_DIR := ${SRCTOP}/${RELDIR:C,/src.*,,}
+.if ${RUST_PROJECT_DIR:T:Nsrc:N.} == ""
+RUST_PROJECT_DIR := ${RUST_PROJECT_DIR:H}
+.endif
+.endif
+
+.if ${.OBJDIR} != ${.CURDIR}
+.if ${.CURDIR:M${RUST_PROJECT_DIR}/*} != ""
+# Our .CURDIR is below RUST_PROJECT_DIR and thus our
+# .OBJDIR is likely not what we want either.
+# This can easily happen if in Emacs we do 'M-x compile' while
+# visiting a src file.
+# It is easily fixed.
+__objdir := ${.OBJDIR:S,${.CURDIR:S,${RUST_PROJECT_DIR},,},,}
+.OBJDIR: ${__objdir}
+.endif
+# tell cargo where to drop build artifacts
+CARGO_TARGET_DIR ?= ${.OBJDIR}
+.if !empty(OBJROOT) && exists(${OBJROOT})
+CARGO_HOME_RELDIR ?= rust/cargo_home
+CARGO_HOME ?= ${OBJROOT}/common/${RUST_CARGO_HOME_RELDIR}
+.endif
+.elif ${.CURDIR} != ${RUST_PROJECT_DIR}
+.OBJDIR: ${RUST_PROJECT_DIR}
+.endif
+CARGO_TARGET_DIR ?= target
+
+.if ${MK_DIRDEPS_BUILD:Uno} == "no" || ${.MAKE.LEVEL} > 0
+.export CARGO_HOME CARGO_TARGET_DIR RUST_PROJECT_DIR RUSTC
+
+all: cargo.build
+
+.if empty(RUST_PROJECT_FILES)
+RUST_PROJECT_FILES != find ${RUST_PROJECT_DIR} -type f \( \
+ -name '*.rs' -o \
+ -name Cargo.lock -o \
+ -name Cargo.toml \) | sort
+.endif
+RUST_CARGO_BUILD_DEPS += ${RUST_PROJECT_FILES:U}
+.endif
+
+RUST_CARGO_PROJECT_DIR ?= ${RUST_PROJECT_DIR}
+
+.if ${RUSTC:M/*}
+# make sure we find all the other toolchain bits in the same place
+RUST_CARGO_ENV += PATH=${RUSTC:H}:${PATH}
+
+# cargo clippy needs extra help finding the sysroot
+# https://github.com/rust-lang/rust-clippy/issues/3523
+RUST_CARGO_CLIPPY_ENV += RUSTC_SYSROOT=${${RUSTC} --print sysroot:L:sh}
+.endif
+
+.if ${LDFLAGS:U:M-[BL]*} != ""
+# we may need to tell rustc where to find the native libs needed
+# rustc documents a space after -L so put it back
+RUST_LDFLAGS := ${LDFLAGS:C/(-[BL]) /\1/gW:M-[BL]*:S/-L/& /:S/-B/-C link-arg=&/}
+.endif
+.if !empty(RUST_LDFLAGS)
+RUSTFLAGS += ${RUST_LDFLAGS}
+.endif
+.if !empty(RUSTFLAGS)
+RUST_CARGO_BUILD_ENV += RUSTFLAGS="${RUSTFLAGS}"
+.endif
+
+_CARGO_USE: .USEBEFORE
+ @(cd ${RUST_CARGO_PROJECT_DIR} && ${RUST_CARGO_ENV} \
+ ${RUST_CARGO_${.TARGET:E:tu}_ENV} \
+ ${RUST_CARGO} ${RUST_CARGO_${.TARGET:E:tu}_FLAGS:U${RUST_CARGO_FLAGS}} \
+ ${.TARGET:E} ${RUST_CARGO_${.TARGET:E:tu}_ARGS})
+
+RUST_CARGO_TARGETS += cargo.build
+cargo.build: ${RUST_CARGO_BUILD_DEPS}
+.if ${.OBJDIR} != ${RUST_PROJECT_DIR}
+ test ! -s Cargo.lock || cp -p Cargo.lock ${RUST_CARGO_PROJECT_DIR}
+.endif
+ @${META_COOKIE_TOUCH}
+
+# handle cargo.{run,test,...}
+RUST_CARGO_TARGETS += ${.TARGETS:Mcargo.*}
+${RUST_CARGO_TARGETS:O:u}: _CARGO_USE
+
+.if ${MK_DEBUG_RUST:Uno} == "no" && \
+ ${DEBUG_RUST_DIRS:Unone:@x@${RELDIR:M$x}@} == ""
+RUST_CARGO_BUILD_ARGS += --release
+.endif
+
+.if ${RUST_CARGO_BUILD_ARGS:U:M--release} != ""
+RUST_CARGO_TARGET = release
+.else
+RUST_CARGO_TARGET = debug
+.endif
+
+# do we want cargo.build to depend on cargo.fmt --check ?
+# if user did make cargo.fmt the target would exist by now
+.if ${MK_RUST_CARGO_FMT_CHECK:Uno} == "yes" && !target(cargo.fmt)
+RUST_CARGO_FMT_CHECK_ARGS ?= --check
+RUST_CARGO_FMT_ARGS += ${RUST_CARGO_FMT_CHECK_ARGS}
+cargo.fmt: _CARGO_USE
+cargo.build: cargo.fmt
+.endif
+
+# useful? defaults
+RUST_CARGO_CLIPPY_ARGS ?= -- -D warnings --no-deps
+
+# do we want cargo.clippy to be run after cargo.build?
+.if ${MK_RUST_CARGO_CLIPPY:Uno} == "yes" && !target(cargo.clippy)
+cargo.clippy: _CARGO_USE
+cargo.clippy: cargo.build
+all: cargo.clippy
+.endif
+
+.if !defined(RUST_LIBS)
+RUST_PROGS ?= ${RUST_PROJECT_DIR:T}
+.endif
+.if !empty(RUST_PROGS)
+BINDIR ?= ${prefix}/bin
+# there could be a target triple involved
+RUST_CARGO_TARGET_DIR ?= ${CARGO_TARGET_DIR}
+RUST_CARGO_OUTPUT_DIR ?= ${RUST_CARGO_TARGET_DIR}/${RUST_CARGO_TARGET}
+
+RUST_CARGO_BUILD_OUTPUT_LIST := ${RUST_PROGS:S,^,${RUST_CARGO_OUTPUT_DIR}/,}
+
+${RUST_CARGO_BUILD_OUTPUT_LIST}: cargo.build
+.endif
+
+# for late customizations
+.-include <local.rust.build.mk>
diff --git a/mk/setopts.sh b/mk/setopts.sh
new file mode 100644
index 000000000000..91c65c776438
--- /dev/null
+++ b/mk/setopts.sh
@@ -0,0 +1,175 @@
+:
+# NAME:
+# setopts.sh - set opt_* for shell scripts
+#
+# SYNOPSIS:
+# opt_str=s:a.b^cl,z=
+# opt_a=default
+#
+# . setopts.sh
+#
+# DESCRIPTION:
+# This module sets shell variables for each option specified in
+# "opt_str".
+#
+# If the option is followed by a ``:'' it requires an argument.
+# It defaults to an empty string and specifying that option on
+# the command line overrides the current value.
+#
+# If the option is followed by a ``.'' then it is treated as for
+# ``:'' except that any argument provided on the command line is
+# appended to the current value using the value of "opt_dot" as
+# separator (default is a space).
+#
+# If the option is followed by a ``,'' then it is treated as for
+# a ``.'' except that the separator is "opt_comma" (default ,).
+#
+# If the option is followed by ``='' it requires an argument
+# of the form "var=val" which will be evaluated.
+#
+# If the option is followed by a ``^'' then it is treated as a
+# boolean and defaults to 0.
+#
+# Options that have no qualifier are set to the flag if present
+# otherwise they are unset. That is if '-c' is given then
+# "opt_c" will be set to '-c'.
+#
+# If "opt_assign_eval" is set (and to something other than
+# 'no'), args of the form "var=val" will be evaluated.
+#
+# NOTES:
+# The implementation uses the getopts builtin if available.
+#
+# Also it does not work when loaded via a function call as "$@"
+# will be the args to that function. In such cases set
+# _SETOPTS_DELAY and call 'setopts "$@"; shift $__shift'
+# afterwards.
+#
+# AUTHOR:
+# Simon J. Gerraty <sjg@crufty.net>
+#
+
+# RCSid:
+# $Id: setopts.sh,v 1.13 2023/02/20 19:30:06 sjg Exp $
+#
+# @(#) Copyright (c) 1995-2023 Simon J. Gerraty
+#
+# This file is provided in the hope that it will
+# be of use. There is absolutely NO WARRANTY.
+# Permission to copy, redistribute or otherwise
+# use this file is hereby granted provided that
+# the above copyright notice and this notice are
+# left intact.
+#
+# Please send copies of changes and bug-fixes to:
+# sjg@crufty.net
+#
+
+# the case checks just skip the sed(1) commands unless needed
+case "$opt_str" in
+*\^*) # the only ones we need to set are the booleans x,
+ eval `echo $opt_str | sed -e 's/[^^]*$//' -e 's/[^^]*\([^^]^\)/\1/g' -e 's/\(.\)^/opt_\1=${opt_\1-0}; /g'`
+ ;;
+esac
+case "$opt_str" in
+*[=,.\^]*)
+ _opt_str=`echo $opt_str | sed -e 's/[=,.]/:/g' -e 's/\^//g'`;;
+*) _opt_str=$opt_str;;
+esac
+
+opt_append=${opt_append:-" "}
+opt_dot=${opt_dot:-$opt_append}
+opt_comma=${opt_comma:-,}
+
+set1opt() {
+ o=$1
+ a="$2"
+
+ case "$opt_str" in
+ *${o}:*) eval "opt_$o=\"$a\"";;
+ *${o}.*) eval "opt_$o=\"\${opt_$o}\${opt_$o:+$opt_dot}$a\"";;
+ *${o},*) eval "opt_$o=\"\${opt_$o}\${opt_$o:+$opt_comma}$a\"";;
+ *${o}=*)
+ case "$a" in
+ *=*) eval "$a";;
+ *) Myname=${Myname:-`basename $0 .sh`}
+ echo "$Myname: -$o requires argument of form var=val" >&2
+ exit 1
+ ;;
+ esac
+ ;;
+ *${o}\^*) eval opt_$o=1;;
+ *) eval opt_$o=-$o;;
+ esac
+}
+
+setopts() {
+ __shift=$#
+ # use getopts builtin if we can
+ case `type getopts 2>&1` in
+ *builtin*)
+ : OPTIND=$OPTIND @="$@"
+ while getopts $_opt_str o
+ do
+ case "$o" in
+ \?) exit 1;;
+ esac
+ set1opt $o "$OPTARG"
+ done
+ shift $(($OPTIND - 1))
+ while :
+ do
+ case "$1" in
+ *=*)
+ case "$opt_assign_eval" in
+ ""|no) break;;
+ *) eval "$1"; shift;;
+ esac
+ ;;
+ *) break;;
+ esac
+ done
+ ;;
+ *) # likely not a POSIX shell either
+ # getopt(1) isn't as good
+ set -- `getopt $_opt_str "$@" 2>&1`
+ case "$1" in
+ getopt:)
+ Myname=${Myname:-`basename $0 .sh`}
+ echo "$*" | tr ':' '\012' | sed -e '/^getopt/d' -e 's/ getopt$//' -e "s/^/$Myname:/" -e 's/ --/:/' -e 's/-.*//' 2>&2
+ exit 1
+ ;;
+ esac
+
+ while :
+ do
+ : 1="$1"
+ case "$1" in
+ --) shift; break;;
+ -*)
+ # Most shells give you ' ' in IFS whether you
+ # want it or not, but at least one, doesn't.
+ # So the following gives us consistency.
+ o=`IFS=" -"; set -- $1; echo $*` # lose the '-'
+ set1opt $o "$2"
+ case "$_opt_str" in
+ *${o}:*) shift;;
+ esac
+ ;;
+ *=*) case "$opt_assign_eval" in
+ ""|no) break;;
+ *) eval "$1";;
+ esac
+ ;;
+ *) break;;
+ esac
+ shift
+ done
+ ;;
+ esac
+ # let caller know how many args we consumed
+ __shift=`expr $__shift - $#`
+}
+
+${_SETOPTS_DELAY:+:} setopts "$@"
+${_SETOPTS_DELAY:+:} shift $__shift
diff --git a/mk/subdir.mk b/mk/subdir.mk
index 0feb63af44d2..09542f147826 100644
--- a/mk/subdir.mk
+++ b/mk/subdir.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: subdir.mk,v 1.24 2024/04/10 01:47:23 sjg Exp $
+# $Id: subdir.mk,v 1.27 2024/09/01 05:02:43 sjg Exp $
#
# @(#) Copyright (c) 2002-2024, Simon J. Gerraty
#
@@ -29,7 +29,7 @@ _this ?= ${.PARSEFILE:S,bsd.,,}
.if !target(__${_this}__)
__${_this}__: .NOTMAIN
-.if defined(SUBDIR)
+.if defined(SUBDIR) || defined(SUBDIR.yes)
.if ${.MAKE.LEVEL} == 0 && ${MK_DIRDEPS_BUILD:Uno} == "yes"
.include <meta.subdir.mk>
@@ -52,7 +52,7 @@ MISSING_DIR=echo "Skipping ===> ${.CURDIR}/$$_dir"; exit 0
# our target should be of the form ${_target}-${_dir}
_SUBDIR_USE: .USE
@Exists() { test -f $$1; }; \
- _dir=${.TARGET:C/^.*-//} \
+ _dir=${.TARGET:C/^[^-]*-//} \
_target=${.TARGET:C/-.*//:S/real//:S/.depend/depend/}; \
if ! Exists ${.CURDIR}/$$_dir/[mM]akefile; then \
${MISSING_DIR}; \
@@ -95,9 +95,11 @@ SUBDIR_TARGETS += \
tags \
etags
-.if ${SUBDIR} == "@auto"
+.if ${SUBDIR:U} == "@auto"
SUBDIR = ${echo ${.CURDIR}/*/[Mm]akefile:L:sh:H:T:O:N\*}
.endif
+# allow for things like SUBDIR.${MK_TESTS}
+SUBDIR += ${SUBDIR.yes:U}
__subdirs =
.for d in ${SUBDIR}
diff --git a/mk/sys.mk b/mk/sys.mk
index b950d991e321..cf6ef061f406 100644
--- a/mk/sys.mk
+++ b/mk/sys.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: sys.mk,v 1.60 2024/02/17 17:26:57 sjg Exp $
+# $Id: sys.mk,v 1.61 2024/10/30 23:46:26 sjg Exp $
#
# @(#) Copyright (c) 2003-2023, Simon J. Gerraty
#
@@ -97,6 +97,7 @@ OPTIONS_DEFAULT_NO += \
OPTIONS_DEFAULT_DEPENDENT += \
AUTO_OBJ/DIRDEPS_BUILD \
+ META_ERROR_TARGET/DIRDEPS_BUILD \
META_MODE/DIRDEPS_BUILD \
STAGING/DIRDEPS_BUILD \
STATIC_DIRDEPS_CACHE/DIRDEPS_CACHE \
diff --git a/mk/sys.vars.mk b/mk/sys.vars.mk
index d8e0dd4f2930..49d1a71b1d98 100644
--- a/mk/sys.vars.mk
+++ b/mk/sys.vars.mk
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: BSD-2-Clause
#
-# $Id: sys.vars.mk,v 1.16 2024/02/17 17:26:57 sjg Exp $
+# $Id: sys.vars.mk,v 1.17 2024/09/28 04:06:47 sjg Exp $
#
# @(#) Copyright (c) 2003-2023, Simon J. Gerraty
#
@@ -140,3 +140,8 @@ M_mtime = tW:S,^,${STAT:Ustat} -f %m ,:sh
M_mtime = mtime${M_mtime_fallback:U}
.endif
+# This line noise allows doing .tab and .bel below
+# don't expect sane results if input is more than a single word
+M_CharLiteral = L:@c@$${x x:L:$${:Uts$$c}:S/x//Wg}@
+.tab := ${\t:${M_CharLiteral}}
+.bel := ${\007:${M_CharLiteral}}
diff --git a/os.sh b/os.sh
index 648ea1d5993c..8216c774cd96 100755..100644
--- a/os.sh
+++ b/os.sh
@@ -17,7 +17,7 @@
# Simon J. Gerraty <sjg@crufty.net>
# RCSid:
-# $Id: os.sh,v 1.64 2024/03/19 16:03:23 sjg Exp $
+# $Id: os.sh,v 1.66 2024/09/25 18:16:09 sjg Exp $
#
# @(#) Copyright (c) 1994 Simon J. Gerraty
#
@@ -223,10 +223,11 @@ MACHINE_ARCH=${MACHINE_ARCH:-$MACHINE}
HOST_ARCH=${HOST_ARCH:-$MACHINE_ARCH}
case "$HOST_ARCH" in
x86*64|amd64) MACHINE32_ARCH=i386;;
-*64) MACHINE32_ARCH=`echo $MACHINE_ARCH | sed 's,64,32,'`;;
+*64) MACHINE32_ARCH=${MACHINE32_ARCH:-`echo $MACHINE_ARCH | sed 's,64,32,'`};;
*) MACHINE32_ARCH=$MACHINE_ARCH;;
esac
HOST_ARCH32=${HOST_ARCH32:-$MACHINE32_ARCH}
+export HOST_ARCH HOST_ARCH32
# we mount server:/share/arch/$SHARE_ARCH as /usr/local
SHARE_ARCH_DEFAULT=$OS/$OSMAJOR.X/$HOST_ARCH
SHARE_ARCH=${SHARE_ARCH:-$SHARE_ARCH_DEFAULT}
@@ -238,10 +239,12 @@ HOST_TARGET=`echo ${OS}${OSMAJOR}-$HOST_ARCH | tr -d / | toLower`
HOST_TARGET32=`echo ${OS}${OSMAJOR}-$HOST_ARCH32 | tr -d / | toLower`
export HOST_TARGET HOST_TARGET32
+case `echo -e .` in -e*) echo_e=;; *) echo_e=-e;; esac
case `echo -n .` in -n*) echo_n=; echo_c="\c";; *) echo_n=-n; echo_c=;; esac
Echo() {
case "$1" in
+ -e) shift; echo $echo_e "$@";;
-n) shift; echo $echo_n "$@$echo_c";;
*) echo "$@";;
esac
@@ -269,4 +272,3 @@ case /$0 in
*/host_target32) echo $HOST_TARGET32;;
*/host_target) echo $HOST_TARGET;;
esac
-
diff --git a/parse.c b/parse.c
index d530efa0ddce..c927f0f6adcf 100644
--- a/parse.c
+++ b/parse.c
@@ -1,4 +1,4 @@
-/* $NetBSD: parse.c,v 1.734 2024/07/09 19:43:01 rillig Exp $ */
+/* $NetBSD: parse.c,v 1.738 2025/01/14 21:34:09 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -110,7 +110,7 @@
#include "pathnames.h"
/* "@(#)parse.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: parse.c,v 1.734 2024/07/09 19:43:01 rillig Exp $");
+MAKE_RCSID("$NetBSD: parse.c,v 1.738 2025/01/14 21:34:09 rillig Exp $");
/* Detects a multiple-inclusion guard in a makefile. */
typedef enum {
@@ -400,6 +400,8 @@ PrintStackTrace(bool includingInnermost)
const IncludedFile *entries;
size_t i, n;
+ EvalStack_PrintDetails();
+
n = includes.len;
if (n == 0)
return;
@@ -530,7 +532,6 @@ ParseVErrorInternal(FILE *f, bool useVars, const GNode *gn,
PrintLocation(f, useVars, gn);
if (level == PARSE_WARNING)
(void)fprintf(f, "warning: ");
- fprintf(f, "%s", EvalStack_Details());
(void)vfprintf(f, fmt, ap);
(void)fprintf(f, "\n");
(void)fflush(f);
@@ -1845,7 +1846,7 @@ VarAssign_EvalShell(const char *name, const char *uvalue, GNode *scope,
char *output, *error;
cmd = FStr_InitRefer(uvalue);
- Var_Expand(&cmd, SCOPE_CMDLINE, VARE_EVAL_DEFINED);
+ Var_Expand(&cmd, SCOPE_CMDLINE, VARE_EVAL);
output = Cmd_Exec(cmd.str, &error);
Var_SetExpand(scope, name, output);
@@ -2621,7 +2622,8 @@ ReadHighLevelLine(void)
if (line == NULL)
return NULL;
- DEBUG2(PARSE, "Parsing line %u: %s\n", curFile->lineno, line);
+ DEBUG3(PARSE, "Parsing %s:%u: %s\n",
+ curFile->name.str, curFile->lineno, line);
if (curFile->guardState != GS_NO
&& ((curFile->guardState == GS_START && line[0] != '.')
|| curFile->guardState == GS_DONE))
@@ -2842,7 +2844,6 @@ FindSemicolon(char *p)
static void
ParseDependencyLine(char *line)
{
- VarEvalMode emode;
char *expanded_line;
const char *shellcmd = NULL;
@@ -2855,41 +2856,7 @@ ParseDependencyLine(char *line)
}
}
- /*
- * We now know it's a dependency line, so it needs to have all
- * variables expanded before being parsed.
- *
- * XXX: Ideally the dependency line would first be split into
- * its left-hand side, dependency operator and right-hand side,
- * and then each side would be expanded on its own. This would
- * allow for the left-hand side to allow only defined variables
- * and to allow variables on the right-hand side to be undefined
- * as well.
- *
- * Parsing the line first would also prevent that targets
- * generated from expressions are interpreted as the
- * dependency operator, such as in "target${:U\:} middle: source",
- * in which the middle is interpreted as a source, not a target.
- */
-
- /*
- * In lint mode, allow undefined variables to appear in dependency
- * lines.
- *
- * Ideally, only the right-hand side would allow undefined variables
- * since it is common to have optional dependencies. Having undefined
- * variables on the left-hand side is more unusual though. Since
- * both sides are expanded in a single pass, there is not much choice
- * what to do here.
- *
- * In normal mode, it does not matter whether undefined variables are
- * allowed or not since as of 2020-09-14, Var_Parse does not print
- * any parse errors in such a case. It simply returns the special
- * empty string var_Error, which cannot be detected in the result of
- * Var_Subst.
- */
- emode = opts.strict ? VARE_EVAL : VARE_EVAL_DEFINED;
- expanded_line = Var_Subst(line, SCOPE_CMDLINE, emode);
+ expanded_line = Var_Subst(line, SCOPE_CMDLINE, VARE_EVAL);
/* TODO: handle errors */
/* Need a fresh list for the target nodes */
diff --git a/suff.c b/suff.c
index 2ca5bb06da47..c24a0ac5afdc 100644
--- a/suff.c
+++ b/suff.c
@@ -1,4 +1,4 @@
-/* $NetBSD: suff.c,v 1.382 2024/07/07 07:50:57 rillig Exp $ */
+/* $NetBSD: suff.c,v 1.383 2025/01/14 21:39:24 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -115,7 +115,7 @@
#include "dir.h"
/* "@(#)suff.c 8.4 (Berkeley) 3/21/94" */
-MAKE_RCSID("$NetBSD: suff.c,v 1.382 2024/07/07 07:50:57 rillig Exp $");
+MAKE_RCSID("$NetBSD: suff.c,v 1.383 2025/01/14 21:39:24 rillig Exp $");
typedef List SuffixList;
typedef ListNode SuffixListNode;
@@ -1343,7 +1343,7 @@ ExpandChildren(GNodeListNode *cln, GNode *pgn)
}
DEBUG1(SUFF, "Expanding \"%s\"...", cgn->name);
- expanded = Var_Subst(cgn->name, pgn, VARE_EVAL_DEFINED);
+ expanded = Var_Subst(cgn->name, pgn, VARE_EVAL);
/* TODO: handle errors */
{
diff --git a/unit-tests/Makefile b/unit-tests/Makefile
index 319643b135a0..e83758871bba 100644
--- a/unit-tests/Makefile
+++ b/unit-tests/Makefile
@@ -1,6 +1,6 @@
-# $Id: Makefile,v 1.224 2024/07/13 05:27:35 sjg Exp $
+# $Id: Makefile,v 1.230 2025/01/30 18:04:20 sjg Exp $
#
-# $NetBSD: Makefile,v 1.350 2024/07/07 09:37:00 rillig Exp $
+# $NetBSD: Makefile,v 1.355 2025/01/25 22:46:30 sjg Exp $
#
# Unit tests for make(1)
#
@@ -46,6 +46,11 @@ TMPDIR:= /tmp/uid${.MAKE.UID}
.if !exist(${TMPDIR})
_!= mkdir -p ${TMPDIR}
.endif
+# and clean it up - outside the context of
+# any target that might be using it.
+.END: rm-tmpdir
+rm-tmpdir: .NOMETA
+ @rm -rf ${TMPDIR}
# Each test is in a sub-makefile.
# Keep the list sorted.
@@ -314,6 +319,7 @@ TESTS+= shell-custom
TESTS+= shell-ksh
.endif
TESTS+= shell-sh
+TESTS+= suff
TESTS+= suff-add-later
TESTS+= suff-clear-regular
TESTS+= suff-clear-single
@@ -575,7 +581,7 @@ SED_CMDS.deptgt-phony= ${STD_SED_CMDS.dd}
SED_CMDS.dir= ${STD_SED_CMDS.dd}
SED_CMDS.directive-include-guard= \
-e '/\.MAKEFLAGS/d' \
- -e '/^Parsing line/d' \
+ -e '/^Parsing .*:[1-9][0-9]*:/d' \
-e '/^SetFilenameVars:/d' \
-e '/^ParseDependency/d' \
-e '/^ParseEOF:/d'
@@ -857,11 +863,12 @@ SED_CMDS.opt-debug-jobs+= -e 's,Command: <shell> -v,Command: <shell>,'
.rawout.out:
@${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.PREFIX:T}} \
- < ${.IMPSRC} > ${.TARGET}.tmp1
- @${POSTPROC.${.PREFIX:T}:Ucat} < ${.TARGET}.tmp1 > ${.TARGET}.tmp2
- @rm ${.TARGET}.tmp1
- @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp2
- @mv ${.TARGET}.tmp2 ${.TARGET}
+ < ${.IMPSRC} > ${.TARGET}.tmp
+ @${POSTPROC.${.PREFIX:T}:D \
+ ${POSTPROC.${.PREFIX:T}} < ${.TARGET}.tmp > ${.TARGET}.post \
+ && mv ${.TARGET}.post ${.TARGET}.tmp}
+ @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp
+ @mv ${.TARGET}.tmp ${.TARGET}
.if empty(DIFF_FLAGS)
DIFF_ECHO= echo
diff --git a/unit-tests/archive.exp b/unit-tests/archive.exp
index 5cf847388544..89e7b7878b4e 100644
--- a/unit-tests/archive.exp
+++ b/unit-tests/archive.exp
@@ -18,6 +18,18 @@ list-archive-wildcard: archive-suffix.mk
list-archive-wildcard: archive.mk
list-archive-wildcard: ternary.mk
+make: "archive.mk" line 61: Error in source archive spec "libprog.a${UNDEF}(archive.mk) pre post"
+ in directory <curdir>
+make: Fatal errors encountered -- cannot continue
+make: stopped making "list-archive-undef-archive" in unit-tests
+exit 1
+
+make: "archive.mk" line 68: Error in source archive spec "libprog.a"
+ in directory <curdir>
+make: Fatal errors encountered -- cannot continue
+make: stopped making "list-archive-undef-member" in unit-tests
+exit 1
+
Making depend-on-existing-member out-of-date archive.mk
depend-on-existing-member
diff --git a/unit-tests/archive.mk b/unit-tests/archive.mk
index eef64396f419..f19c63f29632 100644
--- a/unit-tests/archive.mk
+++ b/unit-tests/archive.mk
@@ -1,4 +1,4 @@
-# $NetBSD: archive.mk,v 1.13 2024/04/27 20:23:22 rillig Exp $
+# $NetBSD: archive.mk,v 1.14 2025/01/10 23:00:38 rillig Exp $
#
# Very basic demonstration of handling archives, based on the description
# in PSD.doc/tutorial.ms.
@@ -21,6 +21,10 @@ all:
@${MAKE} -f ${MAKEFILE} create-archive
@${MAKE} -f ${MAKEFILE} list-archive
@${MAKE} -f ${MAKEFILE} list-archive-wildcard
+ @${MAKE} -f ${MAKEFILE} list-archive-undef-archive || echo "exit $$?"
+ @echo
+ @${MAKE} -f ${MAKEFILE} list-archive-undef-member || echo "exit $$?"
+ @echo
@${MAKE} -f ${MAKEFILE} depend-on-existing-member
@${MAKE} -f ${MAKEFILE} depend-on-nonexistent-member
@${MAKE} -f ${MAKEFILE} remove-archive
@@ -51,6 +55,20 @@ list-archive: ${ARCHIVE} pre post
list-archive-wildcard: ${ARCHIVE}([at]*.mk) pre post
@printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@}
+.if make(list-archive-undef-archive)
+# TODO: Be more specific: mention that the variable "UNDEF" is not defined.
+# expect+1: Error in source archive spec "libprog.a${UNDEF}(archive.mk) pre post"
+list-archive-undef-archive: ${ARCHIVE}$${UNDEF}(archive.mk) pre post
+ @printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@}
+.endif
+
+.if make(list-archive-undef-member)
+# TODO: Be more specific: mention that the variable "UNDEF" is not defined.
+# expect+1: Error in source archive spec "libprog.a"
+list-archive-undef-member: ${ARCHIVE}(archive$${UNDEF}.mk) pre post
+ @printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@}
+.endif
+
depend-on-existing-member: ${ARCHIVE}(archive.mk) pre post
@echo $@
diff --git a/unit-tests/cmd-errors-jobs.exp b/unit-tests/cmd-errors-jobs.exp
index 074ceb3bcf28..7177cd4d18f8 100644
--- a/unit-tests/cmd-errors-jobs.exp
+++ b/unit-tests/cmd-errors-jobs.exp
@@ -1,9 +1,67 @@
-: undefined--eol
-make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-: unclosed-expression-
-make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-: unclosed-modifier-
-make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-: unknown-modifier--eol
-: end-eol
-exit status 2
+begin undefined-direct
+: undefined-direct--eol
+end undefined-direct with status 0
+
+begin undefined-indirect
+: undefined-direct--eol
+end undefined-indirect with status 0
+
+begin parse-error-direct
+make: Unclosed variable "UNCLOSED"
+ in target "parse-error-unclosed-expression"
+make: Unclosed expression, expecting '}'
+ while evaluating variable "UNCLOSED" with value ""
+ in target "parse-error-unclosed-modifier"
+make: Unknown modifier "Z"
+ while evaluating variable "UNKNOWN" with value ""
+ in target "parse-error-unknown-modifier"
+end parse-error-direct with status 2
+
+begin parse-error-indirect
+make: Unclosed variable "UNCLOSED"
+ in target "parse-error-unclosed-expression"
+make: Unclosed expression, expecting '}'
+ while evaluating variable "UNCLOSED" with value ""
+ in target "parse-error-unclosed-modifier"
+make: Unknown modifier "Z"
+ while evaluating variable "UNKNOWN" with value ""
+ in target "parse-error-unknown-modifier"
+end parse-error-indirect with status 2
+
+begin begin-direct
+(exit 13) # .BEGIN
+*** Error code 13 (continuing)
+
+
+Stop.
+make: stopped making "begin-direct" in unit-tests
+end begin-direct with status 1
+
+begin begin-indirect
+(exit 13) # before-begin
+*** Error code 13 (continuing)
+
+
+Stop.
+make: stopped making "begin-indirect" in unit-tests
+end begin-indirect with status 1
+
+begin end-direct
+(exit 13) # .END
+*** Error code 13 (continuing)
+
+
+Stop.
+make: stopped making "end-direct" in unit-tests
+end end-direct with status 1
+
+begin end-indirect
+(exit 13) # before-end
+*** Error code 13 (continuing)
+
+
+Stop.
+make: stopped making "end-indirect" in unit-tests
+end end-indirect with status 1
+
+exit status 0
diff --git a/unit-tests/cmd-errors-jobs.mk b/unit-tests/cmd-errors-jobs.mk
index c24aa51907a2..471f2cbb327c 100644
--- a/unit-tests/cmd-errors-jobs.mk
+++ b/unit-tests/cmd-errors-jobs.mk
@@ -1,38 +1,105 @@
-# $NetBSD: cmd-errors-jobs.mk,v 1.8 2024/07/09 19:43:01 rillig Exp $
+# $NetBSD: cmd-errors-jobs.mk,v 1.13 2024/08/29 20:20:35 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed in jobs mode.
-.MAKEFLAGS: -j1
+RUN= @ run() { \
+ echo "begin $$*" \
+ && ${MAKE} -f ${MAKEFILE} -j1 "$$*" \
+ && echo "end $$* with status $$?" \
+ || echo "end $$* with status $$?" \
+ && echo; \
+ } && run
+
+all:
+ ${RUN} undefined-direct
+ ${RUN} undefined-indirect
+ ${RUN} parse-error-direct
+ ${RUN} parse-error-indirect
+ ${RUN} begin-direct
+ ${RUN} begin-indirect
+ ${RUN} end-direct
+ ${RUN} end-indirect
-all: undefined unclosed-expression unclosed-modifier unknown-modifier end
# Undefined variables in expressions are not an error. They expand to empty
# strings.
-# expect: : undefined--eol
-undefined:
+# expect: : undefined-direct--eol
+# expect: end undefined-direct with status 0
+# expect: : undefined-direct--eol
+# expect: end undefined-indirect with status 0
+undefined-indirect: undefined-direct
+undefined-direct:
: $@-${UNDEFINED}-eol
-unclosed-expression:
-# expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-expression-
- : $@-${UNCLOSED
-
-unclosed-modifier:
-# expect: make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-modifier-
- : $@-${UNCLOSED:
-
-unknown-modifier:
-# expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unknown-modifier--eol
- : $@-${UNKNOWN:Z}-eol
-
-# expect: : end-eol
-end:
- : $@-eol
-
-# expect: exit status 2
+
+parse-error-indirect: parse-error-direct
+parse-error-direct: parse-error-unclosed-expression
+parse-error-direct: parse-error-unclosed-modifier
+parse-error-direct: parse-error-unknown-modifier
+
+parse-error-unclosed-expression:
+ : unexpected $@-${UNCLOSED
+
+parse-error-unclosed-modifier:
+ : unexpected $@-${UNCLOSED:
+
+parse-error-unknown-modifier:
+ : unexpected $@-${UNKNOWN:Z}-eol
+
+# expect-not: : unexpected
+# expect: make: Unclosed variable "UNCLOSED"
+# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unknown modifier "Z"
+# expect: end parse-error-direct with status 2
+# expect: make: Unclosed variable "UNCLOSED"
+# expect: make: Unclosed expression, expecting '}'
+# expect: make: Unknown modifier "Z"
+# expect: end parse-error-indirect with status 2
+
+
+.if make(begin-direct)
+begin-direct:
+.BEGIN:
+ (exit 13) # $@
+.endif
+# expect: begin begin-direct
+# expect: make: stopped making "begin-direct" in unit-tests
+# expect: end begin-direct with status 1
+
+
+.if make(begin-indirect)
+begin-indirect:
+.BEGIN: before-begin
+ : Making $@
+before-begin:
+ (exit 13) # $@
+.endif
+# expect: begin begin-indirect
+# expect: *** Error code 13 (continuing)
+# expect: make: stopped making "begin-indirect" in unit-tests
+# expect: end begin-indirect with status 1
+
+
+.if make(end-direct)
+end-direct:
+.END:
+ (exit 13) # $@
+.endif
+# expect: begin end-direct
+# expect: *** Error code 13 (continuing)
+# expect: Stop.
+# expect: make: stopped making "end-direct" in unit-tests
+# expect: end end-direct with status 1
+
+.if make(end-indirect)
+end-indirect:
+.END: before-end
+ : Making $@
+before-end:
+ (exit 13) # $@
+.endif
+# expect: begin end-indirect
+# expect: *** Error code 13 (continuing)
+# expect: make: stopped making "end-indirect" in unit-tests
+# expect: end end-indirect with status 1
diff --git a/unit-tests/cmd-errors-lint.exp b/unit-tests/cmd-errors-lint.exp
index a5b129c78f92..116e9957a2c5 100644
--- a/unit-tests/cmd-errors-lint.exp
+++ b/unit-tests/cmd-errors-lint.exp
@@ -1,9 +1,11 @@
: undefined
-make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-: unclosed-expression
-make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-: unclosed-modifier
-make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-: unknown-modifier
+make: Unclosed variable "UNCLOSED"
+ in target "unclosed-expression"
+make: Unclosed expression, expecting '}'
+ while evaluating variable "UNCLOSED" with value ""
+ in target "unclosed-modifier"
+make: Unknown modifier "Z"
+ while evaluating variable "UNKNOWN" with value ""
+ in target "unknown-modifier"
: end
exit status 2
diff --git a/unit-tests/cmd-errors-lint.mk b/unit-tests/cmd-errors-lint.mk
index f870fceaa5cb..873f05c6186f 100644
--- a/unit-tests/cmd-errors-lint.mk
+++ b/unit-tests/cmd-errors-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors-lint.mk,v 1.4 2024/07/05 18:59:33 rillig Exp $
+# $NetBSD: cmd-errors-lint.mk,v 1.6 2024/08/29 20:20:35 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed.
@@ -14,21 +14,18 @@ undefined:
: $@ ${UNDEFINED}
unclosed-expression:
-# expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-expression
+# expect: make: Unclosed variable "UNCLOSED"
+# expect-not: : unclosed-expression
: $@ ${UNCLOSED
unclosed-modifier:
-# expect: make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-modifier
+# expect: make: Unclosed expression, expecting '}'
+# expect-not: : unclosed-modifier
: $@ ${UNCLOSED:
unknown-modifier:
-# expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unknown-modifier
+# expect: make: Unknown modifier "Z"
+# expect-not: : unknown-modifier
: $@ ${UNKNOWN:Z}
end:
diff --git a/unit-tests/cmd-errors.exp b/unit-tests/cmd-errors.exp
index 074ceb3bcf28..865072ecbf86 100644
--- a/unit-tests/cmd-errors.exp
+++ b/unit-tests/cmd-errors.exp
@@ -1,9 +1,11 @@
: undefined--eol
-make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-: unclosed-expression-
-make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-: unclosed-modifier-
-make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-: unknown-modifier--eol
+make: Unclosed variable "UNCLOSED"
+ in target "unclosed-expression"
+make: Unclosed expression, expecting '}'
+ while evaluating variable "UNCLOSED" with value ""
+ in target "unclosed-modifier"
+make: Unknown modifier "Z"
+ while evaluating variable "UNKNOWN" with value ""
+ in target "unknown-modifier"
: end-eol
exit status 2
diff --git a/unit-tests/cmd-errors.mk b/unit-tests/cmd-errors.mk
index d9525df6064e..0acc811d43bc 100644
--- a/unit-tests/cmd-errors.mk
+++ b/unit-tests/cmd-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-errors.mk,v 1.9 2024/07/09 19:43:01 rillig Exp $
+# $NetBSD: cmd-errors.mk,v 1.11 2024/08/29 20:20:35 rillig Exp $
#
# Demonstrate how errors in expressions affect whether the commands
# are actually executed in compat mode.
@@ -12,21 +12,18 @@ undefined:
: $@-${UNDEFINED}-eol
unclosed-expression:
-# expect: make: in target "unclosed-expression": Unclosed variable "UNCLOSED"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-expression-
+# expect: make: Unclosed variable "UNCLOSED"
+# expect-not: : unclosed-expression-
: $@-${UNCLOSED
unclosed-modifier:
-# expect: make: in target "unclosed-modifier": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}'
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unclosed-modifier-
+# expect: make: Unclosed expression, expecting '}'
+# expect-not: : unclosed-modifier-
: $@-${UNCLOSED:
unknown-modifier:
-# expect: make: in target "unknown-modifier": while evaluating variable "UNKNOWN" with value "": Unknown modifier "Z"
-# XXX: This command is executed even though it contains parse errors.
-# expect: : unknown-modifier--eol
+# expect: make: Unknown modifier "Z"
+# expect-not: : unknown-modifier--eol
: $@-${UNKNOWN:Z}-eol
end:
diff --git a/unit-tests/cmd-interrupt.exp b/unit-tests/cmd-interrupt.exp
index 242db1d9507d..e03b64870fa3 100755
--- a/unit-tests/cmd-interrupt.exp
+++ b/unit-tests/cmd-interrupt.exp
@@ -5,4 +5,5 @@ interrupt-ordinary: ok
interrupt-phony: ok
> cmd-interrupt-precious
interrupt-precious: ok
+interrupt-compat expected-fail
exit status 0
diff --git a/unit-tests/cmd-interrupt.mk b/unit-tests/cmd-interrupt.mk
index 140651b55c62..7ee53c6c2105 100755
--- a/unit-tests/cmd-interrupt.mk
+++ b/unit-tests/cmd-interrupt.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cmd-interrupt.mk,v 1.4 2023/03/18 22:20:12 sjg Exp $
+# $NetBSD: cmd-interrupt.mk,v 1.5 2024/07/13 15:10:06 rillig Exp $
#
# Tests for interrupting a command.
#
@@ -17,10 +17,16 @@
# See also:
# CompatDeleteTarget
-all: clean-before interrupt-ordinary interrupt-phony interrupt-precious clean-after
+all: clean-before
+all: interrupt-ordinary
+all: interrupt-phony
+all: interrupt-precious
+all: interrupt-compat
+all: clean-after
clean-before clean-after: .PHONY
- @rm -f cmd-interrupt-ordinary cmd-interrupt-phony cmd-interrupt-precious
+ @rm -f cmd-interrupt-ordinary cmd-interrupt-phony
+ @rm -f cmd-interrupt-precious cmd-interrupt-compat
interrupt-ordinary:
@${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-ordinary || true
@@ -37,6 +43,10 @@ interrupt-precious: .PRECIOUS
# The ././ is necessary to work around the file cache.
@echo ${.TARGET}: ${exists(././cmd-interrupt-precious) :? ok : error }
+interrupt-compat:
+ @${MAKE} -f ${MAKEFILE} cmd-interrupt-compat || true
+ @echo ${.TARGET} ${exists(././cmd-interrupt-compat) :? expected-fail : unexpected-ok }
+
cmd-interrupt-ordinary:
> ${.TARGET}
@kill -INT ${.MAKE.PID}
@@ -48,3 +58,11 @@ cmd-interrupt-phony: .PHONY
cmd-interrupt-precious: .PRECIOUS
> ${.TARGET}
@kill -INT ${.MAKE.PID}
+
+# When the make process (and not the process group) is interrupted in compat
+# mode, it first tries to interrupt the process group of the currently running
+# child command, but that fails since there is no such process group, rather
+# the child command runs in the same process group as make itself. The child
+# command then continues, and after sleeping a bit creates the target file.
+cmd-interrupt-compat:
+ @kill -INT ${.MAKE.PID} && sleep 1 && > ${.TARGET}
diff --git a/unit-tests/cmdline.exp b/unit-tests/cmdline.exp
index 5700da3295fb..063be7e83afe 100644
--- a/unit-tests/cmdline.exp
+++ b/unit-tests/cmdline.exp
@@ -1,7 +1,7 @@
makeobjdir-direct:
-show-objdir: <tmpdir>/6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5
+show-objdir: <tmpdir>/cmdline/6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5
makeobjdir-indirect:
-show-objdir: <tmpdir>/a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45/
+show-objdir: <tmpdir>/cmdline/a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45/
space-and-comment:
value # no comment $
value # no comment $
diff --git a/unit-tests/cmdline.mk b/unit-tests/cmdline.mk
index 40a0d7ccddbb..c0c4ee287f2f 100644
--- a/unit-tests/cmdline.mk
+++ b/unit-tests/cmdline.mk
@@ -1,8 +1,8 @@
-# $NetBSD: cmdline.mk,v 1.5 2024/04/23 22:51:28 rillig Exp $
+# $NetBSD: cmdline.mk,v 1.7 2024/08/29 17:56:37 sjg Exp $
#
# Tests for command line parsing and related special variables.
-TMPBASE?= ${TMPDIR:U/tmp/uid${.MAKE.UID}}
+TMPBASE?= ${TMPDIR:U/tmp/uid${.MAKE.UID}}/cmdline
SUB1= a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45 # just a random UUID
SUB2= 6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 # just a random UUID
MAKE_CMD= env TMPBASE=${TMPBASE}/${SUB1} ${.MAKE} -f ${MAKEFILE} -r
@@ -12,6 +12,7 @@ DIR12= ${TMPBASE}/${SUB1}/${SUB2}
all: prepare-dirs
all: makeobjdir-direct makeobjdir-indirect
all: space-and-comment
+all: cleanup
prepare-dirs:
@rm -rf ${DIR2} ${DIR12}
@@ -56,3 +57,6 @@ space-and-comment: .PHONY
@env -i MAKEFLAGS="' VAR= value # no comment '" \
${MAKE} -r -f /dev/null -v VAR \
| sed 's,$$,$$,'
+
+cleanup:
+ @rm -rf ${TMPBASE}
diff --git a/unit-tests/cond-cmp-numeric-eq.exp b/unit-tests/cond-cmp-numeric-eq.exp
index 059007f00c84..e05961f14f87 100644
--- a/unit-tests/cond-cmp-numeric-eq.exp
+++ b/unit-tests/cond-cmp-numeric-eq.exp
@@ -1,5 +1,5 @@
-make: "cond-cmp-numeric-eq.mk" line 68: Malformed conditional (!(12345 = 12345))
-make: "cond-cmp-numeric-eq.mk" line 76: Malformed conditional (!(12345 === 12345))
+make: "cond-cmp-numeric-eq.mk" line 68: Malformed conditional '!(12345 = 12345)'
+make: "cond-cmp-numeric-eq.mk" line 76: Malformed conditional '!(12345 === 12345)'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-cmp-numeric-eq.mk b/unit-tests/cond-cmp-numeric-eq.mk
index 1d0ade26087e..a8630cb37f1f 100755
--- a/unit-tests/cond-cmp-numeric-eq.mk
+++ b/unit-tests/cond-cmp-numeric-eq.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-numeric-eq.mk,v 1.7 2023/09/07 05:36:33 rillig Exp $
+# $NetBSD: cond-cmp-numeric-eq.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $
#
# Tests for numeric comparisons with the == operator in .if conditions.
@@ -64,7 +64,7 @@
.endif
# There is no = operator for numbers.
-# expect+1: Malformed conditional (!(12345 = 12345))
+# expect+1: Malformed conditional '!(12345 = 12345)'
.if !(12345 = 12345)
. error
.else
@@ -72,7 +72,7 @@
.endif
# There is no === operator for numbers either.
-# expect+1: Malformed conditional (!(12345 === 12345))
+# expect+1: Malformed conditional '!(12345 === 12345)'
.if !(12345 === 12345)
. error
.else
diff --git a/unit-tests/cond-cmp-numeric.exp b/unit-tests/cond-cmp-numeric.exp
index 77c0154ca29b..8bec6ed55216 100644
--- a/unit-tests/cond-cmp-numeric.exp
+++ b/unit-tests/cond-cmp-numeric.exp
@@ -5,7 +5,7 @@ make: "cond-cmp-numeric.mk" line 21: Comparison with '>' requires both operands
CondParser_Eval: !(${:UNaN} == NaN)
Comparing "NaN" == "NaN"
CondParser_Eval: 123 ! 123
-make: "cond-cmp-numeric.mk" line 38: Malformed conditional (123 ! 123)
+make: "cond-cmp-numeric.mk" line 38: Malformed conditional '123 ! 123'
CondParser_Eval: ${:U 123} < 124
Comparing 123.000000 < 124.000000
CondParser_Eval: ${:U123 } < 124
diff --git a/unit-tests/cond-cmp-numeric.mk b/unit-tests/cond-cmp-numeric.mk
index e025b99b27cd..63a3bff8d560 100644
--- a/unit-tests/cond-cmp-numeric.mk
+++ b/unit-tests/cond-cmp-numeric.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-numeric.mk,v 1.7 2023/03/04 08:07:29 rillig Exp $
+# $NetBSD: cond-cmp-numeric.mk,v 1.8 2024/08/06 18:00:16 rillig Exp $
#
# Tests for numeric comparisons in .if conditions.
#
@@ -34,7 +34,7 @@
# whether the operator is valid, leaving the rest of the work to the
# evaluation functions EvalCompareNum and EvalCompareStr. Ensure that this
# parse error is properly reported.
-# expect+1: Malformed conditional (123 ! 123)
+# expect+1: Malformed conditional '123 ! 123'
.if 123 ! 123
. error
.else
diff --git a/unit-tests/cond-cmp-string.exp b/unit-tests/cond-cmp-string.exp
index e0aabfdadca4..ce58422afd7e 100644
--- a/unit-tests/cond-cmp-string.exp
+++ b/unit-tests/cond-cmp-string.exp
@@ -1,7 +1,7 @@
-make: "cond-cmp-string.mk" line 19: Malformed conditional (str != str)
-make: "cond-cmp-string.mk" line 44: Malformed conditional ("string" != "str""ing")
-make: "cond-cmp-string.mk" line 52: Malformed conditional (!("value" = "value"))
-make: "cond-cmp-string.mk" line 60: Malformed conditional (!("value" === "value"))
+make: "cond-cmp-string.mk" line 19: Malformed conditional 'str != str'
+make: "cond-cmp-string.mk" line 44: Malformed conditional '"string" != "str""ing"'
+make: "cond-cmp-string.mk" line 52: Malformed conditional '!("value" = "value")'
+make: "cond-cmp-string.mk" line 60: Malformed conditional '!("value" === "value")'
make: "cond-cmp-string.mk" line 118: Comparison with '<' requires both operands 'string' and 'string' to be numeric
make: "cond-cmp-string.mk" line 126: Comparison with '<=' requires both operands 'string' and 'string' to be numeric
make: "cond-cmp-string.mk" line 134: Comparison with '>' requires both operands 'string' and 'string' to be numeric
diff --git a/unit-tests/cond-cmp-string.mk b/unit-tests/cond-cmp-string.mk
index e3346e08b5a0..a913750a017f 100644
--- a/unit-tests/cond-cmp-string.mk
+++ b/unit-tests/cond-cmp-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-cmp-string.mk,v 1.19 2024/04/23 22:51:28 rillig Exp $
+# $NetBSD: cond-cmp-string.mk,v 1.20 2024/08/06 18:00:16 rillig Exp $
#
# Tests for string comparisons in .if conditions.
@@ -15,7 +15,7 @@
# The left-hand side of the comparison must be enclosed in quotes.
# This one is not enclosed in quotes and thus generates an error message.
-# expect+1: Malformed conditional (str != str)
+# expect+1: Malformed conditional 'str != str'
.if str != str
. error
.endif
@@ -40,7 +40,7 @@
# It is not possible to concatenate two string literals to form a single
# string. In C, Python and the shell this is possible, but not in make.
-# expect+1: Malformed conditional ("string" != "str""ing")
+# expect+1: Malformed conditional '"string" != "str""ing"'
.if "string" != "str""ing"
. error
.else
@@ -48,7 +48,7 @@
.endif
# There is no = operator for strings.
-# expect+1: Malformed conditional (!("value" = "value"))
+# expect+1: Malformed conditional '!("value" = "value")'
.if !("value" = "value")
. error
.else
@@ -56,7 +56,7 @@
.endif
# There is no === operator for strings either.
-# expect+1: Malformed conditional (!("value" === "value"))
+# expect+1: Malformed conditional '!("value" === "value")'
.if !("value" === "value")
. error
.else
diff --git a/unit-tests/cond-eof.exp b/unit-tests/cond-eof.exp
index 58a74d854d91..9e19dca175bd 100644
--- a/unit-tests/cond-eof.exp
+++ b/unit-tests/cond-eof.exp
@@ -1,6 +1,6 @@
-make: "cond-eof.mk" line 17: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2})
-make: "cond-eof.mk" line 20: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2})
-make: "cond-eof.mk" line 23: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2})
+make: "cond-eof.mk" line 17: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+make: "cond-eof.mk" line 20: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
+make: "cond-eof.mk" line 23: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-eof.mk b/unit-tests/cond-eof.mk
index a5f7ce95f89e..706a7deebd1a 100644
--- a/unit-tests/cond-eof.mk
+++ b/unit-tests/cond-eof.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-eof.mk,v 1.6 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: cond-eof.mk,v 1.7 2024/08/06 18:00:16 rillig Exp $
#
# Tests for parsing the end of '.if' conditions, which are represented as the
# token TOK_EOF.
@@ -13,12 +13,12 @@ SIDE_EFFECT2= ${:!echo 'side effect 2' 1>&2!}
# These syntax errors are an edge case that does not occur during normal
# operation. Still, it is easy to avoid evaluating these expressions, just in
# case they have side effects.
-# expect+1: Malformed conditional (0 ${SIDE_EFFECT} ${SIDE_EFFECT2})
+# expect+1: Malformed conditional '0 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
.if 0 ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
-# expect+1: Malformed conditional (1 ${SIDE_EFFECT} ${SIDE_EFFECT2})
+# expect+1: Malformed conditional '1 ${SIDE_EFFECT} ${SIDE_EFFECT2}'
.if 1 ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
-# expect+1: Malformed conditional ((0) ${SIDE_EFFECT} ${SIDE_EFFECT2})
+# expect+1: Malformed conditional '(0) ${SIDE_EFFECT} ${SIDE_EFFECT2}'
.if (0) ${SIDE_EFFECT} ${SIDE_EFFECT2}
.endif
diff --git a/unit-tests/cond-func-commands.mk b/unit-tests/cond-func-commands.mk
index e127a8ebdc03..d193587cd2c1 100644
--- a/unit-tests/cond-func-commands.mk
+++ b/unit-tests/cond-func-commands.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-commands.mk,v 1.5 2020/11/15 14:07:53 rillig Exp $
+# $NetBSD: cond-func-commands.mk,v 1.6 2025/01/10 23:00:38 rillig Exp $
#
# Tests for the commands() function in .if conditions.
@@ -33,5 +33,10 @@ target:
. error
.endif
+# Expressions in the argument of a function call don't have to be defined.
+.if commands(${UNDEF})
+. error
+.endif
+
all:
@:;
diff --git a/unit-tests/cond-func-defined.exp b/unit-tests/cond-func-defined.exp
index b9563ac1fa91..0b48906ce83f 100644
--- a/unit-tests/cond-func-defined.exp
+++ b/unit-tests/cond-func-defined.exp
@@ -1,5 +1,5 @@
-make: "cond-func-defined.mk" line 24: Missing closing parenthesis for defined()
-make: "cond-func-defined.mk" line 34: Missing closing parenthesis for defined()
+make: "cond-func-defined.mk" line 24: Missing ')' after argument 'A' for 'defined'
+make: "cond-func-defined.mk" line 34: Missing ')' after argument 'DEF' for 'defined'
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/cond-func-defined.mk b/unit-tests/cond-func-defined.mk
index 6b24182c11c1..66f95f3380c1 100644
--- a/unit-tests/cond-func-defined.mk
+++ b/unit-tests/cond-func-defined.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-defined.mk,v 1.12 2024/04/23 22:51:28 rillig Exp $
+# $NetBSD: cond-func-defined.mk,v 1.14 2025/01/10 23:00:38 rillig Exp $
#
# Tests for the defined() function in .if conditions.
@@ -20,7 +20,7 @@ ${:UA B}= variable name with spaces
.endif
# The argument of a function must not directly contain whitespace.
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument 'A' for 'defined'
.if !defined(A B)
. error
.endif
@@ -30,7 +30,7 @@ ${:UA B}= variable name with spaces
. error
.endif
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument 'DEF' for 'defined'
.if defined(DEF
. error
.else
@@ -49,6 +49,11 @@ ${:UA B}= variable name with spaces
. endif
.endfor
+# Expressions in the argument of a function call don't have to be defined.
+.if defined(${UNDEF})
+. error
+.endif
+
# Neither of the conditions is true. Before July 2020, the right-hand
# condition was evaluated even though it was irrelevant.
.if defined(UNDEF) && ${UNDEF:Mx} != ""
diff --git a/unit-tests/cond-func-empty.exp b/unit-tests/cond-func-empty.exp
index 1d955124d1c6..9102d4a35ae4 100644
--- a/unit-tests/cond-func-empty.exp
+++ b/unit-tests/cond-func-empty.exp
@@ -1,5 +1,4 @@
-make: "cond-func-empty.mk" line 168: Unclosed variable "WORD"
-make: "cond-func-empty.mk" line 168: Malformed conditional (empty(WORD)
+make: "cond-func-empty.mk" line 167: Unclosed variable "WORD"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-func-empty.mk b/unit-tests/cond-func-empty.mk
index d377a84ff574..17e76a63f2e8 100644
--- a/unit-tests/cond-func-empty.mk
+++ b/unit-tests/cond-func-empty.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-empty.mk,v 1.25 2024/06/02 15:31:26 rillig Exp $
+# $NetBSD: cond-func-empty.mk,v 1.28 2025/01/11 20:54:45 rillig Exp $
#
# Tests for the empty() function in .if conditions, which tests an
# expression for emptiness.
@@ -163,8 +163,7 @@ ${:U WORD }= variable name with spaces
. error
.endif
-# expect+2: Unclosed variable "WORD"
-# expect+1: Malformed conditional (empty(WORD)
+# expect+1: Unclosed variable "WORD"
.if empty(WORD
. error
.else
@@ -207,6 +206,10 @@ VARNAME= ${VARNAME${:U1}}
.if defined(VARNAME${:U2}) && !empty(VARNAME${:U2})
.endif
+# Expressions in the argument of a function call don't have to be defined.
+.if !empty(${UNDEF})
+. error
+.endif
# If the word 'empty' is not followed by '(', it is not a function call but an
# ordinary bare word. This bare word is interpreted as 'defined(empty)', and
diff --git a/unit-tests/cond-func-exists.mk b/unit-tests/cond-func-exists.mk
index 40228cd44902..c68507ca1ab9 100644
--- a/unit-tests/cond-func-exists.mk
+++ b/unit-tests/cond-func-exists.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-exists.mk,v 1.7 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: cond-func-exists.mk,v 1.8 2025/01/10 23:00:38 rillig Exp $
#
# Tests for the exists() function in .if conditions.
@@ -38,6 +38,11 @@
. error
.endif
+# Expressions in the argument of a function call don't have to be defined.
+.if exists(${UNDEF})
+. error
+.endif
+
# The exists function does not really look up the file in the file system,
# instead it uses a cache that is preloaded very early, before parsing the
# first makefile. At that time, the file did not exist yet.
diff --git a/unit-tests/cond-func-make.mk b/unit-tests/cond-func-make.mk
index 15bc9f04d4e0..1a14fd320a3c 100644
--- a/unit-tests/cond-func-make.mk
+++ b/unit-tests/cond-func-make.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-make.mk,v 1.5 2023/06/23 04:56:54 rillig Exp $
+# $NetBSD: cond-func-make.mk,v 1.6 2025/01/10 23:00:38 rillig Exp $
#
# Tests for the make() function in .if conditions, which tests whether
# the argument has been passed as a target via the command line or later
@@ -25,5 +25,10 @@
. error
.endif
+# Expressions in the argument of a function call don't have to be defined.
+.if make(${UNDEF})
+. error
+.endif
+
via-cmdline via-dot-makeflags:
: $@
diff --git a/unit-tests/cond-func-target.mk b/unit-tests/cond-func-target.mk
index 62266839df9e..2216997e4393 100644
--- a/unit-tests/cond-func-target.mk
+++ b/unit-tests/cond-func-target.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func-target.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $
+# $NetBSD: cond-func-target.mk,v 1.5 2025/01/10 23:00:38 rillig Exp $
#
# Tests for the target() function in .if conditions.
@@ -34,5 +34,10 @@ target:
. error
.endif
+# Expressions in the argument of a function call don't have to be defined.
+.if target(${UNDEF})
+. error
+.endif
+
all:
@:;
diff --git a/unit-tests/cond-func.exp b/unit-tests/cond-func.exp
index c2c5e94fe7e2..0570a1c4fabc 100644
--- a/unit-tests/cond-func.exp
+++ b/unit-tests/cond-func.exp
@@ -1,12 +1,13 @@
-make: "cond-func.mk" line 37: Missing closing parenthesis for defined()
-make: "cond-func.mk" line 53: Missing closing parenthesis for defined()
-make: "cond-func.mk" line 57: Missing closing parenthesis for defined()
+make: "cond-func.mk" line 37: Missing ')' after argument 'A' for 'defined'
+make: "cond-func.mk" line 53: Missing ')' after argument 'A' for 'defined'
+make: "cond-func.mk" line 57: Missing ')' after argument 'A' for 'defined'
make: "cond-func.mk" line 91: Unknown operator '&'
make: "cond-func.mk" line 107: A plain function name is parsed as defined(...).
make: "cond-func.mk" line 115: A plain function name is parsed as defined(...).
make: "cond-func.mk" line 126: Symbols may start with a function name.
make: "cond-func.mk" line 132: Symbols may start with a function name.
-make: "cond-func.mk" line 138: Missing closing parenthesis for defined()
+make: "cond-func.mk" line 138: Missing ')' after argument '' for 'defined'
+make: "cond-func.mk" line 145: Missing ')' after argument '${:UVARNAME}.param' for 'defined'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-func.mk b/unit-tests/cond-func.mk
index 7ed6f6f5570d..3e4f8a9f151f 100644
--- a/unit-tests/cond-func.mk
+++ b/unit-tests/cond-func.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-func.mk,v 1.15 2024/07/06 21:21:10 rillig Exp $
+# $NetBSD: cond-func.mk,v 1.18 2024/08/07 05:48:45 rillig Exp $
#
# Tests for those parts of the functions in .if conditions that are common
# among several functions.
@@ -33,7 +33,7 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
.endif
# The argument of a function must not directly contain whitespace.
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument 'A' for 'defined'
.if !defined(A B)
. error
.endif
@@ -49,11 +49,11 @@ ${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces
#
# It's not entirely clear why these characters are forbidden.
# The most plausible reason seems to be typo detection.
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument 'A' for 'defined'
.if !defined(A&B)
. error
.endif
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument 'A' for 'defined'
.if !defined(A|B)
. error
.endif
@@ -134,9 +134,16 @@ defined-var= # defined but empty
. error
.endif
-# expect+1: Missing closing parenthesis for defined()
+# expect+1: Missing ')' after argument '' for 'defined'
.if defined(
. error
.else
. error
.endif
+
+# expect+1: Missing ')' after argument '${:UVARNAME}.param' for 'defined'
+.if defined(${:UVARNAME}.param extra)
+. error
+.else
+. error
+.endif
diff --git a/unit-tests/cond-late.exp b/unit-tests/cond-late.exp
index e97fd3789381..d8a24143c2b9 100644
--- a/unit-tests/cond-late.exp
+++ b/unit-tests/cond-late.exp
@@ -1,4 +1,6 @@
-make: "cond-late.mk" line 38: while evaluating variable "VAR" with value "${${UNDEF} != "no":?:}": while evaluating condition " != "no"": Bad condition
+make: "cond-late.mk" line 38: Bad condition
+ while evaluating condition " != "no""
+ while evaluating variable "VAR" with value "${${UNDEF} != "no":?:}"
in directory <curdir>
make: Fatal errors encountered -- cannot continue
make: stopped making "do-parse-time" in unit-tests
diff --git a/unit-tests/cond-late.mk b/unit-tests/cond-late.mk
index 4d8c4fbd5d98..a8f381590a6e 100644
--- a/unit-tests/cond-late.mk
+++ b/unit-tests/cond-late.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-late.mk,v 1.8 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: cond-late.mk,v 1.9 2024/08/29 20:20:35 rillig Exp $
#
# Using the :? modifier, expressions can contain conditional
# expressions that are evaluated late, at expansion time.
@@ -34,7 +34,7 @@ cond-literal:
.if make(do-parse-time)
VAR= ${${UNDEF} != "no":?:}
-# expect+1: while evaluating variable "VAR" with value "${${UNDEF} != "no":?:}": while evaluating condition " != "no"": Bad condition
+# expect+1: Bad condition
. if empty(VAR:Mpattern)
. endif
.endif
diff --git a/unit-tests/cond-op-and.exp b/unit-tests/cond-op-and.exp
index 6d2263dc5d56..ac085e77ce74 100644
--- a/unit-tests/cond-op-and.exp
+++ b/unit-tests/cond-op-and.exp
@@ -1,6 +1,6 @@
-make: "cond-op-and.mk" line 36: Malformed conditional (0 || (${DEF} && ${UNDEF}))
-make: "cond-op-and.mk" line 41: Malformed conditional (0 || (${UNDEF} && ${UNDEF}))
-make: "cond-op-and.mk" line 44: Malformed conditional (0 || (!${UNDEF} && ${UNDEF}))
+make: "cond-op-and.mk" line 36: Variable "UNDEF" is undefined
+make: "cond-op-and.mk" line 41: Variable "UNDEF" is undefined
+make: "cond-op-and.mk" line 44: Variable "UNDEF" is undefined
make: "cond-op-and.mk" line 60: Unknown operator '&'
make: "cond-op-and.mk" line 66: Unknown operator '&'
make: "cond-op-and.mk" line 72: Unknown operator '&'
diff --git a/unit-tests/cond-op-and.mk b/unit-tests/cond-op-and.mk
index b49fb079b3cf..5d7f8a06800a 100644
--- a/unit-tests/cond-op-and.mk
+++ b/unit-tests/cond-op-and.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-and.mk,v 1.10 2024/07/06 21:21:10 rillig Exp $
+# $NetBSD: cond-op-and.mk,v 1.12 2025/01/11 21:21:33 rillig Exp $
#
# Tests for the && operator in .if conditions.
@@ -32,15 +32,15 @@
# Test combinations of outer '||' with inner '&&', to ensure that the operands
# of the inner '&&' are only evaluated if necessary.
DEF= defined
-# expect+1: Malformed conditional (0 || (${DEF} && ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 0 || (${DEF} && ${UNDEF})
.endif
.if 0 || (!${DEF} && ${UNDEF})
.endif
-# expect+1: Malformed conditional (0 || (${UNDEF} && ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 0 || (${UNDEF} && ${UNDEF})
.endif
-# expect+1: Malformed conditional (0 || (!${UNDEF} && ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 0 || (!${UNDEF} && ${UNDEF})
.endif
.if 1 || (${DEF} && ${UNDEF})
diff --git a/unit-tests/cond-op-not.exp b/unit-tests/cond-op-not.exp
index 86d8289d9233..747720159906 100644
--- a/unit-tests/cond-op-not.exp
+++ b/unit-tests/cond-op-not.exp
@@ -3,7 +3,7 @@ make: "cond-op-not.mk" line 39: Not space evaluates to false.
make: "cond-op-not.mk" line 44: Not 0 evaluates to true.
make: "cond-op-not.mk" line 53: Not 1 evaluates to false.
make: "cond-op-not.mk" line 60: Not word evaluates to false.
-make: "cond-op-not.mk" line 65: Malformed conditional (!)
+make: "cond-op-not.mk" line 65: Malformed conditional '!'
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/cond-op-not.mk b/unit-tests/cond-op-not.mk
index 28f835fa3cbd..4565b60b115d 100644
--- a/unit-tests/cond-op-not.mk
+++ b/unit-tests/cond-op-not.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-not.mk,v 1.8 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-op-not.mk,v 1.9 2024/08/06 18:00:17 rillig Exp $
#
# Tests for the ! operator in .if conditions, which negates its argument.
@@ -61,7 +61,7 @@
.endif
# A single exclamation mark is a parse error.
-# expect+1: Malformed conditional (!)
+# expect+1: Malformed conditional '!'
.if !
. error
.else
diff --git a/unit-tests/cond-op-or.exp b/unit-tests/cond-op-or.exp
index dddd29d5bca0..f8b6de761755 100644
--- a/unit-tests/cond-op-or.exp
+++ b/unit-tests/cond-op-or.exp
@@ -1,6 +1,6 @@
-make: "cond-op-or.mk" line 36: Malformed conditional (1 && (!${DEF} || ${UNDEF}))
-make: "cond-op-or.mk" line 41: Malformed conditional (1 && (!${UNDEF} || ${UNDEF}))
-make: "cond-op-or.mk" line 44: Malformed conditional (1 && (${UNDEF} || ${UNDEF}))
+make: "cond-op-or.mk" line 36: Variable "UNDEF" is undefined
+make: "cond-op-or.mk" line 41: Variable "UNDEF" is undefined
+make: "cond-op-or.mk" line 44: Variable "UNDEF" is undefined
make: "cond-op-or.mk" line 60: Unknown operator '|'
make: "cond-op-or.mk" line 66: Unknown operator '|'
make: "cond-op-or.mk" line 72: Unknown operator '|'
diff --git a/unit-tests/cond-op-or.mk b/unit-tests/cond-op-or.mk
index b01fcaf04a28..381516499093 100644
--- a/unit-tests/cond-op-or.mk
+++ b/unit-tests/cond-op-or.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-or.mk,v 1.12 2024/07/06 21:21:10 rillig Exp $
+# $NetBSD: cond-op-or.mk,v 1.14 2025/01/11 21:21:33 rillig Exp $
#
# Tests for the || operator in .if conditions.
@@ -32,15 +32,15 @@
# Test combinations of outer '&&' with inner '||', to ensure that the operands
# of the inner '||' are only evaluated if necessary.
DEF= defined
-# expect+1: Malformed conditional (1 && (!${DEF} || ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 1 && (!${DEF} || ${UNDEF})
.endif
.if 1 && (${DEF} || ${UNDEF})
.endif
-# expect+1: Malformed conditional (1 && (!${UNDEF} || ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 1 && (!${UNDEF} || ${UNDEF})
.endif
-# expect+1: Malformed conditional (1 && (${UNDEF} || ${UNDEF}))
+# expect+1: Variable "UNDEF" is undefined
.if 1 && (${UNDEF} || ${UNDEF})
.endif
.if 0 && (!${DEF} || ${UNDEF})
diff --git a/unit-tests/cond-op-parentheses.exp b/unit-tests/cond-op-parentheses.exp
index f14e62b6d4e3..c11c9eb1be1d 100644
--- a/unit-tests/cond-op-parentheses.exp
+++ b/unit-tests/cond-op-parentheses.exp
@@ -1,7 +1,7 @@
make: "cond-op-parentheses.mk" line 22: Comparison with '>' requires both operands '3' and '(2' to be numeric
-make: "cond-op-parentheses.mk" line 25: Malformed conditional ((3) > 2)
-make: "cond-op-parentheses.mk" line 44: Malformed conditional (()
-make: "cond-op-parentheses.mk" line 58: Malformed conditional ())
+make: "cond-op-parentheses.mk" line 25: Malformed conditional '(3) > 2'
+make: "cond-op-parentheses.mk" line 44: Malformed conditional '('
+make: "cond-op-parentheses.mk" line 58: Malformed conditional ')'
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/cond-op-parentheses.mk b/unit-tests/cond-op-parentheses.mk
index b6c9bd3c0e9d..17d5d767cd41 100644
--- a/unit-tests/cond-op-parentheses.mk
+++ b/unit-tests/cond-op-parentheses.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op-parentheses.mk,v 1.7 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-op-parentheses.mk,v 1.8 2024/08/06 18:00:17 rillig Exp $
#
# Tests for parentheses in .if conditions, which group expressions to override
# the precedence of the operators '!', '&&' and '||'. Parentheses cannot be
@@ -21,7 +21,7 @@
# expect+1: Comparison with '>' requires both operands '3' and '(2' to be numeric
.if 3 > (2)
.endif
-# expect+1: Malformed conditional ((3) > 2)
+# expect+1: Malformed conditional '(3) > 2'
.if (3) > 2
.endif
@@ -40,7 +40,7 @@
.endif
# An unbalanced opening parenthesis is a parse error.
-# expect+1: Malformed conditional (()
+# expect+1: Malformed conditional '('
.if (
. error
.else
@@ -54,7 +54,7 @@
# TOK_TRUE, TOK_FALSE or TOK_ERROR. In cond.c 1.241, the return type of that
# function was changed to a properly restricted enum type, to prevent this bug
# from occurring again.
-# expect+1: Malformed conditional ())
+# expect+1: Malformed conditional ')'
.if )
. error
.else
diff --git a/unit-tests/cond-op.exp b/unit-tests/cond-op.exp
index 1ce5436f023a..3747557789a7 100644
--- a/unit-tests/cond-op.exp
+++ b/unit-tests/cond-op.exp
@@ -1,7 +1,7 @@
-make: "cond-op.mk" line 51: Malformed conditional ("!word" == !word)
-make: "cond-op.mk" line 72: Malformed conditional (0 ${ERR::=evaluated})
+make: "cond-op.mk" line 51: Malformed conditional '"!word" == !word'
+make: "cond-op.mk" line 72: Malformed conditional '0 ${ERR::=evaluated}'
make: "cond-op.mk" line 77: A misplaced expression after 0 is not evaluated.
-make: "cond-op.mk" line 82: Malformed conditional (1 ${ERR::=evaluated})
+make: "cond-op.mk" line 82: Malformed conditional '1 ${ERR::=evaluated}'
make: "cond-op.mk" line 87: A misplaced expression after 1 is not evaluated.
make: "cond-op.mk" line 93: A B C => (A || B) && C A || B && C A || (B && C)
make: "cond-op.mk" line 108: 0 0 0 => 0 0 0
@@ -12,10 +12,10 @@ make: "cond-op.mk" line 108: 1 0 0 => 0 1 1
make: "cond-op.mk" line 108: 1 0 1 => 1 1 1
make: "cond-op.mk" line 108: 1 1 0 => 0 1 1
make: "cond-op.mk" line 108: 1 1 1 => 1 1 1
-make: "cond-op.mk" line 120: Malformed conditional (1 &&)
-make: "cond-op.mk" line 129: Malformed conditional (0 &&)
-make: "cond-op.mk" line 138: Malformed conditional (1 ||)
-make: "cond-op.mk" line 148: Malformed conditional (0 ||)
+make: "cond-op.mk" line 120: Malformed conditional '1 &&'
+make: "cond-op.mk" line 129: Malformed conditional '0 &&'
+make: "cond-op.mk" line 138: Malformed conditional '1 ||'
+make: "cond-op.mk" line 148: Malformed conditional '0 ||'
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/cond-op.mk b/unit-tests/cond-op.mk
index 6371e4db0594..6493d887c806 100644
--- a/unit-tests/cond-op.mk
+++ b/unit-tests/cond-op.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-op.mk,v 1.16 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-op.mk,v 1.17 2024/08/06 18:00:17 rillig Exp $
#
# Tests for operators like &&, ||, ! in .if conditions.
#
@@ -47,7 +47,7 @@
# appear unquoted. If any, it must be enclosed in quotes.
# In any case, it is not interpreted as a negation of an unquoted string.
# See CondParser_String.
-# expect+1: Malformed conditional ("!word" == !word)
+# expect+1: Malformed conditional '"!word" == !word'
.if "!word" == !word
. error
.endif
@@ -68,7 +68,7 @@
# next token, even though in this position of the condition, only comparison
# operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed.
.undef ERR
-# expect+1: Malformed conditional (0 ${ERR::=evaluated})
+# expect+1: Malformed conditional '0 ${ERR::=evaluated}'
.if 0 ${ERR::=evaluated}
. error
.endif
@@ -78,7 +78,7 @@
.endif
.undef ERR
-# expect+1: Malformed conditional (1 ${ERR::=evaluated})
+# expect+1: Malformed conditional '1 ${ERR::=evaluated}'
.if 1 ${ERR::=evaluated}
. error
.endif
@@ -116,7 +116,7 @@
# This condition is obviously malformed. It is properly detected and also
# was properly detected before 2021-01-19, but only because the left hand
# side of the '&&' evaluated to true.
-# expect+1: Malformed conditional (1 &&)
+# expect+1: Malformed conditional '1 &&'
.if 1 &&
. error
.else
@@ -125,7 +125,7 @@
# This obviously malformed condition was not detected as such before cond.c
# 1.238 from 2021-01-19.
-# expect+1: Malformed conditional (0 &&)
+# expect+1: Malformed conditional '0 &&'
.if 0 &&
. error
.else
@@ -134,7 +134,7 @@
# This obviously malformed condition was not detected as such before cond.c
# 1.238 from 2021-01-19.
-# expect+1: Malformed conditional (1 ||)
+# expect+1: Malformed conditional '1 ||'
.if 1 ||
. error
.else
@@ -144,7 +144,7 @@
# This condition is obviously malformed. It is properly detected and also
# was properly detected before 2021-01-19, but only because the left hand
# side of the '||' evaluated to false.
-# expect+1: Malformed conditional (0 ||)
+# expect+1: Malformed conditional '0 ||'
.if 0 ||
. error
.else
diff --git a/unit-tests/cond-token-number.exp b/unit-tests/cond-token-number.exp
index aaa4ec7fe184..eb0870521af1 100644
--- a/unit-tests/cond-token-number.exp
+++ b/unit-tests/cond-token-number.exp
@@ -1,7 +1,7 @@
-make: "cond-token-number.mk" line 16: Malformed conditional (-0)
-make: "cond-token-number.mk" line 27: Malformed conditional (+0)
-make: "cond-token-number.mk" line 38: Malformed conditional (!-1)
-make: "cond-token-number.mk" line 49: Malformed conditional (!+1)
+make: "cond-token-number.mk" line 16: Malformed conditional '-0'
+make: "cond-token-number.mk" line 27: Malformed conditional '+0'
+make: "cond-token-number.mk" line 38: Malformed conditional '!-1'
+make: "cond-token-number.mk" line 49: Malformed conditional '!+1'
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/cond-token-number.mk b/unit-tests/cond-token-number.mk
index 7e73f8b76f94..329a51d73b2a 100644
--- a/unit-tests/cond-token-number.mk
+++ b/unit-tests/cond-token-number.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-number.mk,v 1.10 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: cond-token-number.mk,v 1.11 2024/08/06 18:00:17 rillig Exp $
#
# Tests for number tokens in .if conditions.
#
@@ -12,7 +12,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional (-0)
+# expect+1: Malformed conditional '-0'
.if -0
. error
.else
@@ -23,7 +23,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional (+0)
+# expect+1: Malformed conditional '+0'
.if +0
. error
.else
@@ -34,7 +34,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional (!-1)
+# expect+1: Malformed conditional '!-1'
.if !-1
. error
.else
@@ -45,7 +45,7 @@
# accepted by the condition parser.
#
# See the ch_isdigit call in CondParser_String.
-# expect+1: Malformed conditional (!+1)
+# expect+1: Malformed conditional '!+1'
.if !+1
. error
.else
diff --git a/unit-tests/cond-token-plain.exp b/unit-tests/cond-token-plain.exp
index 8044f3bac826..f3425e7f899d 100644
--- a/unit-tests/cond-token-plain.exp
+++ b/unit-tests/cond-token-plain.exp
@@ -41,7 +41,7 @@ make: "cond-token-plain.mk" line 144: Numbers can be composed from literals and
CondParser_Eval: "" ==
make: "cond-token-plain.mk" line 151: Missing right-hand side of operator '=='
CondParser_Eval: == ""
-make: "cond-token-plain.mk" line 160: Malformed conditional (== "")
+make: "cond-token-plain.mk" line 160: Malformed conditional '== ""'
CondParser_Eval: \\
make: "cond-token-plain.mk" line 176: The variable '\\' is not defined.
CondParser_Eval: \\
@@ -49,15 +49,15 @@ make: "cond-token-plain.mk" line 182: Now the variable '\\' is defined.
CondParser_Eval: "unquoted\"quoted" != unquoted"quoted
Comparing "unquoted"quoted" != "unquoted"quoted"
CondParser_Eval: $$$$$$$$ != ""
-make: "cond-token-plain.mk" line 197: Malformed conditional ($$$$$$$$ != "")
+make: "cond-token-plain.mk" line 197: Malformed conditional '$$$$$$$$ != ""'
CondParser_Eval: left == right
-make: "cond-token-plain.mk" line 206: Malformed conditional (left == right)
+make: "cond-token-plain.mk" line 206: Malformed conditional 'left == right'
CondParser_Eval: ${0:?:} || left == right
CondParser_Eval: 0
-make: "cond-token-plain.mk" line 212: Malformed conditional (${0:?:} || left == right)
+make: "cond-token-plain.mk" line 212: Malformed conditional '${0:?:} || left == right'
CondParser_Eval: left == right || ${0:?:}
-make: "cond-token-plain.mk" line 217: Malformed conditional (left == right || ${0:?:})
-make: "cond-token-plain.mk" line 236: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
+make: "cond-token-plain.mk" line 217: Malformed conditional 'left == right || ${0:?:}'
+make: "cond-token-plain.mk" line 236: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""'
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-token-plain.mk b/unit-tests/cond-token-plain.mk
index 79fcc771a855..4509c1feca80 100644
--- a/unit-tests/cond-token-plain.mk
+++ b/unit-tests/cond-token-plain.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-plain.mk,v 1.19 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: cond-token-plain.mk,v 1.20 2024/08/06 18:00:17 rillig Exp $
#
# Tests for plain tokens (that is, string literals without quotes)
# in .if conditions. These are also called bare words.
@@ -156,7 +156,7 @@ VAR= defined
# If the left-hand side is missing, it's a parse error as well, but without
# a specific error message.
-# expect+1: Malformed conditional (== "")
+# expect+1: Malformed conditional '== ""'
.if == ""
. error
.else
@@ -193,7 +193,7 @@ ${:U\\\\}= backslash
# FIXME: In CondParser_String, Var_Parse returns var_Error without a
# corresponding error message.
-# expect+1: Malformed conditional ($$$$$$$$ != "")
+# expect+1: Malformed conditional '$$$$$$$$ != ""'
.if $$$$$$$$ != ""
. error
.else
@@ -202,18 +202,18 @@ ${:U\\\\}= backslash
# In a condition in an .if directive, the left-hand side must not be an
# unquoted string literal.
-# expect+1: Malformed conditional (left == right)
+# expect+1: Malformed conditional 'left == right'
.if left == right
.endif
# Before cond.c 1.276 from 2021-09-21, an expression containing the
# modifier ':?:' allowed unquoted string literals for the rest of the
# condition. This was an unintended implementation mistake.
-# expect+1: Malformed conditional (${0:?:} || left == right)
+# expect+1: Malformed conditional '${0:?:} || left == right'
.if ${0:?:} || left == right
.endif
# This affected only the comparisons after the expression, so the following
# was still a syntax error.
-# expect+1: Malformed conditional (left == right || ${0:?:})
+# expect+1: Malformed conditional 'left == right || ${0:?:}'
.if left == right || ${0:?:}
.endif
@@ -232,7 +232,7 @@ ${:U\\\\}= backslash
# for the second time. The right-hand side of a comparison may be a bare
# word, but that side has no risk of being parsed more than once.
#
-# expect+1: Malformed conditional (VAR.${IF_COUNT::+=1} != "")
+# expect+1: Malformed conditional 'VAR.${IF_COUNT::+=1} != ""'
.if VAR.${IF_COUNT::+=1} != ""
. error
.else
diff --git a/unit-tests/cond-token-string.exp b/unit-tests/cond-token-string.exp
index f970a21bf69f..e48244a457e9 100644
--- a/unit-tests/cond-token-string.exp
+++ b/unit-tests/cond-token-string.exp
@@ -1,18 +1,18 @@
-make: "cond-token-string.mk" line 15: while evaluating "${:Uvalue:Z}"" with value "value": Unknown modifier "Z"
-make: "cond-token-string.mk" line 15: Malformed conditional ("" != "${:Uvalue:Z}")
-make: "cond-token-string.mk" line 25: xvalue is not defined.
-make: "cond-token-string.mk" line 32: Malformed conditional (x${:Uvalue} == "")
-make: "cond-token-string.mk" line 42: Expected.
+make: "cond-token-string.mk" line 14: Unknown modifier "Z"
+ while evaluating "${:Uvalue:Z}"" with value "value"
+make: "cond-token-string.mk" line 24: xvalue is not defined.
+make: "cond-token-string.mk" line 31: Malformed conditional 'x${:Uvalue} == ""'
+make: "cond-token-string.mk" line 41: Expected.
CondParser_Eval: "UNDEF"
-make: "cond-token-string.mk" line 52: The string literal "UNDEF" is not empty.
+make: "cond-token-string.mk" line 51: The string literal "UNDEF" is not empty.
CondParser_Eval: " "
-make: "cond-token-string.mk" line 61: The string literal " " is not empty, even though it consists of whitespace only.
+make: "cond-token-string.mk" line 60: The string literal " " is not empty, even though it consists of whitespace only.
CondParser_Eval: "${UNDEF}"
-make: "cond-token-string.mk" line 71: An undefined variable in quotes expands to an empty string, which then evaluates to false.
+make: "cond-token-string.mk" line 70: An undefined variable in quotes expands to an empty string, which then evaluates to false.
CondParser_Eval: "${:Uvalue}"
-make: "cond-token-string.mk" line 77: A nonempty expression evaluates to true.
+make: "cond-token-string.mk" line 76: A nonempty expression evaluates to true.
CondParser_Eval: "${:U}"
-make: "cond-token-string.mk" line 86: An empty variable evaluates to false.
+make: "cond-token-string.mk" line 85: An empty variable evaluates to false.
CondParser_Eval: ("${VAR}")
CondParser_Eval: "quoted" == quoted
Comparing "quoted" == "quoted"
diff --git a/unit-tests/cond-token-string.mk b/unit-tests/cond-token-string.mk
index d24645748233..45e9cf8a8469 100644
--- a/unit-tests/cond-token-string.mk
+++ b/unit-tests/cond-token-string.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-string.mk,v 1.11 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: cond-token-string.mk,v 1.15 2025/01/11 20:54:45 rillig Exp $
#
# Tests for quoted string literals in .if conditions.
#
@@ -10,8 +10,7 @@
# Cover the code in CondParser_String that frees the memory after parsing
# an expression based on an undefined variable.
-# expect+2: Malformed conditional ("" != "${:Uvalue:Z}")
-# expect+1: while evaluating "${:Uvalue:Z}"" with value "value": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.if "" != "${:Uvalue:Z}"
. error
.else
@@ -28,7 +27,7 @@
# The 'x' produces a "Malformed conditional" since the left-hand side of a
# comparison in an .if directive must be either an expression, a
# quoted string literal or a number that starts with a digit.
-# expect+1: Malformed conditional (x${:Uvalue} == "")
+# expect+1: Malformed conditional 'x${:Uvalue} == ""'
.if x${:Uvalue} == ""
. error
.else
diff --git a/unit-tests/cond-token-var.exp b/unit-tests/cond-token-var.exp
index d84ca56e981b..a7e5c8ab5531 100644
--- a/unit-tests/cond-token-var.exp
+++ b/unit-tests/cond-token-var.exp
@@ -1,7 +1,21 @@
-make: "cond-token-var.mk" line 21: ok
-make: "cond-token-var.mk" line 28: Malformed conditional (${UNDEF} == ${DEF})
-make: "cond-token-var.mk" line 34: Malformed conditional (${DEF} == ${UNDEF})
-make: "cond-token-var.mk" line 44: Malformed conditional (${UNDEF})
+make: "cond-token-var.mk" line 23: ok
+make: "cond-token-var.mk" line 30: Variable "UNDEF" is undefined
+make: "cond-token-var.mk" line 36: Variable "UNDEF" is undefined
+make: "cond-token-var.mk" line 46: Variable "UNDEF" is undefined
+make: "cond-token-var.mk" line 64: Variable "U" is undefined
+make: "cond-token-var.mk" line 69: Variable "U" is undefined
+make: "cond-token-var.mk" line 78: Variable "U" is undefined
+Var_Parse: ${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3} (eval)
+make: "cond-token-var.mk" line 106: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}'
+Var_Parse: ${DEF}y == "${UNDEF2}" || 0x${UNDEF3} (eval)
+make: "cond-token-var.mk" line 111: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}'
+Var_Parse: ${DEF}y == "${DEF}" || 0x${UNDEF3} (eval)
+make: "cond-token-var.mk" line 116: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}'
+Global: VAR.param = value of VAR.param
+Var_Parse: ${VAR.param$U} (eval-defined-loud)
+Var_Parse: $U} (eval)
+Global: .MAKEFLAGS = -r -k -d v -d
+Global: .MAKEFLAGS = -r -k -d v -d 0
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-token-var.mk b/unit-tests/cond-token-var.mk
index c6471756a3dd..972a6b3c3d4b 100644
--- a/unit-tests/cond-token-var.mk
+++ b/unit-tests/cond-token-var.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-token-var.mk,v 1.8 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: cond-token-var.mk,v 1.11 2025/01/11 21:21:33 rillig Exp $
#
# Tests for expressions in .if conditions.
#
@@ -13,8 +13,10 @@
# Well, except for the assignment modifiers, these do indeed change the value
# of the variable.
+D= defined
DEF= defined
+
# A defined variable may appear on either side of the comparison.
.if ${DEF} == ${DEF}
# expect+1: ok
@@ -24,13 +26,13 @@ DEF= defined
.endif
# A variable that appears on the left-hand side must be defined.
-# expect+1: Malformed conditional (${UNDEF} == ${DEF})
+# expect+1: Variable "UNDEF" is undefined
.if ${UNDEF} == ${DEF}
. error
.endif
# A variable that appears on the right-hand side must be defined.
-# expect+1: Malformed conditional (${DEF} == ${UNDEF})
+# expect+1: Variable "UNDEF" is undefined
.if ${DEF} == ${UNDEF}
. error
.endif
@@ -40,7 +42,7 @@ DEF= defined
.endif
# An undefined variable on its own generates a parse error.
-# expect+1: Malformed conditional (${UNDEF})
+# expect+1: Variable "UNDEF" is undefined
.if ${UNDEF}
.endif
@@ -49,6 +51,34 @@ DEF= defined
.if ${UNDEF:U}
.endif
+
+# The same as above, for single-letter variables without braces or
+# parentheses.
+
+# A defined variable may appear on either side of the comparison.
+.if $D == $D
+.endif
+
+# A variable on the left-hand side must be defined.
+# expect+1: Variable "U" is undefined
+.if $U == $D
+.endif
+
+# A variable on the right-hand side must be defined.
+# expect+1: Variable "U" is undefined
+.if $D == $U
+.endif
+
+# A defined variable may appear as an expression of its own.
+.if $D
+.endif
+
+# An undefined variable without a comparison operator generates a parse error.
+# expect+1: Variable "U" is undefined
+.if $U
+.endif
+
+
# If the value of the expression is a number, it is compared against
# zero.
.if ${:U0}
@@ -69,3 +99,30 @@ DEF= defined
.if !${:Uanything}
. error
.endif
+
+.MAKEFLAGS: -dv
+# The left-hand side of a comparison must not be an unquoted word.
+# expect+1: Malformed conditional 'x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}'
+.if x${UNDEF1}y == "${UNDEF2}" || 0x${UNDEF3}
+.endif
+
+# The left-hand side of a comparison must not be an unquoted word.
+# expect+1: Malformed conditional 'x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}'
+.if x${DEF}y == "${UNDEF2}" || 0x${UNDEF3}
+.endif
+
+# The left-hand side of a comparison must not be an unquoted word.
+# expect+1: Malformed conditional 'x${DEF}y == "${DEF}" || 0x${UNDEF3}'
+.if x${DEF}y == "${DEF}" || 0x${UNDEF3}
+.endif
+
+# An expression in a condition must not be based on an undefined variable,
+# but undefined variables may occur in the variable name or in modifiers.
+#
+# expect: Var_Parse: ${VAR.param$U} (eval-defined-loud)
+# expect: Var_Parse: $U} (eval)
+VAR.param= value of VAR.param
+.if ${VAR.param$U}
+.endif
+
+.MAKEFLAGS: -d0
diff --git a/unit-tests/cond-undef-lint.exp b/unit-tests/cond-undef-lint.exp
index efab46113f67..ce619293a35b 100755
--- a/unit-tests/cond-undef-lint.exp
+++ b/unit-tests/cond-undef-lint.exp
@@ -1,10 +1,6 @@
-make: "cond-undef-lint.mk" line 25: Variable "UNDEF" is undefined
-make: "cond-undef-lint.mk" line 25: Malformed conditional (${UNDEF})
-make: "cond-undef-lint.mk" line 43: Variable "UNDEF" is undefined
-make: "cond-undef-lint.mk" line 43: Variable "VAR." is undefined
-make: "cond-undef-lint.mk" line 43: Malformed conditional (${VAR.${UNDEF}})
-make: "cond-undef-lint.mk" line 56: Variable "VAR.defined" is undefined
-make: "cond-undef-lint.mk" line 56: Malformed conditional (${VAR.${DEF}})
+make: "cond-undef-lint.mk" line 24: Variable "UNDEF" is undefined
+make: "cond-undef-lint.mk" line 35: Variable "VAR." is undefined
+make: "cond-undef-lint.mk" line 45: Variable "VAR.defined" is undefined
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/cond-undef-lint.mk b/unit-tests/cond-undef-lint.mk
index 6fd353dc60e2..1b4d19636c41 100755
--- a/unit-tests/cond-undef-lint.mk
+++ b/unit-tests/cond-undef-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: cond-undef-lint.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: cond-undef-lint.mk,v 1.8 2025/01/11 21:21:33 rillig Exp $
#
# Tests for defined and undefined variables in .if conditions, in lint mode.
#
@@ -20,7 +20,6 @@ DEF= defined
.endif
# Since the condition fails to evaluate, neither of the branches is taken.
-# expect+2: Malformed conditional (${UNDEF})
# expect+1: Variable "UNDEF" is undefined
.if ${UNDEF}
. error
@@ -32,27 +31,17 @@ DEF= defined
# mistake. The variable UNDEF, as used here, can be easily turned into
# an expression that is always defined, using the :U modifier.
#
-# The outer expression does not generate an error message since there was
-# already an error evaluating this variable's name.
-#
-# TODO: Suppress the error message "Variable VAR. is undefined". That part
-# of the expression must not be evaluated at all.
-# expect+3: Variable "UNDEF" is undefined
-# expect+2: Variable "VAR." is undefined
-# expect+1: Malformed conditional (${VAR.${UNDEF}})
+# expect+1: Variable "VAR." is undefined
.if ${VAR.${UNDEF}}
. error
.else
. error
.endif
-# The variable VAR.defined is not defined and thus generates an error message.
+# The inner variable DEF is defined, but the resulting name VAR.defined
+# refers to an undefined variable, thus an error message.
#
-# TODO: This pattern looks a lot like CFLAGS.${OPSYS}, which is at least
-# debatable. Or would any practical use of CFLAGS.${OPSYS} be via an indirect
-# expression, as in the next example?
-# expect+2: Variable "VAR.defined" is undefined
-# expect+1: Malformed conditional (${VAR.${DEF}})
+# expect+1: Variable "VAR.defined" is undefined
.if ${VAR.${DEF}}
. error
.else
diff --git a/unit-tests/dep-var.exp b/unit-tests/dep-var.exp
index 194c723fc1a8..4a570206b300 100755
--- a/unit-tests/dep-var.exp
+++ b/unit-tests/dep-var.exp
@@ -1,4 +1,4 @@
-Var_Parse: ${UNDEF1} (eval-defined)
+Var_Parse: ${UNDEF1} (eval)
Global: .ALLTARGETS = all
Global: .ALLTARGETS = all ${DEF2}
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b
@@ -10,9 +10,9 @@ Global: INDIRECT_3 = indirect
Global: UNDEF1 = undef1
Global: DEF2 = def2
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$)
-Var_Parse: ${:U\$)}: (eval-defined)
-Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
-Result of ${:U\$)} is "$)" (eval-defined, defined)
+Var_Parse: ${:U\$)}: (eval)
+Evaluating modifier ${:U...} on value "" (eval, undefined)
+Result of ${:U\$)} is "$)" (eval, defined)
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2
Global: .ALLTARGETS = all ${DEF2} a-${DEF2}-b ${UNDEF3} 1-${INDIRECT_1}-1 $$) undef1 def2 a-def2-b
diff --git a/unit-tests/dep-var.mk b/unit-tests/dep-var.mk
index fa720c3af610..ed8549583b82 100755
--- a/unit-tests/dep-var.mk
+++ b/unit-tests/dep-var.mk
@@ -1,4 +1,4 @@
-# $NetBSD: dep-var.mk,v 1.12 2024/06/02 15:31:26 rillig Exp $
+# $NetBSD: dep-var.mk,v 1.13 2025/01/14 21:23:17 rillig Exp $
#
# Tests for variable references in dependency declarations.
#
@@ -7,10 +7,8 @@
.MAKEFLAGS: -dv
-# expect: Var_Parse: ${UNDEF1} (eval-defined)
-# Even though undefined expressions should lead to errors, no error message is
-# generated for this line. The expression ${UNDEF1} simply expands
-# to an empty string.
+# In a dependency line, an undefined expressions expands to an empty string.
+# expect: Var_Parse: ${UNDEF1} (eval)
all: ${UNDEF1}
# Using a double dollar in order to circumvent immediate expression expansion
@@ -21,11 +19,7 @@ all: ${UNDEF1}
# is defined, so everything's fine.
all: $${DEF2} a-$${DEF2}-b
-# This variable is not defined at all.
-# XXX: The -dv log says later when expanding the sources of 'all':
-# Var_Parse: ${UNDEF3} (eval-defined)
-# but no error message is generated for this line, just like for UNDEF1.
-# The expression ${UNDEF3} simply expands to an empty string.
+# This variable is neither defined now nor later.
all: $${UNDEF3}
# Try out how many levels of indirection are really expanded in dependency
@@ -83,14 +77,10 @@ all: $$$$)
# Since 2020-09-13, this generates a parse error in lint mode (-dL), but not
# in normal mode since ParseDependency does not handle any errors after
# calling Var_Parse.
-# expect: Var_Parse: ${:U\$)}: (eval-defined)
+# expect: Var_Parse: ${:U\$)}: (eval)
# expect: Var_Parse: $INDIRECT_2-2-1 $): (parse)
# expect: Var_Parse: $): (parse)
undef1 def2 a-def2-b 1-2-$$INDIRECT_2-2-1 ${:U\$)}:
@echo ${.TARGET:Q}
.MAKEFLAGS: -d0
-
-# XXX: The exit status is still 0, even though Parse_Error is called with
-# PARSE_FATAL in SuffExpandChildren. The exit status is only affected by
-# parse errors when they occur in the parsing phase, see Parse_File.
diff --git a/unit-tests/deptgt-makeflags.exp b/unit-tests/deptgt-makeflags.exp
index ea29f76ad464..099ce8e15ed5 100644
--- a/unit-tests/deptgt-makeflags.exp
+++ b/unit-tests/deptgt-makeflags.exp
@@ -2,7 +2,7 @@ Global: ignoring delete 'DOLLAR' as it is not found
Command: DOLLAR = $$$$
Global: .MAKEOVERRIDES = VAR DOLLAR
CondParser_Eval: ${DOLLAR} != "\$\$"
-Var_Parse: ${DOLLAR} != "\$\$" (eval-defined)
+Var_Parse: ${DOLLAR} != "\$\$" (eval-defined-loud)
Comparing "$$" != "$$"
Global: .MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d
Global: .MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d 0
diff --git a/unit-tests/deptgt-order.exp b/unit-tests/deptgt-order.exp
index ecbf03fcc572..c5cdaa4cbe2b 100644
--- a/unit-tests/deptgt-order.exp
+++ b/unit-tests/deptgt-order.exp
@@ -1,9 +1,9 @@
-Parsing line 15: .ORDER: three one
+Parsing deptgt-order.mk:15: .ORDER: three one
ParseDependency(.ORDER: three one)
# .ORDER forces 'three' to be made before 'one'
# three, unmade, type OP_DEPENDS|OP_PHONY|OP_HAS_COMMANDS, flags none
# one, unmade, type OP_DEPENDS|OP_PHONY, flags none
-Parsing line 16: .MAKEFLAGS: -d0
+Parsing deptgt-order.mk:16: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
: 'Making two out of one.'
: 'Making three out of two.'
diff --git a/unit-tests/deptgt.exp b/unit-tests/deptgt.exp
index ae7315716d8c..8a70e2495038 100644
--- a/unit-tests/deptgt.exp
+++ b/unit-tests/deptgt.exp
@@ -1,18 +1,26 @@
make: "deptgt.mk" line 11: warning: Extra target '.PHONY' ignored
make: "deptgt.mk" line 30: Unassociated shell command ": command3 # parse error, since targets == NULL"
-Parsing line 36: ${:U}: empty-source
+Parsing deptgt.mk:36: ${:U}: empty-source
ParseDependency(: empty-source)
-Parsing line 37: : command for empty targets list
-Parsing line 38: : empty-source
+Parsing deptgt.mk:37: : command for empty targets list
+Parsing deptgt.mk:38: : empty-source
ParseDependency(: empty-source)
-Parsing line 39: : command for empty targets list
-Parsing line 40: .MAKEFLAGS: -d0
+Parsing deptgt.mk:39: : command for empty targets list
+Parsing deptgt.mk:40: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
-make: "deptgt.mk" line 45: while evaluating "${:U:Z}:" with value "": Unknown modifier "Z"
-make: "deptgt.mk" line 49: while parsing "${:U:Z}:": Unknown modifier "Z"
-make: "deptgt.mk" line 52: warning: Extra target 'ordinary' ignored
-make: "deptgt.mk" line 55: warning: Extra target (ordinary) ignored
-make: "deptgt.mk" line 58: warning: Special and mundane targets don't mix. Mundane ones ignored
+Var_Parse: ${UNDEF}: depsrc-${UNDEF} (eval)
+Var_Parse: ${UNDEF} (eval)
+Global: .ALLTARGETS = target1 target2 sources empty-source deptgt-
+Global: .ALLTARGETS = target1 target2 sources empty-source deptgt- depsrc-
+Global: .MAKEFLAGS = -r -k -d p -d 0 -d v -d
+Global: .MAKEFLAGS = -r -k -d p -d 0 -d v -d 0
+make: "deptgt.mk" line 51: Unknown modifier "Z"
+ while evaluating "${:U:Z}:" with value ""
+make: "deptgt.mk" line 55: Unknown modifier "Z"
+ while parsing "${:U:Z}:"
+make: "deptgt.mk" line 58: warning: Extra target 'ordinary' ignored
+make: "deptgt.mk" line 61: warning: Extra target (ordinary) ignored
+make: "deptgt.mk" line 64: warning: Special and mundane targets don't mix. Mundane ones ignored
make: Fatal errors encountered -- cannot continue
make: stopped making "target1" in unit-tests
exit status 1
diff --git a/unit-tests/deptgt.mk b/unit-tests/deptgt.mk
index 2e6845b88038..f841f24e8984 100644
--- a/unit-tests/deptgt.mk
+++ b/unit-tests/deptgt.mk
@@ -1,4 +1,4 @@
-# $NetBSD: deptgt.mk,v 1.20 2024/07/06 10:14:35 rillig Exp $
+# $NetBSD: deptgt.mk,v 1.22 2025/01/10 23:00:38 rillig Exp $
#
# Tests for special targets like .BEGIN or .SUFFIXES in dependency
# declarations.
@@ -39,13 +39,19 @@ ${:U}: empty-source
: command for empty targets list
.MAKEFLAGS: -d0
+# An expression based on an undefined variable is allowed on both sides of
+# the dependency declaration.
+.MAKEFLAGS: -dv
+deptgt-${UNDEF}: depsrc-${UNDEF}
+.MAKEFLAGS: -d0
+
# In a dependency declaration, the whole line is expanded before interpreting
# the line.
-# expect+1: while evaluating "${:U:Z}:" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
${:U:Z}:
# After expanding the line as a whole, each target is parsed but not
# evaluated, separately, in ParseDependencyTargetWord.
-# expect+1: while parsing "${:U:Z}:": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
$${:U:Z}:
# expect+1: warning: Extra target 'ordinary' ignored
diff --git a/unit-tests/directive-export-impl.exp b/unit-tests/directive-export-impl.exp
index 7daf1f45b0cb..ff5f1663e160 100644
--- a/unit-tests/directive-export-impl.exp
+++ b/unit-tests/directive-export-impl.exp
@@ -1,19 +1,19 @@
-Parsing line 21: UT_VAR= <${REF}>
+Parsing directive-export-impl.mk:21: UT_VAR= <${REF}>
Global: UT_VAR = <${REF}>
-Parsing line 28: .export UT_VAR
+Parsing directive-export-impl.mk:28: .export UT_VAR
Global: .MAKE.EXPORTED = UT_VAR
-Parsing line 32: : ${UT_VAR:N*}
-Var_Parse: ${UT_VAR:N*} (eval-defined)
-Var_Parse: ${REF}> (eval-defined)
+Parsing directive-export-impl.mk:32: : ${UT_VAR:N*}
+Var_Parse: ${UT_VAR:N*} (eval)
+Var_Parse: ${REF}> (eval)
Evaluating modifier ${UT_VAR:N...} on value "<>"
Pattern for ':N' is "*"
ModifyWords: split "<>" into 1 word
Result of ${UT_VAR:N*} is ""
ParseDependency(: )
-Parsing line 42: .if ${:!echo "\$UT_VAR"!} != "<>"
+Parsing directive-export-impl.mk:42: .if ${:!echo "\$UT_VAR"!} != "<>"
CondParser_Eval: ${:!echo "\$UT_VAR"!} != "<>"
-Var_Parse: ${:!echo "\$UT_VAR"!} != "<>" (eval-defined)
-Evaluating modifier ${:!...} on value "" (eval-defined, undefined)
+Var_Parse: ${:!echo "\$UT_VAR"!} != "<>" (eval-defined-loud)
+Evaluating modifier ${:!...} on value "" (eval, undefined)
Modifier part: "echo "$UT_VAR""
Capturing the output of command "echo "$UT_VAR""
Var_Parse: ${.MAKE.EXPORTED:O:u} (eval)
@@ -23,22 +23,22 @@ Evaluating modifier ${.MAKE.EXPORTED:u} on value "UT_VAR"
Result of ${.MAKE.EXPORTED:u} is "UT_VAR"
Var_Parse: ${UT_VAR} (eval)
Var_Parse: ${REF}> (eval)
-Result of ${:!echo "\$UT_VAR"!} is "<>" (eval-defined, defined)
+Result of ${:!echo "\$UT_VAR"!} is "<>" (eval, defined)
Comparing "<>" != "<>"
-Parsing line 50: : ${UT_VAR:N*}
-Var_Parse: ${UT_VAR:N*} (eval-defined)
-Var_Parse: ${REF}> (eval-defined)
+Parsing directive-export-impl.mk:50: : ${UT_VAR:N*}
+Var_Parse: ${UT_VAR:N*} (eval)
+Var_Parse: ${REF}> (eval)
Evaluating modifier ${UT_VAR:N...} on value "<>"
Pattern for ':N' is "*"
ModifyWords: split "<>" into 1 word
Result of ${UT_VAR:N*} is ""
ParseDependency(: )
-Parsing line 54: REF= defined
+Parsing directive-export-impl.mk:54: REF= defined
Global: REF = defined
-Parsing line 58: .if ${:!echo "\$UT_VAR"!} != "<defined>"
+Parsing directive-export-impl.mk:58: .if ${:!echo "\$UT_VAR"!} != "<defined>"
CondParser_Eval: ${:!echo "\$UT_VAR"!} != "<defined>"
-Var_Parse: ${:!echo "\$UT_VAR"!} != "<defined>" (eval-defined)
-Evaluating modifier ${:!...} on value "" (eval-defined, undefined)
+Var_Parse: ${:!echo "\$UT_VAR"!} != "<defined>" (eval-defined-loud)
+Evaluating modifier ${:!...} on value "" (eval, undefined)
Modifier part: "echo "$UT_VAR""
Capturing the output of command "echo "$UT_VAR""
Var_Parse: ${.MAKE.EXPORTED:O:u} (eval)
@@ -48,12 +48,12 @@ Evaluating modifier ${.MAKE.EXPORTED:u} on value "UT_VAR"
Result of ${.MAKE.EXPORTED:u} is "UT_VAR"
Var_Parse: ${UT_VAR} (eval)
Var_Parse: ${REF}> (eval)
-Result of ${:!echo "\$UT_VAR"!} is "<defined>" (eval-defined, defined)
+Result of ${:!echo "\$UT_VAR"!} is "<defined>" (eval, defined)
Comparing "<defined>" != "<defined>"
-Parsing line 62: all:
+Parsing directive-export-impl.mk:62: all:
ParseDependency(all:)
Global: .ALLTARGETS = all
-Parsing line 63: .MAKEFLAGS: -d0
+Parsing directive-export-impl.mk:63: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
Global: .MAKEFLAGS = -r -k -d cpv -d
Global: .MAKEFLAGS = -r -k -d cpv -d 0
diff --git a/unit-tests/directive-for-errors.exp b/unit-tests/directive-for-errors.exp
index 463f5a376997..e5d5cd158e8e 100644
--- a/unit-tests/directive-for-errors.exp
+++ b/unit-tests/directive-for-errors.exp
@@ -8,7 +8,8 @@ make: "directive-for-errors.mk" line 44: invalid character '$' in .for loop vari
make: "directive-for-errors.mk" line 52: no iteration variables in for
make: "directive-for-errors.mk" line 64: Wrong number of words (5) in .for substitution list with 3 variables
make: "directive-for-errors.mk" line 78: missing `in' in for
-make: "directive-for-errors.mk" line 89: while evaluating "${:U3:Z} 4" with value "3": Unknown modifier "Z"
+make: "directive-for-errors.mk" line 89: Unknown modifier "Z"
+ while evaluating "${:U3:Z} 4" with value "3"
make: "directive-for-errors.mk" line 93: warning: Should not be reached.
make: "directive-for-errors.mk" line 93: warning: Should not be reached.
make: "directive-for-errors.mk" line 93: warning: Should not be reached.
diff --git a/unit-tests/directive-for-errors.mk b/unit-tests/directive-for-errors.mk
index 3cbf457622e8..0fb556ec8ec3 100644
--- a/unit-tests/directive-for-errors.mk
+++ b/unit-tests/directive-for-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-errors.mk,v 1.13 2024/07/06 10:14:35 rillig Exp $
+# $NetBSD: directive-for-errors.mk,v 1.14 2024/08/29 20:20:36 rillig Exp $
#
# Tests for error handling in .for loops.
@@ -85,7 +85,7 @@ ${:U\\}= backslash # see whether the "variable" '\' is local
#
# XXX: As of 2020-12-31, Var_Subst doesn't report any errors, therefore
# the loop body is expanded as if no error had happened.
-# expect+1: while evaluating "${:U3:Z} 4" with value "3": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.for i in 1 2 ${:U3:Z} 4
# expect+3: warning: Should not be reached.
# expect+2: warning: Should not be reached.
diff --git a/unit-tests/directive-for-escape.exp b/unit-tests/directive-for-escape.exp
index 6dfea5e79bb6..be6c2b2a41bf 100644
--- a/unit-tests/directive-for-escape.exp
+++ b/unit-tests/directive-for-escape.exp
@@ -1,13 +1,15 @@
For: end for 1
For: loop body with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~:
. info ${:U!"#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
-make: "directive-for-escape.mk" line 21: while evaluating "${:U!"" with value "!"": Unclosed expression, expecting '}' for modifier "U!""
+make: "directive-for-escape.mk" line 21: Unclosed expression, expecting '}' for modifier "U!""
+ while evaluating "${:U!"" with value "!""
in .for loop from directive-for-escape.mk:20 with chars = !"#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
make: "directive-for-escape.mk" line 21: !"
For: end for 1
For: loop body with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~:
. info ${:U!"\\\\#$%&'()*+,-./0-9\:;<=>?@A-Z[\\]_^a-z{|\}~}
-make: "directive-for-escape.mk" line 33: while evaluating "${:U!"\\\\" with value "!"\\": Unclosed expression, expecting '}' for modifier "U!"\\\\"
+make: "directive-for-escape.mk" line 33: Unclosed expression, expecting '}' for modifier "U!"\\\\"
+ while evaluating "${:U!"\\\\" with value "!"\\"
in .for loop from directive-for-escape.mk:32 with chars = !"\\#$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
make: "directive-for-escape.mk" line 33: !"\\
For: end for 1
@@ -104,7 +106,7 @@ make: "directive-for-escape.mk" line 223: short: " ", long: " "
For: end for 1
For: loop body with i = "
":
-Parsing line 236: .for i in "${.newline}"
+Parsing directive-for-escape.mk:236: .for i in "${.newline}"
For: end for 1
Parse_PushInput: .for loop in directive-for-escape.mk, line 236
make: "directive-for-escape.mk" line 236: newline in .for value
@@ -114,11 +116,11 @@ For: loop body with i = "
":
: ${:U" "}
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 237: : ${:U" "}
+Parsing directive-for-escape.mk:237: : ${:U" "}
ParseDependency(: " ")
ParseEOF: returning to file directive-for-escape.mk, line 239
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `directive-for-escape.mk'
-Parsing line 239: .MAKEFLAGS: -d0
+Parsing directive-for-escape.mk:239: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
For: end for 1
For: loop body with i = #:
diff --git a/unit-tests/directive-for-escape.mk b/unit-tests/directive-for-escape.mk
index dcd13e1392c0..e688ce98f258 100644
--- a/unit-tests/directive-for-escape.mk
+++ b/unit-tests/directive-for-escape.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for-escape.mk,v 1.28 2024/07/07 11:20:10 rillig Exp $
+# $NetBSD: directive-for-escape.mk,v 1.29 2024/08/29 20:20:36 rillig Exp $
#
# Test escaping of special characters in the iteration values of a .for loop.
# These values get expanded later using the :U variable modifier, and this
@@ -15,7 +15,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
# XXX: As of 2020-12-31, the '#' is not preserved in the expanded body of
# the loop. Not only would it need the escaping for the variable modifier
# ':U' but also the escaping for the line-end comment.
-# expect+3: while evaluating "${:U!"" with value "!"": Unclosed expression, expecting '}' for modifier "U!""
+# expect+3: Unclosed expression, expecting '}' for modifier "U!""
# expect+2: !"
.for chars in ${ASCII}
. info ${chars}
@@ -27,7 +27,7 @@ ASCII= !"\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
# This means that a '#' sign cannot be passed in the value of a .for loop
# at all.
ASCII.2020-12-31= !"\\\#$$%&'()*+,-./0-9:;<=>?@A-Z[\]_^a-z{|}~
-# expect+3: while evaluating "${:U!"\\\\" with value "!"\\": Unclosed expression, expecting '}' for modifier "U!"\\\\"
+# expect+3: Unclosed expression, expecting '}' for modifier "U!"\\\\"
# expect+2: !"\\
.for chars in ${ASCII.2020-12-31}
. info ${chars}
diff --git a/unit-tests/directive-for.exp b/unit-tests/directive-for.exp
index 62b51aa406bf..b76a62bc81a2 100755
--- a/unit-tests/directive-for.exp
+++ b/unit-tests/directive-for.exp
@@ -17,7 +17,8 @@ make: "directive-for.mk" line 158: }{ }{ }{
make: "directive-for.mk" line 166: invalid character ':' in .for loop variable name
make: "directive-for.mk" line 173: invalid character '$' in .for loop variable name
make: "directive-for.mk" line 185: invalid character '$' in .for loop variable name
-make: "directive-for.mk" line 210: while evaluating "${:Uword2:Z}-after word3" with value "word2": Unknown modifier "Z"
+make: "directive-for.mk" line 210: Unknown modifier "Z"
+ while evaluating "${:Uword2:Z}-after word3" with value "word2"
make: "directive-for.mk" line 214: XXX: Should not reach word1
make: "directive-for.mk" line 214: XXX: Should not reach before--after
make: "directive-for.mk" line 214: XXX: Should not reach word3
diff --git a/unit-tests/directive-for.mk b/unit-tests/directive-for.mk
index 96c1a492a5f7..cf24e282f730 100755
--- a/unit-tests/directive-for.mk
+++ b/unit-tests/directive-for.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-for.mk,v 1.27 2024/07/06 10:14:35 rillig Exp $
+# $NetBSD: directive-for.mk,v 1.28 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the .for directive.
#
@@ -206,7 +206,7 @@ INDIRECT= ${DIRECT}
# XXX: A parse error or evaluation error in the items of the .for loop
# should skip the whole loop. As of 2023-05-09, the loop is expanded as
# usual.
-# expect+1: while evaluating "${:Uword2:Z}-after word3" with value "word2": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.for var in word1 before-${:Uword2:Z}-after word3
# expect+3: XXX: Should not reach word1
# expect+2: XXX: Should not reach before--after
diff --git a/unit-tests/directive-if-nested.mk b/unit-tests/directive-if-nested.mk
index 19c8e9452660..93fce90b5d52 100644
--- a/unit-tests/directive-if-nested.mk
+++ b/unit-tests/directive-if-nested.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-if-nested.mk,v 1.1 2020/11/10 22:23:37 rillig Exp $
+# $NetBSD: directive-if-nested.mk,v 1.2 2025/01/03 05:00:37 rillig Exp $
#
# Tests for deeply nested .if directives. By default, memory for 128 nested
# .if directives is pre-allocated, any deeper nesting is reallocated.
@@ -13,7 +13,7 @@ all: set-up test tear-down
set-up: .PHONY
@{ printf '.if %s\n' ${:U:range=1000}; \
printf '.info deeply nested .if directives\n'; \
- printf '.endif # %s\n' ${:U:range=1000}; \
+ printf '.endif # %s\n' ${:U:range=1000:[-1..1]}; \
printf '\n'; \
printf 'all:\n'; \
} > ${GEN}
diff --git a/unit-tests/directive-if.exp b/unit-tests/directive-if.exp
index 34ba63d034dd..56c8dfda5e30 100644
--- a/unit-tests/directive-if.exp
+++ b/unit-tests/directive-if.exp
@@ -5,7 +5,7 @@ make: "directive-if.mk" line 45: This is not conditional.
make: "directive-if.mk" line 47: if-less else
make: "directive-if.mk" line 49: This is not conditional.
make: "directive-if.mk" line 51: if-less endif
-make: "directive-if.mk" line 55: Malformed conditional ()
+make: "directive-if.mk" line 55: Malformed conditional ''
make: "directive-if.mk" line 66: Quotes in plain words are probably a mistake.
make: "directive-if.mk" line 76: Don't do this, always put a space after a directive.
make: "directive-if.mk" line 81: Don't do this, always put a space after a directive.
diff --git a/unit-tests/directive-if.mk b/unit-tests/directive-if.mk
index 7a68c0041415..7ff04da0755b 100644
--- a/unit-tests/directive-if.mk
+++ b/unit-tests/directive-if.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-if.mk,v 1.12 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: directive-if.mk,v 1.13 2024/08/06 18:00:17 rillig Exp $
#
# Tests for the .if directive.
#
@@ -51,7 +51,7 @@
.endif
# Missing condition.
-# expect+1: Malformed conditional ()
+# expect+1: Malformed conditional ''
.if
. error
.else
diff --git a/unit-tests/directive-include-fatal.exp b/unit-tests/directive-include-fatal.exp
index edb32df1a59b..35706336c1dd 100755
--- a/unit-tests/directive-include-fatal.exp
+++ b/unit-tests/directive-include-fatal.exp
@@ -1,4 +1,4 @@
-make: "directive-include-fatal.mk" line 14: Malformed conditional (${UNDEF})
+make: "directive-include-fatal.mk" line 14: Variable "UNDEF" is undefined
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/directive-include-fatal.mk b/unit-tests/directive-include-fatal.mk
index d4ed26f2a4aa..ecda6f1982c4 100755
--- a/unit-tests/directive-include-fatal.mk
+++ b/unit-tests/directive-include-fatal.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include-fatal.mk,v 1.4 2023/06/01 20:56:35 rillig Exp $
+# $NetBSD: directive-include-fatal.mk,v 1.6 2025/01/11 21:21:33 rillig Exp $
#
# Test for the .include directive combined with fatal errors.
#
@@ -10,7 +10,7 @@
# the "fatals" counter.
# Using an undefined variable in a condition generates a fatal error.
-# expect+1: Malformed conditional (${UNDEF})
+# expect+1: Variable "UNDEF" is undefined
.if ${UNDEF}
.endif
diff --git a/unit-tests/directive-include-guard.exp b/unit-tests/directive-include-guard.exp
index 70d23a19fe7c..d7d2789681af 100644
--- a/unit-tests/directive-include-guard.exp
+++ b/unit-tests/directive-include-guard.exp
@@ -95,8 +95,10 @@ Parse_PushInput: file target-already-defined.tmp, line 1
Skipping 'target-already-defined.tmp' because 'target-already-defined' is defined
Parse_PushInput: file target-name-exclamation.tmp, line 1
Parse_PushInput: file target-name-exclamation.tmp, line 1
-Parse_PushInput: file target-name-parenthesized.tmp, line 1
-Parse_PushInput: file target-name-parenthesized.tmp, line 1
+Parse_PushInput: file target-name-leading-space.tmp, line 1
+Parse_PushInput: file target-name-leading-space.tmp, line 1
+Parse_PushInput: file target-name-trailing-space.tmp, line 1
+Parse_PushInput: file target-name-trailing-space.tmp, line 1
Parse_PushInput: file target-call-parenthesized.tmp, line 1
Parse_PushInput: file target-call-parenthesized.tmp, line 1
Parse_PushInput: file multiline.tmp, line 1
diff --git a/unit-tests/directive-include-guard.mk b/unit-tests/directive-include-guard.mk
index 85c0242c2009..4c4194be4c36 100644
--- a/unit-tests/directive-include-guard.mk
+++ b/unit-tests/directive-include-guard.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include-guard.mk,v 1.16 2023/12/17 14:07:22 rillig Exp $
+# $NetBSD: directive-include-guard.mk,v 1.18 2024/08/07 05:48:45 rillig Exp $
#
# Tests for multiple-inclusion guards in makefiles.
#
@@ -581,15 +581,25 @@ LINES.target-name-exclamation= \
# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1
# expect: Parse_PushInput: file target-name-exclamation.tmp, line 1
-# If the guard target name is enclosed in spaces, it does not have an effect,
+# If the guard target name has leading spaces, it does not have an effect,
# as that form is not common in practice.
-CASES+= target-name-parenthesized
-LINES.target-name-parenthesized= \
- '.if !target( target-name-parenthesized )' \
- 'target-name-parenthesized: .NOTMAIN' \
+CASES+= target-name-leading-space
+LINES.target-name-leading-space= \
+ '.if !target( target-name-leading-space)' \
+ 'target-name-leading-space: .NOTMAIN' \
'.endif'
-# expect: Parse_PushInput: file target-name-parenthesized.tmp, line 1
-# expect: Parse_PushInput: file target-name-parenthesized.tmp, line 1
+# expect: Parse_PushInput: file target-name-leading-space.tmp, line 1
+# expect: Parse_PushInput: file target-name-leading-space.tmp, line 1
+
+# If the guard target name has trailing spaces, it does not have an effect,
+# as that form is not common in practice.
+CASES+= target-name-trailing-space
+LINES.target-name-trailing-space= \
+ '.if !target(target-name-trailing-space )' \
+ 'target-name-trailing-space: .NOTMAIN' \
+ '.endif'
+# expect: Parse_PushInput: file target-name-trailing-space.tmp, line 1
+# expect: Parse_PushInput: file target-name-trailing-space.tmp, line 1
# If the guard target condition is enclosed in parentheses, it does not have
# an effect, as that form is not common in practice.
diff --git a/unit-tests/directive-include.exp b/unit-tests/directive-include.exp
index 4c395d7532aa..11a6ab8bc88a 100755
--- a/unit-tests/directive-include.exp
+++ b/unit-tests/directive-include.exp
@@ -4,7 +4,8 @@ CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null"
Comparing "directive-include.mk null" != "directive-include.mk null"
make: "directive-include.mk" line 26: Could not find nonexistent.mk
make: "directive-include.mk" line 49: Could not find "
-make: "directive-include.mk" line 56: while evaluating "${:U123:Z}.mk" with value "123": Unknown modifier "Z"
+make: "directive-include.mk" line 56: Unknown modifier "Z"
+ while evaluating "${:U123:Z}.mk" with value "123"
make: "directive-include.mk" line 56: Could not find nonexistent.mk
make: "directive-include.mk" line 61: Cannot open /nonexistent
make: "directive-include.mk" line 66: Invalid line 'include'
diff --git a/unit-tests/directive-include.mk b/unit-tests/directive-include.mk
index e2ef8dc55e3c..bf3dd158b2ad 100755
--- a/unit-tests/directive-include.mk
+++ b/unit-tests/directive-include.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-include.mk,v 1.15 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: directive-include.mk,v 1.17 2025/01/11 20:16:40 rillig Exp $
#
# Tests for the .include directive, which includes another file.
@@ -51,8 +51,8 @@ DQUOT= "
# When the expression in a filename cannot be evaluated, the failing
# expression is skipped and the file is included nevertheless.
# FIXME: Add proper error handling, no file must be included here.
-# expect+2: Could not find nonexistent.mk
-# expect+1: while evaluating "${:U123:Z}.mk" with value "123": Unknown modifier "Z"
+# expect+2: Unknown modifier "Z"
+# expect+1: Could not find nonexistent.mk
.include "nonexistent${:U123:Z}.mk"
# The traditional include directive is seldom used.
diff --git a/unit-tests/directive-undef.exp b/unit-tests/directive-undef.exp
index c3d01fc480c6..c62452abe2ba 100644
--- a/unit-tests/directive-undef.exp
+++ b/unit-tests/directive-undef.exp
@@ -1,5 +1,6 @@
make: "directive-undef.mk" line 30: The .undef directive requires an argument
-make: "directive-undef.mk" line 88: while evaluating variable "VARNAMES" with value "VARNAMES": Unknown modifier "Z"
+make: "directive-undef.mk" line 88: Unknown modifier "Z"
+ while evaluating variable "VARNAMES" with value "VARNAMES"
make: "directive-undef.mk" line 105: warning: UT_EXPORTED is still listed in .MAKE.EXPORTED even though spaceit is not exported anymore.
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/unit-tests/directive-undef.mk b/unit-tests/directive-undef.mk
index 43938e3170ea..167bb79ad07f 100644
--- a/unit-tests/directive-undef.mk
+++ b/unit-tests/directive-undef.mk
@@ -1,4 +1,4 @@
-# $NetBSD: directive-undef.mk,v 1.15 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: directive-undef.mk,v 1.16 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the .undef directive.
#
@@ -84,7 +84,7 @@ ${DOLLAR}= dollar
#
# As of var.c 1.762, this doesn't happen though because the error handling
# in Var_Parse and Var_Subst is not done properly.
-# expect+1: while evaluating variable "VARNAMES" with value "VARNAMES": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.undef ${VARNAMES:L:Z}
diff --git a/unit-tests/include-main.exp b/unit-tests/include-main.exp
index fcc38247109f..f2b4263fccc4 100644
--- a/unit-tests/include-main.exp
+++ b/unit-tests/include-main.exp
@@ -2,13 +2,13 @@ make: "include-main.mk" line 15: main-before-ok
make: "include-main.mk" line 23: main-before-for-ok
make: "include-sub.inc" line 4: sub-before-ok
make: "include-sub.inc" line 14: sub-before-for-ok
-Parsing line 5: . info subsub-ok
+Parsing include-subsub.inc:5: . info subsub-ok
make: "include-subsub.inc" line 5: subsub-ok
in .for loop from include-sub.inc:31 with i = include
in .for loop from include-sub.inc:30 with i = nested
in .for loop from include-sub.inc:29 with i = deeply
in include-main.mk:29
-Parsing line 6: .MAKEFLAGS: -d0
+Parsing include-subsub.inc:6: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
make: "include-sub.inc" line 38: sub-after-ok
make: "include-sub.inc" line 45: sub-after-for-ok
diff --git a/unit-tests/lint.exp b/unit-tests/lint.exp
index 714093ca2b7d..ded93d192b14 100755
--- a/unit-tests/lint.exp
+++ b/unit-tests/lint.exp
@@ -1,4 +1,4 @@
-make: in target "mod-loop-varname": while evaluating variable "VAR" with value "value": In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
-y@:Q}
-xvaluey
+make: In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
+ while evaluating variable "VAR" with value "value"
+ in target "mod-loop-varname"
exit status 2
diff --git a/unit-tests/moderrs.exp b/unit-tests/moderrs.exp
index 05a5108935cd..06c305c83e4f 100644
--- a/unit-tests/moderrs.exp
+++ b/unit-tests/moderrs.exp
@@ -1,115 +1,140 @@
-make: in target "mod-unknown-direct": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
-VAR:Z=before--after
-
-make: in target "mod-unknown-indirect": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
-VAR:Z=before-inner}-after
-
-unclosed-direct:
-make: in target "unclosed-direct": while evaluating variable "VAR" with value "Thevariable": Unclosed expression, expecting '}' for modifier "S,V,v,"
-VAR:S,V,v,=Thevariable
-
-unclosed-indirect:
-make: in target "unclosed-indirect": while evaluating variable "VAR" with value "Thevariable": Unclosed expression after indirect modifier, expecting '}'
-VAR:S,V,v,=Thevariable
-
-make: in target "unfinished-indirect": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-VAR:S,V,v=
-
-make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
-
-make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
-
+make: Unknown modifier "Z"
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-unknown-direct"
+make: Unknown modifier "Z"
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-unknown-indirect"
+make: Unclosed expression, expecting '}' for modifier "S,V,v,"
+ while evaluating variable "VAR" with value "Thevariable"
+ in target "unclosed-direct"
+make: Unclosed expression after indirect modifier, expecting '}'
+ while evaluating variable "VAR" with value "Thevariable"
+ in target "unclosed-indirect"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "unfinished-indirect"
+make: Unfinished modifier ('@' missing)
+ while evaluating variable "UNDEF" with value "1 2 3"
+ in target "unfinished-loop-1"
+make: Unfinished modifier ('@' missing)
+ while evaluating variable "UNDEF" with value "1 2 3"
+ in target "unfinished-loop-2"
1 2 3
-
-loop-close:
-make: in target "loop-close": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+ while evaluating variable "UNDEF" with value "1}... 2}... 3}..."
+ in target "loop-close-1"
1}... 2}... 3}...
-1}... 2}... 3}...
-
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
-
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
-
+make: Unfinished modifier (']' missing)
+ while evaluating variable "UNDEF" with value "1 2 3"
+ in target "words-1"
+make: Unfinished modifier (']' missing)
+ while evaluating variable "UNDEF" with value "1 2 3"
+ in target "words-2"
13=
-make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Bad modifier ":[123451234512345123451234512345]"
-12345=S,^ok,:S,^3ok,}
-
-make: in target "exclam": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
-
-make: in target "exclam": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
-
-
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
-1:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-2:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-3:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-4:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-5:
-make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "S,from,to,"
-6: TheVariable
+make: Bad modifier ":[123451234512345123451234512345]"
+ while evaluating variable "UNDEF" with value "1 2 3"
+ in target "words-3"
+make: Unfinished modifier ('!' missing)
+ while evaluating variable "VARNAME" with value ""
+ in target "exclam-1"
+make: Unfinished modifier ('!' missing)
+ while evaluating variable "!" with value "!"
+ in target "exclam-2"
+make: Missing delimiter for modifier ':S'
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-1"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-2"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-3"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-4"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-5"
+make: Unclosed expression, expecting '}' for modifier "S,from,to,"
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-subst-delimiter-6"
7: TheVariable
-
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
-1:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-2:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-3:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-4:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
-5:
-make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
-6: TheVariable
+make: Missing delimiter for modifier ':C'
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-1"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-2"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-3"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-4"
+make: Unfinished modifier (',' missing)
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-5"
+make: Unclosed expression, expecting '}' for modifier "C,from,to,"
+ while evaluating variable "VAR" with value "TheVariable"
+ in target "mod-regex-delimiter-6"
7: TheVariable
-
-mod-ts-parse:
112358132134
15152535558513521534
-make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
-65oct}
-make: in target "mod-ts-parse": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
-65oct}
-make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
-xy}
-
-mod-t-parse:
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
-y}
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-
-make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
-M*}
-
-make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
-
-make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
-
-make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
-
-make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
-
+make: Bad modifier ":ts\65oct"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-ts-parse-3"
+make: Bad modifier ":ts\65oct"
+ while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-ts-parse-4"
+make: Bad modifier ":tsxy"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-ts-parse-5"
+make: Bad modifier ":t"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-t-parse-1"
+make: Bad modifier ":txy"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-t-parse-2"
+make: Bad modifier ":t"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-t-parse-3"
+make: Bad modifier ":t"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-t-parse-4"
+make: Unfinished modifier (':' missing)
+ while evaluating then-branch of condition "FIB"
+ in target "mod-ifelse-parse-1"
+make: Unfinished modifier (':' missing)
+ while evaluating then-branch of condition "FIB"
+ in target "mod-ifelse-parse-2"
+make: Unfinished modifier ('}' missing)
+ while evaluating else-branch of condition "FIB"
+ in target "mod-ifelse-parse-3"
+make: Unfinished modifier ('}' missing)
+ while evaluating else-branch of condition "FIB"
+ in target "mod-ifelse-parse-4"
then
-
1 1 2 3 5 8 13 21 34
-make: in target "mod-remember-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "__"
-
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
-
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
-make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
-
+make: Unknown modifier "__"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-remember-parse"
+make: Unknown modifier "3"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-sysv-parse-1"
+make: Unclosed expression, expecting '}' for modifier "3"
+ while evaluating variable "FIB" with value ""
+ in target "mod-sysv-parse-1"
+make: Unknown modifier "3="
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-sysv-parse-2"
+make: Unclosed expression, expecting '}' for modifier "3="
+ while evaluating variable "FIB" with value ""
+ in target "mod-sysv-parse-2"
+make: Unknown modifier "3=x3"
+ while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34"
+ in target "mod-sysv-parse-3"
+make: Unclosed expression, expecting '}' for modifier "3=x3"
+ while evaluating variable "FIB" with value ""
+ in target "mod-sysv-parse-3"
1 1 2 x3 5 8 1x3 21 34
-
exit status 2
diff --git a/unit-tests/moderrs.mk b/unit-tests/moderrs.mk
index 66af52c14a65..ad9333dcfb1d 100644
--- a/unit-tests/moderrs.mk
+++ b/unit-tests/moderrs.mk
@@ -1,4 +1,4 @@
-# $NetBSD: moderrs.mk,v 1.38 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: moderrs.mk,v 1.41 2024/08/29 20:20:36 rillig Exp $
#
# various modifier error tests
@@ -12,43 +12,45 @@ FIB= 1 1 2 3 5 8 13 21 34
all: mod-unknown-direct mod-unknown-indirect
all: unclosed-direct unclosed-indirect
-all: unfinished-indirect unfinished-loop
-all: loop-close
-all: words
-all: exclam
-all: mod-subst-delimiter
-all: mod-regex-delimiter
-all: mod-ts-parse
-all: mod-t-parse
-all: mod-ifelse-parse
+all: unfinished-indirect unfinished-loop-{1,2,3}
+all: loop-close-{1,2}
+all: words-{1,2,3}
+all: exclam-{1,2}
+all: mod-subst-delimiter-{1,2,3,4,5,6,7}
+all: mod-regex-delimiter-{1,2,3,4,5,6,7}
+all: mod-ts-parse-{1,2,3,4,5}
+all: mod-t-parse-{1,2,3,4}
+all: mod-ifelse-parse-{1,2,3,4,5}
all: mod-remember-parse
-all: mod-sysv-parse
+all: mod-sysv-parse-{1,2,3,4}
-mod-unknown-direct: print-footer
-# expect: make: in target "mod-unknown-direct": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
+mod-unknown-direct:
+# expect: make: Unknown modifier "Z"
@echo 'VAR:Z=before-${VAR:Z}-after'
-mod-unknown-indirect: print-footer
-# expect: make: in target "mod-unknown-indirect": while evaluating variable "VAR" with value "TheVariable": Unknown modifier "Z"
+mod-unknown-indirect:
+# expect: make: Unknown modifier "Z"
@echo 'VAR:${MOD_UNKN}=before-${VAR:${MOD_UNKN}:inner}-after'
-unclosed-direct: print-header print-footer
-# expect: make: in target "unclosed-direct": while evaluating variable "VAR" with value "Thevariable": Unclosed expression, expecting '}' for modifier "S,V,v,"
+unclosed-direct:
+# expect: make: Unclosed expression, expecting '}' for modifier "S,V,v,"
@echo VAR:S,V,v,=${VAR:S,V,v,
-unclosed-indirect: print-header print-footer
-# expect: make: in target "unclosed-indirect": while evaluating variable "VAR" with value "Thevariable": Unclosed expression after indirect modifier, expecting '}'
+unclosed-indirect:
+# expect: make: Unclosed expression after indirect modifier, expecting '}'
@echo VAR:${MOD_TERM},=${VAR:${MOD_S}
-unfinished-indirect: print-footer
-# expect: make: in target "unfinished-indirect": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+unfinished-indirect:
+# expect: make: Unfinished modifier (',' missing)
-@echo "VAR:${MOD_TERM}=${VAR:${MOD_TERM}}"
-unfinished-loop: print-footer
-# expect: make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
+unfinished-loop-1:
+# expect: make: Unfinished modifier ('@' missing)
@echo ${UNDEF:U1 2 3:@var}
-# expect: make: in target "unfinished-loop": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier ('@' missing)
+unfinished-loop-2:
+# expect: make: Unfinished modifier ('@' missing)
@echo ${UNDEF:U1 2 3:@var@...}
+unfinished-loop-3:
@echo ${UNDEF:U1 2 3:@var@${var}@}
# The closing brace after the ${var} is part of the replacement string.
@@ -57,17 +59,20 @@ unfinished-loop: print-footer
# braces must be balanced.
# This is also contrary to the SysV modifier, where only the actually
# used delimiter (either braces or parentheses) must be balanced.
-loop-close: print-header print-footer
-# expect: make: in target "loop-close": while evaluating variable "UNDEF" with value "1}... 2}... 3}...": Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
+loop-close-1:
+# expect: make: Unclosed expression, expecting '}' for modifier "@var@${var}}...@"
@echo ${UNDEF:U1 2 3:@var@${var}}...@
+loop-close-2:
@echo ${UNDEF:U1 2 3:@var@${var}}...@}
-words: print-footer
-# expect: make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
+words-1:
+# expect: make: Unfinished modifier (']' missing)
@echo ${UNDEF:U1 2 3:[}
-# expect: make: in target "words": while evaluating variable "UNDEF" with value "1 2 3": Unfinished modifier (']' missing)
+words-2:
+# expect: make: Unfinished modifier (']' missing)
@echo ${UNDEF:U1 2 3:[#}
+words-3:
# out of bounds => empty
@echo 13=${UNDEF:U1 2 3:[13]}
@@ -90,95 +95,117 @@ words: print-footer
# That variable is undefined, resulting in an empty string.
@echo 12345=${UNDEF:U1 2 3:[123451234512345123451234512345]:S,^$,ok,:S,^3$,ok,}
-exclam: print-footer
-# expect: make: in target "exclam": while evaluating variable "VARNAME" with value "": Unfinished modifier ('!' missing)
+exclam-1:
+# expect: make: Unfinished modifier ('!' missing)
@echo ${VARNAME:!echo}
# When the final exclamation mark is missing, there is no
# fallback to the SysV substitution modifier.
# If there were a fallback, the output would be "exclam",
# and the above would have produced an "Unknown modifier '!'".
-# expect: make: in target "exclam": while evaluating variable "!" with value "!": Unfinished modifier ('!' missing)
+exclam-2:
+# expect: make: Unfinished modifier ('!' missing)
@echo ${!:L:!=exclam}
-mod-subst-delimiter: print-footer
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':S'
+mod-subst-delimiter-1:
+# expect: make: Missing delimiter for modifier ':S'
@echo 1: ${VAR:S
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-2:
+# expect: make: Unfinished modifier (',' missing)
@echo 2: ${VAR:S,
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-3:
+# expect: make: Unfinished modifier (',' missing)
@echo 3: ${VAR:S,from
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-4:
+# expect: make: Unfinished modifier (',' missing)
@echo 4: ${VAR:S,from,
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-subst-delimiter-5:
+# expect: make: Unfinished modifier (',' missing)
@echo 5: ${VAR:S,from,to
-# expect: make: in target "mod-subst-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "S,from,to,"
+mod-subst-delimiter-6:
+# expect: make: Unclosed expression, expecting '}' for modifier "S,from,to,"
@echo 6: ${VAR:S,from,to,
+mod-subst-delimiter-7:
@echo 7: ${VAR:S,from,to,}
-mod-regex-delimiter: print-footer
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Missing delimiter for modifier ':C'
+mod-regex-delimiter-1:
+# expect: make: Missing delimiter for modifier ':C'
@echo 1: ${VAR:C
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-2:
+# expect: make: Unfinished modifier (',' missing)
@echo 2: ${VAR:C,
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-3:
+# expect: make: Unfinished modifier (',' missing)
@echo 3: ${VAR:C,from
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-4:
+# expect: make: Unfinished modifier (',' missing)
@echo 4: ${VAR:C,from,
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unfinished modifier (',' missing)
+mod-regex-delimiter-5:
+# expect: make: Unfinished modifier (',' missing)
@echo 5: ${VAR:C,from,to
-# expect: make: in target "mod-regex-delimiter": while evaluating variable "VAR" with value "TheVariable": Unclosed expression, expecting '}' for modifier "C,from,to,"
+mod-regex-delimiter-6:
+# expect: make: Unclosed expression, expecting '}' for modifier "C,from,to,"
@echo 6: ${VAR:C,from,to,
+mod-regex-delimiter-7:
@echo 7: ${VAR:C,from,to,}
-mod-ts-parse: print-header print-footer
+mod-ts-parse-1:
@echo ${FIB:ts}
+mod-ts-parse-2:
@echo ${FIB:ts\65} # octal 065 == U+0035 == '5'
-# expect: make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+mod-ts-parse-3:
+# expect: make: Bad modifier ":ts\65oct"
@echo ${FIB:ts\65oct} # bad modifier
-# expect: make: in target "mod-ts-parse": while evaluating "${:U${FIB}:ts\65oct} # bad modifier, variable name is """ with value "1 1 2 3 5 8 13 21 34": Bad modifier ":ts\65oct"
+mod-ts-parse-4:
+# expect: make: Bad modifier ":ts\65oct"
@echo ${:U${FIB}:ts\65oct} # bad modifier, variable name is ""
-# expect: make: in target "mod-ts-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":tsxy"
+mod-ts-parse-5:
+# expect: make: Bad modifier ":tsxy"
@echo ${FIB:tsxy} # modifier too long
-mod-t-parse: print-header print-footer
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-1:
+# expect: make: Bad modifier ":t"
@echo ${FIB:t
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":txy"
+mod-t-parse-2:
+# expect: make: Bad modifier ":txy"
@echo ${FIB:txy}
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-3:
+# expect: make: Bad modifier ":t"
@echo ${FIB:t}
-# expect: make: in target "mod-t-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Bad modifier ":t"
+mod-t-parse-4:
+# expect: make: Bad modifier ":t"
@echo ${FIB:t:M*}
-mod-ifelse-parse: print-footer
-# expect: make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+mod-ifelse-parse-1:
+# expect: make: Unfinished modifier (':' missing)
@echo ${FIB:?
-# expect: make: in target "mod-ifelse-parse": while evaluating then-branch of condition "FIB": Unfinished modifier (':' missing)
+mod-ifelse-parse-2:
+# expect: make: Unfinished modifier (':' missing)
@echo ${FIB:?then
-# expect: make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
+mod-ifelse-parse-3:
+# expect: make: Unfinished modifier ('}' missing)
@echo ${FIB:?then:
-# expect: make: in target "mod-ifelse-parse": while evaluating else-branch of condition "FIB": Unfinished modifier ('}' missing)
+mod-ifelse-parse-4:
+# expect: make: Unfinished modifier ('}' missing)
@echo ${FIB:?then:else
+mod-ifelse-parse-5:
@echo ${FIB:?then:else}
-mod-remember-parse: print-footer
+mod-remember-parse:
@echo ${FIB:_} # ok
-# expect: make: in target "mod-remember-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "__"
+# expect: make: Unknown modifier "__"
@echo ${FIB:__} # modifier name too long
-mod-sysv-parse: print-footer
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3"
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3"
+mod-sysv-parse-1:
+# expect: make: Unknown modifier "3"
+# expect: make: Unclosed expression, expecting '}' for modifier "3"
@echo ${FIB:3
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3="
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3="
+mod-sysv-parse-2:
+# expect: make: Unknown modifier "3="
+# expect: make: Unclosed expression, expecting '}' for modifier "3="
@echo ${FIB:3=
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "1 1 2 3 5 8 13 21 34": Unknown modifier "3=x3"
-# expect: make: in target "mod-sysv-parse": while evaluating variable "FIB" with value "": Unclosed expression, expecting '}' for modifier "3=x3"
+mod-sysv-parse-3:
+# expect: make: Unknown modifier "3=x3"
+# expect: make: Unclosed expression, expecting '}' for modifier "3=x3"
@echo ${FIB:3=x3
+mod-sysv-parse-4:
@echo ${FIB:3=x3} # ok
-
-print-header: .USEBEFORE
- @echo $@:
-print-footer: .USE
- @echo
diff --git a/unit-tests/opt-debug-lint.exp b/unit-tests/opt-debug-lint.exp
index eea6c8db5a49..7274a06333ee 100644
--- a/unit-tests/opt-debug-lint.exp
+++ b/unit-tests/opt-debug-lint.exp
@@ -1,10 +1,11 @@
-make: "opt-debug-lint.mk" line 21: Variable "X" is undefined
-make: "opt-debug-lint.mk" line 21: Malformed conditional ($X)
-make: "opt-debug-lint.mk" line 45: Variable "UNDEF" is undefined
-make: "opt-debug-lint.mk" line 45: Malformed conditional (${UNDEF})
-make: "opt-debug-lint.mk" line 67: while evaluating variable "value" with value "value": Missing delimiter ':' after modifier "L"
-make: "opt-debug-lint.mk" line 67: while evaluating variable "value" with value "value": Missing delimiter ':' after modifier "P"
-make: "opt-debug-lint.mk" line 76: while evaluating variable "value" with value "": Unknown modifier "${"
+make: "opt-debug-lint.mk" line 20: Variable "X" is undefined
+make: "opt-debug-lint.mk" line 43: Variable "UNDEF" is undefined
+make: "opt-debug-lint.mk" line 65: Missing delimiter ':' after modifier "L"
+ while evaluating variable "value" with value "value"
+make: "opt-debug-lint.mk" line 65: Missing delimiter ':' after modifier "P"
+ while evaluating variable "value" with value "value"
+make: "opt-debug-lint.mk" line 74: Unknown modifier "${"
+ while evaluating variable "value" with value ""
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/opt-debug-lint.mk b/unit-tests/opt-debug-lint.mk
index cc20694e268c..7918490b3f1a 100644
--- a/unit-tests/opt-debug-lint.mk
+++ b/unit-tests/opt-debug-lint.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-debug-lint.mk,v 1.18 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: opt-debug-lint.mk,v 1.22 2025/01/11 20:54:45 rillig Exp $
#
# Tests for the -dL command line option, which runs additional checks
# to catch common mistakes, such as unclosed expressions.
@@ -16,7 +16,6 @@
#
# See also:
# cond-undef-lint.mk
-# expect+2: Malformed conditional ($X)
# expect+1: Variable "X" is undefined
.if $X
. error
@@ -40,7 +39,6 @@
# hoping for the caller to print an error message. This resulted in the
# well-known "Malformed conditional" error message, even though the
# conditional was well-formed and the only error was an undefined variable.
-# expect+2: Malformed conditional (${UNDEF})
# expect+1: Variable "UNDEF" is undefined
.if ${UNDEF}
. error
@@ -62,8 +60,8 @@ ${UNDEF}: ${UNDEF}
# Since 2020-10-03, in lint mode the variable modifier must be separated
# by colons. See varparse-mod.mk.
-# expect+2: while evaluating variable "value" with value "value": Missing delimiter ':' after modifier "L"
-# expect+1: while evaluating variable "value" with value "value": Missing delimiter ':' after modifier "P"
+# expect+2: Missing delimiter ':' after modifier "L"
+# expect+1: Missing delimiter ':' after modifier "P"
.if ${value:LPL} != "value"
. error
.endif
@@ -72,7 +70,7 @@ ${UNDEF}: ${UNDEF}
# variable modifier had to be separated by colons. This was wrong though
# since make always fell back trying to parse the indirect modifier as a
# SysV modifier.
-# expect+1: while evaluating variable "value" with value "": Unknown modifier "${"
+# expect+1: Unknown modifier "${"
.if ${value:${:UL}PL} != "LPL}" # FIXME: "LPL}" is unexpected here.
. error ${value:${:UL}PL}
.endif
diff --git a/unit-tests/opt-debug-parse.exp b/unit-tests/opt-debug-parse.exp
index a19a58bcc965..f0b57f2a703b 100644
--- a/unit-tests/opt-debug-parse.exp
+++ b/unit-tests/opt-debug-parse.exp
@@ -1,28 +1,28 @@
-Parsing line 16: .for var in value
+Parsing opt-debug-parse.mk:16: .for var in value
Parse_PushInput: .for loop in opt-debug-parse.mk, line 16
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `opt-debug-parse.mk'
-Parsing line 21: .info trace with multi-line .for loop head
+Parsing opt-debug-parse.mk:21: .info trace with multi-line .for loop head
make: "opt-debug-parse.mk" line 21: trace with multi-line .for loop head
in .for loop from opt-debug-parse.mk:16 with var = value
ParseEOF: returning to file opt-debug-parse.mk, line 23
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `opt-debug-parse.mk'
-Parsing line 26: .include "/dev/null"
+Parsing opt-debug-parse.mk:26: .include "/dev/null"
Parse_PushInput: file /dev/null, line 1
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `null'
SetFilenameVars: ${.INCLUDEDFROMDIR} = <some-dir> ${.INCLUDEDFROMFILE} = `opt-debug-parse.mk'
ParseEOF: returning to file opt-debug-parse.mk, line 27
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `opt-debug-parse.mk'
-Parsing line 31: .for a b c in 1 2 3 ${:U4 5 6}
+Parsing opt-debug-parse.mk:31: .for a b c in 1 2 3 ${:U4 5 6}
Parse_PushInput: .for loop in opt-debug-parse.mk, line 31
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `opt-debug-parse.mk'
-Parsing line 34: .info trace
+Parsing opt-debug-parse.mk:34: .info trace
make: "opt-debug-parse.mk" line 34: trace
in .for loop from opt-debug-parse.mk:31 with a = 1, b = 2, c = 3
-Parsing line 34: .info trace
+Parsing opt-debug-parse.mk:34: .info trace
make: "opt-debug-parse.mk" line 34: trace
in .for loop from opt-debug-parse.mk:31 with a = 4, b = 5, c = 6
ParseEOF: returning to file opt-debug-parse.mk, line 36
SetFilenameVars: ${.PARSEDIR} = <some-dir> ${.PARSEFILE} = `opt-debug-parse.mk'
-Parsing line 38: .MAKEFLAGS: -d0
+Parsing opt-debug-parse.mk:38: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
exit status 0
diff --git a/unit-tests/opt-debug-var.exp b/unit-tests/opt-debug-var.exp
index 5e9d10c671f1..e113e66f26fe 100644
--- a/unit-tests/opt-debug-var.exp
+++ b/unit-tests/opt-debug-var.exp
@@ -2,6 +2,12 @@ Global: ASSIGNED = value
Global: SUBST = # (empty)
Global: SUBST = value
Var_Parse: y(ASSIGNED) (eval)
+Var_Parse: $U (eval-defined-loud)
+make: "opt-debug-var.mk" line 34: Variable "U" is undefined
+Var_Parse: $< (eval-defined-loud)
+make: "opt-debug-var.mk" line 40: Variable "<" is undefined
Global: .MAKEFLAGS = -r -k -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0
-exit status 0
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+exit status 1
diff --git a/unit-tests/opt-debug-var.mk b/unit-tests/opt-debug-var.mk
index 9017f18e81d3..7a3a80f11432 100644
--- a/unit-tests/opt-debug-var.mk
+++ b/unit-tests/opt-debug-var.mk
@@ -1,4 +1,4 @@
-# $NetBSD: opt-debug-var.mk,v 1.3 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: opt-debug-var.mk,v 1.5 2025/01/11 21:21:33 rillig Exp $
#
# Tests for the -dv command line option, which adds debug logging about
# variable assignment and evaluation.
@@ -9,6 +9,7 @@
ASSIGNED= value
# TODO: Explain why the empty assignment "Global: SUBST = " is needed.
+# expect: Global: SUBST = # (empty)
# expect: Global: SUBST = value
SUBST:= value
@@ -26,6 +27,18 @@ SUBST:= value
.if !empty(ASSIGNED)
.endif
-.MAKEFLAGS: -d0
-all: .PHONY
+# An expression for a variable with a single-character ordinary name.
+# expect: Var_Parse: $U (eval-defined-loud)
+# expect+1: Variable "U" is undefined
+.if $U
+.endif
+
+# An expression for a target-specific variable with a single-character name.
+# expect: Var_Parse: $< (eval-defined-loud)
+# expect+1: Variable "<" is undefined
+.if $<
+.endif
+
+
+.MAKEFLAGS: -d0
diff --git a/unit-tests/suff-incomplete.exp b/unit-tests/suff-incomplete.exp
index a0603de34f11..e5e4a770b26d 100644
--- a/unit-tests/suff-incomplete.exp
+++ b/unit-tests/suff-incomplete.exp
@@ -1,17 +1,17 @@
-Parsing line 9: .SUFFIXES:
+Parsing suff-incomplete.mk:9: .SUFFIXES:
ParseDependency(.SUFFIXES:)
Clearing all suffixes
-Parsing line 11: .SUFFIXES: .a .b .c
+Parsing suff-incomplete.mk:11: .SUFFIXES: .a .b .c
ParseDependency(.SUFFIXES: .a .b .c)
Adding suffix ".a"
Adding suffix ".b"
Adding suffix ".c"
-Parsing line 17: .a.b:
+Parsing suff-incomplete.mk:17: .a.b:
ParseDependency(.a.b:)
defining transformation from `.a' to `.b'
inserting ".a" (1) at end of list
inserting ".b" (2) at end of list
-Parsing line 21: .a.c: ${.PREFIX}.dependency
+Parsing suff-incomplete.mk:21: .a.c: ${.PREFIX}.dependency
deleting incomplete transformation from `.a' to `.b'
ParseDependency(.a.c: ${.PREFIX}.dependency)
defining transformation from `.a' to `.c'
@@ -20,10 +20,10 @@ inserting ".c" (3) at end of list
Target ".a.c" depends on "${.PREFIX}.dependency"
# .a.c, unmade, type OP_DEPENDS|OP_TRANSFORM, flags none
# ${.PREFIX}.dependency, unmade, type none, flags none
-Parsing line 23: .DEFAULT:
+Parsing suff-incomplete.mk:23: .DEFAULT:
transformation .a.c complete
ParseDependency(.DEFAULT:)
-Parsing line 24: : Making ${.TARGET} from ${.IMPSRC} all ${.ALLSRC} by default.
+Parsing suff-incomplete.mk:24: : Making ${.TARGET} from ${.IMPSRC} all ${.ALLSRC} by default.
transformation .DEFAULT complete
Wildcard expanding "all"...
SuffFindDeps "all"
diff --git a/unit-tests/suff-main-several.exp b/unit-tests/suff-main-several.exp
index 99585102029e..c06fb0cf88b9 100644
--- a/unit-tests/suff-main-several.exp
+++ b/unit-tests/suff-main-several.exp
@@ -1,11 +1,11 @@
-Parsing line 8: .1.2 .1.3 .1.4:
+Parsing suff-main-several.mk:8: .1.2 .1.3 .1.4:
ParseDependency(.1.2 .1.3 .1.4:)
Setting main node to ".1.2"
-Parsing line 9: : Making ${.TARGET} from ${.IMPSRC}.
-Parsing line 14: next-main:
+Parsing suff-main-several.mk:9: : Making ${.TARGET} from ${.IMPSRC}.
+Parsing suff-main-several.mk:14: next-main:
ParseDependency(next-main:)
-Parsing line 15: : Making ${.TARGET}
-Parsing line 19: .SUFFIXES: .1 .2 .3 .4
+Parsing suff-main-several.mk:15: : Making ${.TARGET}
+Parsing suff-main-several.mk:19: .SUFFIXES: .1 .2 .3 .4
ParseDependency(.SUFFIXES: .1 .2 .3 .4)
Adding suffix ".1"
Adding suffix ".2"
@@ -26,42 +26,42 @@ defining transformation from `.1' to `.4'
inserting ".1" (1) at end of list
inserting ".4" (4) at end of list
Setting main node to "next-main"
-Parsing line 24: .SUFFIXES:
+Parsing suff-main-several.mk:24: .SUFFIXES:
ParseDependency(.SUFFIXES:)
Clearing all suffixes
-Parsing line 32: .SUFFIXES: .4 .3 .2 .1
+Parsing suff-main-several.mk:32: .SUFFIXES: .4 .3 .2 .1
ParseDependency(.SUFFIXES: .4 .3 .2 .1)
Adding suffix ".4"
Adding suffix ".3"
Adding suffix ".2"
Adding suffix ".1"
-Parsing line 33: .SUFFIXES:
+Parsing suff-main-several.mk:33: .SUFFIXES:
ParseDependency(.SUFFIXES:)
Clearing all suffixes
-Parsing line 34: .SUFFIXES: .1 .2 .3 .4
+Parsing suff-main-several.mk:34: .SUFFIXES: .1 .2 .3 .4
ParseDependency(.SUFFIXES: .1 .2 .3 .4)
Adding suffix ".1"
Adding suffix ".2"
Adding suffix ".3"
Adding suffix ".4"
-Parsing line 35: .SUFFIXES:
+Parsing suff-main-several.mk:35: .SUFFIXES:
ParseDependency(.SUFFIXES:)
Clearing all suffixes
-Parsing line 36: .SUFFIXES: .4 .3 .2 .1
+Parsing suff-main-several.mk:36: .SUFFIXES: .4 .3 .2 .1
ParseDependency(.SUFFIXES: .4 .3 .2 .1)
Adding suffix ".4"
Adding suffix ".3"
Adding suffix ".2"
Adding suffix ".1"
-Parsing line 38: suff-main-several.1:
+Parsing suff-main-several.mk:38: suff-main-several.1:
ParseDependency(suff-main-several.1:)
-Parsing line 39: : Making ${.TARGET} out of nothing.
-Parsing line 40: next-main: suff-main-several.{2,3,4}
+Parsing suff-main-several.mk:39: : Making ${.TARGET} out of nothing.
+Parsing suff-main-several.mk:40: next-main: suff-main-several.{2,3,4}
ParseDependency(next-main: suff-main-several.{2,3,4})
Target "next-main" depends on "suff-main-several.{2,3,4}"
# next-main, unmade, type OP_DEPENDS|OP_HAS_COMMANDS, flags none
# suff-main-several.{2,3,4}, unmade, type none, flags none
-Parsing line 42: .MAKEFLAGS: -d0 -dg1
+Parsing suff-main-several.mk:42: .MAKEFLAGS: -d0 -dg1
ParseDependency(.MAKEFLAGS: -d0 -dg1)
#*** Input graph:
# .1.2, unmade, type OP_TRANSFORM, flags none
diff --git a/unit-tests/suff-rebuild.exp b/unit-tests/suff-rebuild.exp
index 8c0979537524..e44fa0fe9893 100644
--- a/unit-tests/suff-rebuild.exp
+++ b/unit-tests/suff-rebuild.exp
@@ -1,36 +1,36 @@
-Parsing line 10: .SUFFIXES:
+Parsing suff-rebuild.mk:10: .SUFFIXES:
ParseDependency(.SUFFIXES:)
Clearing all suffixes
-Parsing line 12: .SUFFIXES: .a .b .c
+Parsing suff-rebuild.mk:12: .SUFFIXES: .a .b .c
ParseDependency(.SUFFIXES: .a .b .c)
Adding suffix ".a"
Adding suffix ".b"
Adding suffix ".c"
-Parsing line 14: suff-rebuild-example.a:
+Parsing suff-rebuild.mk:14: suff-rebuild-example.a:
ParseDependency(suff-rebuild-example.a:)
Adding "suff-rebuild-example.a" to all targets.
-Parsing line 15: : Making ${.TARGET} out of nothing.
-Parsing line 17: .a.b:
+Parsing suff-rebuild.mk:15: : Making ${.TARGET} out of nothing.
+Parsing suff-rebuild.mk:17: .a.b:
ParseDependency(.a.b:)
defining transformation from `.a' to `.b'
inserting ".a" (1) at end of list
inserting ".b" (2) at end of list
-Parsing line 18: : Making ${.TARGET} from ${.IMPSRC}.
-Parsing line 19: .b.c:
+Parsing suff-rebuild.mk:18: : Making ${.TARGET} from ${.IMPSRC}.
+Parsing suff-rebuild.mk:19: .b.c:
transformation .a.b complete
ParseDependency(.b.c:)
defining transformation from `.b' to `.c'
inserting ".b" (2) at end of list
inserting ".c" (3) at end of list
-Parsing line 20: : Making ${.TARGET} from ${.IMPSRC}.
-Parsing line 21: .c:
+Parsing suff-rebuild.mk:20: : Making ${.TARGET} from ${.IMPSRC}.
+Parsing suff-rebuild.mk:21: .c:
transformation .b.c complete
ParseDependency(.c:)
defining transformation from `.c' to `'
inserting ".c" (3) at end of list
inserting "" (0) at end of list
-Parsing line 22: : Making ${.TARGET} from ${.IMPSRC}.
-Parsing line 44: .SUFFIXES: .c .b .a
+Parsing suff-rebuild.mk:22: : Making ${.TARGET} from ${.IMPSRC}.
+Parsing suff-rebuild.mk:44: .SUFFIXES: .c .b .a
transformation .c complete
ParseDependency(.SUFFIXES: .c .b .a)
Adding ".END" to all targets.
diff --git a/unit-tests/suff.exp b/unit-tests/suff.exp
new file mode 100644
index 000000000000..adf646850d6e
--- /dev/null
+++ b/unit-tests/suff.exp
@@ -0,0 +1,146 @@
+Adding suffix ".from"
+Adding suffix ".to"
+defining transformation from `.from' to `.to'
+inserting ".from" (1) at end of list
+inserting ".to" (2) at end of list
+transformation .from.to complete
+Var_Parse: ${.PREFIX}${.ARCHIVE}.additional (eval)
+Var_Parse: ${.ARCHIVE}.additional (eval)
+Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional
+Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from
+Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from edge-case.additional
+Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from edge-case.additional a*.mk
+Global: delete .PARSEDIR
+Global: delete .PARSEFILE
+Global: ignoring delete '.INCLUDEDFROMDIR' as it is not found
+Global: ignoring delete '.INCLUDEDFROMFILE' as it is not found
+Var_Parse: ${.MAKE.DEPENDFILE} (eval)
+Var_Parse: ${.MAKE.MODE:tl} (eval)
+Evaluating modifier ${.MAKE.MODE:t...} on value "" (eval, undefined)
+Result of ${.MAKE.MODE:tl} is "" (eval, undefined)
+Global: MFLAGS = -r -k -d sv
+Var_Parse: ${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@} (eval)
+Var_Parse: ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@} (eval)
+Evaluating modifier ${.MAKEOVERRIDES:O} on value ""
+Result of ${.MAKEOVERRIDES:O} is ""
+Evaluating modifier ${.MAKEOVERRIDES:u} on value ""
+Result of ${.MAKEOVERRIDES:u} is ""
+Evaluating modifier ${.MAKEOVERRIDES:@...} on value ""
+Modifier part: "v"
+Modifier part: "$v=${$v:Q}"
+ModifyWords: split "" into 1 word
+Command: ignoring delete 'v' as it is not found
+Result of ${.MAKEOVERRIDES:@v@$v=${$v:Q}@} is ""
+Global: .INCLUDES = # (empty)
+Global: .LIBS = # (empty)
+Global: ignoring delete '.SHELL' as it is not found
+Command: .SHELL = /bin/sh
+Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from edge-case.additional a*.mk .END
+step1: @ = step1
+step1: @ = step1
+step1: * = step1
+SuffFindDeps "step1"
+step1: @ = step1
+step1: * = step1
+ No valid suffix on step1
+Wildcard expanding "edge-case.to"...suffix is ".to"...
+edge-case.to: @ = edge-case.to
+edge-case.to: @ = edge-case.to
+edge-case.to: * = edge-case.to
+SuffFindDeps "edge-case.to"
+ trying edge-case.from...got it
+edge-case.to: @ = edge-case.to
+edge-case.to: * = edge-case
+Expanding "${.PREFIX}${.ARCHIVE}.additional"...Var_Parse: ${.PREFIX}${.ARCHIVE}.additional (eval)
+Var_Parse: ${.ARCHIVE}.additional (eval)
+edge-case.additional...
+ applying .from -> .to to "edge-case.to"
+everything: @ = everything
+everything: @ = everything
+everything: * = everything
+SuffFindDeps "everything"
+everything: @ = everything
+everything: * = everything
+Wildcard expanding "a*.mk"...
+archive-suffix.mk...Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from edge-case.additional a*.mk .END archive-suffix.mk
+archive.mk...Global: .ALLTARGETS = step1 edge-case.to everything ${.PREFIX}${.ARCHIVE}.additional edge-case.from edge-case.additional a*.mk .END archive-suffix.mk archive.mk
+
+ No valid suffix on everything
+Wildcard expanding "edge-case.additional"...
+edge-case.additional: @ = edge-case.additional
+edge-case.additional: @ = edge-case.additional
+edge-case.additional: * = edge-case.additional
+SuffFindDeps "edge-case.additional"
+ No known suffix on edge-case.additional. Using .NULL suffix
+not adding suffix rules
+edge-case.additional: @ = edge-case.additional
+edge-case.additional: * = edge-case.additional
+suffix is ".from"...
+edge-case.from: @ = edge-case.from
+edge-case.from: @ = edge-case.from
+edge-case.from: * = edge-case.from
+SuffFindDeps "edge-case.from"
+edge-case.from: @ = edge-case.from
+edge-case.from: * = edge-case
+Wildcard expanding "archive-suffix.mk"...
+archive-suffix.mk: @ = archive-suffix.mk
+archive-suffix.mk: @ = archive-suffix.mk
+archive-suffix.mk: * = archive-suffix.mk
+SuffFindDeps "archive-suffix.mk"
+ No known suffix on archive-suffix.mk. Using .NULL suffix
+adding suffix rules
+archive-suffix.mk: @ = archive-suffix.mk
+archive-suffix.mk: * = archive-suffix.mk
+archive-suffix.mk: @ = archive-suffix.mk
+archive-suffix.mk: * = archive-suffix.mk
+Wildcard expanding "archive.mk"...
+archive.mk: @ = archive.mk
+archive.mk: @ = archive.mk
+archive.mk: * = archive.mk
+SuffFindDeps "archive.mk"
+ No known suffix on archive.mk. Using .NULL suffix
+adding suffix rules
+archive.mk: @ = archive.mk
+archive.mk: * = archive.mk
+archive.mk: @ = archive.mk
+archive.mk: * = archive.mk
+Wildcard expanding "edge-case.additional"...
+edge-case.additional: ? = # (empty)
+edge-case.additional: > = # (empty)
+Var_Parse: ${.TARGET} out of nothing. (eval)
+: Making edge-case.additional out of nothing.
+edge-case.to: < = edge-case.from
+suffix is ".from"...
+edge-case.from: ? = # (empty)
+edge-case.from: > = # (empty)
+Var_Parse: ${.TARGET} out of nothing. (eval)
+: Making edge-case.from out of nothing.
+edge-case.to: > = edge-case.additional
+edge-case.to: ? = edge-case.additional
+edge-case.to: > = edge-case.additional edge-case.from
+edge-case.to: ? = edge-case.additional edge-case.from
+Var_Parse: ${.TARGET} from ${.ALLSRC}. (eval)
+Var_Parse: ${.ALLSRC}. (eval)
+: Making edge-case.to from edge-case.additional edge-case.from.
+everything: > = archive-suffix.mk
+everything: ? = archive-suffix.mk
+everything: > = archive-suffix.mk archive.mk
+everything: ? = archive-suffix.mk archive.mk
+Var_Parse: ${.TARGET} from ${.ALLSRC}. (eval)
+Var_Parse: ${.ALLSRC}. (eval)
+: Making everything from archive-suffix.mk archive.mk.
+step1: > = edge-case.to
+step1: ? = edge-case.to
+step1: > = edge-case.to everything
+step1: ? = edge-case.to everything
+.END: @ = .END
+.END: * = .END
+SuffFindDeps ".END"
+ No known suffix on .END. Using .NULL suffix
+adding suffix rules
+.END: @ = .END
+.END: * = .END
+Wildcard expanding ".END"...
+.END: ? = # (empty)
+.END: > = # (empty)
+exit status 0
diff --git a/unit-tests/suff.mk b/unit-tests/suff.mk
new file mode 100644
index 000000000000..53f6eb82b224
--- /dev/null
+++ b/unit-tests/suff.mk
@@ -0,0 +1,41 @@
+# $NetBSD: suff.mk,v 1.3 2025/01/14 21:39:25 rillig Exp $
+#
+# Demonstrate suffix rules and dependency resolution.
+
+
+# Circumvent the file system cache.
+.if !make(init) && !make(step*)
+all:
+ @${MAKE} -f ${MAKEFILE} init
+ @${MAKE} -f ${MAKEFILE} step1
+.endif
+
+
+.if make(init)
+init:
+. if ${.PARSEDIR:tA} != ${.CURDIR:tA}
+${:U}!= cd ${MAKEFILE:H} && cp a*.mk ${.CURDIR}
+. endif
+.endif
+
+
+.if make(step1)
+step1: .PHONY edge-case.to everything
+
+.MAKEFLAGS: -dsv
+
+.SUFFIXES: .from .to
+
+.from.to:
+ : Making ${.TARGET} from ${.ALLSRC}.
+
+# When making this target, ${.ARCHIVE} is undefined, but there's no warning.
+# expect: Var_Parse: ${.ARCHIVE}.additional (eval)
+edge-case.to: ${.PREFIX}${.ARCHIVE}.additional
+
+edge-case.from edge-case.additional:
+ : Making ${.TARGET} out of nothing.
+
+everything: .PHONY a*.mk
+ : Making ${.TARGET} from ${.ALLSRC}.
+.endif
diff --git a/unit-tests/var-eval-short.exp b/unit-tests/var-eval-short.exp
index 12e2b78d7a3d..2b2e95750a1c 100644
--- a/unit-tests/var-eval-short.exp
+++ b/unit-tests/var-eval-short.exp
@@ -1,6 +1,6 @@
-make: "var-eval-short.mk" line 46: while parsing "${:Uword:@${FAIL}@expr@}": In the :@ modifier, the variable name "${FAIL}" must not contain a dollar
-make: "var-eval-short.mk" line 46: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@})
-Parsing line 159: .if 0 && ${0:?${FAIL}then:${FAIL}else}
+make: "var-eval-short.mk" line 45: In the :@ modifier, the variable name "${FAIL}" must not contain a dollar
+ while parsing "${:Uword:@${FAIL}@expr@}"
+Parsing var-eval-short.mk:158: .if 0 && ${0:?${FAIL}then:${FAIL}else}
CondParser_Eval: 0 && ${0:?${FAIL}then:${FAIL}else}
Var_Parse: ${0:?${FAIL}then:${FAIL}else} (parse)
Parsing modifier ${0:?...}
@@ -9,9 +9,9 @@ Modifier part: "${FAIL}then"
Var_Parse: ${FAIL}else} (parse)
Modifier part: "${FAIL}else"
Result of ${0:?${FAIL}then:${FAIL}else} is "" (parse, defined)
-Parsing line 167: DEFINED= defined
+Parsing var-eval-short.mk:166: DEFINED= defined
Global: DEFINED = defined
-Parsing line 168: .if 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
+Parsing var-eval-short.mk:167: .if 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
CondParser_Eval: 0 && ${DEFINED:L:?${FAIL}then:${FAIL}else}
Var_Parse: ${DEFINED:L:?${FAIL}then:${FAIL}else} (parse)
Parsing modifier ${DEFINED:L}
@@ -22,7 +22,7 @@ Modifier part: "${FAIL}then"
Var_Parse: ${FAIL}else} (parse)
Modifier part: "${FAIL}else"
Result of ${DEFINED:?${FAIL}then:${FAIL}else} is "defined" (parse, regular)
-Parsing line 170: .MAKEFLAGS: -d0
+Parsing var-eval-short.mk:169: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
Global: .MAKEFLAGS = -r -k -d cpv -d
Global: .MAKEFLAGS = -r -k -d cpv -d 0
diff --git a/unit-tests/var-eval-short.mk b/unit-tests/var-eval-short.mk
index d6872d158e32..d6dc36254851 100644
--- a/unit-tests/var-eval-short.mk
+++ b/unit-tests/var-eval-short.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-eval-short.mk,v 1.14 2024/07/05 20:01:52 rillig Exp $
+# $NetBSD: var-eval-short.mk,v 1.17 2025/01/11 20:54:45 rillig Exp $
#
# Tests for each variable modifier to ensure that they only do the minimum
# necessary computations. If the result of the expression is irrelevant,
@@ -41,8 +41,7 @@ FAIL= ${:!echo unexpected 1>&2!}
# after the loop, when undefining the temporary global loop variable.
# Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the
# variable name.
-# expect+2: while parsing "${:Uword:@${FAIL}@expr@}": In the :@ modifier, the variable name "${FAIL}" must not contain a dollar
-# expect+1: Malformed conditional (0 && ${:Uword:@${FAIL}@expr@})
+# expect+1: In the :@ modifier, the variable name "${FAIL}" must not contain a dollar
.if 0 && ${:Uword:@${FAIL}@expr@}
.endif
diff --git a/unit-tests/var-op-expand.exp b/unit-tests/var-op-expand.exp
index 63d74f313737..655a46023a11 100644
--- a/unit-tests/var-op-expand.exp
+++ b/unit-tests/var-op-expand.exp
@@ -1,6 +1,10 @@
-make: "var-op-expand.mk" line 274: while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}": while evaluating variable "later" with value "": Unknown modifier "s,value,replaced,"
+make: "var-op-expand.mk" line 274: Unknown modifier "s,value,replaced,"
+ while evaluating variable "later" with value ""
+ while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}"
make: "var-op-expand.mk" line 278: warning: XXX Neither branch should be taken.
-make: "var-op-expand.mk" line 283: while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}": while evaluating variable "later" with value "lowercase-value": Unknown modifier "s,value,replaced,"
+make: "var-op-expand.mk" line 283: Unknown modifier "s,value,replaced,"
+ while evaluating variable "later" with value "lowercase-value"
+ while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}"
make: "var-op-expand.mk" line 285: warning: XXX Neither branch should be taken.
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/unit-tests/var-op-expand.mk b/unit-tests/var-op-expand.mk
index a2ae8b0e22d1..a8e64bf45424 100644
--- a/unit-tests/var-op-expand.mk
+++ b/unit-tests/var-op-expand.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-op-expand.mk,v 1.21 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: var-op-expand.mk,v 1.22 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the := variable assignment operator, which expands its
# right-hand side.
@@ -270,7 +270,7 @@ later= lowercase-value
.undef later
INDIRECT:= ${LATER:S,value,replaced,} OK ${LATER:value=sysv}
indirect:= ${INDIRECT:tl}
-# expect+1: while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}": while evaluating variable "later" with value "": Unknown modifier "s,value,replaced,"
+# expect+1: Unknown modifier "s,value,replaced,"
.if ${indirect} != " ok "
. error
.else
@@ -279,7 +279,7 @@ indirect:= ${INDIRECT:tl}
.endif
LATER= uppercase-value
later= lowercase-value
-# expect+1: while evaluating variable "indirect" with value "${later:s,value,replaced,} ok ${later:value=sysv}": while evaluating variable "later" with value "lowercase-value": Unknown modifier "s,value,replaced,"
+# expect+1: Unknown modifier "s,value,replaced,"
.if ${indirect} != "uppercase-replaced ok uppercase-sysv"
# expect+1: warning: XXX Neither branch should be taken.
. warning XXX Neither branch should be taken.
diff --git a/unit-tests/var-op-shell.exp b/unit-tests/var-op-shell.exp
index 952af6df5518..9117001d40a7 100644
--- a/unit-tests/var-op-shell.exp
+++ b/unit-tests/var-op-shell.exp
@@ -8,4 +8,10 @@ Capturing the output of command "echo '$$$$'"
Global: OUTPUT = $$$$
Global: .MAKEFLAGS = -r -k -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0
+Var_Parse: ${UNDEF}y (eval)
+Capturing the output of command "echo xy"
+Global: OUTPUT_OF_UNDEF = xy
+Var_Parse: ${OUTPUT_OF_UNDEF} != "xy" (eval-defined-loud)
+Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d
+Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0
exit status 0
diff --git a/unit-tests/var-op-shell.mk b/unit-tests/var-op-shell.mk
index bfc2e4f1361d..f9c7c717b8f1 100644
--- a/unit-tests/var-op-shell.mk
+++ b/unit-tests/var-op-shell.mk
@@ -1,4 +1,4 @@
-# $NetBSD: var-op-shell.mk,v 1.10 2024/07/11 20:09:16 sjg Exp $
+# $NetBSD: var-op-shell.mk,v 1.11 2025/01/11 21:21:33 rillig Exp $
#
# Tests for the != variable assignment operator, which runs its right-hand
# side through the shell.
@@ -109,4 +109,13 @@ OUTPUT_LONG!= echo "$$0" || : ${:U:range=1000}
.endif
+# An undefined expression results in an empty string.
+.MAKEFLAGS: -dv
+OUTPUT_OF_UNDEF!= echo x${UNDEF}y
+.if ${OUTPUT_OF_UNDEF} != "xy"
+. error
+.endif
+.MAKEFLAGS: -d0
+
+
all:
diff --git a/unit-tests/var-recursive.exp b/unit-tests/var-recursive.exp
index c92c22b125dc..59812e0e71ff 100644
--- a/unit-tests/var-recursive.exp
+++ b/unit-tests/var-recursive.exp
@@ -1,22 +1,27 @@
-make: "var-recursive.mk" line 21: still there
-make: Variable DIRECT is recursive.
- in var-recursive.mk:22
+make: "var-recursive.mk" line 11: Variable DIRECT is recursive.
+ while evaluating variable "DIRECT" with value "${DIRECT}"
in directory <curdir>
-
-make: stopped in unit-tests
-make: Variable INDIRECT1 is recursive.
- in var-recursive.mk:29
+make: "var-recursive.mk" line 11: <>
+make: "var-recursive.mk" line 19: Variable INDIRECT1 is recursive.
+ while evaluating variable "INDIRECT2" with value "${INDIRECT1}"
+ while evaluating variable "INDIRECT1" with value "${INDIRECT2}"
in directory <curdir>
-
-make: stopped in unit-tests
-make: "var-recursive.mk" line 37: ok
-make: Variable V is recursive.
- in var-recursive.mk:45
+make: "var-recursive.mk" line 19: <>
+make: "var-recursive.mk" line 26: <ok>
+make: "var-recursive.mk" line 34: Variable MODIFIERS is recursive.
+ while evaluating variable "MODIFIERS" with value "${MODIFIERS:Mpattern}"
in directory <curdir>
-
-make: stopped in unit-tests
-: OK
-In a command near "var-recursive.mk" line 57: make[1]: Variable VAR is recursive.
-
-make: stopped making "target" in unit-tests
+make: "var-recursive.mk" line 34: <Mpattern}>
+make: "var-recursive.mk" line 43: Variable V is recursive.
+ while evaluating variable "V" with value "$V"
+ in directory <curdir>
+make: "var-recursive.mk" line 43: <>
+make: Fatal errors encountered -- cannot continue
+make: stopped making "loadtime" in unit-tests
+sub-exit status 1
+: before-recursive
+make: Variable VAR is recursive.
+ while evaluating variable "VAR" with value "${VAR}"
+ in target "runtime"
+sub-exit status 2
exit status 0
diff --git a/unit-tests/var-recursive.mk b/unit-tests/var-recursive.mk
index 72231656673c..e2951c900b11 100644
--- a/unit-tests/var-recursive.mk
+++ b/unit-tests/var-recursive.mk
@@ -1,63 +1,64 @@
-# $NetBSD: var-recursive.mk,v 1.6 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: var-recursive.mk,v 1.10 2024/08/29 20:20:36 rillig Exp $
#
-# Tests for expressions that refer to themselves and thus
-# cannot be evaluated.
+# Tests for expressions that refer to themselves and thus cannot be
+# evaluated, as that would lead to an endless loop.
-TESTS= direct indirect conditional short target
+.if make(loadtime)
-# Since make exits immediately when it detects a recursive expression,
-# the actual tests are run in sub-makes.
-TEST?= # none
-.if ${TEST} == ""
-all:
-.for test in ${TESTS}
- @${.MAKE} -f ${MAKEFILE} TEST=${test} || :
-.endfor
-
-.elif ${TEST} == direct
+DIRECT= ${DIRECT} # Defining a recursive variable is not an error.
+# expect+2: Variable DIRECT is recursive.
+# expect+1: <>
+. info <${DIRECT}> # But expanding such a variable is an error.
-DIRECT= ${DIRECT} # Defining a recursive variable is not yet an error.
-# expect+1: still there
-. info still there # Therefore this line is printed.
-. info ${DIRECT} # But expanding the variable is an error.
-
-.elif ${TEST} == indirect
# The chain of variables that refer to each other may be long.
INDIRECT1= ${INDIRECT2}
INDIRECT2= ${INDIRECT1}
-. info ${INDIRECT1}
+# expect+2: Variable INDIRECT1 is recursive.
+# expect+1: <>
+. info <${INDIRECT1}>
-.elif ${TEST} == conditional
# The variable refers to itself, but only in the branch of a condition that
-# is never satisfied and is thus not evaluated.
+# is not satisfied and is thus not evaluated.
CONDITIONAL= ${1:?ok:${CONDITIONAL}}
-# expect+1: ok
-. info ${CONDITIONAL}
+# expect+1: <ok>
+. info <${CONDITIONAL}>
+
+
+# An expression with modifiers is skipped halfway. This can lead to wrong
+# follow-up error messages, but recursive variables occur seldom.
+MODIFIERS= ${MODIFIERS:Mpattern}
+# expect+2: Variable MODIFIERS is recursive.
+# expect+1: <Mpattern}>
+. info <${MODIFIERS}>
-.elif ${TEST} == short
# Short variable names can be expanded using the short-hand $V notation,
# which takes a different code path in Var_Parse for parsing the variable
# name. Ensure that these are checked as well.
V= $V
-. info $V
+# expect+2: Variable V is recursive.
+# expect+1: <>
+. info <$V>
-.elif ${TEST} == target
+.elif make(runtime)
-# If a recursive variable is accessed in a command of a target, the makefiles
-# are not parsed anymore, so there is no location information from the
-# .includes and .for directives. In such a case, use the location of the last
-# command of the target to provide at least a hint to the location.
VAR= ${VAR}
-target:
- : OK
- : ${VAR}
- : OK
+runtime:
+# expect: : before-recursive
+ : before-recursive
+# expect: make: Variable VAR is recursive.
+# expect-not: recursive-line-before
+# expect-not: recursive-line-after
+ : recursive-line-before <${VAR}> recursive-line-after
+# expect-not: after-recursive
+ : after-recursive
.else
-. error Unknown test "${TEST}"
-.endif
all:
+ @${MAKE} -f ${MAKEFILE} loadtime || echo "sub-exit status $$?"
+ @${MAKE} -f ${MAKEFILE} runtime || echo "sub-exit status $$?"
+
+.endif
diff --git a/unit-tests/vardebug.exp b/unit-tests/vardebug.exp
index 9937185ae807..5e220f24df74 100644
--- a/unit-tests/vardebug.exp
+++ b/unit-tests/vardebug.exp
@@ -11,57 +11,66 @@ Global: ignoring 'FROM_CMDLINE = overwritten' due to a command line variable of
Global: VAR = 1
Global: VAR = 1 2
Global: VAR = 1 2 3
-Var_Parse: ${VAR:M[2]} (eval-defined)
+Var_Parse: ${VAR:M[2]} (eval-defined-loud)
Evaluating modifier ${VAR:M...} on value "1 2 3"
Pattern for ':M' is "[2]"
ModifyWords: split "1 2 3" into 3 words
Result of ${VAR:M[2]} is "2"
-Var_Parse: ${VAR:N[2]} (eval-defined)
+Var_Parse: ${VAR:N[2]} (eval-defined-loud)
Evaluating modifier ${VAR:N...} on value "1 2 3"
Pattern for ':N' is "[2]"
ModifyWords: split "1 2 3" into 3 words
Result of ${VAR:N[2]} is "1 3"
-Var_Parse: ${VAR:S,2,two,} (eval-defined)
+Var_Parse: ${VAR:S,2,two,} (eval-defined-loud)
Evaluating modifier ${VAR:S...} on value "1 2 3"
Modifier part: "2"
Modifier part: "two"
ModifyWords: split "1 2 3" into 3 words
Result of ${VAR:S,2,two,} is "1 two 3"
-Var_Parse: ${VAR:Q} (eval-defined)
+Var_Parse: ${VAR:Q} (eval-defined-loud)
Evaluating modifier ${VAR:Q} on value "1 2 3"
Result of ${VAR:Q} is "1\ 2\ 3"
-Var_Parse: ${VAR:tu:tl:Q} (eval-defined)
+Var_Parse: ${VAR:tu:tl:Q} (eval-defined-loud)
Evaluating modifier ${VAR:t...} on value "1 2 3"
Result of ${VAR:tu} is "1 2 3"
Evaluating modifier ${VAR:t...} on value "1 2 3"
Result of ${VAR:tl} is "1 2 3"
Evaluating modifier ${VAR:Q} on value "1 2 3"
Result of ${VAR:Q} is "1\ 2\ 3"
-Var_Parse: ${:Uvalue:${:UM*e}:Mvalu[e]} (eval-defined)
-Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
-Result of ${:Uvalue} is "value" (eval-defined, defined)
+Var_Parse: ${:Uvalue:${:UM*e}:Mvalu[e]} (eval-defined-loud)
+Evaluating modifier ${:U...} on value "" (eval, undefined)
+Result of ${:Uvalue} is "value" (eval, defined)
Indirect modifier "M*e" from "${:UM*e}"
-Evaluating modifier ${:M...} on value "value" (eval-defined, defined)
+Evaluating modifier ${:M...} on value "value" (eval, defined)
Pattern for ':M' is "*e"
ModifyWords: split "value" into 1 word
-Result of ${:M*e} is "value" (eval-defined, defined)
-Evaluating modifier ${:M...} on value "value" (eval-defined, defined)
+Result of ${:M*e} is "value" (eval, defined)
+Evaluating modifier ${:M...} on value "value" (eval, defined)
Pattern for ':M' is "valu[e]"
ModifyWords: split "value" into 1 word
-Result of ${:Mvalu[e]} is "value" (eval-defined, defined)
+Result of ${:Mvalu[e]} is "value" (eval, defined)
Global: delete VAR
-Var_Parse: ${:Uvariable:unknown} (eval-defined)
-Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
-Result of ${:Uvariable} is "variable" (eval-defined, defined)
-Evaluating modifier ${:u...} on value "variable" (eval-defined, defined)
-make: "vardebug.mk" line 63: while evaluating "${:Uvariable:unknown}" with value "variable": Unknown modifier "unknown"
-Result of ${:unknown} is error (eval-defined, defined)
-make: "vardebug.mk" line 63: Malformed conditional (${:Uvariable:unknown})
-Var_Parse: ${UNDEFINED} (eval-defined)
-make: "vardebug.mk" line 73: Malformed conditional (${UNDEFINED})
+Var_Parse: ${:Uvariable:unknown} (eval-defined-loud)
+Evaluating modifier ${:U...} on value "" (eval, undefined)
+Result of ${:Uvariable} is "variable" (eval, defined)
+Evaluating modifier ${:u...} on value "variable" (eval, defined)
+make: "vardebug.mk" line 62: Unknown modifier "unknown"
+ while evaluating "${:Uvariable:unknown}" with value "variable"
+Result of ${:unknown} is error (eval, defined)
+Var_Parse: ${UNDEFINED} (eval-defined-loud)
+make: "vardebug.mk" line 66: Variable "UNDEFINED" is undefined
Global: ignoring delete '.SHELL' as it is not found
Command: .SHELL = </path/to/shell>
Command: ignoring '.SHELL = overwritten' as it is read-only
+Global: DYN = ${:U$@} $@ ${@}
+Var_Parse: ${DYN} (eval-keep-dollar-and-undefined)
+Var_Parse: ${:U$@} $@ ${@} (eval-keep-dollar-and-undefined)
+Evaluating modifier ${:U...} on value "" (eval-keep-dollar-and-undefined, undefined)
+Var_Parse: $@} $@ ${@} (eval-keep-dollar-and-undefined)
+Result of ${:U$@} is "$(.TARGET)" (eval-keep-dollar-and-undefined, defined)
+Var_Parse: $@ ${@} (eval-keep-dollar-and-undefined)
+Var_Parse: ${@} (eval-keep-dollar-and-undefined)
+Global: DYN = $(.TARGET) $(.TARGET) ${@}
Global: .MAKEFLAGS = -r -k -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0
make: Fatal errors encountered -- cannot continue
diff --git a/unit-tests/vardebug.mk b/unit-tests/vardebug.mk
index 7e6154d7e52c..975f32b62286 100644
--- a/unit-tests/vardebug.mk
+++ b/unit-tests/vardebug.mk
@@ -1,4 +1,4 @@
-# $NetBSD: vardebug.mk,v 1.11 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: vardebug.mk,v 1.16 2025/01/11 21:21:33 rillig Exp $
#
# Demonstrates the debugging output for var.c.
@@ -48,7 +48,7 @@ VAR+= 3
.endif
# ApplyModifiers, "Got ..."
-# expect: Result of ${:Mvalu[e]} is "value" (eval-defined, defined)
+# expect: Result of ${:Mvalu[e]} is "value" (eval, defined)
.if ${:Uvalue:${:UM*e}:Mvalu[e]}
.endif
@@ -57,19 +57,12 @@ VAR+= 3
# When ApplyModifiers results in an error, this appears in the debug log
# as "is error", without surrounding quotes.
-# expect: Result of ${:unknown} is error (eval-defined, defined)
-# expect+2: Malformed conditional (${:Uvariable:unknown})
-# expect+1: while evaluating "${:Uvariable:unknown}" with value "variable": Unknown modifier "unknown"
+# expect: Result of ${:unknown} is error (eval, defined)
+# expect+1: Unknown modifier "unknown"
.if ${:Uvariable:unknown}
.endif
-# XXX: The error message is "Malformed conditional", which is wrong.
-# The condition is syntactically fine, it just contains an undefined variable.
-#
-# There is a specialized error message for "Undefined variable", but as of
-# 2020-08-08, that is not covered by any unit tests. It might even be
-# unreachable.
-# expect+1: Malformed conditional (${UNDEFINED})
+# expect+1: Variable "UNDEFINED" is undefined
.if ${UNDEFINED}
.endif
@@ -79,4 +72,8 @@ VAR+= 3
# expect: Command: ignoring '.SHELL = overwritten' as it is read-only
.MAKEFLAGS: .SHELL=overwritten
+DYN = ${:U$@} $@ ${@}
+# expect: Global: DYN = $(.TARGET) $(.TARGET) ${@}
+DYN := ${DYN}
+
.MAKEFLAGS: -d0
diff --git a/unit-tests/varmisc.exp b/unit-tests/varmisc.exp
index 5e63f9f6563a..79d2c19e4d1b 100644
--- a/unit-tests/varmisc.exp
+++ b/unit-tests/varmisc.exp
@@ -43,29 +43,30 @@ export-appended: env mk
parse-dynamic: parse-dynamic parse-dynamic before
parse-dynamic: parse-dynamic parse-dynamic after
parse-dynamic: parse-dynamic parse-dynamic after
-varerror-unclosed:begin
-make: in target "varerror-unclosed": Unclosed variable ""
+varerror-unclosed-1:begin
+make: Unclosed variable ""
+ in target "varerror-unclosed-2"
+make: Unclosed variable "UNCLOSED"
+ in target "varerror-unclosed-3"
+make: Unclosed variable "UNCLOSED"
+ in target "varerror-unclosed-4"
+make: Unclosed variable "PATTERN"
+ while evaluating variable "UNCLOSED" with value ""
+ in target "varerror-unclosed-5"
+make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
+ while evaluating variable "UNCLOSED" with value ""
+ in target "varerror-unclosed-5"
+make: Unclosed variable "param"
+ in target "varerror-unclosed-6"
+make: Unclosed variable "UNCLOSED."
+ in target "varerror-unclosed-6"
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
-
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed variable "PATTERN"
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
-
-make: in target "varerror-unclosed": Unclosed variable "param"
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED."
-
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.1"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.2"
-
-make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.3"
-
-make: in target "varerror-unclosed": while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}": while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG": Unclosed variable "UNCLOSED_ORIG"
-
-varerror-unclosed:end
+make: Unclosed variable "UNCLOSED.1"
+ in target "varerror-unclosed-7"
+make: Unclosed variable "UNCLOSED_ORIG"
+ while evaluating variable "UNCLOSED_INDIR_1" with value "${UNCLOSED_ORIG"
+ while evaluating variable "UNCLOSED_INDIR_2" with value "${UNCLOSED_INDIR_1}"
+ in target "varerror-unclosed-8"
target1-flags: we have: one two
target2-flags: we have: one two three four
exit status 2
diff --git a/unit-tests/varmisc.mk b/unit-tests/varmisc.mk
index 94ac32812d87..b067742e9ac4 100644
--- a/unit-tests/varmisc.mk
+++ b/unit-tests/varmisc.mk
@@ -1,5 +1,4 @@
-# $Id: varmisc.mk,v 1.27 2024/07/06 18:23:18 sjg Exp $
-# $NetBSD: varmisc.mk,v 1.35 2024/07/05 18:59:33 rillig Exp $
+# $NetBSD: varmisc.mk,v 1.37 2024/08/29 20:20:36 rillig Exp $
#
# Miscellaneous variable tests.
@@ -8,7 +7,7 @@ all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \
all: save-dollars
all: export-appended
all: parse-dynamic
-all: varerror-unclosed
+all: varerror-unclosed-{1,2,3,4,5,6,7,8}
unmatched_var_paren:
@echo ${foo::=foo-text}
@@ -189,25 +188,30 @@ target1-flags: target1.c
target2-flags: target2.c
@echo $@: we have: ${FLAGS}
-varerror-unclosed:
+varerror-unclosed-1:
@echo $@:begin
-# expect: make: in target "varerror-unclosed": Unclosed variable ""
+varerror-unclosed-2:
+# expect: make: Unclosed variable ""
@echo $(
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
+varerror-unclosed-3:
+# expect: make: Unclosed variable "UNCLOSED"
@echo $(UNCLOSED
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED"
+varerror-unclosed-4:
+# expect: make: Unclosed variable "UNCLOSED"
@echo ${UNCLOSED
-# expect: make: in target "varerror-unclosed": while evaluating variable "UNCLOSED" with value "": Unclosed expression, expecting '}' for modifier "M${PATTERN"
+varerror-unclosed-5:
+# expect: make: Unclosed expression, expecting '}' for modifier "M${PATTERN"
@echo ${UNCLOSED:M${PATTERN
-# expect: make: in target "varerror-unclosed": Unclosed variable "param"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED."
+varerror-unclosed-6:
+# expect: make: Unclosed variable "param"
+# expect: make: Unclosed variable "UNCLOSED."
@echo ${UNCLOSED.${param
+varerror-unclosed-7:
@echo $
.for i in 1 2 3
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.1"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.2"
-# expect: make: in target "varerror-unclosed": Unclosed variable "UNCLOSED.3"
+# expect: make: Unclosed variable "UNCLOSED.1"
@echo ${UNCLOSED.${i}
.endfor
+varerror-unclosed-8:
@echo ${UNCLOSED_INDIR_2}
@echo $@:end
diff --git a/unit-tests/varmod-assign-shell.exp b/unit-tests/varmod-assign-shell.exp
index 819fa6a5f304..712636491fc1 100644
--- a/unit-tests/varmod-assign-shell.exp
+++ b/unit-tests/varmod-assign-shell.exp
@@ -4,7 +4,7 @@ Var_Parse: ${ASSIGNED::!=echo output; ${:U(exit 13)}} (eval-keep-dollar-and-unde
Evaluating modifier ${ASSIGNED::...} on value "previous" (eval-keep-dollar-and-undefined, regular)
Modifier part: "echo output; (exit 13)"
Capturing the output of command "echo output; (exit 13)"
-make: "varmod-assign-shell.mk" line 26: warning: while evaluating variable "ASSIGNED" with value "previous": Command "echo output; (exit 13)" exited with status 13
+make: "varmod-assign-shell.mk" line 26: warning: Command "echo output; (exit 13)" exited with status 13
Result of ${ASSIGNED::!=echo output; ${:U(exit 13)}} is "" (eval-keep-dollar-and-undefined, regular)
Global: _ = # (empty)
Global: .MAKEFLAGS = -r -k -d v -d
diff --git a/unit-tests/varmod-assign-shell.mk b/unit-tests/varmod-assign-shell.mk
index 0b3e553055b3..7bbea0ff9463 100644
--- a/unit-tests/varmod-assign-shell.mk
+++ b/unit-tests/varmod-assign-shell.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-assign-shell.mk,v 1.8 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-assign-shell.mk,v 1.11 2025/01/11 21:21:33 rillig Exp $
#
# Tests for the variable modifier '::!=', which assigns the output of a shell
# command to the variable, but only if the command exited successfully. This
@@ -22,7 +22,7 @@ DIRECT!= echo output; (exit 13)
ASSIGNED= previous
.MAKEFLAGS: -dv # to see the "Capturing" debug output
-# expect+1: warning: while evaluating variable "ASSIGNED" with value "previous": Command "echo output; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo output; (exit 13)" exited with status 13
_:= ${ASSIGNED::!=echo output; ${:U(exit 13)}}
.MAKEFLAGS: -d0
diff --git a/unit-tests/varmod-assign.exp b/unit-tests/varmod-assign.exp
index 6c8bfb5cd6e8..4a7dc509642a 100644
--- a/unit-tests/varmod-assign.exp
+++ b/unit-tests/varmod-assign.exp
@@ -2,28 +2,28 @@ Global: param = twice
Global: VARNAME = VAR.$${param}
Var_Parse: ${VARNAME} (eval)
Global: VAR.${param} = initial-value
-Var_Parse: ${${VARNAME}::=assigned-value} (eval-defined)
-Var_Parse: ${VARNAME}::=assigned-value} (eval-defined)
+Var_Parse: ${${VARNAME}::=assigned-value} (eval-defined-loud)
+Var_Parse: ${VARNAME}::=assigned-value} (eval)
Evaluating modifier ${VAR.${param}::...} on value "initial-value"
Modifier part: "assigned-value"
Global: VAR.${param} = assigned-value
Result of ${VAR.${param}::=assigned-value} is ""
-Var_Parse: ${${VARNAME}} != "assigned-value" (eval-defined)
-Var_Parse: ${VARNAME}} != "assigned-value" (eval-defined)
+Var_Parse: ${${VARNAME}} != "assigned-value" (eval-defined-loud)
+Var_Parse: ${VARNAME}} != "assigned-value" (eval)
Global: .MAKEFLAGS = -r -k -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0
-Var_Parse: ${CMD_CMD_VAR::=new-value} || ${CMD_GLOBAL_VAR::=new-value} || ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined)
+Var_Parse: ${CMD_CMD_VAR::=new-value} || ${CMD_GLOBAL_VAR::=new-value} || ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined-loud)
Evaluating modifier ${CMD_CMD_VAR::...} on value "cmd-value"
Modifier part: "new-value"
Command: CMD_CMD_VAR = new-value
Global: .MAKEOVERRIDES = FIRST LAST LAST LAST APPENDED RAN RAN RAN IT1 THEN1 IE2 ELSE2 CMD_CMD_VAR CMD_CMD_VAR
Result of ${CMD_CMD_VAR::=new-value} is ""
-Var_Parse: ${CMD_GLOBAL_VAR::=new-value} || ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined)
+Var_Parse: ${CMD_GLOBAL_VAR::=new-value} || ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined-loud)
Evaluating modifier ${CMD_GLOBAL_VAR::...} on value "global-value"
Modifier part: "new-value"
Global: CMD_GLOBAL_VAR = new-value
Result of ${CMD_GLOBAL_VAR::=new-value} is ""
-Var_Parse: ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined)
+Var_Parse: ${CMD_ENV_VAR::=new-value} || "${CMD_NEW_VAR::=new-value}" (eval-defined-loud)
Evaluating modifier ${CMD_ENV_VAR::...} on value "env-value"
Modifier part: "new-value"
Global: CMD_ENV_VAR = new-value
@@ -37,18 +37,22 @@ Global: .MAKEOVERRIDES = FIRST LAST LAST LAST APPENDED RAN RAN RAN IT1 THEN1 IE
Result of ${CMD_NEW_VAR::=new-value} is "" (eval, undefined)
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0
-make: in target "mod-assign-empty": while evaluating "${::=value}" with value "": Bad modifier ":"
-mod-assign-empty: value}
-make: in target "mod-assign-empty": while evaluating "${:Uvalue::=overwritten}" with value "value": Bad modifier ":"
-mod-assign-empty: overwritten}
-mod-assign-empty: VAR=overwritten
-make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
-
+make: Bad modifier ":"
+ while evaluating "${::=value}" with value ""
+ in target "mod-assign-empty-1"
+make: Bad modifier ":"
+ while evaluating "${:Uvalue::=overwritten}" with value "value"
+ in target "mod-assign-empty-2"
+mod-assign-empty-3: VAR=overwritten
+make: Unknown modifier ":x"
+ while evaluating variable "ASSIGN" with value ""
+ in target "mod-assign-parse-1"
sysv:y
-make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
-
+make: Unfinished modifier ('}' missing)
+ while evaluating variable "ASSIGN" with value ""
+ in target "mod-assign-parse-3"
ok=word
-make: warning: in target "mod-assign-shell-error": while evaluating variable "SH_ERR" with value "previous": Command " echo word; (exit 13) " exited with status 13
+make: warning: Command " echo word; (exit 13) " exited with status 13
err=previous
Command: TARGET_CMD_VAR = cmd-value
Global: TARGET_GLOBAL_VAR = global-value
diff --git a/unit-tests/varmod-assign.mk b/unit-tests/varmod-assign.mk
index ee1c86c039f5..237198faf254 100644
--- a/unit-tests/varmod-assign.mk
+++ b/unit-tests/varmod-assign.mk
@@ -1,12 +1,12 @@
-# $NetBSD: varmod-assign.mk,v 1.23 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-assign.mk,v 1.25 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the obscure ::= variable modifiers, which perform variable
# assignments during evaluation, just like the = operator in C.
.if !make(target)
-all: mod-assign-empty
-all: mod-assign-parse
+all: mod-assign-empty-{1,2,3}
+all: mod-assign-parse-{1,2,3}
all: mod-assign-shell-error
# In the following loop expression,
@@ -71,33 +71,38 @@ SINK4:= ${0:?${THEN4::=then4${IT4::=t4}}:${ELSE4::=else4${IE4::=e4}}} ${THEN4}${
. error
.endif
-mod-assign-empty:
+mod-assign-empty-1:
# Assigning to the empty variable would obviously not work since that
- # variable is write-protected. Therefore it is rejected early with a
- # "Bad modifier" message.
+ # variable is write-protected.
+# expect: make: Bad modifier ":"
@echo $@: ${::=value}
+mod-assign-empty-2:
# In this variant, it is not as obvious that the name of the
- # expression is empty. Assigning to it is rejected as well, with the
- # same "Bad modifier" message.
+ # expression is empty.
+# expect: make: Bad modifier ":"
@echo $@: ${:Uvalue::=overwritten}
+mod-assign-empty-3:
# The :L modifier sets the value of the expression to its variable
# name. The name of the expression is "VAR", therefore assigning to
# that variable works.
+# expect: mod-assign-empty-3: VAR=overwritten
@echo $@: ${VAR:L::=overwritten} VAR=${VAR}
-mod-assign-parse:
+mod-assign-parse-1:
# The modifier for assignment operators starts with a ':'.
# An 'x' after that is an invalid modifier.
- # expect: make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unknown modifier ":x"
+# expect: make: Unknown modifier ":x"
@echo ${ASSIGN::x}
+mod-assign-parse-2:
# When parsing an assignment operator fails because the operator is
# incomplete, make falls back to the SysV modifier.
@echo ${SYSV::=sysv\:x}${SYSV::x=:y}
-# expect: make: in target "mod-assign-parse": while evaluating variable "ASSIGN" with value "": Unfinished modifier ('}' missing)
+mod-assign-parse-3:
+# expect: make: Unfinished modifier ('}' missing)
@echo ${ASSIGN::=value # missing closing brace
mod-assign-shell-error:
diff --git a/unit-tests/varmod-edge.exp b/unit-tests/varmod-edge.exp
index ff4f73d30939..2b3b038373b3 100644
--- a/unit-tests/varmod-edge.exp
+++ b/unit-tests/varmod-edge.exp
@@ -1,12 +1,23 @@
-make: "varmod-edge.mk" line 60: while evaluating variable "MOD" with value "${INP:M${:U*)}}": while evaluating variable "INP" with value "(parentheses)": while evaluating "${:U*)" with value "*)": Unclosed expression, expecting '}' for modifier "U*)"
-make: "varmod-edge.mk" line 88: while evaluating variable "MOD" with value "${INP:M${:U[[}}": while evaluating variable "INP" with value "[ [[ [[[": Unfinished character list in pattern '[[' of modifier ':M'
-make: "varmod-edge.mk" line 178: while evaluating variable "MOD" with value "${INP:a\=b}": while evaluating variable "INP" with value "file.c file...": Unfinished modifier ('=' missing)
-make: "varmod-edge.mk" line 194: while evaluating variable "MOD" with value "${INP::::}": while evaluating variable "INP" with value "value": Unknown modifier ":"
-make: "varmod-edge.mk" line 194: while evaluating variable "MOD" with value "${INP::::}": while evaluating variable "INP" with value "": Unknown modifier ":"
-make: "varmod-edge.mk" line 203: while evaluating "${:Z}" with value "": Unknown modifier "Z"
-make: "varmod-edge.mk" line 203: Malformed conditional (${:Z})
-make: "varmod-edge.mk" line 217: while evaluating "${:S,}" with value "": Unfinished modifier (',' missing)
-make: "varmod-edge.mk" line 217: Malformed conditional (${:S,})
+make: "varmod-edge.mk" line 60: Unclosed expression, expecting '}' for modifier "U*)"
+ while evaluating "${:U*)" with value "*)"
+ while evaluating variable "INP" with value "(parentheses)"
+ while evaluating variable "MOD" with value "${INP:M${:U*)}}"
+make: "varmod-edge.mk" line 88: Unfinished character list in pattern '[[' of modifier ':M'
+ while evaluating variable "INP" with value "[ [[ [[["
+ while evaluating variable "MOD" with value "${INP:M${:U[[}}"
+make: "varmod-edge.mk" line 178: Unfinished modifier ('=' missing)
+ while evaluating variable "INP" with value "file.c file..."
+ while evaluating variable "MOD" with value "${INP:a\=b}"
+make: "varmod-edge.mk" line 194: Unknown modifier ":"
+ while evaluating variable "INP" with value "value"
+ while evaluating variable "MOD" with value "${INP::::}"
+make: "varmod-edge.mk" line 194: Unknown modifier ":"
+ while evaluating variable "INP" with value ""
+ while evaluating variable "MOD" with value "${INP::::}"
+make: "varmod-edge.mk" line 200: Unknown modifier "Z"
+ while evaluating "${:Z}" with value ""
+make: "varmod-edge.mk" line 213: Unfinished modifier (',' missing)
+ while evaluating "${:S,}" with value ""
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-edge.mk b/unit-tests/varmod-edge.mk
index 77c080ef3e5f..ee21b44e00f2 100644
--- a/unit-tests/varmod-edge.mk
+++ b/unit-tests/varmod-edge.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-edge.mk,v 1.29 2024/07/09 17:07:23 rillig Exp $
+# $NetBSD: varmod-edge.mk,v 1.33 2025/01/11 20:54:45 rillig Exp $
#
# Tests for edge cases in variable modifiers.
#
@@ -56,7 +56,7 @@ EXP= \(\{}\):
INP= (parentheses)
MOD= ${INP:M${:U*)}}
EXP= (parentheses)}
-# expect+1: while evaluating variable "MOD" with value "${INP:M${:U*)}}": while evaluating variable "INP" with value "(parentheses)": while evaluating "${:U*)" with value "*)": Unclosed expression, expecting '}' for modifier "U*)"
+# expect+1: Unclosed expression, expecting '}' for modifier "U*)"
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
@@ -84,7 +84,7 @@ EXP= [
INP= [ [[ [[[
MOD= ${INP:M${:U[[}}
EXP= [
-# expect+1: while evaluating variable "MOD" with value "${INP:M${:U[[}}": while evaluating variable "INP" with value "[ [[ [[[": Unfinished character list in pattern '[[' of modifier ':M'
+# expect+1: Unfinished character list in pattern '[[' of modifier ':M'
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
@@ -174,7 +174,7 @@ EXP= file.c file.ext
INP= file.c file...
MOD= ${INP:a\=b}
EXP= # empty
-# expect+1: while evaluating variable "MOD" with value "${INP:a\=b}": while evaluating variable "INP" with value "file.c file...": Unfinished modifier ('=' missing)
+# expect+1: Unfinished modifier ('=' missing)
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
@@ -189,17 +189,14 @@ EXP= value
INP= value
MOD= ${INP::::}
EXP= # empty
-# expect+2: while evaluating variable "MOD" with value "${INP::::}": while evaluating variable "INP" with value "value": Unknown modifier ":"
-# expect+1: while evaluating variable "MOD" with value "${INP::::}": while evaluating variable "INP" with value "": Unknown modifier ":"
+# expect+2: Unknown modifier ":"
+# expect+1: Unknown modifier ":"
.if ${MOD} != ${EXP}
. warning expected "${EXP}", got "${MOD}"
.endif
# Even in expressions based on an unnamed variable, there may be errors.
-# XXX: The error message should mention the variable name of the expression,
-# even though that name is empty in this case.
-# expect+2: Malformed conditional (${:Z})
-# expect+1: while evaluating "${:Z}" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.if ${:Z}
. error
.else
@@ -212,8 +209,7 @@ EXP= # empty
# variable name with quotes, leading to the rather confusing "Unfinished
# modifier for (',' missing)", having two spaces in a row.
#
-# expect+2: while evaluating "${:S,}" with value "": Unfinished modifier (',' missing)
-# expect+1: Malformed conditional (${:S,})
+# expect+1: Unfinished modifier (',' missing)
.if ${:S,}
. error
.else
diff --git a/unit-tests/varmod-gmtime.exp b/unit-tests/varmod-gmtime.exp
index c41e96723f65..d34cb5c6a93f 100644
--- a/unit-tests/varmod-gmtime.exp
+++ b/unit-tests/varmod-gmtime.exp
@@ -1,13 +1,13 @@
-make: "varmod-gmtime.mk" line 61: while evaluating "${:L:gmtime=-1} != """ with value "": Invalid time value "-1"
-make: "varmod-gmtime.mk" line 61: Malformed conditional (${:L:gmtime=-1} != "")
-make: "varmod-gmtime.mk" line 72: while evaluating "${:L:gmtime= 1} != """ with value "": Invalid time value " 1"
-make: "varmod-gmtime.mk" line 72: Malformed conditional (${:L:gmtime= 1} != "")
-make: "varmod-gmtime.mk" line 120: while evaluating "${:L:gmtime=10000000000000000000000000000000} != """ with value "": Invalid time value "10000000000000000000000000000000"
-make: "varmod-gmtime.mk" line 120: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "")
-make: "varmod-gmtime.mk" line 133: while evaluating "${:L:gmtime=error} != """ with value "": Invalid time value "error"
-make: "varmod-gmtime.mk" line 133: Malformed conditional (${:L:gmtime=error} != "")
-make: "varmod-gmtime.mk" line 144: while evaluating variable "%Y" with value "%Y": Invalid time value "100000S,1970,bad,"
-make: "varmod-gmtime.mk" line 144: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad")
+make: "varmod-gmtime.mk" line 60: Invalid time value "-1"
+ while evaluating "${:L:gmtime=-1} != """ with value ""
+make: "varmod-gmtime.mk" line 70: Invalid time value " 1"
+ while evaluating "${:L:gmtime= 1} != """ with value ""
+make: "varmod-gmtime.mk" line 117: Invalid time value "10000000000000000000000000000000"
+ while evaluating "${:L:gmtime=10000000000000000000000000000000} != """ with value ""
+make: "varmod-gmtime.mk" line 129: Invalid time value "error"
+ while evaluating "${:L:gmtime=error} != """ with value ""
+make: "varmod-gmtime.mk" line 139: Invalid time value "100000S,1970,bad,"
+ while evaluating variable "%Y" with value "%Y"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-gmtime.mk b/unit-tests/varmod-gmtime.mk
index a2b983508be5..610aa2d76fd1 100644
--- a/unit-tests/varmod-gmtime.mk
+++ b/unit-tests/varmod-gmtime.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-gmtime.mk,v 1.24 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-gmtime.mk,v 1.27 2025/01/11 20:54:45 rillig Exp $
#
# Tests for the :gmtime variable modifier, which formats a timestamp
# using strftime(3) in UTC.
@@ -56,8 +56,7 @@
# 1970. Going back 50 years in the past is not a practical use case for
# make. Therefore, since var.c 1.631, negative time stamps produce a
# parse error.
-# expect+2: while evaluating "${:L:gmtime=-1} != """ with value "": Invalid time value "-1"
-# expect+1: Malformed conditional (${:L:gmtime=-1} != "")
+# expect+1: Invalid time value "-1"
.if ${:L:gmtime=-1} != ""
. error
.else
@@ -67,8 +66,7 @@
# Spaces were allowed before var.c 1.631 from 2020-10-31 21:40:20, not
# because it would make sense but just as a side-effect from using strtoul.
-# expect+2: while evaluating "${:L:gmtime= 1} != """ with value "": Invalid time value " 1"
-# expect+1: Malformed conditional (${:L:gmtime= 1} != "")
+# expect+1: Invalid time value " 1"
.if ${:L:gmtime= 1} != ""
. error
.else
@@ -115,8 +113,7 @@
#
# Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a
# parse error.
-# expect+2: while evaluating "${:L:gmtime=10000000000000000000000000000000} != """ with value "": Invalid time value "10000000000000000000000000000000"
-# expect+1: Malformed conditional (${:L:gmtime=10000000000000000000000000000000} != "")
+# expect+1: Invalid time value "10000000000000000000000000000000"
.if ${:L:gmtime=10000000000000000000000000000000} != ""
. error
.else
@@ -128,8 +125,7 @@
# stopped after the '=', and the remaining string was parsed for more variable
# modifiers. Because of the unknown modifier 'e' from the 'error', the whole
# variable value was discarded and thus not printed.
-# expect+2: while evaluating "${:L:gmtime=error} != """ with value "": Invalid time value "error"
-# expect+1: Malformed conditional (${:L:gmtime=error} != "")
+# expect+1: Invalid time value "error"
.if ${:L:gmtime=error} != ""
. error
.else
@@ -139,8 +135,7 @@
# Before var.c 1.1050 from 2023-05-09, the timestamp could be directly
# followed by the next modifier, without a ':' separator. This was the same
# bug as for the ':L' and ':P' modifiers.
-# expect+2: while evaluating variable "%Y" with value "%Y": Invalid time value "100000S,1970,bad,"
-# expect+1: Malformed conditional (${%Y:L:gmtime=100000S,1970,bad,} != "bad")
+# expect+1: Invalid time value "100000S,1970,bad,"
.if ${%Y:L:gmtime=100000S,1970,bad,} != "bad"
. error
.endif
diff --git a/unit-tests/varmod-hash.exp b/unit-tests/varmod-hash.exp
index 55f43dbb56d8..030923cf09d6 100644
--- a/unit-tests/varmod-hash.exp
+++ b/unit-tests/varmod-hash.exp
@@ -1,9 +1,12 @@
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "has"
-
+make: Unknown modifier "has"
+ while evaluating variable "12345" with value "12345"
+ in target "step-1"
26bb0f5f
12345
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "hasX"
-
-make: in target "all": while evaluating variable "12345" with value "12345": Unknown modifier "hashed"
-
+make: Unknown modifier "hasX"
+ while evaluating variable "12345" with value "12345"
+ in target "step-4"
+make: Unknown modifier "hashed"
+ while evaluating variable "12345" with value "12345"
+ in target "step-5"
exit status 2
diff --git a/unit-tests/varmod-hash.mk b/unit-tests/varmod-hash.mk
index 5407e8299f9e..7b34b74226f2 100644
--- a/unit-tests/varmod-hash.mk
+++ b/unit-tests/varmod-hash.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-hash.mk,v 1.5 2020/09/04 06:54:07 rillig Exp $
+# $NetBSD: varmod-hash.mk,v 1.6 2024/07/20 11:05:12 rillig Exp $
#
# Tests for the :hash variable modifier, which computes a 32-bit hash from
# the value of the expression.
@@ -56,9 +56,14 @@ VECTORS+= de41416c abcdefghijklmnopqrstuvwxyz
. endif
.endfor
-all:
+all: step-{1,2,3,4,5}
+step-1:
@echo ${12345:L:has} # modifier name too short
+step-2:
@echo ${12345:L:hash} # ok
+step-3:
@echo ${12345:L:hash=SHA-256} # :hash does not accept '='
+step-4:
@echo ${12345:L:hasX} # misspelled
+step-5:
@echo ${12345:L:hashed} # modifier name too long
diff --git a/unit-tests/varmod-ifelse.exp b/unit-tests/varmod-ifelse.exp
index c93a9ec71716..02f434f1d411 100644
--- a/unit-tests/varmod-ifelse.exp
+++ b/unit-tests/varmod-ifelse.exp
@@ -1,32 +1,37 @@
-make: "varmod-ifelse.mk" line 29: while evaluating condition "bare words == "literal"": Bad condition
-make: "varmod-ifelse.mk" line 29: Malformed conditional (${${:Ubare words} == "literal":?bad:bad})
-make: "varmod-ifelse.mk" line 40: while evaluating condition " == """: Bad condition
-make: "varmod-ifelse.mk" line 49: while evaluating condition " == """: Bad condition
-make: "varmod-ifelse.mk" line 49: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond})
-make: "varmod-ifelse.mk" line 73: while evaluating condition "1 == == 2": Bad condition
-make: "varmod-ifelse.mk" line 73: Malformed conditional (${1 == == 2:?yes:no} != "")
+make: "varmod-ifelse.mk" line 28: Bad condition
+ while evaluating condition "bare words == "literal""
+make: "varmod-ifelse.mk" line 39: Bad condition
+ while evaluating condition " == """
+make: "varmod-ifelse.mk" line 47: Bad condition
+ while evaluating condition " == """
+make: "varmod-ifelse.mk" line 70: Bad condition
+ while evaluating condition "1 == == 2"
CondParser_Eval: "${1 == == 2:?yes:no}" != ""
CondParser_Eval: 1 == == 2
Comparing 1.000000 == 0.000000
-make: "varmod-ifelse.mk" line 97: while evaluating condition "1 == == 2": Bad condition
+make: "varmod-ifelse.mk" line 94: Bad condition
+ while evaluating condition "1 == == 2"
Comparing "" != ""
-make: "varmod-ifelse.mk" line 101: warning: Oops, the parse error should have been propagated.
+make: "varmod-ifelse.mk" line 98: warning: Oops, the parse error should have been propagated.
CondParser_Eval: ${ ${:U\$}{VAR} == value:?ok:bad} != "ok"
CondParser_Eval: ${VAR} == value
Comparing "value" == "value"
Comparing "ok" != "ok"
-make: "varmod-ifelse.mk" line 163: no.
-make: "varmod-ifelse.mk" line 167: while evaluating condition "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
-make: "varmod-ifelse.mk" line 167: while evaluating condition "string == "literal" || no >= 10": Bad condition
-make: "varmod-ifelse.mk" line 167: .
-make: "varmod-ifelse.mk" line 174: while evaluating condition "string == "literal" && >= 10": Bad condition
-make: "varmod-ifelse.mk" line 174: .
-make: "varmod-ifelse.mk" line 177: while evaluating condition "string == "literal" || >= 10": Bad condition
-make: "varmod-ifelse.mk" line 177: .
-make: "varmod-ifelse.mk" line 185: <true>
-make: "varmod-ifelse.mk" line 188: <false>
-make: "varmod-ifelse.mk" line 192: while evaluating condition " ": Bad condition
-make: "varmod-ifelse.mk" line 192: <>
+make: "varmod-ifelse.mk" line 160: no.
+make: "varmod-ifelse.mk" line 163: Comparison with '>=' requires both operands 'no' and '10' to be numeric
+ while evaluating condition "string == "literal" || no >= 10"
+make: "varmod-ifelse.mk" line 163: .
+make: "varmod-ifelse.mk" line 170: Bad condition
+ while evaluating condition "string == "literal" && >= 10"
+make: "varmod-ifelse.mk" line 170: .
+make: "varmod-ifelse.mk" line 173: Bad condition
+ while evaluating condition "string == "literal" || >= 10"
+make: "varmod-ifelse.mk" line 173: .
+make: "varmod-ifelse.mk" line 181: <true>
+make: "varmod-ifelse.mk" line 184: <false>
+make: "varmod-ifelse.mk" line 188: Bad condition
+ while evaluating condition " "
+make: "varmod-ifelse.mk" line 188: <>
CondParser_Eval: 0 && ${1:?${:Uthen0:S,}},,}:${:Uelse0:S,}},,}} != "not evaluated"
CondParser_Eval: 1 && ${0:?${:Uthen1:S,}},,}:${:Uelse1:S,}},,}} != "else1"
CondParser_Eval: 0
@@ -36,18 +41,22 @@ CondParser_Eval: 1
Comparing "then2" != "then2"
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: "varmod-ifelse.mk" line 288: no
+make: "varmod-ifelse.mk" line 284: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: "varmod-ifelse.mk" line 290: yes
+make: "varmod-ifelse.mk" line 286: yes
CondParser_Eval: ${DELAYED} == "one"
Comparing "two" == "one"
-make: "varmod-ifelse.mk" line 293: no
+make: "varmod-ifelse.mk" line 289: no
CondParser_Eval: ${DELAYED} == "two"
Comparing "two" == "two"
-make: "varmod-ifelse.mk" line 296: yes
-make: "varmod-ifelse.mk" line 318: while evaluating then-branch of condition "1": while evaluating "${:X-then}:${:X-else}}" with value "": Unknown modifier "X-then"
-make: "varmod-ifelse.mk" line 318: while evaluating else-branch of condition "1": while parsing "${:X-else}}": Unknown modifier "X-else"
+make: "varmod-ifelse.mk" line 292: yes
+make: "varmod-ifelse.mk" line 314: Unknown modifier "X-then"
+ while evaluating "${:X-then}:${:X-else}}" with value ""
+ while evaluating then-branch of condition "1"
+make: "varmod-ifelse.mk" line 314: Unknown modifier "X-else"
+ while parsing "${:X-else}}"
+ while evaluating else-branch of condition "1"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-ifelse.mk b/unit-tests/varmod-ifelse.mk
index 292bc076366e..b2f5419e65ad 100644
--- a/unit-tests/varmod-ifelse.mk
+++ b/unit-tests/varmod-ifelse.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-ifelse.mk,v 1.32 2024/07/05 20:01:52 rillig Exp $
+# $NetBSD: varmod-ifelse.mk,v 1.35 2025/01/11 20:54:45 rillig Exp $
#
# Tests for the ${cond:?then:else} variable modifier, which evaluates either
# the then-expression or the else-expression, depending on the condition.
@@ -24,8 +24,7 @@
# Evaluating the variable name lazily would require additional code in
# Var_Parse and ParseVarname, it would be more useful and predictable
# though.
-# expect+2: while evaluating condition "bare words == "literal"": Bad condition
-# expect+1: Malformed conditional (${${:Ubare words} == "literal":?bad:bad})
+# expect+1: Bad condition
.if ${${:Ubare words} == "literal":?bad:bad}
. error
.else
@@ -36,7 +35,7 @@
# Because of the early expansion, the whole condition evaluates to
# ' == ""' though, which cannot be parsed because the left-hand side looks
# empty.
-# expect+1: while evaluating condition " == """: Bad condition
+# expect+1: Bad condition
COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
# In a condition, undefined variables generate a "Malformed conditional"
@@ -44,8 +43,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
# "Undefined variable" error message is generated.
# The difference to the ':=' variable assignment is the additional
# "Malformed conditional" error message.
-# expect+2: while evaluating condition " == """: Bad condition
-# expect+1: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond})
+# expect+1: Bad condition
.if ${${UNDEF} == "":?bad-cond:bad-cond}
. error
.else
@@ -68,8 +66,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
# conditional therefore returns a parse error from Var_Parse, and this parse
# error propagates to CondEvalExpression, where the "Malformed conditional"
# comes from.
-# expect+2: while evaluating condition "1 == == 2": Bad condition
-# expect+1: Malformed conditional (${1 == == 2:?yes:no} != "")
+# expect+1: Bad condition
.if ${1 == == 2:?yes:no} != ""
. error
.else
@@ -93,7 +90,7 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign}
# condition should be detected as being malformed before any comparison is
# done since there is no well-formed comparison in the condition at all.
.MAKEFLAGS: -dc
-# expect+1: while evaluating condition "1 == == 2": Bad condition
+# expect+1: Bad condition
.if "${1 == == 2:?yes:no}" != ""
. error
.else
@@ -161,18 +158,17 @@ STRING= string
NUMBER= no # not really a number
# expect+1: no.
.info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}.
-# expect+3: while evaluating condition "string == "literal" || no >= 10": Comparison with '>=' requires both operands 'no' and '10' to be numeric
-# expect+2: while evaluating condition "string == "literal" || no >= 10": Bad condition
+# expect+2: Comparison with '>=' requires both operands 'no' and '10' to be numeric
# expect+1: .
.info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}.
# The following situation occasionally occurs with MKINET6 or similar
# variables.
NUMBER= # empty, not really a number either
-# expect+2: while evaluating condition "string == "literal" && >= 10": Bad condition
+# expect+2: Bad condition
# expect+1: .
.info ${${STRING} == "literal" && ${NUMBER} >= 10:?yes:no}.
-# expect+2: while evaluating condition "string == "literal" || >= 10": Bad condition
+# expect+2: Bad condition
# expect+1: .
.info ${${STRING} == "literal" || ${NUMBER} >= 10:?yes:no}.
@@ -187,7 +183,7 @@ EMPTY= # empty
# expect+1: <false>
.info <${${ASTERISK} :?true:false}>
# syntax error since the condition is completely blank.
-# expect+2: while evaluating condition " ": Bad condition
+# expect+2: Bad condition
# expect+1: <>
.info <${${EMPTY} :?true:false}>
@@ -313,7 +309,7 @@ BOTH= <${YES}> <${NO}>
.endif
-# expect+2: while evaluating then-branch of condition "1": while evaluating "${:X-then}:${:X-else}}" with value "": Unknown modifier "X-then"
-# expect+1: while evaluating else-branch of condition "1": while parsing "${:X-else}}": Unknown modifier "X-else"
+# expect+2: Unknown modifier "X-then"
+# expect+1: Unknown modifier "X-else"
.if ${1:?${:X-then}:${:X-else}}
.endif
diff --git a/unit-tests/varmod-indirect.exp b/unit-tests/varmod-indirect.exp
index 360cec21e291..b572e34fcf8d 100644
--- a/unit-tests/varmod-indirect.exp
+++ b/unit-tests/varmod-indirect.exp
@@ -1,5 +1,7 @@
-make: "varmod-indirect.mk" line 19: while evaluating variable "value" with value "value": Unknown modifier "${"
-make: "varmod-indirect.mk" line 52: while evaluating variable "value" with value "value": Unknown modifier "${"
+make: "varmod-indirect.mk" line 19: Unknown modifier "${"
+ while evaluating variable "value" with value "value"
+make: "varmod-indirect.mk" line 52: Unknown modifier "${"
+ while evaluating variable "value" with value "value"
make: "varmod-indirect.mk" line 54: warning: FIXME: this expression should have resulted in a parse error rather than returning the unparsed portion of the expression.
make: "varmod-indirect.mk" line 143: before
make: "varmod-indirect.mk" line 143: after
@@ -7,14 +9,15 @@ make: "varmod-indirect.mk" line 151: before
make: "varmod-indirect.mk" line 151: after
make: "varmod-indirect.mk" line 159: before
make: "varmod-indirect.mk" line 159: after
-make: "varmod-indirect.mk" line 164: while evaluating variable "UNDEF" with value "": Unknown modifier "Z"
+make: "varmod-indirect.mk" line 164: Unknown modifier "Z"
+ while evaluating variable "UNDEF" with value ""
make: "varmod-indirect.mk" line 167: before
make: "varmod-indirect.mk" line 167: after
-Parsing line 176: _:= before ${UNDEF} after
+Parsing varmod-indirect.mk:176: _:= before ${UNDEF} after
Global: _ = # (empty)
Var_Parse: ${UNDEF} after (eval-keep-dollar-and-undefined)
Global: _ = before ${UNDEF} after
-Parsing line 179: _:= before ${UNDEF:${:US,a,a,}} after
+Parsing varmod-indirect.mk:179: _:= before ${UNDEF:${:US,a,a,}} after
Var_Parse: ${UNDEF:${:US,a,a,}} after (eval-keep-dollar-and-undefined)
Indirect modifier "S,a,a," from "${:US,a,a,}"
Evaluating modifier ${UNDEF:S...} on value "" (eval-keep-dollar-and-undefined, undefined)
@@ -23,18 +26,19 @@ Modifier part: "a"
ModifyWords: split "" into 1 word
Result of ${UNDEF:S,a,a,} is "" (eval-keep-dollar-and-undefined, undefined)
Global: _ = before ${UNDEF:S,a,a,} after
-Parsing line 189: _:= before ${UNDEF:${:U}} after
+Parsing varmod-indirect.mk:189: _:= before ${UNDEF:${:U}} after
Var_Parse: ${UNDEF:${:U}} after (eval-keep-dollar-and-undefined)
Indirect modifier "" from "${:U}"
Global: _ = before ${UNDEF:} after
-Parsing line 195: _:= before ${UNDEF:${:UZ}} after
+Parsing varmod-indirect.mk:195: _:= before ${UNDEF:${:UZ}} after
Var_Parse: ${UNDEF:${:UZ}} after (eval-keep-dollar-and-undefined)
Indirect modifier "Z" from "${:UZ}"
Evaluating modifier ${UNDEF:Z} on value "" (eval-keep-dollar-and-undefined, undefined)
-make: "varmod-indirect.mk" line 195: while evaluating variable "UNDEF" with value "": Unknown modifier "Z"
+make: "varmod-indirect.mk" line 195: Unknown modifier "Z"
+ while evaluating variable "UNDEF" with value ""
Result of ${UNDEF:Z} is error (eval-keep-dollar-and-undefined, undefined)
Global: _ = before ${UNDEF:Z} after
-Parsing line 197: .MAKEFLAGS: -d0
+Parsing varmod-indirect.mk:197: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
Global: .MAKEFLAGS = -r -k -d 0 -d pv -d
Global: .MAKEFLAGS = -r -k -d 0 -d pv -d 0
diff --git a/unit-tests/varmod-indirect.mk b/unit-tests/varmod-indirect.mk
index a58cb870aac8..f54c0e232d2a 100644
--- a/unit-tests/varmod-indirect.mk
+++ b/unit-tests/varmod-indirect.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-indirect.mk,v 1.20 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-indirect.mk,v 1.21 2024/08/29 20:20:36 rillig Exp $
#
# Tests for indirect variable modifiers, such as in ${VAR:${M_modifiers}}.
# These can be used for very basic purposes like converting a string to either
@@ -15,7 +15,7 @@
# The following expression generates a parse error since its indirect
# modifier contains more than a sole expression.
#
-# expect+1: while evaluating variable "value" with value "value": Unknown modifier "${"
+# expect+1: Unknown modifier "${"
.if ${value:L:${:US}${:U,value,replacement,}} != "S,value,replacement,}"
. warning unexpected
.endif
@@ -47,7 +47,7 @@
# error. Because of this parse error, this feature cannot be used reasonably
# in practice.
#
-# expect+2: while evaluating variable "value" with value "value": Unknown modifier "${"
+# expect+2: Unknown modifier "${"
#.MAKEFLAGS: -dvc
.if ${value:L:${:UM*}S,value,replaced,} == "M*S,value,replaced,}"
# expect+1: warning: FIXME: this expression should have resulted in a parse error rather than returning the unparsed portion of the expression.
@@ -160,7 +160,7 @@ M_NoPrimes= ${PRIMES:${M_ListToSkip}}
.endfor
# An error in an indirect modifier.
-# expect+1: while evaluating variable "UNDEF" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
.for var in before ${UNDEF:${:UZ}} after
# expect+2: before
# expect+1: after
@@ -191,7 +191,7 @@ _:= before ${UNDEF:${:U}} after
# XXX: This expands to ${UNDEF:Z}, which will behave differently if the
# variable '_' is used in a context where the expression ${_} is
# parsed but not evaluated.
-# expect+1: while evaluating variable "UNDEF" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
_:= before ${UNDEF:${:UZ}} after
.MAKEFLAGS: -d0
diff --git a/unit-tests/varmod-localtime.exp b/unit-tests/varmod-localtime.exp
index 0183ae6dcc2f..b22bfe479227 100644
--- a/unit-tests/varmod-localtime.exp
+++ b/unit-tests/varmod-localtime.exp
@@ -1,13 +1,13 @@
-make: "varmod-localtime.mk" line 61: while evaluating "${:L:localtime=-1} != """ with value "": Invalid time value "-1"
-make: "varmod-localtime.mk" line 61: Malformed conditional (${:L:localtime=-1} != "")
-make: "varmod-localtime.mk" line 72: while evaluating "${:L:localtime= 1} != """ with value "": Invalid time value " 1"
-make: "varmod-localtime.mk" line 72: Malformed conditional (${:L:localtime= 1} != "")
-make: "varmod-localtime.mk" line 120: while evaluating "${:L:localtime=10000000000000000000000000000000} != """ with value "": Invalid time value "10000000000000000000000000000000"
-make: "varmod-localtime.mk" line 120: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "")
-make: "varmod-localtime.mk" line 133: while evaluating "${:L:localtime=error} != """ with value "": Invalid time value "error"
-make: "varmod-localtime.mk" line 133: Malformed conditional (${:L:localtime=error} != "")
-make: "varmod-localtime.mk" line 144: while evaluating variable "%Y" with value "%Y": Invalid time value "100000S,1970,bad,"
-make: "varmod-localtime.mk" line 144: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad")
+make: "varmod-localtime.mk" line 60: Invalid time value "-1"
+ while evaluating "${:L:localtime=-1} != """ with value ""
+make: "varmod-localtime.mk" line 70: Invalid time value " 1"
+ while evaluating "${:L:localtime= 1} != """ with value ""
+make: "varmod-localtime.mk" line 117: Invalid time value "10000000000000000000000000000000"
+ while evaluating "${:L:localtime=10000000000000000000000000000000} != """ with value ""
+make: "varmod-localtime.mk" line 129: Invalid time value "error"
+ while evaluating "${:L:localtime=error} != """ with value ""
+make: "varmod-localtime.mk" line 139: Invalid time value "100000S,1970,bad,"
+ while evaluating variable "%Y" with value "%Y"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-localtime.mk b/unit-tests/varmod-localtime.mk
index b6295965ddb8..41c99c86df6e 100644
--- a/unit-tests/varmod-localtime.mk
+++ b/unit-tests/varmod-localtime.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-localtime.mk,v 1.17 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-localtime.mk,v 1.20 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the :localtime variable modifier, which formats a timestamp
# using strftime(3) in local time.
@@ -56,8 +56,7 @@
# 1970. Going back 50 years in the past is not a practical use case for
# make. Therefore, since var.c 1.631, negative time stamps produce a
# parse error.
-# expect+2: while evaluating "${:L:localtime=-1} != """ with value "": Invalid time value "-1"
-# expect+1: Malformed conditional (${:L:localtime=-1} != "")
+# expect+1: Invalid time value "-1"
.if ${:L:localtime=-1} != ""
. error
.else
@@ -67,8 +66,7 @@
# Spaces were allowed before var.c 1.631 from 2020-10-31 21:40:20, not
# because it would make sense but just as a side-effect from using strtoul.
-# expect+2: while evaluating "${:L:localtime= 1} != """ with value "": Invalid time value " 1"
-# expect+1: Malformed conditional (${:L:localtime= 1} != "")
+# expect+1: Invalid time value " 1"
.if ${:L:localtime= 1} != ""
. error
.else
@@ -115,8 +113,7 @@
#
# Since var.c 1.631 from 2020-10-31, the overflow is detected and produces a
# parse error.
-# expect+2: while evaluating "${:L:localtime=10000000000000000000000000000000} != """ with value "": Invalid time value "10000000000000000000000000000000"
-# expect+1: Malformed conditional (${:L:localtime=10000000000000000000000000000000} != "")
+# expect+1: Invalid time value "10000000000000000000000000000000"
.if ${:L:localtime=10000000000000000000000000000000} != ""
. error
.else
@@ -128,8 +125,7 @@
# stopped after the '=', and the remaining string was parsed for more variable
# modifiers. Because of the unknown modifier 'e' from the 'error', the whole
# variable value was discarded and thus not printed.
-# expect+2: while evaluating "${:L:localtime=error} != """ with value "": Invalid time value "error"
-# expect+1: Malformed conditional (${:L:localtime=error} != "")
+# expect+1: Invalid time value "error"
.if ${:L:localtime=error} != ""
. error
.else
@@ -139,8 +135,7 @@
# Before var.c 1.1050 from 2023-05-09, the timestamp could be directly
# followed by the next modifier, without a ':' separator. This was the same
# bug as for the ':L' and ':P' modifiers.
-# expect+2: while evaluating variable "%Y" with value "%Y": Invalid time value "100000S,1970,bad,"
-# expect+1: Malformed conditional (${%Y:L:localtime=100000S,1970,bad,} != "bad")
+# expect+1: Invalid time value "100000S,1970,bad,"
.if ${%Y:L:localtime=100000S,1970,bad,} != "bad"
. error
.endif
diff --git a/unit-tests/varmod-loop-delete.exp b/unit-tests/varmod-loop-delete.exp
index eb3124a9adfd..874dce4495c1 100644
--- a/unit-tests/varmod-loop-delete.exp
+++ b/unit-tests/varmod-loop-delete.exp
@@ -1,4 +1,6 @@
-make: "varmod-loop-delete.mk" line 20: while evaluating variable "VAR" with value "${:U:@VAR@@} rest of the value": while evaluating "${:U:@VAR@@} rest of the value" with value "": Cannot delete variable "VAR" while it is used
+make: "varmod-loop-delete.mk" line 20: Cannot delete variable "VAR" while it is used
+ while evaluating "${:U:@VAR@@} rest of the value" with value ""
+ while evaluating variable "VAR" with value "${:U:@VAR@@} rest of the value"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-loop-delete.mk b/unit-tests/varmod-loop-delete.mk
index 5a4b273afcaf..478a25e91f6e 100644
--- a/unit-tests/varmod-loop-delete.mk
+++ b/unit-tests/varmod-loop-delete.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-loop-delete.mk,v 1.6 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-loop-delete.mk,v 1.7 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the variable modifier ':@', which as a side effect allows to
# delete an arbitrary variable.
@@ -16,7 +16,7 @@ VAR= ${:U:@VAR@@} rest of the value
# In an assignment, the scope is 'Global'. Since the variable 'VAR' is
# defined in the global scope, it deletes itself.
-# expect+1: while evaluating variable "VAR" with value "${:U:@VAR@@} rest of the value": while evaluating "${:U:@VAR@@} rest of the value" with value "": Cannot delete variable "VAR" while it is used
+# expect+1: Cannot delete variable "VAR" while it is used
EVAL:= ${VAR}
.if ${EVAL} != " rest of the value"
. error
diff --git a/unit-tests/varmod-loop-varname.exp b/unit-tests/varmod-loop-varname.exp
index 8ad1842c4d09..442f9bb6d684 100644
--- a/unit-tests/varmod-loop-varname.exp
+++ b/unit-tests/varmod-loop-varname.exp
@@ -1,11 +1,11 @@
-make: "varmod-loop-varname.mk" line 18: while evaluating "${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+"" with value "one two three": In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
-make: "varmod-loop-varname.mk" line 18: Malformed conditional (${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+")
-make: "varmod-loop-varname.mk" line 89: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$" must not contain a dollar
-make: "varmod-loop-varname.mk" line 89: Malformed conditional (${1 2 3:L:@v$@($v)@} != "(1) (2) (3)")
-make: "varmod-loop-varname.mk" line 96: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$$" must not contain a dollar
-make: "varmod-loop-varname.mk" line 96: Malformed conditional (${1 2 3:L:@v$$@($v)@} != "() () ()")
-make: "varmod-loop-varname.mk" line 103: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$$$" must not contain a dollar
-make: "varmod-loop-varname.mk" line 103: Malformed conditional (${1 2 3:L:@v$$$@($v)@} != "() () ()")
+make: "varmod-loop-varname.mk" line 17: In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
+ while evaluating "${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+"" with value "one two three"
+make: "varmod-loop-varname.mk" line 87: In the :@ modifier, the variable name "v$" must not contain a dollar
+ while evaluating variable "1 2 3" with value "1 2 3"
+make: "varmod-loop-varname.mk" line 93: In the :@ modifier, the variable name "v$$" must not contain a dollar
+ while evaluating variable "1 2 3" with value "1 2 3"
+make: "varmod-loop-varname.mk" line 99: In the :@ modifier, the variable name "v$$$" must not contain a dollar
+ while evaluating variable "1 2 3" with value "1 2 3"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-loop-varname.mk b/unit-tests/varmod-loop-varname.mk
index a41d1d30d019..703e81941c59 100644
--- a/unit-tests/varmod-loop-varname.mk
+++ b/unit-tests/varmod-loop-varname.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-loop-varname.mk,v 1.9 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-loop-varname.mk,v 1.12 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the first part of the variable modifier ':@var@...@', which
# contains the variable name to use during the loop.
@@ -13,8 +13,7 @@
# dynamically. There was no practical use-case for this.
# Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the
# variable name.
-# expect+2: while evaluating "${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+"" with value "one two three": In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
-# expect+1: Malformed conditional (${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+")
+# expect+1: In the :@ modifier, the variable name "${:Ubar:S,b,v,}" must not contain a dollar
.if ${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@} != "+one+ +two+ +three+"
. error
.else
@@ -84,22 +83,19 @@ RES3= 3
# There's no point in allowing a dollar sign in that position.
# Since var.c 1.907 from 2021-04-04, a '$' is no longer allowed in the
# variable name.
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$" must not contain a dollar
-# expect+1: Malformed conditional (${1 2 3:L:@v$@($v)@} != "(1) (2) (3)")
+# expect+1: In the :@ modifier, the variable name "v$" must not contain a dollar
.if ${1 2 3:L:@v$@($v)@} != "(1) (2) (3)"
. error
.else
. error
.endif
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$$" must not contain a dollar
-# expect+1: Malformed conditional (${1 2 3:L:@v$$@($v)@} != "() () ()")
+# expect+1: In the :@ modifier, the variable name "v$$" must not contain a dollar
.if ${1 2 3:L:@v$$@($v)@} != "() () ()"
. error
.else
. error
.endif
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": In the :@ modifier, the variable name "v$$$" must not contain a dollar
-# expect+1: Malformed conditional (${1 2 3:L:@v$$$@($v)@} != "() () ()")
+# expect+1: In the :@ modifier, the variable name "v$$$" must not contain a dollar
.if ${1 2 3:L:@v$$$@($v)@} != "() () ()"
. error
.else
diff --git a/unit-tests/varmod-loop.exp b/unit-tests/varmod-loop.exp
index ccfcd0b2dc06..510b151957f8 100644
--- a/unit-tests/varmod-loop.exp
+++ b/unit-tests/varmod-loop.exp
@@ -1,12 +1,12 @@
-Parsing line 89: USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$
-Parsing line 90: .if ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$"
+Parsing varmod-loop.mk:89: USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$
+Parsing varmod-loop.mk:90: .if ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$"
CondParser_Eval: ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$"
Comparing "$$$$ $$$$ $$$$" != "$$$$ $$$$ $$$$"
-Parsing line 94: SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}
-Parsing line 116: .if ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$"
+Parsing varmod-loop.mk:94: SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}
+Parsing varmod-loop.mk:116: .if ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$"
CondParser_Eval: ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$"
Comparing "$$ $$$$ $$$$" != "$$ $$$$ $$$$"
-Parsing line 119: .MAKEFLAGS: -d0
+Parsing varmod-loop.mk:119: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
:varname-overwriting-target: :x1y x2y x3y: ::
mod-loop-dollar:1:
diff --git a/unit-tests/varmod-match-escape.exp b/unit-tests/varmod-match-escape.exp
index e15445de356b..a972b14816bd 100755
--- a/unit-tests/varmod-match-escape.exp
+++ b/unit-tests/varmod-match-escape.exp
@@ -1,11 +1,11 @@
Global: SPECIALS = \: : \\ * \*
CondParser_Eval: ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}}
-Var_Parse: ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} (eval-defined)
+Var_Parse: ${SPECIALS:M${:U}\:} != ${SPECIALS:M\:${:U}} (eval-defined-loud)
Evaluating modifier ${SPECIALS:M...} on value "\: : \\ * \*"
Pattern for ':M' is "\:"
ModifyWords: split "\: : \\ * \*" into 5 words
Result of ${SPECIALS:M${:U}\:} is ":"
-Var_Parse: ${SPECIALS:M\:${:U}} (eval-defined)
+Var_Parse: ${SPECIALS:M\:${:U}} (eval-defined-loud)
Evaluating modifier ${SPECIALS:M...} on value "\: : \\ * \*"
Pattern for ':M' is ":"
ModifyWords: split "\: : \\ * \*" into 5 words
@@ -13,19 +13,19 @@ Result of ${SPECIALS:M\:${:U}} is ":"
Comparing ":" != ":"
Global: VALUES = : :: :\:
CondParser_Eval: ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:}
-Var_Parse: ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} (eval-defined)
+Var_Parse: ${VALUES:M\:${:U\:}} != ${VALUES:M${:U\:}\:} (eval-defined-loud)
Evaluating modifier ${VALUES:M...} on value ": :: :\:"
-Var_Parse: ${:U:} (eval-defined)
-Evaluating modifier ${:U} on value "" (eval-defined, undefined)
-Result of ${:U} is "" (eval-defined, defined)
+Var_Parse: ${:U:} (eval)
+Evaluating modifier ${:U} on value "" (eval, undefined)
+Result of ${:U} is "" (eval, defined)
Pattern for ':M' is ":"
ModifyWords: split ": :: :\:" into 3 words
Result of ${VALUES:M\:${:U\:}} is ":"
-Var_Parse: ${VALUES:M${:U\:}\:} (eval-defined)
+Var_Parse: ${VALUES:M${:U\:}\:} (eval-defined-loud)
Evaluating modifier ${VALUES:M...} on value ": :: :\:"
-Var_Parse: ${:U\:}\: (eval-defined)
-Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
-Result of ${:U\:} is ":" (eval-defined, defined)
+Var_Parse: ${:U\:}\: (eval)
+Evaluating modifier ${:U...} on value "" (eval, undefined)
+Result of ${:U\:} is ":" (eval, defined)
Pattern for ':M' is ":\:"
ModifyWords: split ": :: :\:" into 3 words
Result of ${VALUES:M${:U\:}\:} is "::"
@@ -33,10 +33,13 @@ Comparing ":" != "::"
make: "varmod-match-escape.mk" line 43: warning: XXX: Oops
Global: .MAKEFLAGS = -r -k -d cv -d
Global: .MAKEFLAGS = -r -k -d cv -d 0
-make: "varmod-match-escape.mk" line 69: while evaluating "${:U\$:M\$} != """ with value "$": Dollar followed by nothing
-make: "varmod-match-escape.mk" line 110: while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]": Unfinished character list in pattern '[A-]' of modifier ':M'
+make: "varmod-match-escape.mk" line 69: Dollar followed by nothing
+ while evaluating "${:U\$:M\$} != """ with value "$"
+make: "varmod-match-escape.mk" line 110: Unfinished character list in pattern '[A-]' of modifier ':M'
+ while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]"
in .for loop from varmod-match-escape.mk:107 with pattern = [A-]
-make: "varmod-match-escape.mk" line 110: while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]": Unfinished character list in pattern '[^A-]' of modifier ':M'
+make: "varmod-match-escape.mk" line 110: Unfinished character list in pattern '[^A-]' of modifier ':M'
+ while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]"
in .for loop from varmod-match-escape.mk:107 with pattern = [^A-]
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
diff --git a/unit-tests/varmod-match-escape.mk b/unit-tests/varmod-match-escape.mk
index eb5730d3e5a1..d9e2009f9b60 100755
--- a/unit-tests/varmod-match-escape.mk
+++ b/unit-tests/varmod-match-escape.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match-escape.mk,v 1.17 2024/07/09 17:07:23 rillig Exp $
+# $NetBSD: varmod-match-escape.mk,v 1.18 2024/08/29 20:20:36 rillig Exp $
#
# As of 2020-08-01, the :M and :N modifiers interpret backslashes differently,
# depending on whether there was an expression somewhere before the
@@ -65,7 +65,7 @@ VALUES= : :: :\:
# In lint mode, the case of a lonely '$' is covered with an error message.
.MAKEFLAGS: -dL
-# expect+1: while evaluating "${:U\$:M\$} != """ with value "$": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${:U\$:M\$} != ""
. error
.endif
@@ -105,8 +105,8 @@ EXP.[^A-]]= a
EXP.[^A-]]]= a]
.for pattern in [A-] [A-]] [A-]]] [^A-] [^A-]] [^A-]]]
-# expect+2: while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]": Unfinished character list in pattern '[A-]' of modifier ':M'
-# expect+1: while evaluating variable "WORDS" with value "A A] A]] B B] B]] ] ]] ]]] a a] a]]": Unfinished character list in pattern '[^A-]' of modifier ':M'
+# expect+2: Unfinished character list in pattern '[A-]' of modifier ':M'
+# expect+1: Unfinished character list in pattern '[^A-]' of modifier ':M'
. if ${WORDS:M${pattern}} != ${EXP.${pattern}}
. warning ${pattern}: ${WORDS:M${pattern}} != ${EXP.${pattern}}
. endif
diff --git a/unit-tests/varmod-match.exp b/unit-tests/varmod-match.exp
index 377a43082fed..fdc76c3ae83a 100644
--- a/unit-tests/varmod-match.exp
+++ b/unit-tests/varmod-match.exp
@@ -1,14 +1,23 @@
-make: "varmod-match.mk" line 289: while evaluating variable "WORDS" with value "a a[": Unfinished character list in pattern 'a[' of modifier ':M'
-make: "varmod-match.mk" line 297: while evaluating variable "WORDS" with value "a a[ aX": Unfinished character list in pattern 'a[^' of modifier ':M'
-make: "varmod-match.mk" line 305: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3": Unfinished character list in pattern '[-x1-3' of modifier ':M'
-make: "varmod-match.mk" line 313: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3": Unfinished character list in pattern '*[-x1-3' of modifier ':M'
-make: "varmod-match.mk" line 322: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3": Unfinished character list in pattern '[^-x1-3' of modifier ':M'
-make: "varmod-match.mk" line 336: while evaluating variable "WORDS" with value "\\ \a x\": Unfinished character list in pattern '?[\' of modifier ':M'
-make: "varmod-match.mk" line 344: while evaluating variable "WORDS" with value "[x- x x- y": Unfinished character range in pattern '[x-' of modifier ':M'
-make: "varmod-match.mk" line 356: while evaluating variable "WORDS" with value "[x- x x- y yyyyy": Unfinished character range in pattern '[^x-' of modifier ':M'
-make: "varmod-match.mk" line 364: while evaluating variable " : :: " with value " : :: ": Unfinished character list in pattern '[' of modifier ':M'
-make: "varmod-match.mk" line 364: while evaluating variable " : :: " with value "": Unknown modifier "]"
-make: "varmod-match.mk" line 364: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
+make: "varmod-match.mk" line 289: Unfinished character list in pattern 'a[' of modifier ':M'
+ while evaluating variable "WORDS" with value "a a["
+make: "varmod-match.mk" line 297: Unfinished character list in pattern 'a[^' of modifier ':M'
+ while evaluating variable "WORDS" with value "a a[ aX"
+make: "varmod-match.mk" line 305: Unfinished character list in pattern '[-x1-3' of modifier ':M'
+ while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3"
+make: "varmod-match.mk" line 313: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
+ while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3"
+make: "varmod-match.mk" line 322: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
+ while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3"
+make: "varmod-match.mk" line 336: Unfinished character list in pattern '?[\' of modifier ':M'
+ while evaluating variable "WORDS" with value "\\ \a x\"
+make: "varmod-match.mk" line 344: Unfinished character range in pattern '[x-' of modifier ':M'
+ while evaluating variable "WORDS" with value "[x- x x- y"
+make: "varmod-match.mk" line 356: Unfinished character range in pattern '[^x-' of modifier ':M'
+ while evaluating variable "WORDS" with value "[x- x x- y yyyyy"
+make: "varmod-match.mk" line 363: Unfinished character list in pattern '[' of modifier ':M'
+ while evaluating variable " : :: " with value " : :: "
+make: "varmod-match.mk" line 363: Unknown modifier "]"
+ while evaluating variable " : :: " with value ""
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-match.mk b/unit-tests/varmod-match.mk
index ce2bbab7eb53..3e9ada78231e 100644
--- a/unit-tests/varmod-match.mk
+++ b/unit-tests/varmod-match.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-match.mk,v 1.26 2024/07/09 17:07:23 rillig Exp $
+# $NetBSD: varmod-match.mk,v 1.29 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the ':M' modifier, which keeps only those words that match the
# given pattern.
@@ -285,7 +285,7 @@ ${:U*}= asterisk
# [ Incomplete empty character list, never matches.
WORDS= a a[
-# expect+1: while evaluating variable "WORDS" with value "a a[": Unfinished character list in pattern 'a[' of modifier ':M'
+# expect+1: Unfinished character list in pattern 'a[' of modifier ':M'
.if ${WORDS:Ma[} != ""
. error
.endif
@@ -293,7 +293,7 @@ WORDS= a a[
# [^ Incomplete negated empty character list, matches any single
# character.
WORDS= a a[ aX
-# expect+1: while evaluating variable "WORDS" with value "a a[ aX": Unfinished character list in pattern 'a[^' of modifier ':M'
+# expect+1: Unfinished character list in pattern 'a[^' of modifier ':M'
.if ${WORDS:Ma[^} != "a[ aX"
. error
.endif
@@ -301,7 +301,7 @@ WORDS= a a[ aX
# [-x1-3 Incomplete character list, matches those elements that can be
# parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
-# expect+1: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3": Unfinished character list in pattern '[-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern '[-x1-3' of modifier ':M'
.if ${WORDS:M[-x1-3} != "- x 1 2 3"
. error
.endif
@@ -309,7 +309,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3
# *[-x1-3 Incomplete character list after a wildcard, matches those
# words that end with one of the characters from the list.
WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3
-# expect+1: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3": Unfinished character list in pattern '*[-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern '*[-x1-3' of modifier ':M'
.if ${WORDS:M*[-x1-3} != "- x xx 1 2 3 01 11 001 011 101 111 [x1-3"
. warning ${WORDS:M*[-x1-3}
.endif
@@ -318,7 +318,7 @@ WORDS= - + x xx 0 1 2 3 4 00 01 10 11 000 001 010 011 100 101 110 111 [x1-3
# Incomplete negated character list, matches any character
# except those elements that can be parsed without lookahead.
WORDS= - + x xx 0 1 2 3 4 [x1-3
-# expect+1: while evaluating variable "WORDS" with value "- + x xx 0 1 2 3 4 [x1-3": Unfinished character list in pattern '[^-x1-3' of modifier ':M'
+# expect+1: Unfinished character list in pattern '[^-x1-3' of modifier ':M'
.if ${WORDS:M[^-x1-3} != "+ 0 4"
. error
.endif
@@ -332,7 +332,7 @@ WORDS= - + x xx 0 1 2 3 4 [x1-3
# '\', as there is no following space that could be escaped.
WORDS= \\ \a ${:Ux\\}
PATTERN= ${:U?[\\}
-# expect+1: while evaluating variable "WORDS" with value "\\ \a x\": Unfinished character list in pattern '?[\' of modifier ':M'
+# expect+1: Unfinished character list in pattern '?[\' of modifier ':M'
.if ${WORDS:M${PATTERN}} != "\\\\ x\\"
. error
.endif
@@ -340,7 +340,7 @@ PATTERN= ${:U?[\\}
# [x- Incomplete character list containing an incomplete character
# range, matches only the 'x'.
WORDS= [x- x x- y
-# expect+1: while evaluating variable "WORDS" with value "[x- x x- y": Unfinished character range in pattern '[x-' of modifier ':M'
+# expect+1: Unfinished character range in pattern '[x-' of modifier ':M'
.if ${WORDS:M[x-} != "x"
. error
.endif
@@ -352,15 +352,14 @@ WORDS= [x- x x- y
# XXX: Even matches strings that are longer than a single
# character.
WORDS= [x- x x- y yyyyy
-# expect+1: while evaluating variable "WORDS" with value "[x- x x- y yyyyy": Unfinished character range in pattern '[^x-' of modifier ':M'
+# expect+1: Unfinished character range in pattern '[^x-' of modifier ':M'
.if ${WORDS:M[^x-} != "[x- y yyyyy"
. error
.endif
# [:] matches never since the ':' starts the next modifier
-# expect+3: while evaluating variable " : :: " with value " : :: ": Unfinished character list in pattern '[' of modifier ':M'
-# expect+2: while evaluating variable " : :: " with value "": Unknown modifier "]"
-# expect+1: Malformed conditional (${ ${:U\:} ${:U\:\:} :L:M[:]} != ":")
+# expect+2: Unfinished character list in pattern '[' of modifier ':M'
+# expect+1: Unknown modifier "]"
.if ${ ${:U\:} ${:U\:\:} :L:M[:]} != ":"
. error
.else
diff --git a/unit-tests/varmod-mtime.exp b/unit-tests/varmod-mtime.exp
index 153b7ff79f08..160bfcdd6cf8 100644
--- a/unit-tests/varmod-mtime.exp
+++ b/unit-tests/varmod-mtime.exp
@@ -1,14 +1,15 @@
-make: "varmod-mtime.mk" line 47: while evaluating variable "no/such/file" with value "no/such/file": Invalid argument '123x' for modifier ':mtime'
-make: "varmod-mtime.mk" line 47: Malformed conditional (${no/such/file:L:mtime=123x})
-make: "varmod-mtime.mk" line 70: while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2": Cannot determine mtime for 'no/such/file1': <ENOENT>
-make: "varmod-mtime.mk" line 70: while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2": Cannot determine mtime for 'no/such/file2': <ENOENT>
-make: "varmod-mtime.mk" line 70: Malformed conditional (${no/such/file1 no/such/file2:L:mtime=error})
-make: "varmod-mtime.mk" line 81: while evaluating variable "MAKEFILE" with value "varmod-mtime.mk": Invalid argument 'errorhandler-no' for modifier ':mtime'
-make: "varmod-mtime.mk" line 81: Malformed conditional (${MAKEFILE:mtime=errorhandler-no} > 0)
-make: "varmod-mtime.mk" line 90: while evaluating variable "MAKEFILE" with value "varmod-mtime.mk": Invalid argument 'warn' for modifier ':mtime'
-make: "varmod-mtime.mk" line 90: Malformed conditional (${MAKEFILE:mtime=warn} > 0)
-make: "varmod-mtime.mk" line 115: while evaluating variable "anything" with value "anything": Unknown modifier "mtim"
-make: "varmod-mtime.mk" line 115: Malformed conditional (${anything:L:mtim})
+make: "varmod-mtime.mk" line 46: Invalid argument '123x' for modifier ':mtime'
+ while evaluating variable "no/such/file" with value "no/such/file"
+make: "varmod-mtime.mk" line 68: Cannot determine mtime for 'no/such/file1': <ENOENT>
+ while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2"
+make: "varmod-mtime.mk" line 68: Cannot determine mtime for 'no/such/file2': <ENOENT>
+ while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2"
+make: "varmod-mtime.mk" line 78: Invalid argument 'errorhandler-no' for modifier ':mtime'
+ while evaluating variable "MAKEFILE" with value "varmod-mtime.mk"
+make: "varmod-mtime.mk" line 86: Invalid argument 'warn' for modifier ':mtime'
+ while evaluating variable "MAKEFILE" with value "varmod-mtime.mk"
+make: "varmod-mtime.mk" line 110: Unknown modifier "mtim"
+ while evaluating variable "anything" with value "anything"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-mtime.mk b/unit-tests/varmod-mtime.mk
index be627fcfe040..0d0ddfc26b52 100644
--- a/unit-tests/varmod-mtime.mk
+++ b/unit-tests/varmod-mtime.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-mtime.mk,v 1.11 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-mtime.mk,v 1.14 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the ':mtime' variable modifier, which maps each word of the
# expression to that file's modification time.
@@ -42,8 +42,7 @@ not_found_mtime:= ${no/such/file:L:mtime}
# The fallback timestamp must only be an integer, without trailing characters.
-# expect+2: while evaluating variable "no/such/file" with value "no/such/file": Invalid argument '123x' for modifier ':mtime'
-# expect+1: Malformed conditional (${no/such/file:L:mtime=123x})
+# expect+1: Invalid argument '123x' for modifier ':mtime'
.if ${no/such/file:L:mtime=123x}
. error
.else
@@ -64,9 +63,8 @@ _!= rm -f ${COOKIE}
# If the optional argument of the ':mtime' modifier is the word 'error', the
# modifier fails with an error message, once for each affected file.
#
-# expect+3: while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2": Cannot determine mtime for 'no/such/file1': <ENOENT>
-# expect+2: while evaluating variable "no/such/file1 no/such/file2" with value "no/such/file1 no/such/file2": Cannot determine mtime for 'no/such/file2': <ENOENT>
-# expect+1: Malformed conditional (${no/such/file1 no/such/file2:L:mtime=error})
+# expect+2: Cannot determine mtime for 'no/such/file1': <ENOENT>
+# expect+1: Cannot determine mtime for 'no/such/file2': <ENOENT>
.if ${no/such/file1 no/such/file2:L:mtime=error}
. error
.else
@@ -76,8 +74,7 @@ _!= rm -f ${COOKIE}
# Only the word 'error' is a special argument to the ':mtime' modifier, all
# other words result in a parse error.
-# expect+2: while evaluating variable "MAKEFILE" with value "varmod-mtime.mk": Invalid argument 'errorhandler-no' for modifier ':mtime'
-# expect+1: Malformed conditional (${MAKEFILE:mtime=errorhandler-no} > 0)
+# expect+1: Invalid argument 'errorhandler-no' for modifier ':mtime'
.if ${MAKEFILE:mtime=errorhandler-no} > 0
.else
. error
@@ -85,8 +82,7 @@ _!= rm -f ${COOKIE}
# Only the word 'error' can be used as a fallback argument to the modifier.
-# expect+2: while evaluating variable "MAKEFILE" with value "varmod-mtime.mk": Invalid argument 'warn' for modifier ':mtime'
-# expect+1: Malformed conditional (${MAKEFILE:mtime=warn} > 0)
+# expect+1: Invalid argument 'warn' for modifier ':mtime'
.if ${MAKEFILE:mtime=warn} > 0
. error
.else
@@ -110,8 +106,7 @@ end:= ${%s:L:gmtime}
# If there is a typo in the modifier name, it does not match.
-# expect+2: while evaluating variable "anything" with value "anything": Unknown modifier "mtim"
-# expect+1: Malformed conditional (${anything:L:mtim})
+# expect+1: Unknown modifier "mtim"
.if ${anything:L:mtim}
. error
.else
diff --git a/unit-tests/varmod-order.exp b/unit-tests/varmod-order.exp
index 591e1f160f61..2b955c123412 100644
--- a/unit-tests/varmod-order.exp
+++ b/unit-tests/varmod-order.exp
@@ -1,26 +1,29 @@
-make: "varmod-order.mk" line 17: while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten": Bad modifier ":OX"
-make: "varmod-order.mk" line 17: Undefined variable "${WORDS:OX"
-make: "varmod-order.mk" line 23: while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten": Bad modifier ":OxXX"
-make: "varmod-order.mk" line 23: Undefined variable "${WORDS:Ox"
-make: "varmod-order.mk" line 27: while evaluating variable "WORDS" with value "eight five four nine one seven six ten three two": Unclosed expression, expecting '}' for modifier "O"
-make: "varmod-order.mk" line 29: while evaluating variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10": Unclosed expression, expecting '}' for modifier "On"
-make: "varmod-order.mk" line 31: while evaluating variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1": Unclosed expression, expecting '}' for modifier "Onr"
-make: "varmod-order.mk" line 38: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Oxn"
-make: "varmod-order.mk" line 38: Malformed conditional (${NUMBERS:Oxn})
-make: "varmod-order.mk" line 48: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":On_typo"
-make: "varmod-order.mk" line 48: Malformed conditional (${NUMBERS:On_typo})
-make: "varmod-order.mk" line 58: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onr_typo"
-make: "varmod-order.mk" line 58: Malformed conditional (${NUMBERS:Onr_typo})
-make: "varmod-order.mk" line 68: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Orn_typo"
-make: "varmod-order.mk" line 68: Malformed conditional (${NUMBERS:Orn_typo})
-make: "varmod-order.mk" line 80: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onn"
-make: "varmod-order.mk" line 80: Malformed conditional (${NUMBERS:Onn})
-make: "varmod-order.mk" line 90: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onrr"
-make: "varmod-order.mk" line 90: Malformed conditional (${NUMBERS:Onrr})
-make: "varmod-order.mk" line 100: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Orrn"
-make: "varmod-order.mk" line 100: Malformed conditional (${NUMBERS:Orrn})
-make: "varmod-order.mk" line 115: while evaluating variable "SWITCH" with value "On": Bad modifier ":On=Off"
-make: "varmod-order.mk" line 115: Malformed conditional (${SWITCH:On=Off} != "Off")
+make: "varmod-order.mk" line 14: Bad modifier ":OX"
+ while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten"
+make: "varmod-order.mk" line 17: Bad modifier ":OxXX"
+ while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten"
+make: "varmod-order.mk" line 20: Unclosed expression, expecting '}' for modifier "O"
+ while evaluating variable "WORDS" with value "eight five four nine one seven six ten three two"
+make: "varmod-order.mk" line 22: Unclosed expression, expecting '}' for modifier "On"
+ while evaluating variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10"
+make: "varmod-order.mk" line 24: Unclosed expression, expecting '}' for modifier "Onr"
+ while evaluating variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1"
+make: "varmod-order.mk" line 30: Bad modifier ":Oxn"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 39: Bad modifier ":On_typo"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 48: Bad modifier ":Onr_typo"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 57: Bad modifier ":Orn_typo"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 68: Bad modifier ":Onn"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 77: Bad modifier ":Onrr"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 86: Bad modifier ":Orrn"
+ while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2"
+make: "varmod-order.mk" line 100: Bad modifier ":On=Off"
+ while evaluating variable "SWITCH" with value "On"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-order.mk b/unit-tests/varmod-order.mk
index b8a631857e6f..0389b3f023af 100644
--- a/unit-tests/varmod-order.mk
+++ b/unit-tests/varmod-order.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-order.mk,v 1.14 2024/07/05 18:59:33 rillig Exp $
+# $NetBSD: varmod-order.mk,v 1.18 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the :O variable modifier and its variants, which either sort the
# words of the value or shuffle them.
@@ -10,31 +10,23 @@ NUMBERS= 8 5 4 9 1 7 6 10 3 2 # in English alphabetical order
. error ${WORDS:O}
.endif
-# Unknown modifier "OX"
-# FIXME: The error message "Undefined variable" is wrong.
-# expect+2: Undefined variable "${WORDS:OX"
-# expect+1: while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten": Bad modifier ":OX"
+# expect+1: Bad modifier ":OX"
_:= ${WORDS:OX}
-# Unknown modifier "OxXX"
-# FIXME: The error message "Undefined variable" is wrong.
-# expect+2: Undefined variable "${WORDS:Ox"
-# expect+1: while evaluating variable "WORDS" with value "one two three four five six seven eight nine ten": Bad modifier ":OxXX"
+# expect+1: Bad modifier ":OxXX"
_:= ${WORDS:OxXX}
-# Missing closing brace, to cover the error handling code.
-# expect+1: while evaluating variable "WORDS" with value "eight five four nine one seven six ten three two": Unclosed expression, expecting '}' for modifier "O"
+# expect+1: Unclosed expression, expecting '}' for modifier "O"
_:= ${WORDS:O
-# expect+1: while evaluating variable "NUMBERS" with value "1 2 3 4 5 6 7 8 9 10": Unclosed expression, expecting '}' for modifier "On"
+# expect+1: Unclosed expression, expecting '}' for modifier "On"
_:= ${NUMBERS:On
-# expect+1: while evaluating variable "NUMBERS" with value "10 9 8 7 6 5 4 3 2 1": Unclosed expression, expecting '}' for modifier "Onr"
+# expect+1: Unclosed expression, expecting '}' for modifier "Onr"
_:= ${NUMBERS:Onr
# Shuffling numerically doesn't make sense, so don't allow 'x' and 'n' to be
# combined.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Oxn"
-# expect+1: Malformed conditional (${NUMBERS:Oxn})
+# expect+1: Bad modifier ":Oxn"
.if ${NUMBERS:Oxn}
. error
.else
@@ -43,8 +35,7 @@ _:= ${NUMBERS:Onr
# Extra characters after ':On' are detected and diagnosed.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":On_typo"
-# expect+1: Malformed conditional (${NUMBERS:On_typo})
+# expect+1: Bad modifier ":On_typo"
.if ${NUMBERS:On_typo}
. error
.else
@@ -53,8 +44,7 @@ _:= ${NUMBERS:Onr
# Extra characters after ':Onr' are detected and diagnosed.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onr_typo"
-# expect+1: Malformed conditional (${NUMBERS:Onr_typo})
+# expect+1: Bad modifier ":Onr_typo"
.if ${NUMBERS:Onr_typo}
. error
.else
@@ -63,8 +53,7 @@ _:= ${NUMBERS:Onr
# Extra characters after ':Orn' are detected and diagnosed.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Orn_typo"
-# expect+1: Malformed conditional (${NUMBERS:Orn_typo})
+# expect+1: Bad modifier ":Orn_typo"
.if ${NUMBERS:Orn_typo}
. error
.else
@@ -75,8 +64,7 @@ _:= ${NUMBERS:Onr
# criteria are fixed, not computed, therefore allowing this redundancy does
# not make sense.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onn"
-# expect+1: Malformed conditional (${NUMBERS:Onn})
+# expect+1: Bad modifier ":Onn"
.if ${NUMBERS:Onn}
. error
.else
@@ -85,8 +73,7 @@ _:= ${NUMBERS:Onr
# Repeating the 'r' is not supported as well, for the same reasons as above.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Onrr"
-# expect+1: Malformed conditional (${NUMBERS:Onrr})
+# expect+1: Bad modifier ":Onrr"
.if ${NUMBERS:Onrr}
. error
.else
@@ -95,8 +82,7 @@ _:= ${NUMBERS:Onr
# Repeating the 'r' is not supported as well, for the same reasons as above.
#
-# expect+2: while evaluating variable "NUMBERS" with value "8 5 4 9 1 7 6 10 3 2": Bad modifier ":Orrn"
-# expect+1: Malformed conditional (${NUMBERS:Orrn})
+# expect+1: Bad modifier ":Orrn"
.if ${NUMBERS:Orrn}
. error
.else
@@ -110,8 +96,7 @@ _:= ${NUMBERS:Onr
# ':H' modifier but instead replaces a trailing 'H' with 'new' in each word.
# There is no such fallback for the ':O' modifiers.
SWITCH= On
-# expect+2: while evaluating variable "SWITCH" with value "On": Bad modifier ":On=Off"
-# expect+1: Malformed conditional (${SWITCH:On=Off} != "Off")
+# expect+1: Bad modifier ":On=Off"
.if ${SWITCH:On=Off} != "Off"
. error
.else
diff --git a/unit-tests/varmod-range.exp b/unit-tests/varmod-range.exp
index 2848193e0db1..dbd50c6def80 100644
--- a/unit-tests/varmod-range.exp
+++ b/unit-tests/varmod-range.exp
@@ -1,14 +1,14 @@
-make: "varmod-range.mk" line 43: Malformed conditional (${:range=5} != "")
-make: "varmod-range.mk" line 67: while evaluating "${:U:range=x}Rest" != "Rest"" with value "": Invalid number "x}Rest" != "Rest"" for ':range' modifier
-make: "varmod-range.mk" line 67: Malformed conditional ("${:U:range=x}Rest" != "Rest")
-make: "varmod-range.mk" line 78: while evaluating "${:U:range=0x0}Rest" != "Rest"" with value "1": Unknown modifier "x0"
-make: "varmod-range.mk" line 78: Malformed conditional ("${:U:range=0x0}Rest" != "Rest")
-make: "varmod-range.mk" line 96: while evaluating variable "a b c" with value "a b c": Unknown modifier "rang"
-make: "varmod-range.mk" line 96: Malformed conditional ("${a b c:L:rang}Rest" != "Rest")
-make: "varmod-range.mk" line 105: while evaluating variable "a b c" with value "a b c": Unknown modifier "rango"
-make: "varmod-range.mk" line 105: Malformed conditional ("${a b c:L:rango}Rest" != "Rest")
-make: "varmod-range.mk" line 114: while evaluating variable "a b c" with value "a b c": Unknown modifier "ranger"
-make: "varmod-range.mk" line 114: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest")
+make: "varmod-range.mk" line 43: Malformed conditional '${:range=5} != ""'
+make: "varmod-range.mk" line 66: Invalid number "x}Rest" != "Rest"" for ':range' modifier
+ while evaluating "${:U:range=x}Rest" != "Rest"" with value ""
+make: "varmod-range.mk" line 76: Unknown modifier "x0"
+ while evaluating "${:U:range=0x0}Rest" != "Rest"" with value "1"
+make: "varmod-range.mk" line 93: Unknown modifier "rang"
+ while evaluating variable "a b c" with value "a b c"
+make: "varmod-range.mk" line 101: Unknown modifier "rango"
+ while evaluating variable "a b c" with value "a b c"
+make: "varmod-range.mk" line 109: Unknown modifier "ranger"
+ while evaluating variable "a b c" with value "a b c"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-range.mk b/unit-tests/varmod-range.mk
index 4b07b659489c..277935dc8bc7 100644
--- a/unit-tests/varmod-range.mk
+++ b/unit-tests/varmod-range.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-range.mk,v 1.13 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-range.mk,v 1.16 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the :range variable modifier, which generates sequences
# of integers from the given range.
@@ -39,7 +39,7 @@
# XXX: As of 2023-12-17, the ':range=n' modifier does not turn the undefined
# expression into a defined one, even though it does not depend on the value
# of the expression. This looks like an oversight.
-# expect+1: Malformed conditional (${:range=5} != "")
+# expect+1: Malformed conditional '${:range=5} != ""'
.if ${:range=5} != ""
. error
.else
@@ -62,8 +62,7 @@
#
# Since 2020-11-01, the parser issues a more precise "Invalid number" error
# instead.
-# expect+2: while evaluating "${:U:range=x}Rest" != "Rest"" with value "": Invalid number "x}Rest" != "Rest"" for ':range' modifier
-# expect+1: Malformed conditional ("${:U:range=x}Rest" != "Rest")
+# expect+1: Invalid number "x}Rest" != "Rest"" for ':range' modifier
.if "${:U:range=x}Rest" != "Rest"
. error
.else
@@ -73,8 +72,7 @@
# The upper limit of the range must always be given in decimal.
# This parse error stops at the 'x', trying to parse it as a variable
# modifier.
-# expect+2: while evaluating "${:U:range=0x0}Rest" != "Rest"" with value "1": Unknown modifier "x0"
-# expect+1: Malformed conditional ("${:U:range=0x0}Rest" != "Rest")
+# expect+1: Unknown modifier "x0"
.if "${:U:range=0x0}Rest" != "Rest"
. error
.else
@@ -91,8 +89,7 @@
#.endif
# modifier name too short
-# expect+2: while evaluating variable "a b c" with value "a b c": Unknown modifier "rang"
-# expect+1: Malformed conditional ("${a b c:L:rang}Rest" != "Rest")
+# expect+1: Unknown modifier "rang"
.if "${a b c:L:rang}Rest" != "Rest"
. error
.else
@@ -100,8 +97,7 @@
.endif
# misspelled modifier name
-# expect+2: while evaluating variable "a b c" with value "a b c": Unknown modifier "rango"
-# expect+1: Malformed conditional ("${a b c:L:rango}Rest" != "Rest")
+# expect+1: Unknown modifier "rango"
.if "${a b c:L:rango}Rest" != "Rest"
. error
.else
@@ -109,8 +105,7 @@
.endif
# modifier name too long
-# expect+2: while evaluating variable "a b c" with value "a b c": Unknown modifier "ranger"
-# expect+1: Malformed conditional ("${a b c:L:ranger}Rest" != "Rest")
+# expect+1: Unknown modifier "ranger"
.if "${a b c:L:ranger}Rest" != "Rest"
. error
.else
diff --git a/unit-tests/varmod-select-words.exp b/unit-tests/varmod-select-words.exp
index c503e57b384b..7877837744ea 100644
--- a/unit-tests/varmod-select-words.exp
+++ b/unit-tests/varmod-select-words.exp
@@ -1,5 +1,6 @@
-make: in target "mod-squarebrackets-0-star-at": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[]"
-LIST:[]="" is an error
+make: Bad modifier ":[]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-empty"
LIST:[0]="one two three four five six"
LIST:[0x0]="one two three four five six"
LIST:[000]="one two three four five six"
@@ -37,18 +38,22 @@ REALLYSPACE=" "
REALLYSPACE:[1]="" == "" ?
REALLYSPACE:[*]:[1]=" " == " " ?
LIST:[1]="one"
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
-LIST:[1.]="" is an error
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1]."
-LIST:[1].="}" is an error
+make: Bad modifier ":[1.]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-n-error-1"
+make: Bad modifier ":[1]."
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-n-error-2"
LIST:[2]="two"
LIST:[6]="six"
LIST:[7]=""
LIST:[999]=""
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-]"
-LIST:[-]="" is an error
-make: in target "mod-squarebrackets-n": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[--]"
-LIST:[--]="" is an error
+make: Bad modifier ":[-]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-n-error-3"
+make: Bad modifier ":[--]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-n-error-4"
LIST:[-1]="six"
LIST:[-2]="five"
LIST:[-6]="one"
@@ -67,23 +72,29 @@ LIST:[*]:C/ /,/:[2]=""
LIST:[*]:C/ /,/:[*]:[2]=""
LIST:[*]:C/ /,/:[@]:[2]="three"
LONGLIST:[012..0x12]="10 11 12 13 14 15 16 17 18"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.]"
-LIST:[1.]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..]"
-LIST:[1..]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1.. ]"
-LIST:[1.. ]="" is an error
+make: Bad modifier ":[1.]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-1"
+make: Bad modifier ":[1..]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-2"
+make: Bad modifier ":[1.. ]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-3"
LIST:[1..1]="one"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[1..1.]"
-LIST:[1..1.]="" is an error
+make: Bad modifier ":[1..1.]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-4"
LIST:[1..2]="one two"
LIST:[2..1]="two one"
LIST:[3..-2]="three four five"
LIST:[-4..4]="three four"
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[0..1]"
-LIST:[0..1]="" is an error
-make: in target "mod-squarebrackets-start-end": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[-1..0]"
-LIST:[-1..0]="" is an error
+make: Bad modifier ":[0..1]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-5"
+make: Bad modifier ":[-1..0]"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-start-end-error-6"
LIST:[-1..1]="six five four three two one"
LIST:[0..0]="one two three four five six"
LIST:[3..99]="three four five six"
@@ -97,8 +108,9 @@ LIST:[${ONE}]="one"
LIST:[${MINUSONE}]="six"
LIST:[${STAR}]="one two three four five six"
LIST:[${AT}]="one two three four five six"
-make: in target "mod-squarebrackets-nested": while evaluating variable "LIST" with value "one two three four five six": Bad modifier ":[${EMPTY"
-LIST:[${EMPTY}]="" is an error
+make: Bad modifier ":[${EMPTY"
+ while evaluating variable "LIST" with value "one two three four five six"
+ in target "mod-squarebrackets-nested-error-1"
LIST:[${LONGLIST:[21]:S/2//}]="one"
LIST:[${LIST:[#]}]="six"
LIST:[${LIST:[${HASH}]}]="six"
diff --git a/unit-tests/varmod-select-words.mk b/unit-tests/varmod-select-words.mk
index 910b67a24e39..25a085891c0a 100644
--- a/unit-tests/varmod-select-words.mk
+++ b/unit-tests/varmod-select-words.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-select-words.mk,v 1.4 2022/01/23 16:09:38 rillig Exp $
+# $NetBSD: varmod-select-words.mk,v 1.6 2024/08/29 20:20:36 rillig Exp $
#
# Tests for the :[...] variable modifier, which selects a single word
# or a range of words from a variable.
@@ -24,15 +24,36 @@ ZERO= 0
ONE= 1
MINUSONE= -1
-mod-squarebrackets: mod-squarebrackets-0-star-at \
+mod-squarebrackets: \
+ mod-squarebrackets-empty \
+ mod-squarebrackets-0-star-at \
mod-squarebrackets-hash \
- mod-squarebrackets-n \
- mod-squarebrackets-start-end \
- mod-squarebrackets-nested \
+ mod-squarebrackets-n-ok-1 \
+ mod-squarebrackets-n-error-1 \
+ mod-squarebrackets-n-error-2 \
+ mod-squarebrackets-n-ok-2 \
+ mod-squarebrackets-n-error-3 \
+ mod-squarebrackets-n-error-4 \
+ mod-squarebrackets-n-ok-3 \
+ mod-squarebrackets-start-end-error-1 \
+ mod-squarebrackets-start-end-error-2 \
+ mod-squarebrackets-start-end-error-3 \
+ mod-squarebrackets-start-end-ok-1 \
+ mod-squarebrackets-start-end-error-4 \
+ mod-squarebrackets-start-end-ok-2 \
+ mod-squarebrackets-start-end-error-5 \
+ mod-squarebrackets-start-end-error-6 \
+ mod-squarebrackets-start-end-ok-3 \
+ mod-squarebrackets-nested-ok-1 \
+ mod-squarebrackets-nested-error-1 \
+ mod-squarebrackets-nested-ok-2 \
mod-squarebrackets-space
-mod-squarebrackets-0-star-at:
+mod-squarebrackets-empty:
+# expect: make: Bad modifier ":[]"
@echo 'LIST:[]="${LIST:[]}" is an error'
+
+mod-squarebrackets-0-star-at:
@echo 'LIST:[0]="${LIST:[0]}"'
@echo 'LIST:[0x0]="${LIST:[0x0]}"'
@echo 'LIST:[000]="${LIST:[000]}"'
@@ -66,7 +87,7 @@ mod-squarebrackets-hash:
@echo 'LIST:[1]:[#]="${LIST:[1]:[#]}"'
@echo 'LIST:[1..3]:[#]="${LIST:[1..3]:[#]}"'
-mod-squarebrackets-n:
+mod-squarebrackets-n-ok-1:
@echo 'EMPTY:[1]="${EMPTY:[1]}"'
@echo 'ESCAPEDSPACE="${ESCAPEDSPACE}"'
@echo 'ESCAPEDSPACE:[1]="${ESCAPEDSPACE:[1]}"'
@@ -74,14 +95,24 @@ mod-squarebrackets-n:
@echo 'REALLYSPACE:[1]="${REALLYSPACE:[1]}" == "" ?'
@echo 'REALLYSPACE:[*]:[1]="${REALLYSPACE:[*]:[1]}" == " " ?'
@echo 'LIST:[1]="${LIST:[1]}"'
+mod-squarebrackets-n-error-1:
+# expect: make: Bad modifier ":[1.]"
@echo 'LIST:[1.]="${LIST:[1.]}" is an error'
+mod-squarebrackets-n-error-2:
+# expect: make: Bad modifier ":[1]."
@echo 'LIST:[1].="${LIST:[1].}" is an error'
+mod-squarebrackets-n-ok-2:
@echo 'LIST:[2]="${LIST:[2]}"'
@echo 'LIST:[6]="${LIST:[6]}"'
@echo 'LIST:[7]="${LIST:[7]}"'
@echo 'LIST:[999]="${LIST:[999]}"'
+mod-squarebrackets-n-error-3:
+# expect: make: Bad modifier ":[-]"
@echo 'LIST:[-]="${LIST:[-]}" is an error'
+mod-squarebrackets-n-error-4:
+# expect: make: Bad modifier ":[--]"
@echo 'LIST:[--]="${LIST:[--]}" is an error'
+mod-squarebrackets-n-ok-3:
@echo 'LIST:[-1]="${LIST:[-1]}"'
@echo 'LIST:[-2]="${LIST:[-2]}"'
@echo 'LIST:[-6]="${LIST:[-6]}"'
@@ -101,25 +132,39 @@ mod-squarebrackets-n:
@echo 'LIST:[*]:C/ /,/:[@]:[2]="${LIST:[*]:C/ /,/:[@]:[2]}"'
@echo 'LONGLIST:[012..0x12]="${LONGLIST:[012..0x12]}"'
-mod-squarebrackets-start-end:
+mod-squarebrackets-start-end-error-1:
+# expect: make: Bad modifier ":[1.]"
@echo 'LIST:[1.]="${LIST:[1.]}" is an error'
+mod-squarebrackets-start-end-error-2:
+# expect: make: Bad modifier ":[1..]"
@echo 'LIST:[1..]="${LIST:[1..]}" is an error'
+mod-squarebrackets-start-end-error-3:
+# expect: make: Bad modifier ":[1.. ]"
@echo 'LIST:[1.. ]="${LIST:[1.. ]}" is an error'
+mod-squarebrackets-start-end-ok-1:
@echo 'LIST:[1..1]="${LIST:[1..1]}"'
+mod-squarebrackets-start-end-error-4:
+# expect: make: Bad modifier ":[1..1.]"
@echo 'LIST:[1..1.]="${LIST:[1..1.]}" is an error'
+mod-squarebrackets-start-end-ok-2:
@echo 'LIST:[1..2]="${LIST:[1..2]}"'
@echo 'LIST:[2..1]="${LIST:[2..1]}"'
@echo 'LIST:[3..-2]="${LIST:[3..-2]}"'
@echo 'LIST:[-4..4]="${LIST:[-4..4]}"'
+mod-squarebrackets-start-end-error-5:
+# expect: make: Bad modifier ":[0..1]"
@echo 'LIST:[0..1]="${LIST:[0..1]}" is an error'
+mod-squarebrackets-start-end-error-6:
+# expect: make: Bad modifier ":[-1..0]"
@echo 'LIST:[-1..0]="${LIST:[-1..0]}" is an error'
+mod-squarebrackets-start-end-ok-3:
@echo 'LIST:[-1..1]="${LIST:[-1..1]}"'
@echo 'LIST:[0..0]="${LIST:[0..0]}"'
@echo 'LIST:[3..99]="${LIST:[3..99]}"'
@echo 'LIST:[-3..-99]="${LIST:[-3..-99]}"'
@echo 'LIST:[-99..-3]="${LIST:[-99..-3]}"'
-mod-squarebrackets-nested:
+mod-squarebrackets-nested-ok-1:
@echo 'HASH="${HASH}" == "#" ?'
@echo 'LIST:[$${HASH}]="${LIST:[${HASH}]}"'
@echo 'LIST:[$${ZERO}]="${LIST:[${ZERO}]}"'
@@ -128,7 +173,10 @@ mod-squarebrackets-nested:
@echo 'LIST:[$${MINUSONE}]="${LIST:[${MINUSONE}]}"'
@echo 'LIST:[$${STAR}]="${LIST:[${STAR}]}"'
@echo 'LIST:[$${AT}]="${LIST:[${AT}]}"'
+mod-squarebrackets-nested-error-1:
+# expect: make: Bad modifier ":[${EMPTY"
@echo 'LIST:[$${EMPTY}]="${LIST:[${EMPTY}]}" is an error'
+mod-squarebrackets-nested-ok-2:
@echo 'LIST:[$${LONGLIST:[21]:S/2//}]="${LIST:[${LONGLIST:[21]:S/2//}]}"'
@echo 'LIST:[$${LIST:[#]}]="${LIST:[${LIST:[#]}]}"'
@echo 'LIST:[$${LIST:[$${HASH}]}]="${LIST:[${LIST:[${HASH}]}]}"'
diff --git a/unit-tests/varmod-shell.exp b/unit-tests/varmod-shell.exp
index 6ada8f74d75e..b2c6c59eea40 100644
--- a/unit-tests/varmod-shell.exp
+++ b/unit-tests/varmod-shell.exp
@@ -1,11 +1,11 @@
-make: "varmod-shell.mk" line 25: warning: while evaluating "${:!echo word; (exit 13)!} != "word"" with value "word": Command "echo word; (exit 13)" exited with status 13
-make: "varmod-shell.mk" line 29: warning: while evaluating "${:Uprevious value:!echo word; (exit 13)!} != "word"" with value "word": Command "echo word; (exit 13)" exited with status 13
+make: "varmod-shell.mk" line 25: warning: Command "echo word; (exit 13)" exited with status 13
+make: "varmod-shell.mk" line 29: warning: Command "echo word; (exit 13)" exited with status 13
Global: _ = # (empty)
Var_Parse: ${:!echo word; ${:U(exit 13)}!} (eval-keep-dollar-and-undefined)
Evaluating modifier ${:!...} on value "" (eval-keep-dollar-and-undefined, undefined)
Modifier part: "echo word; (exit 13)"
Capturing the output of command "echo word; (exit 13)"
-make: "varmod-shell.mk" line 36: warning: while evaluating "${:!echo word; ${:U(exit 13)}!}" with value "word": Command "echo word; (exit 13)" exited with status 13
+make: "varmod-shell.mk" line 36: warning: Command "echo word; (exit 13)" exited with status 13
Result of ${:!echo word; ${:U(exit 13)}!} is "word" (eval-keep-dollar-and-undefined, defined)
Global: _ = word
Global: .MAKEFLAGS = -r -k -d v -d
diff --git a/unit-tests/varmod-shell.mk b/unit-tests/varmod-shell.mk
index 87918c5bbbf6..5f614d0c7f3c 100644
--- a/unit-tests/varmod-shell.mk
+++ b/unit-tests/varmod-shell.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-shell.mk,v 1.10 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-shell.mk,v 1.11 2024/08/29 20:20:37 rillig Exp $
#
# Tests for the ':!cmd!' variable modifier, which runs the shell command
# given by the variable modifier and returns its output.
@@ -21,18 +21,18 @@
# Between 2000-04-29 and 2020-11-17, the error message mentioned the previous
# value of the expression (which is usually an empty string) instead of the
# command that was executed.
-# expect+1: warning: while evaluating "${:!echo word; (exit 13)!} != "word"" with value "word": Command "echo word; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo word; (exit 13)" exited with status 13
.if ${:!echo word; (exit 13)!} != "word"
. error
.endif
-# expect+1: warning: while evaluating "${:Uprevious value:!echo word; (exit 13)!} != "word"" with value "word": Command "echo word; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo word; (exit 13)" exited with status 13
.if ${:Uprevious value:!echo word; (exit 13)!} != "word"
. error
.endif
.MAKEFLAGS: -dv # to see the "Capturing" debug output
-# expect+1: warning: while evaluating "${:!echo word; ${:U(exit 13)}!}" with value "word": Command "echo word; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo word; (exit 13)" exited with status 13
_:= ${:!echo word; ${:U(exit 13)}!}
.MAKEFLAGS: -d0
diff --git a/unit-tests/varmod-subst-regex.exp b/unit-tests/varmod-subst-regex.exp
index 722abdff5813..98c37f6fd8e7 100644
--- a/unit-tests/varmod-subst-regex.exp
+++ b/unit-tests/varmod-subst-regex.exp
@@ -1,27 +1,52 @@
-make: in target "mod-regex-compile-error": while evaluating "${:Uword1 word2:C,****,____,g:C,word,____,:Q}." with value "word1 word2": Regex compilation error: (details omitted)
-mod-regex-compile-error: C,word,____,:Q}.
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456": No subexpression \1
-mod-regex-limits:11-missing:1 6
-mod-regex-limits:11-ok:1 22 446
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456": No subexpression \2
-mod-regex-limits:22-missing:1 6
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-make: in target "mod-regex-limits": while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456": No subexpression \2
-mod-regex-limits:22-missing:1 6
-mod-regex-limits:22-ok:1 33 556
-mod-regex-limits:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
-make: in target "mod-regex-errors": while evaluating variable "UNDEF" with value "value": Regex compilation error: (details omitted)
-mod-regex-errors:
-make: in target "mod-regex-errors": while evaluating variable "word" with value "word": while evaluating "${:U:Z}y,W}" with value "": Unknown modifier "Z"
-mod-regex-errors: xy
+make: Regex compilation error: (details omitted)
+ while evaluating "${:Uword1 word2:C,****,____,g:C,word,____,:Q}." with value "word1 word2"
+ in target "mod-regex-compile-error"
+make: No subexpression \1
+ while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-1"
+make: No subexpression \1
+ while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-1"
+make: No subexpression \1
+ while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-1"
+make: No subexpression \1
+ while evaluating "${:U1 23 456:C,..,\1\1,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-1"
+mod-regex-limits-2:11-ok:1 22 446
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-3"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-3"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-3"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,..,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-3"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-4"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-4"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-4"
+make: No subexpression \2
+ while evaluating "${:U1 23 456:C,(.).,\2\2,:Q}" with value "1 23 456"
+ in target "mod-regex-limits-4"
+mod-regex-limits-5:22-ok:1 33 556
+mod-regex-limits-6:capture:ihgfedcbaabcdefghijABCDEFGHIJa0a1a2rest
+make: Regex compilation error: (details omitted)
+ while evaluating variable "UNDEF" with value "value"
+ in target "mod-regex-errors-1"
+make: Unknown modifier "Z"
+ while evaluating "${:U:Z}y,W}" with value ""
+ while evaluating variable "word" with value "word"
+ in target "mod-regex-errors-2"
unmatched-subexpression.ok: one one 2 3 5 8 one3 2one 34
make: No match for subexpression \2
unmatched-subexpression.1: ()()
diff --git a/unit-tests/varmod-subst-regex.mk b/unit-tests/varmod-subst-regex.mk
index c1ffc4580d3a..bc04bc5fffb9 100644
--- a/unit-tests/varmod-subst-regex.mk
+++ b/unit-tests/varmod-subst-regex.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-subst-regex.mk,v 1.11 2023/12/18 11:13:51 rillig Exp $
+# $NetBSD: varmod-subst-regex.mk,v 1.12 2024/07/20 11:05:12 rillig Exp $
#
# Tests for the :C,from,to, variable modifier.
@@ -6,8 +6,8 @@
.MAKEFLAGS: -dL
all: mod-regex-compile-error
-all: mod-regex-limits
-all: mod-regex-errors
+all: mod-regex-limits-{1,2,3,4,5,6}
+all: mod-regex-errors-{1,2}
all: unmatched-subexpression
# The expression expands to 4 words. Of these words, none matches
@@ -139,19 +139,25 @@ mod-regex-compile-error:
# These tests generate error messages but as of 2020-08-28 just continue
# parsing and execution as if nothing bad had happened.
-mod-regex-limits:
+mod-regex-limits-1:
@echo $@:11-missing:${:U1 23 456:C,..,\1\1,:Q}
+mod-regex-limits-2:
@echo $@:11-ok:${:U1 23 456:C,(.).,\1\1,:Q}
+mod-regex-limits-3:
@echo $@:22-missing:${:U1 23 456:C,..,\2\2,:Q}
+mod-regex-limits-4:
@echo $@:22-missing:${:U1 23 456:C,(.).,\2\2,:Q}
+mod-regex-limits-5:
@echo $@:22-ok:${:U1 23 456:C,(.)(.),\2\2,:Q}
+mod-regex-limits-6:
# The :C modifier only handles single-digit capturing groups,
# which is enough for all practical use cases.
@echo $@:capture:${:UabcdefghijABCDEFGHIJrest:C,(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.)(.),\9\8\7\6\5\4\3\2\1\0\10\11\12,}
-mod-regex-errors:
+mod-regex-errors-1:
@echo $@: ${UNDEF:Uvalue:C,[,,}
+mod-regex-errors-2:
# If the replacement pattern produces a parse error because of an
# unknown modifier, the parse error is ignored in ParseModifierPart
# and the faulty expression expands to "".
diff --git a/unit-tests/varmod-subst.exp b/unit-tests/varmod-subst.exp
index 9b91c0e50857..1547201bb404 100644
--- a/unit-tests/varmod-subst.exp
+++ b/unit-tests/varmod-subst.exp
@@ -45,8 +45,9 @@ mod-subst-delimiter:
1 two 3 tilde
mod-subst-chain:
A B c.
-make: in target "mod-subst-chain": while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue": Unknown modifier "i"
-.
+make: Unknown modifier "i"
+ while evaluating "${:Uvalue:S,a,x,i}." with value "vxlue"
+ in target "mod-subst-chain"
mod-subst-dollar:$1:
mod-subst-dollar:$2:
mod-subst-dollar:$3:
diff --git a/unit-tests/varmod-subst.mk b/unit-tests/varmod-subst.mk
index 2903d36445f8..34f20a5f96f2 100644
--- a/unit-tests/varmod-subst.mk
+++ b/unit-tests/varmod-subst.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-subst.mk,v 1.14 2023/12/18 11:13:51 rillig Exp $
+# $NetBSD: varmod-subst.mk,v 1.16 2024/08/29 20:20:37 rillig Exp $
#
# Tests for the :S,from,to, variable modifier.
@@ -252,6 +252,7 @@ mod-subst-chain:
# The error message is "make: Unknown modifier 'i'", which is
# kind of correct, although it is mixing the terms for variable
# modifiers with the matching modifiers.
+# expect: make: Unknown modifier "i"
@echo ${:Uvalue:S,a,x,i}.
# No matter how many dollar signs there are, they all get merged
diff --git a/unit-tests/varmod-sun-shell.exp b/unit-tests/varmod-sun-shell.exp
index 80dec0935f28..5a557b97cec8 100644
--- a/unit-tests/varmod-sun-shell.exp
+++ b/unit-tests/varmod-sun-shell.exp
@@ -1,11 +1,11 @@
-make: "varmod-sun-shell.mk" line 17: warning: while evaluating variable "echo word; (exit 13)" with value "echo word; (exit 13)": Command "echo word; (exit 13)" exited with status 13
+make: "varmod-sun-shell.mk" line 17: warning: Command "echo word; (exit 13)" exited with status 13
Global: _ = # (empty)
Var_Parse: ${echo word; ${:U(exit 13)}:L:sh} (eval-keep-dollar-and-undefined)
Evaluating modifier ${echo word; (exit 13):L} on value "" (eval-keep-dollar-and-undefined, undefined)
Result of ${echo word; (exit 13):L} is "echo word; (exit 13)" (eval-keep-dollar-and-undefined, defined)
Evaluating modifier ${echo word; (exit 13):s...} on value "echo word; (exit 13)" (eval-keep-dollar-and-undefined, defined)
Capturing the output of command "echo word; (exit 13)"
-make: "varmod-sun-shell.mk" line 24: warning: while evaluating variable "echo word; (exit 13)" with value "echo word; (exit 13)": Command "echo word; (exit 13)" exited with status 13
+make: "varmod-sun-shell.mk" line 24: warning: Command "echo word; (exit 13)" exited with status 13
Result of ${echo word; (exit 13):sh} is "word" (eval-keep-dollar-and-undefined, defined)
Global: _ = word
Global: .MAKEFLAGS = -r -k -d v -d
diff --git a/unit-tests/varmod-sun-shell.mk b/unit-tests/varmod-sun-shell.mk
index 4a37a271eced..8f6a5bc4cc05 100644
--- a/unit-tests/varmod-sun-shell.mk
+++ b/unit-tests/varmod-sun-shell.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-sun-shell.mk,v 1.5 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-sun-shell.mk,v 1.6 2024/08/29 20:20:37 rillig Exp $
#
# Tests for the :sh variable modifier, which runs the shell command
# given by the variable value and returns its output.
@@ -13,14 +13,14 @@
.endif
# If the command exits with non-zero, a warning is printed.
-# expect+1: warning: while evaluating variable "echo word; (exit 13)" with value "echo word; (exit 13)": Command "echo word; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo word; (exit 13)" exited with status 13
.if ${echo word; (exit 13):L:sh} != "word"
. error
.endif
.MAKEFLAGS: -dv # to see the "Capturing" debug output
-# expect+1: warning: while evaluating variable "echo word; (exit 13)" with value "echo word; (exit 13)": Command "echo word; (exit 13)" exited with status 13
+# expect+1: warning: Command "echo word; (exit 13)" exited with status 13
_:= ${echo word; ${:U(exit 13)}:L:sh}
.MAKEFLAGS: -d0
diff --git a/unit-tests/varmod-sysv.exp b/unit-tests/varmod-sysv.exp
index be87193b4066..ecda358758e1 100644
--- a/unit-tests/varmod-sysv.exp
+++ b/unit-tests/varmod-sysv.exp
@@ -1,5 +1,5 @@
-make: "varmod-sysv.mk" line 216: while evaluating variable "word216" with value "word216": Unfinished modifier ('=' missing)
-make: "varmod-sysv.mk" line 216: Malformed conditional (${word216:L:from${:D=}to})
+make: "varmod-sysv.mk" line 215: Unfinished modifier ('=' missing)
+ while evaluating variable "word216" with value "word216"
word modifier result
'' = ""
suffix = "suffix"
@@ -145,8 +145,8 @@ pre-middle-suffix pre%ffix=NPre% "NPre-middle-su"
suffix pre%ffix=NPre%NS "suffix"
prefix pre%ffix=NPre%NS "prefix"
pre-middle-suffix pre%ffix=NPre%NS "NPre-middle-suNS"
-make: "varmod-sysv.mk" line 261: while evaluating variable "error" with value "error": Unfinished modifier ('}' missing)
-make: "varmod-sysv.mk" line 261: Malformed conditional (${error:L:from=$(}))
+make: "varmod-sysv.mk" line 259: Unfinished modifier ('}' missing)
+ while evaluating variable "error" with value "error"
make: Fatal errors encountered -- cannot continue
make: stopped making "all" in unit-tests
exit status 1
diff --git a/unit-tests/varmod-sysv.mk b/unit-tests/varmod-sysv.mk
index 8db41d7fb364..f7d7a1ffe81a 100644
--- a/unit-tests/varmod-sysv.mk
+++ b/unit-tests/varmod-sysv.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-sysv.mk,v 1.19 2024/07/04 17:47:54 rillig Exp $
+# $NetBSD: varmod-sysv.mk,v 1.22 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the variable modifier ':from=to', which replaces the suffix
# "from" with "to". It can also use '%' as a wildcard.
@@ -211,8 +211,7 @@
# XXX: As of 2024-06-30, this expression generates an "Unfinished modifier"
# error, while the correct error message would be "Unknown modifier" since
# there is no modifier named "fromto".
-# expect+2: while evaluating variable "word216" with value "word216": Unfinished modifier ('=' missing)
-# expect+1: Malformed conditional (${word216:L:from${:D=}to})
+# expect+1: Unfinished modifier ('=' missing)
.if ${word216:L:from${:D=}to}
. error
.endif
@@ -256,8 +255,7 @@ INDIRECT= 1:${VALUE} 2:$${VALUE} 4:$$$${VALUE}
# The error case of an unfinished ':from=to' modifier after the '=' requires
# an expression that is missing the closing '}'.
-# expect+2: while evaluating variable "error" with value "error": Unfinished modifier ('}' missing)
-# expect+1: Malformed conditional (${error:L:from=$(}))
+# expect+1: Unfinished modifier ('}' missing)
.if ${error:L:from=$(})
.endif
diff --git a/unit-tests/varmod-to-separator.exp b/unit-tests/varmod-to-separator.exp
index fe61ada505df..368def5f7ffe 100644
--- a/unit-tests/varmod-to-separator.exp
+++ b/unit-tests/varmod-to-separator.exp
@@ -1,29 +1,29 @@
-make: "varmod-to-separator.mk" line 155: while evaluating variable "WORDS" with value "one two three": Invalid character number at "400:tu}"
-make: "varmod-to-separator.mk" line 155: Malformed conditional (${WORDS:[1..3]:ts\400:tu})
-make: "varmod-to-separator.mk" line 171: while evaluating variable "WORDS" with value "one two three": Invalid character number at "100:tu}"
-make: "varmod-to-separator.mk" line 171: Malformed conditional (${WORDS:[1..3]:ts\x100:tu})
-make: "varmod-to-separator.mk" line 180: while evaluating variable "word" with value "word": Invalid character number at ",}"
-make: "varmod-to-separator.mk" line 180: Malformed conditional (${word:L:ts\x,})
-make: "varmod-to-separator.mk" line 187: while evaluating variable "word" with value "word": Invalid character number at "112233445566778899}"
-make: "varmod-to-separator.mk" line 187: Malformed conditional (${word:L:ts\x112233445566778899})
-make: "varmod-to-separator.mk" line 193: while evaluating variable "WORDS" with value "one two three": Bad modifier ":ts\-300"
-make: "varmod-to-separator.mk" line 193: Malformed conditional (${WORDS:[1..3]:ts\-300:tu})
-make: "varmod-to-separator.mk" line 203: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\8"
-make: "varmod-to-separator.mk" line 203: Malformed conditional (${1 2 3:L:ts\8:tu})
-make: "varmod-to-separator.mk" line 212: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\100L"
-make: "varmod-to-separator.mk" line 212: Malformed conditional (${1 2 3:L:ts\100L})
-make: "varmod-to-separator.mk" line 221: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\x40g"
-make: "varmod-to-separator.mk" line 221: Malformed conditional (${1 2 3:L:ts\x40g})
-make: "varmod-to-separator.mk" line 231: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":tx"
-make: "varmod-to-separator.mk" line 231: Malformed conditional (${WORDS:tx})
-make: "varmod-to-separator.mk" line 240: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":ts\X"
-make: "varmod-to-separator.mk" line 240: Malformed conditional (${WORDS:ts\X})
-make: "varmod-to-separator.mk" line 250: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":t\X"
-make: "varmod-to-separator.mk" line 250: Malformed conditional (${WORDS:t\X} != "anything")
-make: "varmod-to-separator.mk" line 267: while evaluating "${:Ua b:ts\69}" with value "a b": Bad modifier ":ts\69"
-make: "varmod-to-separator.mk" line 267: Malformed conditional (${:Ua b:ts\69})
-make: "varmod-to-separator.mk" line 276: while evaluating "${:Ua b:ts\x1F60E}" with value "a b": Invalid character number at "1F60E}"
-make: "varmod-to-separator.mk" line 276: Malformed conditional (${:Ua b:ts\x1F60E})
+make: "varmod-to-separator.mk" line 154: Invalid character number at "400:tu}"
+ while evaluating variable "WORDS" with value "one two three"
+make: "varmod-to-separator.mk" line 169: Invalid character number at "100:tu}"
+ while evaluating variable "WORDS" with value "one two three"
+make: "varmod-to-separator.mk" line 177: Invalid character number at ",}"
+ while evaluating variable "word" with value "word"
+make: "varmod-to-separator.mk" line 183: Invalid character number at "112233445566778899}"
+ while evaluating variable "word" with value "word"
+make: "varmod-to-separator.mk" line 188: Bad modifier ":ts\-300"
+ while evaluating variable "WORDS" with value "one two three"
+make: "varmod-to-separator.mk" line 197: Bad modifier ":ts\8"
+ while evaluating variable "1 2 3" with value "1 2 3"
+make: "varmod-to-separator.mk" line 205: Bad modifier ":ts\100L"
+ while evaluating variable "1 2 3" with value "1 2 3"
+make: "varmod-to-separator.mk" line 213: Bad modifier ":ts\x40g"
+ while evaluating variable "1 2 3" with value "1 2 3"
+make: "varmod-to-separator.mk" line 222: Bad modifier ":tx"
+ while evaluating variable "WORDS" with value "one two three four five six"
+make: "varmod-to-separator.mk" line 230: Bad modifier ":ts\X"
+ while evaluating variable "WORDS" with value "one two three four five six"
+make: "varmod-to-separator.mk" line 239: Bad modifier ":t\X"
+ while evaluating variable "WORDS" with value "one two three four five six"
+make: "varmod-to-separator.mk" line 255: Bad modifier ":ts\69"
+ while evaluating "${:Ua b:ts\69}" with value "a b"
+make: "varmod-to-separator.mk" line 263: Invalid character number at "1F60E}"
+ while evaluating "${:Ua b:ts\x1F60E}" with value "a b"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod-to-separator.mk b/unit-tests/varmod-to-separator.mk
index b4c6839a0a2b..5cb838bf5bb7 100644
--- a/unit-tests/varmod-to-separator.mk
+++ b/unit-tests/varmod-to-separator.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod-to-separator.mk,v 1.18 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod-to-separator.mk,v 1.21 2025/01/11 20:54:46 rillig Exp $
#
# Tests for the :ts variable modifier, which joins the words of the variable
# using an arbitrary character as word separator.
@@ -150,8 +150,7 @@ WORDS= one two three four five six
# for an unsigned character though.
#
# Since 2020-11-01, these out-of-bounds values are rejected.
-# expect+2: while evaluating variable "WORDS" with value "one two three": Invalid character number at "400:tu}"
-# expect+1: Malformed conditional (${WORDS:[1..3]:ts\400:tu})
+# expect+1: Invalid character number at "400:tu}"
.if ${WORDS:[1..3]:ts\400:tu}
. warning The separator \400 is accepted even though it is out of bounds.
.else
@@ -166,8 +165,7 @@ WORDS= one two three four five six
# The hexadecimal number must be in the range of an unsigned char.
#
# Since 2020-11-01, these out-of-bounds values are rejected.
-# expect+2: while evaluating variable "WORDS" with value "one two three": Invalid character number at "100:tu}"
-# expect+1: Malformed conditional (${WORDS:[1..3]:ts\x100:tu})
+# expect+1: Invalid character number at "100:tu}"
.if ${WORDS:[1..3]:ts\x100:tu}
. warning The separator \x100 is accepted even though it is out of bounds.
.else
@@ -175,21 +173,18 @@ WORDS= one two three four five six
.endif
# The number after ':ts\x' must be hexadecimal.
-# expect+2: while evaluating variable "word" with value "word": Invalid character number at ",}"
-# expect+1: Malformed conditional (${word:L:ts\x,})
+# expect+1: Invalid character number at ",}"
.if ${word:L:ts\x,}
.endif
# The hexadecimal number must be in the range of 'unsigned long' on all
# supported platforms.
-# expect+2: while evaluating variable "word" with value "word": Invalid character number at "112233445566778899}"
-# expect+1: Malformed conditional (${word:L:ts\x112233445566778899})
+# expect+1: Invalid character number at "112233445566778899}"
.if ${word:L:ts\x112233445566778899}
.endif
# Negative numbers are not allowed for the separator character.
-# expect+2: while evaluating variable "WORDS" with value "one two three": Bad modifier ":ts\-300"
-# expect+1: Malformed conditional (${WORDS:[1..3]:ts\-300:tu})
+# expect+1: Bad modifier ":ts\-300"
.if ${WORDS:[1..3]:ts\-300:tu}
. warning The separator \-300 is accepted even though it is negative.
.else
@@ -198,8 +193,7 @@ WORDS= one two three four five six
# The character number is interpreted as octal number by default.
# The digit '8' is not an octal digit though.
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\8"
-# expect+1: Malformed conditional (${1 2 3:L:ts\8:tu})
+# expect+1: Bad modifier ":ts\8"
.if ${1 2 3:L:ts\8:tu}
. warning The separator \8 is accepted even though it is not octal.
.else
@@ -207,8 +201,7 @@ WORDS= one two three four five six
.endif
# Trailing characters after the octal character number are rejected.
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\100L"
-# expect+1: Malformed conditional (${1 2 3:L:ts\100L})
+# expect+1: Bad modifier ":ts\100L"
.if ${1 2 3:L:ts\100L}
. warning The separator \100L is accepted even though it contains an 'L'.
.else
@@ -216,8 +209,7 @@ WORDS= one two three four five six
.endif
# Trailing characters after the hexadecimal character number are rejected.
-# expect+2: while evaluating variable "1 2 3" with value "1 2 3": Bad modifier ":ts\x40g"
-# expect+1: Malformed conditional (${1 2 3:L:ts\x40g})
+# expect+1: Bad modifier ":ts\x40g"
.if ${1 2 3:L:ts\x40g}
. warning The separator \x40g is accepted even though it contains a 'g'.
.else
@@ -226,8 +218,7 @@ WORDS= one two three four five six
# In the :t modifier, the :t must be followed by any of A, l, s, u.
-# expect+2: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":tx"
-# expect+1: Malformed conditional (${WORDS:tx})
+# expect+1: Bad modifier ":tx"
.if ${WORDS:tx}
. error
.else
@@ -235,8 +226,7 @@ WORDS= one two three four five six
.endif
# The word separator can only be a single character.
-# expect+2: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":ts\X"
-# expect+1: Malformed conditional (${WORDS:ts\X})
+# expect+1: Bad modifier ":ts\X"
.if ${WORDS:ts\X}
. error
.else
@@ -245,8 +235,7 @@ WORDS= one two three four five six
# After the backslash, only n, t, an octal number, or x and a hexadecimal
# number are allowed.
-# expect+2: while evaluating variable "WORDS" with value "one two three four five six": Bad modifier ":t\X"
-# expect+1: Malformed conditional (${WORDS:t\X} != "anything")
+# expect+1: Bad modifier ":t\X"
.if ${WORDS:t\X} != "anything"
. info This line is not reached.
.endif
@@ -262,8 +251,7 @@ WORDS= one two three four five six
# happens for non-octal digits. From 2003.07.23.18.06.46 to
# 2016.02.27.16.20.06, the result was '1E2', since 2016.03.07.20.20.35 make no
# longer accepts this escape and complains.
-# expect+2: while evaluating "${:Ua b:ts\69}" with value "a b": Bad modifier ":ts\69"
-# expect+1: Malformed conditional (${:Ua b:ts\69})
+# expect+1: Bad modifier ":ts\69"
.if ${:Ua b:ts\69}
. error
.else
@@ -271,8 +259,7 @@ WORDS= one two three four five six
.endif
# Try whether bmake is Unicode-ready.
-# expect+2: while evaluating "${:Ua b:ts\x1F60E}" with value "a b": Invalid character number at "1F60E}"
-# expect+1: Malformed conditional (${:Ua b:ts\x1F60E})
+# expect+1: Invalid character number at "1F60E}"
.if ${:Ua b:ts\x1F60E} # U+1F60E "smiling face with sunglasses"
. error
.else
diff --git a/unit-tests/varmod.exp b/unit-tests/varmod.exp
index 0948b585a477..91968a7f310f 100644
--- a/unit-tests/varmod.exp
+++ b/unit-tests/varmod.exp
@@ -1,33 +1,44 @@
make: "varmod.mk" line 101: To escape a dollar, use \$, not $$, at "$$:L} != """
make: "varmod.mk" line 101: Invalid variable name ':', at "$:L} != """
-make: "varmod.mk" line 107: while evaluating "${:Uword:@word@${word}$@} != "word"" with value "word": Dollar followed by nothing
-make: "varmod.mk" line 117: while evaluating variable "VAR" with value "VAR": Missing delimiter ':' after modifier "P"
+make: "varmod.mk" line 107: Dollar followed by nothing
+ while evaluating "${:Uword:@word@${word}$@} != "word"" with value "word"
+make: "varmod.mk" line 117: Missing delimiter ':' after modifier "P"
+ while evaluating variable "VAR" with value "VAR"
make: "varmod.mk" line 119: Missing argument for ".error"
-make: "varmod.mk" line 126: while evaluating variable "word" with value "word": Bad modifier ":[99333000222000111000]"
-make: "varmod.mk" line 126: Malformed conditional (${word:L:[99333000222000111000]})
-make: "varmod.mk" line 130: while evaluating variable "word" with value "word": Bad modifier ":[2147483648]"
-make: "varmod.mk" line 130: Malformed conditional (${word:L:[2147483648]})
-make: "varmod.mk" line 137: while evaluating variable "word" with value "word": Invalid number "99333000222000111000}" for ':range' modifier
-make: "varmod.mk" line 137: Malformed conditional (${word:L:range=99333000222000111000})
-make: "varmod.mk" line 145: while evaluating "${:${:Ugmtime=\\}}" with value "": Invalid time value "\"
-make: "varmod.mk" line 145: Malformed conditional (${:${:Ugmtime=\\}})
-make: "varmod.mk" line 160: while evaluating variable "VAR" with value "value$": Dollar followed by nothing
-make: "varmod.mk" line 166: while evaluating variable "VAR" with value "value$": Dollar followed by nothing
-make: "varmod.mk" line 166: while evaluating variable "VAR" with value "value$ appended$": Dollar followed by nothing
-make: "varmod.mk" line 176: while evaluating variable "word" with value "word": Dollar followed by nothing
-make: "varmod.mk" line 181: while evaluating variable "word" with value "": Bad modifier ":[$]"
-make: "varmod.mk" line 181: Malformed conditional (${word:[$]})
-make: "varmod.mk" line 198: while evaluating variable "VAR" with value "value$ appended$": Dollar followed by nothing
-make: "varmod.mk" line 198: while evaluating variable "VAR" with value "value<space>appended": Invalid variable name '}', at "$} != "set""
-make: "varmod.mk" line 202: while evaluating "${:Ufallback$} != "fallback"" with value "": Invalid variable name '}', at "$} != "fallback""
-make: "varmod.mk" line 207: while evaluating variable "%y" with value "%y": Invalid time value "1000$"
-make: "varmod.mk" line 207: Malformed conditional (${%y:L:gmtime=1000$})
-make: "varmod.mk" line 214: while evaluating variable "%y" with value "%y": Invalid time value "1000$"
-make: "varmod.mk" line 214: Malformed conditional (${%y:L:localtime=1000$})
-make: "varmod.mk" line 220: while evaluating variable "word" with value "word": Dollar followed by nothing
-make: "varmod.mk" line 224: while evaluating variable "word" with value "word": Dollar followed by nothing
-make: "varmod.mk" line 229: while evaluating variable "." with value ".": Invalid argument 'fallback$' for modifier ':mtime'
-make: "varmod.mk" line 229: Malformed conditional (${.:L:mtime=fallback$})
+make: "varmod.mk" line 125: Bad modifier ":[99333000222000111000]"
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 128: Bad modifier ":[2147483648]"
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 134: Invalid number "99333000222000111000}" for ':range' modifier
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 141: Invalid time value "\"
+ while evaluating "${:${:Ugmtime=\\}}" with value ""
+make: "varmod.mk" line 156: Dollar followed by nothing
+ while evaluating variable "VAR" with value "value$"
+make: "varmod.mk" line 162: Dollar followed by nothing
+ while evaluating variable "VAR" with value "value$"
+make: "varmod.mk" line 162: Dollar followed by nothing
+ while evaluating variable "VAR" with value "value$ appended$"
+make: "varmod.mk" line 172: Dollar followed by nothing
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 176: Bad modifier ":[$]"
+ while evaluating variable "word" with value ""
+make: "varmod.mk" line 193: Dollar followed by nothing
+ while evaluating variable "VAR" with value "value$ appended$"
+make: "varmod.mk" line 193: Invalid variable name '}', at "$} != "set""
+ while evaluating variable "VAR" with value "value<space>appended"
+make: "varmod.mk" line 197: Invalid variable name '}', at "$} != "fallback""
+ while evaluating "${:Ufallback$} != "fallback"" with value ""
+make: "varmod.mk" line 201: Invalid time value "1000$"
+ while evaluating variable "%y" with value "%y"
+make: "varmod.mk" line 207: Invalid time value "1000$"
+ while evaluating variable "%y" with value "%y"
+make: "varmod.mk" line 213: Dollar followed by nothing
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 217: Dollar followed by nothing
+ while evaluating variable "word" with value "word"
+make: "varmod.mk" line 221: Invalid argument 'fallback$' for modifier ':mtime'
+ while evaluating variable "." with value "."
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varmod.mk b/unit-tests/varmod.mk
index fbb60d80680f..e0398965229b 100644
--- a/unit-tests/varmod.mk
+++ b/unit-tests/varmod.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varmod.mk,v 1.18 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varmod.mk,v 1.22 2025/01/11 20:54:46 rillig Exp $
#
# Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback.
#
@@ -103,7 +103,7 @@ DOLLAR2= ${:U\$}
.endif
# A '$' followed by nothing is an error as well.
-# expect+1: while evaluating "${:Uword:@word@${word}$@} != "word"" with value "word": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${:Uword:@word@${word}$@} != "word"
. error
.endif
@@ -113,7 +113,7 @@ DOLLAR2= ${:U\$}
# XXX: The .error should not be reached since the expression is
# malformed, and this error should be propagated up to Cond_EvalLine.
VAR= STOP
-# expect+1: while evaluating variable "VAR" with value "VAR": Missing delimiter ':' after modifier "P"
+# expect+1: Missing delimiter ':' after modifier "P"
.if ${VAR:P=RE} != "STORE"
# expect+1: Missing argument for ".error"
. error
@@ -121,27 +121,23 @@ VAR= STOP
# Test the word selection modifier ':[n]' with a very large number that is
# larger than ULONG_MAX for any supported platform.
-# expect+2: while evaluating variable "word" with value "word": Bad modifier ":[99333000222000111000]"
-# expect+1: Malformed conditional (${word:L:[99333000222000111000]})
+# expect+1: Bad modifier ":[99333000222000111000]"
.if ${word:L:[99333000222000111000]}
.endif
-# expect+2: while evaluating variable "word" with value "word": Bad modifier ":[2147483648]"
-# expect+1: Malformed conditional (${word:L:[2147483648]})
+# expect+1: Bad modifier ":[2147483648]"
.if ${word:L:[2147483648]}
.endif
# Test the range generation modifier ':range=n' with a very large number that
# is larger than SIZE_MAX for any supported platform.
-# expect+2: Malformed conditional (${word:L:range=99333000222000111000})
-# expect+1: while evaluating variable "word" with value "word": Invalid number "99333000222000111000}" for ':range' modifier
+# expect+1: Invalid number "99333000222000111000}" for ':range' modifier
.if ${word:L:range=99333000222000111000}
.endif
# In an indirect modifier, the delimiter is '\0', which at the same time marks
# the end of the string. The sequence '\\' '\0' is not an escaped delimiter,
# as it would be wrong to skip past the end of the string.
-# expect+2: while evaluating "${:${:Ugmtime=\\}}" with value "": Invalid time value "\"
-# expect+1: Malformed conditional (${:${:Ugmtime=\\}})
+# expect+1: Invalid time value "\"
.if ${:${:Ugmtime=\\}}
. error
.endif
@@ -156,13 +152,13 @@ VAR= STOP
.if ${:U:!printf '%s\n' $!} != "\$"
. error
.endif
-# expect+1: while evaluating variable "VAR" with value "value$": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${VAR::=value$} != "" || ${VAR} != "value"
. error
.endif
${:U }= <space>
-# expect+2: while evaluating variable "VAR" with value "value$": Dollar followed by nothing
-# expect+1: while evaluating variable "VAR" with value "value$ appended$": Dollar followed by nothing
+# expect+2: Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${VAR::+=appended$} != "" || ${VAR} != "value<space>appended"
. error
.endif
@@ -172,12 +168,11 @@ ${:U }= <space>
.if ${0:?then$:else$} != "else\$"
. error
.endif
-# expect+1: while evaluating variable "word" with value "word": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${word:L:@w@$w$@} != "word"
. error
.endif
-# expect+2: while evaluating variable "word" with value "": Bad modifier ":[$]"
-# expect+1: Malformed conditional (${word:[$]})
+# expect+1: Bad modifier ":[$]"
.if ${word:[$]}
. error
.else
@@ -193,39 +188,36 @@ VAR_DOLLAR= VAR$$
.if ${word:L:C,d,$,} != "wor\$"
. error
.endif
-# expect+2: while evaluating variable "VAR" with value "value$ appended$": Dollar followed by nothing
-# expect+1: while evaluating variable "VAR" with value "value<space>appended": Invalid variable name '}', at "$} != "set""
+# expect+2: Dollar followed by nothing
+# expect+1: Invalid variable name '}', at "$} != "set""
.if ${VAR:Dset$} != "set"
. error
.endif
-# expect+1: while evaluating "${:Ufallback$} != "fallback"" with value "": Invalid variable name '}', at "$} != "fallback""
+# expect+1: Invalid variable name '}', at "$} != "fallback""
.if ${:Ufallback$} != "fallback"
. error
.endif
-# expect+2: Malformed conditional (${%y:L:gmtime=1000$})
-# expect+1: while evaluating variable "%y" with value "%y": Invalid time value "1000$"
+# expect+1: Invalid time value "1000$"
.if ${%y:L:gmtime=1000$}
. error
.else
. error
.endif
-# expect+2: Malformed conditional (${%y:L:localtime=1000$})
-# expect+1: while evaluating variable "%y" with value "%y": Invalid time value "1000$"
+# expect+1: Invalid time value "1000$"
.if ${%y:L:localtime=1000$}
. error
.else
. error
.endif
-# expect+1: while evaluating variable "word" with value "word": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${word:L:Mw*$} != "word"
. error
.endif
-# expect+1: while evaluating variable "word" with value "word": Dollar followed by nothing
+# expect+1: Dollar followed by nothing
.if ${word:L:NX*$} != "word"
. error
.endif
-# expect+2: while evaluating variable "." with value ".": Invalid argument 'fallback$' for modifier ':mtime'
-# expect+1: Malformed conditional (${.:L:mtime=fallback$})
+# expect+1: Invalid argument 'fallback$' for modifier ':mtime'
.if ${.:L:mtime=fallback$}
. error
.else
diff --git a/unit-tests/varname-dot-make-level.exp b/unit-tests/varname-dot-make-level.exp
index 963b6a3a4f96..005bc85bed0f 100644
--- a/unit-tests/varname-dot-make-level.exp
+++ b/unit-tests/varname-dot-make-level.exp
@@ -1,4 +1,12 @@
level 1: variable 0, env 1
level 2: variable 1, env 2
level 3: variable 2, env 3
-exit status 0
+make: Cannot override read-only global variable ".MAKE.LEVEL.ENV" with a command line variable
+make: Fatal errors encountered -- cannot continue
+make: stopped in unit-tests
+*** Error code 1 (continuing)
+`all' not remade because of errors.
+
+Stop.
+make: stopped making "all" in unit-tests
+exit status 1
diff --git a/unit-tests/varname-dot-make-level.mk b/unit-tests/varname-dot-make-level.mk
index 246890b23171..c4b6dc90028e 100644
--- a/unit-tests/varname-dot-make-level.mk
+++ b/unit-tests/varname-dot-make-level.mk
@@ -1,9 +1,11 @@
-# $NetBSD: varname-dot-make-level.mk,v 1.3 2024/06/01 18:44:05 rillig Exp $
+# $NetBSD: varname-dot-make-level.mk,v 1.5 2024/11/23 22:59:51 rillig Exp $
#
# Tests for the special .MAKE.LEVEL variable, which informs about the
# recursion level. It is related to the environment variable MAKELEVEL,
# even though they don't have the same value.
+all: level_1 set-env
+
level_1: .PHONY
@printf 'level 1: variable %s, env %s\n' ${.MAKE.LEVEL} "$$${.MAKE.LEVEL.ENV}"
@${MAKE} -f ${MAKEFILE} level_2
@@ -20,3 +22,8 @@ level_3: .PHONY
.if make(level_2)
.unexport-env
.endif
+
+
+# expect: make: Cannot override read-only global variable ".MAKE.LEVEL.ENV" with a command line variable
+set-env:
+ @${MAKE} -f /dev/null .MAKE.LEVEL.ENV=MAKELEVEL
diff --git a/unit-tests/varname-dot-shell.exp b/unit-tests/varname-dot-shell.exp
index 7d481fdf6ff1..7cc17435895b 100755
--- a/unit-tests/varname-dot-shell.exp
+++ b/unit-tests/varname-dot-shell.exp
@@ -1,34 +1,34 @@
-Parsing line 10: ORIG_SHELL:= ${.SHELL}
+Parsing varname-dot-shell.mk:10: ORIG_SHELL:= ${.SHELL}
Global: ORIG_SHELL = # (empty)
Var_Parse: ${.SHELL} (eval-keep-dollar-and-undefined)
Global: ignoring delete '.SHELL' as it is not found
Command: .SHELL = (details omitted)
Global: ORIG_SHELL = (details omitted)
-Parsing line 12: .SHELL= overwritten
+Parsing varname-dot-shell.mk:12: .SHELL= overwritten
Global: ignoring '.SHELL = overwritten' due to a command line variable of the same name
-Parsing line 13: .if ${.SHELL} != ${ORIG_SHELL}
+Parsing varname-dot-shell.mk:13: .if ${.SHELL} != ${ORIG_SHELL}
CondParser_Eval: ${.SHELL} != ${ORIG_SHELL}
-Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined)
-Var_Parse: ${ORIG_SHELL} (eval-defined)
+Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined-loud)
+Var_Parse: ${ORIG_SHELL} (eval-defined-loud)
Comparing "(details omitted)" != "(details omitted)"
-Parsing line 19: .MAKEFLAGS: .SHELL+=appended
+Parsing varname-dot-shell.mk:19: .MAKEFLAGS: .SHELL+=appended
ParseDependency(.MAKEFLAGS: .SHELL+=appended)
Command: ignoring '.SHELL += appended' as it is read-only
-Parsing line 20: .if ${.SHELL} != ${ORIG_SHELL}
+Parsing varname-dot-shell.mk:20: .if ${.SHELL} != ${ORIG_SHELL}
CondParser_Eval: ${.SHELL} != ${ORIG_SHELL}
-Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined)
-Var_Parse: ${ORIG_SHELL} (eval-defined)
+Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined-loud)
+Var_Parse: ${ORIG_SHELL} (eval-defined-loud)
Comparing "(details omitted)" != "(details omitted)"
-Parsing line 27: .undef .SHELL
+Parsing varname-dot-shell.mk:27: .undef .SHELL
Global: ignoring delete '.SHELL' as it is not found
-Parsing line 28: .SHELL= newly overwritten
+Parsing varname-dot-shell.mk:28: .SHELL= newly overwritten
Global: ignoring '.SHELL = newly overwritten' due to a command line variable of the same name
-Parsing line 29: .if ${.SHELL} != ${ORIG_SHELL}
+Parsing varname-dot-shell.mk:29: .if ${.SHELL} != ${ORIG_SHELL}
CondParser_Eval: ${.SHELL} != ${ORIG_SHELL}
-Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined)
-Var_Parse: ${ORIG_SHELL} (eval-defined)
+Var_Parse: ${.SHELL} != ${ORIG_SHELL} (eval-defined-loud)
+Var_Parse: ${ORIG_SHELL} (eval-defined-loud)
Comparing "(details omitted)" != "(details omitted)"
-Parsing line 33: .MAKEFLAGS: -d0
+Parsing varname-dot-shell.mk:33: .MAKEFLAGS: -d0
ParseDependency(.MAKEFLAGS: -d0)
Global: .MAKEFLAGS = -r -k -d cpv -d
Global: .MAKEFLAGS = -r -k -d cpv -d 0
diff --git a/unit-tests/varname-dot-suffixes.exp b/unit-tests/varname-dot-suffixes.exp
index 230ba36d56ed..96f68d245d54 100644
--- a/unit-tests/varname-dot-suffixes.exp
+++ b/unit-tests/varname-dot-suffixes.exp
@@ -19,21 +19,21 @@ Result of ${preserve:_=.SUFFIXES} is "preserve" (eval-keep-dollar-and-undefined,
Global: _ = preserve
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0
-Var_Parse: ${1 2:L:@.SUFFIXES@${.SUFFIXES}@} != ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz" (eval-defined)
-Evaluating modifier ${1 2:L} on value "" (eval-defined, undefined)
-Result of ${1 2:L} is "1 2" (eval-defined, defined)
-Evaluating modifier ${1 2:@...} on value "1 2" (eval-defined, defined)
+Var_Parse: ${1 2:L:@.SUFFIXES@${.SUFFIXES}@} != ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz" (eval-defined-loud)
+Evaluating modifier ${1 2:L} on value "" (eval, undefined)
+Result of ${1 2:L} is "1 2" (eval, defined)
+Evaluating modifier ${1 2:@...} on value "1 2" (eval, defined)
Modifier part: ".SUFFIXES"
Modifier part: "${.SUFFIXES}"
ModifyWords: split "1 2" into 2 words
Command: ignoring '.SUFFIXES = 1' as it is read-only
-Var_Parse: ${.SUFFIXES} (eval-defined)
+Var_Parse: ${.SUFFIXES} (eval)
ModifyWord_Loop: expand "${.SUFFIXES}" to ".c .o .1 .err .tar.gz"
Command: ignoring '.SUFFIXES = 2' as it is read-only
-Var_Parse: ${.SUFFIXES} (eval-defined)
+Var_Parse: ${.SUFFIXES} (eval)
ModifyWord_Loop: expand "${.SUFFIXES}" to ".c .o .1 .err .tar.gz"
Command: ignoring delete '.SUFFIXES' as it is not found
-Result of ${1 2:@.SUFFIXES@${.SUFFIXES}@} is ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz" (eval-defined, defined)
+Result of ${1 2:@.SUFFIXES@${.SUFFIXES}@} is ".c .o .1 .err .tar.gz .c .o .1 .err .tar.gz" (eval, defined)
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0 -d v -d
Global: .MAKEFLAGS = -r -k -d v -d 0 -d v -d 0 -d v -d 0
exit status 0
diff --git a/unit-tests/varname.exp b/unit-tests/varname.exp
index 9351b0761e98..46e6d13d41bd 100644
--- a/unit-tests/varname.exp
+++ b/unit-tests/varname.exp
@@ -5,11 +5,11 @@ Var_Parse: ${VARNAME} (eval)
Global: VAR((( = 3 open parentheses
Var_Parse: ${VAR(((}}}}" != "3 open parentheses}}}" (eval)
Global: .ALLTARGETS = VAR(((=)
-make: "varname.mk" line 32: No closing parenthesis in archive specification
+make: "varname.mk" line 32: Missing ')' in archive specification
make: "varname.mk" line 32: Error in archive specification: "VAR"
-Var_Parse: ${:UVAR\(\(\(}= try2 (eval-defined)
-Evaluating modifier ${:U...} on value "" (eval-defined, undefined)
-Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (eval-defined, defined)
+Var_Parse: ${:UVAR\(\(\(}= try2 (eval)
+Evaluating modifier ${:U...} on value "" (eval, undefined)
+Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (eval, defined)
Global: .ALLTARGETS = VAR(((=) VAR\(\(\(=
make: "varname.mk" line 38: Invalid line '${:UVAR\(\(\(}= try2', expanded to 'VAR\(\(\(= try2'
Var_Parse: ${VARNAME} (eval)
diff --git a/unit-tests/varname.mk b/unit-tests/varname.mk
index cad0a10fe563..d2c36afb3aa2 100644
--- a/unit-tests/varname.mk
+++ b/unit-tests/varname.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varname.mk,v 1.14 2023/11/19 21:47:52 rillig Exp $
+# $NetBSD: varname.mk,v 1.16 2025/01/11 20:16:40 rillig Exp $
#
# Tests for special variables, such as .MAKE or .PARSEDIR.
# And for variable names in general.
@@ -27,8 +27,8 @@ ${VARNAME}= 3 open parentheses
# This is not a variable assignment since the parentheses and braces are not
# balanced. At the end of the line, there are still 3 levels open, which
# means the variable name is not finished.
-# expect+2: Error in archive specification: "VAR"
-# expect+1: No closing parenthesis in archive specification
+# expect+2: Missing ')' in archive specification
+# expect+1: Error in archive specification: "VAR"
${:UVAR(((}= try1
# On the left-hand side of a variable assignments, the backslash is not parsed
# as an escape character, therefore the parentheses still count to the nesting
diff --git a/unit-tests/varparse-dynamic.exp b/unit-tests/varparse-dynamic.exp
index caf8424fa91a..940c61163b9c 100644
--- a/unit-tests/varparse-dynamic.exp
+++ b/unit-tests/varparse-dynamic.exp
@@ -1,5 +1,5 @@
-make: "varparse-dynamic.mk" line 9: Malformed conditional (${.TARGEX})
-make: "varparse-dynamic.mk" line 12: Malformed conditional (${.TARGXX})
+make: "varparse-dynamic.mk" line 9: Variable ".TARGEX" is undefined
+make: "varparse-dynamic.mk" line 12: Variable ".TARGXX" is undefined
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varparse-dynamic.mk b/unit-tests/varparse-dynamic.mk
index 40f43b049b13..aafe3cca5329 100644
--- a/unit-tests/varparse-dynamic.mk
+++ b/unit-tests/varparse-dynamic.mk
@@ -1,14 +1,14 @@
-# $NetBSD: varparse-dynamic.mk,v 1.8 2023/11/19 22:32:44 rillig Exp $
+# $NetBSD: varparse-dynamic.mk,v 1.10 2025/01/11 21:21:34 rillig Exp $
# Before 2020-07-27, there was an off-by-one error in Var_Parse that skipped
# the last character in the variable name.
# To trigger the bug, the variable had to be undefined.
.if ${.TARGET} # exact match, may be undefined
.endif
-# expect+1: Malformed conditional (${.TARGEX})
+# expect+1: Variable ".TARGEX" is undefined
.if ${.TARGEX} # 1 character difference, must be defined
.endif
-# expect+1: Malformed conditional (${.TARGXX})
+# expect+1: Variable ".TARGXX" is undefined
.if ${.TARGXX} # 2 characters difference, must be defined
.endif
diff --git a/unit-tests/varparse-errors.exp b/unit-tests/varparse-errors.exp
index 9ca443c6fd67..b2212cb8baf0 100644
--- a/unit-tests/varparse-errors.exp
+++ b/unit-tests/varparse-errors.exp
@@ -1,25 +1,45 @@
-make: "varparse-errors.mk" line 38: while evaluating "${:U:Z}" with value "": Unknown modifier "Z"
-make: "varparse-errors.mk" line 47: while evaluating "${:U:Z}post" with value "": Unknown modifier "Z"
-make: "varparse-errors.mk" line 75: while evaluating "${:U:OX:U${IND}} ${:U:OX:U${IND}}" with value "": Bad modifier ":OX"
-make: "varparse-errors.mk" line 75: Undefined variable "${:U:OX"
-make: "varparse-errors.mk" line 75: while evaluating variable "IND" with value "${:OX}": while evaluating "${:OX}" with value "": Bad modifier ":OX"
-make: "varparse-errors.mk" line 75: while evaluating "${:U:OX:U${IND}}" with value "": Bad modifier ":OX"
-make: "varparse-errors.mk" line 75: Undefined variable "${:U:OX"
-make: "varparse-errors.mk" line 75: while evaluating variable "IND" with value "${:OX}": while evaluating "${:OX}" with value "": Bad modifier ":OX"
-make: "varparse-errors.mk" line 83: while evaluating "${:U:Q" with value "": Unclosed expression, expecting '}' for modifier "Q"
-make: "varparse-errors.mk" line 85: while evaluating "${:U:sh" with value "": Unclosed expression, expecting '}' for modifier "sh"
-make: "varparse-errors.mk" line 87: while evaluating "${:U:tA" with value "": Unclosed expression, expecting '}' for modifier "tA"
-make: "varparse-errors.mk" line 89: while evaluating "${:U:tsX" with value "": Unclosed expression, expecting '}' for modifier "tsX"
-make: "varparse-errors.mk" line 91: while evaluating "${:U:ts" with value "": Unclosed expression, expecting '}' for modifier "ts"
-make: "varparse-errors.mk" line 93: while evaluating "${:U:ts\040" with value "": Unclosed expression, expecting '}' for modifier "ts\040"
-make: "varparse-errors.mk" line 95: while evaluating "${:U:u" with value "": Unclosed expression, expecting '}' for modifier "u"
-make: "varparse-errors.mk" line 97: while evaluating "${:U:H" with value ".": Unclosed expression, expecting '}' for modifier "H"
-make: "varparse-errors.mk" line 99: while evaluating "${:U:[1]" with value "": Unclosed expression, expecting '}' for modifier "[1]"
-make: "varparse-errors.mk" line 101: while evaluating "${:U:hash" with value "b2af338b": Unclosed expression, expecting '}' for modifier "hash"
-make: "varparse-errors.mk" line 103: while evaluating "${:U:range" with value "1": Unclosed expression, expecting '}' for modifier "range"
-make: "varparse-errors.mk" line 105: while evaluating "${:U:_" with value "": Unclosed expression, expecting '}' for modifier "_"
-make: "varparse-errors.mk" line 107: while evaluating "${:U:gmtime" with value "<timestamp>": Unclosed expression, expecting '}' for modifier "gmtime"
-make: "varparse-errors.mk" line 109: while evaluating "${:U:localtime" with value "<timestamp>": Unclosed expression, expecting '}' for modifier "localtime"
+make: "varparse-errors.mk" line 38: Unknown modifier "Z"
+ while evaluating "${:U:Z}" with value ""
+make: "varparse-errors.mk" line 47: Unknown modifier "Z"
+ while evaluating "${:U:Z}post" with value ""
+make: "varparse-errors.mk" line 73: Bad modifier ":OX"
+ while evaluating "${:U:OX:U${IND}} ${:U:OX:U${IND}}" with value ""
+make: "varparse-errors.mk" line 73: Bad modifier ":OX"
+ while evaluating "${:OX}" with value ""
+ while evaluating variable "IND" with value "${:OX}"
+make: "varparse-errors.mk" line 73: Bad modifier ":OX"
+ while evaluating "${:U:OX:U${IND}}" with value ""
+make: "varparse-errors.mk" line 73: Bad modifier ":OX"
+ while evaluating "${:OX}" with value ""
+ while evaluating variable "IND" with value "${:OX}"
+make: "varparse-errors.mk" line 81: Unclosed expression, expecting '}' for modifier "Q"
+ while evaluating "${:U:Q" with value ""
+make: "varparse-errors.mk" line 83: Unclosed expression, expecting '}' for modifier "sh"
+ while evaluating "${:U:sh" with value ""
+make: "varparse-errors.mk" line 85: Unclosed expression, expecting '}' for modifier "tA"
+ while evaluating "${:U:tA" with value ""
+make: "varparse-errors.mk" line 87: Unclosed expression, expecting '}' for modifier "tsX"
+ while evaluating "${:U:tsX" with value ""
+make: "varparse-errors.mk" line 89: Unclosed expression, expecting '}' for modifier "ts"
+ while evaluating "${:U:ts" with value ""
+make: "varparse-errors.mk" line 91: Unclosed expression, expecting '}' for modifier "ts\040"
+ while evaluating "${:U:ts\040" with value ""
+make: "varparse-errors.mk" line 93: Unclosed expression, expecting '}' for modifier "u"
+ while evaluating "${:U:u" with value ""
+make: "varparse-errors.mk" line 95: Unclosed expression, expecting '}' for modifier "H"
+ while evaluating "${:U:H" with value "."
+make: "varparse-errors.mk" line 97: Unclosed expression, expecting '}' for modifier "[1]"
+ while evaluating "${:U:[1]" with value ""
+make: "varparse-errors.mk" line 99: Unclosed expression, expecting '}' for modifier "hash"
+ while evaluating "${:U:hash" with value "b2af338b"
+make: "varparse-errors.mk" line 101: Unclosed expression, expecting '}' for modifier "range"
+ while evaluating "${:U:range" with value "1"
+make: "varparse-errors.mk" line 103: Unclosed expression, expecting '}' for modifier "_"
+ while evaluating "${:U:_" with value ""
+make: "varparse-errors.mk" line 105: Unclosed expression, expecting '}' for modifier "gmtime"
+ while evaluating "${:U:gmtime" with value "<timestamp>"
+make: "varparse-errors.mk" line 107: Unclosed expression, expecting '}' for modifier "localtime"
+ while evaluating "${:U:localtime" with value "<timestamp>"
make: Fatal errors encountered -- cannot continue
make: stopped in unit-tests
exit status 1
diff --git a/unit-tests/varparse-errors.mk b/unit-tests/varparse-errors.mk
index d10160b816e5..b28ac1ec5dc1 100644
--- a/unit-tests/varparse-errors.mk
+++ b/unit-tests/varparse-errors.mk
@@ -1,4 +1,4 @@
-# $NetBSD: varparse-errors.mk,v 1.17 2024/07/05 19:47:22 rillig Exp $
+# $NetBSD: varparse-errors.mk,v 1.19 2024/08/29 20:20:37 rillig Exp $
# Tests for parsing and evaluating all kinds of expressions.
#
@@ -34,7 +34,7 @@ ERR_EVAL= An evaluation error ${:Uvalue:C,.,\3,}.
# As of 2020-12-01, errors in the variable name are silently ignored.
# Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result
# in an error message and a non-zero exit status.
-# expect+1: while evaluating "${:U:Z}" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
VAR.${:U:Z}= unknown modifier in the variable name
.if ${VAR.} != "unknown modifier in the variable name"
. error
@@ -43,7 +43,7 @@ VAR.${:U:Z}= unknown modifier in the variable name
# As of 2020-12-01, errors in the variable name are silently ignored.
# Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result
# in an error message and a non-zero exit status.
-# expect+1: while evaluating "${:U:Z}post" with value "": Unknown modifier "Z"
+# expect+1: Unknown modifier "Z"
VAR.${:U:Z}post= unknown modifier with text in the variable name
.if ${VAR.post} != "unknown modifier with text in the variable name"
. error
@@ -66,12 +66,10 @@ VAR.${:U:Z}post= unknown modifier with text in the variable name
#
#.MAKEFLAGS: -dv
IND= ${:OX}
-# expect+6: while evaluating "${:U:OX:U${IND}} ${:U:OX:U${IND}}" with value "": Bad modifier ":OX"
-# expect+5: while evaluating "${:U:OX:U${IND}}" with value "": Bad modifier ":OX"
-# expect+4: Undefined variable "${:U:OX"
-# expect+3: while evaluating variable "IND" with value "${:OX}": while evaluating "${:OX}" with value "": Bad modifier ":OX"
-# expect+2: Undefined variable "${:U:OX"
-# expect+1: while evaluating variable "IND" with value "${:OX}": while evaluating "${:OX}" with value "": Bad modifier ":OX"
+# expect+4: Bad modifier ":OX"
+# expect+3: Bad modifier ":OX"
+# expect+2: Bad modifier ":OX"
+# expect+1: Bad modifier ":OX"
_:= ${:U:OX:U${IND}} ${:U:OX:U${IND}}
#.MAKEFLAGS: -d0
@@ -79,31 +77,31 @@ _:= ${:U:OX:U${IND}} ${:U:OX:U${IND}}
# Before var.c 1.032 from 2022-08-24, make complained about 'Unknown modifier'
# or 'Bad modifier' when in fact the modifier was entirely correct, it was
# just not delimited by either ':' or '}' but instead by '\0'.
-# expect+1: while evaluating "${:U:Q" with value "": Unclosed expression, expecting '}' for modifier "Q"
+# expect+1: Unclosed expression, expecting '}' for modifier "Q"
UNCLOSED:= ${:U:Q
-# expect+1: while evaluating "${:U:sh" with value "": Unclosed expression, expecting '}' for modifier "sh"
+# expect+1: Unclosed expression, expecting '}' for modifier "sh"
UNCLOSED:= ${:U:sh
-# expect+1: while evaluating "${:U:tA" with value "": Unclosed expression, expecting '}' for modifier "tA"
+# expect+1: Unclosed expression, expecting '}' for modifier "tA"
UNCLOSED:= ${:U:tA
-# expect+1: while evaluating "${:U:tsX" with value "": Unclosed expression, expecting '}' for modifier "tsX"
+# expect+1: Unclosed expression, expecting '}' for modifier "tsX"
UNCLOSED:= ${:U:tsX
-# expect+1: while evaluating "${:U:ts" with value "": Unclosed expression, expecting '}' for modifier "ts"
+# expect+1: Unclosed expression, expecting '}' for modifier "ts"
UNCLOSED:= ${:U:ts
-# expect+1: while evaluating "${:U:ts\040" with value "": Unclosed expression, expecting '}' for modifier "ts\040"
+# expect+1: Unclosed expression, expecting '}' for modifier "ts\040"
UNCLOSED:= ${:U:ts\040
-# expect+1: while evaluating "${:U:u" with value "": Unclosed expression, expecting '}' for modifier "u"
+# expect+1: Unclosed expression, expecting '}' for modifier "u"
UNCLOSED:= ${:U:u
-# expect+1: while evaluating "${:U:H" with value ".": Unclosed expression, expecting '}' for modifier "H"
+# expect+1: Unclosed expression, expecting '}' for modifier "H"
UNCLOSED:= ${:U:H
-# expect+1: while evaluating "${:U:[1]" with value "": Unclosed expression, expecting '}' for modifier "[1]"
+# expect+1: Unclosed expression, expecting '}' for modifier "[1]"
UNCLOSED:= ${:U:[1]
-# expect+1: while evaluating "${:U:hash" with value "b2af338b": Unclosed expression, expecting '}' for modifier "hash"
+# expect+1: Unclosed expression, expecting '}' for modifier "hash"
UNCLOSED:= ${:U:hash
-# expect+1: while evaluating "${:U:range" with value "1": Unclosed expression, expecting '}' for modifier "range"
+# expect+1: Unclosed expression, expecting '}' for modifier "range"
UNCLOSED:= ${:U:range
-# expect+1: while evaluating "${:U:_" with value "": Unclosed expression, expecting '}' for modifier "_"
+# expect+1: Unclosed expression, expecting '}' for modifier "_"
UNCLOSED:= ${:U:_
-# expect+1: while evaluating "${:U:gmtime" with value "<timestamp>": Unclosed expression, expecting '}' for modifier "gmtime"
+# expect+1: Unclosed expression, expecting '}' for modifier "gmtime"
UNCLOSED:= ${:U:gmtime
-# expect+1: while evaluating "${:U:localtime" with value "<timestamp>": Unclosed expression, expecting '}' for modifier "localtime"
+# expect+1: Unclosed expression, expecting '}' for modifier "localtime"
UNCLOSED:= ${:U:localtime
diff --git a/var.c b/var.c
index 3d611bdd9b5d..eed451779673 100644
--- a/var.c
+++ b/var.c
@@ -1,4 +1,4 @@
-/* $NetBSD: var.c,v 1.1135 2024/07/09 17:07:23 rillig Exp $ */
+/* $NetBSD: var.c,v 1.1144 2025/01/11 21:21:33 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990, 1993
@@ -143,7 +143,7 @@
#endif
/* "@(#)var.c 8.3 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: var.c,v 1.1135 2024/07/09 17:07:23 rillig Exp $");
+MAKE_RCSID("$NetBSD: var.c,v 1.1144 2025/01/11 21:21:33 rillig Exp $");
/*
* Variables are defined using one of the VAR=value assignments. Their
@@ -290,7 +290,6 @@ typedef struct {
EvalStackElement *elems;
size_t len;
size_t cap;
- Buffer details;
} EvalStack;
/* Whether we have replaced the original environ (which we cannot free). */
@@ -354,6 +353,7 @@ static const char VarEvalMode_Name[][32] = {
"parse",
"parse-balanced",
"eval",
+ "eval-defined-loud",
"eval-defined",
"eval-keep-undefined",
"eval-keep-dollar-and-undefined",
@@ -383,15 +383,12 @@ EvalStack_Pop(void)
evalStack.len--;
}
-const char *
-EvalStack_Details(void)
+void
+EvalStack_PrintDetails(void)
{
size_t i;
- Buffer *buf = &evalStack.details;
-
- buf->len = 0;
- for (i = 0; i < evalStack.len; i++) {
+ for (i = evalStack.len; i > 0; i--) {
static const char descr[][42] = {
"in target",
"while evaluating variable",
@@ -401,19 +398,16 @@ EvalStack_Details(void)
"while evaluating",
"while parsing",
};
- EvalStackElement *elem = evalStack.elems + i;
+ EvalStackElement *elem = evalStack.elems + i - 1;
EvalStackElementKind kind = elem->kind;
- Buf_AddStr(buf, descr[kind]);
- Buf_AddStr(buf, " \"");
- Buf_AddStr(buf, elem->str);
- if (elem->value != NULL
- && (kind == VSK_VARNAME || kind == VSK_EXPR)) {
- Buf_AddStr(buf, "\" with value \"");
- Buf_AddStr(buf, elem->value->str);
- }
- Buf_AddStr(buf, "\": ");
+ const char* value = elem->value != NULL
+ && (kind == VSK_VARNAME || kind == VSK_EXPR)
+ ? elem->value->str : NULL;
+
+ debug_printf("\t%s \"%s%s%s\"\n", descr[kind], elem->str,
+ value != NULL ? "\" with value \"" : "",
+ value != NULL ? value : "");
}
- return buf->len > 0 ? buf->data : "";
}
static Var *
@@ -984,7 +978,7 @@ UnexportVar(Substring varname, UnexportWhat what)
}
static void
-UnexportVars(FStr *varnames, UnexportWhat what)
+UnexportVars(const char *varnames, UnexportWhat what)
{
size_t i;
SubstringWords words;
@@ -992,7 +986,7 @@ UnexportVars(FStr *varnames, UnexportWhat what)
if (what == UNEXPORT_ENV)
ClearEnv();
- words = Substring_Words(varnames->str, false);
+ words = Substring_Words(varnames, false);
for (i = 0; i < words.len; i++)
UnexportVar(words.words[i], what);
SubstringWords_Free(words);
@@ -1009,7 +1003,7 @@ Var_UnExport(bool isEnv, const char *arg)
FStr varnames;
GetVarnamesToUnexport(isEnv, arg, &varnames, &what);
- UnexportVars(&varnames, what);
+ UnexportVars(varnames.str, what);
FStr_Done(&varnames);
}
@@ -1057,7 +1051,14 @@ Var_SetWithFlags(GNode *scope, const char *name, const char *val,
*
* See ExistsInCmdline.
*/
- Var_Delete(SCOPE_GLOBAL, name);
+ Var *gl = VarFind(name, SCOPE_GLOBAL, false);
+ if (gl != NULL && gl->readOnlyLoud)
+ Parse_Error(PARSE_FATAL,
+ "Cannot override "
+ "read-only global variable \"%s\" "
+ "with a command line variable", name);
+ else
+ Var_Delete(SCOPE_GLOBAL, name);
}
if (strcmp(name, ".SUFFIXES") == 0) {
/* special: treat as read-only */
@@ -1339,12 +1340,6 @@ VarEvalMode_WithoutKeepDollar(VarEvalMode emode)
? VARE_EVAL_KEEP_UNDEFINED : emode;
}
-static VarEvalMode
-VarEvalMode_UndefOk(VarEvalMode emode)
-{
- return emode == VARE_EVAL_DEFINED ? VARE_EVAL : emode;
-}
-
static bool
VarEvalMode_ShouldEval(VarEvalMode emode)
{
@@ -3491,8 +3486,9 @@ ApplyModifier_IfElse(const char **pp, ModChain *ch)
VarEvalMode then_emode = VARE_PARSE;
VarEvalMode else_emode = VARE_PARSE;
+ int parseErrorsBefore = parseErrors, parseErrorsAfter = parseErrors;
- CondResult cond_rc = CR_TRUE; /* just not CR_ERROR */
+ CondResult cond_rc = CR_TRUE; /* anything other than CR_ERROR */
if (Expr_ShouldEval(expr)) {
evalStack.elems[evalStack.len - 1].kind = VSK_COND;
cond_rc = Cond_EvalCondition(expr->name);
@@ -3500,6 +3496,7 @@ ApplyModifier_IfElse(const char **pp, ModChain *ch)
then_emode = expr->emode;
if (cond_rc == CR_FALSE)
else_emode = expr->emode;
+ parseErrorsAfter = parseErrors;
}
evalStack.elems[evalStack.len - 1].kind = VSK_COND_THEN;
@@ -3519,7 +3516,8 @@ ApplyModifier_IfElse(const char **pp, ModChain *ch)
if (cond_rc == CR_ERROR) {
evalStack.elems[evalStack.len - 1].kind = VSK_COND;
- Parse_Error(PARSE_FATAL, "Bad condition");
+ if (parseErrorsAfter == parseErrorsBefore)
+ Parse_Error(PARSE_FATAL, "Bad condition");
LazyBuf_Done(&thenBuf);
LazyBuf_Done(&elseBuf);
return AMR_CLEANUP;
@@ -3811,7 +3809,9 @@ ApplyModifier_SunShell(const char **pp, ModChain *ch)
static bool
ShouldLogInSimpleFormat(const Expr *expr)
{
- return (expr->emode == VARE_EVAL || expr->emode == VARE_EVAL_DEFINED)
+ return (expr->emode == VARE_EVAL
+ || expr->emode == VARE_EVAL_DEFINED
+ || expr->emode == VARE_EVAL_DEFINED_LOUD)
&& expr->defined == DEF_REGULAR;
}
@@ -4298,9 +4298,12 @@ ParseVarnameShort(char varname, const char **pp, GNode *scope,
val = UndefinedShortVarValue(varname, scope);
if (val == NULL)
- val = emode == VARE_EVAL_DEFINED ? var_Error : varUndefined;
+ val = emode == VARE_EVAL_DEFINED
+ || emode == VARE_EVAL_DEFINED_LOUD
+ ? var_Error : varUndefined;
- if (opts.strict && val == var_Error) {
+ if ((opts.strict || emode == VARE_EVAL_DEFINED_LOUD)
+ && val == var_Error) {
Parse_Error(PARSE_FATAL,
"Variable \"%s\" is undefined", name);
}
@@ -4343,7 +4346,8 @@ EvalUndefined(bool dynamic, const char *start, const char *p,
if (dynamic)
return FStr_InitOwn(bmake_strsedup(start, p));
- if (emode == VARE_EVAL_DEFINED && opts.strict) {
+ if (emode == VARE_EVAL_DEFINED_LOUD
+ || (emode == VARE_EVAL_DEFINED && opts.strict)) {
Parse_Error(PARSE_FATAL,
"Variable \"%.*s\" is undefined",
(int)Substring_Length(varname), varname.start);
@@ -4351,7 +4355,8 @@ EvalUndefined(bool dynamic, const char *start, const char *p,
}
return FStr_InitRefer(
- emode == VARE_EVAL_DEFINED ? var_Error : varUndefined);
+ emode == VARE_EVAL_DEFINED_LOUD || emode == VARE_EVAL_DEFINED
+ ? var_Error : varUndefined);
}
/*
@@ -4366,6 +4371,7 @@ ParseVarnameLong(
char startc,
GNode *scope,
VarEvalMode emode,
+ VarEvalMode nested_emode,
const char **out_false_pp,
FStr *out_false_val,
@@ -4389,7 +4395,7 @@ ParseVarnameLong(
char endc = startc == '(' ? ')' : '}';
p += 2; /* skip "${" or "$(" or "y(" */
- ParseVarname(&p, startc, endc, scope, emode, &varname);
+ ParseVarname(&p, startc, endc, scope, nested_emode, &varname);
name = LazyBuf_Get(&varname);
if (*p == ':')
@@ -4542,8 +4548,6 @@ Var_Parse_U(const char **pp, VarEvalMode emode, FStr *out_value)
* was undefined, emode was not VARE_EVAL_DEFINED,
* and none of the modifiers turned the undefined
* expression into a defined expression.
- * XXX: It is not guaranteed that an error message has
- * been printed.
*/
FStr
Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
@@ -4561,7 +4565,9 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
bool dynamic;
const char *extramodifiers;
Var *v;
- Expr expr = Expr_Init(NULL, FStr_InitRefer(NULL), emode,
+ Expr expr = Expr_Init(NULL, FStr_InitRefer(NULL),
+ emode == VARE_EVAL_DEFINED || emode == VARE_EVAL_DEFINED_LOUD
+ ? VARE_EVAL : emode,
scope, DEF_REGULAR);
FStr val;
@@ -4585,7 +4591,7 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
haveModifier = false;
p++;
} else {
- if (!ParseVarnameLong(&p, startc, scope, emode,
+ if (!ParseVarnameLong(&p, startc, scope, emode, expr.emode,
pp, &val,
&endc, &v, &haveModifier, &extramodifiers,
&dynamic, &expr.defined))
@@ -4594,11 +4600,13 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
expr.name = v->name.str;
if (v->inUse && VarEvalMode_ShouldEval(emode)) {
- if (scope->fname != NULL) {
- fprintf(stderr, "In a command near ");
- PrintLocation(stderr, false, scope);
- }
- Fatal("Variable %s is recursive.", v->name.str);
+ Parse_Error(PARSE_FATAL, "Variable %s is recursive.",
+ v->name.str);
+ FStr_Done(&val);
+ if (*p != '\0')
+ p++;
+ *pp = p;
+ return FStr_InitRefer(var_Error);
}
/*
@@ -4635,11 +4643,8 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
if (VarEvalMode_ShouldEval(emode) &&
strchr(Expr_Str(&expr), '$') != NULL) {
char *expanded;
- VarEvalMode nested_emode = emode;
- if (opts.strict)
- nested_emode = VarEvalMode_UndefOk(nested_emode);
v->inUse = true;
- expanded = Var_Subst(Expr_Str(&expr), scope, nested_emode);
+ expanded = Var_Subst(Expr_Str(&expr), scope, expr.emode);
v->inUse = false;
/* TODO: handle errors */
Expr_SetValueOwn(&expr, expanded);
@@ -4664,13 +4669,9 @@ Var_Parse(const char **pp, GNode *scope, VarEvalMode emode)
if (dynamic)
Expr_SetValueOwn(&expr, bmake_strsedup(start, p));
else {
- /*
- * The expression is still undefined, therefore
- * discard the actual value and return an error marker
- * instead.
- */
Expr_SetValueRefer(&expr,
emode == VARE_EVAL_DEFINED
+ || emode == VARE_EVAL_DEFINED_LOUD
? var_Error : varUndefined);
}
}
@@ -4699,8 +4700,7 @@ VarSubstDollarDollar(const char **pp, Buffer *res, VarEvalMode emode)
}
static void
-VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
- VarEvalMode emode, bool *inout_errorReported)
+VarSubstExpr(const char **pp, Buffer *buf, GNode *scope, VarEvalMode emode)
{
const char *p = *pp;
const char *nested_p = p;
@@ -4708,28 +4708,8 @@ VarSubstExpr(const char **pp, Buffer *buf, GNode *scope,
/* TODO: handle errors */
if (val.str == var_Error || val.str == varUndefined) {
- if (!VarEvalMode_ShouldKeepUndef(emode)) {
- p = nested_p;
- } else if (val.str == var_Error) {
-
- /*
- * FIXME: The condition 'val.str == var_Error' doesn't
- * mean there was an undefined variable. It could
- * equally well be a parse error; see
- * unit-tests/varmod-order.mk.
- */
-
- /*
- * If variable is undefined, complain and skip the
- * variable. The complaint will stop us from doing
- * anything when the file is parsed.
- */
- if (!*inout_errorReported) {
- Parse_Error(PARSE_FATAL,
- "Undefined variable \"%.*s\"",
- (int)(nested_p - p), p);
- *inout_errorReported = true;
- }
+ if (!VarEvalMode_ShouldKeepUndef(emode)
+ || val.str == var_Error) {
p = nested_p;
} else {
/*
@@ -4783,20 +4763,13 @@ Var_Subst(const char *str, GNode *scope, VarEvalMode emode)
const char *p = str;
Buffer res;
- /*
- * Set true if an error has already been reported, to prevent a
- * plethora of messages when recursing
- */
- static bool errorReported;
-
Buf_Init(&res);
- errorReported = false;
while (*p != '\0') {
if (p[0] == '$' && p[1] == '$')
VarSubstDollarDollar(&p, &res, emode);
else if (p[0] == '$')
- VarSubstExpr(&p, &res, scope, emode, &errorReported);
+ VarSubstExpr(&p, &res, scope, emode);
else
VarSubstPlain(&p, &res);
}