[latex3-commits] [git/latex3] master: Make \cs_generate_variant:Nn stricter (forbid n to c etc) (fixes #418) (9e813f4)

Bruno Le Floch bruno at le-floch.fr
Mon Nov 27 23:20:51 CET 2017


Repository : https://github.com/latex3/latex3
On branch  : master
Link       : https://github.com/latex3/latex3/commit/9e813f489cbf83fd824dc82a10271b0cd5529451

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

commit 9e813f489cbf83fd824dc82a10271b0cd5529451
Author: Bruno Le Floch <bruno at le-floch.fr>
Date:   Mon Nov 27 13:28:18 2017 -0500

    Make \cs_generate_variant:Nn stricter (forbid n to c etc) (fixes #418)
    
    This forbids variants that try to change N to n,o,f,V,v,x or n to N,c.
    It also makes it an error to try and use unknown letters (more precisely,
    that's only an error if the letter changes).


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

9e813f489cbf83fd824dc82a10271b0cd5529451
 l3kernel/l3expan.dtx              |   70 ++++++++++++--------
 l3kernel/testfiles/m3expan001.lvt |   25 ++++++-
 l3kernel/testfiles/m3expan001.tlg |  129 ++++++++++++++++++++++++++++++++++++-
 3 files changed, 192 insertions(+), 32 deletions(-)

diff --git a/l3kernel/l3expan.dtx b/l3kernel/l3expan.dtx
index d4a1c0c..2d98707 100644
--- a/l3kernel/l3expan.dtx
+++ b/l3kernel/l3expan.dtx
@@ -1611,32 +1611,34 @@
 %
 %   There are further subtleties:
 %   \begin{itemize}
-%     \item In \cs{cs_generate_variant:Nn} |\foo:nnTF| |{xxTF}|, it
-%       would be better to define |\foo:xxTF| using |\exp_args:Nxx|,
+%     \item In \cs{cs_generate_variant:Nn} |\foo:nnTF| |{xxTF}|, we must define
+%       |\foo:xxTF| using |\exp_args:Nxx|,
 %       rather than a hypothetical |\exp_args:NxxTF|.  Thus, we wish to
 %       trim a common trailing part from the base signature and the
 %       variant signature.
 %     \item In \cs{cs_generate_variant:Nn} |\foo:on| |{ox}|, the
-%       function |\foo:ox| should be defined using |\exp_args:Nnx|, not
+%       function |\foo:ox| must be defined using |\exp_args:Nnx|, not
 %       |\exp_args:Nox|, to avoid double |o| expansion.
-%     \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| should
+%     \item Lastly, \cs{cs_generate_variant:Nn} |\foo:on| |{xn}| must
 %       trigger an error, because we do not have a means to replace
 %       |o|-expansion by |x|-expansion.
+%       More generally, we can only convert |N| to |c|, or convert |n|
+%       to |V|, |v|, |o|, |f|, |x|.
 %     \end{itemize}
 %     All this boils down to a few rules.  Only |n| and |N|-type
 %     arguments can be replaced by \cs{cs_generate_variant:Nn}.  Other
 %     argument types are allowed to be passed unchanged from the base
 %     form to the variant: in the process they are changed to |n|
-%     (except for two cases: |N| and |p|-type arguments).  A common
-%     trailing part is ignored.
+%     except for |N| and |p|-type arguments.  A common trailing
+%     part is ignored.
 %
 %     We compare the base and variant signatures one character at a time
 %     within |x|-expansion.  The result is given to
-%     \cs{@@_generate_variant:wwNN} in the form \meta{processed variant
-%       signature} \cs{q_mark} \meta{errors} \cs{q_stop} \meta{base
-%       function} \meta{new function}.  If all went well, \meta{errors}
-%     is empty; otherwise, it is a kernel error message, followed by
-%     some clean-up code (\cs{use_none:nnn}).
+%     \cs{@@_generate_variant:wwNN} (defined later) in the form
+%     \meta{processed variant signature} \cs{q_mark} \meta{errors}
+%     \cs{q_stop} \meta{base function} \meta{new function}.  If all went
+%     well, \meta{errors} is empty; otherwise, it is a kernel error
+%     message and some clean-up code.
 %
 %     Note the space after |#3| and after the following brace group.
 %     Those are ignored by \TeX{} when fetching the last argument for
@@ -1666,7 +1668,7 @@
 %    \end{macrocode}
 % \end{macro}
 %
-% \begin{macro}[aux, EXP]
+% \begin{macro}[aux, rEXP]
 %   {
 %     \@@_generate_variant_loop:nNwN,
 %     \@@_generate_variant_loop_same:w,
@@ -1675,8 +1677,8 @@
 %     \@@_generate_variant_loop_invalid:NNwNNnn,
 %   }
 %   \begin{arguments}
-%     \item Last few (consecutive) letters common between the base
-%       and variant (in fact, \cs{@@_generate_variant_same:N}
+%     \item Last few consecutive letters common between the base and
+%       variant (more precisely, \cs{@@_generate_variant_same:N}
 %       \meta{letter} for each letter).
 %     \item Next variant letter.
 %     \item Remainder of variant form.
@@ -1688,15 +1690,16 @@
 %   two letters are different: if the loop ends before, the argument is
 %   dropped, which means that trailing common letters are ignored.
 %
-%   The case where the two letters are different is only allowed with a
-%   base letter of |N| or |n|.  Otherwise, call
+%   The case where the two letters are different is only allowed if the
+%   base is |N| and the variant is |c|, or when the base is |n| and the
+%   variant is |o|, |V|, |v|, |f| or |x|.  Otherwise, call
 %   \cs{@@_generate_variant_loop_invalid:NNwNNnn} to remove the end of
 %   the loop, get arguments at the end of the loop, and place an
 %   appropriate error message as a second argument of
-%   \cs{@@_generate_variant:wwNN}.  If the letters are distinct and
-%   the base letter is indeed |n| or |N|, leave in the input stream
-%   whatever argument was collected, and the next variant letter |#2|,
-%   then loop by calling \cs{@@_generate_variant_loop:nNwN}.
+%   \cs{@@_generate_variant:wwNN}.  If the letters are distinct and the
+%   base letter is indeed |n| or |N|, leave in the input stream whatever
+%   argument |#1| was collected, and the next variant letter |#2|, then
+%   loop by calling \cs{@@_generate_variant_loop:nNwN}.
 %
 %   The loop can stop in three ways.
 %   \begin{itemize}
@@ -1714,8 +1717,9 @@
 %       \cs{@@_generate_variant:wwNN}.
 %     \item The loop can be interrupted early if the requested expansion
 %       is unavailable, namely when the variant and base letters differ
-%       and the base is neither |n| nor |N|.  Again, an error is placed
-%       as the second argument of \cs{@@_generate_variant:wwNN}.
+%       and the base is not the right one (|n| or |N| to support the
+%       variant).  In that case too an error is placed as the second
+%       argument of \cs{@@_generate_variant:wwNN}.
 %   \end{itemize}
 %   Note that if the variant form has the same length as the base form,
 %   |#2| is as described in the first point, and |#4| as described in
@@ -1729,10 +1733,22 @@
     \if:w #2 #4
       \exp_after:wN \@@_generate_variant_loop_same:w
     \else:
-      \if:w N #4 \else:
-        \if:w n #4 \else:
-          \@@_generate_variant_loop_invalid:NNwNNnn #4#2
+      \if:w #4
+        \if:w c #2 N \else:
+          \if:w o #2 n \else:
+            \if:w V #2 n \else:
+              \if:w v #2 n \else:
+                \if:w f #2 n \else:
+                  \if:w x #2 n \else:
+                    \scan_stop:
+                  \fi:
+                \fi:
+              \fi:
+            \fi:
+          \fi:
         \fi:
+      \else:
+        \@@_generate_variant_loop_invalid:NNwNNnn #4#2
       \fi:
     \fi:
     #1
@@ -1768,9 +1784,9 @@
       }
   }
 \cs_new:Npn \@@_generate_variant_loop_invalid:NNwNNnn
-    #1#2 \fi: \fi: \fi: #3 \q_stop #4#5#6#7
+    #1#2 \fi: \fi: #3 \q_stop #4#5#6#7
   {
-    \fi: \fi: \fi:
+    \fi: \fi:
     \exp_not:n
       {
         \q_mark
diff --git a/l3kernel/testfiles/m3expan001.lvt b/l3kernel/testfiles/m3expan001.lvt
index c302826..0ab3023 100644
--- a/l3kernel/testfiles/m3expan001.lvt
+++ b/l3kernel/testfiles/m3expan001.lvt
@@ -1,6 +1,6 @@
 %
 % Copyright (C) 2008 Frank Mittelbach
-%               2009-2012 The LaTeX3 Project
+%               2009-2012,2017 The LaTeX3 Project
 %
 
 % Input the regression test macros for LaTeX
@@ -51,7 +51,6 @@
     \foo:oo { \c_aa_tl } { \c_bb_tl }
     \foo:VV \c_aa_tl \c_bb_tl
     \foo:xx { \c_aa_tl } { \c_bb_tl }
-    \foo:cc { a } { b }
     \foo:nx { a } { \c_b_tl }
     \foo:fx { \c_aaa_tl } { \c_bbb_tl }
     \foo:xf { \c_aaa_tl } { \c_bbb_tl }
@@ -107,4 +106,26 @@
     \iow_term:x { \cs_meaning:N \foo: }
   }
 
+\cs_new:Npn \foobar:Nn { }
+\TEST { Incorrect~letters }
+  {
+    \cs_generate_variant:Nn \foobar:Nn { pn , :Nn }
+    \TYPE
+      {
+        \cs_meaning:N \foobar:pn ,
+        \cs_meaning:N \foobar::Nn ,
+      }
+  }
+
+\TEST { Issue~418:~changing~N/n~to~incompatible~variants }
+  {
+    \cs_generate_variant:Nn \foobar:Nn { on , Nc , n }
+    \TYPE
+      {
+        \cs_meaning:N \foobar:on ,
+        \cs_meaning:N \foobar:Nc ,
+        \cs_meaning:N \foobar:nn ,
+      }
+  }
+
 \END
diff --git a/l3kernel/testfiles/m3expan001.tlg b/l3kernel/testfiles/m3expan001.tlg
index 3d548fb..89c2aa6 100644
--- a/l3kernel/testfiles/m3expan001.tlg
+++ b/l3kernel/testfiles/m3expan001.tlg
@@ -11,7 +11,25 @@ Defining \foo:nn on line ...
 Defining \foo:oo on line ...
 Defining \foo:VV on line ...
 Defining \foo:xx on line ...
-Defining \foo:cc on line ...
+Variant \foo:nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form 'cc' invalid for base form '\foo:nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  { oo , VV , xx , cc , nx , fx , xf }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foo:nn' with a
+| signature starting with 'cc', but cannot change an argument from type 'n' to
+| type 'c'.
+|...............................................
 Defining \foo:nx on line ...
 Defining \exp_args:Nfx on line ...
 Defining \foo:fx on line ...
@@ -26,7 +44,7 @@ TEST 1: protection
 \long macro:->\exp_args:Noo \foo:nn 
 \long macro:->\exp_args:NVV \foo:nn 
 \protected\long macro:->\exp_args:Nxx \foo:nn 
-\long macro:->\exp_args:Ncc \foo:nn 
+undefined
 \protected\long macro:->\exp_args:Nnx \foo:nn 
 \protected\long macro:->\exp_args:Nfx \foo:nn 
 \protected\long macro:->\exp_args:Nxf \foo:nn 
@@ -41,7 +59,6 @@ TEST 2: expansion
 (\c_a_tl )(\c_b_tl )
 (\c_a_tl )(\c_b_tl )
 (A)(B)
-(\a )(\b )
 (a)(B)
 (A\c_a_tl )(BB)
 (AA)(B\c_b_tl )
@@ -183,3 +200,109 @@ l. ...  }
 |...............................................
 undefined
 ============================================================
+Defining \foobar:Nn on line ...
+============================================================
+TEST 9: Incorrect letters
+============================================================
+Variant \foobar:Nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form 'pn' invalid for base form '\foobar:Nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foobar:Nn' with a
+| signature starting with 'pn', but cannot change an argument from type 'N' to
+| type 'p'.
+|...............................................
+Variant \foobar:Nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form ':Nn' invalid for base form '\foobar:Nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foobar:Nn' with a
+| signature starting with ':Nn', but cannot change an argument from type 'N'
+| to type ':'.
+|...............................................
+undefined,undefined,
+============================================================
+============================================================
+TEST 10: Issue 418: changing N/n to incompatible variants
+============================================================
+Variant \foobar:Nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form 'on' invalid for base form '\foobar:Nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foobar:Nn' with a
+| signature starting with 'on', but cannot change an argument from type 'N' to
+| type 'o'.
+|...............................................
+Variant \foobar:Nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form 'Nc' invalid for base form '\foobar:Nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foobar:Nn' with a
+| signature starting with 'Nc', but cannot change an argument from type 'n' to
+| type 'c'.
+|...............................................
+Variant \foobar:Nn already defined; not changing it on line ...
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+!
+! LaTeX error: "kernel/invalid-variant"
+! 
+! Variant form 'n' invalid for base form '\foobar:Nn'.
+! 
+! See the LaTeX3 documentation for further information.
+! 
+! For immediate help type H <return>.
+!...............................................  
+l. ...  }
+|'''''''''''''''''''''''''''''''''''''''''''''''
+| This is a coding error.
+| 
+| LaTeX has been asked to create a variant of the function '\foobar:Nn' with a
+| signature starting with 'n', but cannot change an argument from type 'N' to
+| type 'n'.
+|...............................................
+undefined,undefined,undefined,
+============================================================





More information about the latex3-commits mailing list