| @@ -1,127 +1,135 @@ | | | @@ -1,127 +1,135 @@ |
1 | # $Id: modmisc.mk,v 1.12 2020/07/04 18:54:18 rillig Exp $ | | 1 | # $Id: modmisc.mk,v 1.13 2020/07/19 15:16:22 rillig Exp $ |
2 | # | | 2 | # |
3 | # miscellaneous modifier tests | | 3 | # miscellaneous modifier tests |
4 | | | 4 | |
5 | # do not put any dirs in this list which exist on some | | 5 | # do not put any dirs in this list which exist on some |
6 | # but not all target systems - an exists() check is below. | | 6 | # but not all target systems - an exists() check is below. |
7 | path=:/bin:/tmp::/:.:/no/such/dir:. | | 7 | path=:/bin:/tmp::/:.:/no/such/dir:. |
8 | # strip cwd from path. | | 8 | # strip cwd from path. |
9 | MOD_NODOT=S/:/ /g:N.:ts: | | 9 | MOD_NODOT=S/:/ /g:N.:ts: |
10 | # and decorate, note that $'s need to be doubled. Also note that | | 10 | # and decorate, note that $'s need to be doubled. Also note that |
11 | # the modifier_variable can be used with other modifiers. | | 11 | # the modifier_variable can be used with other modifiers. |
12 | MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ | | 12 | MOD_NODOTX=S/:/ /g:N.:@d@'$$d'@ |
13 | # another mod - pretend it is more interesting | | 13 | # another mod - pretend it is more interesting |
14 | MOD_HOMES=S,/home/,/homes/, | | 14 | MOD_HOMES=S,/home/,/homes/, |
15 | MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ | | 15 | MOD_OPT=@d@$${exists($$d):?$$d:$${d:S,/usr,/opt,}}@ |
16 | MOD_SEP=S,:, ,g | | 16 | MOD_SEP=S,:, ,g |
17 | | | 17 | |
18 | all: modvar modvarloop modsysv mod-HTE emptyvar undefvar | | 18 | all: modvar modvarloop modsysv mod-HTE emptyvar undefvar |
19 | all: mod-S mod-C mod-at-varname mod-at-resolve | | 19 | all: mod-S mod-C mod-at-varname mod-at-resolve mod-at-dollar |
20 | all: mod-subst-dollar mod-loop-dollar | | 20 | all: mod-subst-dollar mod-loop-dollar |
21 | | | 21 | |
22 | modsysv: | | 22 | modsysv: |
23 | @echo "The answer is ${libfoo.a:L:libfoo.a=42}" | | 23 | @echo "The answer is ${libfoo.a:L:libfoo.a=42}" |
24 | | | 24 | |
25 | modvar: | | 25 | modvar: |
26 | @echo "path='${path}'" | | 26 | @echo "path='${path}'" |
27 | @echo "path='${path:${MOD_NODOT}}'" | | 27 | @echo "path='${path:${MOD_NODOT}}'" |
28 | @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" | | 28 | @echo "path='${path:S,home,homes,:${MOD_NODOT}}'" |
29 | @echo "path=${path:${MOD_NODOTX}:ts:}" | | 29 | @echo "path=${path:${MOD_NODOTX}:ts:}" |
30 | @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" | | 30 | @echo "path=${path:${MOD_HOMES}:${MOD_NODOTX}:ts:}" |
31 | | | 31 | |
32 | .for d in ${path:${MOD_SEP}:N.} /usr/xbin | | 32 | .for d in ${path:${MOD_SEP}:N.} /usr/xbin |
33 | path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ | | 33 | path_$d?= ${d:${MOD_OPT}:${MOD_HOMES}}/ |
34 | paths+= ${d:${MOD_OPT}:${MOD_HOMES}} | | 34 | paths+= ${d:${MOD_OPT}:${MOD_HOMES}} |
35 | .endfor | | 35 | .endfor |
36 | | | 36 | |
37 | modvarloop: | | 37 | modvarloop: |
38 | @echo "path_/usr/xbin=${path_/usr/xbin}" | | 38 | @echo "path_/usr/xbin=${path_/usr/xbin}" |
39 | @echo "paths=${paths}" | | 39 | @echo "paths=${paths}" |
40 | @echo "PATHS=${paths:tu}" | | 40 | @echo "PATHS=${paths:tu}" |
41 | | | 41 | |
42 | PATHNAMES= a/b/c def a.b.c a.b/c a a.a .gitignore a a.a | | 42 | PATHNAMES= a/b/c def a.b.c a.b/c a a.a .gitignore a a.a |
43 | mod-HTE: | | 43 | mod-HTE: |
44 | @echo "dirname of '"${PATHNAMES:Q}"' is '"${PATHNAMES:H:Q}"'" | | 44 | @echo "dirname of '"${PATHNAMES:Q}"' is '"${PATHNAMES:H:Q}"'" |
45 | @echo "basename of '"${PATHNAMES:Q}"' is '"${PATHNAMES:T:Q}"'" | | 45 | @echo "basename of '"${PATHNAMES:Q}"' is '"${PATHNAMES:T:Q}"'" |
46 | @echo "suffix of '"${PATHNAMES:Q}"' is '"${PATHNAMES:E:Q}"'" | | 46 | @echo "suffix of '"${PATHNAMES:Q}"' is '"${PATHNAMES:E:Q}"'" |
47 | @echo "root of '"${PATHNAMES:Q}"' is '"${PATHNAMES:R:Q}"'" | | 47 | @echo "root of '"${PATHNAMES:Q}"' is '"${PATHNAMES:R:Q}"'" |
48 | | | 48 | |
49 | # When a modifier is applied to the "" variable, the result is discarded. | | 49 | # When a modifier is applied to the "" variable, the result is discarded. |
50 | emptyvar: | | 50 | emptyvar: |
51 | @echo S:${:S,^$,empty,} | | 51 | @echo S:${:S,^$,empty,} |
52 | @echo C:${:C,^$,empty,} | | 52 | @echo C:${:C,^$,empty,} |
53 | @echo @:${:@var@${var}@} | | 53 | @echo @:${:@var@${var}@} |
54 | | | 54 | |
55 | # The :U modifier turns even the "" variable into something that has a value. | | 55 | # The :U modifier turns even the "" variable into something that has a value. |
56 | # The resulting variable is empty, but is still considered to contain a | | 56 | # The resulting variable is empty, but is still considered to contain a |
57 | # single empty word. This word can be accessed by the :S and :C modifiers, | | 57 | # single empty word. This word can be accessed by the :S and :C modifiers, |
58 | # but not by the :@ modifier since it explicitly skips empty words. | | 58 | # but not by the :@ modifier since it explicitly skips empty words. |
59 | undefvar: | | 59 | undefvar: |
60 | @echo S:${:U:S,^$,empty,} | | 60 | @echo S:${:U:S,^$,empty,} |
61 | @echo C:${:U:C,^$,empty,} | | 61 | @echo C:${:U:C,^$,empty,} |
62 | @echo @:${:U:@var@empty@} | | 62 | @echo @:${:U:@var@empty@} |
63 | | | 63 | |
64 | mod-S: | | 64 | mod-S: |
65 | @echo :${:Ua b b c:S,a b,,:Q}: | | 65 | @echo :${:Ua b b c:S,a b,,:Q}: |
66 | @echo :${:Ua b b c:S,a b,,1:Q}: | | 66 | @echo :${:Ua b b c:S,a b,,1:Q}: |
67 | @echo :${:Ua b b c:S,a b,,W:Q}: | | 67 | @echo :${:Ua b b c:S,a b,,W:Q}: |
68 | @echo :${:Ua b b c:S,b,,g:Q}: | | 68 | @echo :${:Ua b b c:S,b,,g:Q}: |
69 | @echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}: | | 69 | @echo :${:U1 2 3 1 2 3:S,1 2,___,Wg:S,_,x,:Q}: |
70 | | | 70 | |
71 | mod-C: | | 71 | mod-C: |
72 | @echo :${:Ua b b c:C,a b,,:Q}: | | 72 | @echo :${:Ua b b c:C,a b,,:Q}: |
73 | @echo :${:Ua b b c:C,a b,,1:Q}: | | 73 | @echo :${:Ua b b c:C,a b,,1:Q}: |
74 | @echo :${:Ua b b c:C,a b,,W:Q}: | | 74 | @echo :${:Ua b b c:C,a b,,W:Q}: |
75 | @echo :${:Uword1 word2:C,****,____,g:C,word,____,:Q}: | | 75 | @echo :${:Uword1 word2:C,****,____,g:C,word,____,:Q}: |
76 | @echo :${:Ua b b c:C,b,,g:Q}: | | 76 | @echo :${:Ua b b c:C,b,,g:Q}: |
77 | @echo :${:U1 2 3 1 2 3:C,1 2,___,Wg:C,_,x,:Q}: | | 77 | @echo :${:U1 2 3 1 2 3:C,1 2,___,Wg:C,_,x,:Q}: |
78 | | | 78 | |
79 | # In the :@ modifier, the name of the loop variable can even be generated | | 79 | # In the :@ modifier, the name of the loop variable can even be generated |
80 | # dynamically. There's no practical use-case for this, and hopefully nobody | | 80 | # dynamically. There's no practical use-case for this, and hopefully nobody |
81 | # will ever depend on this, but technically it's possible. | | 81 | # will ever depend on this, but technically it's possible. |
82 | mod-at-varname: | | 82 | mod-at-varname: |
83 | @echo :${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@:Q}: | | 83 | @echo :${:Uone two three:@${:Ubar:S,b,v,}@+${var}+@:Q}: |
84 | | | 84 | |
85 | # The :@ modifier resolves the variables a little more often than expected. | | 85 | # The :@ modifier resolves the variables a little more often than expected. |
86 | # In particular, it resolves _all_ variables from the context, and not only | | 86 | # In particular, it resolves _all_ variables from the context, and not only |
87 | # the loop variable (in this case v). | | 87 | # the loop variable (in this case v). |
88 | # | | 88 | # |
89 | # The d means direct reference, the i means indirect reference. | | 89 | # The d means direct reference, the i means indirect reference. |
90 | RESOLVE= ${RES1} $${RES1} | | 90 | RESOLVE= ${RES1} $${RES1} |
91 | RES1= 1d${RES2} 1i$${RES2} | | 91 | RES1= 1d${RES2} 1i$${RES2} |
92 | RES2= 2d${RES3} 2i$${RES3} | | 92 | RES2= 2d${RES3} 2i$${RES3} |
93 | RES3= 3 | | 93 | RES3= 3 |
94 | | | 94 | |
95 | mod-at-resolve: | | 95 | mod-at-resolve: |
96 | @echo $@:${RESOLVE:@v@w${v}w@:Q}: | | 96 | @echo $@:${RESOLVE:@v@w${v}w@:Q}: |
97 | | | 97 | |
| | | 98 | # As of 2020-07-19, the variable name of the :@ modifier may end with one |
| | | 99 | # or two dollar signs, which are silently ignored. There's no point in |
| | | 100 | # allowing a dollar sign in that position. |
| | | 101 | mod-at-dollar: |
| | | 102 | @echo $@:${1 2 3:L:@v$@($v)@:Q}. |
| | | 103 | @echo $@:${1 2 3:L:@v$$@($v)@:Q}. |
| | | 104 | @echo $@:${1 2 3:L:@v$$$@($v)@:Q}. |
| | | 105 | |
98 | # No matter how many dollar characters there are, they all get merged | | 106 | # No matter how many dollar characters there are, they all get merged |
99 | # into a single dollar by the :S modifier. | | 107 | # into a single dollar by the :S modifier. |
100 | mod-subst-dollar: | | 108 | mod-subst-dollar: |
101 | @echo $@:${:U1:S,^,$,:Q}: | | 109 | @echo $@:${:U1:S,^,$,:Q}: |
102 | @echo $@:${:U2:S,^,$$,:Q}: | | 110 | @echo $@:${:U2:S,^,$$,:Q}: |
103 | @echo $@:${:U3:S,^,$$$,:Q}: | | 111 | @echo $@:${:U3:S,^,$$$,:Q}: |
104 | @echo $@:${:U4:S,^,$$$$,:Q}: | | 112 | @echo $@:${:U4:S,^,$$$$,:Q}: |
105 | @echo $@:${:U5:S,^,$$$$$,:Q}: | | 113 | @echo $@:${:U5:S,^,$$$$$,:Q}: |
106 | @echo $@:${:U6:S,^,$$$$$$,:Q}: | | 114 | @echo $@:${:U6:S,^,$$$$$$,:Q}: |
107 | @echo $@:${:U7:S,^,$$$$$$$,:Q}: | | 115 | @echo $@:${:U7:S,^,$$$$$$$,:Q}: |
108 | @echo $@:${:U8:S,^,$$$$$$$$,:Q}: | | 116 | @echo $@:${:U8:S,^,$$$$$$$$,:Q}: |
109 | # This generates no dollar at all: | | 117 | # This generates no dollar at all: |
110 | @echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}: | | 118 | @echo $@:${:UU8:S,^,${:U$$$$$$$$},:Q}: |
111 | # Here is an alternative way to generate dollar characters. | | 119 | # Here is an alternative way to generate dollar characters. |
112 | # It's unexpectedly complicated though. | | 120 | # It's unexpectedly complicated though. |
113 | @echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}: | | 121 | @echo $@:${:U:range=5:ts\x24:C,[0-9],,g:Q}: |
114 | | | 122 | |
115 | # Demonstrate that it is possible to generate dollar characters using the | | 123 | # Demonstrate that it is possible to generate dollar characters using the |
116 | # :@ modifier. | | 124 | # :@ modifier. |
117 | # | | 125 | # |
118 | # These are edge cases that could have resulted in a parse error as well | | 126 | # These are edge cases that could have resulted in a parse error as well |
119 | # since the $@ at the end could have been interpreted as a variable, which | | 127 | # since the $@ at the end could have been interpreted as a variable, which |
120 | # would mean a missing closing @ delimiter. | | 128 | # would mean a missing closing @ delimiter. |
121 | mod-loop-dollar: | | 129 | mod-loop-dollar: |
122 | @echo $@:${:U1:@word@${word}$@:Q}: | | 130 | @echo $@:${:U1:@word@${word}$@:Q}: |
123 | @echo $@:${:U2:@word@$${word}$$@:Q}: | | 131 | @echo $@:${:U2:@word@$${word}$$@:Q}: |
124 | @echo $@:${:U3:@word@$$${word}$$$@:Q}: | | 132 | @echo $@:${:U3:@word@$$${word}$$$@:Q}: |
125 | @echo $@:${:U4:@word@$$$${word}$$$$@:Q}: | | 133 | @echo $@:${:U4:@word@$$$${word}$$$$@:Q}: |
126 | @echo $@:${:U5:@word@$$$$${word}$$$$$@:Q}: | | 134 | @echo $@:${:U5:@word@$$$$${word}$$$$$@:Q}: |
127 | @echo $@:${:U6:@word@$$$$$${word}$$$$$$@:Q}: | | 135 | @echo $@:${:U6:@word@$$$$$${word}$$$$$$@:Q}: |