From bbbe8128e7ae9d816a221377dbf5ff3969bb203b Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 30 Sep 2019 03:00:43 +0000
Subject: CTAN sync 201909300300

---
 macros/latex/contrib/l3kernel/l3expan.dtx | 354 ++++++++++++++++++------------
 1 file changed, 213 insertions(+), 141 deletions(-)

(limited to 'macros/latex/contrib/l3kernel/l3expan.dtx')

diff --git a/macros/latex/contrib/l3kernel/l3expan.dtx b/macros/latex/contrib/l3kernel/l3expan.dtx
index ab6ec3271b..ab72686865 100644
--- a/macros/latex/contrib/l3kernel/l3expan.dtx
+++ b/macros/latex/contrib/l3kernel/l3expan.dtx
@@ -43,7 +43,7 @@
 %    }^^A
 % }
 %
-% \date{Released 2019-09-19}
+% \date{Released 2019-09-28}
 %
 % \maketitle
 %
@@ -1128,7 +1128,7 @@
       \exp_after:wN { \exp:w \@@_eval_register:N #3 }
       {#1} {#2}
 }
-\cs_new:Npn \::v # 1\::: #2#3
+\cs_new:Npn \::v #1 \::: #2#3
   {
     \exp_after:wN \@@_arg_next:nnn
       \exp_after:wN { \exp:w \@@_eval_register:c {#3} }
@@ -1400,99 +1400,13 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \subsection{Definitions with the automated technique}
-% \label{sec:l3expan:gendef}
-%
-% Some of these could be done more efficiently, but the complexity of
-% coding then becomes an issue. Notice that the auto-generated functions
-% actually take no arguments themselves.
-%
 % \begin{macro}{\exp_args:Nx}
 %    \begin{macrocode}
-\cs_new_protected:Npn \exp_args:Nx { \::x \::: }
+\cs_new_protected:Npn \exp_args:Nx #1#2
+  { \use:x { \exp_not:N #1 {#2} } }
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[EXP]
-%   {
-%     \exp_args:Nnc, \exp_args:Nno, \exp_args:NnV, \exp_args:Nnv, \exp_args:Nne, \exp_args:Nnf,
-%     \exp_args:Noc, \exp_args:Noo, \exp_args:Nof,
-%     \exp_args:NVo, \exp_args:Nfo, \exp_args:Nff,
-%   }
-% \begin{macro}
-%   {
-%     \exp_args:NNx, \exp_args:Ncx, \exp_args:Nnx,
-%     \exp_args:Nox, \exp_args:Nxo, \exp_args:Nxx,
-%   }
-%   Here are the actual function definitions, using the helper functions
-%   above.
-%    \begin{macrocode}
-\cs_new:Npn \exp_args:Nnc { \::n \::c \::: }
-\cs_new:Npn \exp_args:Nno { \::n \::o \::: }
-\cs_new:Npn \exp_args:NnV { \::n \::V \::: }
-\cs_new:Npn \exp_args:Nnv { \::n \::v \::: }
-\cs_new:Npn \exp_args:Nne { \::n \::e \::: }
-\cs_new:Npn \exp_args:Nnf { \::n \::f \::: }
-\cs_new:Npn \exp_args:Noc { \::o \::c \::: }
-\cs_new:Npn \exp_args:Noo { \::o \::o \::: }
-\cs_new:Npn \exp_args:Nof { \::o \::f \::: }
-\cs_new:Npn \exp_args:NVo { \::V \::o \::: }
-\cs_new:Npn \exp_args:Nfo { \::f \::o \::: }
-\cs_new:Npn \exp_args:Nff { \::f \::f \::: }
-\cs_new_protected:Npn \exp_args:NNx { \::N \::x \::: }
-\cs_new_protected:Npn \exp_args:Ncx { \::c \::x \::: }
-\cs_new_protected:Npn \exp_args:Nnx { \::n \::x \::: }
-\cs_new_protected:Npn \exp_args:Nox { \::o \::x \::: }
-\cs_new_protected:Npn \exp_args:Nxo { \::x \::o \::: }
-\cs_new_protected:Npn \exp_args:Nxx { \::x \::x \::: }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
-% \begin{macro}[EXP]
-%   {
-%     \exp_args:NNNv, \exp_args:NNcf,
-%     \exp_args:NNno, \exp_args:NNnV, \exp_args:NNoo, \exp_args:NNVV,
-%     \exp_args:Ncno, \exp_args:NcnV, \exp_args:Ncoo, \exp_args:NcVV,
-%     \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nnnf, \exp_args:Nnff,
-%     \exp_args:Nooo, \exp_args:Noof, \exp_args:Nffo,
-%   }
-% \begin{macro}
-%   {
-%     \exp_args:NNNx, \exp_args:NNnx, \exp_args:NNox,
-%     \exp_args:Nccx, \exp_args:Ncnx,
-%     \exp_args:Nnnx, \exp_args:Nnox, \exp_args:Noox,
-%   }
-%    \begin{macrocode}
-\cs_new:Npn \exp_args:NNNv { \::N \::N \::v \::: }
-\cs_new:Npn \exp_args:NNcf { \::N \::c \::f \::: }
-\cs_new:Npn \exp_args:NNno { \::N \::n \::o \::: }
-\cs_new:Npn \exp_args:NNnV { \::N \::n \::V \::: }
-\cs_new:Npn \exp_args:NNoo { \::N \::o \::o \::: }
-\cs_new:Npn \exp_args:NNVV { \::N \::V \::V \::: }
-\cs_new:Npn \exp_args:Ncno { \::c \::n \::o \::: }
-\cs_new:Npn \exp_args:NcnV { \::c \::n \::V \::: }
-\cs_new:Npn \exp_args:Ncoo { \::c \::o \::o \::: }
-\cs_new:Npn \exp_args:NcVV { \::c \::V \::V \::: }
-\cs_new:Npn \exp_args:Nnnc { \::n \::n \::c \::: }
-\cs_new:Npn \exp_args:Nnno { \::n \::n \::o \::: }
-\cs_new:Npn \exp_args:Nnnf { \::n \::n \::f \::: }
-\cs_new:Npn \exp_args:Nnff { \::n \::f \::f \::: }
-\cs_new:Npn \exp_args:Nooo { \::o \::o \::o \::: }
-\cs_new:Npn \exp_args:Noof { \::o \::o \::f \::: }
-\cs_new:Npn \exp_args:Nffo { \::f \::f \::o \::: }
-\cs_new_protected:Npn \exp_args:NNNx { \::N \::N \::x \::: }
-\cs_new_protected:Npn \exp_args:NNnx { \::N \::n \::x \::: }
-\cs_new_protected:Npn \exp_args:NNox { \::N \::o \::x \::: }
-\cs_new_protected:Npn \exp_args:Nnnx { \::n \::n \::x \::: }
-\cs_new_protected:Npn \exp_args:Nnox { \::n \::o \::x \::: }
-\cs_new_protected:Npn \exp_args:Nccx { \::c \::c \::x \::: }
-\cs_new_protected:Npn \exp_args:Ncnx { \::c \::n \::x \::: }
-\cs_new_protected:Npn \exp_args:Noox { \::o \::o \::x \::: }
-%    \end{macrocode}
-% \end{macro}
-% \end{macro}
-%
 % \subsection{Last-unbraced versions}
 %
 % \begin{macro}[EXP]{\@@_arg_last_unbraced:nn}
@@ -2263,7 +2177,6 @@
 %   iterate through the comma list of variant argument specifiers, which
 %   we first convert to a string: the reason is explained later.
 %    \begin{macrocode}
-\__kernel_patch:nnNNpn { \__kernel_chk_cs_exist:N #1 } { }
 \cs_new_protected:Npn \cs_generate_variant:Nn #1#2
   {
     \@@_generate_variant:N #1
@@ -2598,9 +2511,9 @@
 %    \begin{macrocode}
 \cs_new:Npn \@@_generate_variant_same:N #1
   {
-    \if:w N #1 N \else:
-      \if:w p #1 p \else:
-        n
+    \if:w N #1 #1 \else:
+      \if:w p #1 #1 \else:
+        \token_to_str:N n
         \if:w n #1 \else:
           \@@_generate_variant_loop_special:NNwNNnn #1#1
         \fi:
@@ -2618,18 +2531,6 @@
 %   \cs{cs_new_protected:Npx}.  Then define the variant by
 %   combining the |\exp_args:N #3| variant and the base function.
 %    \begin{macrocode}
-\__kernel_patch:nnNNpn
-  {
-    \cs_if_free:NF #4
-      {
-        \__kernel_debug_log:x
-          {
-            Variant~\token_to_str:N #4~%
-            already~defined;~ not~ changing~ it~ \msg_line_context:
-          }
-      }
-  }
-  { }
 \cs_new_protected:Npn \@@_generate_variant:wwNN
     #1 \q_mark #2 \q_stop #3#4
   {
@@ -2646,38 +2547,129 @@
 % \end{macro}
 %
 % \begin{macro}{\@@_generate_internal_variant:n}
-% \begin{macro}{\@@_generate_internal_variant:wwnw}
 % \begin{macro}[rEXP]{\@@_generate_internal_variant_loop:n}
-%   Test if |\exp_args:N #1| is already defined and if not define it via
-%   the |\::| commands using the chars in |#1|.  If |#1| contains an |x|
-%   (this is the place where having converted the original comma-list
-%   argument to a string is very important), the result should be
-%   protected, and the next variant to be defined using that internal
-%   variant should be protected.
+%   First test for the presence of |x| (this is where working with
+%   strings makes our lives easier), as the result should be protected,
+%   and the next variant to be defined using that internal variant
+%   should be protected (done by setting \cs{@@_tmp:w}).  Then call
+%   \cs{@@_generate_internal_variant:NNn} with arguments
+%   \cs{cs_new_protected:cpn} \cs{use:x} (for protected) or
+%   \cs{cs_new:cpn} \cs{tex_expanded:D} (expandable) and the signature.  If |p|
+%   appears in the signature, or if the function to be defined is
+%   expandable and the primitive \tn{expanded} is not available, call
+%   some fall-back code that just puts the appropriate |\::| commands.
+%   Otherwise, call \cs{@@_generate_internal_one_go:NNn} to construct
+%   the \cs[no-index]{exp_args:N\dots} function as a macro taking up to
+%   $9$~arguments and expanding them using \cs{use:x} or \cs{tex_expanded:D}.
 %    \begin{macrocode}
 \cs_new_protected:Npx \@@_generate_internal_variant:n #1
   {
-    \exp_not:N \@@_generate_internal_variant:wwnNwnn
+    \exp_not:N \@@_generate_internal_variant:wwnNwn
       #1 \exp_not:N \q_mark
         { \cs_set_eq:NN \exp_not:N \@@_tmp:w \cs_new_protected:Npx }
-        \cs_new_protected:cpx
+        \cs_new_protected:cpn
+        \use:x
       \token_to_str:N x \exp_not:N \q_mark
         { }
-        \cs_new:cpx
+        \cs_new:cpn
+        \exp_not:N \tex_expanded:D
     \exp_not:N \q_stop
-      { exp_args:N #1 }
-      {
-        \exp_not:N \@@_generate_internal_variant_loop:n #1
-          { : \exp_not:N \use_i:nn }
-      }
+      {#1}
   }
 \exp_last_unbraced:NNNNo
-  \cs_new_protected:Npn \@@_generate_internal_variant:wwnNwnn #1
-    { \token_to_str:N x } #2 \q_mark #3#4#5 \q_stop #6#7
+  \cs_new_protected:Npn \@@_generate_internal_variant:wwnNwn #1
+    { \token_to_str:N x } #2 \q_mark #3#4#5#6 \q_stop #7
   {
     #3
-    \cs_if_free:cT {#6} { #4 {#6} {#7} }
+    \cs_if_free:cT { exp_args:N #7 }
+      { \@@_generate_internal_variant:NNn #4 #5 {#7} }
   }
+\cs_set_protected:Npn \@@_tmp:w #1
+  {
+    \cs_new_protected:Npn \@@_generate_internal_variant:NNn ##1##2##3
+      {
+        \@@_generate_internal_test:Nw ##2 ##3
+        \q_mark
+        {
+          \use:x
+            {
+              ##1 { exp_args:N ##3 }
+                { \@@_generate_internal_variant_loop:n ##3 { : \use_i:nn } }
+            }
+        }
+        #1
+        \q_mark
+        { \exp_not:n { \@@_generate_internal_one_go:NNn ##1 ##2 {##3} } }
+        \q_stop
+      }
+    \cs_new_protected:Npn \@@_generate_internal_test_aux:w
+        ##1 #1 ##2 \q_mark ##3 ##4 \q_stop {##3}
+    \cs_if_exist:NTF \tex_expanded:D
+      {
+        \cs_new_eq:NN \@@_generate_internal_test:Nw
+          \@@_generate_internal_test_aux:w
+      }
+      {
+        \cs_new_protected:Npn \@@_generate_internal_test:Nw ##1
+          {
+            \if_meaning:w \tex_expanded:D ##1
+              \exp_after:wN \@@_generate_internal_test_aux:w
+              \exp_after:wN #1
+            \else:
+              \exp_after:wN \@@_generate_internal_test_aux:w
+            \fi:
+          }
+      }
+  }
+\exp_args:No \@@_tmp:w { \token_to_str:N p }
+\cs_new_protected:Npn \@@_generate_internal_one_go:NNn #1#2#3
+  {
+    \@@_generate_internal_loop:nwnnw
+      { \exp_not:N ##1 } 1 . { } { }
+      #3 { ? \@@_generate_internal_end:w } X ;
+      23456789 { ? \@@_generate_internal_long:w } ;
+    #1 #2 {#3}
+  }
+\cs_new_protected:Npn \@@_generate_internal_loop:nwnnw #1#2 . #3#4#5#6 ; #7
+  {
+    \use_none:n #5
+    \use_none:n #7
+    \cs_if_exist_use:cF { @@_generate_internal_#5:NN }
+      { \@@_generate_internal_other:NN }
+        #5 #7
+    #7 .
+    { #3 #1 } { #4 ## #2 }
+    #6 ;
+  }
+\cs_new_protected:Npn \@@_generate_internal_N:NN #1#2
+  { \@@_generate_internal_loop:nwnnw { \exp_not:N ###2 } }
+\cs_new_protected:Npn \@@_generate_internal_c:NN #1#2
+  { \exp_args:No \@@_generate_internal_loop:nwnnw { \exp_not:c {###2} } }
+\cs_new_protected:Npn \@@_generate_internal_n:NN #1#2
+  { \@@_generate_internal_loop:nwnnw { { \exp_not:n {###2} } } }
+\cs_new_protected:Npn \@@_generate_internal_x:NN #1#2
+  { \@@_generate_internal_loop:nwnnw { {###2} } }
+\cs_new_protected:Npn \@@_generate_internal_other:NN #1#2
+  {
+    \exp_args:No \@@_generate_internal_loop:nwnnw
+      {
+        \exp_after:wN
+        {
+          \exp:w \exp_args:NNc \exp_after:wN \exp_end:
+          { exp_not:#1 } {###2}
+        }
+      }
+  }
+\cs_new_protected:Npn \@@_generate_internal_end:w #1 . #2#3#4 ; #5 ; #6#7#8
+  { #6 { exp_args:N #8 } #3 { #7 {#2} } }
+\cs_new_protected:Npn \@@_generate_internal_long:w #1 N #2#3 . #4#5#6#
+  {
+    \exp_args:Nx \@@_generate_internal_long:nnnNNn
+      { \@@_generate_internal_variant_loop:n #2 #6 { : \use_i:nn } }
+      {#4} {#5}
+  }
+\cs_new:Npn \@@_generate_internal_long:nnnNNn #1#2#3#4 ; ; #5#6#7
+  { #5 { exp_args:N #7 } #3 { #6 { \exp_not:n {#1} {#2} } } }
 %    \end{macrocode}
 %   This command grabs char by char outputting |\::#1| (not expanded
 %   further).  We avoid tests by putting a trailing |: \use_i:nn|, which
@@ -2693,7 +2685,6 @@
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
-% \end{macro}
 %
 % \begin{macro}
 %   {
@@ -2756,15 +2747,12 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}{\exp_args_generate:n, \@@_args_generate:Nn}
-% \begin{macro}[EXP]{\@@_args_generate:n}
+% \begin{macro}{\exp_args_generate:n}
 %   This function is not used in the kernel hence we can use functions
 %   that are defined in later modules.  It also does not need to be fast
 %   so use inline mappings.  For each requested variant we check that
 %   there are no characters besides |NnpcofVvx|, in particular that
-%   there are no spaces.  Then we loop through the variant specifier and
-%   convert each letter to \cs[no-index]{::\meta{variant letter}}, with a
-%   trailing \cs{:::}.
+%   there are no spaces.  Then we just call the internal function.
 %    \begin{macrocode}
 \cs_new_protected:Npn \exp_args_generate:n #1
   {
@@ -2776,21 +2764,105 @@
               {
                 \__kernel_msg_error:nnnn { kernel } { invalid-exp-args }
                   {####1} {##1}
-                \str_map_break:n { \use_none:nnnn }
+                \str_map_break:n { \use_none:nn }
               }
           }
-        \exp_args:Nc \@@_args_generate:Nn { exp_args:N ##1 } {##1}
+        \@@_generate_internal_variant:n {##1}
       }
   }
-\cs_new_protected:Npn \@@_args_generate:Nn #1#2
-  {
-    \cs_if_exist:NF #1
-      {
-        \str_if_in:nnTF {#2} { x } { \cs_new_protected:Npx } { \cs_new:Npx }
-          #1 { \tl_map_function:nN { #2 : } \@@_args_generate:n }
-      }
-  }
-\cs_new:Npn \@@_args_generate:n #1 { \exp_not:c { :: #1 } }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Definitions with the automated technique}
+% \label{sec:l3expan:gendef}
+%
+% Some of these could be done more efficiently, but the complexity of
+% coding then becomes an issue. Notice that the auto-generated functions
+% actually take no arguments themselves.
+%
+% \begin{macro}[EXP]
+%   {
+%     \exp_args:Nnc, \exp_args:Nno, \exp_args:NnV, \exp_args:Nnv, \exp_args:Nne, \exp_args:Nnf,
+%     \exp_args:Noc, \exp_args:Noo, \exp_args:Nof,
+%     \exp_args:NVo, \exp_args:Nfo, \exp_args:Nff,
+%   }
+% \begin{macro}
+%   {
+%     \exp_args:NNx, \exp_args:Ncx, \exp_args:Nnx,
+%     \exp_args:Nox, \exp_args:Nxo, \exp_args:Nxx,
+%   }
+%   Here are the actual function definitions, using the helper
+%   functions above.  The group is used because
+%   \cs{@@_generate_internal_variant:n} redefines \cs{@@_tmp:w} locally.
+%    \begin{macrocode}
+\cs_set_protected:Npn \@@_tmp:w #1
+  {
+    \group_begin:
+      \exp_args:No \@@_generate_internal_variant:n
+        { \tl_to_str:n {#1} }
+    \group_end:
+  }
+\@@_tmp:w { nc }
+\@@_tmp:w { no }
+\@@_tmp:w { nV }
+\@@_tmp:w { nv }
+\@@_tmp:w { ne }
+\@@_tmp:w { nf }
+\@@_tmp:w { oc }
+\@@_tmp:w { oo }
+\@@_tmp:w { of }
+\@@_tmp:w { Vo }
+\@@_tmp:w { fo }
+\@@_tmp:w { ff }
+\@@_tmp:w { Nx }
+\@@_tmp:w { cx }
+\@@_tmp:w { nx }
+\@@_tmp:w { ox }
+\@@_tmp:w { xo }
+\@@_tmp:w { xx }
+%    \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}[EXP]
+%   {
+%     \exp_args:NNcf,
+%     \exp_args:NNno, \exp_args:NNnV, \exp_args:NNoo, \exp_args:NNVV,
+%     \exp_args:Ncno, \exp_args:NcnV, \exp_args:Ncoo, \exp_args:NcVV,
+%     \exp_args:Nnnc, \exp_args:Nnno, \exp_args:Nnnf, \exp_args:Nnff,
+%     \exp_args:Nooo, \exp_args:Noof, \exp_args:Nffo,
+%   }
+% \begin{macro}
+%   {
+%     \exp_args:NNNx, \exp_args:NNnx, \exp_args:NNox,
+%     \exp_args:Nccx, \exp_args:Ncnx,
+%     \exp_args:Nnnx, \exp_args:Nnox, \exp_args:Noox,
+%   }
+%    \begin{macrocode}
+\@@_tmp:w { Ncf }
+\@@_tmp:w { Nno }
+\@@_tmp:w { NnV }
+\@@_tmp:w { Noo }
+\@@_tmp:w { NVV }
+\@@_tmp:w { cno }
+\@@_tmp:w { cnV }
+\@@_tmp:w { coo }
+\@@_tmp:w { cVV }
+\@@_tmp:w { nnc }
+\@@_tmp:w { nno }
+\@@_tmp:w { nnf }
+\@@_tmp:w { nff }
+\@@_tmp:w { ooo }
+\@@_tmp:w { oof }
+\@@_tmp:w { ffo }
+\@@_tmp:w { NNx }
+\@@_tmp:w { Nnx }
+\@@_tmp:w { Nox }
+\@@_tmp:w { nnx }
+\@@_tmp:w { nox }
+\@@_tmp:w { ccx }
+\@@_tmp:w { cnx }
+\@@_tmp:w { oox }
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
-- 
cgit v1.2.3

