[latex3-commits] [git/LaTeX3-latex3-latex3] main: Enable \char_generate:nn to deal with \outer tokens (d1001f273)

Joseph Wright joseph.wright at morningstar2.co.uk
Sun Jan 1 10:25:03 CET 2023


Repository : https://github.com/latex3/latex3
On branch  : main
Link       : https://github.com/latex3/latex3/commit/d1001f2738cf1423e50486707def96166024361d

>---------------------------------------------------------------

commit d1001f2738cf1423e50486707def96166024361d
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Sun Jan 1 09:15:40 2023 +0000

    Enable \char_generate:nn to deal with \outer tokens
    
    See https://tex.stackexchange.com/q/669877


>---------------------------------------------------------------

d1001f2738cf1423e50486707def96166024361d
 l3kernel/CHANGELOG.md                   |  4 ++
 l3kernel/l3token.dtx                    | 99 ++++++++++++++++-----------------
 l3kernel/testfiles/m3char001.luatex.tlg |  6 ++
 l3kernel/testfiles/m3char001.lvt        | 15 ++++-
 l3kernel/testfiles/m3char001.tlg        |  6 ++
 l3kernel/testfiles/m3char001.xetex.tlg  |  6 ++
 6 files changed, 83 insertions(+), 53 deletions(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index 7952d0343..63cca888d 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -7,6 +7,10 @@ this project uses date-based 'snapshot' version identifiers.
 
 ## [Unreleased]
 
+### Fixed
+- Enable `\char_generate:nn` to create active tokens which are `\outer`
+  or equal to `\fi`
+
 ## [2022-12-17]
 
 ### Added
diff --git a/l3kernel/l3token.dtx b/l3kernel/l3token.dtx
index 6fa3508c4..a06a82178 100644
--- a/l3kernel/l3token.dtx
+++ b/l3kernel/l3token.dtx
@@ -2,7 +2,7 @@
 %
 %% File: l3token.dtx
 %
-% Copyright (C) 2005-2022 The LaTeX Project
+% Copyright (C) 2005-2023 The LaTeX Project
 %
 % It may be distributed and/or modified under the conditions of the
 % LaTeX Project Public License (LPPL), either version 1.3c of this
@@ -1571,9 +1571,6 @@
 %   auxiliaries reflects that.
 %    \begin{macrocode}
 \group_begin:
-  \char_set_catcode_active:N \^^L
-  \cs_set:Npn ^^L { }
-  \char_set_catcode_other:n { 0 }
   \if_int_odd:w 0
       \sys_if_engine_luatex:T { 1 }
       \sys_if_engine_xetex:T { 1 } \exp_stop_f:
@@ -1604,48 +1601,45 @@
 %   to build up a |tl| containing |^^@| with each category code that can
 %   be accessed in this way, with an error set up for the other cases. This
 %   is all done such that it can be quickly accessed using a |\if_case:w|
-%   low-level conditional. There are a few things to notice here.
-%   As |^^L| is |\outer| we need to locally set it to avoid a problem.
-%   To get open/close braces into the list, they are set up using |\if_false:|
-%   pairing and are then |x|-type expanded together into the desired form.
-%    \begin{macrocode}
-      \tl_set:Nn \l_@@_tmp_tl { \exp_not:N \or: }
-      \char_set_catcode_group_begin:n { 0 } % {
-      \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \if_false: } }
-      \char_set_catcode_group_end:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { { \fi: \exp_not:N \or: ^^@ } % }
-      \__kernel_tl_set:Nx \l_@@_tmp_tl { \l_@@_tmp_tl }
-      \char_set_catcode_math_toggle:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \char_set_catcode_alignment:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: }
-      \char_set_catcode_parameter:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \char_set_catcode_math_superscript:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \char_set_catcode_math_subscript:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: }
-%    \end{macrocode}
+%   low-level conditional. The list is done in reverse as this puts the case
+%   of an active token \emph{first}: that's needed to cover the possibility
+%   that it is \tn{outer}. Getting the braces into the list is done using
+%   some standard \cs{if_false:} manipulation, while all of the \cs{exp_not:N}
+%   are required as there is an expansion in the setup.
+%    \begin{macrocode}
+    \char_set_catcode_active:N \^^L
+    \cs_set:Npn ^^L { }
+    \char_set_catcode_active:n { 0 }
+    \tl_set:Nn \l_@@_tmp_tl { \exp_not:N ^^@ \exp_not:N \or: }
+    \char_set_catcode_other:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
+    \char_set_catcode_letter:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
 %   For making spaces, there needs to be an |o|-type expansion of a |\use:n|
 %   (or some other tokenization) to avoid dropping the space.
 %    \begin{macrocode}
