diff options
author | Simon J. Gerraty <sjg@FreeBSD.org> | 2020-11-20 06:02:31 +0000 |
---|---|---|
committer | Simon J. Gerraty <sjg@FreeBSD.org> | 2020-11-20 06:02:31 +0000 |
commit | e2eeea75eb8b6dd50c1298067a0655880d186734 (patch) | |
tree | 213e83f0d8e9a7e187083d9c33d8af6651cedeb2 /contrib/bmake/unit-tests | |
parent | 466d0a2572130a2e393d6fffef5c716a8f867367 (diff) | |
parent | 1b65f0bd2bda7121a90f8cb4c1cacaa20f1b681d (diff) |
Merge bmake-20201117
o allow env var MAKE_OBJDIR_CHECK_WRITABLE=no to skip writable
checks in InitObjdir. Explicit .OBJDIR target always allows
read-only directory.
o More code cleanup and refactoring.
o More unit tests
MFC after: 1 week
Notes
Notes:
svn path=/head/; revision=367863
Diffstat (limited to 'contrib/bmake/unit-tests')
201 files changed, 2452 insertions, 674 deletions
diff --git a/contrib/bmake/unit-tests/Makefile b/contrib/bmake/unit-tests/Makefile index 0940d55671ee..cca63155e868 100644 --- a/contrib/bmake/unit-tests/Makefile +++ b/contrib/bmake/unit-tests/Makefile @@ -1,6 +1,6 @@ -# $Id: Makefile,v 1.107 2020/11/02 00:40:25 sjg Exp $ +# $Id: Makefile,v 1.115 2020/11/18 04:01:07 sjg Exp $ # -# $NetBSD: Makefile,v 1.181 2020/11/01 19:02:22 rillig Exp $ +# $NetBSD: Makefile,v 1.206 2020/11/18 01:12:00 sjg Exp $ # # Unit tests for make(1) # @@ -36,8 +36,11 @@ # src/tests/usr.bin/make/t_make.sh as well. #TESTS+= archive TESTS+= archive-suffix +TESTS+= cmd-errors +TESTS+= cmd-errors-lint TESTS+= cmd-interrupt TESTS+= cmdline +TESTS+= cmdline-undefined TESTS+= comment TESTS+= cond-cmp-numeric TESTS+= cond-cmp-numeric-eq @@ -58,8 +61,10 @@ TESTS+= cond-func-target TESTS+= cond-late TESTS+= cond-op TESTS+= cond-op-and +TESTS+= cond-op-and-lint TESTS+= cond-op-not TESTS+= cond-op-or +TESTS+= cond-op-or-lint TESTS+= cond-op-parentheses TESTS+= cond-short TESTS+= cond-token-number @@ -144,6 +149,7 @@ TESTS+= directive-for TESTS+= directive-for-generating-endif TESTS+= directive-hyphen-include TESTS+= directive-if +TESTS+= directive-if-nested TESTS+= directive-ifdef TESTS+= directive-ifmake TESTS+= directive-ifndef @@ -156,7 +162,6 @@ TESTS+= directive-undef TESTS+= directive-unexport TESTS+= directive-unexport-env TESTS+= directive-warning -TESTS+= directives TESTS+= dollar TESTS+= doterror TESTS+= dotwait @@ -169,9 +174,11 @@ TESTS+= export-env TESTS+= export-variants TESTS+= forloop TESTS+= forsubst +TESTS+= gnode-submake TESTS+= hanoi-include TESTS+= impsrc TESTS+= include-main +TESTS+= job-flags #TESTS+= job-output-long-lines TESTS+= lint TESTS+= make-exported @@ -180,6 +187,7 @@ TESTS+= modmatch TESTS+= modmisc TESTS+= modts TESTS+= modword +TESTS+= objdir-writable TESTS+= opt TESTS+= opt-backwards TESTS+= opt-chdir @@ -223,6 +231,7 @@ TESTS+= opt-query TESTS+= opt-raw TESTS+= opt-silent TESTS+= opt-touch +TESTS+= opt-touch-jobs TESTS+= opt-tracefile TESTS+= opt-var-expanded TESTS+= opt-var-literal @@ -248,7 +257,9 @@ TESTS+= sh-multi-line TESTS+= sh-single-line TESTS+= shell-csh TESTS+= shell-custom +.if exists(/bin/ksh) TESTS+= shell-ksh +.endif TESTS+= shell-sh TESTS+= suff-add-later TESTS+= suff-clear-regular @@ -256,6 +267,7 @@ TESTS+= suff-clear-single TESTS+= suff-lookup TESTS+= suff-main TESTS+= suff-rebuild +TESTS+= suff-self TESTS+= suff-transform-endless TESTS+= suff-transform-expand TESTS+= suff-transform-select @@ -366,38 +378,54 @@ TESTS+= varname-makeflags TESTS+= varname-pwd TESTS+= varname-vpath TESTS+= varparse-dynamic +TESTS+= varparse-errors TESTS+= varparse-mod TESTS+= varparse-undef-partial TESTS+= varquote -TESTS+= varshell +# Ideas for more tests: +# char-0020-space.mk +# char-005C-backslash.mk +# escape-cond-str.mk +# escape-cond-func-arg.mk +# escape-cond-func-arg.mk +# escape-varmod.mk +# escape-varmod-define.mk +# escape-varmod-match.mk +# escape-varname.mk +# escape-varassign-varname.mk +# escape-varassign-varname-cmdline.mk +# escape-varassign-value.mk +# escape-varassign-value-cmdline.mk +# escape-dependency-source.mk +# escape-dependency-target.mk +# escape-for-varname.mk +# escape-for-item.mk +# posix-*.mk (see posix.mk and posix1.mk) + +.if ${.OBJDIR} != ${.CURDIR} +RO_OBJDIR:= ${.OBJDIR}/roobj +.else +RO_OBJDIR:= ${TMPDIR:U/tmp}/roobj +.endif # Additional environment variables for some of the tests. # The base environment is -i PATH="$PATH". +ENV.depsrc-optional+= TZ=UTC ENV.envfirst= FROM_ENV=value-from-env +ENV.objdir-writable+= RO_OBJDIR=${RO_OBJDIR} ENV.varmisc= FROM_ENV=env ENV.varmisc+= FROM_ENV_BEFORE=env ENV.varmisc+= FROM_ENV_AFTER=env ENV.varmod-localtime+= TZ=Europe/Berlin +ENV.varname-vpath+= VPATH=varname-vpath.dir:varname-vpath.dir2 # Override make flags for some of the tests; default is -k. # If possible, write ".MAKEFLAGS: -dv" in the test .mk file instead of # settings FLAGS.test=-dv here, since that is closer to the test code. FLAGS.cond-func-make= via-cmdline FLAGS.directive-ifmake= first second -FLAGS.doterror= # none -FLAGS.envfirst= -e -FLAGS.export= # none -FLAGS.opt-ignore= -i -FLAGS.opt-keep-going= -k -FLAGS.opt-no-action= -n -FLAGS.opt-query= -q -FLAGS.opt-var-expanded= -v VAR -v VALUE -FLAGS.opt-var-literal= -V VAR -V VALUE -FLAGS.opt-warnings-as-errors= -W -FLAGS.order= -j1 -FLAGS.recursive= -dL -FLAGS.sh-leading-plus= -n -FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmline-plain' +FLAGS.doterror= # none, especially not -k +FLAGS.varname-empty= -dv '$${:U}=cmdline-u' '=cmdline-plain' # Some tests need extra postprocessing. SED_CMDS.export= \ @@ -406,6 +434,9 @@ SED_CMDS.export= \ .for t in export-all export-env SED_CMDS.$t= ${SED_CMDS.export} .endfor +SED_CMDS.directive-export-gmake= \ + ${:D dash is a pain } \ + -e /non-zero/d SED_CMDS.job-output-long-lines= \ ${:D Job separators on their own line are ok. } \ -e '/^--- job-[ab] ---$$/d' \ @@ -417,6 +448,7 @@ SED_CMDS.job-output-long-lines= \ ${:D marker should always be at the beginning of the line. } \ -e '/^aa*--- job-b ---$$/d' \ -e '/^bb*--- job-a ---$$/d' +SED_CMDS.objdir-writable= -e 's,${RO_OBJDIR},OBJDIR/roobj,g' SED_CMDS.opt-debug-graph1= \ -e 's,${.CURDIR},CURDIR,' SED_CMDS.opt-debug-graph1+= \ @@ -428,11 +460,14 @@ SED_CMDS.opt-debug-jobs+= -e 's,Process [0-9][0-9]*,Process <pid>,' SED_CMDS.opt-debug-jobs+= -e 's,JobFinish: [0-9][0-9]*,JobFinish: <pid>,' # The "-q" may be there or not, see jobs.c, variable shells. SED_CMDS.opt-debug-jobs+= -e 's,^\(.Command: sh\) -q,\1,' +SED_CMDS.var-op-shell+= -e 's,^${.SHELL:T}: ,,' +SED_CMDS.var-op-shell+= -e '/command/{ s,^[1-9]: ,,;s,No such.*,not found,; }' +SED_CMDS.vardebug= \ + ${:D canonicalize .SHELL } \ + -e 's,${.SHELL},</path/to/shell>,' SED_CMDS.varmod-subst-regex+= \ -e 's,\(Regex compilation error:\).*,\1 (details omitted),' SED_CMDS.varmod-edge+= -e 's, line [0-9]*:, line omitted:,' -SED_CMDS.varshell+= -e 's,^${.SHELL:T}: ,,' -SED_CMDS.varshell+= -e '/command/s,No such.*,not found,' SED_CMDS.varname-dot-parsedir= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,' SED_CMDS.varname-dot-parsefile= -e '/in some cases/ s,^make: "[^"]*,make: "<normalized>,' SED_CMDS.varname-dot-shell= -e 's, = /[^ ]*, = (details omitted),g' @@ -442,7 +477,7 @@ SED_CMDS.varname-dot-shell+= -e 's,\[/[^] ]*\],[(details omitted)],g' # Some tests need an additional round of postprocessing. POSTPROC.deptgt-suffixes= \ ${TOOL_SED} -n -e '/^\#\*\*\* Suffixes/,/^\#\*/p' -POSTPROC.varname= ${TOOL_SED} -n -e '/^MAGIC/p' -e '/^ORDER_/p' +POSTPROC.gnode-submake= awk '/Input graph/, /^$$/' POSTPROC.varname-empty= ${TOOL_SED} -n -e '/^Var_Set/p' -e '/^out:/p' # Some tests reuse other tests, which makes them unnecessarily fragile. @@ -519,6 +554,8 @@ MAKE_TEST_ENV?= MALLOC_OPTIONS="JA" # for jemalloc # always pretend .MAKE was called 'make' _SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,' _SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,' +_SED_CMDS+= -e 's,${TEST_MAKE:T:S,.,\\.,g}[][0-9]* warning,make warning,' +_SED_CMDS+= -e 's,^usage: ${TEST_MAKE:T:S,.,\\.,g} ,usage: make ,' # replace anything after 'stopped in' with unit-tests _SED_CMDS+= -e '/stopped/s, /.*, unit-tests,' # strip ${.CURDIR}/ from the output diff --git a/contrib/bmake/unit-tests/archive-suffix.mk b/contrib/bmake/unit-tests/archive-suffix.mk index 9f7fa219c667..a216fd2d3c6a 100755 --- a/contrib/bmake/unit-tests/archive-suffix.mk +++ b/contrib/bmake/unit-tests/archive-suffix.mk @@ -1,11 +1,11 @@ -# $NetBSD: archive-suffix.mk,v 1.1 2020/08/29 14:47:26 rillig Exp $ +# $NetBSD: archive-suffix.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $ # # Between 2020-08-23 and 2020-08-30, the below code produced an assertion -# failure in Var_Set_with_flags, triggered by Compat_Make, when setting the +# failure in Var_SetWithFlags, triggered by Compat_Make, when setting the # .IMPSRC of an archive node to its .TARGET. # # The code assumed that the .TARGET variable of every node would be set, but -# but that is not guaranteed. +# that is not guaranteed. # # Between 2016-03-15 and 2016-03-16 the behavior of the below code changed. # Until 2016-03-15, it remade the target, starting with 2016-03-16 it says diff --git a/contrib/bmake/unit-tests/archive.mk b/contrib/bmake/unit-tests/archive.mk index 2f91005f988c..f8815cf40a40 100644 --- a/contrib/bmake/unit-tests/archive.mk +++ b/contrib/bmake/unit-tests/archive.mk @@ -1,18 +1,15 @@ -# $NetBSD: archive.mk,v 1.10 2020/10/09 06:44:42 rillig Exp $ +# $NetBSD: archive.mk,v 1.11 2020/11/15 14:07:53 rillig Exp $ # # Very basic demonstration of handling archives, based on the description # in PSD.doc/tutorial.ms. # # This test aims at covering the code, not at being an introduction to -# archive handling. That's why it is more complicated and detailed than -# strictly necessary. +# archive handling. That's why it deviates from the tutorial style of +# several other tests. ARCHIVE= libprog.a FILES= archive.mk modmisc.mk varmisc.mk -MAKE_CMD= ${.MAKE} -f ${MAKEFILE} -RUN?= @set -eu; - all: .if ${.PARSEDIR:tA} != ${.CURDIR:tA} @cd ${MAKEFILE:H} && cp ${FILES} [at]*.mk ${.CURDIR} @@ -20,13 +17,13 @@ all: # The following targets create and remove files. The filesystem cache in # dir.c would probably not handle this correctly, therefore each of the # targets is run in its separate sub-make. - ${RUN} ${MAKE_CMD} remove-archive - ${RUN} ${MAKE_CMD} create-archive - ${RUN} ${MAKE_CMD} list-archive - ${RUN} ${MAKE_CMD} list-archive-wildcard - ${RUN} ${MAKE_CMD} depend-on-existing-member - ${RUN} ${MAKE_CMD} depend-on-nonexistent-member - ${RUN} ${MAKE_CMD} remove-archive + @${MAKE} -f ${MAKEFILE} remove-archive + @${MAKE} -f ${MAKEFILE} create-archive + @${MAKE} -f ${MAKEFILE} list-archive + @${MAKE} -f ${MAKEFILE} list-archive-wildcard + @${MAKE} -f ${MAKEFILE} depend-on-existing-member + @${MAKE} -f ${MAKEFILE} depend-on-nonexistent-member + @${MAKE} -f ${MAKEFILE} remove-archive create-archive: ${ARCHIVE} pre post @@ -43,15 +40,16 @@ list-archive: ${ARCHIVE} pre post # XXX: I had expected that this dependency would select all *.mk files from # the archive. Instead, the globbing is done in the current directory. +# # To prevent an overly long file list, the pattern is restricted to [at]*.mk. list-archive-wildcard: ${ARCHIVE}([at]*.mk) pre post - ${RUN} printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@} + @printf '%s\n' ${.ALLSRC:O:@member@${.TARGET:Q}': '${member:Q}@} depend-on-existing-member: ${ARCHIVE}(archive.mk) pre post - ${RUN} echo $@ + @echo $@ depend-on-nonexistent-member: ${ARCHIVE}(nonexistent.mk) pre post - ${RUN} echo $@ + @echo $@ remove-archive: pre post rm -f ${ARCHIVE} diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.exp b/contrib/bmake/unit-tests/cmd-errors-lint.exp new file mode 100644 index 000000000000..09924c538de0 --- /dev/null +++ b/contrib/bmake/unit-tests/cmd-errors-lint.exp @@ -0,0 +1,9 @@ +: undefined +make: Unclosed variable "UNCLOSED" +: unclosed-variable +make: Unclosed variable expression (expecting '}') for "UNCLOSED" +: unclosed-modifier +make: Unknown modifier 'Z' +: unknown-modifier +: end +exit status 2 diff --git a/contrib/bmake/unit-tests/cmd-errors-lint.mk b/contrib/bmake/unit-tests/cmd-errors-lint.mk new file mode 100644 index 000000000000..371e12af0f4f --- /dev/null +++ b/contrib/bmake/unit-tests/cmd-errors-lint.mk @@ -0,0 +1,32 @@ +# $NetBSD: cmd-errors-lint.mk,v 1.1 2020/11/02 20:43:27 rillig Exp $ +# +# Demonstrate how errors in variable expansions affect whether the commands +# are actually executed. + +.MAKEFLAGS: -dL + +all: undefined unclosed-variable unclosed-modifier unknown-modifier end + +# Undefined variables are not an error. They expand to empty strings. +undefined: + : $@ ${UNDEFINED} + +# XXX: As of 2020-11-01, this obvious syntax error is not detected. +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unclosed-variable: + : $@ ${UNCLOSED + +# XXX: As of 2020-11-01, this obvious syntax error is not detected. +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unclosed-modifier: + : $@ ${UNCLOSED: + +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unknown-modifier: + : $@ ${UNKNOWN:Z} + +end: + : $@ diff --git a/contrib/bmake/unit-tests/cmd-errors.exp b/contrib/bmake/unit-tests/cmd-errors.exp new file mode 100644 index 000000000000..6d9c6bb7f890 --- /dev/null +++ b/contrib/bmake/unit-tests/cmd-errors.exp @@ -0,0 +1,9 @@ +: undefined eol +make: Unclosed variable "UNCLOSED" +: unclosed-variable +make: Unclosed variable expression (expecting '}') for "UNCLOSED" +: unclosed-modifier +make: Unknown modifier 'Z' +: unknown-modifier eol +: end eol +exit status 0 diff --git a/contrib/bmake/unit-tests/cmd-errors.mk b/contrib/bmake/unit-tests/cmd-errors.mk new file mode 100644 index 000000000000..5ad4be311873 --- /dev/null +++ b/contrib/bmake/unit-tests/cmd-errors.mk @@ -0,0 +1,30 @@ +# $NetBSD: cmd-errors.mk,v 1.3 2020/11/09 23:36:34 rillig Exp $ +# +# Demonstrate how errors in variable expansions affect whether the commands +# are actually executed. + +all: undefined unclosed-variable unclosed-modifier unknown-modifier end + +# Undefined variables are not an error. They expand to empty strings. +undefined: + : $@ ${UNDEFINED} eol + +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unclosed-variable: + : $@ ${UNCLOSED + +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unclosed-modifier: + : $@ ${UNCLOSED: + +# XXX: As of 2020-11-01, this command is executed even though it contains +# parse errors. +unknown-modifier: + : $@ ${UNKNOWN:Z} eol + +end: + : $@ eol + +# XXX: As of 2020-11-02, despite the parse errors, the exit status is 0. diff --git a/contrib/bmake/unit-tests/cmd-interrupt.mk b/contrib/bmake/unit-tests/cmd-interrupt.mk index 033f3307bd2e..fa0d85fc9063 100755 --- a/contrib/bmake/unit-tests/cmd-interrupt.mk +++ b/contrib/bmake/unit-tests/cmd-interrupt.mk @@ -1,4 +1,4 @@ -# $NetBSD: cmd-interrupt.mk,v 1.2 2020/08/28 18:16:22 rillig Exp $ +# $NetBSD: cmd-interrupt.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $ # # Tests for interrupting a command. # @@ -22,7 +22,7 @@ all: clean-before interrupt-ordinary interrupt-phony interrupt-precious clean-af clean-before clean-after: .PHONY @rm -f cmd-interrupt-ordinary cmd-interrupt-phony cmd-interrupt-precious -interrupt-ordinary: .PHONY +interrupt-ordinary: @${.MAKE} ${MAKEFLAGS} -f ${MAKEFILE} cmd-interrupt-ordinary || true # The ././ is necessary to work around the file cache. @echo ${.TARGET}: ${exists(././cmd-interrupt-ordinary) :? error : ok } diff --git a/contrib/bmake/unit-tests/cmdline-undefined.exp b/contrib/bmake/unit-tests/cmdline-undefined.exp new file mode 100644 index 000000000000..977ceee6dbf5 --- /dev/null +++ b/contrib/bmake/unit-tests/cmdline-undefined.exp @@ -0,0 +1,17 @@ +The = assignment operator +make: "cmdline-undefined.mk" line 29: From the command line: Undefined is . +make: "cmdline-undefined.mk" line 30: From .MAKEFLAGS '=': Undefined is . +make: "cmdline-undefined.mk" line 31: From .MAKEFLAGS ':=': Undefined is . +make: "cmdline-undefined.mk" line 35: From the command line: Undefined is now defined. +make: "cmdline-undefined.mk" line 36: From .MAKEFLAGS '=': Undefined is now defined. +make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is now defined. + +The := assignment operator +make: "cmdline-undefined.mk" line 29: From the command line: Undefined is . +make: "cmdline-undefined.mk" line 30: From .MAKEFLAGS '=': Undefined is . +make: "cmdline-undefined.mk" line 31: From .MAKEFLAGS ':=': Undefined is . +make: "cmdline-undefined.mk" line 35: From the command line: Undefined is now defined. +make: "cmdline-undefined.mk" line 36: From .MAKEFLAGS '=': Undefined is now defined. +make: "cmdline-undefined.mk" line 37: From .MAKEFLAGS ':=': Undefined is now defined. + +exit status 0 diff --git a/contrib/bmake/unit-tests/cmdline-undefined.mk b/contrib/bmake/unit-tests/cmdline-undefined.mk new file mode 100644 index 000000000000..5a3375cbbfb8 --- /dev/null +++ b/contrib/bmake/unit-tests/cmdline-undefined.mk @@ -0,0 +1,40 @@ +# $NetBSD: cmdline-undefined.mk,v 1.2 2020/11/04 04:49:33 rillig Exp $ +# +# Tests for undefined variable expressions in the command line. + +all: + # When the command line is parsed, variable assignments using the + # '=' assignment operator do get their variable name expanded + # (which probably occurs rarely in practice, if at all), but their + # variable value is not expanded, as usual. + # + @echo 'The = assignment operator' + @${.MAKE} -f ${MAKEFILE} print-undefined \ + CMDLINE='Undefined is $${UNDEFINED}.' + @echo + + # The interesting case is using the ':=' assignment operator, which + # expands its right-hand side. But only those variables that are + # defined. + @echo 'The := assignment operator' + @${.MAKE} -f ${MAKEFILE} print-undefined \ + CMDLINE:='Undefined is $${UNDEFINED}.' + @echo + +.if make(print-undefined) + +.MAKEFLAGS: MAKEFLAGS_ASSIGN='Undefined is $${UNDEFINED}.' +.MAKEFLAGS: MAKEFLAGS_SUBST:='Undefined is $${UNDEFINED}.' + +.info From the command line: ${CMDLINE} +.info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} +.info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} + +UNDEFINED?= now defined + +.info From the command line: ${CMDLINE} +.info From .MAKEFLAGS '=': ${MAKEFLAGS_ASSIGN} +.info From .MAKEFLAGS ':=': ${MAKEFLAGS_SUBST} + +print-undefined: +.endif diff --git a/contrib/bmake/unit-tests/cmdline.mk b/contrib/bmake/unit-tests/cmdline.mk index c12c31220cb5..cd88cead4558 100644 --- a/contrib/bmake/unit-tests/cmdline.mk +++ b/contrib/bmake/unit-tests/cmdline.mk @@ -1,8 +1,7 @@ -# $NetBSD: cmdline.mk,v 1.1 2020/07/28 22:44:44 rillig Exp $ +# $NetBSD: cmdline.mk,v 1.2 2020/11/15 14:07:53 rillig Exp $ # # Tests for command line parsing and related special variables. -RUN?= @set -eu; TMPBASE?= /tmp SUB1= a7b41170-53f8-4cc2-bc5c-e4c3dd93ec45 # just a random UUID SUB2= 6a8899d2-d227-4b55-9b6b-f3c8eeb83fd5 # just a random UUID @@ -14,14 +13,14 @@ all: prepare-dirs all: makeobjdir-direct makeobjdir-indirect prepare-dirs: - ${RUN} rm -rf ${DIR2} ${DIR12} - ${RUN} mkdir -p ${DIR2} ${DIR12} + @rm -rf ${DIR2} ${DIR12} + @mkdir -p ${DIR2} ${DIR12} # The .OBJDIR can be set via the MAKEOBJDIR command line variable. # It must be a command line variable; an environment variable would not work. makeobjdir-direct: @echo $@: - ${RUN} ${MAKE_CMD} MAKEOBJDIR=${DIR2} show-objdir + @${MAKE_CMD} MAKEOBJDIR=${DIR2} show-objdir # The .OBJDIR can be set via the MAKEOBJDIR command line variable, # and that variable could even contain the usual modifiers. @@ -31,7 +30,7 @@ makeobjdir-direct: # see MAKE_CMD. makeobjdir-indirect: @echo $@: - ${RUN} ${MAKE_CMD} MAKEOBJDIR='$${TMPBASE}/$${SUB2}' show-objdir + @${MAKE_CMD} MAKEOBJDIR='$${TMPBASE}/$${SUB2}' show-objdir show-objdir: @echo $@: ${.OBJDIR:Q} diff --git a/contrib/bmake/unit-tests/comment.mk b/contrib/bmake/unit-tests/comment.mk index 1cdcfcdd86ba..d4fb041104a7 100644 --- a/contrib/bmake/unit-tests/comment.mk +++ b/contrib/bmake/unit-tests/comment.mk @@ -1,4 +1,4 @@ -# $NetBSD: comment.mk,v 1.2 2020/09/07 19:17:36 rillig Exp $ +# $NetBSD: comment.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $ # # Demonstrate how comments are written in makefiles. @@ -12,7 +12,7 @@ that \ goes \ on and on. - # Comments can be indented, but that is rather unusual. + # Comments can be indented with spaces, but that is rather unusual. # Comments can be indented with a tab. # These are not shell commands, they are just makefile comments. @@ -21,6 +21,8 @@ on and on. .endif # And after the closing directive. VAR= # This comment makes the variable value empty. + # ParseGetLine removes any whitespace before the + # comment. .if ${VAR} != "" . error .endif @@ -35,7 +37,9 @@ VAR= value . error .endif -# This is NOT an escaped comment due to the double backslashes \\ +# This comment ends with 2 backslashes. An even number of backslashes does +# not count as a line continuation, therefore the variable assignment that +# follows is actively interpreted. \\ VAR= not part of the comment .if ${VAR} != "not part of the comment" . error @@ -55,7 +59,7 @@ WORDS= ${VAR:[#]} [# . error .endif -# An odd number of comment signs makes a line continuation, \\\ +# An odd number of backslashes makes a line continuation, \\\ no matter if it is 3 or 5 \\\\\ or 9 backslashes. \\\\\\\\\ This is the last line of the comment. diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp index 1f12e858a66c..64e383ef32a2 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp +++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.exp @@ -1,6 +1,6 @@ -make: "cond-cmp-numeric-eq.mk" line 54: warning: Unknown operator -make: "cond-cmp-numeric-eq.mk" line 54: Malformed conditional (!(12345 = 12345)) -make: "cond-cmp-numeric-eq.mk" line 61: Malformed conditional (!(12345 === 12345)) +make: "cond-cmp-numeric-eq.mk" line 67: warning: Unknown operator +make: "cond-cmp-numeric-eq.mk" line 67: Malformed conditional (!(12345 = 12345)) +make: "cond-cmp-numeric-eq.mk" line 74: Malformed conditional (!(12345 === 12345)) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk index 0e77d364ac94..c6b39876e75e 100755 --- a/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk +++ b/contrib/bmake/unit-tests/cond-cmp-numeric-eq.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-numeric-eq.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-cmp-numeric-eq.mk,v 1.5 2020/11/08 21:47:59 rillig Exp $ # # Tests for numeric comparisons with the == operator in .if conditions. @@ -49,6 +49,19 @@ . error .endif +# Because an IEEE 754 double can only hold integers with a mantissa of 53 +# bits, these two numbers are considered the same. The 993 is rounded down +# to the 992. +.if 9007199254740993 == 9007199254740992 +.else +. error +.endif +# The 995 is rounded up, the 997 is rounded down. +.if 9007199254740995 == 9007199254740997 +.else +. error Probably a misconfiguration in the floating point environment, \ + or maybe a machine without IEEE 754 floating point support. +.endif # There is no = operator for numbers. .if !(12345 = 12345) diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.exp b/contrib/bmake/unit-tests/cond-cmp-numeric.exp index 67d882e0c628..578d53228f6e 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric.exp +++ b/contrib/bmake/unit-tests/cond-cmp-numeric.exp @@ -6,6 +6,10 @@ make: "cond-cmp-numeric.mk" line 16: warning: String comparison operator must be make: "cond-cmp-numeric.mk" line 16: Malformed conditional (${:UNaN} > NaN) CondParser_Eval: !(${:UNaN} == NaN) lhs = "NaN", rhs = "NaN", op = == +CondParser_Eval: 123 ! 123 +lhs = 123.000000, rhs = 123.000000, op = ! +make: "cond-cmp-numeric.mk" line 34: warning: Unknown operator +make: "cond-cmp-numeric.mk" line 34: Malformed conditional (123 ! 123) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-numeric.mk b/contrib/bmake/unit-tests/cond-cmp-numeric.mk index 67358ddaf86b..b1ec3e719d47 100644 --- a/contrib/bmake/unit-tests/cond-cmp-numeric.mk +++ b/contrib/bmake/unit-tests/cond-cmp-numeric.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-numeric.mk,v 1.3 2020/09/12 18:01:51 rillig Exp $ +# $NetBSD: cond-cmp-numeric.mk,v 1.4 2020/11/08 22:56:16 rillig Exp $ # # Tests for numeric comparisons in .if conditions. @@ -25,5 +25,17 @@ . error .endif +# The parsing code in CondParser_Comparison only performs a light check on +# 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. +# +# XXX: The warning message does not mention the actual operator. +.if 123 ! 123 +. error +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-cmp-string.exp b/contrib/bmake/unit-tests/cond-cmp-string.exp index 735b7cda4430..6e6c218267bc 100644 --- a/contrib/bmake/unit-tests/cond-cmp-string.exp +++ b/contrib/bmake/unit-tests/cond-cmp-string.exp @@ -1,8 +1,8 @@ make: "cond-cmp-string.mk" line 18: Malformed conditional (str != str) -make: "cond-cmp-string.mk" line 37: Malformed conditional ("string" != "str""ing") -make: "cond-cmp-string.mk" line 42: warning: String comparison operator must be either == or != -make: "cond-cmp-string.mk" line 42: Malformed conditional (!("value" = "value")) -make: "cond-cmp-string.mk" line 49: Malformed conditional (!("value" === "value")) +make: "cond-cmp-string.mk" line 42: Malformed conditional ("string" != "str""ing") +make: "cond-cmp-string.mk" line 49: warning: String comparison operator must be either == or != +make: "cond-cmp-string.mk" line 49: Malformed conditional (!("value" = "value")) +make: "cond-cmp-string.mk" line 56: Malformed conditional (!("value" === "value")) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-cmp-string.mk b/contrib/bmake/unit-tests/cond-cmp-string.mk index 6af457925e97..6b5cba83bef7 100644 --- a/contrib/bmake/unit-tests/cond-cmp-string.mk +++ b/contrib/bmake/unit-tests/cond-cmp-string.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-string.mk,v 1.11 2020/10/30 14:53:31 rillig Exp $ +# $NetBSD: cond-cmp-string.mk,v 1.13 2020/11/15 14:07:53 rillig Exp $ # # Tests for string comparisons in .if conditions. @@ -19,9 +19,14 @@ . error .endif -# The left-hand side of the comparison requires a defined variable. -# The variable named "" is not defined, but applying the :U modifier to it -# makes it "kind of defined" (see VAR_KEEP). Therefore it is ok here. +# The left-hand side of the comparison requires that any variable expression +# is defined. +# +# The variable named "" is never defined, nevertheless it can be used as a +# starting point for variable expressions. Applying the :U modifier to such +# an undefined expression turns it into a defined expression. +# +# See ApplyModifier_Defined and VEF_DEF. .if ${:Ustr} != "str" . error .endif @@ -33,9 +38,11 @@ .endif # It is not possible to concatenate two string literals to form a single -# string. +# string. In C, Python and the shell this is possible, but not in make. .if "string" != "str""ing" . error +.else +. error .endif # There is no = operator for strings. @@ -88,3 +95,16 @@ .if ${:U word } != " ${:Uword} " . error .endif + +# If at least one side of the comparison is a string literal, the string +# comparison is performed. +.if 12345 != "12345" +. error +.endif + +# If at least one side of the comparison is a string literal, the string +# comparison is performed. The ".0" in the left-hand side makes the two +# sides of the equation unequal. +.if 12345.0 == "12345" +. error +.endif diff --git a/contrib/bmake/unit-tests/cond-cmp-unary.exp b/contrib/bmake/unit-tests/cond-cmp-unary.exp index 39a9383953dd..89f90dc1651f 100755 --- a/contrib/bmake/unit-tests/cond-cmp-unary.exp +++ b/contrib/bmake/unit-tests/cond-cmp-unary.exp @@ -1 +1,2 @@ +make: "cond-cmp-unary.mk" line 53: This is only reached because of a bug in EvalNotEmpty. exit status 0 diff --git a/contrib/bmake/unit-tests/cond-cmp-unary.mk b/contrib/bmake/unit-tests/cond-cmp-unary.mk index 88ce79bf1a99..168de0f30e3f 100755 --- a/contrib/bmake/unit-tests/cond-cmp-unary.mk +++ b/contrib/bmake/unit-tests/cond-cmp-unary.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-cmp-unary.mk,v 1.1 2020/09/14 06:22:59 rillig Exp $ +# $NetBSD: cond-cmp-unary.mk,v 1.2 2020/11/11 07:30:11 rillig Exp $ # # Tests for unary comparisons in .if conditions, that is, comparisons with # a single operand. If the operand is a number, it is compared to zero, @@ -25,6 +25,9 @@ .endif # The empty string may come from a variable expression. +# +# XXX: As of 2020-11-11, this empty string is interpreted "as a number" in +# EvalNotEmpty, which is plain wrong. The bug is in TryParseNumber. .if ${:U} . error .endif @@ -40,4 +43,16 @@ . error .endif +# A string of whitespace should evaluate to false. +# +# XXX: As of 2020-11-11, the implementation in EvalNotEmpty does not skip +# whitespace before testing for the end. This was probably an oversight in +# a commit from 1992-04-15 saying "A variable is empty when it just contains +# spaces". +.if ${:U } +. info This is only reached because of a bug in EvalNotEmpty. +.else +. error +.endif + all: # nothing diff --git a/contrib/bmake/unit-tests/cond-func-commands.mk b/contrib/bmake/unit-tests/cond-func-commands.mk index c6e1724c72f3..e127a8ebdc03 100644 --- a/contrib/bmake/unit-tests/cond-func-commands.mk +++ b/contrib/bmake/unit-tests/cond-func-commands.mk @@ -1,10 +1,11 @@ -# $NetBSD: cond-func-commands.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-func-commands.mk,v 1.5 2020/11/15 14:07:53 rillig Exp $ # # Tests for the commands() function in .if conditions. .MAIN: all -# The target "target" does not exist yet, therefore it cannot have commands. +# At this point, the target 'target' does not exist yet, therefore it cannot +# have commands. Sounds obvious, but good to know that it is really so. .if commands(target) . error .endif diff --git a/contrib/bmake/unit-tests/cond-func-defined.exp b/contrib/bmake/unit-tests/cond-func-defined.exp index 70c6342a02c3..caf66e39938f 100644 --- a/contrib/bmake/unit-tests/cond-func-defined.exp +++ b/contrib/bmake/unit-tests/cond-func-defined.exp @@ -1,5 +1,10 @@ make: "cond-func-defined.mk" line 23: warning: Missing closing parenthesis for defined() make: "cond-func-defined.mk" line 23: Malformed conditional (!defined(A B)) +make: "cond-func-defined.mk" line 33: warning: Missing closing parenthesis for defined() +make: "cond-func-defined.mk" line 33: Malformed conditional (defined(DEF) +make: "cond-func-defined.mk" line 45: In .for loops, variable expressions for the loop variables are +make: "cond-func-defined.mk" line 46: substituted at evaluation time. There is no actual variable +make: "cond-func-defined.mk" line 47: involved, even if it feels like it. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-func-defined.mk b/contrib/bmake/unit-tests/cond-func-defined.mk index ec4feae05839..2aa49ccbf147 100644 --- a/contrib/bmake/unit-tests/cond-func-defined.mk +++ b/contrib/bmake/unit-tests/cond-func-defined.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-func-defined.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-func-defined.mk,v 1.7 2020/11/15 14:07:53 rillig Exp $ # # Tests for the defined() function in .if conditions. @@ -29,5 +29,24 @@ ${:UA B}= variable name with spaces . error .endif +# Parse error: missing closing parenthesis; see ParseFuncArg. +.if defined(DEF +. error +.else +. error +.endif + +# Variables from .for loops are not defined. +# See directive-for.mk for more details. +.for var in value +. if defined(var) +. error +. else +. info In .for loops, variable expressions for the loop variables are +. info substituted at evaluation time. There is no actual variable +. info involved, even if it feels like it. +. endif +.endfor + all: @:; diff --git a/contrib/bmake/unit-tests/cond-func-empty.exp b/contrib/bmake/unit-tests/cond-func-empty.exp index 39a9383953dd..77a4edd47f49 100644 --- a/contrib/bmake/unit-tests/cond-func-empty.exp +++ b/contrib/bmake/unit-tests/cond-func-empty.exp @@ -1 +1,5 @@ -exit status 0 +make: "cond-func-empty.mk" line 152: Unclosed variable "WORD" +make: "cond-func-empty.mk" line 152: Malformed conditional (empty(WORD) +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/cond-func-empty.mk b/contrib/bmake/unit-tests/cond-func-empty.mk index f93b45895e6e..f43d99bf92c5 100644 --- a/contrib/bmake/unit-tests/cond-func-empty.mk +++ b/contrib/bmake/unit-tests/cond-func-empty.mk @@ -1,11 +1,10 @@ -# $NetBSD: cond-func-empty.mk,v 1.8 2020/09/23 08:11:28 rillig Exp $ +# $NetBSD: cond-func-empty.mk,v 1.10 2020/11/15 14:07:53 rillig Exp $ # # Tests for the empty() function in .if conditions, which tests a variable # expression for emptiness. # # Note that the argument in the parentheses is indeed a variable name, -# optionally followed by variable modifiers. This is like the defined() -# function. +# optionally followed by variable modifiers. # .undef UNDEF @@ -25,13 +24,15 @@ WORD= word . error .endif -# The :S modifier replaces the empty value with an actual word, and -# after that the expression is no longer empty. Because the variable -# was undefined in the first place, the expression has the flag VAR_JUNK -# but not VAR_KEEP, therefore it is still considered undefined. -# Only very few variable modifiers turn an undefined variable expression -# into a defined variable expression. The :U and :D modifiers belong to -# that group, but :S doesn't (see VAR_KEEP). +# The :S modifier replaces the empty value with an actual word. The +# expression is now no longer empty, but it is still possible to see whether +# the expression was based on an undefined variable. The expression has the +# flag VEF_UNDEF. +# +# The expression does not have the flag VEF_DEF though, therefore it is still +# considered undefined. Yes, indeed, undefined but not empty. There are a +# few variable modifiers that turn an undefined expression into a defined +# expression, among them :U and :D, but not :S. # # XXX: This is hard to explain to someone who doesn't know these # implementation details. @@ -49,13 +50,14 @@ WORD= word .endif # And now to the surprising part. Applying the following :S modifier to the -# undefined variable makes it non-empty, but the marker VAR_JUNK is preserved -# nevertheless. The :U modifier that follows only looks at VAR_JUNK to decide -# whether the variable is defined or not. This kind of makes sense since the -# :U modifier tests the _variable_, not the _expression_. +# undefined expression makes it non-empty, but the marker VEF_UNDEF is +# preserved nevertheless. The :U modifier that follows only looks at the +# VEF_UNDEF flag to decide whether the variable is defined or not. This kind +# of makes sense since the :U modifier tests the _variable_, not the +# _expression_. # -# But since the variable was undefined to begin with, the fallback value is -# used in this expression. +# But since the variable was undefined to begin with, the fallback value from +# the :U modifier is used in this expression. # .if ${UNDEF:S,^$,value,W:Ufallback} != "fallback" . error @@ -128,7 +130,7 @@ ${:U }= space # If everything goes well, the argument expands to "WORD", and that variable # is defined at the beginning of this file. The surrounding 'W' and 'D' # ensure that the parser in ParseEmptyArg has the correct position, both -# before and after the call to Var_ParsePP. +# before and after the call to Var_Parse. .if empty(W${:UOR}D) . error .endif @@ -146,5 +148,12 @@ ${:U WORD }= variable name with spaces . error .endif +# Parse error: missing closing parenthesis. +.if empty(WORD +. error +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-func.exp b/contrib/bmake/unit-tests/cond-func.exp index 0069ed75726c..73b6273d0b09 100644 --- a/contrib/bmake/unit-tests/cond-func.exp +++ b/contrib/bmake/unit-tests/cond-func.exp @@ -1,9 +1,15 @@ -make: "cond-func.mk" line 29: warning: Missing closing parenthesis for defined() -make: "cond-func.mk" line 29: Malformed conditional (!defined(A B)) -make: "cond-func.mk" line 44: warning: Missing closing parenthesis for defined() -make: "cond-func.mk" line 44: Malformed conditional (!defined(A&B)) -make: "cond-func.mk" line 47: warning: Missing closing parenthesis for defined() -make: "cond-func.mk" line 47: Malformed conditional (!defined(A|B)) +make: "cond-func.mk" line 36: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 36: Malformed conditional (!defined(A B)) +make: "cond-func.mk" line 51: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 51: Malformed conditional (!defined(A&B)) +make: "cond-func.mk" line 54: warning: Missing closing parenthesis for defined() +make: "cond-func.mk" line 54: Malformed conditional (!defined(A|B)) +make: "cond-func.mk" line 94: The empty variable is never defined. +make: "cond-func.mk" line 102: A plain function name is parsed as !empty(...). +make: "cond-func.mk" line 109: A plain function name is parsed as !empty(...). +make: "cond-func.mk" line 119: Symbols may start with a function name. +make: "cond-func.mk" line 124: Symbols may start with a function name. +make: "cond-func.mk" line 130: Malformed conditional (defined() make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-func.mk b/contrib/bmake/unit-tests/cond-func.mk index 8e7362182429..4ff43b72ef88 100644 --- a/contrib/bmake/unit-tests/cond-func.mk +++ b/contrib/bmake/unit-tests/cond-func.mk @@ -1,15 +1,22 @@ -# $NetBSD: cond-func.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-func.mk,v 1.9 2020/11/15 14:07:53 rillig Exp $ # # Tests for those parts of the functions in .if conditions that are common # among several functions. # # The below test uses the function defined(...) since it has no side-effects, -# the other functions (except empty(...)) would work equally well. +# the other functions (except empty(...)) would work equally well. The +# function empty is special because it uses a different parsing algorithm for +# its argument. DEF= defined ${:UA B}= variable name with spaces ${:UVAR(value)}= variable name with parentheses -${:UVAR{value}}= variable name with braces +${:UVAR{value}}= variable name with balanced braces + +# Really strange variable names must be given indirectly via another variable, +# so that no unbalanced braces appear in the top-level expression. +VARNAME_UNBALANCED_BRACES= VAR{{{value +${VARNAME_UNBALANCED_BRACES}= variable name with unbalanced braces .if !defined(DEF) . error @@ -59,6 +66,12 @@ ${:UVAR{value}}= variable name with braces . error .endif +# Braces do not have any special meaning when parsing arguments. +# They don't need to be balanced. +.if !defined(VAR{{{value) +. error +.endif + # There may be spaces around the operators and parentheses, and even # inside the parentheses. The spaces inside the parentheses are not # allowed for the empty() function (see cond-func-empty.mk), therefore @@ -67,5 +80,58 @@ ${:UVAR{value}}= variable name with braces . error .endif +# The following condition is interpreted as defined(A) && defined(B). +# In lack of a function call expression, each kind of .if directive has a +# default function that is called when a bare word is parsed. For the plain +# .if directive, this function is defined(); see "struct If ifs" in cond.c. +.if A&B +. error +.endif + +.if defined() +. error +.else +. info The empty variable is never defined. +.endif + +# The plain word 'defined' is interpreted as '!empty(defined)'. +# That variable is not defined (yet). +.if defined +. error +.else +. info A plain function name is parsed as !empty(...). +.endif + +# If a variable named 'defined' is actually defined and not empty, the plain +# symbol 'defined' evaluates to true. +defined= non-empty +.if defined +. info A plain function name is parsed as !empty(...). +.else +. error +.endif + +# A plain symbol name may start with one of the function names, in this case +# 'defined'. +.if defined-var +. error +.else +. info Symbols may start with a function name. +.endif + +defined-var= non-empty +.if defined-var +. info Symbols may start with a function name. +.else +. error +.endif + +# Missing closing parenthesis when parsing the function argument. +.if defined( +. error +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-late.mk b/contrib/bmake/unit-tests/cond-late.mk index 397f5febd480..4df3df2cf1d4 100644 --- a/contrib/bmake/unit-tests/cond-late.mk +++ b/contrib/bmake/unit-tests/cond-late.mk @@ -1,7 +1,9 @@ -# $NetBSD: cond-late.mk,v 1.2 2020/07/25 20:37:46 rillig Exp $ +# $NetBSD: cond-late.mk,v 1.3 2020/11/15 14:07:53 rillig Exp $ # # Using the :? modifier, variable expressions can contain conditional -# expressions that are evaluated late. Any variables appearing in these +# expressions that are evaluated late, at expansion time. +# +# Any variables appearing in these # conditions are expanded before parsing the condition. This is # different from many other places. # @@ -11,15 +13,15 @@ # They should also not contain operators like == or <, since these are # actually interpreted as these operators. This is demonstrated below. # -# If the order of evaluation were to change to first parse the condition -# and then expand the variables, the output would change from the -# current "yes no" to "yes yes", since both variables are non-empty. all: cond-literal COND.true= "yes" == "yes" COND.false= "yes" != "yes" +# If the order of evaluation were to change to first parse the condition +# and then expand the variables, the output would change from the +# current "yes no" to "yes yes", since both variables are non-empty. cond-literal: @echo ${ ${COND.true} :?yes:no} @echo ${ ${COND.false} :?yes:no} diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.exp b/contrib/bmake/unit-tests/cond-op-and-lint.exp new file mode 100644 index 000000000000..8817fd0d658b --- /dev/null +++ b/contrib/bmake/unit-tests/cond-op-and-lint.exp @@ -0,0 +1,4 @@ +make: "cond-op-and-lint.mk" line 9: Unknown operator '&' +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-and-lint.mk b/contrib/bmake/unit-tests/cond-op-and-lint.mk new file mode 100644 index 000000000000..6262339016f5 --- /dev/null +++ b/contrib/bmake/unit-tests/cond-op-and-lint.mk @@ -0,0 +1,13 @@ +# $NetBSD: cond-op-and-lint.mk,v 1.1 2020/11/08 23:54:28 rillig Exp $ +# +# Tests for the && operator in .if conditions, in lint mode. + +.MAKEFLAGS: -dL + +# The '&' operator is not allowed in lint mode. +# It is not used in practice anyway. +.if 0 & 0 +. error +.else +. error +.endif diff --git a/contrib/bmake/unit-tests/cond-op-not.exp b/contrib/bmake/unit-tests/cond-op-not.exp index 39a9383953dd..37f57b7fdfa7 100644 --- a/contrib/bmake/unit-tests/cond-op-not.exp +++ b/contrib/bmake/unit-tests/cond-op-not.exp @@ -1 +1,6 @@ +make: "cond-op-not.mk" line 29: Not empty evaluates to true. +make: "cond-op-not.mk" line 37: Not space evaluates to false. +make: "cond-op-not.mk" line 41: Not 0 evaluates to true. +make: "cond-op-not.mk" line 49: Not 1 evaluates to false. +make: "cond-op-not.mk" line 55: Not word evaluates to false. exit status 0 diff --git a/contrib/bmake/unit-tests/cond-op-not.mk b/contrib/bmake/unit-tests/cond-op-not.mk index d929318785a5..388c62d8898f 100644 --- a/contrib/bmake/unit-tests/cond-op-not.mk +++ b/contrib/bmake/unit-tests/cond-op-not.mk @@ -1,6 +1,6 @@ -# $NetBSD: cond-op-not.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-op-not.mk,v 1.6 2020/11/15 14:58:14 rillig Exp $ # -# Tests for the ! operator in .if conditions. +# Tests for the ! operator in .if conditions, which negates its argument. # The exclamation mark negates its operand. .if !1 @@ -18,5 +18,42 @@ . error .endif +# The operator '==' binds more tightly than '!'. +# This is unusual since most other programming languages define the precedence +# to be the other way round. +.if !${:Uexpression} == "expression" +. error +.endif + +.if !${:U} +. info Not empty evaluates to true. +.else +. info Not empty evaluates to false. +.endif + +.if !${:U } +. info Not space evaluates to true. +.else +. info Not space evaluates to false. +.endif + +.if !${:U0} +. info Not 0 evaluates to true. +.else +. info Not 0 evaluates to false. +.endif + +.if !${:U1} +. info Not 1 evaluates to true. +.else +. info Not 1 evaluates to false. +.endif + +.if !${:Uword} +. info Not word evaluates to true. +.else +. info Not word evaluates to false. +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.exp b/contrib/bmake/unit-tests/cond-op-or-lint.exp new file mode 100644 index 000000000000..8abae99b6c4c --- /dev/null +++ b/contrib/bmake/unit-tests/cond-op-or-lint.exp @@ -0,0 +1,4 @@ +make: "cond-op-or-lint.mk" line 9: Unknown operator '|' +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op-or-lint.mk b/contrib/bmake/unit-tests/cond-op-or-lint.mk new file mode 100644 index 000000000000..aa29e9a6c2f2 --- /dev/null +++ b/contrib/bmake/unit-tests/cond-op-or-lint.mk @@ -0,0 +1,13 @@ +# $NetBSD: cond-op-or-lint.mk,v 1.1 2020/11/08 23:54:28 rillig Exp $ +# +# Tests for the || operator in .if conditions, in lint mode. + +.MAKEFLAGS: -dL + +# The '|' operator is not allowed in lint mode. +# It is not used in practice anyway. +.if 0 | 0 +. error +.else +. error +.endif diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.exp b/contrib/bmake/unit-tests/cond-op-parentheses.exp index 39a9383953dd..a0fa137af4ca 100644 --- a/contrib/bmake/unit-tests/cond-op-parentheses.exp +++ b/contrib/bmake/unit-tests/cond-op-parentheses.exp @@ -1 +1,2 @@ +make: "cond-op-parentheses.mk" line 13: Parentheses can be nested at least to depth 112. exit status 0 diff --git a/contrib/bmake/unit-tests/cond-op-parentheses.mk b/contrib/bmake/unit-tests/cond-op-parentheses.mk index 6c48d83dd2be..39ebc1607455 100644 --- a/contrib/bmake/unit-tests/cond-op-parentheses.mk +++ b/contrib/bmake/unit-tests/cond-op-parentheses.mk @@ -1,8 +1,19 @@ -# $NetBSD: cond-op-parentheses.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: cond-op-parentheses.mk,v 1.3 2020/11/15 14:58:14 rillig Exp $ # # Tests for parentheses in .if conditions. # TODO: Implementation +# Test for deeply nested conditions. +.if (((((((((((((((((((((((((((((((((((((((((((((((((((((((( \ + (((((((((((((((((((((((((((((((((((((((((((((((((((((((( \ + 1 \ + )))))))))))))))))))))))))))))))))))))))))))))))))))))))) \ + )))))))))))))))))))))))))))))))))))))))))))))))))))))))) +. info Parentheses can be nested at least to depth 112. +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-op.exp b/contrib/bmake/unit-tests/cond-op.exp index fd5bc20f673c..1a66e5ffeabd 100644 --- a/contrib/bmake/unit-tests/cond-op.exp +++ b/contrib/bmake/unit-tests/cond-op.exp @@ -1,7 +1,16 @@ -make: "cond-op.mk" line 45: Malformed conditional ("!word" == !word) -make: "cond-op.mk" line 70: Malformed conditional (0 ${ERR::=evaluated}) -make: "cond-op.mk" line 74: warning: After detecting a parse error, the rest is evaluated. -make: "cond-op.mk" line 78: Parsing continues until here. +make: "cond-op.mk" line 50: Malformed conditional ("!word" == !word) +make: "cond-op.mk" line 75: Malformed conditional (0 ${ERR::=evaluated}) +make: "cond-op.mk" line 79: After detecting a parse error, the rest is evaluated. +make: "cond-op.mk" line 83: Parsing continues until here. +make: "cond-op.mk" line 86: A B C => (A || B) && C A || B && C A || (B && C) +make: "cond-op.mk" line 93: 0 0 0 => 0 0 0 +make: "cond-op.mk" line 93: 0 0 1 => 0 0 0 +make: "cond-op.mk" line 93: 0 1 0 => 0 0 0 +make: "cond-op.mk" line 93: 0 1 1 => 1 1 1 +make: "cond-op.mk" line 93: 1 0 0 => 0 1 1 +make: "cond-op.mk" line 93: 1 0 1 => 1 1 1 +make: "cond-op.mk" line 93: 1 1 0 => 0 1 1 +make: "cond-op.mk" line 93: 1 1 1 => 1 1 1 make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-op.mk b/contrib/bmake/unit-tests/cond-op.mk index 71c4f7b66441..170355f6c0ad 100644 --- a/contrib/bmake/unit-tests/cond-op.mk +++ b/contrib/bmake/unit-tests/cond-op.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-op.mk,v 1.8 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-op.mk,v 1.10 2020/11/15 14:58:14 rillig Exp $ # # Tests for operators like &&, ||, ! in .if conditions. # @@ -9,8 +9,8 @@ # cond-op-parentheses.mk # In make, && binds more tightly than ||, like in C. -# If make had the same precedence for both && and ||, the result would be -# different. +# If make had the same precedence for both && and ||, like in the shell, +# the result would be different. # If || were to bind more tightly than &&, the result would be different # as well. .if !(1 || 1 && 0) @@ -18,13 +18,17 @@ .endif # If make were to interpret the && and || operators like the shell, the -# implicit binding would be this: +# previous condition would be interpreted as: .if (1 || 1) && 0 . error .endif # The precedence of the ! operator is different from C though. It has a -# lower precedence than the comparison operators. +# lower precedence than the comparison operators. Negating a condition +# does not need parentheses. +# +# This kind of condition looks so unfamiliar that it doesn't occur in +# practice. .if !"word" == "word" . error .endif @@ -36,7 +40,8 @@ # TODO: Demonstrate that the precedence of the ! and == operators actually # makes a difference. There is a simple example for sure, I just cannot -# wrap my head around it. +# wrap my head around it right now. See the truth table generator below +# for an example that doesn't require much thought. # This condition is malformed because the '!' on the right-hand side must not # appear unquoted. If any, it must be enclosed in quotes. @@ -71,11 +76,27 @@ . error .endif .if ${ERR:Uundefined} == evaluated -. warning After detecting a parse error, the rest is evaluated. +. info After detecting a parse error, the rest is evaluated. .endif # Just in case that parsing should ever stop on the first error. .info Parsing continues until here. +# Demonstration that '&&' has higher precedence than '||'. +.info A B C => (A || B) && C A || B && C A || (B && C) +.for a in 0 1 +. for b in 0 1 +. for c in 0 1 +. for r1 in ${ ($a || $b) && $c :?1:0} +. for r2 in ${ $a || $b && $c :?1:0} +. for r3 in ${ $a || ($b && $c) :?1:0} +. info $a $b $c => ${r1} ${r2} ${r3} +. endfor +. endfor +. endfor +. endfor +. endfor +.endfor + all: @:; diff --git a/contrib/bmake/unit-tests/cond-short.mk b/contrib/bmake/unit-tests/cond-short.mk index 9e3b0575eb78..077684be33fc 100644 --- a/contrib/bmake/unit-tests/cond-short.mk +++ b/contrib/bmake/unit-tests/cond-short.mk @@ -1,11 +1,14 @@ -# $NetBSD: cond-short.mk,v 1.11 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: cond-short.mk,v 1.12 2020/11/15 14:58:14 rillig Exp $ # # Demonstrates that in conditions, the right-hand side of an && or || # is only evaluated if it can actually influence the result. +# This is called 'short-circuit evaluation' and is the usual evaluation +# mode in most programming languages. A notable exception is Ada, which +# distinguishes between the operators 'And', 'And Then', 'Or', 'Or Else'. # # Between 2015-10-11 and 2020-06-28, the right-hand side of an && or || # operator was always evaluated, which was wrong. -# +# TODO: Had the evaluation been correct at some time before 2015-11-12? # The && operator. @@ -113,6 +116,9 @@ VAR= # empty again, for the following tests # make sure these do not cause complaint #.MAKEFLAGS: -dc +# TODO: Rewrite this whole section and check all the conditions and variables. +# Several of the assumptions are probably wrong here. +# TODO: replace 'x=' with '.info' or '.error'. V42= 42 iV1= ${V42} iV2= ${V66} @@ -167,5 +173,16 @@ x= Fail .endif x!= echo '0 || ${iV2:U2} < ${V42}: $x' >&2; echo +# TODO: Has this always worked? There may have been a time, maybe around +# 2000, when make would complain about the "Malformed conditional" because +# UNDEF is not defined. +.if defined(UNDEF) && ${UNDEF} != "undefined" +. error +.endif + +# TODO: Test each modifier to make sure it is skipped when it is irrelevant +# for the result. Since this test is already quite long, do that in another +# test. + all: @:;: diff --git a/contrib/bmake/unit-tests/cond-token-number.exp b/contrib/bmake/unit-tests/cond-token-number.exp index ea1f92797ff4..b5bfaf95d575 100644 --- a/contrib/bmake/unit-tests/cond-token-number.exp +++ b/contrib/bmake/unit-tests/cond-token-number.exp @@ -1,8 +1,8 @@ -make: "cond-token-number.mk" line 13: Malformed conditional (-0) -make: "cond-token-number.mk" line 21: Malformed conditional (+0) -make: "cond-token-number.mk" line 29: Malformed conditional (!-1) -make: "cond-token-number.mk" line 37: Malformed conditional (!+1) -make: "cond-token-number.mk" line 54: End of the tests. +make: "cond-token-number.mk" line 15: Malformed conditional (-0) +make: "cond-token-number.mk" line 25: Malformed conditional (+0) +make: "cond-token-number.mk" line 35: Malformed conditional (!-1) +make: "cond-token-number.mk" line 45: Malformed conditional (!+1) +make: "cond-token-number.mk" line 80: End of the tests. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-token-number.mk b/contrib/bmake/unit-tests/cond-token-number.mk index 4171a07d56c6..93e2646a60eb 100644 --- a/contrib/bmake/unit-tests/cond-token-number.mk +++ b/contrib/bmake/unit-tests/cond-token-number.mk @@ -1,6 +1,8 @@ -# $NetBSD: cond-token-number.mk,v 1.3 2020/09/14 06:22:59 rillig Exp $ +# $NetBSD: cond-token-number.mk,v 1.5 2020/11/15 14:58:14 rillig Exp $ # # Tests for number tokens in .if conditions. +# +# TODO: Add introduction. .if 0 . error @@ -12,6 +14,8 @@ # See the ch_isdigit call in CondParser_String. .if -0 . error +.else +. error .endif # Even though +0 is a number and would be accepted by strtod, it is not @@ -20,6 +24,8 @@ # See the ch_isdigit call in CondParser_String. .if +0 . error +.else +. error .endif # Even though -1 is a number and would be accepted by strtod, it is not @@ -28,6 +34,8 @@ # See the ch_isdigit call in CondParser_String. .if !-1 . error +.else +. error .endif # Even though +1 is a number and would be accepted by strtod, it is not @@ -36,6 +44,8 @@ # See the ch_isdigit call in CondParser_String. .if !+1 . error +.else +. error .endif # When the number comes from a variable expression though, it may be signed. @@ -50,6 +60,22 @@ . error .endif +# Hexadecimal numbers are accepted. +.if 0x0 +. error +.endif +.if 0x1 +.else +. error +.endif + +# This is not a hexadecimal number, even though it has an x. +# It is interpreted as a string instead, effectively meaning defined(3x4). +.if 3x4 +.else +. error +.endif + # Ensure that parsing continues until here. .info End of the tests. diff --git a/contrib/bmake/unit-tests/cond-token-plain.mk b/contrib/bmake/unit-tests/cond-token-plain.mk index ba9934f5b882..a5ffa37a5c84 100644 --- a/contrib/bmake/unit-tests/cond-token-plain.mk +++ b/contrib/bmake/unit-tests/cond-token-plain.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-plain.mk,v 1.4 2020/09/12 17:47:24 rillig Exp $ +# $NetBSD: cond-token-plain.mk,v 1.6 2020/11/15 14:58:14 rillig Exp $ # # Tests for plain tokens (that is, string literals without quotes) # in .if conditions. @@ -14,7 +14,7 @@ # parser gets to see it. # # XXX: The error message is missing for this malformed condition. -# The right-hand side of the comparison is just a '"'. +# The right-hand side of the comparison is just a '"', before unescaping. .if ${:U} != "#hash" . error .endif @@ -31,16 +31,19 @@ # comment handling anymore. The comments are supposed to be stripped off # in a very early parsing phase. # +# See https://gnats.netbsd.org/19596 for example makefiles demonstrating the +# original problems. This workaround is probably not needed anymore. +# # XXX: Missing error message for the malformed condition. The right-hand -# side is double-quotes, backslash, backslash. -# XXX: It is unexpected that the right-hand side evaluates to a single -# backslash. +# side before unescaping is double-quotes, backslash, backslash. .if ${:U\\} != "\\#hash" . error .endif # The right-hand side of a comparison is not parsed as a token, therefore # the code from CondParser_Token does not apply to it. +# TODO: Explain the consequences. +# TODO: Does this mean that more syntactic variants are allowed here? .if ${:U\#hash} != \#hash . error .endif diff --git a/contrib/bmake/unit-tests/cond-token-string.exp b/contrib/bmake/unit-tests/cond-token-string.exp index 39a9383953dd..5df4cc675bb1 100644 --- a/contrib/bmake/unit-tests/cond-token-string.exp +++ b/contrib/bmake/unit-tests/cond-token-string.exp @@ -1 +1,8 @@ -exit status 0 +make: Unknown modifier 'Z' +make: "cond-token-string.mk" line 9: Malformed conditional ("" != "${:Uvalue:Z}") +make: "cond-token-string.mk" line 18: xvalue is not defined. +make: "cond-token-string.mk" line 24: Malformed conditional (x${:Uvalue} == "") +make: "cond-token-string.mk" line 33: Expected. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/cond-token-string.mk b/contrib/bmake/unit-tests/cond-token-string.mk index 1a8019754824..7e110806d408 100644 --- a/contrib/bmake/unit-tests/cond-token-string.mk +++ b/contrib/bmake/unit-tests/cond-token-string.mk @@ -1,8 +1,39 @@ -# $NetBSD: cond-token-string.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: cond-token-string.mk,v 1.3 2020/11/10 22:23:37 rillig Exp $ # # Tests for quoted and unquoted string literals in .if conditions. # TODO: Implementation +# Cover the code in CondParser_String that frees the memory after parsing +# a variable expression based on an undefined variable. +.if "" != "${:Uvalue:Z}" +. error +.else +. error +.endif + +.if x${:Uvalue} +. error +.else +. info xvalue is not defined. +.endif + +# The 'x' produces a "Malformed conditional" since the left-hand side of a +# comparison in an .if directive must be either a variable expression, a +# quoted string literal or a number that starts with a digit. +.if x${:Uvalue} == "" +. error +.else +. error +.endif + +# In plain words, a '\' can be used to escape any character, just as in +# double-quoted string literals. See CondParser_String. +.if \x${:Uvalue} == "xvalue" +. info Expected. +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/cond-token-var.exp b/contrib/bmake/unit-tests/cond-token-var.exp index eb71a43c55f3..fcd92d12a3da 100644 --- a/contrib/bmake/unit-tests/cond-token-var.exp +++ b/contrib/bmake/unit-tests/cond-token-var.exp @@ -1,7 +1,7 @@ -make: "cond-token-var.mk" line 9: ok -make: "cond-token-var.mk" line 15: Malformed conditional (${UNDEF} == ${DEF}) -make: "cond-token-var.mk" line 20: Malformed conditional (${DEF} == ${UNDEF}) -make: "cond-token-var.mk" line 29: Malformed conditional (${UNDEF}) +make: "cond-token-var.mk" line 20: ok +make: "cond-token-var.mk" line 27: Malformed conditional (${UNDEF} == ${DEF}) +make: "cond-token-var.mk" line 33: Malformed conditional (${DEF} == ${UNDEF}) +make: "cond-token-var.mk" line 42: Malformed conditional (${UNDEF}) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-token-var.mk b/contrib/bmake/unit-tests/cond-token-var.mk index 6e55bd2d552d..30eba87ad4d2 100644 --- a/contrib/bmake/unit-tests/cond-token-var.mk +++ b/contrib/bmake/unit-tests/cond-token-var.mk @@ -1,6 +1,17 @@ -# $NetBSD: cond-token-var.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: cond-token-var.mk,v 1.5 2020/11/15 14:58:14 rillig Exp $ # -# Tests for variables in .if conditions. +# Tests for variable expressions in .if conditions. +# +# Note the fine distinction between a variable and a variable expression. +# A variable has a name and a value. To access the value, one writes a +# variable expression of the form ${VAR}. This is a simple variable +# expression. Variable expressions can get more complicated by adding +# variable modifiers such as in ${VAR:Mpattern}. +# +# XXX: Strictly speaking, variable modifiers should be called expression +# modifiers instead since they only modify the expression, not the variable. +# Well, except for the assignment modifiers, these do indeed change the value +# of the variable. DEF= defined @@ -12,11 +23,13 @@ DEF= defined .endif # A variable that appears on the left-hand side must be defined. +# The following line thus generates a parse error. .if ${UNDEF} == ${DEF} . error .endif # A variable that appears on the right-hand side must be defined. +# The following line thus generates a parse error. .if ${DEF} == ${UNDEF} . error .endif @@ -25,10 +38,11 @@ DEF= defined .if ${DEF} .endif -# An undefined variable generates a warning. +# An undefined variable on its own generates a parse error. .if ${UNDEF} .endif -# The :U modifier turns an undefined variable into an ordinary expression. +# The :U modifier turns an undefined expression into a defined expression. +# Since the expression is defined now, it doesn't generate any parse error. .if ${UNDEF:U} .endif diff --git a/contrib/bmake/unit-tests/cond-undef-lint.exp b/contrib/bmake/unit-tests/cond-undef-lint.exp index 365edae61275..2c4feb0376ff 100755 --- a/contrib/bmake/unit-tests/cond-undef-lint.exp +++ b/contrib/bmake/unit-tests/cond-undef-lint.exp @@ -1,7 +1,7 @@ make: "cond-undef-lint.mk" line 23: Variable "UNDEF" is undefined make: "cond-undef-lint.mk" line 38: Variable "UNDEF" is undefined make: "cond-undef-lint.mk" line 38: Variable "VAR." is undefined -make: "cond-undef-lint.mk" line 45: Variable "VAR.defined" is undefined +make: "cond-undef-lint.mk" line 49: Variable "VAR.defined" is undefined make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/cond-undef-lint.mk b/contrib/bmake/unit-tests/cond-undef-lint.mk index 334ceb594054..9dfd1bd53252 100755 --- a/contrib/bmake/unit-tests/cond-undef-lint.mk +++ b/contrib/bmake/unit-tests/cond-undef-lint.mk @@ -1,4 +1,4 @@ -# $NetBSD: cond-undef-lint.mk,v 1.2 2020/09/14 07:13:29 rillig Exp $ +# $NetBSD: cond-undef-lint.mk,v 1.3 2020/11/15 14:58:14 rillig Exp $ # # Tests for defined and undefined variables in .if conditions, in lint mode. # @@ -42,6 +42,10 @@ DEF= defined .endif # The variable VAR.defined is not defined and thus generates 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? .if ${VAR.${DEF}} . error .else diff --git a/contrib/bmake/unit-tests/cond1.exp b/contrib/bmake/unit-tests/cond1.exp index 38d616babdfb..b9db035833be 100644 --- a/contrib/bmake/unit-tests/cond1.exp +++ b/contrib/bmake/unit-tests/cond1.exp @@ -1,5 +1,5 @@ -make: "cond1.mk" line 75: warning: extra else -make: "cond1.mk" line 85: warning: extra else +make: "cond1.mk" line 80: warning: extra else +make: "cond1.mk" line 90: warning: extra else 2 is prime A='other' B='unknown' C='clever' o='no,no' Passed: diff --git a/contrib/bmake/unit-tests/cond1.mk b/contrib/bmake/unit-tests/cond1.mk index eedff8c1530b..53908c2dacf1 100644 --- a/contrib/bmake/unit-tests/cond1.mk +++ b/contrib/bmake/unit-tests/cond1.mk @@ -1,4 +1,9 @@ -# $NetBSD: cond1.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ +# $NetBSD: cond1.mk,v 1.3 2020/11/15 14:58:14 rillig Exp $ + +# TODO: Convert these tests into tutorial form. +# TODO: Split these tests by topic. +# TODO: Use better variable names and expression values that actually express +# the intended behavior. uname(1) has nothing to do with conditions. # hard code these! TEST_UNAME_S= NetBSD diff --git a/contrib/bmake/unit-tests/dep-double-colon.mk b/contrib/bmake/unit-tests/dep-double-colon.mk index 67a28a4315cd..70fddbcf21a4 100644 --- a/contrib/bmake/unit-tests/dep-double-colon.mk +++ b/contrib/bmake/unit-tests/dep-double-colon.mk @@ -1,6 +1,9 @@ -# $NetBSD: dep-double-colon.mk,v 1.4 2020/09/26 15:41:53 rillig Exp $ +# $NetBSD: dep-double-colon.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the :: operator in dependency declarations. +# Tests for the '::' operator in dependency declarations, which allows +# several dependency groups for a single node, each having its own attributes +# and dependencies. In the code, the additional dependency groups are called +# cohorts. all:: @echo 'command 1a' diff --git a/contrib/bmake/unit-tests/dep-exclam.mk b/contrib/bmake/unit-tests/dep-exclam.mk index 2779a66ea6e3..5f6b72da3fe0 100644 --- a/contrib/bmake/unit-tests/dep-exclam.mk +++ b/contrib/bmake/unit-tests/dep-exclam.mk @@ -1,6 +1,11 @@ -# $NetBSD: dep-exclam.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: dep-exclam.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the ! operator in dependency declarations. +# Tests for the ! operator in dependency declarations, which always re-creates +# the target, whether or not it is out of date. +# +# TODO: Is this related to OP_PHONY? +# TODO: Is this related to OP_EXEC? +# TODO: Is this related to OP_MAKE? # TODO: Implementation diff --git a/contrib/bmake/unit-tests/depsrc-ignore.mk b/contrib/bmake/unit-tests/depsrc-ignore.mk index 1be3eabe8806..aea7d24941ab 100644 --- a/contrib/bmake/unit-tests/depsrc-ignore.mk +++ b/contrib/bmake/unit-tests/depsrc-ignore.mk @@ -1,11 +1,10 @@ -# $NetBSD: depsrc-ignore.mk,v 1.4 2020/08/29 16:13:27 rillig Exp $ +# $NetBSD: depsrc-ignore.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $ # # Tests for the special source .IGNORE in dependency declarations, # which ignores any command failures for that target. # -# Even though ignore-errors fails, the all target is still made. -# Since the all target is not marked with .IGNORE, it stops at the -# first failing command. +# Even though 'ignore-errors' fails, 'all' is still made. Since 'all' is +# not marked with .IGNORE, it stops at the first failing command. # # XXX: The ordering of the messages in the output is confusing. # The "ignored" comes much too late to be related to the "false @@ -24,8 +23,8 @@ # This is what actually happens, as of 2020-08-29. To verify it, set the # following breakpoints in CompatRunCommand: # -# * the "!silent" line, to see all commands. -# * the "fflush" line, to see stdout being flushed. +# * the "!silent" line, to see all commands +# * the "fflush" line, to see stdout being flushed # * the "status = WEXITSTATUS" line # * the "(continuing)" line # * the "(ignored)" line diff --git a/contrib/bmake/unit-tests/depsrc-make.mk b/contrib/bmake/unit-tests/depsrc-make.mk index f7b5a9cca8ff..8069007e6e11 100644 --- a/contrib/bmake/unit-tests/depsrc-make.mk +++ b/contrib/bmake/unit-tests/depsrc-make.mk @@ -1,9 +1,11 @@ -# $NetBSD: depsrc-make.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# $NetBSD: depsrc-make.mk,v 1.4 2020/11/15 20:20:58 rillig Exp $ # # Tests for the special source .MAKE in dependency declarations, which # executes the commands of the target even if the -n or -t command line # options are given. +# TODO: Add a test for the -t command line option. + .MAKEFLAGS: -n all: this-is-made diff --git a/contrib/bmake/unit-tests/depsrc-optional.exp b/contrib/bmake/unit-tests/depsrc-optional.exp index 05f2ac6624c4..fce85b3cb38e 100644 --- a/contrib/bmake/unit-tests/depsrc-optional.exp +++ b/contrib/bmake/unit-tests/depsrc-optional.exp @@ -1,2 +1,20 @@ -`all' is up to date. +Make_ExpandUse: examine all +ExamineLater: need to examine "important" +Make_ExpandUse: examine important +ExamineLater: need to examine "optional" +ExamineLater: need to examine "optional-cohort" +Make_ExpandUse: examine optional +Make_ExpandUse: examine optional-cohort +Examining optional...non-existent...up-to-date. +Examining optional-cohort...non-existent...:: operator and no sources...out-of-date. +: A leaf node using '::' is considered out-of-date. + recheck(optional-cohort): update time from 0:00:00 Jan 01, 1970 to now +Examining important...non-existent...modified before source "optional-cohort"...out-of-date. +: important is made. + recheck(important): update time from 0:00:00 Jan 01, 1970 to now +Examining all...non-existent...modified before source "important"...out-of-date. +: all is made. + recheck(all): update time from 0:00:00 Jan 01, 1970 to now +Examining .END...non-existent...non-existent and no sources...out-of-date. + recheck(.END): update time from 0:00:00 Jan 01, 1970 to now exit status 0 diff --git a/contrib/bmake/unit-tests/depsrc-optional.mk b/contrib/bmake/unit-tests/depsrc-optional.mk index 75ae38bf3194..f12eeca2b3cb 100644 --- a/contrib/bmake/unit-tests/depsrc-optional.mk +++ b/contrib/bmake/unit-tests/depsrc-optional.mk @@ -1,18 +1,21 @@ -# $NetBSD: depsrc-optional.mk,v 1.3 2020/09/05 15:57:12 rillig Exp $ +# $NetBSD: depsrc-optional.mk,v 1.5 2020/11/08 10:33:47 rillig Exp $ # # Tests for the special source .OPTIONAL in dependency declarations, # which ignores the target if make cannot find out how to create it. # # TODO: Describe practical use cases for this feature. -# TODO: Explain why the commands for "important" are not executed. -# I had thought that only the "optional" commands were skipped. - all: important : ${.TARGET} is made. -important: optional +important: optional optional-cohort : ${.TARGET} is made. optional: .OPTIONAL - : This is not executed. + : An optional leaf node is not executed. + +# See IsOODateRegular. +optional-cohort:: .OPTIONAL + : A leaf node using '::' is considered out-of-date. + +.MAKEFLAGS: -dm diff --git a/contrib/bmake/unit-tests/depsrc-precious.mk b/contrib/bmake/unit-tests/depsrc-precious.mk index 699b83d767b1..e8522a300790 100644 --- a/contrib/bmake/unit-tests/depsrc-precious.mk +++ b/contrib/bmake/unit-tests/depsrc-precious.mk @@ -1,6 +1,14 @@ -# $NetBSD: depsrc-precious.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: depsrc-precious.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the special source .PRECIOUS in dependency declarations. +# Tests for the special source .PRECIOUS in dependency declarations, which +# is only relevant if the commands for the target fail or are interrupted. +# In such a case, the target file is usually removed, to avoid having +# half-finished files with a timestamp suggesting the file were up-to-date. +# +# For targets marked with .PRECIOUS, the target file is not removed. +# The author of the makefile is then responsible for avoiding the above +# situation, in which the target would be wrongly considered up-to-date, +# just because its timestamp says so. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/depsrc-usebefore.mk b/contrib/bmake/unit-tests/depsrc-usebefore.mk index c6be2bae0a9c..001cfb0d71c1 100644 --- a/contrib/bmake/unit-tests/depsrc-usebefore.mk +++ b/contrib/bmake/unit-tests/depsrc-usebefore.mk @@ -1,7 +1,11 @@ -# $NetBSD: depsrc-usebefore.mk,v 1.5 2020/08/22 11:53:18 rillig Exp $ +# $NetBSD: depsrc-usebefore.mk,v 1.6 2020/11/15 20:20:58 rillig Exp $ # # Tests for the special source .USEBEFORE in dependency declarations, # which allows to prepend common commands to other targets. +# +# See also: +# .USE +# depsrc-use.mk all: action directly diff --git a/contrib/bmake/unit-tests/depsrc.mk b/contrib/bmake/unit-tests/depsrc.mk index d461e1111d0f..15b27286de22 100644 --- a/contrib/bmake/unit-tests/depsrc.mk +++ b/contrib/bmake/unit-tests/depsrc.mk @@ -1,9 +1,11 @@ -# $NetBSD: depsrc.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: depsrc.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # # Tests for special sources (those starting with a dot, followed by # uppercase letters) in dependency declarations, such as .PHONY. # TODO: Implementation +# TODO: Test 'target: ${:U.SILENT}' + all: @:; diff --git a/contrib/bmake/unit-tests/deptgt-begin.exp b/contrib/bmake/unit-tests/deptgt-begin.exp index 527020f6818d..abc80afe9964 100644 --- a/contrib/bmake/unit-tests/deptgt-begin.exp +++ b/contrib/bmake/unit-tests/deptgt-begin.exp @@ -1,4 +1,7 @@ +make: "deptgt-begin.mk" line 17: warning: duplicate script for target ".BEGIN" ignored +make: "deptgt-begin.mk" line 8: warning: using previous script for ".BEGIN" defined here : parse time +: Making before-begin before .BEGIN. : .BEGIN : all exit status 0 diff --git a/contrib/bmake/unit-tests/deptgt-begin.mk b/contrib/bmake/unit-tests/deptgt-begin.mk index c6ca2f4aa3c7..b71d78f371ed 100644 --- a/contrib/bmake/unit-tests/deptgt-begin.mk +++ b/contrib/bmake/unit-tests/deptgt-begin.mk @@ -1,4 +1,4 @@ -# $NetBSD: deptgt-begin.mk,v 1.3 2020/08/29 17:34:21 rillig Exp $ +# $NetBSD: deptgt-begin.mk,v 1.5 2020/11/15 22:28:08 rillig Exp $ # # Tests for the special target .BEGIN in dependency declarations, # which is a container for commands that are run before any other @@ -7,6 +7,40 @@ .BEGIN: : $@ +# To register a custom action to be run at the beginning, the simplest way is +# to directly place some commands on the '.BEGIN' target. This doesn't scale +# though, since the ':' dependency operator prevents that any other place may +# add its commands after this. +# +# There are several ways to resolve this situation, which are detailed below. +.BEGIN: + : Making another $@. + +# One way to run commands at the beginning is to define a custom target and +# make the .BEGIN depend on that target. This way, the commands from the +# custom target are run even before the .BEGIN target. +.BEGIN: before-begin +before-begin: .PHONY .NOTMAIN + : Making $@ before .BEGIN. + +# Another way is to define a custom target and make that a .USE dependency. +# For the .BEGIN target, .USE dependencies do not work though, since in +# Compat_Run, the .USE and .USEBEFORE nodes are expanded right after the +# .BEGIN target has been run, which is too late. +.BEGIN: use +use: .USE .NOTMAIN + : Making $@ from a .USE dependency. + +# Same as with .USE, but run the commands before the main commands from the +# .BEGIN target. +# +# For the .BEGIN target, .USEBEFORE dependencies do not work though, since in +# Compat_Run, the .USE and .USEBEFORE nodes are expanded right after the +# .BEGIN target has been run, which is too late. +.BEGIN: use-before +use-before: .USEBEFORE .NOTMAIN + : Making $@ from a .USEBEFORE dependency. + all: : $@ diff --git a/contrib/bmake/unit-tests/deptgt-error.mk b/contrib/bmake/unit-tests/deptgt-error.mk index 07bc1b5d3408..5d515b95afc3 100644 --- a/contrib/bmake/unit-tests/deptgt-error.mk +++ b/contrib/bmake/unit-tests/deptgt-error.mk @@ -1,6 +1,7 @@ -# $NetBSD: deptgt-error.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: deptgt-error.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the special target .ERROR in dependency declarations. +# Tests for the special target .ERROR in dependency declarations, which +# collects commands that are run when another target fails. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/deptgt-ignore.mk b/contrib/bmake/unit-tests/deptgt-ignore.mk index 6ace0841f28b..49c14d2cfd43 100644 --- a/contrib/bmake/unit-tests/deptgt-ignore.mk +++ b/contrib/bmake/unit-tests/deptgt-ignore.mk @@ -1,6 +1,7 @@ -# $NetBSD: deptgt-ignore.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: deptgt-ignore.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the special target .IGNORE in dependency declarations. +# Tests for the special target .IGNORE in dependency declarations, which +# does not stop if a command from this target exits with a non-zero status. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/deptgt-interrupt.mk b/contrib/bmake/unit-tests/deptgt-interrupt.mk index d555f864563e..d94009a52e05 100644 --- a/contrib/bmake/unit-tests/deptgt-interrupt.mk +++ b/contrib/bmake/unit-tests/deptgt-interrupt.mk @@ -1,6 +1,8 @@ -# $NetBSD: deptgt-interrupt.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: deptgt-interrupt.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the special target .INTERRUPT in dependency declarations. +# Tests for the special target .INTERRUPT in dependency declarations, which +# collects commands to be run when make is interrupted while building another +# target. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/deptgt-main.mk b/contrib/bmake/unit-tests/deptgt-main.mk index cf1b1b4fd340..84d05dc25ed6 100644 --- a/contrib/bmake/unit-tests/deptgt-main.mk +++ b/contrib/bmake/unit-tests/deptgt-main.mk @@ -1,6 +1,8 @@ -# $NetBSD: deptgt-main.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: deptgt-main.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # -# Tests for the special target .MAIN in dependency declarations. +# Tests for the special target .MAIN in dependency declarations, which defines +# the main target. This main target is built if no target has been specified +# on the command line or via MAKEFLAGS. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/deptgt-makeflags.exp b/contrib/bmake/unit-tests/deptgt-makeflags.exp index a226cafc9ba1..7eb54eba7f30 100644 --- a/contrib/bmake/unit-tests/deptgt-makeflags.exp +++ b/contrib/bmake/unit-tests/deptgt-makeflags.exp @@ -6,4 +6,5 @@ Var_Parse: ${DOLLAR} != "\$\$" with VARE_UNDEFERR|VARE_WANTRES lhs = "$$", rhs = "$$", op = != Global:.MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d Global:.MAKEFLAGS = -r -k -D VAR -D VAR -d cv -d 0 +make: Unterminated quoted string [make VAR=initial UNBALANCED='] exit status 0 diff --git a/contrib/bmake/unit-tests/deptgt-makeflags.mk b/contrib/bmake/unit-tests/deptgt-makeflags.mk index 70a9cd0b590b..0a0f410e14c4 100644 --- a/contrib/bmake/unit-tests/deptgt-makeflags.mk +++ b/contrib/bmake/unit-tests/deptgt-makeflags.mk @@ -1,30 +1,35 @@ -# $NetBSD: deptgt-makeflags.mk,v 1.4 2020/10/23 14:48:49 rillig Exp $ +# $NetBSD: deptgt-makeflags.mk,v 1.6 2020/11/15 20:20:58 rillig Exp $ # # Tests for the special target .MAKEFLAGS in dependency declarations, # which adds command line options later, at parse time. +# +# In these unit tests, it is often used to temporarily toggle the debug log +# during parsing. # The -D option sets a variable in the "Global" scope and thus can be # undefined later. .MAKEFLAGS: -D VAR - .if ${VAR} != 1 . error .endif +# Variables that are set via the -D command line option are normal global +# variables and can thus be undefined later. .undef VAR - .if defined(VAR) . error .endif +# The -D command line option can define a variable again, after it has been +# undefined. .MAKEFLAGS: -D VAR - .if ${VAR} != 1 . error .endif +# The "dependency" for .MAKEFLAGS is split into words, interpreting the usual +# quotes and escape sequences from the backslash. .MAKEFLAGS: VAR="value"' with'\ spaces - .if ${VAR} != "value with spaces" . error .endif @@ -32,7 +37,6 @@ # Variables set on the command line as VAR=value are placed in the # "Command" scope and thus cannot be undefined. .undef VAR - .if ${VAR} != "value with spaces" . error .endif @@ -47,5 +51,43 @@ .endif .MAKEFLAGS: -d0 +# An empty command line is skipped. +.MAKEFLAGS: # none + +# Escape sequences like \n are interpreted. +# The following line looks as if it assigned a newline to nl, but it doesn't. +# Instead, the \n ends up as a line that is then interpreted as a variable +# assignment. At that point, the line is simply "nl=\n", and the \n is +# skipped since it is whitespace (see Parse_IsVar). +.MAKEFLAGS: nl="\n" +.if ${nl} != "" +. error +.endif + +# Next try at defining another newline variable. Since whitespace around the +# variable value is trimmed, two empty variable expressions surround the +# literal newline now. This prevents the newline from being skipped during +# parsing. The ':=' assignment operator expands the empty variable +# expressions, leaving only the newline as the variable value. +# +# This is one of the very few ways (maybe even the only one) to inject literal +# newlines into a line that is being parsed. This may confuse the parser. +# For example, in cond.c the parser only expects horizontal whitespace (' ' +# and '\t'), but no newlines. +#.MAKEFLAGS: -dcpv +.MAKEFLAGS: nl:="$${:U}\n$${:U}" +.if ${nl} != ${.newline} +. error +.endif +#.MAKEFLAGS: -d0 + +# Unbalanced quotes produce an error message. If they occur anywhere in the +# command line, the whole command line is skipped. +.MAKEFLAGS: VAR=previous +.MAKEFLAGS: VAR=initial UNBALANCED=' +.if ${VAR} != "previous" +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/deptgt-silent.exp b/contrib/bmake/unit-tests/deptgt-silent.exp index 6cab88f53144..c9b89da0ae5e 100644 --- a/contrib/bmake/unit-tests/deptgt-silent.exp +++ b/contrib/bmake/unit-tests/deptgt-silent.exp @@ -1,3 +1,5 @@ +echo 'This is a loud command.' +This is a loud command. This is not echoed because of the @. This is not echoed because of the .SILENT. exit status 0 diff --git a/contrib/bmake/unit-tests/deptgt-silent.mk b/contrib/bmake/unit-tests/deptgt-silent.mk index 64d54c00e632..335a1e897295 100644 --- a/contrib/bmake/unit-tests/deptgt-silent.mk +++ b/contrib/bmake/unit-tests/deptgt-silent.mk @@ -1,10 +1,15 @@ -# $NetBSD: deptgt-silent.mk,v 1.3 2020/09/10 21:40:50 rillig Exp $ +# $NetBSD: deptgt-silent.mk,v 1.4 2020/11/15 20:49:20 rillig Exp $ # # Tests for the special target .SILENT in dependency declarations. .SILENT: all -all: +all: loud @echo 'This is not echoed because of the @.' # Without the .SILENT, the following command would be echoed. echo 'This is not echoed because of the .SILENT.' + +# Demonstrate that the .SILENT only applies to the particular target. +# This is unlike .DELETE_ON_ERROR, which is a global setting. +loud: .PHONY + echo 'This is a loud command.' diff --git a/contrib/bmake/unit-tests/deptgt.exp b/contrib/bmake/unit-tests/deptgt.exp index 2b899313b938..fee0563f5b37 100644 --- a/contrib/bmake/unit-tests/deptgt.exp +++ b/contrib/bmake/unit-tests/deptgt.exp @@ -1,5 +1,13 @@ make: "deptgt.mk" line 10: warning: Extra target ignored make: "deptgt.mk" line 28: Unassociated shell command ": command3 # parse error, since targets == NULL" +ParseReadLine (34): '${:U}: empty-source' +ParseDoDependency(: empty-source) +ParseReadLine (35): ' : command for empty targets list' +ParseReadLine (36): ': empty-source' +ParseDoDependency(: empty-source) +ParseReadLine (37): ' : command for empty targets list' +ParseReadLine (38): '.MAKEFLAGS: -d0' +ParseDoDependency(.MAKEFLAGS: -d0) make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/deptgt.mk b/contrib/bmake/unit-tests/deptgt.mk index 517ed5aa2b75..83f81b6f58ed 100644 --- a/contrib/bmake/unit-tests/deptgt.mk +++ b/contrib/bmake/unit-tests/deptgt.mk @@ -1,4 +1,4 @@ -# $NetBSD: deptgt.mk,v 1.8 2020/10/18 13:02:10 rillig Exp $ +# $NetBSD: deptgt.mk,v 1.9 2020/11/15 11:57:00 rillig Exp $ # # Tests for special targets like .BEGIN or .SUFFIXES in dependency # declarations. @@ -27,5 +27,15 @@ target1 target2: sources # targets := [target1, target2] VAR=value # targets := NULL : command3 # parse error, since targets == NULL +# In a dependency declaration, the list of targets can be empty. +# It doesn't matter whether the empty string is generated by a variable +# expression or whether it is just omitted. +.MAKEFLAGS: -dp +${:U}: empty-source + : command for empty targets list +: empty-source + : command for empty targets list +.MAKEFLAGS: -d0 + all: @:; diff --git a/contrib/bmake/unit-tests/dir.mk b/contrib/bmake/unit-tests/dir.mk index 24ce47d959ed..55e22d88b803 100644 --- a/contrib/bmake/unit-tests/dir.mk +++ b/contrib/bmake/unit-tests/dir.mk @@ -1,4 +1,4 @@ -# $NetBSD: dir.mk,v 1.7 2020/10/31 21:30:03 rillig Exp $ +# $NetBSD: dir.mk,v 1.8 2020/11/03 18:42:33 rillig Exp $ # # Tests for dir.c. @@ -64,7 +64,8 @@ fetch fetch-post extract extract-post: : $@ # The expansions may have duplicates. -# These are merged together because of the dependency line. +# When the source of the dependency line is expanded later, each of the +# expanded words will be the same. all: dup-{1,1,1,1,1,1,1} dup-1: diff --git a/contrib/bmake/unit-tests/directive-elif.exp b/contrib/bmake/unit-tests/directive-elif.exp index 39a9383953dd..6219b4896795 100644 --- a/contrib/bmake/unit-tests/directive-elif.exp +++ b/contrib/bmake/unit-tests/directive-elif.exp @@ -1 +1,17 @@ -exit status 0 +make: "directive-elif.mk" line 7: begin .elif misspellings tests, part 1 +make: "directive-elif.mk" line 9: 1-then +make: "directive-elif.mk" line 18: begin .elif misspellings tests, part 2 +make: "directive-elif.mk" line 29: begin .elif misspellings tests, part 3 +make: "directive-elif.mk" line 41: which branch is taken on misspelling after false? +make: "directive-elif.mk" line 49: else +make: "directive-elif.mk" line 52: which branch is taken on misspelling after true? +make: "directive-elif.mk" line 54: 1-then +make: "directive-elif.mk" line 55: Unknown directive "elsif" +make: "directive-elif.mk" line 56: 1-elsif +make: "directive-elif.mk" line 57: Unknown directive "elsif" +make: "directive-elif.mk" line 58: 2-elsif +make: "directive-elif.mk" line 64: if-less elif +make: "directive-elif.mk" line 69: warning: extra elif +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-elif.mk b/contrib/bmake/unit-tests/directive-elif.mk index fc8bb7e7d197..f9a43abfffc1 100644 --- a/contrib/bmake/unit-tests/directive-elif.mk +++ b/contrib/bmake/unit-tests/directive-elif.mk @@ -1,8 +1,72 @@ -# $NetBSD: directive-elif.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-elif.mk,v 1.6 2020/11/12 19:46:36 rillig Exp $ # # Tests for the .elif directive. # TODO: Implementation +.info begin .elif misspellings tests, part 1 +.if 1 +. info 1-then +.elif 1 # ok +. info 1-elif +.elsif 1 # oops: misspelled +. info 1-elsif +.elseif 1 # oops: misspelled +. info 1-elseif +.endif + +.info begin .elif misspellings tests, part 2 +.if 0 +. info 0-then +.elif 0 # ok +. info 0-elif +.elsif 0 # oops: misspelled +. info 0-elsif +.elseif 0 # oops: misspelled +. info 0-elseif +.endif + +.info begin .elif misspellings tests, part 3 +.if 0 +. info 0-then +.elsif 0 # oops: misspelled +. info 0-elsif +.endif +.if 0 +. info 0-then +.elseif 0 # oops: misspelled +. info 0-elseif +.endif + +.info which branch is taken on misspelling after false? +.if 0 +. info 0-then +.elsif 1 +. info 1-elsif +.elsif 2 +. info 2-elsif +.else +. info else +.endif + +.info which branch is taken on misspelling after true? +.if 1 +. info 1-then +.elsif 1 +. info 1-elsif +.elsif 2 +. info 2-elsif +.else +. info else +.endif + +# Expect: "if-less elif" +.elif 0 + +.if 1 +.else +# Expect: "warning: if-less elif" +.elif +.endif + all: - @:; diff --git a/contrib/bmake/unit-tests/directive-else.exp b/contrib/bmake/unit-tests/directive-else.exp index 387577099b81..ca60595745a9 100644 --- a/contrib/bmake/unit-tests/directive-else.exp +++ b/contrib/bmake/unit-tests/directive-else.exp @@ -1,8 +1,11 @@ -make: "directive-else.mk" line 10: ok -make: "directive-else.mk" line 14: ok -make: "directive-else.mk" line 20: if-less else -make: "directive-else.mk" line 26: ok -make: "directive-else.mk" line 27: warning: extra else +make: "directive-else.mk" line 11: The .else directive does not take arguments. +make: "directive-else.mk" line 12: ok +make: "directive-else.mk" line 16: ok +make: "directive-else.mk" line 17: The .else directive does not take arguments. +make: "directive-else.mk" line 22: if-less else +make: "directive-else.mk" line 28: ok +make: "directive-else.mk" line 29: warning: extra else +make: "directive-else.mk" line 42: The .else directive does not take arguments. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/directive-else.mk b/contrib/bmake/unit-tests/directive-else.mk index 8fbbb5189ad5..fdd94007a1fa 100644 --- a/contrib/bmake/unit-tests/directive-else.mk +++ b/contrib/bmake/unit-tests/directive-else.mk @@ -1,7 +1,9 @@ -# $NetBSD: directive-else.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: directive-else.mk,v 1.6 2020/11/13 09:01:59 rillig Exp $ # # Tests for the .else directive. +.MAKEFLAGS: -dL # To enable the check for ".else <cond>" + # The .else directive does not take any arguments. # As of 2020-08-29, make doesn't warn about this. .if 0 @@ -28,5 +30,17 @@ . info After an extra .else, everything is skipped. .endif +# An .else may have a comment. This comment does not count as an argument, +# therefore no parse error. +.if 0 +.else # comment +.endif + +# A variable expression does count as an argument, even if it is empty. +# XXX: This should be a parse error. +.if 0 +.else ${:U} +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/directive-endif.mk b/contrib/bmake/unit-tests/directive-endif.mk index 12b608ffbeee..b0b531af2f06 100644 --- a/contrib/bmake/unit-tests/directive-endif.mk +++ b/contrib/bmake/unit-tests/directive-endif.mk @@ -1,8 +1,27 @@ -# $NetBSD: directive-endif.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-endif.mk,v 1.3 2020/11/12 22:40:11 rillig Exp $ # # Tests for the .endif directive. +# +# See also: +# Cond_EvalLine # TODO: Implementation +.MAKEFLAGS: -dL + +# Error: .endif does not take arguments +# XXX: Missing error message +.if 0 +.endif 0 + +# Error: .endif does not take arguments +# XXX: Missing error message +.if 1 +.endif 1 + +# Comments are allowed after an '.endif'. +.if 2 +.endif # comment + all: @:; diff --git a/contrib/bmake/unit-tests/directive-export-env.mk b/contrib/bmake/unit-tests/directive-export-env.mk index 49d1edb9f6fe..82b5e8087c6d 100644 --- a/contrib/bmake/unit-tests/directive-export-env.mk +++ b/contrib/bmake/unit-tests/directive-export-env.mk @@ -1,8 +1,12 @@ -# $NetBSD: directive-export-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-export-env.mk,v 1.3 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .export-env directive. # TODO: Implementation +.export-en # oops: misspelled +.export-env +.export-environment # oops: misspelled + all: @:; diff --git a/contrib/bmake/unit-tests/directive-export-gmake.mk b/contrib/bmake/unit-tests/directive-export-gmake.mk index 51de8fe55f64..d94cd9debf64 100644 --- a/contrib/bmake/unit-tests/directive-export-gmake.mk +++ b/contrib/bmake/unit-tests/directive-export-gmake.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-export-gmake.mk,v 1.2 2020/10/19 18:59:53 rillig Exp $ +# $NetBSD: directive-export-gmake.mk,v 1.3 2020/11/17 20:16:44 rillig Exp $ # # Tests for the export directive (without leading dot), as in GNU make. @@ -39,8 +39,8 @@ export VAR= leading spaces # may be silently discarded. One such shell is dash, which is the default # shell on Ubuntu and Debian. export VAR =trailing space in varname -.if ${:!env | grep trailing!} != "VAR =trailing space in varname" -. if ${:!env | grep trailing!} != "" # for dash +.if ${:!env | grep trailing || true!} != "VAR =trailing space in varname" +. if ${:!env | grep trailing || true!} != "" # for dash . error . endif .endif diff --git a/contrib/bmake/unit-tests/directive-export-literal.mk b/contrib/bmake/unit-tests/directive-export-literal.mk index 817c836fd6c4..51e5b522a3b9 100644 --- a/contrib/bmake/unit-tests/directive-export-literal.mk +++ b/contrib/bmake/unit-tests/directive-export-literal.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-export-literal.mk,v 1.5 2020/10/05 19:27:48 rillig Exp $ +# $NetBSD: directive-export-literal.mk,v 1.6 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .export-literal directive, which exports a variable value # without expanding it. @@ -7,5 +7,9 @@ UT_VAR= value with ${UNEXPANDED} expression .export-literal UT_VAR +.export-litera # oops: misspelled +.export-literal # oops: missing argument +.export-literally # oops: misspelled + all: @echo "$$UT_VAR" diff --git a/contrib/bmake/unit-tests/directive-export.exp b/contrib/bmake/unit-tests/directive-export.exp index 39a9383953dd..bd828b63c10c 100644 --- a/contrib/bmake/unit-tests/directive-export.exp +++ b/contrib/bmake/unit-tests/directive-export.exp @@ -1 +1,4 @@ -exit status 0 +make: "directive-export.mk" line 25: Unknown directive "expor" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-export.mk b/contrib/bmake/unit-tests/directive-export.mk index 6fbf8f09d4dc..bae50aecbdaf 100644 --- a/contrib/bmake/unit-tests/directive-export.mk +++ b/contrib/bmake/unit-tests/directive-export.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-export.mk,v 1.3 2020/10/29 17:27:12 rillig Exp $ +# $NetBSD: directive-export.mk,v 1.4 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .export directive. @@ -21,5 +21,11 @@ VAR= value $$ ${INDIRECT} . error .endif +# Tests for parsing the .export directive. +.expor # misspelled +.export # oops: missing argument +.export VARNAME +.exporting works # oops: misspelled + all: @:; diff --git a/contrib/bmake/unit-tests/directive-for.exp b/contrib/bmake/unit-tests/directive-for.exp index 88ab45529e3f..af610cc34edd 100755 --- a/contrib/bmake/unit-tests/directive-for.exp +++ b/contrib/bmake/unit-tests/directive-for.exp @@ -1,19 +1,19 @@ -make: "directive-for.mk" line 100: outer -make: "directive-for.mk" line 125: a:\ a:\file.txt -make: "directive-for.mk" line 125: d:\\ -make: "directive-for.mk" line 125: d:\\file.txt -make: "directive-for.mk" line 132: ( ( ( -make: "directive-for.mk" line 132: [ [ [ -make: "directive-for.mk" line 132: { { { -make: "directive-for.mk" line 132: ) ) ) -make: "directive-for.mk" line 132: ] ] ] -make: "directive-for.mk" line 132: } } } -make: "directive-for.mk" line 132: (()) (()) (()) -make: "directive-for.mk" line 132: [[]] [[]] [[]] -make: "directive-for.mk" line 132: {{}} {{}} {{}} -make: "directive-for.mk" line 132: )( )( )( -make: "directive-for.mk" line 132: ][ ][ ][ -make: "directive-for.mk" line 132: }{ }{ }{ -make: "directive-for.mk" line 140: outer value value -make: "directive-for.mk" line 140: outer "quoted" \"quoted\" +make: "directive-for.mk" line 108: outer +make: "directive-for.mk" line 133: a:\ a:\file.txt +make: "directive-for.mk" line 133: d:\\ +make: "directive-for.mk" line 133: d:\\file.txt +make: "directive-for.mk" line 140: ( ( ( +make: "directive-for.mk" line 140: [ [ [ +make: "directive-for.mk" line 140: { { { +make: "directive-for.mk" line 140: ) ) ) +make: "directive-for.mk" line 140: ] ] ] +make: "directive-for.mk" line 140: } } } +make: "directive-for.mk" line 140: (()) (()) (()) +make: "directive-for.mk" line 140: [[]] [[]] [[]] +make: "directive-for.mk" line 140: {{}} {{}} {{}} +make: "directive-for.mk" line 140: )( )( )( +make: "directive-for.mk" line 140: ][ ][ ][ +make: "directive-for.mk" line 140: }{ }{ }{ +make: "directive-for.mk" line 148: outer value value +make: "directive-for.mk" line 148: outer "quoted" \"quoted\" exit status 0 diff --git a/contrib/bmake/unit-tests/directive-for.mk b/contrib/bmake/unit-tests/directive-for.mk index e0987d331a14..93f0a14f5892 100755 --- a/contrib/bmake/unit-tests/directive-for.mk +++ b/contrib/bmake/unit-tests/directive-for.mk @@ -1,6 +1,13 @@ -# $NetBSD: directive-for.mk,v 1.8 2020/10/25 15:49:03 rillig Exp $ +# $NetBSD: directive-for.mk,v 1.9 2020/11/15 20:20:58 rillig Exp $ # # Tests for the .for directive. +# +# TODO: Describe naming conventions for the loop variables. +# .for f in values +# .for file in values +# .for _FILE_ in values +# .for .FILE. in values +# .for _f_ in values # Using the .for loop, lists of values can be produced. # In simple cases, the :@var@${var}@ variable modifier can be used to @@ -15,6 +22,7 @@ NUMBERS+= ${num} .endif # The .for loop also works for multiple iteration variables. +# This is something that the variable modifier :@ cannot do. .for name value in VARNAME value NAME2 value2 ${name}= ${value} .endfor @@ -26,7 +34,7 @@ ${name}= ${value} # just like the :M or :S variable modifiers. # # Until 2012-06-03, it had split the items exactly at whitespace, without -# taking the quotes into account. +# taking the quotes into account. This had resulted in 10 words. # .undef WORDS .for var in one t\ w\ o "three three" 'four four' `five six` diff --git a/contrib/bmake/unit-tests/directive-if-nested.exp b/contrib/bmake/unit-tests/directive-if-nested.exp new file mode 100644 index 000000000000..1a9ae02f07b2 --- /dev/null +++ b/contrib/bmake/unit-tests/directive-if-nested.exp @@ -0,0 +1,2 @@ +make: "directive-if-nested.inc" line 1001: deeply nested .if directives +exit status 0 diff --git a/contrib/bmake/unit-tests/directive-if-nested.mk b/contrib/bmake/unit-tests/directive-if-nested.mk new file mode 100644 index 000000000000..19c8e9452660 --- /dev/null +++ b/contrib/bmake/unit-tests/directive-if-nested.mk @@ -0,0 +1,25 @@ +# $NetBSD: directive-if-nested.mk,v 1.1 2020/11/10 22:23: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. +# +# See also: +# Cond_EvalLine + +GEN= directive-if-nested.inc + +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 '\n'; \ + printf 'all:\n'; \ + } > ${GEN} + +test: .PHONY + @${MAKE} -f ${GEN} + +tear-down: .PHONY + @rm -f ${GEN} diff --git a/contrib/bmake/unit-tests/directive-if.exp b/contrib/bmake/unit-tests/directive-if.exp index 39a9383953dd..21a33fe4cfd6 100644 --- a/contrib/bmake/unit-tests/directive-if.exp +++ b/contrib/bmake/unit-tests/directive-if.exp @@ -1 +1,15 @@ -exit status 0 +make: "directive-if.mk" line 13: 0 evaluates to false. +make: "directive-if.mk" line 17: 1 evaluates to true. +make: "directive-if.mk" line 40: Unknown directive "ifx" +make: "directive-if.mk" line 41: Unknown directive "error" +make: "directive-if.mk" line 42: if-less else +make: "directive-if.mk" line 43: Unknown directive "error" +make: "directive-if.mk" line 44: if-less endif +make: "directive-if.mk" line 47: Malformed conditional () +make: "directive-if.mk" line 57: Quotes in plain words are probably a mistake. +make: "directive-if.mk" line 66: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 70: Don't do this, always put a space after a directive. +make: "directive-if.mk" line 76: Don't do this, always put a space around comparison operators. +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-if.mk b/contrib/bmake/unit-tests/directive-if.mk index 72d7d0e2d920..3b1d13c7a0c0 100644 --- a/contrib/bmake/unit-tests/directive-if.mk +++ b/contrib/bmake/unit-tests/directive-if.mk @@ -1,8 +1,81 @@ -# $NetBSD: directive-if.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-if.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $ # # Tests for the .if directive. +# +# See also: +# cond-*.mk # TODO: Implementation +.if 0 +. error +.else +. info 0 evaluates to false. +.endif + +.if 1 +. info 1 evaluates to true. +.else +. error +.endif + +# There is no '.ifx'. +# +# The commit from 2005-05-01 intended to detect this situation, but it failed +# to do this since the call to is_token had its arguments switched. They were +# expected as (str, token, token_len) but were actually passed as (token, str, +# token_len). This made is_token return true even if the directive was +# directly followed by alphanumerical characters, which was wrong. The +# typical cases produced an error message such as "Malformed conditional +# (x 123)", while the intended error message was "Unknown directive". +# +# Back at that time, the commits only modified the main code but did not add +# the corresponding unit tests. This allowed the bug to hide for more than +# 15 years. +# +# Since 2020-11-10, the correct error message is produced. The '.ifx' is no +# longer interpreted as a variant of '.if', therefore the '.error' and '.else' +# are interpreted as ordinary directives, producing the error messages +# "if-less else" and "if-less endif". +.ifx 123 +. error +.else +. error +.endif + +# Missing condition. +.if +. error +.else +. error +.endif + +# A plain word must not start with a '"'. It may contain a embedded quotes +# though, which are kept. The quotes need not be balanced. The next space +# ends the word, and the remaining " || 1" is parsed as "or true". +.if ${:Uplain"""""} == plain""""" || 1 +. info Quotes in plain words are probably a mistake. +# XXX: Accepting quotes in plain words is probably a mistake as well. +.else +. error +.endif + +.if0 +. error +.else +. info Don't do this, always put a space after a directive. +.endif + +.if${:U-3} +. info Don't do this, always put a space after a directive. +.else +. error +.endif + +.if${:U-3}>-4 +. info Don't do this, always put a space around comparison operators. +.else +. error +.endif + all: - @:; diff --git a/contrib/bmake/unit-tests/directive-ifdef.exp b/contrib/bmake/unit-tests/directive-ifdef.exp index 39a9383953dd..b8453ecc4124 100644 --- a/contrib/bmake/unit-tests/directive-ifdef.exp +++ b/contrib/bmake/unit-tests/directive-ifdef.exp @@ -1 +1,2 @@ +make: "directive-ifdef.mk" line 12: Function calls in .ifdef are possible. exit status 0 diff --git a/contrib/bmake/unit-tests/directive-ifdef.mk b/contrib/bmake/unit-tests/directive-ifdef.mk index 64f073fb5ae1..516e095c464f 100644 --- a/contrib/bmake/unit-tests/directive-ifdef.mk +++ b/contrib/bmake/unit-tests/directive-ifdef.mk @@ -1,8 +1,18 @@ -# $NetBSD: directive-ifdef.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-ifdef.mk,v 1.3 2020/11/08 22:38:28 rillig Exp $ # # Tests for the .ifdef directive. # TODO: Implementation +DEFINED= defined + +# It looks redundant to have a call to defined() in an .ifdef, but it's +# possible. The .ifdef only affects plain symbols, not function calls. +.ifdef defined(DEFINED) +. info Function calls in .ifdef are possible. +.else +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/directive-ifmake.exp b/contrib/bmake/unit-tests/directive-ifmake.exp index 5fefeb252b48..fd4bcae151a0 100644 --- a/contrib/bmake/unit-tests/directive-ifmake.exp +++ b/contrib/bmake/unit-tests/directive-ifmake.exp @@ -1,9 +1,10 @@ -make: "directive-ifmake.mk" line 8: ok: positive condition works -make: "directive-ifmake.mk" line 19: ok: negation works -make: "directive-ifmake.mk" line 25: ok: double negation works -make: "directive-ifmake.mk" line 32: ok: both mentioned -make: "directive-ifmake.mk" line 39: ok: only those mentioned -make: "directive-ifmake.mk" line 49: Targets can even be added at parse time. +make: "directive-ifmake.mk" line 13: ok: positive condition works +make: "directive-ifmake.mk" line 24: ok: negation works +make: "directive-ifmake.mk" line 33: ok: double negation works +make: "directive-ifmake.mk" line 40: ok: both mentioned +make: "directive-ifmake.mk" line 47: ok: only those mentioned +make: "directive-ifmake.mk" line 57: Targets can even be added at parse time. +make: "directive-ifmake.mk" line 75: ok : first : second : late-target diff --git a/contrib/bmake/unit-tests/directive-ifmake.mk b/contrib/bmake/unit-tests/directive-ifmake.mk index 20329bc5ce25..4d49add72626 100644 --- a/contrib/bmake/unit-tests/directive-ifmake.mk +++ b/contrib/bmake/unit-tests/directive-ifmake.mk @@ -1,44 +1,52 @@ -# $NetBSD: directive-ifmake.mk,v 1.4 2020/08/30 14:25:45 rillig Exp $ +# $NetBSD: directive-ifmake.mk,v 1.8 2020/11/15 20:20:58 rillig Exp $ # # Tests for the .ifmake directive, which provides a shortcut for asking # whether a certain target is requested to be made from the command line. +# +# TODO: Describe why the shortcut may be useful (if it's useful at all), +# instead of sticking to the simple '.if' only. + +# The targets 'first' and 'second' are passed in on the command line. # This is the most basic form. .ifmake first -.info ok: positive condition works +. info ok: positive condition works .else -.warning positive condition fails +. warning positive condition fails .endif # The not operator works as expected. # An alternative interpretation were that this condition is asking whether # the target "!first" was requested. To distinguish this, see the next test. .ifmake !first -.warning unexpected +. warning unexpected .else -.info ok: negation works +. info ok: negation works .endif # See if the exclamation mark really means "not", or if it is just part of -# the target name. +# the target name. Since it means 'not', the two exclamation marks are +# effectively ignored, and 'first' is indeed a requested target. If the +# exclamation mark were part of the name instead, the name would be '!!first', +# and such a target was not requested to be made. .ifmake !!first -.info ok: double negation works +. info ok: double negation works .else -.warning double negation fails +. warning double negation fails .endif # Multiple targets can be combined using the && and || operators. .ifmake first && second -.info ok: both mentioned +. info ok: both mentioned .else -.warning && does not work as expected +. warning && does not work as expected .endif # Negation also works in complex conditions. .ifmake first && !unmentioned -.info ok: only those mentioned +. info ok: only those mentioned .else -.warning && with ! does not work as expected +. warning && with ! does not work as expected .endif # Using the .MAKEFLAGS special dependency target, arbitrary command @@ -46,10 +54,29 @@ # possible to extend the targets to be made. .MAKEFLAGS: late-target .ifmake late-target -.info Targets can even be added at parse time. +. info Targets can even be added at parse time. +.else +. info No, targets cannot be added at parse time anymore. +.endif + +# Numbers are interpreted as numbers, no matter whether the directive is +# a plain .if or an .ifmake. +.ifmake 0 +. error +.endif +.ifmake 1 .else -.info No, targets cannot be added at parse time anymore. +. error .endif +# A condition that consists of a variable expression only (without any +# comparison operator) can be used with .if and the other .ifxxx directives. +.ifmake ${:Ufirst} +. info ok +.else +. error +.endif + + first second unmentioned late-target: : $@ diff --git a/contrib/bmake/unit-tests/directive-include.exp b/contrib/bmake/unit-tests/directive-include.exp index 3a75ce38728b..af56eefb2b88 100755 --- a/contrib/bmake/unit-tests/directive-include.exp +++ b/contrib/bmake/unit-tests/directive-include.exp @@ -2,4 +2,7 @@ CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" lhs = "directive-include.mk null", rhs = "directive-include.mk null", op = != CondParser_Eval: ${.MAKE.MAKEFILES:T} != "${.PARSEFILE} null" lhs = "directive-include.mk null", rhs = "directive-include.mk null", op = != -exit status 0 +make: "directive-include.mk" line 25: Could not find nonexistent.mk +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-include.mk b/contrib/bmake/unit-tests/directive-include.mk index d71b27ef2c63..120706cef8d7 100755 --- a/contrib/bmake/unit-tests/directive-include.mk +++ b/contrib/bmake/unit-tests/directive-include.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-include.mk,v 1.3 2020/10/31 23:01:23 rillig Exp $ +# $NetBSD: directive-include.mk,v 1.4 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .include directive, which includes another file. @@ -22,5 +22,10 @@ . error .endif +.include "nonexistent.mk" +.include "/dev/null" # size 0 +# including a directory technically succeeds, but shouldn't. +#.include "." # directory + all: @:; diff --git a/contrib/bmake/unit-tests/directive-info.exp b/contrib/bmake/unit-tests/directive-info.exp index 39a9383953dd..971f417b706a 100644 --- a/contrib/bmake/unit-tests/directive-info.exp +++ b/contrib/bmake/unit-tests/directive-info.exp @@ -1 +1,14 @@ -exit status 0 +make: "directive-info.mk" line 7: begin .info tests +make: "directive-info.mk" line 8: Unknown directive "inf" +make: "directive-info.mk" line 9: Unknown directive "info" +make: "directive-info.mk" line 10: message +make: "directive-info.mk" line 11: indented message +make: "directive-info.mk" line 12: Unknown directive "information" +make: "directive-info.mk" line 13: message +make: "directive-info.mk" line 18: Unknown directive "info" +make: "directive-info.mk" line 19: Unknown directive "info" +make: "directive-info.mk" line 22: Unknown directive "info-message" +make: "directive-info.mk" line 23: no-target: no-source +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-info.mk b/contrib/bmake/unit-tests/directive-info.mk index 3eb972ad7a0e..bbfc80ea0c9a 100644 --- a/contrib/bmake/unit-tests/directive-info.mk +++ b/contrib/bmake/unit-tests/directive-info.mk @@ -1,8 +1,27 @@ -# $NetBSD: directive-info.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-info.mk,v 1.4 2020/11/15 11:57:00 rillig Exp $ # # Tests for the .info directive. # TODO: Implementation +.info begin .info tests +.inf # misspelled +.info # oops: message should be "missing parameter" +.info message +.info indented message +.information +.information message # oops: misspelled +.info.man: # not a message, but possibly a suffix rule + +# Even if lines would have trailing whitespace, this would be trimmed by +# ParseGetLine. +.info +.info # comment + +.info: message # This is a dependency declaration. +.info-message # This is an unknown directive. +.info no-target: no-source # This is a .info directive, not a dependency. +# See directive.mk for more tests of this kind. + all: @:; diff --git a/contrib/bmake/unit-tests/directive-sinclude.mk b/contrib/bmake/unit-tests/directive-sinclude.mk index b1faa7d41e65..1932e7b3ba13 100755 --- a/contrib/bmake/unit-tests/directive-sinclude.mk +++ b/contrib/bmake/unit-tests/directive-sinclude.mk @@ -1,7 +1,11 @@ -# $NetBSD: directive-sinclude.mk,v 1.1 2020/09/13 09:20:23 rillig Exp $ +# $NetBSD: directive-sinclude.mk,v 1.2 2020/11/15 20:20:58 rillig Exp $ # # Tests for the .sinclude directive, which includes another file, # silently skipping it if it cannot be opened. +# +# The 'silently skipping' only applies to the case where the file cannot be +# opened. Parse errors and other errors are handled the same way as in the +# other .include directives. # TODO: Implementation diff --git a/contrib/bmake/unit-tests/directive-undef.exp b/contrib/bmake/unit-tests/directive-undef.exp index 39a9383953dd..303d5a3e2a27 100644 --- a/contrib/bmake/unit-tests/directive-undef.exp +++ b/contrib/bmake/unit-tests/directive-undef.exp @@ -1 +1,4 @@ -exit status 0 +make: "directive-undef.mk" line 16: Unknown directive "unde" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-undef.mk b/contrib/bmake/unit-tests/directive-undef.mk index aac110437686..c72513a1bf5a 100644 --- a/contrib/bmake/unit-tests/directive-undef.mk +++ b/contrib/bmake/unit-tests/directive-undef.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-undef.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: directive-undef.mk,v 1.5 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .undef directive. @@ -13,5 +13,9 @@ . warning $1$2$3 .endif +.unde # misspelled +.undef # oops: missing argument +.undefined # oops: misspelled + all: @:; diff --git a/contrib/bmake/unit-tests/directive-unexport-env.mk b/contrib/bmake/unit-tests/directive-unexport-env.mk index 34d867d706ef..637286af0d6b 100644 --- a/contrib/bmake/unit-tests/directive-unexport-env.mk +++ b/contrib/bmake/unit-tests/directive-unexport-env.mk @@ -1,8 +1,12 @@ -# $NetBSD: directive-unexport-env.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-unexport-env.mk,v 1.3 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .unexport-env directive. # TODO: Implementation +.unexport-en # oops: misspelled +.unexport-env # ok +.unexport-environment # oops: misspelled + all: @:; diff --git a/contrib/bmake/unit-tests/directive-unexport.exp b/contrib/bmake/unit-tests/directive-unexport.exp index 263a2fedcc0b..72b24e7344fc 100644 --- a/contrib/bmake/unit-tests/directive-unexport.exp +++ b/contrib/bmake/unit-tests/directive-unexport.exp @@ -2,4 +2,7 @@ make: "directive-unexport.mk" line 14: UT_A=a UT_B=b UT_C=c make: "directive-unexport.mk" line 15: UT_A UT_B UT_C make: "directive-unexport.mk" line 23: UT_A=a UT_B=b UT_C=c make: "directive-unexport.mk" line 24: -exit status 0 +make: "directive-unexport.mk" line 26: Unknown directive "unexpor" +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-unexport.mk b/contrib/bmake/unit-tests/directive-unexport.mk index b44932904805..3ba4a1b1f307 100644 --- a/contrib/bmake/unit-tests/directive-unexport.mk +++ b/contrib/bmake/unit-tests/directive-unexport.mk @@ -1,4 +1,4 @@ -# $NetBSD: directive-unexport.mk,v 1.4 2020/10/30 23:54:42 sjg Exp $ +# $NetBSD: directive-unexport.mk,v 1.5 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .unexport directive. @@ -23,5 +23,9 @@ UT_C= c .info ${:!env|sort|grep '^UT_'!} .info ${.MAKE.EXPORTED} +.unexpor # misspelled +.unexport # oops: missing argument +.unexporting works # oops: misspelled + all: @:; diff --git a/contrib/bmake/unit-tests/directive-warning.exp b/contrib/bmake/unit-tests/directive-warning.exp index 39a9383953dd..630285fd3612 100644 --- a/contrib/bmake/unit-tests/directive-warning.exp +++ b/contrib/bmake/unit-tests/directive-warning.exp @@ -1 +1,11 @@ -exit status 0 +make: "directive-warning.mk" line 7: Unknown directive "warn" +make: "directive-warning.mk" line 8: Unknown directive "warn" +make: "directive-warning.mk" line 9: Unknown directive "warnin" +make: "directive-warning.mk" line 10: Unknown directive "warnin" +make: "directive-warning.mk" line 11: Unknown directive "warning" +make: "directive-warning.mk" line 12: warning: message +make: "directive-warning.mk" line 13: Unknown directive "warnings" +make: "directive-warning.mk" line 14: warning: messages +make: Fatal errors encountered -- cannot continue +make: stopped in unit-tests +exit status 1 diff --git a/contrib/bmake/unit-tests/directive-warning.mk b/contrib/bmake/unit-tests/directive-warning.mk index e1e636e3ec9f..75560aa9e4df 100644 --- a/contrib/bmake/unit-tests/directive-warning.mk +++ b/contrib/bmake/unit-tests/directive-warning.mk @@ -1,8 +1,17 @@ -# $NetBSD: directive-warning.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive-warning.mk,v 1.3 2020/11/03 17:17:31 rillig Exp $ # # Tests for the .warning directive. # TODO: Implementation +.warn # misspelled +.warn message # misspelled +.warnin # misspelled +.warnin message # misspelled +.warning # oops: should be "missing argument" +.warning message # ok +.warnings # misspelled +.warnings messages # oops + all: @:; diff --git a/contrib/bmake/unit-tests/directive.exp b/contrib/bmake/unit-tests/directive.exp index 39a9383953dd..b93d768169ab 100644 --- a/contrib/bmake/unit-tests/directive.exp +++ b/contrib/bmake/unit-tests/directive.exp @@ -1 +1,12 @@ -exit status 0 +make: "directive.mk" line 9: Unknown directive "indented" +make: "directive.mk" line 10: Unknown directive "indented" +make: "directive.mk" line 11: Unknown directive "indented" +make: "directive.mk" line 15: Unknown directive "info" +Global:.info = +Global:.info = value +make: "directive.mk" line 26: := value +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/contrib/bmake/unit-tests/directive.mk b/contrib/bmake/unit-tests/directive.mk index 8d01a49a34cf..d463ce4f009a 100644 --- a/contrib/bmake/unit-tests/directive.mk +++ b/contrib/bmake/unit-tests/directive.mk @@ -1,8 +1,35 @@ -# $NetBSD: directive.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: directive.mk,v 1.4 2020/11/15 11:57:00 rillig Exp $ # # Tests for the preprocessing directives, such as .if or .info. # TODO: Implementation +# Unknown directives are correctly named in the error messages, +# even if they are indented. +.indented none +. indented 2 spaces +. indented tab + +# Directives must be written directly, not indirectly via variable +# expressions. +.${:Uinfo} directives cannot be indirect + +# There is no directive called '.target', therefore this is parsed as a +# dependency declaration with 2 targets and 1 source. +.target target: source + +# This looks ambiguous. It could be either an .info message or a variable +# assignment. It is a variable assignment. +.MAKEFLAGS: -dv +.info:= value +.info?= value # This is a variable assignment as well. +.info := value # The space after the '.info' makes this + # a directive. +.MAKEFLAGS: -d0 + +# This is a dependency since directives must be given directly. +# Not even the space after the '.info' can change anything about this. +.${:Uinfo} : source + all: @:; diff --git a/contrib/bmake/unit-tests/directives.exp b/contrib/bmake/unit-tests/directives.exp deleted file mode 100644 index 15dd9aa9e962..000000000000 --- a/contrib/bmake/unit-tests/directives.exp +++ /dev/null @@ -1,42 +0,0 @@ -make: "directives.mk" line 10: begin .export tests -make: "directives.mk" line 11: Unknown directive "expor" -make: "directives.mk" line 20: begin .export-env tests -make: "directives.mk" line 30: begin .export-literal tests -make: "directives.mk" line 40: begin .info tests -make: "directives.mk" line 41: Unknown directive "inf" -make: "directives.mk" line 42: Unknown directive "info" -make: "directives.mk" line 43: message -make: "directives.mk" line 44: indented message -make: "directives.mk" line 45: Unknown directive "information" -make: "directives.mk" line 46: message -make: "directives.mk" line 50: begin .undef tests -make: "directives.mk" line 51: Unknown directive "unde" -make: "directives.mk" line 60: begin .unexport tests -make: "directives.mk" line 61: Unknown directive "unexpor" -make: "directives.mk" line 70: begin .unexport-env tests -make: "directives.mk" line 80: begin .warning tests -make: "directives.mk" line 81: Unknown directive "warn" -make: "directives.mk" line 82: Unknown directive "warnin" -make: "directives.mk" line 83: Unknown directive "warning" -make: "directives.mk" line 84: warning: message -make: "directives.mk" line 85: Unknown directive "warnings" -make: "directives.mk" line 86: warning: messages -make: "directives.mk" line 90: begin .elif misspellings tests, part 1 -make: "directives.mk" line 100: begin .elif misspellings tests, part 2 -make: "directives.mk" line 110: begin .elif misspellings tests, part 3 -make: "directives.mk" line 120: which branch is taken on misspelling after false? -make: "directives.mk" line 127: else taken -make: "directives.mk" line 130: which branch is taken on misspelling after true? -make: "directives.mk" line 132: Unknown directive "elsif" -make: "directives.mk" line 133: 1 taken -make: "directives.mk" line 134: Unknown directive "elsif" -make: "directives.mk" line 135: 2 taken -make: "directives.mk" line 140: Unknown directive "indented" -make: "directives.mk" line 141: Unknown directive "indented" -make: "directives.mk" line 142: Unknown directive "indented" -make: "directives.mk" line 143: Unknown directive "info" -make: "directives.mk" line 150: Could not find nonexistent.mk -make: "directives.mk" line 160: end of the tests -make: Fatal errors encountered -- cannot continue -make: stopped in unit-tests -exit status 1 diff --git a/contrib/bmake/unit-tests/directives.mk b/contrib/bmake/unit-tests/directives.mk deleted file mode 100644 index 436a5d35e4ec..000000000000 --- a/contrib/bmake/unit-tests/directives.mk +++ /dev/null @@ -1,163 +0,0 @@ -# $NetBSD: directives.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ -# -# Tests for parsing directives, in the same order as in the manual page. -# -# Each test group has 10 lines, to keep the line numbers in directives.exp -# stable. -# -# no tests for .error since it exits immediately, see ParseMessage. - -.info begin .export tests -.expor # misspelled -.export # oops: missing argument -.export VARNAME -.exporting works # oops: misspelled - - - - - -.info begin .export-env tests -.export-en # oops: misspelled -.export-env -.export-environment # oops: misspelled - - - - - - -.info begin .export-literal tests -.export-litera # oops: misspelled -.export-literal # oops: missing argument -.export-literal VARNAME -.export-literally # oops: misspelled - - - - - -.info begin .info tests -.inf # misspelled -.info # oops: message should be "missing parameter" -.info message -.info indented message -.information -.information message # oops: misspelled -.info.man: # not a message, but a suffix rule - - -.info begin .undef tests -.unde # misspelled -.undef # oops: missing argument -.undefined # oops: misspelled -.undef VARNAME - - - - - -.info begin .unexport tests -.unexpor # misspelled -.unexport # oops: missing argument -.unexport VARNAME # ok -.unexporting works # oops: misspelled - - - - - -.info begin .unexport-env tests -.unexport-en # misspelled -.unexport-env # ok -.unexport-environment # oops: misspelled - - - - - - -.info begin .warning tests -.warn # misspelled -.warnin # misspelled -.warning # oops: should be "missing argument" -.warning message # ok -.warnings # misspelled -.warnings messages # oops - - - -.info begin .elif misspellings tests, part 1 -.if 1 -.elif 1 # ok -.elsif 1 # oops: misspelled -.elseif 1 # oops: misspelled -.endif - - - - -.info begin .elif misspellings tests, part 2 -.if 0 -.elif 0 # ok -.elsif 0 # oops: misspelled -.elseif 0 # oops: misspelled -.endif - - - - -.info begin .elif misspellings tests, part 3 -.if 0 -.elsif 0 # oops: misspelled -.endif -.if 0 -.elseif 0 # oops: misspelled -.endif - - - -.info which branch is taken on misspelling after false? -.if 0 -.elsif 1 -. info 1 taken -.elsif 2 -. info 2 taken -.else -. info else taken -.endif - -.info which branch is taken on misspelling after true? -.if 1 -.elsif 1 -. info 1 taken -.elsif 2 -. info 2 taken -.else -. info else taken -.endif - -.indented none -. indented 2 spaces -. indented tab -.${:Uinfo} directives cannot be indirect - - - - - - -.include "nonexistent.mk" -.include "/dev/null" # size 0 -# including a directory technically succeeds, but shouldn't. -#.include "." # directory - - - - - - -.info end of the tests - -all: - @: diff --git a/contrib/bmake/unit-tests/dollar.exp b/contrib/bmake/unit-tests/dollar.exp index 496adc02f157..9b8c9d638a87 100644 --- a/contrib/bmake/unit-tests/dollar.exp +++ b/contrib/bmake/unit-tests/dollar.exp @@ -1,7 +1,7 @@ Printing dollar from literals and variables -To survive the parser, a dollar character must be doubled. +To survive the parser, a dollar sign must be doubled. 1 dollar literal => <single-quote-var-value> 1 dollar literal eol => <> 2 dollar literal => <$> diff --git a/contrib/bmake/unit-tests/dollar.mk b/contrib/bmake/unit-tests/dollar.mk index b7f7d9fa7c9e..8a06c5bf722b 100644 --- a/contrib/bmake/unit-tests/dollar.mk +++ b/contrib/bmake/unit-tests/dollar.mk @@ -1,6 +1,6 @@ -# $NetBSD: dollar.mk,v 1.3 2020/05/17 09:37:48 rillig Exp $ +# $NetBSD: dollar.mk,v 1.4 2020/11/03 18:21:36 rillig Exp $ # -# Test the various places where a dollar character can appear and +# Test the various places where a dollar sign can appear and # see what happens. There are lots of surprises here. # @@ -30,7 +30,7 @@ ${:U'}= single-quote-var-value' all: $H 'Printing dollar from literals and variables' - $C 'To survive the parser, a dollar character must be doubled.' + $C 'To survive the parser, a dollar sign must be doubled.' $T '1 dollar literal' '$' $T '1 dollar literal eol' ''$ $T '2 dollar literal' '$$' diff --git a/contrib/bmake/unit-tests/envfirst.mk b/contrib/bmake/unit-tests/envfirst.mk index fedcc0a75056..b5cfc4f5c578 100644 --- a/contrib/bmake/unit-tests/envfirst.mk +++ b/contrib/bmake/unit-tests/envfirst.mk @@ -1,7 +1,9 @@ -# $NetBSD: envfirst.mk,v 1.3 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: envfirst.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # The -e option makes environment variables stronger than global variables. +.MAKEFLAGS: -e + .if ${FROM_ENV} != value-from-env . error ${FROM_ENV} .endif diff --git a/contrib/bmake/unit-tests/error.exp b/contrib/bmake/unit-tests/error.exp index 8d0ebef89e8e..3adc099a4625 100644 --- a/contrib/bmake/unit-tests/error.exp +++ b/contrib/bmake/unit-tests/error.exp @@ -1,6 +1,6 @@ -make: "error.mk" line 3: just FYI -make: "error.mk" line 4: warning: this could be serious -make: "error.mk" line 5: this is fatal +make: "error.mk" line 6: just FYI +make: "error.mk" line 7: warning: this could be serious +make: "error.mk" line 8: this is fatal make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/error.mk b/contrib/bmake/unit-tests/error.mk index 6e2654dbea72..0029b3bc6aa9 100644 --- a/contrib/bmake/unit-tests/error.mk +++ b/contrib/bmake/unit-tests/error.mk @@ -1,10 +1,12 @@ -# $NetBSD: error.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ +# $NetBSD: error.mk,v 1.3 2020/11/03 17:38:45 rillig Exp $ +# +# Demonstrate that the .error directive exits immediately, without +# continuing parsing until the end of the file. .info just FYI .warning this could be serious .error this is fatal +.info this is not reached because of the .error above all: - -.info.html: - @echo this should be ignored + : this is not reached because of the .error diff --git a/contrib/bmake/unit-tests/escape.mk b/contrib/bmake/unit-tests/escape.mk index 264b124bf1ad..8bdd3ad2ab49 100644 --- a/contrib/bmake/unit-tests/escape.mk +++ b/contrib/bmake/unit-tests/escape.mk @@ -1,4 +1,4 @@ -# $NetBSD: escape.mk,v 1.13 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: escape.mk,v 1.14 2020/11/03 17:38:45 rillig Exp $ # # Test backslash escaping. @@ -187,7 +187,7 @@ var-1bsnl-space: .PHONY __printvars \ # Backslash-newline in a command is retained. # # The "#" in "# second line without space" makes it a comment instead -# of a syntax error if the preceding line is parsed incorretly. +# of a syntax error if the preceding line is parsed incorrectly. # The ":" in "third line':" makes it look like the start of a # target instead of a syntax error if the first line is parsed incorrectly. # @@ -220,7 +220,7 @@ cmd-1bsnl-eof: # XXX: This may differ from POSIX, but matches gmake. # # When make passes two backslashes to the shell, the shell will pass one -# backslash to the echo commant. +# backslash to the echo command. # all: cmd-2bsnl cmd-2bsnl: .PHONY diff --git a/contrib/bmake/unit-tests/forloop.exp b/contrib/bmake/unit-tests/forloop.exp index 63b67c15bcc6..422711b41247 100644 --- a/contrib/bmake/unit-tests/forloop.exp +++ b/contrib/bmake/unit-tests/forloop.exp @@ -1,17 +1,17 @@ -x=one -x="two and three" -x=four -x="five" -x=-I/this -x=-I"This or that" -x=-Ithat -x="-DTHIS=\"this and that\"" -cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" -newline-item=(a) -a=one b="two and three" -a=four b="five" -a=ONE b="TWO AND THREE" -a=FOUR b="FIVE" +make: "forloop.mk" line 14: x=one +make: "forloop.mk" line 14: x="two and three" +make: "forloop.mk" line 14: x=four +make: "forloop.mk" line 14: x="five" +make: "forloop.mk" line 20: x=-I/this +make: "forloop.mk" line 20: x=-I"This or that" +make: "forloop.mk" line 20: x=-Ithat +make: "forloop.mk" line 20: x="-DTHIS=\"this and that\"" +make: "forloop.mk" line 27: cfl=-I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" +make: "forloop.mk" line 41: newline-item=(a) +make: "forloop.mk" line 47: a=one b="two and three" +make: "forloop.mk" line 47: a=four b="five" +make: "forloop.mk" line 47: a=ONE b="TWO AND THREE" +make: "forloop.mk" line 47: a=FOUR b="FIVE" We expect an error next: make: "forloop.mk" line 46: Wrong number of words (9) in .for substitution list with 2 variables make: Fatal errors encountered -- cannot continue diff --git a/contrib/bmake/unit-tests/forloop.mk b/contrib/bmake/unit-tests/forloop.mk index 0162ffa27a07..cef05cbe4c61 100644 --- a/contrib/bmake/unit-tests/forloop.mk +++ b/contrib/bmake/unit-tests/forloop.mk @@ -1,4 +1,4 @@ -# $NetBSD: forloop.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: forloop.mk,v 1.7 2020/11/03 17:37:57 rillig Exp $ all: for-loop @@ -11,40 +11,40 @@ XTRA_LIST= xtra .else . for x in ${LIST} -X!= echo 'x=$x' >&2; echo +. info x=$x . endfor CFL= -I/this -I"This or that" -Ithat "-DTHIS=\"this and that\"" cfl= . for x in ${CFL} -X!= echo 'x=$x' >&2; echo +. info x=$x . if empty(cfl) cfl= $x . else cfl+= $x . endif . endfor -X!= echo 'cfl=${cfl}' >&2; echo +. info cfl=${cfl} . if ${cfl} != ${CFL} -. error ${.newline}'${cfl}' != ${.newline}'${CFL}' +. error ${.newline}${cfl} != ${.newline}${CFL} . endif . for a b in ${EMPTY} -X!= echo 'a=$a b=$b' >&2; echo +. info a=$a b=$b . endfor # Since at least 1993, iteration stops at the first newline. # Back then, the .newline variable didn't exist, therefore it was unlikely # that a newline ever occurred. . for var in a${.newline}b${.newline}c -X!= echo 'newline-item=('${var:Q}')' 1>&2; echo +. info newline-item=(${var}) . endfor .endif # for-fail .for a b in ${LIST} ${LIST:tu} ${XTRA_LIST} -X!= echo 'a=$a b=$b' >&2; echo +. info a=$a b=$b .endfor for-loop: diff --git a/contrib/bmake/unit-tests/forsubst.mk b/contrib/bmake/unit-tests/forsubst.mk index 79af3d9a45fb..9f293ab7f94e 100644 --- a/contrib/bmake/unit-tests/forsubst.mk +++ b/contrib/bmake/unit-tests/forsubst.mk @@ -1,4 +1,16 @@ -# $NetBSD: forsubst.mk,v 1.2 2020/10/24 08:34:59 rillig Exp $ +# $NetBSD: forsubst.mk,v 1.3 2020/11/03 17:59:27 rillig Exp $ +# +# The parser used to break dependency lines at ';' without regard for +# substitution patterns. Back then, the first ';' was interpreted as the +# separator between the dependency and its commands. This (perhaps coupled +# with the new handling of .for variables in ${:U<value>...) caused +# interesting results for lines like: +# +# .for file in ${LIST} +# for-subst: ${file:S;^;${here}/;g} +# .endfor +# +# See the commit to unit-tests/forsubst (without the .mk) from 2009-10-07. all: for-subst diff --git a/contrib/bmake/unit-tests/gnode-submake.exp b/contrib/bmake/unit-tests/gnode-submake.exp new file mode 100644 index 000000000000..dbce13efaefa --- /dev/null +++ b/contrib/bmake/unit-tests/gnode-submake.exp @@ -0,0 +1,11 @@ +#*** Input graph: +# all, made UNMADE, type OP_DEPENDS, flags none +# makeinfo, made UNMADE, type OP_DEPENDS|OP_HAS_COMMANDS, flags none +# make-index, made UNMADE, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none +# braces-dot, made UNMADE, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none +# braces-no-dot, made UNMADE, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none +# braces-no-dot-modifier, made UNMADE, type OP_DEPENDS|OP_HAS_COMMANDS, flags none +# parentheses-dot, made UNMADE, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none +# parentheses-no-dot, made UNMADE, type OP_DEPENDS|OP_SUBMAKE|OP_HAS_COMMANDS, flags none + +exit status 0 diff --git a/contrib/bmake/unit-tests/gnode-submake.mk b/contrib/bmake/unit-tests/gnode-submake.mk new file mode 100644 index 000000000000..40ff20276df9 --- /dev/null +++ b/contrib/bmake/unit-tests/gnode-submake.mk @@ -0,0 +1,42 @@ +# $NetBSD: gnode-submake.mk,v 1.1 2020/11/07 23:25:06 rillig Exp $ +# +# Test whether OP_SUBMAKE is determined correctly. If it is, this node's +# shell commands are connected to the make process via pipes, to coordinate +# the number of running jobs. +# +# Determining whether a node is a sub-make node happens when the node is +# parsed. This information is only used in parallel mode, but the result +# from parsing is available in compat mode as well. + +.MAKEFLAGS: -n -dg1 + +all: makeinfo make-index +all: braces-dot braces-no-dot +all: braces-no-dot-modifier +all: parentheses-dot parentheses-no-dot + +makeinfo: + # The command contains the substring "make", but not as a whole word. + : makeinfo submake + +make-index: + # The command contains the word "make", therefore it is considered a + # possible sub-make. It isn't really, but that doesn't hurt. + : make-index + +braces-dot: + : ${.MAKE} + +braces-no-dot: + : ${MAKE} + +braces-no-dot-modifier: + # The command refers to MAKE, but not in its pure form. Therefore it + # is not considered a sub-make. + : ${MAKE:T} + +parentheses-dot: + : $(.MAKE) + +parentheses-no-dot: + : $(MAKE) diff --git a/contrib/bmake/unit-tests/include-sub.mk b/contrib/bmake/unit-tests/include-sub.mk index aeb7c3a69082..0b8dc77398ab 100644 --- a/contrib/bmake/unit-tests/include-sub.mk +++ b/contrib/bmake/unit-tests/include-sub.mk @@ -1,4 +1,4 @@ -# $NetBSD: include-sub.mk,v 1.6 2020/10/25 12:08:53 rillig Exp $ +# $NetBSD: include-sub.mk,v 1.7 2020/11/02 19:07:09 rillig Exp $ .if ${.INCLUDEDFROMFILE} == "include-main.mk" . info sub-before-ok @@ -20,7 +20,7 @@ # To see the variable 'includes' in action: # # Breakpoints: -# Parse_File at "PtrVector_Push(&includes, curFile)" +# Parse_File at "Vector_Push(&includes)" # ParseMessage at entry # Watches: # ((const IFile *[10])(*includes.items)) diff --git a/contrib/bmake/unit-tests/job-flags.exp b/contrib/bmake/unit-tests/job-flags.exp new file mode 100644 index 000000000000..b0c81d8f7094 --- /dev/null +++ b/contrib/bmake/unit-tests/job-flags.exp @@ -0,0 +1,12 @@ +.BEGIN +silent +ignore +true in ignore +false in ignore +*** [ignore] Error code 1 (ignored) +false without indentation +false space +false tab +*** [ignore-cmds] Error code 1 (ignored) +.END +exit status 0 diff --git a/contrib/bmake/unit-tests/job-flags.mk b/contrib/bmake/unit-tests/job-flags.mk new file mode 100644 index 000000000000..d4c3b5d43643 --- /dev/null +++ b/contrib/bmake/unit-tests/job-flags.mk @@ -0,0 +1,32 @@ +# $NetBSD: job-flags.mk,v 1.2 2020/11/14 13:17:47 rillig Exp $ +# +# Tests for Job.flags, which are controlled by special source dependencies +# like .SILENT or .IGNORE, as well as the command line options -s or -i. + +.MAKEFLAGS: -j1 + +all: silent .WAIT ignore .WAIT ignore-cmds + +.BEGIN: + @echo $@ + +silent: .SILENT .PHONY + echo $@ + +ignore: .IGNORE .PHONY + @echo $@ + true in $@ + false in $@ + @echo 'Still there in $@' + +ignore-cmds: .PHONY + # This node is not marked .IGNORE; individual commands can be switched + # to ignore mode by prefixing them with a '-'. + -false without indentation + # This also works if the '-' is indented by a space or a tab. + # Leading whitespace is stripped off by ParseLine_ShellCommand. + -false space + -false tab + +.END: + @echo $@ diff --git a/contrib/bmake/unit-tests/moderrs.mk b/contrib/bmake/unit-tests/moderrs.mk index 77ba39a3d57d..8fdcb496ee29 100644 --- a/contrib/bmake/unit-tests/moderrs.mk +++ b/contrib/bmake/unit-tests/moderrs.mk @@ -1,4 +1,4 @@ -# $NetBSD: moderrs.mk,v 1.24 2020/11/01 14:36:25 rillig Exp $ +# $NetBSD: moderrs.mk,v 1.25 2020/11/15 20:20:58 rillig Exp $ # # various modifier error tests @@ -123,7 +123,7 @@ mod-regex-delimiter: print-header print-footer # always set; some may be missing. Warn about these. # # Since there is no way to turn off this warning, the combination of -# alternative matches and capturing groups is not widely used. +# alternative matches and capturing groups is seldom used, if at all. # # A newly added modifier 'U' such as in :C,(a.)|(b.),\1\2,U might be added # for treating undefined capturing groups as empty, but that would create a diff --git a/contrib/bmake/unit-tests/modmisc.mk b/contrib/bmake/unit-tests/modmisc.mk index f57e679cd4da..64a84ce0dadd 100644 --- a/contrib/bmake/unit-tests/modmisc.mk +++ b/contrib/bmake/unit-tests/modmisc.mk @@ -1,4 +1,4 @@ -# $NetBSD: modmisc.mk,v 1.49 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: modmisc.mk,v 1.51 2020/11/15 20:20:58 rillig Exp $ # # miscellaneous modifier tests @@ -48,9 +48,9 @@ emptyvar: @echo @:${:@var@${var}@} # The :U modifier turns even the "" variable into something that has a value. -# The resulting variable is empty, but is still considered to contain a -# single empty word. This word can be accessed by the :S and :C modifiers, -# but not by the :@ modifier since it explicitly skips empty words. +# The value of the resulting expression is empty, but is still considered to +# contain a single empty word. This word can be accessed by the :S and :C +# modifiers, but not by the :@ modifier since it explicitly skips empty words. undefvar: @echo S:${:U:S,^$,empty,} @echo C:${:U:C,^$,empty,} @@ -60,12 +60,12 @@ undefvar: mod-quote: @echo $@: new${.newline:Q}${.newline:Q}line -# Cover the bmake_realloc in brk_string. +# Cover the bmake_realloc in Str_Words. mod-break-many-words: @echo $@: ${UNDEF:U:range=500:[#]} # To apply a modifier indirectly via another variable, the whole -# modifier must be put into a single variable. +# modifier must be put into a single variable expression. .if ${value:L:${:US}${:U,value,replacement,}} != "S,value,replacement,}" . warning unexpected .endif diff --git a/contrib/bmake/unit-tests/modts.mk b/contrib/bmake/unit-tests/modts.mk index 67ba7eb97078..4776c5818ea5 100644 --- a/contrib/bmake/unit-tests/modts.mk +++ b/contrib/bmake/unit-tests/modts.mk @@ -1,7 +1,6 @@ -# $NetBSD: modts.mk,v 1.7 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: modts.mk,v 1.8 2020/11/03 18:42:33 rillig Exp $ -LIST= one two three -LIST+= four five six +LIST= one two three four five six FU_mod-ts= a / b / cool diff --git a/contrib/bmake/unit-tests/modword.mk b/contrib/bmake/unit-tests/modword.mk index 43edf6a32b77..383c9dca975b 100644 --- a/contrib/bmake/unit-tests/modword.mk +++ b/contrib/bmake/unit-tests/modword.mk @@ -1,6 +1,7 @@ -# $NetBSD: modword.mk,v 1.4 2020/11/01 13:55:31 rillig Exp $ +# $NetBSD: modword.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $ # # Test behaviour of new :[] modifier +# TODO: When was this modifier new? all: mod-squarebrackets mod-S-W mod-C-W mod-tW-tw diff --git a/contrib/bmake/unit-tests/objdir-writable.exp b/contrib/bmake/unit-tests/objdir-writable.exp new file mode 100644 index 000000000000..f15cf914a7f5 --- /dev/null +++ b/contrib/bmake/unit-tests/objdir-writable.exp @@ -0,0 +1,5 @@ +make warning: OBJDIR/roobj: Permission denied. +/tmp +OBJDIR/roobj +OBJDIR/roobj +exit status 0 diff --git a/contrib/bmake/unit-tests/objdir-writable.mk b/contrib/bmake/unit-tests/objdir-writable.mk new file mode 100644 index 000000000000..9fc1c69afb56 --- /dev/null +++ b/contrib/bmake/unit-tests/objdir-writable.mk @@ -0,0 +1,31 @@ +# $NetBSD: objdir-writable.mk,v 1.4 2020/11/14 07:36:00 sjg Exp $ + +# test checking for writable objdir + +RO_OBJDIR?= ${TMPDIR:U/tmp}/roobj + +.if make(do-objdir) +# this should succeed +.OBJDIR: ${RO_OBJDIR} + +do-objdir: +.else +all: no-objdir ro-objdir explicit-objdir + +# make it now +x!= echo; mkdir -p ${RO_OBJDIR}; chmod 555 ${RO_OBJDIR} + +.END: rm-objdir +rm-objdir: + @rmdir ${RO_OBJDIR} + +no-objdir: + @MAKEOBJDIR=${RO_OBJDIR} ${.MAKE} -r -f /dev/null -C /tmp -V .OBJDIR + +ro-objdir: + @MAKEOBJDIR=${RO_OBJDIR} ${.MAKE} -r -f /dev/null -C /tmp -V .OBJDIR MAKE_OBJDIR_CHECK_WRITABLE=no + +explicit-objdir: + @MAKEOBJDIR=/tmp ${.MAKE} -r -f ${MAKEFILE:tA} -C /tmp do-objdir -V .OBJDIR +.endif + diff --git a/contrib/bmake/unit-tests/opt-chdir.exp b/contrib/bmake/unit-tests/opt-chdir.exp index 39a9383953dd..d20f9eb2f07b 100644 --- a/contrib/bmake/unit-tests/opt-chdir.exp +++ b/contrib/bmake/unit-tests/opt-chdir.exp @@ -1 +1,6 @@ +make: chdir /./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././: File name too long +*** Error code 1 (ignored) +cwd: / +make: chdir /nonexistent: No such file or directory +*** Error code 1 (ignored) exit status 0 diff --git a/contrib/bmake/unit-tests/opt-chdir.mk b/contrib/bmake/unit-tests/opt-chdir.mk index 8735fddbef9e..20241f02740e 100644 --- a/contrib/bmake/unit-tests/opt-chdir.mk +++ b/contrib/bmake/unit-tests/opt-chdir.mk @@ -1,8 +1,27 @@ -# $NetBSD: opt-chdir.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: opt-chdir.mk,v 1.5 2020/11/15 05:43:56 sjg Exp $ # -# Tests for the -C command line option. +# Tests for the -C command line option, which changes the directory at the +# beginning. +# +# This option has been available since 2009-08-27. + +.MAKEFLAGS: -d0 # switch stdout to line-buffered + +all: chdir-filename-too-long +all: chdir-root +all: chdir-nonexistent + +# Try to overflow the internal buffer for .CURDIR, which is curdir. +chdir-filename-too-long: .PHONY .IGNORE + # 5000 slashes, separated by dots: /./././.../././ + @${MAKE} -C ${:U:range=5000:@@/@:ts.} -# TODO: Implementation +# Changing to another directory is possible via the command line. +# In this test, it is the root directory since almost any other directory +# is not guaranteed to exist on every platform. +chdir-root: .PHONY .IGNORE + @MAKE_OBJDIR_CHECK_WRITABLE=no ${MAKE} -C / -V 'cwd: $${.CURDIR}' -all: - @:; +# Trying to change to a nonexistent directory exits immediately. +chdir-nonexistent: .PHONY .IGNORE + @${MAKE} -C /nonexistent diff --git a/contrib/bmake/unit-tests/opt-debug-jobs.exp b/contrib/bmake/unit-tests/opt-debug-jobs.exp index 1214dce781b5..0431867756a1 100644 --- a/contrib/bmake/unit-tests/opt-debug-jobs.exp +++ b/contrib/bmake/unit-tests/opt-debug-jobs.exp @@ -10,7 +10,9 @@ echo ": variable" echo ": 'single' and \"double\" quotes" { : 'single' and "double" quotes } || exit $? -Running all locally +{ sleep 1 +} || exit $? +Running all Command: sh JobExec(all): pid <pid> added to jobs table job table @ job started diff --git a/contrib/bmake/unit-tests/opt-debug-jobs.mk b/contrib/bmake/unit-tests/opt-debug-jobs.mk index fb65d4f3356c..f3732df7e25d 100644 --- a/contrib/bmake/unit-tests/opt-debug-jobs.mk +++ b/contrib/bmake/unit-tests/opt-debug-jobs.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-debug-jobs.mk,v 1.4 2020/10/05 19:27:48 rillig Exp $ +# $NetBSD: opt-debug-jobs.mk,v 1.5 2020/11/12 21:54:52 rillig Exp $ # # Tests for the -dj command line option, which adds debug logging about # running jobs in multiple shells. @@ -24,3 +24,10 @@ all: # This allows to copy and paste the whole command, without having # to unescape anything. : 'single' and "double" quotes + + # Avoid a race condition in the debug output. Without sleeping, + # it is not guaranteed that the two lines "exited/stopped" and + # "JobFinish" are output earlier than the stdout of the actual shell + # commands. The '@' prefix avoids that this final command gets into + # another race condition with the "exited/stopped" line. + @sleep 1 diff --git a/contrib/bmake/unit-tests/opt-ignore.mk b/contrib/bmake/unit-tests/opt-ignore.mk index ff11c1e15c31..f776e8a27229 100644 --- a/contrib/bmake/unit-tests/opt-ignore.mk +++ b/contrib/bmake/unit-tests/opt-ignore.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-ignore.mk,v 1.4 2020/10/18 18:12:42 rillig Exp $ +# $NetBSD: opt-ignore.mk,v 1.5 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -i command line option, which ignores the exit status of the # shell commands, and just continues with the next command, even from the same @@ -11,6 +11,7 @@ # failed? .MAKEFLAGS: -d0 # switch stdout to being line-buffered +.MAKEFLAGS: -i all: dependency other diff --git a/contrib/bmake/unit-tests/opt-keep-going.mk b/contrib/bmake/unit-tests/opt-keep-going.mk index ec4adfa00e62..72f605246712 100644 --- a/contrib/bmake/unit-tests/opt-keep-going.mk +++ b/contrib/bmake/unit-tests/opt-keep-going.mk @@ -1,10 +1,11 @@ -# $NetBSD: opt-keep-going.mk,v 1.4 2020/10/18 18:12:42 rillig Exp $ +# $NetBSD: opt-keep-going.mk,v 1.5 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -k command line option, which stops building a target as soon # as an error is detected, but continues building the other, independent # targets, as far as possible. .MAKEFLAGS: -d0 # switch stdout to being line-buffered +.MAKEFLAGS: -k all: dependency other diff --git a/contrib/bmake/unit-tests/opt-no-action.mk b/contrib/bmake/unit-tests/opt-no-action.mk index 32b3b1564acb..91c05b2dc00f 100644 --- a/contrib/bmake/unit-tests/opt-no-action.mk +++ b/contrib/bmake/unit-tests/opt-no-action.mk @@ -1,9 +1,11 @@ -# $NetBSD: opt-no-action.mk,v 1.3 2020/08/19 05:25:26 rillig Exp $ +# $NetBSD: opt-no-action.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -n command line option, which runs almost no commands. # It just outputs them, to be inspected by human readers. # Only commands that are in a .MAKE target or prefixed by '+' are run. +.MAKEFLAGS: -n + # This command cannot be prevented from being run since it is used at parse # time, and any later variable assignments may depend on its result. != echo 'command during parsing' 1>&2; echo diff --git a/contrib/bmake/unit-tests/opt-query.mk b/contrib/bmake/unit-tests/opt-query.mk index 04e605991140..0a7d5219a8fe 100644 --- a/contrib/bmake/unit-tests/opt-query.mk +++ b/contrib/bmake/unit-tests/opt-query.mk @@ -1,4 +1,4 @@ -# $NetBSD: opt-query.mk,v 1.3 2020/08/19 05:13:18 rillig Exp $ +# $NetBSD: opt-query.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -q command line option. # @@ -6,6 +6,8 @@ # None of the commands in the targets are run, not even those that are # prefixed with '+'. +.MAKEFLAGS: -q + # This command cannot be prevented from being run since it is used at parse # time, and any later variable assignments may depend on its result. != echo 'command during parsing' 1>&2; echo diff --git a/contrib/bmake/unit-tests/opt-touch-jobs.exp b/contrib/bmake/unit-tests/opt-touch-jobs.exp new file mode 100644 index 000000000000..0cfde5135198 --- /dev/null +++ b/contrib/bmake/unit-tests/opt-touch-jobs.exp @@ -0,0 +1,4 @@ +: Making opt-touch-make. +`opt-touch-join' is up to date. +`opt-touch-use' is up to date. +exit status 0 diff --git a/contrib/bmake/unit-tests/opt-touch-jobs.mk b/contrib/bmake/unit-tests/opt-touch-jobs.mk new file mode 100644 index 000000000000..4402d76e9578 --- /dev/null +++ b/contrib/bmake/unit-tests/opt-touch-jobs.mk @@ -0,0 +1,30 @@ +# $NetBSD: opt-touch-jobs.mk,v 1.1 2020/11/14 15:35:20 rillig Exp $ +# +# Tests for the -t command line option in jobs mode. + +.MAKEFLAGS: -j1 +.MAKEFLAGS: -t +.MAKEFLAGS: opt-touch-phony +.MAKEFLAGS: opt-touch-join +.MAKEFLAGS: opt-touch-use +.MAKEFLAGS: opt-touch-make + +opt-touch-phony: .PHONY + : Making $@. + +opt-touch-join: .JOIN + : Making $@. + +opt-touch-use: .USE + : Making use of $@. + +# Even though it is listed last, in the output it appears first. +# This is because it is the only node that actually needs to be run. +# The "is up to date" of the other nodes happens after all jobs have +# finished, by Make_Run > MakePrintStatusList > MakePrintStatus. +opt-touch-make: .MAKE + : Making $@. + +.END: + @files=$$(ls opt-touch-* 2>/dev/null | grep -v -e '\.' -e '\*'); \ + [ -z "$$files" ] || { echo "created files: $$files" 1>&2; exit 1; } diff --git a/contrib/bmake/unit-tests/opt-touch.exp b/contrib/bmake/unit-tests/opt-touch.exp index 39a9383953dd..c9e6c7890f42 100644 --- a/contrib/bmake/unit-tests/opt-touch.exp +++ b/contrib/bmake/unit-tests/opt-touch.exp @@ -1 +1,4 @@ +`opt-touch-join' is up to date. +`opt-touch-use' is up to date. +: Making opt-touch-make. exit status 0 diff --git a/contrib/bmake/unit-tests/opt-touch.mk b/contrib/bmake/unit-tests/opt-touch.mk index 5093c5cad6ac..defb7c59e0ad 100644 --- a/contrib/bmake/unit-tests/opt-touch.mk +++ b/contrib/bmake/unit-tests/opt-touch.mk @@ -1,8 +1,21 @@ -# $NetBSD: opt-touch.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: opt-touch.mk,v 1.4 2020/11/14 14:13:09 rillig Exp $ # # Tests for the -t command line option. -# TODO: Implementation +.MAKEFLAGS: -t opt-touch-phony opt-touch-join opt-touch-use opt-touch-make -all: - @:; +opt-touch-phony: .PHONY + : Making $@. + +opt-touch-join: .JOIN + : Making $@. + +opt-touch-use: .USE + : Making use of $@. + +opt-touch-make: .MAKE + : Making $@. + +.END: + @files=$$(ls opt-touch-* 2>/dev/null | grep -v -e '\.' -e '\*'); \ + [ -z "$$files" ] || { echo "created files: $$files" 1>&2; exit 1; } diff --git a/contrib/bmake/unit-tests/opt-var-expanded.mk b/contrib/bmake/unit-tests/opt-var-expanded.mk index 0b4088a82082..f7203374b8cc 100644 --- a/contrib/bmake/unit-tests/opt-var-expanded.mk +++ b/contrib/bmake/unit-tests/opt-var-expanded.mk @@ -1,6 +1,8 @@ -# $NetBSD: opt-var-expanded.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# $NetBSD: opt-var-expanded.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -v command line option. +.MAKEFLAGS: -v VAR -v VALUE + VAR= other ${VALUE} $$$$ VALUE= value diff --git a/contrib/bmake/unit-tests/opt-var-literal.mk b/contrib/bmake/unit-tests/opt-var-literal.mk index a819e7537105..d236e389d259 100644 --- a/contrib/bmake/unit-tests/opt-var-literal.mk +++ b/contrib/bmake/unit-tests/opt-var-literal.mk @@ -1,6 +1,8 @@ -# $NetBSD: opt-var-literal.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# $NetBSD: opt-var-literal.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -V command line option. +.MAKEFLAGS: -V VAR -V VALUE + VAR= other ${VALUE} $$$$ VALUE= value diff --git a/contrib/bmake/unit-tests/opt-warnings-as-errors.exp b/contrib/bmake/unit-tests/opt-warnings-as-errors.exp index bd54bb673f08..278c9469607f 100644 --- a/contrib/bmake/unit-tests/opt-warnings-as-errors.exp +++ b/contrib/bmake/unit-tests/opt-warnings-as-errors.exp @@ -1,6 +1,6 @@ -make: "opt-warnings-as-errors.mk" line 5: warning: message 1 +make: "opt-warnings-as-errors.mk" line 7: warning: message 1 make: parsing warnings being treated as errors -make: "opt-warnings-as-errors.mk" line 6: warning: message 2 +make: "opt-warnings-as-errors.mk" line 8: warning: message 2 parsing continues make: Fatal errors encountered -- cannot continue make: stopped in unit-tests diff --git a/contrib/bmake/unit-tests/opt-warnings-as-errors.mk b/contrib/bmake/unit-tests/opt-warnings-as-errors.mk index 905753410db0..2302dd4794b5 100644 --- a/contrib/bmake/unit-tests/opt-warnings-as-errors.mk +++ b/contrib/bmake/unit-tests/opt-warnings-as-errors.mk @@ -1,7 +1,9 @@ -# $NetBSD: opt-warnings-as-errors.mk,v 1.3 2020/08/23 14:28:04 rillig Exp $ +# $NetBSD: opt-warnings-as-errors.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for the -W command line option, which turns warnings into errors. +.MAKEFLAGS: -W + .warning message 1 .warning message 2 diff --git a/contrib/bmake/unit-tests/opt.exp b/contrib/bmake/unit-tests/opt.exp index 39a9383953dd..11344ae0c359 100644 --- a/contrib/bmake/unit-tests/opt.exp +++ b/contrib/bmake/unit-tests/opt.exp @@ -1 +1,22 @@ +make -r -f /dev/null -V MAKEFLAGS + -r -k -d 0 + +make -: +usage: make [-BeikNnqrSstWwX] + [-C directory] [-D variable] [-d flags] [-f makefile] + [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file] + [-V variable] [-v variable] [variable=value] [target ...] +*** Error code 2 (ignored) + +make -r -f /dev/null -- -VAR=value -f /dev/null +make: don't know how to make -f (continuing) +`/dev/null' is up to date. + +make -? +usage: make [-BeikNnqrSstWwX] + [-C directory] [-D variable] [-d flags] [-f makefile] + [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file] + [-V variable] [-v variable] [variable=value] [target ...] +*** Error code 2 (ignored) + exit status 0 diff --git a/contrib/bmake/unit-tests/opt.mk b/contrib/bmake/unit-tests/opt.mk index eae430965df7..0931a66d3d15 100644 --- a/contrib/bmake/unit-tests/opt.mk +++ b/contrib/bmake/unit-tests/opt.mk @@ -1,8 +1,28 @@ -# $NetBSD: opt.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: opt.mk,v 1.6 2020/11/18 01:06:59 sjg Exp $ # # Tests for the command line options. -# TODO: Implementation +.MAKEFLAGS: -d0 # make stdout line-buffered -all: - @:; +all: .IGNORE + # The options from the top-level make are passed to the sub-makes via + # the environment variable MAKEFLAGS. This is where the " -r -k -d 0" + # comes from. See MainParseArg. + ${MAKE} -r -f /dev/null -V MAKEFLAGS + @echo + + # Just to see how the custom argument parsing code reacts to a syntax + # error. The colon is used in the options string, marking an option + # that takes arguments. It is not an option by itself, though. + ${MAKE} -: + @echo + + # See whether a '--' stops handling of command line options, like in + # standard getopt programs. Yes, it does, and it treats the + # second '-f' as a target to be created. + ${MAKE} -r -f /dev/null -- -VAR=value -f /dev/null + @echo + + # This is the normal way to print the usage of a command. + ${MAKE} -? + @echo diff --git a/contrib/bmake/unit-tests/order.mk b/contrib/bmake/unit-tests/order.mk index f90b627d9e5f..9b94016c1841 100644 --- a/contrib/bmake/unit-tests/order.mk +++ b/contrib/bmake/unit-tests/order.mk @@ -1,10 +1,12 @@ -# $NetBSD: order.mk,v 1.1 2014/08/21 13:44:51 apb Exp $ +# $NetBSD: order.mk,v 1.2 2020/11/09 20:50:56 rillig Exp $ # Test that .ORDER is handled correctly. # The explicit dependency the.o: the.h will make us examine the.h # the .ORDER will prevent us building it immediately, # we should then examine the.c rather than stop. +.MAKEFLAGS: -j1 + all: the.o .ORDER: the.c the.h diff --git a/contrib/bmake/unit-tests/recursive.exp b/contrib/bmake/unit-tests/recursive.exp index bb5db75a474c..36cd1c989532 100644 --- a/contrib/bmake/unit-tests/recursive.exp +++ b/contrib/bmake/unit-tests/recursive.exp @@ -1,5 +1,5 @@ -make: "recursive.mk" line 34: Unclosed variable "MISSING_PAREN" -make: "recursive.mk" line 35: Unclosed variable "MISSING_BRACE" +make: "recursive.mk" line 36: Unclosed variable "MISSING_PAREN" +make: "recursive.mk" line 37: Unclosed variable "MISSING_BRACE" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/recursive.mk b/contrib/bmake/unit-tests/recursive.mk index 6e5d8a2ca8b5..73a8409fe030 100644 --- a/contrib/bmake/unit-tests/recursive.mk +++ b/contrib/bmake/unit-tests/recursive.mk @@ -1,4 +1,4 @@ -# $NetBSD: recursive.mk,v 1.3 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: recursive.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # In -dL mode, a variable may get expanded before it makes sense. # This would stop make from doing anything since the "recursive" error @@ -11,6 +11,8 @@ # Seen in pkgsrc/x11/libXfixes, and probably many more package that use # GNU Automake. +.MAKEFLAGS: -dL + AM_V_lt= ${am__v_lt_${V}} am__v_lt_= ${am__v_lt_${AM_DEFAULT_VERBOSITY}} am__v_lt_0= --silent diff --git a/contrib/bmake/unit-tests/sh-leading-at.exp b/contrib/bmake/unit-tests/sh-leading-at.exp index 5ffa84690a40..8347fda085f7 100644 --- a/contrib/bmake/unit-tests/sh-leading-at.exp +++ b/contrib/bmake/unit-tests/sh-leading-at.exp @@ -2,4 +2,5 @@ ok space after @ echo 'echoed' echoed +3 exit status 0 diff --git a/contrib/bmake/unit-tests/sh-leading-at.mk b/contrib/bmake/unit-tests/sh-leading-at.mk index 19a6e59e4e6a..9f98005ec088 100644 --- a/contrib/bmake/unit-tests/sh-leading-at.mk +++ b/contrib/bmake/unit-tests/sh-leading-at.mk @@ -1,10 +1,18 @@ -# $NetBSD: sh-leading-at.mk,v 1.3 2020/08/22 09:16:08 rillig Exp $ +# $NetBSD: sh-leading-at.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $ # # Tests for shell commands preceded by an '@', to suppress printing # the command to stdout. +# +# See also: +# .SILENT +# depsrc-silent.mk +# opt-silent.mk all: @ @echo 'ok' @ echo 'space after @' echo 'echoed' + # The leading '@' can be repeated. + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @@@echo '3' diff --git a/contrib/bmake/unit-tests/sh-leading-hyphen.mk b/contrib/bmake/unit-tests/sh-leading-hyphen.mk index 94be43495afb..d760abb9afdd 100644 --- a/contrib/bmake/unit-tests/sh-leading-hyphen.mk +++ b/contrib/bmake/unit-tests/sh-leading-hyphen.mk @@ -1,7 +1,12 @@ -# $NetBSD: sh-leading-hyphen.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: sh-leading-hyphen.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # # Tests for shell commands preceded by a '-', to ignore the exit status of # the command line. +# +# See also: +# .IGNORE +# depsrc-ignore.mk +# opt-ignore.mk # TODO: Implementation diff --git a/contrib/bmake/unit-tests/sh-leading-plus.mk b/contrib/bmake/unit-tests/sh-leading-plus.mk index 75279d7d57fd..ff57b4a38a7d 100644 --- a/contrib/bmake/unit-tests/sh-leading-plus.mk +++ b/contrib/bmake/unit-tests/sh-leading-plus.mk @@ -1,8 +1,10 @@ -# $NetBSD: sh-leading-plus.mk,v 1.3 2020/08/23 14:46:33 rillig Exp $ +# $NetBSD: sh-leading-plus.mk,v 1.4 2020/11/09 20:50:56 rillig Exp $ # # Tests for shell commands preceded by a '+', to run them even if # the command line option -n is given. +.MAKEFLAGS: -n + all: @echo 'this command is not run' @+echo 'this command is run' diff --git a/contrib/bmake/unit-tests/sh-meta-chars.mk b/contrib/bmake/unit-tests/sh-meta-chars.mk index 126ca2ceb118..a029c73a855c 100644 --- a/contrib/bmake/unit-tests/sh-meta-chars.mk +++ b/contrib/bmake/unit-tests/sh-meta-chars.mk @@ -1,9 +1,13 @@ -# $NetBSD: sh-meta-chars.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: sh-meta-chars.mk,v 1.3 2020/11/15 20:20:58 rillig Exp $ # # Tests for running shell commands that contain meta-characters. # # These meta-characters decide whether the command is run by the shell -# or executed directly via execv. See Cmd_Exec for details. +# or executed directly via execv, but only in compatibility mode, not +# in jobs mode, and only if MAKE_NATIVE is defined during compilation. +# +# See also: +# Compat_RunCommand, useShell # TODO: Implementation diff --git a/contrib/bmake/unit-tests/suff-self.exp b/contrib/bmake/unit-tests/suff-self.exp new file mode 100644 index 000000000000..4e70762209a2 --- /dev/null +++ b/contrib/bmake/unit-tests/suff-self.exp @@ -0,0 +1,3 @@ +make: Graph cycles through suff-self.suff +`all' not remade because of errors. +exit status 0 diff --git a/contrib/bmake/unit-tests/suff-self.mk b/contrib/bmake/unit-tests/suff-self.mk new file mode 100644 index 000000000000..8874cc5157e8 --- /dev/null +++ b/contrib/bmake/unit-tests/suff-self.mk @@ -0,0 +1,11 @@ +# $NetBSD: suff-self.mk,v 1.1 2020/11/16 15:12:16 rillig Exp $ +# +# See what happens if someone defines a self-referencing suffix +# transformation rule. + +.SUFFIXES: .suff + +.suff.suff: + : Making ${.TARGET} out of ${.IMPSRC}. + +all: suff-self.suff diff --git a/contrib/bmake/unit-tests/use-inference.mk b/contrib/bmake/unit-tests/use-inference.mk index b0e5017bc6fb..cde3c772edaa 100644 --- a/contrib/bmake/unit-tests/use-inference.mk +++ b/contrib/bmake/unit-tests/use-inference.mk @@ -1,4 +1,4 @@ -# $NetBSD: use-inference.mk,v 1.1 2020/08/09 16:32:28 rillig Exp $ +# $NetBSD: use-inference.mk,v 1.2 2020/11/05 00:41:04 rillig Exp $ # # Demonstrate that .USE rules do not have an effect on inference rules. # At least not in the special case where the inference rule does not @@ -33,3 +33,6 @@ use-inference.from: # assume it exists # This is strange since make definitely knows about the .from.to suffix # inference rule. But it seems to ignore it, maybe because it doesn't # have any associated commands. + +# XXX: Despite the error message "don't know how to make", the exit status +# is 0. This is inconsistent. diff --git a/contrib/bmake/unit-tests/var-class-local.exp b/contrib/bmake/unit-tests/var-class-local.exp index f1595c6810fb..db85b47cae06 100644 --- a/contrib/bmake/unit-tests/var-class-local.exp +++ b/contrib/bmake/unit-tests/var-class-local.exp @@ -1,2 +1,5 @@ +: Making var-class-local.c out of nothing. +: Making var-class-local.o from var-class-local.c. +: Making basename "var-class-local.o" in "." from "var-class-local.c" in ".". : all overwritten exit status 0 diff --git a/contrib/bmake/unit-tests/var-class-local.mk b/contrib/bmake/unit-tests/var-class-local.mk index 68696ea854af..f9d56e539ff0 100644 --- a/contrib/bmake/unit-tests/var-class-local.mk +++ b/contrib/bmake/unit-tests/var-class-local.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-class-local.mk,v 1.4 2020/10/25 09:46:25 rillig Exp $ +# $NetBSD: var-class-local.mk,v 1.5 2020/11/05 18:08:39 rillig Exp $ # # Tests for target-local variables, such as ${.TARGET} or $@. @@ -25,6 +25,20 @@ .endif all: + +.SUFFIXES: .c .o + +var-class-local.c: + : Making ${.TARGET} out of nothing. + +.c.o: + : Making ${.TARGET} from ${.IMPSRC}. + + # The local variables @F, @D, <F, <D are legacy forms. + # See the manual page for details. + : Making basename "${@F}" in "${@D}" from "${<F}" in "${<D}". + +all: var-class-local.o # The ::= modifier overwrites the .TARGET variable in the node # 'all', not in the global scope. This can be seen with the -dv # option, looking for "all:@ = overwritten". diff --git a/contrib/bmake/unit-tests/var-op-assign.exp b/contrib/bmake/unit-tests/var-op-assign.exp index 0e9e2d211a5f..0562ffcda733 100644 --- a/contrib/bmake/unit-tests/var-op-assign.exp +++ b/contrib/bmake/unit-tests/var-op-assign.exp @@ -1,6 +1,6 @@ this will be evaluated later -make: "var-op-assign.mk" line 52: Need an operator -make: "var-op-assign.mk" line 86: Parsing still continues until here. +make: "var-op-assign.mk" line 59: Need an operator +make: "var-op-assign.mk" line 93: Parsing still continues until here. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/var-op-assign.mk b/contrib/bmake/unit-tests/var-op-assign.mk index c988d4141b83..3bcc3de0ba0e 100644 --- a/contrib/bmake/unit-tests/var-op-assign.mk +++ b/contrib/bmake/unit-tests/var-op-assign.mk @@ -1,11 +1,12 @@ -# $NetBSD: var-op-assign.mk,v 1.6 2020/10/24 08:50:17 rillig Exp $ +# $NetBSD: var-op-assign.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $ # # Tests for the = variable assignment operator, which overwrites an existing # variable or creates it. # This is a simple variable assignment. # To the left of the assignment operator '=' there is the variable name, -# and to the right is the variable value. +# and to the right is the variable value. The variable value is stored as-is, +# it is not expanded in any way. # VAR= value @@ -36,9 +37,15 @@ VAR= new value and \# some $$ special characters # comment # The variable value may contain references to other variables. # In this example, the reference is to the variable with the empty name, -# which always expands to an empty string. This alone would not produce -# any side-effects, therefore the variable has a :!...! modifier that -# executes a shell command. +# which is never defined. +# +# This alone would not produce any side-effects, therefore the variable has +# a :!...! modifier that executes a shell command. The :!...! modifier turns +# an undefined expression into a defined one, see ApplyModifier_ShellCommand, +# the call to ApplyModifiersState_Define. +# +# Since the right-hand side of a '=' assignment is not expanded at the time +# when the variable is defined, the first command is not run at all. VAR= ${:! echo 'not yet evaluated' 1>&2 !} VAR= ${:! echo 'this will be evaluated later' 1>&2 !} @@ -48,7 +55,7 @@ VAR= ${:! echo 'this will be evaluated later' 1>&2 !} .endif # In a variable assignment, the variable name must consist of a single word. -# +# The following line therefore generates a parse error. VARIABLE NAME= variable value # But if the whitespace appears inside parentheses or braces, everything is diff --git a/contrib/bmake/unit-tests/var-op-expand.exp b/contrib/bmake/unit-tests/var-op-expand.exp index 39a9383953dd..8ccbbd5ae92d 100644 --- a/contrib/bmake/unit-tests/var-op-expand.exp +++ b/contrib/bmake/unit-tests/var-op-expand.exp @@ -1 +1,10 @@ +Var_Parse: ${UNDEF} with VARE_WANTRES +Global:VAR_ASSIGN_ = undef value +Var_Parse: ${UNDEF} with VARE_WANTRES +Var_Parse: ${UNDEF} with VARE_WANTRES +Global:VAR_SUBST_${UNDEF} = +Var_Parse: ${UNDEF} with VARE_WANTRES +Global:VAR_SUBST_ = undef value +Global:.MAKEFLAGS = -r -k -d v -d +Global:.MAKEFLAGS = -r -k -d v -d 0 exit status 0 diff --git a/contrib/bmake/unit-tests/var-op-expand.mk b/contrib/bmake/unit-tests/var-op-expand.mk index 07c5fb647759..0b5ddbbc0386 100644 --- a/contrib/bmake/unit-tests/var-op-expand.mk +++ b/contrib/bmake/unit-tests/var-op-expand.mk @@ -1,9 +1,27 @@ -# $NetBSD: var-op-expand.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: var-op-expand.mk,v 1.4 2020/11/08 14:00:52 rillig Exp $ # # Tests for the := variable assignment operator, which expands its # right-hand side. # TODO: Implementation +# XXX: edge case: When a variable name refers to an undefined variable, the +# behavior differs between the '=' and the ':=' assignment operators. +# This bug exists since var.c 1.42 from 2000-05-11. +# +# The '=' operator expands the undefined variable to an empty string, thus +# assigning to VAR_ASSIGN_. In the name of variables to be set, it should +# really be forbidden to refer to undefined variables. +# +# The ':=' operator expands the variable name twice. In one of these +# expansions, the undefined variable expression is preserved (controlled by +# preserveUndefined in VarAssign_EvalSubst), in the other expansion it expands +# to an empty string. This way, 2 variables are created using a single +# variable assignment. It's magic. :-/ +.MAKEFLAGS: -dv +VAR_ASSIGN_${UNDEF}= undef value +VAR_SUBST_${UNDEF}:= undef value +.MAKEFLAGS: -d0 + all: @:; diff --git a/contrib/bmake/unit-tests/var-op-shell.exp b/contrib/bmake/unit-tests/var-op-shell.exp index 39a9383953dd..caea85ab5daa 100644 --- a/contrib/bmake/unit-tests/var-op-shell.exp +++ b/contrib/bmake/unit-tests/var-op-shell.exp @@ -1 +1,7 @@ +make: "var-op-shell.mk" line 28: warning: "echo "failed"; false" returned non-zero status +make: "var-op-shell.mk" line 34: warning: "false" returned non-zero status +make: "var-op-shell.mk" line 59: warning: "kill -14 $$" exited on a signal +/bin/no/such/command: not found +make: "var-op-shell.mk" line 65: warning: "/bin/no/such/command" returned non-zero status +stderr exit status 0 diff --git a/contrib/bmake/unit-tests/var-op-shell.mk b/contrib/bmake/unit-tests/var-op-shell.mk index 83580a89e6c2..7b52513e1131 100644 --- a/contrib/bmake/unit-tests/var-op-shell.mk +++ b/contrib/bmake/unit-tests/var-op-shell.mk @@ -1,9 +1,84 @@ -# $NetBSD: var-op-shell.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: var-op-shell.mk,v 1.3 2020/11/09 20:39:46 rillig Exp $ # # Tests for the != variable assignment operator, which runs its right-hand # side through the shell. -# TODO: Implementation +# The variable OUTPUT gets the output from running the shell command. +OUTPUT!= echo "success"'ful' +.if ${OUTPUT} != "successful" +. error +.endif + +# Since 2014-08-20, the output of the shell command may be empty. +# +# On 1996-05-29, when the '!=' assignment operator and Cmd_Exec were added, +# an empty output produced the error message "Couldn't read shell's output +# for \"%s\"". +# +# The error message is still there but reserved for technical errors. +# It may be possible to trigger the error message by killing the shell after +# reading part of its output. +OUTPUT!= true +.if ${OUTPUT} != "" +. error +.endif + +# The output of a shell command that failed is processed nevertheless. +# TODO: Make this an error in lint mode. +OUTPUT!= echo "failed"; false +.if ${OUTPUT} != "failed" +. error +.endif + +# A command with empty output may fail as well. +OUTPUT!= false +.if ${OUTPUT} != "" +. error +.endif + +# In the output of the command, each newline is replaced with a space. +# Except for the very last one, which is discarded. +OUTPUT!= echo "line 1"; echo "line 2" +.if ${OUTPUT} != "line 1 line 2" +. error +.endif + +# A failing command in the middle results in the exit status 0, which in the +# end means that the whole sequence of commands succeeded. +OUTPUT!= echo "before"; false; echo "after" +.if ${OUTPUT} != "before after" +. error +.endif + +# NB: The signal number must be numeric since some shells (which ones?) don't +# accept symbolic signal names. 14 is typically SIGALRM. +# +# XXX: The number of the signal is not mentioned in the warning since that +# would have been difficult to implement; currently the errfmt is a format +# string containing a single %s conversion. +OUTPUT!= kill -14 $$$$ +.if ${OUTPUT} != "" +. error +.endif + +# A nonexistent command produces a non-zero exit status. +OUTPUT!= /bin/no/such/command +.if ${OUTPUT} != "" +. error +.endif + +# The output from the shell's stderr is not captured, it just passes through. +OUTPUT!= echo "stdout"; echo "stderr" 1>&2 +.if ${OUTPUT} != "stdout" +. error +.endif + +# The 8 dollar signs end up as 4 dollar signs when expanded. The shell sees +# the command "echo '$$$$'". The 4 dollar signs are stored in OUTPUT, and +# when that variable is expanded, they expand to 2 dollar signs. +OUTPUT!= echo '$$$$$$$$' +.if ${OUTPUT} != "\$\$" +. error +.endif all: - @:; diff --git a/contrib/bmake/unit-tests/var-op-sunsh.mk b/contrib/bmake/unit-tests/var-op-sunsh.mk index efef19bf1567..0e16b2b42d34 100644 --- a/contrib/bmake/unit-tests/var-op-sunsh.mk +++ b/contrib/bmake/unit-tests/var-op-sunsh.mk @@ -1,4 +1,4 @@ -# $NetBSD: var-op-sunsh.mk,v 1.5 2020/10/04 08:32:52 rillig Exp $ +# $NetBSD: var-op-sunsh.mk,v 1.6 2020/11/15 20:20:58 rillig Exp $ # # Tests for the :sh= variable assignment operator, which runs its right-hand # side through the shell. It is a seldom-used alternative to the != @@ -118,5 +118,7 @@ VAR :sh += echo two . error ${VAR} .endif +# TODO: test VAR:sh!=command + all: @:; diff --git a/contrib/bmake/unit-tests/vardebug.exp b/contrib/bmake/unit-tests/vardebug.exp index 474a46ee1b5c..06c8b590e1b1 100644 --- a/contrib/bmake/unit-tests/vardebug.exp +++ b/contrib/bmake/unit-tests/vardebug.exp @@ -77,7 +77,7 @@ make: "vardebug.mk" line 44: Malformed conditional (${:Uvariable:unknown}) Var_Parse: ${UNDEFINED} with VARE_UNDEFERR|VARE_WANTRES make: "vardebug.mk" line 53: Malformed conditional (${UNDEFINED}) Global:delete .SHELL (not found) -Command:.SHELL = /bin/sh +Command:.SHELL = </path/to/shell> Command:.SHELL = overwritten ignored (read-only) Global:.MAKEFLAGS = -r -k -d v -d Global:.MAKEFLAGS = -r -k -d v -d 0 diff --git a/contrib/bmake/unit-tests/varmisc.mk b/contrib/bmake/unit-tests/varmisc.mk index e2d53129a932..aced1a0554d1 100644 --- a/contrib/bmake/unit-tests/varmisc.mk +++ b/contrib/bmake/unit-tests/varmisc.mk @@ -1,5 +1,5 @@ -# $Id: varmisc.mk,v 1.20 2020/10/26 17:43:57 sjg Exp $ -# $NetBSD: varmisc.mk,v 1.26 2020/10/24 08:50:17 rillig Exp $ +# $Id: varmisc.mk,v 1.21 2020/11/11 23:08:50 sjg Exp $ +# $NetBSD: varmisc.mk,v 1.28 2020/11/07 00:07:02 rillig Exp $ # # Miscellaneous variable tests. @@ -88,7 +88,7 @@ VARNAME= ${VARNAME${:U1}} .if defined(VARNAME${:U2}) && !empty(VARNAME${:U2}) .endif -# begin .MAKE.SAVE_DOLLARS; see Var_Set_with_flags and s2Boolean. +# begin .MAKE.SAVE_DOLLARS; see Var_SetWithFlags and ParseBoolean. SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off SD_4_DOLLARS= $$$$ diff --git a/contrib/bmake/unit-tests/varmod-defined.exp b/contrib/bmake/unit-tests/varmod-defined.exp index 39a9383953dd..7f61cc426305 100644 --- a/contrib/bmake/unit-tests/varmod-defined.exp +++ b/contrib/bmake/unit-tests/varmod-defined.exp @@ -1 +1,23 @@ +Global:8_DOLLARS = $$$$$$$$ +Global:VAR = +Var_Parse: ${8_DOLLARS} with VARE_WANTRES|VARE_KEEP_DOLLAR +Global:VAR = $$$$$$$$ +Var_Parse: ${VAR:D${8_DOLLARS}} with VARE_WANTRES|VARE_KEEP_DOLLAR +Applying ${VAR:D...} to "$$$$$$$$" (VARE_WANTRES|VARE_KEEP_DOLLAR, none, none) +Var_Parse: ${8_DOLLARS}} with VARE_WANTRES|VARE_KEEP_DOLLAR +Result of ${VAR:D${8_DOLLARS}} is "$$$$$$$$" (VARE_WANTRES|VARE_KEEP_DOLLAR, none, none) +Global:VAR = $$$$$$$$ +Var_Parse: ${VAR:@var@${8_DOLLARS}@} with VARE_WANTRES|VARE_KEEP_DOLLAR +Applying ${VAR:@...} to "$$$$$$$$" (VARE_WANTRES|VARE_KEEP_DOLLAR, none, none) +Modifier part: "var" +Modifier part: "${8_DOLLARS}" +ModifyWords: split "$$$$$$$$" into 1 words +Global:var = $$$$$$$$ +Var_Parse: ${8_DOLLARS} with VARE_WANTRES +ModifyWord_Loop: in "$$$$$$$$", replace "var" with "${8_DOLLARS}" to "$$$$" +Global:delete var +Result of ${VAR:@var@${8_DOLLARS}@} is "$$$$" (VARE_WANTRES|VARE_KEEP_DOLLAR, none, none) +Global:VAR = $$$$ +Global:.MAKEFLAGS = -r -k -d v -d +Global:.MAKEFLAGS = -r -k -d v -d 0 exit status 0 diff --git a/contrib/bmake/unit-tests/varmod-defined.mk b/contrib/bmake/unit-tests/varmod-defined.mk index a722ebf666e6..59b9d79d754b 100644 --- a/contrib/bmake/unit-tests/varmod-defined.mk +++ b/contrib/bmake/unit-tests/varmod-defined.mk @@ -1,8 +1,10 @@ -# $NetBSD: varmod-defined.mk,v 1.7 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-defined.mk,v 1.9 2020/11/12 00:40:55 rillig Exp $ # # Tests for the :D variable modifier, which returns the given string # if the variable is defined. It is closely related to the :U modifier. +.MAKE.SAVE_DOLLARS= yes + DEF= defined .undef UNDEF @@ -85,5 +87,19 @@ DEF= defined # TODO: Add more tests for parsing the plain text part, to cover each branch # of ApplyModifier_Defined. +# The :D and :U modifiers behave differently from the :@var@ modifier in +# that they preserve dollars in a ':=' assignment. This is because +# ApplyModifier_Defined passes the eflags unmodified to Var_Parse, unlike +# ApplyModifier_Loop, which uses ParseModifierPart, which in turn removes +# VARE_KEEP_DOLLAR from eflags. +# +# XXX: This inconsistency is documented nowhere. +.MAKEFLAGS: -dv +8_DOLLARS= $$$$$$$$ +VAR:= ${8_DOLLARS} +VAR:= ${VAR:D${8_DOLLARS}} +VAR:= ${VAR:@var@${8_DOLLARS}@} +.MAKEFLAGS: -d0 + all: @:; diff --git a/contrib/bmake/unit-tests/varmod-exclam-shell.mk b/contrib/bmake/unit-tests/varmod-exclam-shell.mk index eaad8275805f..14b3d2510b72 100644 --- a/contrib/bmake/unit-tests/varmod-exclam-shell.mk +++ b/contrib/bmake/unit-tests/varmod-exclam-shell.mk @@ -1,27 +1,36 @@ -# $NetBSD: varmod-exclam-shell.mk,v 1.3 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-exclam-shell.mk,v 1.4 2020/11/03 18:42:33 rillig Exp $ # -# Tests for the :!cmd! variable modifier. +# Tests for the :!cmd! variable modifier, which evaluates the modifier +# argument, independent of the value or the name of the original variable. .if ${:!echo hello | tr 'l' 'l'!} != "hello" -. warning unexpected +. error .endif # The output is truncated at the first null byte. # Cmd_Exec returns only a string pointer without length information. +# Truncating the output is not necessarily intended but may also be a side +# effect from the implementation. Having null bytes in the output of a +# shell command is so unusual that it doesn't matter in practice. .if ${:!echo hello | tr 'l' '\0'!} != "he" -. warning unexpected +. error .endif +# The newline at the end of the output is stripped. .if ${:!echo!} != "" -. warning A newline at the end of the output must be stripped. +. error .endif +# Only the final newline of the output is stripped. All other newlines are +# converted to spaces. .if ${:!echo;echo!} != " " -. warning Only a single newline at the end of the output is stripped. +. error .endif +# Each newline in the output is converted to a space, except for the newline +# at the end of the output, which is stripped. .if ${:!echo;echo;echo;echo!} != " " -. warning Other newlines in the output are converted to spaces. +. error .endif all: diff --git a/contrib/bmake/unit-tests/varmod-ifelse.exp b/contrib/bmake/unit-tests/varmod-ifelse.exp index ac1527a11c9e..75518c08117f 100644 --- a/contrib/bmake/unit-tests/varmod-ifelse.exp +++ b/contrib/bmake/unit-tests/varmod-ifelse.exp @@ -3,6 +3,14 @@ make: "varmod-ifelse.mk" line 27: Malformed conditional (${${:Uvariable expressi make: Bad conditional expression ` == ""' in == ""?bad-assign:bad-assign make: Bad conditional expression ` == ""' in == ""?bad-cond:bad-cond make: "varmod-ifelse.mk" line 44: Malformed conditional (${${UNDEF} == "":?bad-cond:bad-cond}) +make: Bad conditional expression `1 == == 2' in 1 == == 2?yes:no +make: "varmod-ifelse.mk" line 66: Malformed conditional (${1 == == 2:?yes:no} != "") +CondParser_Eval: "${1 == == 2:?yes:no}" != "" +CondParser_Eval: 1 == == 2 +lhs = 1.000000, rhs = 0.000000, op = == +make: Bad conditional expression `1 == == 2' in 1 == == 2?yes:no +lhs = "", rhs = "", op = != +make: "varmod-ifelse.mk" line 92: warning: Oops, the parse error should have been propagated. make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/varmod-ifelse.mk b/contrib/bmake/unit-tests/varmod-ifelse.mk index 8bd67195282c..ea94dc875e4d 100644 --- a/contrib/bmake/unit-tests/varmod-ifelse.mk +++ b/contrib/bmake/unit-tests/varmod-ifelse.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-ifelse.mk,v 1.5 2020/10/23 14:24:51 rillig Exp $ +# $NetBSD: varmod-ifelse.mk,v 1.6 2020/11/12 00:29:55 rillig Exp $ # # Tests for the ${cond:?then:else} variable modifier, which evaluates either # the then-expression or the else-expression, depending on the condition. @@ -57,5 +57,41 @@ COND:= ${${UNDEF} == "":?bad-assign:bad-assign} . error .endif +# This line generates 2 error messages. The first comes from evaluating the +# malformed conditional "1 == == 2", which is reported as "Bad conditional +# expression" by ApplyModifier_IfElse. The variable expression containing that +# conditional therefore returns a parse error from Var_Parse, and this parse +# error propagates to CondEvalExpression, where the "Malformed conditional" +# comes from. +.if ${1 == == 2:?yes:no} != "" +. error +.else +. error +.endif + +# If the "Bad conditional expression" appears in a quoted string literal, the +# error message "Malformed conditional" is not printed, leaving only the "Bad +# conditional expression". +# +# XXX: The left-hand side is enclosed in quotes. This results in Var_Parse +# being called without VARE_UNDEFERR being set. When ApplyModifier_IfElse +# returns AMR_CLEANUP as result, Var_Parse returns varUndefined since the +# value of the variable expression is still undefined. CondParser_String is +# then supposed to do proper error handling, but since varUndefined is local +# to var.c, it cannot distinguish this return value from an ordinary empty +# string. The left-hand side of the comparison is therefore just an empty +# string, which is obviously equal to the empty string on the right-hand side. +# +# XXX: The debug log for -dc shows a comparison between 1.0 and 0.0. The +# 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 +.if "${1 == == 2:?yes:no}" != "" +. error +.else +. warning Oops, the parse error should have been propagated. +.endif +.MAKEFLAGS: -d0 + all: @:; diff --git a/contrib/bmake/unit-tests/varmod-loop.exp b/contrib/bmake/unit-tests/varmod-loop.exp index 497de68df82c..66cfd6f51e16 100644 --- a/contrib/bmake/unit-tests/varmod-loop.exp +++ b/contrib/bmake/unit-tests/varmod-loop.exp @@ -1,3 +1,11 @@ +ParseReadLine (117): 'USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$' +CondParser_Eval: ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$" +lhs = "$$$$ $$$$ $$$$", rhs = "$$$$ $$$$ $$$$", op = != +ParseReadLine (122): 'SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS}' +CondParser_Eval: ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$" +lhs = "$$ $$$$ $$$$", rhs = "$$ $$$$ $$$$", op = != +ParseReadLine (147): '.MAKEFLAGS: -d0' +ParseDoDependency(.MAKEFLAGS: -d0) :+one+ +two+ +three+: :x1y x2y x3y: :x1y x2y x3y: diff --git a/contrib/bmake/unit-tests/varmod-loop.mk b/contrib/bmake/unit-tests/varmod-loop.mk index a3fbbfceae8d..654c449d7bfa 100644 --- a/contrib/bmake/unit-tests/varmod-loop.mk +++ b/contrib/bmake/unit-tests/varmod-loop.mk @@ -1,7 +1,9 @@ -# $NetBSD: varmod-loop.mk,v 1.5 2020/10/31 12:34:03 rillig Exp $ +# $NetBSD: varmod-loop.mk,v 1.8 2020/11/12 00:40:55 rillig Exp $ # # Tests for the :@var@...${var}...@ variable modifier. +.MAKE.SAVE_DOLLARS= yes + all: mod-loop-varname all: mod-loop-resolve all: mod-loop-varname-dollar @@ -57,7 +59,7 @@ mod-loop-varname-dollar: @echo $@:${1 2 3:L:@v$$@($v)@:Q}. @echo $@:${1 2 3:L:@v$$$@($v)@:Q}. -# Demonstrate that it is possible to generate dollar characters using the +# Demonstrate that it is possible to generate dollar signs using the # :@ modifier. # # These are edge cases that could have resulted in a parse error as well @@ -100,3 +102,46 @@ mod-loop-dollar: .if defined(var) . error .endif + +# Assignment using the ':=' operator, combined with the :@var@ modifier +# +8_DOLLARS= $$$$$$$$ +# This string literal is written with 8 dollars, and this is saved as the +# variable value. But as soon as this value is evaluated, it goes through +# Var_Subst, which replaces each '$$' with a single '$'. This could be +# prevented by VARE_KEEP_DOLLAR, but that flag is usually removed before +# expanding subexpressions. See ApplyModifier_Loop and ParseModifierPart +# for examples. +# +.MAKEFLAGS: -dcp +USE_8_DOLLARS= ${:U1:@var@${8_DOLLARS}@} ${8_DOLLARS} $$$$$$$$ +.if ${USE_8_DOLLARS} != "\$\$\$\$ \$\$\$\$ \$\$\$\$" +. error +.endif +# +SUBST_CONTAINING_LOOP:= ${USE_8_DOLLARS} +# The ':=' assignment operator evaluates the variable value using the flag +# VARE_KEEP_DOLLAR, which means that some dollar signs are preserved, but not +# all. The dollar signs in the top-level expression and in the indirect +# ${8_DOLLARS} are preserved. +# +# The variable modifier :@var@ does not preserve the dollar signs though, no +# matter in which context it is evaluated. What happens in detail is: +# First, the modifier part "${8_DOLLARS}" is parsed without expanding it. +# Next, each word of the value is expanded on its own, and at this moment +# in ApplyModifier_Loop, the VARE_KEEP_DOLLAR flag is not passed down to +# ModifyWords, resulting in "$$$$" for the first word of USE_8_DOLLARS. +# +# The remaining words of USE_8_DOLLARS are not affected by any variable +# modifier and are thus expanded with the flag VARE_KEEP_DOLLAR in action. +# The variable SUBST_CONTAINING_LOOP therefore gets assigned the raw value +# "$$$$ $$$$$$$$ $$$$$$$$". +# +# The variable expression in the condition then expands this raw stored value +# once, resulting in "$$ $$$$ $$$$". The effects from VARE_KEEP_DOLLAR no +# longer take place since they had only been active during the evaluation of +# the variable assignment. +.if ${SUBST_CONTAINING_LOOP} != "\$\$ \$\$\$\$ \$\$\$\$" +. error +.endif +.MAKEFLAGS: -d0 diff --git a/contrib/bmake/unit-tests/varmod-match.mk b/contrib/bmake/unit-tests/varmod-match.mk index 5e16a9cc8bf1..9b56fb451eda 100644 --- a/contrib/bmake/unit-tests/varmod-match.mk +++ b/contrib/bmake/unit-tests/varmod-match.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-match.mk,v 1.5 2020/09/13 05:36:26 rillig Exp $ +# $NetBSD: varmod-match.mk,v 1.6 2020/11/15 18:33:41 rillig Exp $ # # Tests for the :M variable modifier, which filters words that match the # given pattern. @@ -51,5 +51,10 @@ ${:U*}= asterisk . error .endif +# TODO: ${VAR:M(((}}}} +# TODO: ${VAR:M{{{)))} +# TODO: ${VAR:M${UNBALANCED}} +# TODO: ${VAR:M${:U(((\}\}\}}} + all: @:; diff --git a/contrib/bmake/unit-tests/varmod-order-shuffle.mk b/contrib/bmake/unit-tests/varmod-order-shuffle.mk index 4ad057e0a810..185141b6c4a5 100644 --- a/contrib/bmake/unit-tests/varmod-order-shuffle.mk +++ b/contrib/bmake/unit-tests/varmod-order-shuffle.mk @@ -1,8 +1,10 @@ -# $NetBSD: varmod-order-shuffle.mk,v 1.5 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-order-shuffle.mk,v 1.6 2020/11/09 20:16:33 rillig Exp $ # # Tests for the :Ox variable modifier, which returns the words of the # variable, shuffled. # +# The variable modifier :Ox is available since 2005-06-01. +# # As of 2020-08-16, make uses random(3) seeded by the current time in seconds. # This makes the random numbers completely predictable since there is no other # part of make that uses random numbers. diff --git a/contrib/bmake/unit-tests/varmod-shell.exp b/contrib/bmake/unit-tests/varmod-shell.exp index 39a9383953dd..9aef0c9e5acc 100644 --- a/contrib/bmake/unit-tests/varmod-shell.exp +++ b/contrib/bmake/unit-tests/varmod-shell.exp @@ -1 +1,3 @@ +make: "echo word; false" returned non-zero status +make: "echo word; false" returned non-zero status exit status 0 diff --git a/contrib/bmake/unit-tests/varmod-shell.mk b/contrib/bmake/unit-tests/varmod-shell.mk index 052968004f1b..db82e302f2a8 100644 --- a/contrib/bmake/unit-tests/varmod-shell.mk +++ b/contrib/bmake/unit-tests/varmod-shell.mk @@ -1,9 +1,35 @@ -# $NetBSD: varmod-shell.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: varmod-shell.mk,v 1.5 2020/11/17 20:11:02 rillig Exp $ # # Tests for the :sh variable modifier, which runs the shell command # given by the variable value and returns its output. +# +# This modifier has been added on 2000-04-29. +# +# See also: +# ApplyModifier_ShellCommand # TODO: Implementation +# The command to be run is enclosed between exclamation marks. +# The previous value of the expression is irrelevant for this modifier. +# The :!cmd! modifier turns an undefined expression into a defined one. +.if ${:!echo word!} != "word" +. error +.endif + +# If the command exits with non-zero, an error message is printed. +# XXX: Processing continues as usual though. +# +# 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. It's strange that such a simple bug could +# survive such a long time. +.if ${:!echo word; false!} != "word" +. error +.endif +.if ${:Uprevious value:!echo word; false!} != "word" +. error +.endif + all: @:; diff --git a/contrib/bmake/unit-tests/varmod-subst.exp b/contrib/bmake/unit-tests/varmod-subst.exp index e752fb8058a8..3122c17b1ed3 100644 --- a/contrib/bmake/unit-tests/varmod-subst.exp +++ b/contrib/bmake/unit-tests/varmod-subst.exp @@ -9,28 +9,39 @@ mod-subst-delimiter: 1 two 3 horizontal tabulator 1 two 3 space 1 two 3 exclamation mark -1 two 3 double quotes -1 two 3 hash -1 two 3 dollar -1 two 3 percent +1 two 3 quotation mark +1 two 3 number sign +1 two 3 dollar sign +1 two 3 percent sign +1 two 3 ampersand 1 two 3 apostrophe -1 two 3 opening parenthesis -1 two 3 closing parenthesis +1 two 3 left parenthesis +1 two 3 right parenthesis +1 two 3 asterisk +1 two 3 plus sign +1 two 3 comma +1 two 3 hyphen-minus +1 two 3 full stop +1 two 3 solidus 1 two 3 digit 1 two 3 colon -1 two 3 less than sign -1 two 3 equal sign -1 two 3 greater than sign +1 two 3 semicolon +1 two 3 less-than sign +1 two 3 equals sign +1 two 3 greater-than sign 1 two 3 question mark -1 two 3 at -1 two 3 letter -1 two 3 opening bracket -1 two 3 backslash -1 two 3 closing bracket -1 two 3 caret -1 two 3 opening brace +1 two 3 commercial at +1 two 3 capital letter +1 two 3 left square bracket +1 two 3 reverse solidus +1 two 3 right square bracket +1 two 3 circumflex accent +1 two 3 low line +1 two 3 grave accent +1 two 3 small letter +1 two 3 left curly bracket 1 two 3 vertical line -1 two 3 closing brace +1 two 3 right curly bracket 1 two 3 tilde mod-subst-chain: A B c. diff --git a/contrib/bmake/unit-tests/varmod-subst.mk b/contrib/bmake/unit-tests/varmod-subst.mk index 5fc657ea10ee..3c3ee673c07a 100644 --- a/contrib/bmake/unit-tests/varmod-subst.mk +++ b/contrib/bmake/unit-tests/varmod-subst.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-subst.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-subst.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $ # # Tests for the :S,from,to, variable modifier. @@ -8,55 +8,72 @@ all: mod-subst-chain all: mod-subst-dollar WORDS= sequences of letters + .if ${WORDS:S,,,} != ${WORDS} . warning The empty pattern matches something. .endif + .if ${WORDS:S,e,*,1} != "s*quences of letters" . warning The :S modifier flag '1' is not applied exactly once. .endif + .if ${WORDS:S,f,*,1} != "sequences o* letters" . warning The :S modifier flag '1' is only applied to the first word,\ not to the first occurrence. .endif + .if ${WORDS:S,e,*,} != "s*quences of l*tters" . warning The :S modifier does not replace every first match per word. .endif + .if ${WORDS:S,e,*,g} != "s*qu*nc*s of l*tt*rs" . warning The :S modifier flag 'g' does not replace every occurrence. .endif + .if ${WORDS:S,^sequ,occurr,} != "occurrences of letters" . warning The :S modifier fails for a short match anchored at the start. .endif + .if ${WORDS:S,^of,with,} != "sequences with letters" . warning The :S modifier fails for an exact match anchored at the start. .endif + .if ${WORDS:S,^office,does not match,} != ${WORDS} . warning The :S modifier matches a too long pattern anchored at the start. .endif + .if ${WORDS:S,f$,r,} != "sequences or letters" . warning The :S modifier fails for a short match anchored at the end. .endif + .if ${WORDS:S,s$,,} != "sequence of letter" . warning The :S modifier fails to replace one occurrence per word. .endif + .if ${WORDS:S,of$,,} != "sequences letters" . warning The :S modifier fails for an exact match anchored at the end. .endif + .if ${WORDS:S,eof$,,} != ${WORDS} . warning The :S modifier matches a too long pattern anchored at the end. .endif + .if ${WORDS:S,^of$,,} != "sequences letters" . warning The :S modifier does not match a word anchored at both ends. .endif + .if ${WORDS:S,^o$,,} != ${WORDS} . warning The :S modifier matches a prefix anchored at both ends. .endif + .if ${WORDS:S,^f$,,} != ${WORDS} . warning The :S modifier matches a suffix anchored at both ends. .endif + .if ${WORDS:S,^eof$,,} != ${WORDS} . warning The :S modifier matches a too long prefix anchored at both ends. .endif + .if ${WORDS:S,^office$,,} != ${WORDS} . warning The :S modifier matches a too long suffix anchored at both ends. .endif @@ -78,30 +95,41 @@ mod-subst-delimiter: @echo ${:U1 2 3:S 2 two :Q} horizontal tabulator @echo ${:U1 2 3:S 2 two :Q} space @echo ${:U1 2 3:S!2!two!:Q} exclamation mark - @echo ${:U1 2 3:S"2"two":Q} double quotes + @echo ${:U1 2 3:S"2"two":Q} quotation mark # In shell command lines, the hash does not need to be escaped. # It needs to be escaped in variable assignment lines though. - @echo ${:U1 2 3:S#2#two#:Q} hash - @echo ${:U1 2 3:S$2$two$:Q} dollar - @echo ${:U1 2 3:S%2%two%:Q} percent + @echo ${:U1 2 3:S#2#two#:Q} number sign + @echo ${:U1 2 3:S$2$two$:Q} dollar sign + @echo ${:U1 2 3:S%2%two%:Q} percent sign + @echo ${:U1 2 3:S&2&two&:Q} ampersand @echo ${:U1 2 3:S'2'two':Q} apostrophe - @echo ${:U1 2 3:S(2(two(:Q} opening parenthesis - @echo ${:U1 2 3:S)2)two):Q} closing parenthesis + @echo ${:U1 2 3:S(2(two(:Q} left parenthesis + @echo ${:U1 2 3:S)2)two):Q} right parenthesis + @echo ${:U1 2 3:S*2*two*:Q} asterisk + @echo ${:U1 2 3:S+2+two+:Q} plus sign + @echo ${:U1 2 3:S,2,two,:Q} comma + @echo ${:U1 2 3:S-2-two-:Q} hyphen-minus + @echo ${:U1 2 3:S.2.two.:Q} full stop + @echo ${:U1 2 3:S/2/two/:Q} solidus @echo ${:U1 2 3:S121two1:Q} digit @echo ${:U1 2 3:S:2:two::Q} colon - @echo ${:U1 2 3:S<2<two<:Q} less than sign - @echo ${:U1 2 3:S=2=two=:Q} equal sign - @echo ${:U1 2 3:S>2>two>:Q} greater than sign + @echo ${:U1 2 3:S;2;two;:Q} semicolon + @echo ${:U1 2 3:S<2<two<:Q} less-than sign + @echo ${:U1 2 3:S=2=two=:Q} equals sign + @echo ${:U1 2 3:S>2>two>:Q} greater-than sign @echo ${:U1 2 3:S?2?two?:Q} question mark - @echo ${:U1 2 3:S@2@two@:Q} at - @echo ${:U1 2 3:Sa2atwoa:Q} letter - @echo ${:U1 2 3:S[2[two[:Q} opening bracket - @echo ${:U1 2 3:S\2\two\:Q} backslash - @echo ${:U1 2 3:S]2]two]:Q} closing bracket - @echo ${:U1 2 3:S^2^two^:Q} caret - @echo ${:U1 2 3:S{2{two{:Q} opening brace + @echo ${:U1 2 3:S@2@two@:Q} commercial at + @echo ${:U1 2 3:SA2AtwoA:Q} capital letter + @echo ${:U1 2 3:S[2[two[:Q} left square bracket + @echo ${:U1 2 3:S\2\two\:Q} reverse solidus + @echo ${:U1 2 3:S]2]two]:Q} right square bracket + @echo ${:U1 2 3:S^2^two^:Q} circumflex accent + @echo ${:U1 2 3:S_2_two_:Q} low line + @echo ${:U1 2 3:S`2`two`:Q} grave accent + @echo ${:U1 2 3:Sa2atwoa:Q} small letter + @echo ${:U1 2 3:S{2{two{:Q} left curly bracket @echo ${:U1 2 3:S|2|two|:Q} vertical line - @echo ${:U1 2 3:S}2}two}:Q} closing brace + @echo ${:U1 2 3:S}2}two}:Q} right curly bracket @echo ${:U1 2 3:S~2~two~:Q} tilde # The :S and :C modifiers can be chained without a separating ':'. @@ -121,7 +149,7 @@ mod-subst-chain: # modifiers with the matching modifiers. @echo ${:Uvalue:S,a,x,i}. -# No matter how many dollar characters there are, they all get merged +# No matter how many dollar signs there are, they all get merged # into a single dollar by the :S modifier. # # As of 2020-08-09, this is because ParseModifierPart sees a '$' and @@ -145,7 +173,7 @@ mod-subst-dollar: @echo $@:${:U40:S,^,$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$,:Q}: # This generates no dollar at all: @echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}: -# Here is an alternative way to generate dollar characters. +# Here is an alternative way to generate dollar signs. # It's unexpectedly complicated though. @echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}: # In modifiers, dollars are escaped using the backslash, not using another diff --git a/contrib/bmake/unit-tests/varmod-to-abs.exp b/contrib/bmake/unit-tests/varmod-to-abs.exp index 39a9383953dd..426b4d39744f 100644 --- a/contrib/bmake/unit-tests/varmod-to-abs.exp +++ b/contrib/bmake/unit-tests/varmod-to-abs.exp @@ -1 +1,5 @@ +make: "varmod-to-abs.mk" line 18: does-not-exist.c +make: "varmod-to-abs.mk" line 19: does-not-exist.c +cached_realpath: varmod-to-abs.mk -> varmod-to-abs.mk +make: "varmod-to-abs.mk" line 23: varmod-to-abs.mk exit status 0 diff --git a/contrib/bmake/unit-tests/varmod-to-abs.mk b/contrib/bmake/unit-tests/varmod-to-abs.mk index 7a74e89088e5..7f23318487e3 100644 --- a/contrib/bmake/unit-tests/varmod-to-abs.mk +++ b/contrib/bmake/unit-tests/varmod-to-abs.mk @@ -1,9 +1,28 @@ -# $NetBSD: varmod-to-abs.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: varmod-to-abs.mk,v 1.5 2020/11/15 05:48:17 rillig Exp $ # # Tests for the :tA variable modifier, which returns the absolute path for # each of the words in the variable value. # TODO: Implementation +# Between 2016-06-03 and 2020-11-14, it was possible to trick the :tA modifier +# into resolving completely unrelated absolute paths by defining a global +# variable with the same name as the path that is to be resolved. There were +# a few restrictions though: The "redirected" path had to start with a slash, +# and it had to exist (see ModifyWord_Realpath). +# +# This unintended behavior was caused by cached_realpath using a GNode for +# keeping the cache, just like the GNode for global variables. +.MAKEFLAGS: -dd +does-not-exist.c= /dev/null +.info ${does-not-exist.c:L:tA} +.info ${does-not-exist.c:L:tA} + +# The output of the following line is modified by the global _SED_CMDS in +# unit-tests/Makefile. See the .rawout file for the truth. +.info ${MAKEFILE:tA} + +.MAKEFLAGS: -d0 + all: @:; diff --git a/contrib/bmake/unit-tests/varmod-to-lower.mk b/contrib/bmake/unit-tests/varmod-to-lower.mk index 6ab4af740fae..19d3406054b7 100644 --- a/contrib/bmake/unit-tests/varmod-to-lower.mk +++ b/contrib/bmake/unit-tests/varmod-to-lower.mk @@ -1,7 +1,9 @@ -# $NetBSD: varmod-to-lower.mk,v 1.4 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-to-lower.mk,v 1.5 2020/11/15 20:20:58 rillig Exp $ # # Tests for the :tl variable modifier, which returns the words in the # variable value, converted to lowercase. +# +# TODO: What about non-ASCII characters? ISO-8859-1, UTF-8? .if ${:UUPPER:tl} != "upper" . error diff --git a/contrib/bmake/unit-tests/varmod-to-separator.mk b/contrib/bmake/unit-tests/varmod-to-separator.mk index 89aa3d978bee..08c6126ecc68 100644 --- a/contrib/bmake/unit-tests/varmod-to-separator.mk +++ b/contrib/bmake/unit-tests/varmod-to-separator.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod-to-separator.mk,v 1.6 2020/11/01 14:36:25 rillig Exp $ +# $NetBSD: varmod-to-separator.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $ # # Tests for the :ts variable modifier, which joins the words of the variable # using an arbitrary character as word separator. @@ -166,4 +166,10 @@ WORDS= one two three four five six . info This line is not reached. .endif +# TODO: This modifier used to accept decimal numbers as well, in the form +# ':ts\120'. When has this been changed to octal, and what happens now +# for ':ts\90' ('Z' in decimal ASCII, undefined in octal)? + +# TODO: :ts\x1F600 + all: diff --git a/contrib/bmake/unit-tests/varmod-undefined.mk b/contrib/bmake/unit-tests/varmod-undefined.mk index 1beaa763716b..e06fc73244ab 100644 --- a/contrib/bmake/unit-tests/varmod-undefined.mk +++ b/contrib/bmake/unit-tests/varmod-undefined.mk @@ -1,9 +1,10 @@ -# $NetBSD: varmod-undefined.mk,v 1.6 2020/10/24 08:46:08 rillig Exp $ +# $NetBSD: varmod-undefined.mk,v 1.7 2020/11/15 20:20:58 rillig Exp $ # # Tests for the :U variable modifier, which returns the given string # if the variable is undefined. # # See also: +# directive-for.mk # varmod-defined.mk # The pattern ${:Uword} is heavily used when expanding .for loops. diff --git a/contrib/bmake/unit-tests/varmod.exp b/contrib/bmake/unit-tests/varmod.exp index e4257bb0b596..a80979e1410d 100644 --- a/contrib/bmake/unit-tests/varmod.exp +++ b/contrib/bmake/unit-tests/varmod.exp @@ -1,6 +1,8 @@ make: "varmod.mk" line 42: To escape a dollar, use \$, not $$, at "$$:L} != """ make: "varmod.mk" line 42: Invalid variable name ':', at "$:L} != """ make: "varmod.mk" line 47: Dollar followed by nothing +make: "varmod.mk" line 56: Missing delimiter ':' after modifier "P" +make: "varmod.mk" line 57: Unknown directive "error" make: Fatal errors encountered -- cannot continue make: stopped in unit-tests exit status 1 diff --git a/contrib/bmake/unit-tests/varmod.mk b/contrib/bmake/unit-tests/varmod.mk index 0a2a4c52c29b..b496bdd206a2 100644 --- a/contrib/bmake/unit-tests/varmod.mk +++ b/contrib/bmake/unit-tests/varmod.mk @@ -1,4 +1,4 @@ -# $NetBSD: varmod.mk,v 1.3 2020/09/13 07:42:20 rillig Exp $ +# $NetBSD: varmod.mk,v 1.4 2020/11/02 17:30:22 rillig Exp $ # # Tests for variable modifiers, such as :Q, :S,from,to or :Ufallback. @@ -48,4 +48,13 @@ DOLLAR2= ${:U\$} . error .endif +# The variable modifier :P does not fall back to the SysV modifier. +# Therefore the modifier :P=RE generates a parse error. +# XXX: The .error should not be reached since the variable expression is +# malformed. +VAR= STOP +.if ${VAR:P=RE} != "STORE" +. error +.endif + all: # nothing diff --git a/contrib/bmake/unit-tests/varname-dot-shell.exp b/contrib/bmake/unit-tests/varname-dot-shell.exp index 704d4863d4e9..f219515444cf 100755 --- a/contrib/bmake/unit-tests/varname-dot-shell.exp +++ b/contrib/bmake/unit-tests/varname-dot-shell.exp @@ -1,6 +1,6 @@ ParseReadLine (10): 'ORIG_SHELL:= ${.SHELL}' Global:ORIG_SHELL = -Var_Parse: ${.SHELL} with VARE_WANTRES|VARE_ASSIGN +Var_Parse: ${.SHELL} with VARE_WANTRES|VARE_KEEP_DOLLAR Global:delete .SHELL (not found) Command:.SHELL = (details omitted) Global:ORIG_SHELL = (details omitted) diff --git a/contrib/bmake/unit-tests/varname-empty.exp b/contrib/bmake/unit-tests/varname-empty.exp index ba465cc3eff2..24c596e1c568 100644 --- a/contrib/bmake/unit-tests/varname-empty.exp +++ b/contrib/bmake/unit-tests/varname-empty.exp @@ -1,5 +1,5 @@ Var_Set("${:U}", "cmdline-u", ...) name expands to empty string - ignored -Var_Set("", "cmline-plain", ...) name expands to empty string - ignored +Var_Set("", "cmdline-plain", ...) name expands to empty string - ignored Var_Set("", "default", ...) name expands to empty string - ignored Var_Set("", "assigned", ...) name expands to empty string - ignored Var_Set("", "appended", ...) name expands to empty string - ignored diff --git a/contrib/bmake/unit-tests/varname-makefile.exp b/contrib/bmake/unit-tests/varname-makefile.exp index 39a9383953dd..67919c400193 100755 --- a/contrib/bmake/unit-tests/varname-makefile.exp +++ b/contrib/bmake/unit-tests/varname-makefile.exp @@ -1 +1,2 @@ +: In the end, MAKEFILE is /dev/null. exit status 0 diff --git a/contrib/bmake/unit-tests/varname-makefile.mk b/contrib/bmake/unit-tests/varname-makefile.mk index 785fe9301df2..641c53de9cf8 100755 --- a/contrib/bmake/unit-tests/varname-makefile.mk +++ b/contrib/bmake/unit-tests/varname-makefile.mk @@ -1,4 +1,4 @@ -# $NetBSD: varname-makefile.mk,v 1.2 2020/09/05 06:25:38 rillig Exp $ +# $NetBSD: varname-makefile.mk,v 1.3 2020/11/09 22:36:44 rillig Exp $ # # Tests for the special MAKEFILE variable, which contains the current # makefile from the -f command line option. @@ -41,4 +41,9 @@ MAKEFILE= overwritten .endif all: - @:; + # MAKEFILE is the file that appeared last in the command line. + : In the end, MAKEFILE is ${MAKEFILE}. + +# Additional makefiles can be added while reading a makefile. They will be +# read in order. +.MAKEFLAGS: -f /dev/null diff --git a/contrib/bmake/unit-tests/varname-vpath.exp b/contrib/bmake/unit-tests/varname-vpath.exp index 39a9383953dd..bf7a3036e99d 100644 --- a/contrib/bmake/unit-tests/varname-vpath.exp +++ b/contrib/bmake/unit-tests/varname-vpath.exp @@ -1 +1,12 @@ +CondParser_Eval: !defined(TEST_MAIN) +CondParser_Eval: exists(file-in-subdirectory) +exists(file-in-subdirectory) result is "" +CondParser_Eval: exists(file2-in-subdirectory) +exists(file2-in-subdirectory) result is "" +CondParser_Eval: exists(file-in-subdirectory) +exists(file-in-subdirectory) result is "varname-vpath.dir/file-in-subdirectory" +: yes 1 +CondParser_Eval: exists(file2-in-subdirectory) +exists(file2-in-subdirectory) result is "varname-vpath.dir2/file2-in-subdirectory" +: yes 2 exit status 0 diff --git a/contrib/bmake/unit-tests/varname-vpath.mk b/contrib/bmake/unit-tests/varname-vpath.mk index 8924647a5072..65fe9945c202 100644 --- a/contrib/bmake/unit-tests/varname-vpath.mk +++ b/contrib/bmake/unit-tests/varname-vpath.mk @@ -1,8 +1,42 @@ -# $NetBSD: varname-vpath.mk,v 1.2 2020/08/16 14:25:16 rillig Exp $ +# $NetBSD: varname-vpath.mk,v 1.3 2020/11/10 00:19:19 rillig Exp $ # -# Tests for the special VPATH variable. +# Tests for the special VPATH variable, which is an obsolete way of +# specifying a colon-separated search path. This search path is not active +# when the makefiles are read, but only later when the shell commands are run. +# +# Instead of the VPATH, better use the -I option or the special target .PATH. + +.if !defined(TEST_MAIN) + +all: .SILENT + rm -rf varname-vpath.dir + mkdir varname-vpath.dir + touch varname-vpath.dir/file-in-subdirectory + rm -rf varname-vpath.dir2 + mkdir varname-vpath.dir2 + touch varname-vpath.dir2/file2-in-subdirectory + + TEST_MAIN=yes VPATH=varname-vpath.dir:varname-vpath.dir2 \ + ${MAKE} -f ${MAKEFILE} -dc -# TODO: Implementation + rm -r varname-vpath.dir + rm -r varname-vpath.dir2 + +.else + +# The VPATH variable does not take effect at parse time. +# It is evaluated only once, between reading the makefiles and making the +# targets. Therefore it could also be an ordinary variable, it doesn't need +# to be an environment variable or a command line variable. +. if exists(file-in-subdirectory) +. error +. endif +. if exists(file2-in-subdirectory) +. error +. endif all: - @:; + : ${exists(file-in-subdirectory):L:?yes 1:no 1} + : ${exists(file2-in-subdirectory):L:?yes 2:no 2} + +.endif diff --git a/contrib/bmake/unit-tests/varname.exp b/contrib/bmake/unit-tests/varname.exp index 39a9383953dd..93962d7fb7b7 100644 --- a/contrib/bmake/unit-tests/varname.exp +++ b/contrib/bmake/unit-tests/varname.exp @@ -1 +1,24 @@ -exit status 0 +Global:VAR{{{}}} = 3 braces +Var_Parse: ${VAR{{{}}}}" != "3 braces" with VARE_WANTRES +Global:VARNAME = VAR((( +Var_Parse: ${VARNAME} with VARE_WANTRES +Global:VAR((( = 3 open parentheses +Var_Parse: ${VAR(((}}}}" != "3 open parentheses}}}" with VARE_WANTRES +Var_Parse: ${:UVAR(((}= try1 with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:UVAR(((} is "VAR(((" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Global:.ALLTARGETS = VAR(((=) +make: "varname.mk" line 30: No closing parenthesis in archive specification +make: "varname.mk" line 30: Error in archive specification: "VAR" +Var_Parse: ${:UVAR\(\(\(}= try2 with VARE_UNDEFERR|VARE_WANTRES +Applying ${:U...} to "" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF) +Result of ${:UVAR\(\(\(} is "VAR\(\(\(" (VARE_UNDEFERR|VARE_WANTRES, none, VEF_UNDEF|VEF_DEF) +Global:.ALLTARGETS = VAR(((=) VAR\(\(\(= +make: "varname.mk" line 35: Need an operator +Var_Parse: ${VARNAME} with VARE_WANTRES +Global:VAR((( = try3 +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/contrib/bmake/unit-tests/varname.mk b/contrib/bmake/unit-tests/varname.mk index e9fbc89873ca..f586c7602cb7 100644 --- a/contrib/bmake/unit-tests/varname.mk +++ b/contrib/bmake/unit-tests/varname.mk @@ -1,8 +1,44 @@ -# $NetBSD: varname.mk,v 1.4 2020/10/18 08:47:54 rillig Exp $ +# $NetBSD: varname.mk,v 1.8 2020/11/02 22:59:48 rillig Exp $ # # Tests for special variables, such as .MAKE or .PARSEDIR. +# And for variable names in general. -# TODO: Implementation +.MAKEFLAGS: -dv + +# In variable names, braces are allowed, but they must be balanced. +# Parentheses and braces may be mixed. +VAR{{{}}}= 3 braces +.if "${VAR{{{}}}}" != "3 braces" +. error +.endif + +# In variable expressions, the parser works differently. It doesn't treat +# braces and parentheses equally, therefore the first closing brace already +# marks the end of the variable name. +VARNAME= VAR((( +${VARNAME}= 3 open parentheses +.if "${VAR(((}}}}" != "3 open parentheses}}}" +. error +.endif + +# In the above test, the variable name is constructed indirectly. Neither +# of the following expressions produces the intended effect. +# +# 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. +${: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 +# level, which at the end of the line is still 3. Therefore this is not a +# variable assignment as well. +${:UVAR\(\(\(}= try2 +# To assign to a variable with an arbitrary name, the variable name has to +# come from an external source, not the text that is parsed in the assignment +# itself. This is exactly the reason why further above, the indirect +# ${VARNAME} works, while all other attempts fail. +${VARNAME}= try3 + +.MAKEFLAGS: -d0 all: - @:; diff --git a/contrib/bmake/unit-tests/varparse-errors.exp b/contrib/bmake/unit-tests/varparse-errors.exp new file mode 100644 index 000000000000..39a9383953dd --- /dev/null +++ b/contrib/bmake/unit-tests/varparse-errors.exp @@ -0,0 +1 @@ +exit status 0 diff --git a/contrib/bmake/unit-tests/varparse-errors.mk b/contrib/bmake/unit-tests/varparse-errors.mk new file mode 100644 index 000000000000..42f5b65a728e --- /dev/null +++ b/contrib/bmake/unit-tests/varparse-errors.mk @@ -0,0 +1,35 @@ +# $NetBSD: varparse-errors.mk,v 1.1 2020/11/08 16:44:47 rillig Exp $ + +# Tests for parsing and evaluating all kinds of variable expressions. +# +# This is the basis for redesigning the error handling in Var_Parse and +# Var_Subst, collecting typical and not so typical use cases. +# +# See also: +# VarParseResult +# Var_Parse +# Var_Subst + +PLAIN= plain value + +LITERAL_DOLLAR= To get a dollar, double $$ it. + +INDIRECT= An ${:Uindirect} value. + +REF_UNDEF= A reference to an ${UNDEF}undefined variable. + +ERR_UNCLOSED= An ${UNCLOSED variable expression. + +ERR_BAD_MOD= An ${:Uindirect:Z} expression with an unknown modifier. + +ERR_EVAL= An evaluation error ${:Uvalue:C,.,\3,}. + +# In a conditional, a variable expression that is not enclosed in quotes is +# expanded using the flags VARE_UNDEFERR and VARE_WANTRES. +# The variable itself must be defined. +# It may refer to undefined variables though. +.if ${REF_UNDEF} != "A reference to an undefined variable." +. error +.endif + +all: diff --git a/contrib/bmake/unit-tests/varparse-undef-partial.mk b/contrib/bmake/unit-tests/varparse-undef-partial.mk index 4851b6d9d567..27f44d79b31a 100644 --- a/contrib/bmake/unit-tests/varparse-undef-partial.mk +++ b/contrib/bmake/unit-tests/varparse-undef-partial.mk @@ -1,4 +1,4 @@ -# $NetBSD: varparse-undef-partial.mk,v 1.2 2020/09/27 09:53:41 rillig Exp $ +# $NetBSD: varparse-undef-partial.mk,v 1.3 2020/11/04 05:10:01 rillig Exp $ # When an undefined variable is expanded in a ':=' assignment, only the # initial '$' of the variable expression is skipped by the parser, while @@ -9,7 +9,7 @@ LIST= ${DEF} ${UNDEF} ${VAR.${PARAM}} end DEF= defined PARAM= :Q -# The expression ${VAR.{PARAM}} refers to the variable named "VAR.:Q", +# The expression ${VAR.${PARAM}} refers to the variable named "VAR.:Q", # with the ":Q" being part of the name. This variable is not defined, # therefore the initial '$' of that whole expression is skipped by the # parser (see Var_Subst, the Buf_AddByte in the else branch) and the rest @@ -28,15 +28,15 @@ VAR.= var-dot without parameter ${:UVAR.\:Q}= var-dot with parameter :Q # At this point, the variable "VAR." is defined, therefore the expression -# ${VAR.:Q} is expanded as usual. +# ${VAR.:Q} is expanded, consisting of the variable name "VAR." and the +# modifier ":Q". .if ${EVAL} != "defined var-dot\\ without\\ parameter end" . error ${EVAL} .endif # In contrast to the previous line, evaluating the original LIST again now -# produces a different result since the ":Q" has already been inserted -# literally into the expression. The variable named "VAR.:Q" is defined, -# therefore it is resolved as usual. The ":Q" is interpreted as part of the +# produces a different result since the variable named "VAR.:Q" is now +# defined. It is expanded as usual, interpreting the ":Q" as part of the # variable name, as would be expected from reading the variable expression. EVAL:= ${LIST} .if ${EVAL} != "defined var-dot with parameter :Q end" diff --git a/contrib/bmake/unit-tests/varshell.exp b/contrib/bmake/unit-tests/varshell.exp deleted file mode 100644 index 54df3527ed1c..000000000000 --- a/contrib/bmake/unit-tests/varshell.exp +++ /dev/null @@ -1,10 +0,0 @@ -make: "varshell.mk" line 6: warning: "/bin/no/such/command 2> /dev/null" returned non-zero status -make: "varshell.mk" line 9: warning: "false" returned non-zero status -make: "varshell.mk" line 10: warning: "echo "output before the error"; false" returned non-zero status -EXEC_FAILED='' -TERMINATED_BY_SIGNAL='' -ERROR_NO_OUTPUT='' -ERROR_WITH_OUTPUT='output before the error' -NO_ERROR_NO_OUTPUT='' -NO_ERROR_WITH_OUTPUT='this is good' -exit status 0 diff --git a/contrib/bmake/unit-tests/varshell.mk b/contrib/bmake/unit-tests/varshell.mk deleted file mode 100644 index 113c265cce3c..000000000000 --- a/contrib/bmake/unit-tests/varshell.mk +++ /dev/null @@ -1,20 +0,0 @@ -# $Id: varshell.mk,v 1.6 2020/10/26 17:55:23 sjg Exp $ -# $NetBSD: varshell.mk,v 1.4 2020/10/24 08:50:17 rillig Exp $ -# -# Test VAR != shell command - -EXEC_FAILED!= /bin/no/such/command 2> /dev/null -# SunOS cannot handle this one -#TERMINATED_BY_SIGNAL!= kill -14 $$$$ -ERROR_NO_OUTPUT!= false -ERROR_WITH_OUTPUT!= echo "output before the error"; false -NO_ERROR_NO_OUTPUT!= true -NO_ERROR_WITH_OUTPUT!= echo "this is good" - -allvars= EXEC_FAILED TERMINATED_BY_SIGNAL ERROR_NO_OUTPUT ERROR_WITH_OUTPUT \ - NO_ERROR_NO_OUTPUT NO_ERROR_WITH_OUTPUT - -all: -.for v in ${allvars} - @echo ${v}=\'${${v}}\' -.endfor |