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