1# $NetBSD: parse-var.mk,v 1.6 2022/09/25 21:26:23 rillig Exp $
2#
3# Tests for parsing variable 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#	eval
24#	eval-undeferr
25#	eval-keep-dollar
26#	eval-keep-undef
27#	eval-keep-dollar-undef
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 (out_val)?
72#	What's the status after parsing the expression (VarParseResult)?
73#	What error messages are printed (Parse_Error)?
74#	What no-effect error messages are printed (Error)?
75#	What error messages should be printed but aren't?
76#	What other side effects are there?
77
78.MAKEFLAGS: -dL
79
80# In variable assignments, there may be spaces in the middle of the left-hand
81# side of the assignment, but only if they occur inside variable expressions.
82# Leading spaces (but not tabs) are possible but unusual.
83# Trailing spaces are common in some coding styles, others omit them.
84VAR.${:U param }=	value
85.if ${VAR.${:U param }} != "value"
86.  error
87.endif
88
89# XXX: The following paragraph already uses past tense, in the hope that the
90# parsing behavior can be cleaned up soon.
91
92# Since var.c 1.323 from 2020-07-26 18:11 and except for var.c 1.1028 from
93# 2022-08-08, the exact way of parsing an expression depended on whether the
94# expression was actually evaluated or merely parsed.
95#
96# If it was evaluated, nested expressions were parsed correctly, parsing each
97# modifier according to its exact definition (see varmod.mk).
98#
99# If the expression was merely parsed but not evaluated (for example, because
100# its value would not influence the outcome of the condition, or during the
101# first pass of the ':@var@body@' modifier), and the expression contained a
102# modifier, and that modifier contained a nested expression, the nested
103# expression was not parsed correctly.  Instead, make only counted the opening
104# and closing delimiters, which failed for nested modifiers with unbalanced
105# braces.
106#
107# This naive brace counting was implemented in ParseModifierPartDollar.  As of
108# var.c 1.1029, there are still several other places that merely count braces
109# instead of properly parsing subexpressions.
110
111#.MAKEFLAGS: -dcpv
112# Keep these braces outside the conditions below, to keep them simple to
113# understand.  If the BRACE_PAIR had been replaced with ':U{}', the '}' would
114# have to be escaped, but not the '{'.  This asymmetry would have made the
115# example even more complicated to understand.
116BRACE_PAIR=	{}
117# In this test word, the '{{}' in the middle will be replaced.
118BRACE_GROUP=	{{{{}}}}
119
120# The inner ':S' modifier turns the word '{}' into '{{}'.
121# The outer ':S' modifier then replaces '{{}' with '<lbraces>'.
122# In the first case, the outer expression is relevant and is parsed correctly.
123.if 1 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
124.endif
125# In the second case, the outer expression was irrelevant.  In this case, in
126# the parts of the outer ':S' modifier, make only counted the braces, and since
127# the inner expression '${BRACE_PAIR:...}' contains more '{' than '}', parsing
128# failed with the error message 'Unfinished modifier for "BRACE_GROUP"'.  Fixed
129# in var.c 1.1028 from 2022-08-08, reverted in var.c 1.1029 from 2022-08-23.
130.if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
131.endif
132#.MAKEFLAGS: -d0
133
134
135all: .PHONY
136