Home | History | Annotate | Line # | Download | only in unit-tests
      1 # $NetBSD: cond-op.mk,v 1.18 2025/06/28 22:39:28 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 # expect+1: Malformed conditional ""!word" == !word"
     51 .if "!word" == !word
     52 .  error
     53 .endif
     54 
     55 # Surprisingly, the ampersand and pipe are allowed in bare strings.
     56 # That's another opportunity for writing confusing code.
     57 # See CondParser_String, which only has '!' in the list of stop characters.
     58 .if "a&&b||c" != a&&b||c
     59 .  error
     60 .endif
     61 
     62 # In the following malformed conditions, as soon as the parser sees the '$'
     63 # after the '0' or the '1', it knows that the condition will be malformed.
     64 # Therefore there is no point in evaluating the misplaced expression.
     65 #
     66 # Before cond.c 1.286 from 2021-12-10, the extra expression was evaluated
     67 # nevertheless, since CondParser_Or and CondParser_And asked for the expanded
     68 # next token, even though in this position of the condition, only comparison
     69 # operators, TOK_AND, TOK_OR or TOK_RPAREN are allowed.
     70 .undef ERR
     71 # expect+1: Malformed conditional "0 ${ERR::=evaluated}"
     72 .if 0 ${ERR::=evaluated}
     73 .  error
     74 .endif
     75 .if ${ERR:Uundefined} == undefined
     76 # expect+1: A misplaced expression after 0 is not evaluated.
     77 .  info A misplaced expression after 0 is not evaluated.
     78 .endif
     79 
     80 .undef ERR
     81 # expect+1: Malformed conditional "1 ${ERR::=evaluated}"
     82 .if 1 ${ERR::=evaluated}
     83 .  error
     84 .endif
     85 .if ${ERR:Uundefined} == undefined
     86 # expect+1: A misplaced expression after 1 is not evaluated.
     87 .  info A misplaced expression after 1 is not evaluated.
     88 .endif
     89 
     90 
     91 # Demonstration that '&&' has higher precedence than '||'.
     92 # expect+1: A B C   =>   (A || B) && C   A || B && C   A || (B && C)
     93 .info A B C   =>   (A || B) && C   A || B && C   A || (B && C)
     94 .for a in 0 1
     95 .  for b in 0 1
     96 .    for c in 0 1
     97 .      for r1 in ${ ($a || $b) && $c :?1:0}
     98 .        for r2 in ${ $a || $b && $c :?1:0}
     99 .          for r3 in ${ $a || ($b && $c) :?1:0}
    100 # expect+8: 0 0 0   =>   0               0             0
    101 # expect+7: 0 0 1   =>   0               0             0
    102 # expect+6: 0 1 0   =>   0               0             0
    103 # expect+5: 0 1 1   =>   1               1             1
    104 # expect+4: 1 0 0   =>   0               1             1
    105 # expect+3: 1 0 1   =>   1               1             1
    106 # expect+2: 1 1 0   =>   0               1             1
    107 # expect+1: 1 1 1   =>   1               1             1
    108 .            info $a $b $c   =>   ${r1}               ${r2}             ${r3}
    109 .          endfor
    110 .        endfor
    111 .      endfor
    112 .    endfor
    113 .  endfor
    114 .endfor
    115 
    116 # This condition is obviously malformed.  It is properly detected and also
    117 # was properly detected before 2021-01-19, but only because the left hand
    118 # side of the '&&' evaluated to true.
    119 # expect+1: Malformed conditional "1 &&"
    120 .if 1 &&
    121 .  error
    122 .else
    123 .  error
    124 .endif
    125 
    126 # This obviously malformed condition was not detected as such before cond.c
    127 # 1.238 from 2021-01-19.
    128 # expect+1: Malformed conditional "0 &&"
    129 .if 0 &&
    130 .  error
    131 .else
    132 .  error
    133 .endif
    134 
    135 # This obviously malformed condition was not detected as such before cond.c
    136 # 1.238 from 2021-01-19.
    137 # expect+1: Malformed conditional "1 ||"
    138 .if 1 ||
    139 .  error
    140 .else
    141 .  error
    142 .endif
    143 
    144 # This condition is obviously malformed.  It is properly detected and also
    145 # was properly detected before 2021-01-19, but only because the left hand
    146 # side of the '||' evaluated to false.
    147 # expect+1: Malformed conditional "0 ||"
    148 .if 0 ||
    149 .  error
    150 .else
    151 .  error
    152 .endif
    153 
    154 all:
    155 	@:;
    156