Module Name: src Committed By: rillig Date: Sun Nov 15 14:58:14 UTC 2020
Modified Files: src/usr.bin/make/unit-tests: cond-op-not.exp cond-op-not.mk cond-op-parentheses.exp cond-op-parentheses.mk cond-op.exp cond-op.mk cond-short.mk cond-token-number.exp cond-token-number.mk cond-token-plain.mk cond-token-var.exp cond-token-var.mk cond-undef-lint.exp cond-undef-lint.mk cond1.exp cond1.mk Log Message: make(1): add remarks to the tests about conditions To generate a diff of this commit: cvs rdiff -u -r1.2 -r1.3 src/usr.bin/make/unit-tests/cond-op-not.exp \ src/usr.bin/make/unit-tests/cond-op-parentheses.mk \ src/usr.bin/make/unit-tests/cond-token-var.exp \ src/usr.bin/make/unit-tests/cond-undef-lint.mk \ src/usr.bin/make/unit-tests/cond1.exp \ src/usr.bin/make/unit-tests/cond1.mk cvs rdiff -u -r1.5 -r1.6 src/usr.bin/make/unit-tests/cond-op-not.mk \ src/usr.bin/make/unit-tests/cond-token-plain.mk cvs rdiff -u -r1.1 -r1.2 src/usr.bin/make/unit-tests/cond-op-parentheses.exp cvs rdiff -u -r1.6 -r1.7 src/usr.bin/make/unit-tests/cond-op.exp cvs rdiff -u -r1.9 -r1.10 src/usr.bin/make/unit-tests/cond-op.mk cvs rdiff -u -r1.11 -r1.12 src/usr.bin/make/unit-tests/cond-short.mk cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/cond-token-number.exp \ src/usr.bin/make/unit-tests/cond-undef-lint.exp cvs rdiff -u -r1.4 -r1.5 src/usr.bin/make/unit-tests/cond-token-number.mk \ src/usr.bin/make/unit-tests/cond-token-var.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/unit-tests/cond-op-not.exp diff -u src/usr.bin/make/unit-tests/cond-op-not.exp:1.2 src/usr.bin/make/unit-tests/cond-op-not.exp:1.3 --- src/usr.bin/make/unit-tests/cond-op-not.exp:1.2 Sun Nov 15 14:14:24 2020 +++ src/usr.bin/make/unit-tests/cond-op-not.exp Sun Nov 15 14:58:14 2020 @@ -1,6 +1,6 @@ -make: "cond-op-not.mk" line 27: Not empty evaluates to true. -make: "cond-op-not.mk" line 35: Not space evaluates to false. -make: "cond-op-not.mk" line 39: Not 0 evaluates to true. -make: "cond-op-not.mk" line 47: Not 1 evaluates to false. -make: "cond-op-not.mk" line 53: Not word evaluates to false. +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 Index: src/usr.bin/make/unit-tests/cond-op-parentheses.mk diff -u src/usr.bin/make/unit-tests/cond-op-parentheses.mk:1.2 src/usr.bin/make/unit-tests/cond-op-parentheses.mk:1.3 --- src/usr.bin/make/unit-tests/cond-op-parentheses.mk:1.2 Sun Aug 16 14:25:16 2020 +++ src/usr.bin/make/unit-tests/cond-op-parentheses.mk Sun Nov 15 14:58:14 2020 @@ -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: @:; Index: src/usr.bin/make/unit-tests/cond-token-var.exp diff -u src/usr.bin/make/unit-tests/cond-token-var.exp:1.2 src/usr.bin/make/unit-tests/cond-token-var.exp:1.3 --- src/usr.bin/make/unit-tests/cond-token-var.exp:1.2 Thu Aug 20 19:43:42 2020 +++ src/usr.bin/make/unit-tests/cond-token-var.exp Sun Nov 15 14:58:14 2020 @@ -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 Index: src/usr.bin/make/unit-tests/cond-undef-lint.mk diff -u src/usr.bin/make/unit-tests/cond-undef-lint.mk:1.2 src/usr.bin/make/unit-tests/cond-undef-lint.mk:1.3 --- src/usr.bin/make/unit-tests/cond-undef-lint.mk:1.2 Mon Sep 14 07:13:29 2020 +++ src/usr.bin/make/unit-tests/cond-undef-lint.mk Sun Nov 15 14:58:14 2020 @@ -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 Index: src/usr.bin/make/unit-tests/cond1.exp diff -u src/usr.bin/make/unit-tests/cond1.exp:1.2 src/usr.bin/make/unit-tests/cond1.exp:1.3 --- src/usr.bin/make/unit-tests/cond1.exp:1.2 Sat Sep 12 10:39:34 2020 +++ src/usr.bin/make/unit-tests/cond1.exp Sun Nov 15 14:58:14 2020 @@ -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: Index: src/usr.bin/make/unit-tests/cond1.mk diff -u src/usr.bin/make/unit-tests/cond1.mk:1.2 src/usr.bin/make/unit-tests/cond1.mk:1.3 --- src/usr.bin/make/unit-tests/cond1.mk:1.2 Sat Oct 24 08:34:59 2020 +++ src/usr.bin/make/unit-tests/cond1.mk Sun Nov 15 14:58:14 2020 @@ -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 Index: src/usr.bin/make/unit-tests/cond-op-not.mk diff -u src/usr.bin/make/unit-tests/cond-op-not.mk:1.5 src/usr.bin/make/unit-tests/cond-op-not.mk:1.6 --- src/usr.bin/make/unit-tests/cond-op-not.mk:1.5 Sun Nov 15 14:14:24 2020 +++ src/usr.bin/make/unit-tests/cond-op-not.mk Sun Nov 15 14:58:14 2020 @@ -1,4 +1,4 @@ -# $NetBSD: cond-op-not.mk,v 1.5 2020/11/15 14:14:24 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, which negates its argument. @@ -18,7 +18,9 @@ . error .endif -# The '==' binds more tightly than '!'. +# 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 Index: src/usr.bin/make/unit-tests/cond-token-plain.mk diff -u src/usr.bin/make/unit-tests/cond-token-plain.mk:1.5 src/usr.bin/make/unit-tests/cond-token-plain.mk:1.6 --- src/usr.bin/make/unit-tests/cond-token-plain.mk:1.5 Mon Nov 9 00:07:06 2020 +++ src/usr.bin/make/unit-tests/cond-token-plain.mk Sun Nov 15 14:58:14 2020 @@ -1,4 +1,4 @@ -# $NetBSD: cond-token-plain.mk,v 1.5 2020/11/09 00:07:06 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 @@ -35,15 +35,15 @@ # 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 Index: src/usr.bin/make/unit-tests/cond-op-parentheses.exp diff -u src/usr.bin/make/unit-tests/cond-op-parentheses.exp:1.1 src/usr.bin/make/unit-tests/cond-op-parentheses.exp:1.2 --- src/usr.bin/make/unit-tests/cond-op-parentheses.exp:1.1 Sun Aug 16 12:07:51 2020 +++ src/usr.bin/make/unit-tests/cond-op-parentheses.exp Sun Nov 15 14:58:14 2020 @@ -1 +1,2 @@ +make: "cond-op-parentheses.mk" line 13: Parentheses can be nested at least to depth 112. exit status 0 Index: src/usr.bin/make/unit-tests/cond-op.exp diff -u src/usr.bin/make/unit-tests/cond-op.exp:1.6 src/usr.bin/make/unit-tests/cond-op.exp:1.7 --- src/usr.bin/make/unit-tests/cond-op.exp:1.6 Sun Nov 15 14:04:26 2020 +++ src/usr.bin/make/unit-tests/cond-op.exp Sun Nov 15 14:58:14 2020 @@ -1,16 +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 81: A B C => (A || B) && C A || B && C A || (B && C) -make: "cond-op.mk" line 88: 0 0 0 => 0 0 0 -make: "cond-op.mk" line 88: 0 0 1 => 0 0 0 -make: "cond-op.mk" line 88: 0 1 0 => 0 0 0 -make: "cond-op.mk" line 88: 0 1 1 => 1 1 1 -make: "cond-op.mk" line 88: 1 0 0 => 0 1 1 -make: "cond-op.mk" line 88: 1 0 1 => 1 1 1 -make: "cond-op.mk" line 88: 1 1 0 => 0 1 1 -make: "cond-op.mk" line 88: 1 1 1 => 1 1 1 +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 Index: src/usr.bin/make/unit-tests/cond-op.mk diff -u src/usr.bin/make/unit-tests/cond-op.mk:1.9 src/usr.bin/make/unit-tests/cond-op.mk:1.10 --- src/usr.bin/make/unit-tests/cond-op.mk:1.9 Sun Nov 15 14:04:26 2020 +++ src/usr.bin/make/unit-tests/cond-op.mk Sun Nov 15 14:58:14 2020 @@ -1,4 +1,4 @@ -# $NetBSD: cond-op.mk,v 1.9 2020/11/15 14:04:26 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,7 +76,7 @@ . 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. Index: src/usr.bin/make/unit-tests/cond-short.mk diff -u src/usr.bin/make/unit-tests/cond-short.mk:1.11 src/usr.bin/make/unit-tests/cond-short.mk:1.12 --- src/usr.bin/make/unit-tests/cond-short.mk:1.11 Sat Oct 24 08:50:17 2020 +++ src/usr.bin/make/unit-tests/cond-short.mk Sun Nov 15 14:58:14 2020 @@ -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 te # 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: @:;: Index: src/usr.bin/make/unit-tests/cond-token-number.exp diff -u src/usr.bin/make/unit-tests/cond-token-number.exp:1.3 src/usr.bin/make/unit-tests/cond-token-number.exp:1.4 --- src/usr.bin/make/unit-tests/cond-token-number.exp:1.3 Sun Nov 8 22:28:05 2020 +++ src/usr.bin/make/unit-tests/cond-token-number.exp Sun Nov 15 14:58:14 2020 @@ -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 70: 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 Index: src/usr.bin/make/unit-tests/cond-undef-lint.exp diff -u src/usr.bin/make/unit-tests/cond-undef-lint.exp:1.3 src/usr.bin/make/unit-tests/cond-undef-lint.exp:1.4 --- src/usr.bin/make/unit-tests/cond-undef-lint.exp:1.3 Mon Sep 14 07:13:29 2020 +++ src/usr.bin/make/unit-tests/cond-undef-lint.exp Sun Nov 15 14:58:14 2020 @@ -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 Index: src/usr.bin/make/unit-tests/cond-token-number.mk diff -u src/usr.bin/make/unit-tests/cond-token-number.mk:1.4 src/usr.bin/make/unit-tests/cond-token-number.mk:1.5 --- src/usr.bin/make/unit-tests/cond-token-number.mk:1.4 Sun Nov 8 22:28:05 2020 +++ src/usr.bin/make/unit-tests/cond-token-number.mk Sun Nov 15 14:58:14 2020 @@ -1,6 +1,8 @@ -# $NetBSD: cond-token-number.mk,v 1.4 2020/11/08 22:28:05 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. Index: src/usr.bin/make/unit-tests/cond-token-var.mk diff -u src/usr.bin/make/unit-tests/cond-token-var.mk:1.4 src/usr.bin/make/unit-tests/cond-token-var.mk:1.5 --- src/usr.bin/make/unit-tests/cond-token-var.mk:1.4 Sat Oct 24 08:46:08 2020 +++ src/usr.bin/make/unit-tests/cond-token-var.mk Sun Nov 15 14:58:14 2020 @@ -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