[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