Module Name: src Committed By: rillig Date: Sat Feb 25 10:41:15 UTC 2023
Modified Files: src/usr.bin/make/unit-tests: varname-dot-makeflags.mk Log Message: tests/make: fix explanation for '$' in MAKEFLAGS My previous interpretation was completely wrong. To generate a diff of this commit: cvs rdiff -u -r1.3 -r1.4 src/usr.bin/make/unit-tests/varname-dot-makeflags.mk Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/make/unit-tests/varname-dot-makeflags.mk diff -u src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.3 src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.4 --- src/usr.bin/make/unit-tests/varname-dot-makeflags.mk:1.3 Sat Feb 25 09:02:45 2023 +++ src/usr.bin/make/unit-tests/varname-dot-makeflags.mk Sat Feb 25 10:41:14 2023 @@ -1,4 +1,4 @@ -# $NetBSD: varname-dot-makeflags.mk,v 1.3 2023/02/25 09:02:45 rillig Exp $ +# $NetBSD: varname-dot-makeflags.mk,v 1.4 2023/02/25 10:41:14 rillig Exp $ # # Tests for the special .MAKEFLAGS variable, which collects almost all # command line arguments and passes them on to any child processes via @@ -31,52 +31,65 @@ spaces_stage_1: # make processes via MAKEFLAGS. dollars_stage_0: @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' - # The '$$$$' gets parsed as a literal '$$', making the actual variable - # value '$${varname}'. - # - # When Main_ExportMAKEFLAGS adds the variable DOLLARS to MAKEFLAGS, it - # first evaluates the variable value, resulting in '${varname}'. - # - # This value is then escaped as '\$\{varname\}', to ensure that the - # variable is later interpreted as a single shell word. + + # The '$$$$' becomes a literal '$$' when building the '${MAKE}' + # command line, making the actual argument 'DOLLARS=$${varname}'. + # At this stage, MAKEFLAGS is not yet involved. @${MAKE} -f ${MAKEFILE} dollars_stage_1 DOLLARS='$$$${varname}' -# The environment variable 'MAKEFLAGS' now contains the variable assignment -# 'DOLLARS=\$\{varname\}', including the backslashes. -# -# expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}> -# -# When Main_ParseArgLine calls Str_Words to parse the flags from MAKEFLAGS, it -# removes the backslashes, resulting in the plain variable assignment -# 'DOLLARS=${varname}'. +.if make(dollars_stage_1) +# At this point, the variable 'DOLLARS' contains '$${varname}', which +# evaluates to a literal '$' followed by '{varname}'. +. if ${DOLLARS} != "\${varname}" +. error +. endif +.endif dollars_stage_1: + # At this point, the stage 1 make provides the environment variable + # 'MAKEFLAGS' to its child processes, even if the child process is not + # another make. + # + # expect: dollars_stage_1: env MAKEFLAGS=< -r -k DOLLARS=\$\{varname\}> + # + # The 'DOLLARS=\$\{varname\}' assignment is escaped so that the stage + # 2 make will see it as a single word. @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>" - # At this point, evaluating the environment variable 'MAKEFLAGS' has - # strange side effects, as the string '\$\{varname\}' is interpreted + # At this point, evaluating the environment variable 'MAKEFLAGS' leads + # to strange side effects as the string '\$\{varname\}' is interpreted # as: # - # \ a single backslash + # \ a literal string of a single backslash # $\ the value of the variable named '\' # {varname\} a literal string # # Since the variable name '\' is not defined, the resulting value is - # '\{varname\}'. + # '\{varname\}'. Make doesn't handle isolated '$' characters in + # strings well, instead each '$' has to be part of a '$$' or be part + # of a subexpression like '${VAR}'. @echo '$@: MAKEFLAGS=<'${MAKEFLAGS:Q}'>' - # The modifier ':q' escapes a '$' in the variable value to '$$', but - # it's too late, as that modifier applies after the expression has - # been evaluated. + # The modifier ':q' preserves a '$$' in an expression value instead of + # expanding it to a single '$', but it's already too late, as that + # modifier applies after the expression has been evaluated. Except + # for debug logging, there is no way to process strings that contain + # isolated '$'. @echo '$@: MAKEFLAGS:q=<'${MAKEFLAGS:q}'>' - # The value of the variable DOLLARS is now '${varname}'. Since there - # is no variable named 'varname', this expression evaluates to ''. @${MAKE} -f ${MAKEFILE} dollars_stage_2 -# Uncomment these lines to see the above variable expansions in action. -#${:U\\}=backslash -#varname=varvalue - +.if make(dollars_stage_2) +# At this point, the variable 'DOLLARS' contains '${varname}', and since +# 'varname' is undefined, that expression evaluates to an empty string. +. if ${DOLLARS} != "" +. error +. endif +varname= varvalue +. if ${DOLLARS} != "varvalue" +. error +. endif +. undef varname +.endif dollars_stage_2: @echo "$@: env MAKEFLAGS=<$$MAKEFLAGS>" @echo '$@: dollars=<'${DOLLARS:Q}'>'