[BACK]Return to var-op-expand.mk CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.bin / make / unit-tests

Annotation of src/usr.bin/make/unit-tests/var-op-expand.mk, Revision 1.13

1.13    ! rillig      1: # $NetBSD: var-op-expand.mk,v 1.12 2021/11/13 18:37:42 rillig Exp $
1.1       rillig      2: #
1.2       rillig      3: # Tests for the := variable assignment operator, which expands its
                      4: # right-hand side.
1.1       rillig      5:
1.11      sjg         6: .MAKE.SAVE_DOLLARS:=      yes
1.5       rillig      7:
                      8: # If the right-hand side does not contain a dollar sign, the ':=' assignment
                      9: # operator has the same effect as the '=' assignment operator.
                     10: VAR:=                  value
                     11: .if ${VAR} != "value"
                     12: .  error
                     13: .endif
                     14:
                     15: # When a ':=' assignment is performed, its right-hand side is evaluated and
                     16: # expanded as far as possible.  Contrary to other situations, '$$' and
                     17: # variable expressions based on undefined variables are preserved though.
                     18: #
                     19: # Whether a variable expression is undefined or not is determined at the end
                     20: # of evaluating the expression.  The consequence is that ${:Ufallback} expands
                     21: # to "fallback"; initially this expression is undefined since it is based on
                     22: # the variable named "", which is guaranteed to be never defined, but at the
                     23: # end of evaluating the expression ${:Ufallback}, the modifier ':U' has turned
                     24: # the expression into a defined expression.
                     25:
                     26:
                     27: # literal dollar signs
                     28: VAR:=          $$ $$$$ $$$$$$$$
                     29: .if ${VAR} != "\$ \$\$ \$\$\$\$"
                     30: .  error
                     31: .endif
                     32:
                     33:
                     34: # reference to a variable containing a literal dollar sign
                     35: REF=           $$ $$$$ $$$$$$$$
                     36: VAR:=          ${REF}
                     37: REF=           too late
                     38: .if ${VAR} != "\$ \$\$ \$\$\$\$"
                     39: .  error
                     40: .endif
                     41:
                     42:
                     43: # reference to an undefined variable
                     44: .undef UNDEF
                     45: VAR:=          <${UNDEF}>
                     46: UNDEF=         after
                     47: .if ${VAR} != "<after>"
                     48: .  error
                     49: .endif
                     50:
                     51:
                     52: # reference to a variable whose name is computed from another variable
                     53: REF2=          referred to
                     54: REF=           REF2
                     55: VAR:=          ${${REF}}
                     56: REF=           too late
                     57: .if ${VAR} != "referred to"
                     58: .  error
                     59: .endif
                     60:
                     61:
                     62: # expression with an indirect modifier referring to an undefined variable
                     63: .undef UNDEF
                     64: VAR:=          ${:${UNDEF}}
                     65: UNDEF=         Uwas undefined
                     66: .if ${VAR} != "was undefined"
                     67: .  error
                     68: .endif
                     69:
                     70:
                     71: # expression with an indirect modifier referring to another variable that
                     72: # in turn refers to an undefined variable
                     73: #
                     74: # XXX: Even though this is a ':=' assignment, the '${UNDEF}' in the part of
                     75: # the variable modifier is not preserved.  To preserve it, ParseModifierPart
                     76: # would have to call VarSubstExpr somehow since this is the only piece of
                     77: # code that takes care of this global variable.
                     78: .undef UNDEF
                     79: REF=           U${UNDEF}
                     80: #.MAKEFLAGS: -dv
                     81: VAR:=          ${:${REF}}
                     82: #.MAKEFLAGS: -d0
                     83: REF=           too late
                     84: UNDEF=         Uwas undefined
                     85: .if ${VAR} != ""
                     86: .  error
                     87: .endif
                     88:
1.1       rillig     89:
1.6       rillig     90: # In variable assignments using the ':=' operator, undefined variables are
                     91: # preserved, no matter how indirectly they are referenced.
                     92: .undef REF3
                     93: REF2=          <${REF3}>
                     94: REF=           ${REF2}
                     95: VAR:=          ${REF}
                     96: REF3=          too late
                     97: .if ${VAR} != "<too late>"
                     98: .  error
                     99: .endif
                    100:
                    101:
                    102: # In variable assignments using the ':=' operator, '$$' are preserved, no
                    103: # matter how indirectly they are referenced.
                    104: REF2=          REF2:$$ $$$$
                    105: REF=           REF:$$ $$$$ ${REF2}
                    106: VAR:=          VAR:$$ $$$$ ${REF}
                    107: .if ${VAR} != "VAR:\$ \$\$ REF:\$ \$\$ REF2:\$ \$\$"
                    108: .  error
                    109: .endif
                    110:
                    111:
                    112: # In variable assignments using the ':=' operator, '$$' are preserved in the
                    113: # expressions of the top level, but not in expressions that are nested.
                    114: VAR:=          top:$$ ${:Unest1\:\$\$} ${:Unest2${:U\:\$\$}}
                    115: .if ${VAR} != "top:\$ nest1:\$ nest2:\$"
                    116: .  error
                    117: .endif
                    118:
                    119:
1.9       rillig    120: # In variable assignments using the ':=' operator, there may be expressions
                    121: # containing variable modifiers, and these modifiers may refer to other
1.10      rillig    122: # variables.  These referred-to variables are expanded at the time of
                    123: # assignment.  The undefined variables are kept as-is and are later expanded
                    124: # when evaluating the condition.
1.9       rillig    125: #
                    126: # Contrary to the assignment operator '=', the assignment operator ':='
                    127: # consumes the '$' from modifier parts.
                    128: REF.word=      1:$$ 2:$$$$ 4:$$$$$$$$
