make(1): add test for appending and exporting a variablediff -r1.64 -r1.65 src/usr.bin/make/unit-tests/Makefile
(rillig)
--- src/usr.bin/make/unit-tests/Makefile 2020/07/25 21:19:29 1.64
+++ src/usr.bin/make/unit-tests/Makefile 2020/07/26 11:10:29 1.65
@@ -1,182 +1,185 @@ | @@ -1,182 +1,185 @@ | |||
1 | # $NetBSD: Makefile,v 1.64 2020/07/25 21:19:29 rillig Exp $ | 1 | # $NetBSD: Makefile,v 1.65 2020/07/26 11:10:29 rillig Exp $ | |
2 | # | 2 | # | |
3 | # Unit tests for make(1) | 3 | # Unit tests for make(1) | |
4 | # | 4 | # | |
5 | # The main targets are: | 5 | # The main targets are: | |
6 | # | 6 | # | |
7 | # all: | 7 | # all: | |
8 | # run all the tests | 8 | # run all the tests | |
9 | # test: | 9 | # test: | |
10 | # run 'all', and compare to expected results | 10 | # run 'all', and compare to expected results | |
11 | # accept: | 11 | # accept: | |
12 | # move generated output to expected results | 12 | # move generated output to expected results | |
13 | # | 13 | # | |
14 | # Settable variables | 14 | # Settable variables | |
15 | # | 15 | # | |
16 | # TEST_MAKE | 16 | # TEST_MAKE | |
17 | # The make program to be tested. | 17 | # The make program to be tested. | |
18 | # | 18 | # | |
19 | # | 19 | # | |
20 | # Adding a test case | 20 | # Adding a test case | |
21 | # | 21 | # | |
22 | # Each feature should get its own set of tests in its own suitably | 22 | # Each feature should get its own set of tests in its own suitably | |
23 | # named makefile (*.mk), with its own set of expected results (*.exp), | 23 | # named makefile (*.mk), with its own set of expected results (*.exp), | |
24 | # and it should be added to the TESTS list. | 24 | # and it should be added to the TESTS list. | |
25 | # | 25 | # | |
26 | # Any added files must also be added to src/distrib/sets/lists/tests/mi. | 26 | # Any added files must also be added to src/distrib/sets/lists/tests/mi. | |
27 | # Makefiles that are not added to TESTS must be ignored in | 27 | # Makefiles that are not added to TESTS must be ignored in | |
28 | # src/tests/usr.bin/make/t_make.sh (example: include-sub). | 28 | # src/tests/usr.bin/make/t_make.sh (example: include-sub). | |
29 | # | 29 | # | |
30 | 30 | |||
31 | # Each test is in a sub-makefile. | 31 | # Each test is in a sub-makefile. | |
32 | # Keep the list sorted. | 32 | # Keep the list sorted. | |
33 | TESTS+= comment | 33 | TESTS+= comment | |
34 | TESTS+= cond-late | 34 | TESTS+= cond-late | |
35 | TESTS+= cond-short | 35 | TESTS+= cond-short | |
36 | TESTS+= cond1 | 36 | TESTS+= cond1 | |
37 | TESTS+= cond2 | 37 | TESTS+= cond2 | |
38 | TESTS+= dollar | 38 | TESTS+= dollar | |
39 | TESTS+= doterror | 39 | TESTS+= doterror | |
40 | TESTS+= dotwait | 40 | TESTS+= dotwait | |
41 | TESTS+= envfirst | 41 | TESTS+= envfirst | |
42 | TESTS+= error | 42 | TESTS+= error | |
43 | TESTS+= # escape # broken by reverting POSIX changes | 43 | TESTS+= # escape # broken by reverting POSIX changes | |
44 | TESTS+= export | 44 | TESTS+= export | |
45 | TESTS+= export-all | 45 | TESTS+= export-all | |
46 | TESTS+= export-env | 46 | TESTS+= export-env | |
47 | TESTS+= forloop | 47 | TESTS+= forloop | |
48 | TESTS+= forsubst | 48 | TESTS+= forsubst | |
49 | TESTS+= hash | 49 | TESTS+= hash | |
50 | TESTS+= # impsrc # broken by reverting POSIX changes | 50 | TESTS+= # impsrc # broken by reverting POSIX changes | |
51 | TESTS+= include-main | 51 | TESTS+= include-main | |
52 | TESTS+= misc | 52 | TESTS+= misc | |
53 | TESTS+= moderrs | 53 | TESTS+= moderrs | |
54 | TESTS+= modmatch | 54 | TESTS+= modmatch | |
55 | TESTS+= modmisc | 55 | TESTS+= modmisc | |
56 | TESTS+= modorder | 56 | TESTS+= modorder | |
57 | TESTS+= modts | 57 | TESTS+= modts | |
58 | TESTS+= modword | 58 | TESTS+= modword | |
59 | TESTS+= order | 59 | TESTS+= order | |
60 | TESTS+= # phony-end # broken by reverting POSIX changes | 60 | TESTS+= # phony-end # broken by reverting POSIX changes | |
61 | TESTS+= posix | 61 | TESTS+= posix | |
62 | TESTS+= # posix1 # broken by reverting POSIX changes | 62 | TESTS+= # posix1 # broken by reverting POSIX changes | |
63 | TESTS+= qequals | 63 | TESTS+= qequals | |
64 | TESTS+= # suffixes # broken by reverting POSIX changes | 64 | TESTS+= # suffixes # broken by reverting POSIX changes | |
65 | TESTS+= sunshcmd | 65 | TESTS+= sunshcmd | |
66 | TESTS+= sysv | 66 | TESTS+= sysv | |
67 | TESTS+= ternary | 67 | TESTS+= ternary | |
68 | TESTS+= unexport | 68 | TESTS+= unexport | |
69 | TESTS+= unexport-env | 69 | TESTS+= unexport-env | |
70 | TESTS+= varcmd | 70 | TESTS+= varcmd | |
71 | TESTS+= vardebug | 71 | TESTS+= vardebug | |
72 | TESTS+= varfind | 72 | TESTS+= varfind | |
73 | TESTS+= varmisc | 73 | TESTS+= varmisc | |
74 | TESTS+= varmod-edge | 74 | TESTS+= varmod-edge | |
75 | TESTS+= varquote | 75 | TESTS+= varquote | |
76 | TESTS+= varshell | 76 | TESTS+= varshell | |
77 | 77 | |||
78 | # Override environment variables for some of the tests. | 78 | # Override environment variables for some of the tests. | |
79 | ENV.envfirst= FROM_ENV=value-from-env | 79 | ENV.envfirst= FROM_ENV=value-from-env | |
80 | ENV.varmisc= FROM_ENV=env | |||
81 | ENV.varmisc+= FROM_ENV_BEFORE=env | |||
82 | ENV.varmisc+= FROM_ENV_AFTER=env | |||
80 | 83 | |||
81 | # Override make flags for some of the tests; default is -k. | 84 | # Override make flags for some of the tests; default is -k. | |
82 | FLAGS.doterror= # none | 85 | FLAGS.doterror= # none | |
83 | FLAGS.order= -j1 | 86 | FLAGS.order= -j1 | |
84 | FLAGS.envfirst= -e | 87 | FLAGS.envfirst= -e | |
85 | FLAGS.vardebug= -k -dv FROM_CMDLINE= | 88 | FLAGS.vardebug= -k -dv FROM_CMDLINE= | |
86 | 89 | |||
87 | # Some tests need extra post-processing. | 90 | # Some tests need extra post-processing. | |
88 | SED_CMDS.modmisc+= -e 's,\(substitution error:\).*,\1 (details omitted),' | 91 | SED_CMDS.modmisc+= -e 's,\(substitution error:\).*,\1 (details omitted),' | |
89 | SED_CMDS.varshell+= -e 's,^[a-z]*sh: ,,' | 92 | SED_CMDS.varshell+= -e 's,^[a-z]*sh: ,,' | |
90 | SED_CMDS.varshell+= -e '/command/s,No such.*,not found,' | 93 | SED_CMDS.varshell+= -e '/command/s,No such.*,not found,' | |
91 | 94 | |||
92 | # Some tests need an additional round of postprocessing. | 95 | # Some tests need an additional round of postprocessing. | |
93 | POSTPROC.vardebug= ${TOOL_SED} -n -e '/:RELEVANT = yes/,/:RELEVANT = no/p' | 96 | POSTPROC.vardebug= ${TOOL_SED} -n -e '/:RELEVANT = yes/,/:RELEVANT = no/p' | |
94 | 97 | |||
95 | # End of the configuration section. | 98 | # End of the configuration section. | |
96 | 99 | |||
97 | .MAIN: all | 100 | .MAIN: all | |
98 | 101 | |||
99 | UNIT_TESTS:= ${.PARSEDIR} | 102 | UNIT_TESTS:= ${.PARSEDIR} | |
100 | .PATH: ${UNIT_TESTS} | 103 | .PATH: ${UNIT_TESTS} | |
101 | 104 | |||
102 | OUTFILES= ${TESTS:=.out} | 105 | OUTFILES= ${TESTS:=.out} | |
103 | 106 | |||
104 | all: ${OUTFILES} | 107 | all: ${OUTFILES} | |
105 | 108 | |||
106 | CLEANFILES+= *.rawout *.out *.status *.tmp *.core *.tmp | 109 | CLEANFILES+= *.rawout *.out *.status *.tmp *.core *.tmp | |
107 | CLEANFILES+= obj*.[och] lib*.a # posix1.mk | 110 | CLEANFILES+= obj*.[och] lib*.a # posix1.mk | |
108 | CLEANFILES+= issue* .[ab]* # suffixes.mk | 111 | CLEANFILES+= issue* .[ab]* # suffixes.mk | |
109 | CLEANRECURSIVE+= dir dummy # posix1.mk | 112 | CLEANRECURSIVE+= dir dummy # posix1.mk | |
110 | 113 | |||
111 | clean: | 114 | clean: | |
112 | rm -f ${CLEANFILES} | 115 | rm -f ${CLEANFILES} | |
113 | .if !empty(CLEANRECURSIVE) | 116 | .if !empty(CLEANRECURSIVE) | |
114 | rm -rf ${CLEANRECURSIVE} | 117 | rm -rf ${CLEANRECURSIVE} | |
115 | .endif | 118 | .endif | |
116 | 119 | |||
117 | TEST_MAKE?= ${.MAKE} | 120 | TEST_MAKE?= ${.MAKE} | |
118 | TOOL_SED?= sed | 121 | TOOL_SED?= sed | |
119 | 122 | |||
120 | # ensure consistent results from sort(1) | 123 | # ensure consistent results from sort(1) | |
121 | LC_ALL= C | 124 | LC_ALL= C | |
122 | LANG= C | 125 | LANG= C | |
123 | .export LANG LC_ALL | 126 | .export LANG LC_ALL | |
124 | 127 | |||
125 | # the tests are actually done with sub-makes. | 128 | # the tests are actually done with sub-makes. | |
126 | .SUFFIXES: .mk .rawout .out | 129 | .SUFFIXES: .mk .rawout .out | |
127 | .mk.rawout: | 130 | .mk.rawout: | |
128 | @echo testing ${.IMPSRC} | 131 | @echo testing ${.IMPSRC} | |
129 | @set -eu; \ | 132 | @set -eu; \ | |
130 | cd ${.OBJDIR}; \ | 133 | cd ${.OBJDIR}; \ | |
131 | ${ENV.${.TARGET:R}} ${TEST_MAKE} \ | 134 | ${ENV.${.TARGET:R}} ${TEST_MAKE} \ | |
132 | ${FLAGS.${.TARGET:R}:U-k} -f ${.IMPSRC} \ | 135 | ${FLAGS.${.TARGET:R}:U-k} -f ${.IMPSRC} \ | |
133 | > ${.TARGET}.tmp 2>&1 \ | 136 | > ${.TARGET}.tmp 2>&1 \ | |
134 | && status=$$? || status=$$?; \ | 137 | && status=$$? || status=$$?; \ | |
135 | echo $$status > ${.TARGET:R}.status | 138 | echo $$status > ${.TARGET:R}.status | |
136 | @mv ${.TARGET}.tmp ${.TARGET} | 139 | @mv ${.TARGET}.tmp ${.TARGET} | |
137 | 140 | |||
138 | # Post-process the test output so that the results can be compared. | 141 | # Post-process the test output so that the results can be compared. | |
139 | # | 142 | # | |
140 | # always pretend .MAKE was called 'make' | 143 | # always pretend .MAKE was called 'make' | |
141 | _SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,' | 144 | _SED_CMDS+= -e 's,^${TEST_MAKE:T:S,.,\\.,g}[][0-9]*:,make:,' | |
142 | _SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,' | 145 | _SED_CMDS+= -e 's,${TEST_MAKE:S,.,\\.,g},make,' | |
143 | # replace anything after 'stopped in' with unit-tests | 146 | # replace anything after 'stopped in' with unit-tests | |
144 | _SED_CMDS+= -e '/stopped/s, /.*, unit-tests,' | 147 | _SED_CMDS+= -e '/stopped/s, /.*, unit-tests,' | |
145 | # strip ${.CURDIR}/ from the output | 148 | # strip ${.CURDIR}/ from the output | |
146 | _SED_CMDS+= -e 's,${.CURDIR:S,.,\\.,g}/,,g' | 149 | _SED_CMDS+= -e 's,${.CURDIR:S,.,\\.,g}/,,g' | |
147 | _SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g' | 150 | _SED_CMDS+= -e 's,${UNIT_TESTS:S,.,\\.,g}/,,g' | |
148 | 151 | |||
149 | .rawout.out: | 152 | .rawout.out: | |
150 | @echo postprocess ${.TARGET} | 153 | @echo postprocess ${.TARGET} | |
151 | @${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.TARGET:R}} \ | 154 | @${TOOL_SED} ${_SED_CMDS} ${SED_CMDS.${.TARGET:R}} \ | |
152 | < ${.IMPSRC} > ${.TARGET}.tmp1 | 155 | < ${.IMPSRC} > ${.TARGET}.tmp1 | |
153 | @${POSTPROC.${.TARGET:R}:U${TOOL_SED}} < ${.TARGET}.tmp1 > ${.TARGET}.tmp2 | 156 | @${POSTPROC.${.TARGET:R}:U${TOOL_SED}} < ${.TARGET}.tmp1 > ${.TARGET}.tmp2 | |
154 | @rm ${.TARGET}.tmp1 | 157 | @rm ${.TARGET}.tmp1 | |
155 | @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp2 | 158 | @echo "exit status `cat ${.TARGET:R}.status`" >> ${.TARGET}.tmp2 | |
156 | @mv ${.TARGET}.tmp2 ${.TARGET} | 159 | @mv ${.TARGET}.tmp2 ${.TARGET} | |
157 | 160 | |||
158 | # Compare all output files | 161 | # Compare all output files | |
159 | test: ${OUTFILES} .PHONY | 162 | test: ${OUTFILES} .PHONY | |
160 | @failed= ; \ | 163 | @failed= ; \ | |
161 | for test in ${TESTS}; do \ | 164 | for test in ${TESTS}; do \ | |
162 | diff -u ${UNIT_TESTS}/$${test}.exp $${test}.out \ | 165 | diff -u ${UNIT_TESTS}/$${test}.exp $${test}.out \ | |
163 | || failed="$${failed}$${failed:+ }$${test}" ; \ | 166 | || failed="$${failed}$${failed:+ }$${test}" ; \ | |
164 | done ; \ | 167 | done ; \ | |
165 | if [ -n "$${failed}" ]; then \ | 168 | if [ -n "$${failed}" ]; then \ | |
166 | echo "Failed tests: $${failed}" ; false ; \ | 169 | echo "Failed tests: $${failed}" ; false ; \ | |
167 | else \ | 170 | else \ | |
168 | echo "All tests passed" ; \ | 171 | echo "All tests passed" ; \ | |
169 | fi | 172 | fi | |
170 | 173 | |||
171 | accept: | 174 | accept: | |
172 | @for test in ${TESTS}; do \ | 175 | @for test in ${TESTS}; do \ | |
173 | cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \ | 176 | cmp -s ${UNIT_TESTS}/$${test}.exp $${test}.out \ | |
174 | || { echo "Replacing $${test}.exp" ; \ | 177 | || { echo "Replacing $${test}.exp" ; \ | |
175 | cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \ | 178 | cp $${test}.out ${UNIT_TESTS}/$${test}.exp ; } \ | |
176 | done | 179 | done | |
177 | 180 | |||
178 | .if exists(${TEST_MAKE}) | 181 | .if exists(${TEST_MAKE}) | |
179 | ${TESTS:=.rawout}: ${TEST_MAKE} | 182 | ${TESTS:=.rawout}: ${TEST_MAKE} | |
180 | .endif | 183 | .endif | |
181 | 184 | |||
182 | .-include <bsd.obj.mk> | 185 | .-include <bsd.obj.mk> |
--- src/usr.bin/make/unit-tests/varmisc.exp 2020/07/26 10:48:21 1.9
+++ src/usr.bin/make/unit-tests/varmisc.exp 2020/07/26 11:10:29 1.10
@@ -1,43 +1,46 @@ | @@ -1,43 +1,46 @@ | |||
1 | 1 | |||
2 | :D expanded when var set | 2 | :D expanded when var set | |
3 | true | 3 | true | |
4 | TRUE | 4 | TRUE | |
5 | :U expanded when var undef | 5 | :U expanded when var undef | |
6 | true | 6 | true | |
7 | TRUE | 7 | TRUE | |
8 | :D skipped if var undef | 8 | :D skipped if var undef | |
9 | 9 | |||
10 | :U skipped when var set | 10 | :U skipped when var set | |
11 | is set | 11 | is set | |
12 | :? only lhs when value true | 12 | :? only lhs when value true | |
13 | true | 13 | true | |
14 | TRUE | 14 | TRUE | |
15 | :? only rhs when value false | 15 | :? only rhs when value false | |
16 | false | 16 | false | |
17 | FALSE | 17 | FALSE | |
18 | do not evaluate or expand :? if discarding | 18 | do not evaluate or expand :? if discarding | |
19 | is set | 19 | is set | |
20 | year=2016 month=04 day=01 | 20 | year=2016 month=04 day=01 | |
21 | date=20160401 | 21 | date=20160401 | |
22 | Version=123.456.789 == 123456789 | 22 | Version=123.456.789 == 123456789 | |
23 | Literal=3.4.5 == 3004005 | 23 | Literal=3.4.5 == 3004005 | |
24 | We have target specific vars | 24 | We have target specific vars | |
25 | MAN= make.1 | 25 | MAN= make.1 | |
26 | save-dollars: 0 = $ | 26 | save-dollars: 0 = $ | |
27 | save-dollars: 1 = $$ | 27 | save-dollars: 1 = $$ | |
28 | save-dollars: 2 = $$ | 28 | save-dollars: 2 = $$ | |
29 | save-dollars: False = $ | 29 | save-dollars: False = $ | |
30 | save-dollars: True = $$ | 30 | save-dollars: True = $$ | |
31 | save-dollars: false = $ | 31 | save-dollars: false = $ | |
32 | save-dollars: true = $$ | 32 | save-dollars: true = $$ | |
33 | save-dollars: Yes = $$ | 33 | save-dollars: Yes = $$ | |
34 | save-dollars: No = $ | 34 | save-dollars: No = $ | |
35 | save-dollars: yes = $$ | 35 | save-dollars: yes = $$ | |
36 | save-dollars: no = $ | 36 | save-dollars: no = $ | |
37 | save-dollars: On = $$ | 37 | save-dollars: On = $$ | |
38 | save-dollars: Off = $ | 38 | save-dollars: Off = $ | |
39 | save-dollars: ON = $$ | 39 | save-dollars: ON = $$ | |
40 | save-dollars: OFF = $ | 40 | save-dollars: OFF = $ | |
41 | save-dollars: on = $$ | 41 | save-dollars: on = $$ | |
42 | save-dollars: off = $ | 42 | save-dollars: off = $ | |
43 | export-appended: env | |||
44 | export-appended: env | |||
45 | export-appended: env mk | |||
43 | exit status 0 | 46 | exit status 0 |
--- src/usr.bin/make/unit-tests/varmisc.mk 2020/07/26 10:59:56 1.13
+++ src/usr.bin/make/unit-tests/varmisc.mk 2020/07/26 11:10:29 1.14
@@ -1,141 +1,158 @@ | @@ -1,141 +1,158 @@ | |||
1 | # $Id: varmisc.mk,v 1.13 2020/07/26 10:59:56 rillig Exp $ | 1 | # $Id: varmisc.mk,v 1.14 2020/07/26 11:10:29 rillig Exp $ | |
2 | # | 2 | # | |
3 | # Miscellaneous variable tests. | 3 | # Miscellaneous variable tests. | |
4 | 4 | |||
5 | all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \ | 5 | all: unmatched_var_paren D_true U_true D_false U_false Q_lhs Q_rhs NQ_none \ | |
6 | strftime cmpv manok | 6 | strftime cmpv manok | |
7 | all: save-dollars | 7 | all: save-dollars | |
8 | all: export-appended | |||
8 | 9 | |||
9 | unmatched_var_paren: | 10 | unmatched_var_paren: | |
10 | @echo ${foo::=foo-text} | 11 | @echo ${foo::=foo-text} | |
11 | 12 | |||
12 | True = ${echo true >&2:L:sh}TRUE | 13 | True = ${echo true >&2:L:sh}TRUE | |
13 | False= ${echo false >&2:L:sh}FALSE | 14 | False= ${echo false >&2:L:sh}FALSE | |
14 | 15 | |||
15 | VSET= is set | 16 | VSET= is set | |
16 | .undef UNDEF | 17 | .undef UNDEF | |
17 | 18 | |||
18 | U_false: | 19 | U_false: | |
19 | @echo :U skipped when var set | 20 | @echo :U skipped when var set | |
20 | @echo ${VSET:U${False}} | 21 | @echo ${VSET:U${False}} | |
21 | 22 | |||
22 | D_false: | 23 | D_false: | |
23 | @echo :D skipped if var undef | 24 | @echo :D skipped if var undef | |
24 | @echo ${UNDEF:D${False}} | 25 | @echo ${UNDEF:D${False}} | |
25 | 26 | |||
26 | U_true: | 27 | U_true: | |
27 | @echo :U expanded when var undef | 28 | @echo :U expanded when var undef | |
28 | @echo ${UNDEF:U${True}} | 29 | @echo ${UNDEF:U${True}} | |
29 | 30 | |||
30 | D_true: | 31 | D_true: | |
31 | @echo :D expanded when var set | 32 | @echo :D expanded when var set | |
32 | @echo ${VSET:D${True}} | 33 | @echo ${VSET:D${True}} | |
33 | 34 | |||
34 | Q_lhs: | 35 | Q_lhs: | |
35 | @echo :? only lhs when value true | 36 | @echo :? only lhs when value true | |
36 | @echo ${1:L:?${True}:${False}} | 37 | @echo ${1:L:?${True}:${False}} | |
37 | 38 | |||
38 | Q_rhs: | 39 | Q_rhs: | |
39 | @echo :? only rhs when value false | 40 | @echo :? only rhs when value false | |
40 | @echo ${0:L:?${True}:${False}} | 41 | @echo ${0:L:?${True}:${False}} | |
41 | 42 | |||
42 | NQ_none: | 43 | NQ_none: | |
43 | @echo do not evaluate or expand :? if discarding | 44 | @echo do not evaluate or expand :? if discarding | |
44 | @echo ${VSET:U${1:L:?${True}:${False}}} | 45 | @echo ${VSET:U${1:L:?${True}:${False}}} | |
45 | 46 | |||
46 | April1= 1459494000 | 47 | April1= 1459494000 | |
47 | 48 | |||
48 | # slightly contorted syntax to use utc via variable | 49 | # slightly contorted syntax to use utc via variable | |
49 | strftime: | 50 | strftime: | |
50 | @echo ${year=%Y month=%m day=%d:L:gmtime=1459494000} | 51 | @echo ${year=%Y month=%m day=%d:L:gmtime=1459494000} | |
51 | @echo date=${%Y%m%d:L:${gmtime=${April1}:L}} | 52 | @echo date=${%Y%m%d:L:${gmtime=${April1}:L}} | |
52 | 53 | |||
53 | # big jumps to handle 3 digits per step | 54 | # big jumps to handle 3 digits per step | |
54 | M_cmpv.units = 1 1000 1000000 | 55 | M_cmpv.units = 1 1000 1000000 | |
55 | M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh | 56 | M_cmpv = S,., ,g:_:range:@i@+ $${_:[-$$i]} \* $${M_cmpv.units:[$$i]}@:S,^,expr 0 ,1:sh | |
56 | 57 | |||
57 | Version = 123.456.789 | 58 | Version = 123.456.789 | |
58 | cmpv.only = target specific vars | 59 | cmpv.only = target specific vars | |
59 | 60 | |||
60 | cmpv: | 61 | cmpv: | |
61 | @echo Version=${Version} == ${Version:${M_cmpv}} | 62 | @echo Version=${Version} == ${Version:${M_cmpv}} | |
62 | @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}} | 63 | @echo Literal=3.4.5 == ${3.4.5:L:${M_cmpv}} | |
63 | @echo We have ${${.TARGET:T}.only} | 64 | @echo We have ${${.TARGET:T}.only} | |
64 | 65 | |||
65 | # catch misshandling of nested vars in .for loop | 66 | # catch misshandling of nested vars in .for loop | |
66 | MAN= | 67 | MAN= | |
67 | MAN1= make.1 | 68 | MAN1= make.1 | |
68 | .for s in 1 2 | 69 | .for s in 1 2 | |
69 | .if defined(MAN$s) && !empty(MAN$s) | 70 | .if defined(MAN$s) && !empty(MAN$s) | |
70 | MAN+= ${MAN$s} | 71 | MAN+= ${MAN$s} | |
71 | .endif | 72 | .endif | |
72 | .endfor | 73 | .endfor | |
73 | 74 | |||
74 | manok: | 75 | manok: | |
75 | @echo MAN=${MAN} | 76 | @echo MAN=${MAN} | |
76 | 77 | |||
77 | # This is an expanded variant of the above .for loop. | 78 | # This is an expanded variant of the above .for loop. | |
78 | # Between 2020-06-28 and 2020-07-02 this paragraph generated a wrong | 79 | # Between 2020-06-28 and 2020-07-02 this paragraph generated a wrong | |
79 | # error message "Variable VARNAME is recursive". | 80 | # error message "Variable VARNAME is recursive". | |
80 | # When evaluating the !empty expression, the ${:U1} was not expanded and | 81 | # When evaluating the !empty expression, the ${:U1} was not expanded and | |
81 | # thus resulted in the seeming definition VARNAME=${VARNAME}, which is | 82 | # thus resulted in the seeming definition VARNAME=${VARNAME}, which is | |
82 | # obviously recursive. | 83 | # obviously recursive. | |
83 | VARNAME= ${VARNAME${:U1}} | 84 | VARNAME= ${VARNAME${:U1}} | |
84 | .if defined(VARNAME${:U2}) && !empty(VARNAME${:U2}) | 85 | .if defined(VARNAME${:U2}) && !empty(VARNAME${:U2}) | |
85 | .endif | 86 | .endif | |
86 | 87 | |||
87 | # begin .MAKE.SAVE_DOLLARS; see Var_Set_with_flags and s2Boolean. | 88 | # begin .MAKE.SAVE_DOLLARS; see Var_Set_with_flags and s2Boolean. | |
88 | SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off | 89 | SD_VALUES= 0 1 2 False True false true Yes No yes no On Off ON OFF on off | |
89 | SD_4_DOLLARS= $$$$ | 90 | SD_4_DOLLARS= $$$$ | |
90 | 91 | |||
91 | .for val in ${SD_VALUES} | 92 | .for val in ${SD_VALUES} | |
92 | .MAKE.SAVE_DOLLARS:= ${val} # Must be := since a simple = has no effect. | 93 | .MAKE.SAVE_DOLLARS:= ${val} # Must be := since a simple = has no effect. | |
93 | SD.${val}:= ${SD_4_DOLLARS} | 94 | SD.${val}:= ${SD_4_DOLLARS} | |
94 | .endfor | 95 | .endfor | |
95 | .MAKE.SAVE_DOLLARS:= yes | 96 | .MAKE.SAVE_DOLLARS:= yes | |
96 | 97 | |||
97 | save-dollars: | 98 | save-dollars: | |
98 | .for val in ${SD_VALUES} | 99 | .for val in ${SD_VALUES} | |
99 | @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q} | 100 | @printf '%s: %-8s = %s\n' $@ ${val} ${SD.${val}:Q} | |
100 | .endfor | 101 | .endfor | |
101 | 102 | |||
102 | # Appending to an undefined variable does not add a space in front. | 103 | # Appending to an undefined variable does not add a space in front. | |
103 | .undef APPENDED | 104 | .undef APPENDED | |
104 | APPENDED+= value | 105 | APPENDED+= value | |
105 | .if ${APPENDED} != "value" | 106 | .if ${APPENDED} != "value" | |
106 | .error "${APPENDED}" | 107 | .error "${APPENDED}" | |
107 | .endif | 108 | .endif | |
108 | 109 | |||
109 | # Appending to an empty variable adds a space between the old value | 110 | # Appending to an empty variable adds a space between the old value | |
110 | # and the additional value. | 111 | # and the additional value. | |
111 | APPENDED= # empty | 112 | APPENDED= # empty | |
112 | APPENDED+= value | 113 | APPENDED+= value | |
113 | .if ${APPENDED} != " value" | 114 | .if ${APPENDED} != " value" | |
114 | .error "${APPENDED}" | 115 | .error "${APPENDED}" | |
115 | .endif | 116 | .endif | |
116 | 117 | |||
117 | # Appending to parameterized variables works as well. | 118 | # Appending to parameterized variables works as well. | |
118 | PARAM= param | 119 | PARAM= param | |
119 | VAR.${PARAM}= 1 | 120 | VAR.${PARAM}= 1 | |
120 | VAR.${PARAM}+= 2 | 121 | VAR.${PARAM}+= 2 | |
121 | .if ${VAR.param} != "1 2" | 122 | .if ${VAR.param} != "1 2" | |
122 | .error "${VAR.param}" | 123 | .error "${VAR.param}" | |
123 | .endif | 124 | .endif | |
124 | 125 | |||
125 | # The variable name can contain arbitrary characters. | 126 | # The variable name can contain arbitrary characters. | |
126 | # If the expanded variable name ends in a +, this still does not influence | 127 | # If the expanded variable name ends in a +, this still does not influence | |
127 | # the parser. The assignment operator is still a simple assignment. | 128 | # the parser. The assignment operator is still a simple assignment. | |
128 | # Therefore, there is no need to add a space between the variable name | 129 | # Therefore, there is no need to add a space between the variable name | |
129 | # and the assignment operator. | 130 | # and the assignment operator. | |
130 | PARAM= + | 131 | PARAM= + | |
131 | VAR.${PARAM}= 1 | 132 | VAR.${PARAM}= 1 | |
132 | VAR.${PARAM}+= 2 | 133 | VAR.${PARAM}+= 2 | |
133 | .if ${VAR.+} != "1 2" | 134 | .if ${VAR.+} != "1 2" | |
134 | .error "${VAR.+}" | 135 | .error "${VAR.+}" | |
135 | .endif | 136 | .endif | |
136 | .for param in + ! ? | 137 | .for param in + ! ? | |
137 | VAR.${param}= ${param} | 138 | VAR.${param}= ${param} | |
138 | .endfor | 139 | .endfor | |
139 | .if ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?" | 140 | .if ${VAR.+} != "+" || ${VAR.!} != "!" || ${VAR.?} != "?" | |
140 | .error "${VAR.+}" "${VAR.!}" "${VAR.?}" | 141 | .error "${VAR.+}" "${VAR.!}" "${VAR.?}" | |
141 | .endif | 142 | .endif | |
143 | ||||
144 | # Appending to a variable from the environment creates a copy of that variable | |||
145 | # in the global context. | |||
146 | # The appended value is not exported automatically. | |||
147 | # When a variable is exported, the exported value is taken at the time of the | |||
148 | # .export directive. Later changes to the variable have no effect. | |||
149 | .export FROM_ENV_BEFORE | |||
150 | FROM_ENV+= mk | |||
151 | FROM_ENV_BEFORE+= mk | |||
152 | FROM_ENV_AFTER+= mk | |||
153 | .export FROM_ENV_AFTER | |||
154 | ||||
155 | export-appended: | |||
156 | @echo $@: "$$FROM_ENV" | |||
157 | @echo $@: "$$FROM_ENV_BEFORE" | |||
158 | @echo $@: "$$FROM_ENV_AFTER" |