1 # $NetBSD: parse-var.mk,v 1.10 2024/06/02 15:31:26 rillig Exp $ 2 # 3 # Tests for parsing expressions. 4 # 5 # TODO: Add systematic tests for all of the below combinations. 6 # 7 # Written form: 8 # short form 9 # long form with braces endc == '}' 10 # long form with parentheses endc == ')' 11 # indirect modifiers endc == '\0' 12 # 13 # Based on: 14 # undefined variable 15 # global variable 16 # command-line variable 17 # environment variable 18 # target-local variable 19 # legacy variable '@F' 20 # 21 # VarEvalMode: 22 # parse 23 # parse-balanced 24 # eval 25 # eval-defined 26 # eval-keep-undefined 27 # eval-keep-dollar-and-undefined 28 # 29 # Global mode: 30 # without -dL 31 # with -dL 32 # 33 # Modifiers: 34 # no 35 # yes, stay undefined 36 # convert to defined 37 # indirect modifiers, involving changes to VarEvalMode 38 # 39 # Error conditions: 40 # for the short form, EOF after the '$' 41 # for the short form, each character 42 # for the long forms, EOF right after '${' 43 # for the long forms, EOF after the variable name 44 # for the long forms, EOF after the ':' 45 # for the long forms, EOF after parsing a modifier 46 # for the long forms, ':}' 47 # for each modifier: syntactic error 48 # for each modifier: evaluation error 49 # 50 # Context: 51 # in a condition, only operand, unquoted 52 # in a condition, only operand, quoted 53 # in a condition, left-hand side, unquoted 54 # in a condition, left-hand side, quoted 55 # in a condition, right-hand side, unquoted 56 # in a condition, right-hand side, quoted 57 # left-hand side of a variable assignment 58 # right-hand side of a ':=' variable assignment 59 # right-hand side of a '!=' variable assignment 60 # shell command in a target 61 # .info directive 62 # dependency line 63 # items in a .for loop 64 # everywhere else Var_Parse is called 65 # 66 # Further influences: 67 # multi-level evaluations like 'other=${OTHER}' with OTHER='$$ ${THIRD}' 68 # 69 # Effects: 70 # How much does the parsing position advance (pp)? 71 # What's the value of the expression (return value)? 72 # What error messages are printed (Parse_Error)? 73 # What no-effect error messages are printed (Error)? 74 # What error messages should be printed but aren't? 75 # What other side effects are there? 76 77 .MAKEFLAGS: -dL 78 79 # In variable assignments, there may be spaces in the middle of the left-hand 80 # side of the assignment, but only if they occur inside expressions. 81 # Leading spaces (but not tabs) are possible but unusual. 82 # Trailing spaces are common in some coding styles, others omit them. 83 VAR.${:U param }= value 84 .if ${VAR.${:U param }} != "value" 85 . error 86 .endif 87 88 # Since var.c 1.323 from 2020-07-26 18:11 and until var.c 1.1047 from 89 # 2023-02-18, the exact way of parsing an expression with subexpressions 90 # depended on whether the expression was actually evaluated or merely parsed. 91 # 92 # If it was evaluated, nested expressions were parsed correctly, parsing each 93 # modifier according to its exact definition (see varmod.mk). 94 # 95 # If the expression was merely parsed but not evaluated (for example, because 96 # its value would not influence the outcome of the condition, or during the 97 # first pass of the ':@var@body@' modifier), and the expression contained a 98 # modifier, and that modifier contained a nested expression, the nested 99 # expression was not parsed correctly. Instead, make only counted the opening 100 # and closing delimiters, which failed for nested modifiers with unbalanced 101 # braces. 102 103 #.MAKEFLAGS: -dcpv 104 # Keep these braces outside the conditions below, to keep them simple to 105 # understand. If the expression ${BRACE_PAIR:...} had been replaced with the 106 # literal ${:U{}}, the '}' would have to be escaped, but not the '{'. This 107 # asymmetry would have made the example even more complicated to understand. 108 BRACE_PAIR= {} 109 # In this test word, the below conditions will replace the '{{}' in the middle 110 # with the string '<lbraces>'. 111 BRACE_GROUP= {{{{}}}} 112 113 # The inner ':S' modifier turns the word '{}' into '{{}'. 114 # The outer ':S' modifier then replaces '{{}' with '<lbraces>'. 115 # Due to the always-true condition '1', the outer expression is relevant and 116 # is parsed correctly. 117 .if 1 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,} 118 .endif 119 # Due to the always-false condition '0', the outer expression is irrelevant. 120 # In this case, in the parts of the outer ':S' modifier, the expression parser 121 # only counted the braces, and since the inner expression '${BRACE_PAIR:...}' 122 # contains more '{' than '}', parsing failed with the error message 'Unfinished 123 # modifier for "BRACE_GROUP"'. Fixed in var.c 1.1047 from 2023-02-18. 124 .if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,} 125 .endif 126 #.MAKEFLAGS: -d0 127 128 129 all: .PHONY 130