xref: /src/contrib/bmake/unit-tests/parse-var.mk (revision 8d5c8e21c690b35d0a9a604d6b886fba222cd2fe)
1dbb5be7fSSimon J. Gerraty# $NetBSD: parse-var.mk,v 1.10 2024/06/02 15:31:26 rillig Exp $
22e36ab23SSimon J. Gerraty#
37a05a715SSimon J. Gerraty# Tests for parsing expressions.
42e36ab23SSimon J. Gerraty#
52e36ab23SSimon J. Gerraty# TODO: Add systematic tests for all of the below combinations.
62e36ab23SSimon J. Gerraty#
72e36ab23SSimon J. Gerraty# Written form:
82e36ab23SSimon J. Gerraty#	short form
92e36ab23SSimon J. Gerraty#	long form with braces		endc == '}'
102e36ab23SSimon J. Gerraty#	long form with parentheses	endc == ')'
112e36ab23SSimon J. Gerraty#	indirect modifiers		endc == '\0'
122e36ab23SSimon J. Gerraty#
132e36ab23SSimon J. Gerraty# Based on:
142e36ab23SSimon J. Gerraty#	undefined variable
152e36ab23SSimon J. Gerraty#	global variable
162e36ab23SSimon J. Gerraty#	command-line variable
172e36ab23SSimon J. Gerraty#	environment variable
182e36ab23SSimon J. Gerraty#	target-local variable
192e36ab23SSimon J. Gerraty#	legacy variable '@F'
202e36ab23SSimon J. Gerraty#
212e36ab23SSimon J. Gerraty# VarEvalMode:
222e36ab23SSimon J. Gerraty#	parse
23dbb5be7fSSimon J. Gerraty#	parse-balanced
242e36ab23SSimon J. Gerraty#	eval
25dbb5be7fSSimon J. Gerraty#	eval-defined
26dbb5be7fSSimon J. Gerraty#	eval-keep-undefined
27dbb5be7fSSimon J. Gerraty#	eval-keep-dollar-and-undefined
282e36ab23SSimon J. Gerraty#
292e36ab23SSimon J. Gerraty# Global mode:
302e36ab23SSimon J. Gerraty#	without -dL
312e36ab23SSimon J. Gerraty#	with -dL
322e36ab23SSimon J. Gerraty#
332e36ab23SSimon J. Gerraty# Modifiers:
342e36ab23SSimon J. Gerraty#	no
352e36ab23SSimon J. Gerraty#	yes, stay undefined
362e36ab23SSimon J. Gerraty#	convert to defined
372e36ab23SSimon J. Gerraty#	indirect modifiers, involving changes to VarEvalMode
382e36ab23SSimon J. Gerraty#
392e36ab23SSimon J. Gerraty# Error conditions:
402e36ab23SSimon J. Gerraty#	for the short form, EOF after the '$'
412e36ab23SSimon J. Gerraty#	for the short form, each character
422e36ab23SSimon J. Gerraty#	for the long forms, EOF right after '${'
432e36ab23SSimon J. Gerraty#	for the long forms, EOF after the variable name
442e36ab23SSimon J. Gerraty#	for the long forms, EOF after the ':'
452e36ab23SSimon J. Gerraty#	for the long forms, EOF after parsing a modifier
462e36ab23SSimon J. Gerraty#	for the long forms, ':}'
472e36ab23SSimon J. Gerraty#	for each modifier: syntactic error
482e36ab23SSimon J. Gerraty#	for each modifier: evaluation error
492e36ab23SSimon J. Gerraty#
502e36ab23SSimon J. Gerraty# Context:
512e36ab23SSimon J. Gerraty#	in a condition, only operand, unquoted
522e36ab23SSimon J. Gerraty#	in a condition, only operand, quoted
532e36ab23SSimon J. Gerraty#	in a condition, left-hand side, unquoted
542e36ab23SSimon J. Gerraty#	in a condition, left-hand side, quoted
552e36ab23SSimon J. Gerraty#	in a condition, right-hand side, unquoted
562e36ab23SSimon J. Gerraty#	in a condition, right-hand side, quoted
572e36ab23SSimon J. Gerraty#	left-hand side of a variable assignment
582e36ab23SSimon J. Gerraty#	right-hand side of a ':=' variable assignment
592e36ab23SSimon J. Gerraty#	right-hand side of a '!=' variable assignment
602e36ab23SSimon J. Gerraty#	shell command in a target
612e36ab23SSimon J. Gerraty#	.info directive
622e36ab23SSimon J. Gerraty#	dependency line
632e36ab23SSimon J. Gerraty#	items in a .for loop
642e36ab23SSimon J. Gerraty#	everywhere else Var_Parse is called
652e36ab23SSimon J. Gerraty#
662e36ab23SSimon J. Gerraty# Further influences:
672e36ab23SSimon J. Gerraty#	multi-level evaluations like 'other=${OTHER}' with OTHER='$$ ${THIRD}'
682e36ab23SSimon J. Gerraty#
692e36ab23SSimon J. Gerraty# Effects:
702e36ab23SSimon J. Gerraty#	How much does the parsing position advance (pp)?
7151d8a8b4SSimon J. Gerraty#	What's the value of the expression (return value)?
722e36ab23SSimon J. Gerraty#	What error messages are printed (Parse_Error)?
732e36ab23SSimon J. Gerraty#	What no-effect error messages are printed (Error)?
742e36ab23SSimon J. Gerraty#	What error messages should be printed but aren't?
752e36ab23SSimon J. Gerraty#	What other side effects are there?
76302da1a3SSimon J. Gerraty
77302da1a3SSimon J. Gerraty.MAKEFLAGS: -dL
78302da1a3SSimon J. Gerraty
792e36ab23SSimon J. Gerraty# In variable assignments, there may be spaces in the middle of the left-hand
807a05a715SSimon J. Gerraty# side of the assignment, but only if they occur inside expressions.
812e36ab23SSimon J. Gerraty# Leading spaces (but not tabs) are possible but unusual.
822e36ab23SSimon J. Gerraty# Trailing spaces are common in some coding styles, others omit them.
83302da1a3SSimon J. GerratyVAR.${:U param }=	value
84302da1a3SSimon J. Gerraty.if ${VAR.${:U param }} != "value"
85302da1a3SSimon J. Gerraty.  error
86302da1a3SSimon J. Gerraty.endif
87302da1a3SSimon J. Gerraty
8851d8a8b4SSimon J. Gerraty# Since var.c 1.323 from 2020-07-26 18:11 and until var.c 1.1047 from
8951d8a8b4SSimon J. Gerraty# 2023-02-18, the exact way of parsing an expression with subexpressions
9051d8a8b4SSimon J. Gerraty# depended on whether the expression was actually evaluated or merely parsed.
912e36ab23SSimon J. Gerraty#
922e36ab23SSimon J. Gerraty# If it was evaluated, nested expressions were parsed correctly, parsing each
932e36ab23SSimon J. Gerraty# modifier according to its exact definition (see varmod.mk).
942e36ab23SSimon J. Gerraty#
952e36ab23SSimon J. Gerraty# If the expression was merely parsed but not evaluated (for example, because
962e36ab23SSimon J. Gerraty# its value would not influence the outcome of the condition, or during the
972e36ab23SSimon J. Gerraty# first pass of the ':@var@body@' modifier), and the expression contained a
982e36ab23SSimon J. Gerraty# modifier, and that modifier contained a nested expression, the nested
992e36ab23SSimon J. Gerraty# expression was not parsed correctly.  Instead, make only counted the opening
1002e36ab23SSimon J. Gerraty# and closing delimiters, which failed for nested modifiers with unbalanced
1012e36ab23SSimon J. Gerraty# braces.
1022e36ab23SSimon J. Gerraty
1032e36ab23SSimon J. Gerraty#.MAKEFLAGS: -dcpv
1042e36ab23SSimon J. Gerraty# Keep these braces outside the conditions below, to keep them simple to
10551d8a8b4SSimon J. Gerraty# understand.  If the expression ${BRACE_PAIR:...} had been replaced with the
10651d8a8b4SSimon J. Gerraty# literal ${:U{}}, the '}' would have to be escaped, but not the '{'.  This
10751d8a8b4SSimon J. Gerraty# asymmetry would have made the example even more complicated to understand.
1082e36ab23SSimon J. GerratyBRACE_PAIR=	{}
10951d8a8b4SSimon J. Gerraty# In this test word, the below conditions will replace the '{{}' in the middle
11051d8a8b4SSimon J. Gerraty# with the string '<lbraces>'.
1112e36ab23SSimon J. GerratyBRACE_GROUP=	{{{{}}}}
1122e36ab23SSimon J. Gerraty
1132e36ab23SSimon J. Gerraty# The inner ':S' modifier turns the word '{}' into '{{}'.
1142e36ab23SSimon J. Gerraty# The outer ':S' modifier then replaces '{{}' with '<lbraces>'.
11551d8a8b4SSimon J. Gerraty# Due to the always-true condition '1', the outer expression is relevant and
11651d8a8b4SSimon J. Gerraty# is parsed correctly.
1172e36ab23SSimon J. Gerraty.if 1 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
1182e36ab23SSimon J. Gerraty.endif
11951d8a8b4SSimon J. Gerraty# Due to the always-false condition '0', the outer expression is irrelevant.
12051d8a8b4SSimon J. Gerraty# In this case, in the parts of the outer ':S' modifier, the expression parser
12151d8a8b4SSimon J. Gerraty# only counted the braces, and since the inner expression '${BRACE_PAIR:...}'
12251d8a8b4SSimon J. Gerraty# contains more '{' than '}', parsing failed with the error message 'Unfinished
12351d8a8b4SSimon J. Gerraty# modifier for "BRACE_GROUP"'.  Fixed in var.c 1.1047 from 2023-02-18.
1242e36ab23SSimon J. Gerraty.if 0 && ${BRACE_GROUP:S,${BRACE_PAIR:S,{,{{,},<lbraces>,}
1252e36ab23SSimon J. Gerraty.endif
1262e36ab23SSimon J. Gerraty#.MAKEFLAGS: -d0
1272e36ab23SSimon J. Gerraty
1282e36ab23SSimon J. Gerraty
1292e36ab23SSimon J. Gerratyall: .PHONY
130