.section "Expansion of lists" "SECTlistexpand"
.cindex "expansion" "of lists"
-Each list is expanded as a single string before it is used.
+.new
+Each list, after any leading change-of-separator specification
+(see &<<SECTlistsepchange>>&) is expanded as a single string,
.cindex "tainted data" tracking
-&*Note*&: As a result, if any componend was tainted then the
-entire result string becomes tainted.
+&*Note*&: As a result, if any component was tainted then the
+entire expansion result string becomes tainted.
+
+Splitting out a leading explicit change-of-separator permits
+one being safely used on a list that has tainted components
+while still detecting the use of a tainted setting.
+The latter is not permitted.
+.wen
&'Exception: the router headers_remove option, where list-item
splitting is done before string-expansion.'&
.cindex "list" "selecting by condition"
.cindex "expansion" "selecting from list by condition"
.vindex "&$item$&"
-After expansion, <&'string'&> is interpreted as a list, colon-separated by
-default, but the separator can be changed in the usual way (&<<SECTlistsepchange>>&).
-For each item
-in this list, its value is placed in &$item$&, and then the condition is
-evaluated.
+.new
+<&'string1'&> first has the part after any change-of-list-separator
+(see &<<SECTlistsepchange>>&) expanded,
+then the whole is taken as a list.
+.wen
+The default separator for the list is a colon.
+
+For each item in this list,
+its value is placed in &$item$&, and then the condition is evaluated.
Any modification of &$value$& by this evaluation is discarded.
If the condition is true, &$item$& is added to the output as an
item in a new list; if the condition is false, the item is discarded. The
apart from an optional leading minus,
and leading and trailing white space (which is ignored).
-After expansion, <&'string1'&> is interpreted as a list, colon-separated by
-default, but the separator can be changed in the usual way (&<<SECTlistsepchange>>&).
+.new
+The <&'string1'&> argument, after any leading change-of-separator
+(see &<<SECTlistsepchange>>&),
+is expanded and the whole forms the list.
+.wen
+By default, the list separator is a colon.
The first field of the list is numbered one.
If the number is negative, the fields are
.vitem &*${map{*&<&'string1'&>&*}{*&<&'string2'&>&*}}*&
.cindex "expansion" "list creation"
.vindex "&$item$&"
-After expansion, <&'string1'&> is interpreted as a list, colon-separated by
-default, but the separator can be changed in the usual way (&<<SECTlistsepchange>>&).
-For each item
-in this list, its value is place in &$item$&, and then <&'string2'&> is
+.new
+<&'string1'&> first has the part after any change-of-list-separator
+(see &<<SECTlistsepchange>>&) expanded,
+then the whole is taken as a list.
+.wen
+The default separator for the list is a colon.
+
+For each item in this list,
+its value is place in &$item$&, and then <&'string2'&> is
expanded and added to the output as an item in a new list. The separator used
for the output list is the same as the one used for the input, but a separator
setting is not included in the output. For example:
.cindex "list" "reducing to a scalar"
.vindex "&$value$&"
.vindex "&$item$&"
-This operation reduces a list to a single, scalar string. After expansion,
-<&'string1'&> is interpreted as a list, colon-separated by default, but the
-separator can be changed in the usual way (&<<SECTlistsepchange>>&).
+This operation reduces a list to a single, scalar string.
+
+.new
+<&'string1'&> first has the part after any change-of-list-separator
+(see &<<SECTlistsepchange>>&) expanded,
+then the whole is taken as a list.
+.wen
+The default separator for the list is a colon.
+
Then <&'string2'&> is expanded and
assigned to the &$value$& variable. After this, each item in the <&'string1'&>
list is assigned to &$item$&, in turn, and <&'string3'&> is expanded for each of
.cindex sorting "a list"
.cindex list sorting
.cindex expansion "list sorting"
-After expansion, <&'string'&> is interpreted as a list, colon-separated by
-default, but the separator can be changed in the usual way (&<<SECTlistsepchange>>&).
+.new
+<&'string'&> first has the part after any change-of-list-separator
+(see &<<SECTlistsepchange>>&) expanded,
+then the whole is taken as a list.
+.wen
+The default separator for the list is a colon.
+
The <&'comparator'&> argument is interpreted as the operator
of a two-argument expansion condition.
The numeric operators plus ge, gt, le, lt (and ~i variants) are supported.
.cindex "list" "item count"
.cindex "list" "count of items"
.cindex "&%listcount%& expansion item"
-The string is interpreted as a list and the number of items is returned.
+The part of the string after any leading change-of-separator is expanded,
+then the whole is interpreted as a list and the number of items is returned.
.vitem &*${listnamed:*&<&'name'&>&*}*&&~and&~&*${listnamed_*&<&'type'&>&*:*&<&'name'&>&*}*&
.cindex "expansion" "&*forall*& condition"
.cindex "expansion" "&*forany*& condition"
.vindex "&$item$&"
-These conditions iterate over a list. The first argument is expanded to form
-the list. By default, the list separator is a colon, but it can be changed by
-the normal method (&<<SECTlistsepchange>>&).
+These conditions iterate over a list.
+.new
+The first argument, after any leading change-of-separator
+(see &<<SECTlistsepchange>>&),
+is expanded and the whole forms the list.
+.wen
+By default, the list separator is a colon.
+
The second argument is interpreted as a condition that is to
be applied to each item in the list in turn. During the interpretation of the
condition, the current list item is placed in a variable called &$item$&.
&*inlisti&~{*&<&'subject'&>&*}{*&<&'list'&>&*}*&
.cindex "string" "comparison"
.cindex "list" "iterative conditions"
-Both strings are expanded; the second string is treated as a list of simple
-strings; if the first string is a member of the second, then the condition
-is true.
+The <&'subject'&> string is expanded.
+.new
+The <&'list'&> first has any change-of-list-separator
++(see &<<SECTlistsepchange>>&) retained verbatim,
++then the remainder is expanded.
++.wen
+The whole is treated as a list of simple strings;
+if the subject string is a member of that list, then the condition is true.
For the case-independent &%inlisti%& condition, case is defined per the system C locale.
These are simpler to use versions of the more powerful &*forany*& condition.
Note that <&'string2'&> is not itself subject to string expansion, unless
Exim was built with the EXPAND_LISTMATCH_RHS option.
+.new
+For the latter case, only the part after any leading
+change-of-separator specification is expanded.
+.wen
Consult section &<<SECThoslispatip>>& for further details of these patterns.
.endd
.cindex "&`+caseful`&"
For address lists, the matching starts off caselessly, but the &`+caseful`&
-item can be used, as in all address lists, to cause subsequent items to
-have their local parts matched casefully. Domains are always matched
-caselessly.
+item can be used, as in all address lists, to cause subsequent items
+(including those of referenced named lists)
+to have their local parts matched casefully.
+Domains are always matched caselessly.
The variable &$value$& will be set for a successful match and can be
used in the success clause of an &%if%& expansion item using the condition.
Note that <&'string2'&> is not itself subject to string expansion, unless
Exim was built with the EXPAND_LISTMATCH_RHS option.
+.new
+For the latter case, only the part after any leading
+change-of-separator specification is expanded.
+.wen
&*Note*&: Host lists are &'not'& supported in this way. This is because
hosts have two identities: a name and an IP address, and it is not clear