-      \char_set_catcode_space:n { 0 }
-      \tl_put_right:No \l_@@_tmp_tl { \use:n { \or: } ^^@ }
-      \char_set_catcode_letter:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \char_set_catcode_other:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
-      \char_set_catcode_active:n { 0 }
-      \tl_put_right:Nn \l_@@_tmp_tl { \or: ^^@ }
+    \tl_put_right:Nn \l_@@_tmp_tl { \use:n { ~ } \exp_not:N \or: }
+    \tl_put_right:Nn \l_@@_tmp_tl { \exp_not:N \or: }
+    \char_set_catcode_math_subscript:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
+    \char_set_catcode_math_superscript:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
+    \char_set_catcode_parameter:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@^^@ \exp_not:N \or: }
+    \tl_put_right:Nn \l_@@_tmp_tl { { \if_false: } \fi: \exp_not:N \or: }
+    \char_set_catcode_alignment:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
+    \char_set_catcode_math_toggle:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: }
+    \char_set_catcode_group_end:n { 0 }
+    \tl_put_right:Nn \l_@@_tmp_tl { \if_false: { \fi: ^^@ \exp_not:N \or: } % }
+    \char_set_catcode_group_begin:n { 0 } % {
+    \tl_put_right:Nn \l_@@_tmp_tl { ^^@ \exp_not:N \or: } }
 %    \end{macrocode}
 %   Convert the above temporary list into a series of constant token
 %   lists, one for each character code, using \cs{tex_lowercase:D} to
 %   convert |^^@| in each case. The \texttt{x}-type expansion ensures
 %   that \cs{tex_lowercase:D} receives the contents of the token list.
