[latex3-commits] [git/LaTeX3-latex3-latex3] main: Use scanmark not quark for \text_expand:n loop (0404bfcf5)

Joseph Wright joseph.wright at morningstar2.co.uk
Fri Aug 5 15:39:00 CEST 2022


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

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

commit 0404bfcf5780254476f1a614aefb19eac41de527
Author: Joseph Wright <joseph.wright at morningstar2.co.uk>
Date:   Fri Aug 5 14:39:00 2022 +0100

    Use scanmark not quark for \text_expand:n loop
    
    This is needed as it means \romannumeral will correctly
    terminate even if given without a proper end.
    
    Other loops are left unchanged: this means we do
    not have a slower test for *all* loop ends and
    means the outer loop is differentiated.


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

0404bfcf5780254476f1a614aefb19eac41de527
 l3kernel/CHANGELOG.md            |  1 +
 l3kernel/l3text.dtx              | 60 +++++++++++++++++++++++++++++++---------
 l3kernel/testfiles/m3text001.lvt |  5 ++++
 l3kernel/testfiles/m3text001.tlg |  7 +++++
 4 files changed, 60 insertions(+), 13 deletions(-)

diff --git a/l3kernel/CHANGELOG.md b/l3kernel/CHANGELOG.md
index 3a4e44ad3..9fcaa43d5 100644
--- a/l3kernel/CHANGELOG.md
+++ b/l3kernel/CHANGELOG.md
@@ -14,6 +14,7 @@ this project uses date-based 'snapshot' version identifiers.
 
 ### Fixed
 - Behavior of `\color_math:nn` in alignments
+- Expansion of text containing unterminated `\romannumeral` primitives
 
 ## [2022-07-21]
 
diff --git a/l3kernel/l3text.dtx b/l3kernel/l3text.dtx
index c99c3e6bf..7bba36eff 100644
--- a/l3kernel/l3text.dtx
+++ b/l3kernel/l3text.dtx
@@ -363,6 +363,38 @@
 %    \end{macrocode}
 % \end{macro}
 %
