1 # $NetBSD: varparse-errors.mk,v 1.26 2025/06/28 22:39:29 rillig Exp $ 2 3 # Tests for parsing and evaluating all kinds of expressions. 4 # 5 # This is the basis for redesigning the error handling in Var_Parse and 6 # Var_Subst, collecting typical and not so typical use cases. 7 # 8 # See also: 9 # Var_Parse 10 # Var_Subst 11 12 PLAIN= plain value 13 14 LITERAL_DOLLAR= To get a dollar, double $$ it. 15 16 INDIRECT= An ${:Uindirect} value. 17 18 REF_UNDEF= A reference to an ${UNDEF}undefined variable. 19 20 ERR_UNCLOSED= An ${UNCLOSED expression. 21 22 ERR_BAD_MOD= An ${:Uindirect:Z} expression with an unknown modifier. 23 24 ERR_EVAL= An evaluation error ${:Uvalue:C,.,\3,}. 25 26 # In a conditional, an expression that is not enclosed in quotes is 27 # expanded using the mode VARE_EVAL_DEFINED. 28 # The variable itself must be defined. 29 # It may refer to undefined variables though. 30 .if ${REF_UNDEF} != "A reference to an undefined variable." 31 . error 32 .endif 33 34 # As of 2020-12-01, errors in the variable name are silently ignored. 35 # Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result 36 # in an error message and a non-zero exit status. 37 # expect+1: Unknown modifier ":Z" 38 VAR.${:U:Z}= unknown modifier in the variable name 39 .if ${VAR.} != "unknown modifier in the variable name" 40 . error 41 .endif 42 43 # As of 2020-12-01, errors in the variable name are silently ignored. 44 # Since var.c 1.754 from 2020-12-20, unknown modifiers at parse time result 45 # in an error message and a non-zero exit status. 46 # expect+1: Unknown modifier ":Z" 47 VAR.${:U:Z}post= unknown modifier with text in the variable name 48 .if ${VAR.post} != "unknown modifier with text in the variable name" 49 . error 50 .endif 51 52 # Demonstrate an edge case in which the 'static' for 'errorReported' in 53 # Var_Subst actually makes a difference, preventing "a plethora of messages". 54 # Given that this is an edge case and the error message is wrong and thus 55 # misleading anyway, that piece of code is probably not necessary. The wrong 56 # condition was added in var.c 1.185 from 2014-05-19. 57 # 58 # To trigger this difference, the variable assignment must use the assignment 59 # operator ':=' to make VarEvalMode_ShouldKeepUndef return true. There must 60 # be 2 expressions that create a parse error, which in this case is ':OX'. 61 # These expressions must be nested in some way. The below expressions are 62 # minimal, that is, removing any part of it destroys the effect. 63 # 64 # Without the 'static', there would be one more message like this: 65 # Undefined variable "${:U:OX" 66 # 67 #.MAKEFLAGS: -dv 68 IND= ${:OX} 69 # expect+4: Unknown modifier ":OX" 70 # expect+3: Unknown modifier ":OX" 71 # expect+2: Unknown modifier ":OX" 72 # expect+1: Unknown modifier ":OX" 73 _:= ${:U:OX:U${IND}} ${:U:OX:U${IND}} 74 #.MAKEFLAGS: -d0 75 76 77 # Before var.c 1.032 from 2022-08-24, make complained about 'Unknown modifier' 78 # or 'Bad modifier' when in fact the modifier was entirely correct, it was 79 # just not delimited by either ':' or '}' but instead by '\0'. 80 # expect+1: Unclosed expression, expecting "}" for modifier "Q" 81 UNCLOSED:= ${:U:Q 82 # expect+1: Unclosed expression, expecting "}" for modifier "sh" 83 UNCLOSED:= ${:U:sh 84 # expect+1: Unclosed expression, expecting "}" for modifier "tA" 85 UNCLOSED:= ${:U:tA 86 # expect+1: Unclosed expression, expecting "}" for modifier "tsX" 87 UNCLOSED:= ${:U:tsX 88 # expect+1: Unclosed expression, expecting "}" for modifier "ts" 89 UNCLOSED:= ${:U:ts 90 # expect+1: Unclosed expression, expecting "}" for modifier "ts\040" 91 UNCLOSED:= ${:U:ts\040 92 # expect+1: Unclosed expression, expecting "}" for modifier "u" 93 UNCLOSED:= ${:U:u 94 # expect+1: Unclosed expression, expecting "}" for modifier "H" 95 UNCLOSED:= ${:U:H 96 # expect+1: Unclosed expression, expecting "}" for modifier "[1]" 97 UNCLOSED:= ${:U:[1] 98 # expect+1: Unclosed expression, expecting "}" for modifier "hash" 99 UNCLOSED:= ${:U:hash 100 # expect+1: Unclosed expression, expecting "}" for modifier "range" 101 UNCLOSED:= ${:U:range 102 # expect+1: Unclosed expression, expecting "}" for modifier "_" 103 UNCLOSED:= ${:U:_ 104 # expect+1: Unclosed expression, expecting "}" for modifier "gmtime" 105 UNCLOSED:= ${:U:gmtime 106 # expect+1: Unclosed expression, expecting "}" for modifier "localtime" 107 UNCLOSED:= ${:U:localtime 108 109 110 # In a stack trace that has both evaluation details and included files, list 111 # the current file twice: Once in the first line and once in the call 112 # hierarchy. While this is redundant, omitting the current file from the 113 # call hierarchy is more confusing, as the '.include' line does not contain 114 # the faulty expression. 115 # 116 # expect: make: varparse-errors.tmp:1: Unknown modifier ":Z" 117 # expect: while evaluating "${:Z}" with value "" 118 # expect: while evaluating variable "INDIRECT" with value "${:Z}" 119 # expect: while evaluating variable "VALUE" with value "${INDIRECT}" 120 # expect: in varparse-errors.tmp:1 121 # expect: in varparse-errors.mk:126 122 _!= echo '.info $${VALUE}' > varparse-errors.tmp 123 VALUE= ${INDIRECT} 124 INDIRECT= ${:Z} 125 # The "${.OBJDIR}/" is necessary to bypass the directory cache. 126 .include "${.OBJDIR}/varparse-errors.tmp" 127 _!= rm -f varparse-errors.tmp 128