Home | History | Annotate | Line # | Download | only in unit-tests
      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