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