1# $NetBSD: cond-op.mk,v 1.8 2020/10/24 08:46:08 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 ||, the result would be 13# 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# implicit binding would be this: 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. 28.if !"word" == "word" 29. error 30.endif 31 32# This is how the above condition is actually interpreted. 33.if !("word" == "word") 34. error 35.endif 36 37# TODO: Demonstrate that the precedence of the ! and == operators actually 38# makes a difference. There is a simple example for sure, I just cannot 39# wrap my head around it. 40 41# This condition is malformed because the '!' on the right-hand side must not 42# appear unquoted. If any, it must be enclosed in quotes. 43# In any case, it is not interpreted as a negation of an unquoted string. 44# See CondParser_String. 45.if "!word" == !word 46. error 47.endif 48 49# Surprisingly, the ampersand and pipe are allowed in bare strings. 50# That's another opportunity for writing confusing code. 51# See CondParser_String, which only has '!' in the list of stop characters. 52.if "a&&b||c" != a&&b||c 53. error 54.endif 55 56# As soon as the parser sees the '$', it knows that the condition will 57# be malformed. Therefore there is no point in evaluating it. 58# 59# As of 2020-09-11, that part of the condition is evaluated nevertheless, 60# since CondParser_Expr just requests the next token, without restricting 61# the token to the expected tokens. If the parser were to restrict the 62# valid follow tokens for the token "0" to those that can actually produce 63# a correct condition (which in this case would be comparison operators, 64# TOK_AND, TOK_OR or TOK_RPAREN), the variable expression would not have 65# to be evaluated. 66# 67# This would add a good deal of complexity to the code though, for almost 68# no benefit, especially since most expressions and conditions are side 69# effect free. 70.if 0 ${ERR::=evaluated} 71. error 72.endif 73.if ${ERR:Uundefined} == evaluated 74. warning After detecting a parse error, the rest is evaluated. 75.endif 76 77# Just in case that parsing should ever stop on the first error. 78.info Parsing continues until here. 79 80all: 81 @:; 82