parse-var.mk revision 1.10 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