-%   |^^L| is awkward hence this is done in three parts: up to |^^L|,
-%   |^^L| itslef and above |^L|. Notice that at this stage |^^@| is active.
 %    \begin{macrocode}
       \cs_set_protected:Npn \@@_tmp:n #1
         {
@@ -1653,34 +1647,35 @@
           \char_set_lccode:nn { 32 } {#1}
           \exp_args:Nx \tex_lowercase:D
             {
-              \tl_const:Nn
+              \tl_const:Nx
                 \exp_not:c { c_@@_ \@@_int_to_roman:w #1 _tl }
                 { \exp_not:o \l_@@_tmp_tl }
             }
         }
-      \int_step_function:nnN { 0 } { 11 }  \@@_tmp:n
-      \group_begin:
-        \tl_replace_once:Nnn \l_@@_tmp_tl { ^^@ } { \ERROR }
-        \@@_tmp:n { 12 }
-      \group_end:
-      \int_step_function:nnN { 13 } { 255 } \@@_tmp:n
+      \int_step_function:nnN { 0 } { 255 }  \@@_tmp:n
 %    \end{macrocode}
 %   As \TeX{} is very unhappy if it finds an alignment character inside
 %   a primitive \tn{halign} even when skipping false branches, some
 %   precautions are required. \TeX{} is happy if the token is hidden
-%   between braces within \cs{if_false:} \dots{} \cs{fi:}.
+%   between braces within \cs{if_false:} \dots{} \cs{fi:}. The
+%   rather low-level approach here expands in one step to the
+%   \meta{target token} (\cs{or:} \dots{}), then \cs{exp_after:wN}
+%   \meta{target token} (\cs{or:} \dots{}) expands in one step to
+%   \meta{target token}. This means that \cs{exp_not:N} is applied to
+%   a potentially-problematic active token.
 %    \begin{macrocode}
       \cs_new:Npn \@@_generate_aux:nnw #1#2#3 \exp_end:
         {
           #3
           \if_false: { \fi:
+          \exp_after:wN \exp_after:wN \exp_after:wN \exp_end:
           \exp_after:wN \exp_after:wN
-          \exp_after:wN \exp_end:
-          \exp_after:wN \exp_after:wN
-          \if_case:w #2
-            \exp_last_unbraced:Nv \exp_stop_f:
-              { c_@@_ \@@_int_to_roman:w #1 _tl }
-          \or: }
+          \if_case:w \tex_numexpr:D 13 - #2
+            \exp_after:wN \exp_after:wN \exp_after:wN \exp_after:wN
+            \exp_after:wN \exp_after:wN \exp_after:wN \scan_stop:
+            \exp_after:wN \exp_after:wN \exp_after:wN \exp_not:N
+              \cs:w c_@@_ \@@_int_to_roman:w #1 _tl \cs_end:
+          }
           \fi:
         }
   \fi:
diff --git a/l3kernel/testfiles/m3char001.luatex.tlg b/l3kernel/testfiles/m3char001.luatex.tlg
index 88fe75c50..3f0701872 100644
--- a/l3kernel/testfiles/m3char001.luatex.tlg
+++ b/l3kernel/testfiles/m3char001.luatex.tlg
@@ -502,3 +502,9 @@ the letter A
 the character A
 undefined
 ============================================================
+============================================================
+TEST 8: Difficult actives
+============================================================
+\outer macro:->outer Q
+\fi
+============================================================
diff --git a/l3kernel/testfiles/m3char001.lvt b/l3kernel/testfiles/m3char001.lvt
index 24e770d62..d5390f34a 100644
--- a/l3kernel/testfiles/m3char001.lvt
+++ b/l3kernel/testfiles/m3char001.lvt
@@ -1,5 +1,5 @@
 %
-% Copyright (C) 2015,2016,2018-2021 The LaTeX Project
+% Copyright (C) 2015,2016,2018-2021,2023 The LaTeX Project
 %
 \documentclass{minimal}
 \input{regression-test}
@@ -165,4 +165,17 @@
     \test:nn { 65 } { 13 }
   }
 
+\OMIT
+  \char_set_catcode_active:n { `\Q }
+  \char_set_catcode_active:n { `\Z }
+  \outer\def Q { outer~Q }
+  \cs_set_eq:NN Z \fi
+\TIMO
+
+\TESTEXP { Difficult~actives }
+  {
+    \test:nn { `\Q } { 13 }
+    \test:nn { `\Z } { 13 }
+  }
+
 \END
diff --git a/l3kernel/testfiles/m3char001.tlg b/l3kernel/testfiles/m3char001.tlg
index a60895277..e23607996 100644
--- a/l3kernel/testfiles/m3char001.tlg
+++ b/l3kernel/testfiles/m3char001.tlg
@@ -531,3 +531,9 @@ the letter A
 the character A
 undefined
 ============================================================
+============================================================
+TEST 8: Difficult actives
+============================================================
+\outer macro:->outer Q
+\fi
+============================================================
diff --git a/l3kernel/testfiles/m3char001.xetex.tlg b/l3kernel/testfiles/m3char001.xetex.tlg
index ae1b61283..87ecdf3db 100644
--- a/l3kernel/testfiles/m3char001.xetex.tlg
+++ b/l3kernel/testfiles/m3char001.xetex.tlg
@@ -502,3 +502,9 @@ the letter A
 the character A
 undefined
 ============================================================
+============================================================
+TEST 8: Difficult actives
+============================================================
+\outer macro:->outer Q
+\fi
+============================================================





More information about the latex3-commits mailing list.