]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - unit-tests/cond-op.mk
Import bmake-20220330
[FreeBSD/FreeBSD.git] / unit-tests / cond-op.mk
1 # $NetBSD: cond-op.mk,v 1.15 2021/12/10 23:12:44 rillig Exp $
2 #
3 # Tests for operators like &&, ||, ! in .if conditions.
4 #
5 # See also:
6 #       cond-op-and.mk
7 #       cond-op-not.mk
8 #       cond-op-or.mk
9 #       cond-op-parentheses.mk
10
11 # In make, && binds more tightly than ||, like in C.
12 # If make had the same precedence for both && and ||, like in the shell,
13 # the result would be different.
14 # If || were to bind more tightly than &&, the result would be different
15 # as well.
16 .if !(1 || 1 && 0)
17 .  error
18 .endif
19
20 # If make were to interpret the && and || operators like the shell, the
21 # previous condition would be interpreted as:
22 .if (1 || 1) && 0
23 .  error
24 .endif
25
26 # The precedence of the ! operator is different from C though. It has a
27 # lower precedence than the comparison operators.  Negating a condition
28 # does not need parentheses.
29 #
30 # This kind of condition looks so unfamiliar that it doesn't occur in
31 # practice.
32 .if !"word" == "word"
33 .  error
34 .endif
35
36 # This is how the above condition is actually interpreted.
37 .if !("word" == "word")
38 .  error
39 .endif
40
41 # TODO: Demonstrate that the precedence of the ! and == operators actually
42 # makes a difference.  There is a simple example for sure, I just cannot
43 # wrap my head around it right now.  See the truth table generator below
44 # for an example that doesn't require much thought.
45
46 # This condition is malformed because the '!' on the right-hand side must not
47 # appear unquoted.  If any, it must be enclosed in quotes.
48 # In any case, it is not interpreted as a negation of an unquoted string.
49 # See CondParser_String.
50 .if "!word" == !word
51 .  error
52 .endif
53
54 # Surprisingly, the ampersand and pipe are allowed in bare strings.
55 # That's another opportunity for writing confusing code.
56 # See CondParser_String, which only has '!' in the list of stop characters.
57 .if "a&&b||c" != a&&b||c
58 .  error
59 .endif
60
61 # In the following malformed conditions, as soon as the parser sees the '$'
62 # after the '0' or the '1', it knows that the condition will be malformed.
63 # Therefore there is no point in evaluating the misplaced expression.
64 #
65 # Before cond.c 1.286 from 2021-12-10, the extra expression was evaluated
66 # nevertheless, since CondParser_Or and CondParser_And asked for the expanded
67 # next token, even though in this position of the condition, only comparison
68 # operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed.
69 #
70 #
71 #
72 #
73 #
74 #
75 .undef ERR
76 .if 0 ${ERR::=evaluated}
77 .  error
78 .endif
79 .if ${ERR:Uundefined} == undefined
80 .  info A misplaced expression after 0 is not evaluated.
81 .endif
82
83 .undef ERR
84 .if 1 ${ERR::=evaluated}
85 .  error
86 .endif
87 .if ${ERR:Uundefined} == undefined
88 .  info A misplaced expression after 1 is not evaluated.
89 .endif
90
91 # Just in case that parsing should ever stop on the first error.
92 .info Parsing continues until here.
93
94 # Demonstration that '&&' has higher precedence than '||'.
95 .info A B C   =>   (A || B) && C   A || B && C   A || (B && C)
96 .for a in 0 1
97 .  for b in 0 1
98 .    for c in 0 1
99 .      for r1 in ${ ($a || $b) && $c :?1:0}
100 .        for r2 in ${ $a || $b && $c :?1:0}
101 .          for r3 in ${ $a || ($b && $c) :?1:0}
102 .            info $a $b $c   =>   ${r1}               ${r2}             ${r3}
103 .          endfor
104 .        endfor
105 .      endfor
106 .    endfor
107 .  endfor
108 .endfor
109
110 # This condition is obviously malformed.  It is properly detected and also
111 # was properly detected before 2021-01-19, but only because the left hand
112 # side of the '&&' evaluated to true.
113 .if 1 &&
114 .  error
115 .else
116 .  error
117 .endif
118
119 # This obviously malformed condition was not detected as such before cond.c
120 # 1.238 from 2021-01-19.
121 .if 0 &&
122 .  error
123 .else
124 .  error
125 .endif
126
127 # This obviously malformed condition was not detected as such before cond.c
128 # 1.238 from 2021-01-19.
129 .if 1 ||
130 .  error
131 .else
132 .  error
133 .endif
134
135 # This condition is obviously malformed.  It is properly detected and also
136 # was properly detected before 2021-01-19, but only because the left hand
137 # side of the '||' evaluated to false.
138 .if 0 ||
139 .  error
140 .else
141 .  error
142 .endif
143
144 all:
145         @:;