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