xref: /freebsd/contrib/bmake/unit-tests/parse-var.mk (revision 8d5c8e21c690b35d0a9a604d6b886fba222cd2fe)
1*8d5c8e21SSimon J. Gerraty# $NetBSD: parse-var.mk,v 1.10 2024/06/02 15:31:26 rillig Exp $
24fde40d9SSimon J. Gerraty#
3d5e0a182SSimon J. Gerraty# Tests for parsing expressions.
44fde40d9SSimon J. Gerraty#
54fde40d9SSimon J. Gerraty# TODO: Add systematic tests for all of the below combinations.
64fde40d9SSimon J. Gerraty#
74fde40d9SSimon J. Gerraty# Written form:
84fde40d9SSimon J. Gerraty#	short form
94fde40d9SSimon J. Gerraty#	long form with braces		endc == '}'
104fde40d9SSimon J. Gerraty#	long form with parentheses	endc == ')'
114fde40d9SSimon J. Gerraty#	indirect modifiers		endc == '\0'
124fde40d9SSimon J. Gerraty#
134fde40d9SSimon J. Gerraty# Based on:
144fde40d9SSimon J. Gerraty#	undefined variable
154fde40d9SSimon J. Gerraty#	global variable
164fde40d9SSimon J. Gerraty#	command-line variable
174fde40d9SSimon J. Gerraty#	environment variable
184fde40d9SSimon J. Gerraty#	target-local variable
194fde40d9SSimon J. Gerraty#	legacy variable '@F'
204fde40d9SSimon J. Gerraty#
214fde40d9SSimon J. Gerraty# VarEvalMode:
224fde40d9SSimon J. Gerraty#	parse
23*8d5c8e21SSimon J. Gerraty#	parse-balanced
244fde40d9SSimon J. Gerraty#	eval
25*8d5c8e21SSimon J. Gerraty#	eval-defined
26*8d5c8e21SSimon J. Gerraty#	eval-keep-undefined
27*8d5c8e21SSimon J. Gerraty#	eval-keep-dollar-and-undefined
284fde40d9SSimon J. Gerraty#
294fde40d9SSimon J. Gerraty# Global mode:
304fde40d9SSimon J. Gerraty#	without -dL
314fde40d9SSimon J. Gerraty#	with -dL
324fde40d9SSimon J. Gerraty#
334fde40d9SSimon J. Gerraty# Modifiers:
344fde40d9SSimon J. Gerraty#	no
354fde40d9SSimon J. Gerraty#	yes, stay undefined
364fde40d9SSimon J. Gerraty#	convert to defined
374fde40d9SSimon J. Gerraty#	indirect modifiers, involving changes to VarEvalMode
384fde40d9SSimon J. Gerraty#
394fde40d9SSimon J. Gerraty# Error conditions:
404fde40d9SSimon J. Gerraty#	for the short form, EOF after the '$'
414fde40d9SSimon J. Gerraty#	for the short form, each character
424fde40d9SSimon J. Gerraty#	for the long forms, EOF right after '${'
434fde40d9SSimon J. Gerraty#	for the long forms, EOF after the variable name
444fde40d9SSimon J. Gerraty#	for the long forms, EOF after the ':'
454fde40d9SSimon J. Gerraty#	for the long forms, EOF after parsing a modifier
464fde40d9SSimon J. Gerraty#	for the long forms, ':}'
474fde40d9SSimon J. Gerraty#	for each modifier: syntactic error
484fde40d9SSimon J. Gerraty#	for each modifier: evaluation error
494fde40d9SSimon J. Gerraty#
504fde40d9SSimon J. Gerraty# Context:
514fde40d9SSimon J. Gerraty#	in a condition, only operand, unquoted
524fde40d9SSimon J. Gerraty#	in a condition, only operand, quoted
534fde40d9SSimon J. Gerraty#	in a condition, left-hand side, unquoted
544fde40d9SSimon J. Gerraty#	in a condition, left-hand side, quoted
554fde40d9SSimon J. Gerraty#	in a condition, right-hand side, unquoted
564fde40d9SSimon J. Gerraty#	in a condition, right-hand side, quoted
574fde40d9SSimon J. Gerraty#	left-hand side of a variable assignment
584fde40d9SSimon J. Gerraty#	right-hand side of a ':=' variable assignment
594fde40d9SSimon J. Gerraty#	right-hand side of a '!=' variable assignment
604fde40d9SSimon J. Gerraty#	shell command in a target
614fde40d9SSimon J. Gerraty#	.info directive
624fde40d9SSimon J. Gerraty#	dependency line
634fde40d9SSimon J. Gerraty#	items in a .for loop
644fde40d9SSimon J. Gerraty#	everywhere else Var_Parse is called
654fde40d9SSimon J. Gerraty#
664fde40d9SSimon J. Gerraty# Further influences:
674fde40d9SSimon J. Gerraty#	multi-level evaluations like 'other=${OTHER}' with OTHER='$$ ${THIRD}'
684fde40d9SSimon J. Gerraty#
694fde40d9SSimon J. Gerraty# Effects:
704fde40d9SSimon J. Gerraty#	How much does the parsing position advance (pp)?
718c973ee2SSimon J. Gerraty#	What's the value of the expression (return value)?
724fde40d9SSimon J. Gerraty#	What error messages are printed (Parse_Error)?
734fde40d9SSimon J. Gerraty#	What no-effect error messages are printed (Error)?
744fde40d9SSimon J. Gerraty#	What error messages should be printed but aren't?
754fde40d9SSimon J. Gerraty#	What other side effects are there?
76956e45f6SSimon J. Gerraty
77956e45f6SSimon J. Gerraty.MAKEFLAGS: -dL
78956e45f6SSimon J. Gerraty
794fde40d9SSimon J. Gerraty# In variable assignments, there may be spaces in the middle of the left-hand
80d5e0a182SSimon J. Gerraty# side of the assignment, but only if they occur inside expressions.
814fde40d9SSimon J. Gerraty# Leading spaces (but not tabs) are possible but unusual.
824fde40d9SSimon J. Gerraty# Trailing spaces are common in some coding styles, others omit them.
83956e45f6SSimon J. GerratyVAR.${:U param }=	value
84956e45f6SSimon J. Gerraty.if ${VAR.${:U param }} != "value"
85956e45f6SSimon J. Gerraty.  error
86956e45f6SSimon J. Gerraty.endif
87956e45f6SSimon J. Gerraty
888c973ee2SSimon J. Gerraty# Since var.c 1.323 from 2020-07-26 18:11 and until var.c 1.1047 from
898c973ee2SSimon J. Gerraty# 2023-02-18, the exact way of parsing an expression with subexpressions
908c973ee2SSimon J. Gerraty# depended on whether the expression was actually evaluated or merely parsed.
914fde40d9SSimon J. Gerraty#
924fde40d9SSimon J. Gerraty# If it was evaluated, nested expressions were parsed correctly, parsing each
934fde40d9SSimon J. Gerraty# modifier according to its exact definition (see varmod.mk).
944fde40d9SSimon J. Gerraty#
954fde40d9SSimon J. Gerraty# If the expression was merely parsed but not evaluated (for example, because
964fde40d9SSimon J. Gerraty# its value would not influence the outcome of the condition, or during the
974fde40d9SSimon J. Gerraty# first pass of the ':@var@body@' modifier), and the expression contained a
984fde40d9SSimon J. Gerraty# modifier, and that modifier contained a nested expression, the nested
994fde40d9SSimon J. Gerraty# expression was not parsed correctly.  Instead, make only counted the opening
1004fde40d9SSimon J. Gerraty# and closing delimiters, which failed for nested modifiers with unbalanced
1014fde40d9SSimon J. Gerraty# braces.
1024fde40d9SSimon J. Gerraty
1034fde40d9SSimon J. Gerraty#.MAKEFLAGS: -dcpv
1044fde40d9SSimon J. Gerraty# Keep these braces outside the conditions below, to keep them simple to
1058c973ee2SSimon J. Gerraty# understand.  If the expression ${BRACE_PAIR:...} had been replaced with the
1068c973ee2SSimon J. Gerraty# literal ${:U{}}, the '}' would have to be escaped, but not the '{'.  This
1078c973ee2SSimon J. Gerraty# asymmetry would have made the example even more complicated to understand.
1084fde40d9SSimon J. GerratyBRACE_PAIR=	{}
1098c973ee2SSimon J. Gerraty# In this test word, the below conditions will replace the '{{}' in the middle
1108c973ee2SSimon J. Gerraty# with the string '<lbraces>'.
1114fde40d9SSimon J. GerratyBRACE_GROUP=	{{{{}}}}
1124fde40d9SSimon J. Gerraty
1134fde40d9SSimon J. Gerraty# The inner ':S' modifier turns the word '{}' into '{{}'.
1144fde40d9SSimon J. Gerraty# The outer ':S' modifier then replaces '{{}' with '<lbraces>'.
1158c973ee2SSimon J. Gerraty# Due to the always-true condition '1', the outer expression is relevant and
1168c973ee2SSimon J. Gerraty# is parsed correctly.
1174fde40d9SSimon J. Gerraty.if 1 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
1184fde40d9SSimon J. Gerraty.endif
1198c973ee2SSimon J. Gerraty# Due to the always-false condition '0', the outer expression is irrelevant.
1208c973ee2SSimon J. Gerraty# In this case, in the parts of the outer ':S' modifier, the expression parser
1218c973ee2SSimon J. Gerraty# only counted the braces, and since the inner expression '${BRACE_PAIR:...}'
1228c973ee2SSimon J. Gerraty# contains more '{' than '}', parsing failed with the error message 'Unfinished
1238c973ee2SSimon J. Gerraty# modifier for "BRACE_GROUP"'.  Fixed in var.c 1.1047 from 2023-02-18.
1244fde40d9SSimon J. Gerraty.if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
1254fde40d9SSimon J. Gerraty.endif
1264fde40d9SSimon J. Gerraty#.MAKEFLAGS: -d0
1274fde40d9SSimon J. Gerraty
1284fde40d9SSimon J. Gerraty
1294fde40d9SSimon J. Gerratyall: .PHONY
130