1.10      rillig    129: .undef REF.undef
                    130: VAR:=          ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
                    131: REF.word=      word.after
                    132: REF.undef=     undef.after
                    133: .if ${VAR} != "1:2:\$ 4:\$\$ undef.after, direct: 1:\$ 2:\$\$ 4:\$\$\$\$ undef.after"
1.9       rillig    134: .  error
                    135: .endif
                    136:
                    137: # Just for comparison, the previous example using the assignment operator '='
1.10      rillig    138: # instead of ':='.  The right-hand side of the assignment is not evaluated at
                    139: # the time of assignment but only later, when ${VAR} appears in the condition.
                    140: #
                    141: # At that point, both REF.word and REF.undef are defined.
1.9       rillig    142: REF.word=      1:$$ 2:$$$$ 4:$$$$$$$$
1.10      rillig    143: .undef REF.undef
                    144: VAR=           ${:Uword undef:@word@${REF.${word}}@}, direct: ${REF.word} ${REF.undef}
                    145: REF.word=      word.after
                    146: REF.undef=     undef.after
                    147: .if ${VAR} != "word.after undef.after, direct: word.after undef.after"
1.9       rillig    148: .  error
                    149: .endif
                    150:
                    151:
1.8       rillig    152: # Between var.c 1.42 from 2000-05-11 and before parse.c 1.520 from 2020-12-27,
                    153: # if the variable name in a ':=' assignment referred to an undefined variable,
                    154: # there were actually 2 assignments to different variables:
                    155: #
                    156: #      Global["VAR_SUBST_${UNDEF}"] = ""
                    157: #      Global["VAR_SUBST_"] = ""
                    158: #
                    159: # The variable name with the empty value actually included a dollar sign.
                    160: # Variable names with dollars are not used in practice.
                    161: #
                    162: # It might be a good idea to forbid undefined variables on the left-hand side
                    163: # of a variable assignment.
1.5       rillig    164: .undef UNDEF
1.7       rillig    165: VAR_ASSIGN_${UNDEF}=   assigned by '='
                    166: VAR_SUBST_${UNDEF}:=   assigned by ':='
                    167: .if ${VAR_ASSIGN_} != "assigned by '='"
                    168: .  error
                    169: .endif
1.8       rillig    170: .if defined(${:UVAR_SUBST_\${UNDEF\}})
1.7       rillig    171: .  error
                    172: .endif
                    173: .if ${VAR_SUBST_} != "assigned by ':='"
                    174: .  error
                    175: .endif
1.3       rillig    176:
1.12      rillig    177:
                    178: # The following test case demonstrates that the variable 'LATER' is preserved
                    179: # in the ':=' assignment since the variable 'LATER' is not yet defined.
                    180: # After the assignment to 'LATER', evaluating the variable 'INDIRECT'
                    181: # evaluates 'LATER' as well.
                    182: #
                    183: .undef LATER
                    184: INDIRECT:=     ${LATER:S,value,replaced,}
                    185: .if ${INDIRECT} != ""
                    186: .  error
                    187: .endif
                    188: LATER= late-value
                    189: .if ${INDIRECT} != "late-replaced"
                    190: .  error
                    191: .endif
                    192:
                    193:
                    194: # Same as the test case above, except for the additional modifier ':tl' when
                    195: # evaluating the variable 'INDIRECT'.  Nothing surprising here.
                    196: .undef LATER
                    197: .undef later
                    198: INDIRECT:=     ${LATER:S,value,replaced,}
                    199: .if ${INDIRECT:tl} != ""
                    200: .  error
                    201: .endif
                    202: LATER= uppercase-value
                    203: later= lowercase-value
                    204: .if ${INDIRECT:tl} != "uppercase-replaced"
                    205: .  error
                    206: .endif
                    207:
                    208:
                    209: # Similar to the two test cases above, the situation gets a bit more involved
                    210: # here, due to the double indirection.  The variable 'indirect' is supposed to
                    211: # be the lowercase version of the variable 'INDIRECT'.
                    212: #
                    213: # The assignment operator ':=' for the variable 'INDIRECT' could be a '=' as
                    214: # well, it wouldn't make a difference in this case.  The crucial detail is the
                    215: # assignment operator ':=' for the variable 'indirect', though.  During this
                    216: # assignment, the variable modifier ':S,value,replaced,' is converted to
                    217: # lowercase, which turns 'S' into 's', thus producing an unknown modifier.
                    218: # In this case, make issues a warning, but in cases where the modifier
                    219: # includes a '=', the modifier would be interpreted as a SysV-style
                    220: # substitution like '.c=.o', and make would not issue a warning, leading to
                    221: # silent unexpected behavior.
                    222: #
                    223: # As of 2021-11-13, the actual behavior is unexpected though since
                    224: .undef LATER
                    225: .undef later
1.13    ! rillig    226: INDIRECT:=     ${LATER:S,value,replaced,} OK ${LATER:value=sysv}
1.12      rillig    227: indirect:=     ${INDIRECT:tl}
                    228: # expect+1: Unknown modifier "s,value,replaced,"
1.13    ! rillig    229: .if ${indirect} != " ok "
1.12      rillig    230: .  error
                    231: .else
                    232: .  warning     XXX Neither branch should be taken.
                    233: .endif
                    234: LATER= uppercase-value
                    235: later= lowercase-value
                    236: # expect+1: Unknown modifier "s,value,replaced,"
1.13    ! rillig    237: .if ${indirect} != "uppercase-replaced ok uppercase-sysv"
1.12      rillig    238: .  warning     XXX Neither branch should be taken.
                    239: .else
                    240: .  error
                    241: .endif
                    242:
                    243:
1.1       rillig    244: all:
                    245:        @:;

CVSweb <webmaster@jp.NetBSD.org>