+% \begin{variable}{\s_@@_recursion_tail,\s_@@_recursion_stop}
+%   Internal scan marks quarks.
+%    \begin{macrocode}
+\scan_new:N \s_@@_recursion_tail
+\scan_new:N \s_@@_recursion_stop
+%    \end{macrocode}
+% \end{variable}
+%
+% \begin{macro}[EXP]{\@@_use_i_delimit_by_s_recursion_stop:nw}
+%   Functions to gobble up to a scan mark.
+%    \begin{macrocode}
+\cs_new:Npn \@@_use_i_delimit_by_s_recursion_stop:nw
+  #1 #2 \s_@@_recursion_stop {#1}
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[EXP]{\@@_if_s_recursion_tail_stop_do:Nn}
+%   Functions to query recursion scan marks. Slower than a quark
+%   test but needed to avoid issues in the outer expansion loop
+%   with unterminated \tn{romannumeral} primitives.
+%    \begin{macrocode}
+\cs_new:Npn \@@_if_s_recursion_tail_stop_do:Nn #1
+  {
+    \bool_lazy_and:nnTF
+      { \cs_if_eq_p:NN \s_@@_recursion_tail #1 }
+      { \str_if_eq_p:nn { \s_@@_recursion_tail } {#1} }
+      { \@@_use_i_delimit_by_s_recursion_stop:nw }
+      { \use_none:n }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
 % \subsection{Utilities}
 %
 % \begin{macro}[EXP]
@@ -732,7 +764,9 @@
 %   arbitrary user commands which might be protected \emph{and} take
 %   arguments, and if the expansion code is used in a typesetting
 %   context, that will otherwise explode. (The same issue applies more
-%   clearly to case changing: see the example there.)
+%   clearly to case changing: see the example there.) The outer
+%   loop has to use scan marks as delimiters to protect against
+%   unterminated \tn{romannumeral} usage in the input.
 %    \begin{macrocode}
 \cs_new:Npn \text_expand:n #1
   {
@@ -746,7 +780,7 @@
   {
     \group_align_safe_begin:
     \@@_expand_loop:w #1
-      \q_@@_recursion_tail \q_@@_recursion_stop
+      \s_@@_recursion_tail \s_@@_recursion_stop
     \@@_expand_result:n { }
   }
 %    \end{macrocode}
@@ -769,7 +803,7 @@
 %   recursively, while spaces are just passed through. Thus all of the
 %   action is in handling \texttt{N}-type tokens.
 %    \begin{macrocode}
-\cs_new:Npn \@@_expand_loop:w #1 \q_@@_recursion_stop
+\cs_new:Npn \@@_expand_loop:w #1 \s_@@_recursion_stop
   {
     \tl_if_head_is_N_type:nTF {#1}
       { \@@_expand_N_type:N }
@@ -778,7 +812,7 @@
           { \@@_expand_group:n }
           { \@@_expand_space:w }
       }
-    #1 \q_@@_recursion_stop
+    #1 \s_@@_recursion_stop
   }
 \cs_new:Npn \@@_expand_group:n #1
   {
@@ -806,7 +840,7 @@
 %    \begin{macrocode}
 \cs_new:Npx \@@_expand_N_type:N #1
   {
-    \exp_not:N \@@_if_q_recursion_tail_stop_do:Nn #1
+    \exp_not:N \@@_if_s_recursion_tail_stop_do:Nn #1
       { \exp_not:N \@@_expand_end:w }
     \exp_not:N \bool_lazy_any:nTF
       {
@@ -897,7 +931,7 @@
       }
       { \@@_expand_math_search:NNN #1 }
   }
-\cs_new:Npn \@@_expand_math_loop:Nw #1#2 \q_@@_recursion_stop
+\cs_new:Npn \@@_expand_math_loop:Nw #1#2 \s_@@_recursion_stop
   {
     \tl_if_head_is_N_type:nTF {#2}
       { \@@_expand_math_N_type:NN }
@@ -906,11 +940,11 @@
           { \@@_expand_math_group:Nn }
           { \@@_expand_math_space:Nw }
       }
-    #1#2 \q_@@_recursion_stop
+    #1#2 \s_@@_recursion_stop
   }
 \cs_new:Npn \@@_expand_math_N_type:NN #1#2
   {
-    \@@_if_q_recursion_tail_stop_do:Nn #2
+    \@@_if_s_recursion_tail_stop_do:Nn #2
       { \@@_expand_end:w }
     \@@_expand_store:n {#2}
     \token_if_eq_meaning:NNTF #2 #1
@@ -1073,7 +1107,7 @@
           { \exp_not:N \@@_expand_replace:N #1 }
       }
   }
-\cs_new:Npn \@@_expand_protect:w #1 \q_@@_recursion_stop
+\cs_new:Npn \@@_expand_protect:w #1 \s_@@_recursion_stop
   {
     \tl_if_head_is_N_type:nTF {#1}
       { \@@_expand_protect:N }
@@ -1081,11 +1115,11 @@
         \@@_expand_store:n { \protect }
         \@@_expand_loop:w
       }
-        #1 \q_@@_recursion_stop
+        #1 \s_@@_recursion_stop
   }
 \cs_new:Npn \@@_expand_protect:N #1
   {
-    \@@_if_q_recursion_tail_stop_do:Nn #1
+    \@@_if_s_recursion_tail_stop_do:Nn #1
       {
         \@@_expand_store:n { \protect }
         \@@_expand_end:w
@@ -1187,7 +1221,7 @@
     \exp_after:wN \@@_expand_unexpanded_test:w
     \exp:w \exp_end_continue_f:w
   }
-\cs_new:Npn \@@_expand_unexpanded_test:w #1 \q_@@_recursion_stop
+\cs_new:Npn \@@_expand_unexpanded_test:w #1 \s_@@_recursion_stop
   {
     \tl_if_head_is_group:nTF {#1}
       { \@@_expand_unexpanded:n }
@@ -1195,7 +1229,7 @@
         \@@_expand_unexpanded:w
         \tl_if_head_is_N_type:nT {#1} { \@@_expand_unexpanded:N }
       }
-    #1 \q_@@_recursion_stop
+    #1 \s_@@_recursion_stop
   }
 \cs_new:Npn \@@_expand_unexpanded:N #1
   {
diff --git a/l3kernel/testfiles/m3text001.lvt b/l3kernel/testfiles/m3text001.lvt
index adccfb8e5..22b79d388 100644
--- a/l3kernel/testfiles/m3text001.lvt
+++ b/l3kernel/testfiles/m3text001.lvt
@@ -110,4 +110,9 @@
     \tl_show:x { \text_expand:n { \protect { ab } } }
   }
 
+\TEST { Non-terminated~\romannumeral }
+  {
+    \tl_show:x { \text_expand:n { \romannumeral 10 } }
+  }
+
 \END
diff --git a/l3kernel/testfiles/m3text001.tlg b/l3kernel/testfiles/m3text001.tlg
index 4c996a389..2b4d41dc6 100644
--- a/l3kernel/testfiles/m3text001.tlg
+++ b/l3kernel/testfiles/m3text001.tlg
@@ -95,3 +95,10 @@ l. ...  }
 <recently read> }
 l. ...  }
 ============================================================
+============================================================
+TEST 11: Non-terminated \romannumeral 
+============================================================
+> x.
+<recently read> }
+l. ...  }
+============================================================





More information about the latex3-commits mailing list.