diff options
author | Karl Berry <karl@freefriends.org> | 2015-10-14 22:32:58 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2015-10-14 22:32:58 +0000 |
commit | 0346eca0b9378bffafb6b32579dd4542b71b57f5 (patch) | |
tree | f9a5b79922bd74de6945c98e47f9b1d3009da982 /Master/texmf-dist/source/latex/l3kernel | |
parent | 6028cf981b015fefcf1205f6cba193542627ddbf (diff) |
l3 (14oct15)
git-svn-id: svn://tug.org/texlive/trunk@38642 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex/l3kernel')
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/expl3.dtx | 4 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx | 3 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx | 179 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3msg.dtx | 39 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3names.dtx | 42 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3prg.dtx | 111 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3tl.dtx | 28 | ||||
-rw-r--r-- | Master/texmf-dist/source/latex/l3kernel/l3token.dtx | 327 |
8 files changed, 384 insertions, 349 deletions
diff --git a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx index 753aeb0ec53..42ff1e3e4f4 100644 --- a/Master/texmf-dist/source/latex/l3kernel/expl3.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/expl3.dtx @@ -36,8 +36,8 @@ %<*driver|generic|package> \def\ExplFileName{expl3} \def\ExplFileDescription{L3 programming layer} -\def\ExplFileDate{2015/09/27} -\def\ExplFileVersion{6111} +\def\ExplFileDate{2015/10/14} +\def\ExplFileVersion{6210} %</driver|generic|package> %<*driver> \documentclass[full]{l3doc} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx index 29d0a01caa8..69556596190 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3bootstrap.dtx @@ -145,7 +145,7 @@ % \end{macro} % \end{macro} % \end{macro} -\GetIdInfo$Id: l3bootstrap.dtx 5983 2015-09-10 18:57:56Z joseph $ +\GetIdInfo$Id: l3bootstrap.dtx 6139 2015-09-30 14:02:38Z bruno $ {L3 Bootstrap code} %</driver|package> %<*driver> @@ -609,6 +609,7 @@ \catcode 9 = 9\relax \catcode 32 = 9\relax \catcode 34 = 12\relax +\catcode 38 = 4\relax \catcode 58 = 11\relax \catcode 94 = 7\relax \catcode 95 = 11\relax diff --git a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx index 6c65d33db05..d9a3202c949 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3candidates.dtx @@ -38,7 +38,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3candidates.dtx 6039 2015-09-23 12:41:26Z joseph $ +\GetIdInfo$Id: l3candidates.dtx 6208 2015-10-09 20:01:54Z joseph $ {L3 Experimental additions to l3kernel} %</driver|package> %<*driver> @@ -576,6 +576,98 @@ % % \section{Additions to \pkg{l3prg}} % +% Minimal (lazy) evaluation can be obtained using the functions +% \cs{bool_all_p:n}, \cs{bool_and_p:nn}, \cs{bool_any_p:n}, or +% \cs{bool_or_p:nn}, which only evaluate their boolean expression +% arguments when they are needed to determine the resulting truth +% value. For example, when evaluating the boolean expression +% \begin{verbatim} +% \bool_and_p:nn +% { +% \bool_any_p:n +% { +% { \int_compare_p:n { 2 = 3 } } +% { \int_compare_p:n { 4 <= 4 } } +% { \int_compare_p:n { 1 = \error } } % is skipped +% } +% } +% { ! \int_compare_p:n { 2 = 4 } } +% \end{verbatim} +% the line marked with |is skipped| is not expanded because the result +% of \cs{bool_any_p:n} is known once the second boolean expression is +% found to be logically \texttt{true}. On the other hand, the last +% line is expanded because its logical value is needed to determine the +% result of \cs{bool_and_p:nn}. +% +% \begin{function}[EXP, added = 2015-09-28]{\bool_all_p:n} +% \begin{syntax} +% \cs{bool_all_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} +% \end{syntax} +% Implements the \enquote{And} operation on the \meta{boolean +% expressions}, hence is \texttt{true} if all of them are +% \texttt{true} and \texttt{false} if any of them is \texttt{false}. +% Contrarily to the infix operator |&&|, only the \meta{boolean +% expressions} which are needed to determine the result of +% \cs{bool_all_p:n} will be evaluated. See also \cs{bool_and_p:nn} +% when there are only two \meta{boolean expressions}. +% \end{function} +% +% \begin{function}[EXP, added = 2015-09-28]{\bool_and_p:nn} +% \begin{syntax} +% \cs{bool_and_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2} +% \end{syntax} +% Implements the \enquote{And} operation between two boolean +% expressions, hence is \texttt{true} if both are \texttt{true}. +% Contrarily to the infix operator |&&|, the \meta{boolexpr_2} will +% only be evaluated if it is needed to determine the result of +% \cs{bool_and_p:nn}. See also \cs{bool_all_p:n} when there are more +% than two \meta{boolean expressions}. +% \end{function} +% +% \begin{function}[EXP, added = 2015-09-28]{\bool_any_p:n} +% \begin{syntax} +% \cs{bool_any_p:n} \{ \Arg{boolexpr_1} \Arg{boolexpr_2} $\cdots$ \Arg{boolexpr_N} \} +% \end{syntax} +% Implements the \enquote{Or} operation on the \meta{boolean +% expressions}, hence is \texttt{true} if any of them is +% \texttt{true} and \texttt{false} if all of them are \texttt{false}. +% Contrarily to the infix operator \verb"||", only the \meta{boolean +% expressions} which are needed to determine the result of +% \cs{bool_any_p:n} will be evaluated. See also \cs{bool_or_p:nn} +% when there are only two \meta{boolean expressions}. +% \end{function} +% +% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n} +% \begin{syntax} +% \cs{bool_not_p:n} \Arg{boolean expression} +% \end{syntax} +% Function version of |!(|\meta{boolean expression}|)| within a boolean +% expression. +% \end{function} +% +% \begin{function}[EXP, added = 2015-09-28]{\bool_or_p:nn} +% \begin{syntax} +% \cs{bool_or_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2} +% \end{syntax} +% Implements the \enquote{Or} operation between two boolean +% expressions, hence is \texttt{true} if either one is \texttt{true}. +% Contrarily to the infix operator \verb"||", the \meta{boolexpr_2} +% will only be evaluated if it is needed to determine the result of +% \cs{bool_or_p:nn}. See also \cs{bool_any_p:n} when there are more +% than two \meta{boolean expressions}. +% \end{function} +% +% \begin{function}[EXP, updated = 2012-07-08]{\bool_xor_p:nn} +% \begin{syntax} +% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2} +% \end{syntax} +% Implements an \enquote{exclusive or} operation between two boolean +% expressions. There is no infix operation for this logical +% operator. +% \end{function} +% + +% % \begin{function}[added = 2014-08-22, updated = 2015-08-03]{\bool_log:N, \bool_log:c} % \begin{syntax} % \cs{bool_log:N} \meta{boolean} @@ -1057,7 +1149,7 @@ % \end{itemize} % and other values will raise an error. % -% The \meta{catcode} may be any one valid for the engine in use. Note +% The \meta{charcode} may be any one valid for the engine in use. Note % however that for \XeTeX{} releases prior to 0.99992 only the 8-bit % range ($0$ to $255$) is accepted due to engine limitations. % \end{function} @@ -2484,6 +2576,86 @@ %<@@=bool> % \end{macrocode} % +% \begin{macro}{\bool_all_p:n} +% \begin{macro}[aux]{\@@_all_aux:n} +% Go through the list of expressions, stopping whenever an expression +% is \texttt{false}. If the end is reached without finding any +% \texttt{false} expression, then the result is \texttt{true}. +% \begin{macrocode} +\cs_new:Npn \bool_all_p:n #1 + { \@@_all_aux:n #1 \q_recursion_tail \q_recursion_stop } +\cs_new:Npn \@@_all_aux:n #1 + { + \quark_if_recursion_tail_stop_do:nn {#1} { \c_true_bool } + \bool_if:nF {#1} + { \use_i_delimit_by_q_recursion_stop:nw { \c_false_bool } } + \@@_all_aux:n + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\bool_and_p:nn} +% Only evaluate the second expression if the first is \texttt{true}. +% \begin{macrocode} +\cs_new:Npn \bool_and_p:nn #1#2 + { \bool_if:nTF {#1} { \bool_if_p:n {#2} } { \c_false_bool } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\bool_any_p:n} +% \begin{macro}[aux]{\@@_any_aux:n} +% Go through the list of expressions, stopping whenever an expression +% is \texttt{true}. If the end is reached without finding any +% \texttt{true} expression, then the result is \texttt{false}. +% \begin{macrocode} +\cs_new:Npn \bool_any_p:n #1 + { \@@_any_aux:n #1 \q_recursion_tail \q_recursion_stop } +\cs_new:Npn \@@_any_aux:n #1 + { + \quark_if_recursion_tail_stop_do:nn {#1} { \c_false_bool } + \bool_if:nT {#1} + { \use_i_delimit_by_q_recursion_stop:nw { \c_true_bool } } + \@@_any_aux:n + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\bool_not_p:n} +% \UnitTested +% The Not variant just reverses the outcome of \cs{bool_if_p:n}. Can +% be optimized but this is nice and simple and according to the +% implementation plan. Not even particularly useful to have it when +% the infix notation is easier to use. +% \begin{macrocode} +\cs_new:Npn \bool_not_p:n #1 { \bool_if_p:n { ! ( #1 ) } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\bool_or_p:nn} +% Only evaluate the second expression if the first is \texttt{false}. +% \begin{macrocode} +\cs_new:Npn \bool_or_p:nn #1#2 + { \bool_if:nTF {#1} { \c_true_bool } { \bool_if_p:n {#2} } } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\bool_xor_p:nn} +% \UnitTested +% Exclusive or. If the boolean expressions have same truth value, +% return false, otherwise return true. +% \begin{macrocode} +\cs_new:Npn \bool_xor_p:nn #1#2 + { + \int_compare:nNnTF { \bool_if_p:n {#1} } = { \bool_if_p:n {#2} } + \c_false_bool + \c_true_bool + } +% \end{macrocode} +% \end{macro} +% +% % \begin{macro}{\bool_log:N, \bool_log:c, \bool_log:n} % Redirect output of \cs{bool_show:N} to the log. % \begin{macrocode} @@ -4418,7 +4590,8 @@ \char_set_lccode:nn { 32 } {#1} \exp_args:Nx \tex_lowercase:D { - \tl_const:cn { c_@@_ \__int_to_roman:w #1 _tl } + \tl_const:Nn + \exp_not:c { c_@@_ \__int_to_roman:w #1 _tl } { \exp_not:o \l_@@_tmp_tl } } } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx index 7ff417961b5..c4cce9a58aa 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3msg.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3msg.dtx 6037 2015-09-23 12:41:15Z joseph $ +\GetIdInfo$Id: l3msg.dtx 6113 2015-09-28 21:30:11Z bruno $ {L3 Messages} %</driver|package> %<*driver> @@ -2005,31 +2005,30 @@ % (with category code $7$) and keep tokens until that space character, % dropping everything else until \cs{q_stop}. The \cs{exp_end:} prevents % losing braces around the user-inserted text if any, and stops the -% expansion of \cs{exp:w}. +% expansion of \cs{exp:w}. One group is used to keep the settings +% for \tn{lowercase} local and the other one is used to prevent +% |\LaTeX3~error:| from being equal to \cs{scan_stop:}. % \begin{macrocode} \group_begin: -\char_set_catcode_math_superscript:N \^ -\char_set_lccode:nn { `^ } { `\ } -\char_set_lccode:nn { `L } { `L } -\char_set_lccode:nn { `T } { `T } -\char_set_lccode:nn { `X } { `X } -\tex_lowercase:D +\cs_set_protected:Npn \@@_tmp:w #1#2 { - \cs_new:Npx \@@_expandable_error:n #1 + \group_end: + \cs_new:Npn \@@_expandable_error:n ##1 { - \exp_not:n - { - \exp:w - \exp_after:wN \exp_after:wN - \exp_after:wN \@@_expandable_error:w - \exp_after:wN \exp_after:wN - \exp_after:wN \exp_end: - } - \exp_not:N \use:n { \exp_not:c { LaTeX3~error: } ^ #1 } ^ + \exp:w + \exp_after:wN \exp_after:wN + \exp_after:wN \@@_expandable_error:w + \exp_after:wN \exp_after:wN + \exp_after:wN \exp_end: + \use:n { #2 #1 ##1 } #1 } - \cs_new:Npn \@@_expandable_error:w #1 ^ #2 ^ { #1 } + \cs_new:Npn \@@_expandable_error:w ##1 #1 ##2 #1 {##1} } -\group_end: +\group_begin: +\char_set_catcode_math_superscript:N \^ +\char_set_lccode:nn { `^ } { `\ } +\tex_lowercase:D + { \group_end: \exp_args:NNc \@@_tmp:w ^ } { LaTeX3~error: } % \end{macrocode} % \end{macro} % \end{macro} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx index 6b3dafbc2b3..f7d7ed4e2ee 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3names.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3names.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3names.dtx 6108 2015-09-27 08:58:42Z joseph $ +\GetIdInfo$Id: l3names.dtx 6209 2015-10-10 19:51:42Z joseph $ {L3 Namespace for primitives} %</driver|package> %<*driver> @@ -611,11 +611,9 @@ \__kernel_primitive:NN \pdfoutput \pdftex_pdfoutput:D \__kernel_primitive:NN \pdfpageattr \pdftex_pdfpageattr:D \__kernel_primitive:NN \pdfpagebox \pdftex_pdfpagebox:D - \__kernel_primitive:NN \pdfpageheight \pdftex_pdfpageheight:D \__kernel_primitive:NN \pdfpageref \pdftex_pdfpageref:D \__kernel_primitive:NN \pdfpageresources \pdftex_pdfpageresources:D \__kernel_primitive:NN \pdfpagesattr \pdftex_pdfpagesattr:D - \__kernel_primitive:NN \pdfpagewidth \pdftex_pdfpagewidth:D \__kernel_primitive:NN \pdfrefobj \pdftex_pdfrefobj:D \__kernel_primitive:NN \pdfrefxform \pdftex_pdfrefxform:D \__kernel_primitive:NN \pdfrefximage \pdftex_pdfrefximage:D @@ -639,6 +637,8 @@ % \end{macrocode} % While these are not. % \begin{macrocode} + \__kernel_primitive:NN \ifpdfabsdim \pdftex_ifabsdim:D + \__kernel_primitive:NN \ifpdfabsnum \pdftex_ifabsnum:D \__kernel_primitive:NN \ifpdfprimitive \pdftex_ifprimitive:D \__kernel_primitive:NN \pdfadjustspacing \pdftex_adjustspacing:D \__kernel_primitive:NN \pdfcopyfont \pdftex_copyfont:D @@ -657,6 +657,8 @@ \__kernel_primitive:NN \pdfmapline \pdftex_mapline:D \__kernel_primitive:NN \pdfnoligatures \pdftex_noligatures:D \__kernel_primitive:NN \pdfnormaldeviate \pdftex_normaldeviate:D + \__kernel_primitive:NN \pdfpageheight \pdftex_pageheight:D + \__kernel_primitive:NN \pdfpagewidth \pdftex_pagewidth:D \__kernel_primitive:NN \pdfpkmode \pdftex_pkmode:D \__kernel_primitive:NN \pdfpkresolution \pdftex_pkresolution:D \__kernel_primitive:NN \pdfprimitive \pdftex_primitive:D @@ -753,9 +755,7 @@ % \end{macrocode} % Primitives from \LuaTeX{}, some of which have been ported back to % \XeTeX{}. Notice that \tn{expanded} was intended for \pdfTeX{}~1.50 but -% as that was not released we call this a \LuaTeX{} primitive. Primitives -% which are aliases are covered only once, so for example \tn{pdfpageheight} -% covers \tn{pageheight} as well. +% as that was not released we call this a \LuaTeX{} primitive. % \begin{macrocode} \__kernel_primitive:NN \alignmark \luatex_alignmark:D \__kernel_primitive:NN \aligntab \luatex_aligntab:D @@ -771,6 +771,7 @@ \__kernel_primitive:NN \expanded \luatex_expanded:D \__kernel_primitive:NN \fontid \luatex_fontid:D \__kernel_primitive:NN \formatname \luatex_formatname:D + \__kernel_primitive:NN \hyphenationmin \luatex_hypenationmin:D \__kernel_primitive:NN \gleaders \luatex_gleaders:D \__kernel_primitive:NN \initcatcodetable \luatex_initcatcodetable:D \__kernel_primitive:NN \latelua \luatex_latelua:D @@ -1037,7 +1038,7 @@ % (depending on the format-building date). There are a few primitives % that get the right names anyway so are missing here! % \begin{macrocode} -\etex_ifdefined:D \luatexcatcodetable +\etex_ifdefined:D \luatexsuppressfontnotfounderror \tex_let:D \luatex_alignmark:D \luatexalignmark \tex_let:D \luatex_aligntab:D \luatexaligntab \tex_let:D \luatex_attribute:D \luatexattribute @@ -1079,10 +1080,6 @@ % \begin{macrocode} \tex_let:D \luatex_bodydir:D \luatexbodydir \tex_let:D \luatex_boxdir:D \luatexboxdir - \tex_let:D \luatex_chardp:D \luatexchardp - \tex_let:D \luatex_charht:D \luatexcharht - \tex_let:D \luatex_charit:D \luatexcharit - \tex_let:D \luatex_charwd:D \luatexcharwd \tex_let:D \luatex_leftghost:D \luatexleftghost \tex_let:D \luatex_localbrokenpenalty:D \luatexlocalbrokenpenalty \tex_let:D \luatex_localinterlinepenalty:D \luatexlocalinterlinepenalty @@ -1139,12 +1136,27 @@ \tex_fi:D % \end{macrocode} % Up to v0.80, \LuaTeX{} defines the \pdfTeX{} version data: rather -% confusing. +% confusing. Removing them means that \cs{pdftex_pdftexversion:D} is +% a marker for \pdfTeX{} alone: useful in engine-dependent code later. % \begin{macrocode} \etex_ifdefined:D \luatex_luatexversion:D - \tex_let:D \pdftex_pdftexbanner:D \tex_undefined:D - \tex_let:D \pdftex_pdftexbanner:D \tex_undefined:D - \tex_let:D \pdftex_pdftexversion:D \tex_undefined:D + \tex_let:D \pdftex_pdftexbanner:D \tex_undefined:D + \tex_let:D \pdftex_pdftexrevision:D \tex_undefined:D + \tex_let:D \pdftex_pdftexversion:D \tex_undefined:D +\tex_fi:D +% \end{macrocode} +% From v0.81, \LuaTeX{} drops the |pdf| prefix in some cases. +% \begin{macrocode} +\etex_ifdefined:D \lastxpos + \tex_let:D \pdftex_lastxpos:D \lastxpos + \tex_let:D \pdftex_lastypos:D \lastypos + \tex_let:D \pdftex_normaldeviate:D \normaldeviate + \tex_let:D \pdftex_pageheight:D \pageheight + \tex_let:D \pdftex_pagewith:D \pagewidth + \tex_let:D \pdftex_randomseed:D \randomseed + \tex_let:D \pdftex_setrandomseed:D \setrandomseed + \tex_let:D \pdftex_savepos:D \savepos + \tex_let:D \pdftex_uniformdeviate:D \uniformdeviate \tex_fi:D % \end{macrocode} % diff --git a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx index 9acff26f534..1fc47d225b9 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3prg.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3prg.dtx 5983 2015-09-10 18:57:56Z joseph $ +\GetIdInfo$Id: l3prg.dtx 6208 2015-10-09 20:01:54Z joseph $ {L3 Control structures} %</driver|package> %<*driver> @@ -72,9 +72,7 @@ % performs a series of tests, possibly involving assignments and % calling other functions that do not read further ahead in the input % stream. After processing the input, a \emph{state} is returned. The -% typical states returned are \meta{true} and \meta{false} but other -% states are possible, say an \meta{error} state for erroneous -% input, \emph{e.g.}, text as input in a function comparing integers. +% states returned are \meta{true} and \meta{false}. % % \LaTeX3 has two forms of conditional flow processing based % on these states. The first form is predicate functions that turn the @@ -87,8 +85,12 @@ % input stream based on the result of the testing as in % \cs{cs_if_free:NTF} which also takes one argument (the |N|) and then % executes either \texttt{true} or \texttt{false} depending on the -% result. Important to note here is that the arguments are executed -% after exiting the underlying |\if...\fi:| structure. +% result. +% +% \begin{texnote} +% The arguments are executed after exiting the underlying +% |\if...\fi:| structure. +% \end{texnote} % % \section{Defining a set of conditional functions} % \label{sec:l3prg:new-conditional-functions} @@ -140,7 +142,7 @@ % which will supply either a logical \texttt{true} or logical % \texttt{false}. This function is intended for use in cases where % one or more logical tests are combined to lead to a final outcome. -% This function will not work properly for \texttt{protected} +% This function cannot be defined for \texttt{protected} % conditionals. % \item \cs{\meta{name}:\meta{arg spec}T} --- a function with one more % argument than the original \meta{arg spec} demands. The \meta{true @@ -192,7 +194,7 @@ % \begin{syntax} % \cs{prg_new_eq_conditional:NNn} \cs{\meta{name_1}:\meta{arg spec_1}} \cs{\meta{name_2}:\meta{arg spec_2}} \Arg{conditions} % \end{syntax} -% These functions copies a family of conditionals. The \texttt{new} version +% These functions copy a family of conditionals. The \texttt{new} version % will check for existing definitions (\emph{cf.}~\cs{cs_new:Npn}) whereas % the \texttt{set} version will not (\emph{cf.}~\cs{cs_set:Npn}). The % conditionals copied are depended on the comma-separated list of @@ -208,7 +210,7 @@ % These `return' functions define the logical state of a conditional statement. % They appear within the code for a conditional % function generated by \cs{prg_set_conditional:Npnn}, \emph{etc}, to indicate -% when a true or false branch has been taken. +% when a true or false branch should be taken. % While they may appear multiple times each within the code of such conditionals, % the execution of the conditional must result in the expansion of one of these % two functions \emph{exactly once}. @@ -357,22 +359,23 @@ % of predicate functions and boolean variables, return boolean % \meta{true} or \meta{false}. It supports the logical operations And, % Or and Not as the well-known infix operators |&&|, \verb"||" and |!| -% with their usual precedences. In +% with their usual precedences (namely, |&&| binds more tightly than +% \verb"||"). In % addition to this, parentheses can be used to isolate % sub-expressions. For example, % \begin{verbatim} % \int_compare_p:n { 1 = 1 } && % ( % \int_compare_p:n { 2 = 3 } || -% \int_compare_p:n { 4 = 4 } || -% \int_compare_p:n { 1 = \error } % is skipped +% \int_compare_p:n { 4 <= 4 } || +% \str_if_eq_p:nn { abc } { def } % ) && -% ! ( \int_compare_p:n { 2 = 4 } ) +% ! \int_compare_p:n { 2 = 4 } % \end{verbatim} -% is a valid boolean expression. Note that minimal evaluation is -% carried out whenever possible so that whenever a truth value cannot -% be changed any more, the remaining tests within the current group -% are skipped. +% is a valid boolean expression. +% +% At present, the infix operators |&&| and \verb"||" perform lazy +% evaluation as well, but this will change in a future release. % % \begin{function}[EXP, pTF, updated = 2012-07-08]{\bool_if:n} % \begin{syntax} @@ -384,45 +387,10 @@ % \meta{boolean expression} should consist of a series of predicates % or boolean variables with the logical relationship between these % defined using |&&| (\enquote{And}), \verb"||" (\enquote{Or}), -% |!| (\enquote{Not}) and parentheses. Minimal evaluation is used -% in the processing, so that once a result is defined there is -% not further expansion of the tests. For example -% \begin{verbatim} -% \bool_if_p:n -% { -% \int_compare_p:nNn { 1 } = { 1 } -% && -% ( -% \int_compare_p:nNn { 2 } = { 3 } || -% \int_compare_p:nNn { 4 } = { 4 } || -% \int_compare_p:nNn { 1 } = { \error } % is skipped -% ) -% && -% ! \int_compare_p:nNn { 2 } = { 4 } -% } -% \end{verbatim} -% will be \texttt{true} and will not evaluate -% |\int_compare_p:nNn { 1 } = { \error }|. The logical Not applies to +% |!| (\enquote{Not}) and parentheses. The logical Not applies to % the next predicate or group. % \end{function} % -% \begin{function}[EXP, updated = 2012-07-08]{\bool_not_p:n} -% \begin{syntax} -% \cs{bool_not_p:n} \Arg{boolean expression} -% \end{syntax} -% Function version of |!(|\meta{boolean expression}|)| within a boolean -% expression. -% \end{function} -% -% \begin{function}[EXP, updated = 2012-07-08]{\bool_xor_p:nn} -% \begin{syntax} -% \cs{bool_xor_p:nn} \Arg{boolexpr_1} \Arg{boolexpr_2} -% \end{syntax} -% Implements an \enquote{exclusive or} operation between two boolean -% expressions. There is no infix operation for this logical -% operator. -% \end{function} -% % \section{Logical loops} % % Loops using either boolean expressions or stored boolean values. @@ -568,17 +536,17 @@ % % \begin{function}[EXP]{\if_predicate:w} % \begin{syntax} -% "\if_predicate:w" <predicate> <true code> "\else:" <false code> "\fi:" +% \cs{if_predicate:w} \meta{predicate} \meta{true code} \cs{else:} \meta{false code} \cs{fi:} % \end{syntax} % This function takes a predicate function and % branches according to the result. (In practice this function would also -% accept a single boolean variable in place of the <predicate> but to make the -% coding clearer this should be done through "\if_bool:N".) +% accept a single boolean variable in place of the \meta{predicate} but to make the +% coding clearer this should be done through \cs{if_bool:N}.) % \end{function} % % \begin{function}[EXP]{\if_bool:N} % \begin{syntax} -% "\if_bool:N" <boolean> <true code> "\else:" <false code> "\fi:" +% \cs{if_bool:N} \meta{boolean} \meta{true code} \cs{else:} \meta{false code} \cs{fi:} % \end{syntax} % This function takes a boolean variable and % branches according to the result. @@ -664,7 +632,7 @@ % \section{\pkg{l3prg} implementation} % % \TestFiles{m3prg001.lvt,m3prg002.lvt,m3prg003.lvt} -%% +% % \begin{macrocode} %<*initex|package> % \end{macrocode} @@ -1128,7 +1096,7 @@ % \begin{macro}[aux]+\@@_&_1:w+ % \begin{macro}[aux]+\@@_|_0:w+ % Two cases where we simply continue scanning. We must remove the -% second "&" or \verb"|". +% second |&| or \verb"|". % \begin{macrocode} \cs_new_nopar:cpn { @@_&_1:w } & { \@@_get_next:NN \use_i:nn } \cs_new_nopar:cpn { @@_|_0:w } | { \@@_get_next:NN \use_i:nn } @@ -1237,31 +1205,6 @@ % \end{macro} % \end{macro} % -% \begin{macro}{\bool_not_p:n} -% \UnitTested -% The Not variant just reverses the outcome of \cs{bool_if_p:n}. Can -% be optimized but this is nice and simple and according to the -% implementation plan. Not even particularly useful to have it when -% the infix notation is easier to use. -% \begin{macrocode} -\cs_new:Npn \bool_not_p:n #1 { \bool_if_p:n { ! ( #1 ) } } -% \end{macrocode} -% \end{macro} -% -% \begin{macro}{\bool_xor_p:nn} -% \UnitTested -% Exclusive or. If the boolean expressions have same truth value, -% return false, otherwise return true. -% \begin{macrocode} -\cs_new:Npn \bool_xor_p:nn #1#2 - { - \int_compare:nNnTF { \bool_if_p:n {#1} } = { \bool_if_p:n {#2} } - \c_false_bool - \c_true_bool - } -% \end{macrocode} -% \end{macro} -% % \subsection{Logical loops} % % \begin{macro}{\bool_while_do:Nn, \bool_while_do:cn} diff --git a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx index 5ffb9ffdf33..57bfe04f3d7 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3tl.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3tl.dtx 6037 2015-09-23 12:41:15Z joseph $ +\GetIdInfo$Id: l3tl.dtx 6121 2015-09-29 20:31:06Z bruno $ {L3 Token lists} %</driver|package> %<*driver> @@ -1833,14 +1833,16 @@ % If on the one hand it is found within the \meta{token list}, then % |##1| cannot contain the \meta{delimiter}~|#1| that we worked so % hard to obtain, thus \cs{@@_replace_wrap:w} gets~|##1| as its own -% argument~|##1|, and wraps it using \cs{exp_not:o} for consumption by +% argument~|##1|, and protects it against % the \texttt{x}-expanding assignment. It also finds \cs{exp_not:n} % as~|##2| and does nothing to it, thus letting through \cs{exp_not:n} -% \Arg{replacement} into the assignment. (Note that +% \Arg{replacement} into the assignment. Note that % \cs{@@_replace_next:w} and \cs{@@_replace_wrap:w} are always called -% followed by \cs{prg_do_nothing:} to avoid losing braces when -% grabbing delimited arguments, hence the use of \cs{exp_not:o} rather -% than \cs{exp_not:n}.) Afterwards, \cs{@@_replace_next:w} is called +% followed by two empty brace groups. These are safe because no +% delimiter can match them. They prevent losing braces when grabbing +% delimited arguments, but require the use of \cs{exp_not:o} and +% \cs{use_none:nn}, rather than simply \cs{exp_not:n}. +% Afterwards, \cs{@@_replace_next:w} is called % to repeat the replacement, or \cs{@@_replace_wrap:w} if we only want % a single replacement. In this second case, |##1| is the % \meta{remaining tokens} in the \meta{token list} and |##2| is some @@ -1850,9 +1852,9 @@ % % If on the other hand the argument~|##1| of \cs{@@_replace_next:w} is % delimited by the trailing \meta{pattern}~|#5|, then |##1| is -% \enquote{\cs{prg_do_nothing:} \meta{token list} \meta{delimiter} +% \enquote{\{ \} \{ \} \meta{token list} \meta{delimiter} % \Arg{ending code}}, hence \cs{@@_replace_wrap:w} finds -% \enquote{\cs{prg_do_nothing:} \meta{token list}} as |##1| and the +% \enquote{\{ \} \{ \} \meta{token list}} as |##1| and the % \meta{ending code} as~|##2|. It leaves the \meta{token list} into % the assignment and unbraces the \meta{ending code} which removes % what remains (essentially the \meta{delimiter} and @@ -1861,25 +1863,27 @@ \cs_new_protected:Npn \@@_replace_auxii:nNNNnn #1#2#3#4#5#6 { \group_align_safe_begin: - \cs_set:Npn \@@_replace_wrap:w ##1 #1 ##2 { \exp_not:o {##1} ##2 } + \cs_set:Npn \@@_replace_wrap:w ##1 #1 ##2 + { \exp_not:o { \use_none:nn ##1 } ##2 } \cs_set:Npx \@@_replace_next:w ##1 #5 { \exp_not:N \@@_replace_wrap:w ##1 \exp_not:n { #1 } \exp_not:n { \exp_not:n {#6} } - \exp_not:n { #2 \prg_do_nothing: } + \exp_not:n { #2 { } { } } } #3 #4 { \exp_after:wN \@@_replace_next:w - \exp_after:wN \prg_do_nothing: #4 + \exp_after:wN { \exp_after:wN } + \exp_after:wN { \exp_after:wN } + #4 #1 { \if_false: { \fi: } \exp_after:wN \use_none:n \exp_after:wN { \if_false: } \fi: } #5 - \q_recursion_stop } \group_align_safe_end: } diff --git a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx index 9699b2492eb..0075c4abfeb 100644 --- a/Master/texmf-dist/source/latex/l3kernel/l3token.dtx +++ b/Master/texmf-dist/source/latex/l3kernel/l3token.dtx @@ -37,7 +37,7 @@ \documentclass[full]{l3doc} %</driver> %<*driver|package> -\GetIdInfo$Id: l3token.dtx 6040 2015-09-23 12:41:32Z joseph $ +\GetIdInfo$Id: l3token.dtx 6114 2015-09-28 21:32:37Z bruno $ {L3 Experimental token manipulation} %</driver|package> %<*driver> @@ -1668,240 +1668,143 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}[aux] +% { +% \@@_delimit_by_char":w, +% \@@_delimit_by_count:w, +% \@@_delimit_by_dimen:w, +% \@@_delimit_by_macro:w, +% \@@_delimit_by_muskip:w, +% \@@_delimit_by_skip:w, +% \@@_delimit_by_toks:w, +% } +% These auxiliary functions are used below to define some +% conditionals which detect whether the \tn{meaning} of their +% argument begins with a particular string. Each auxiliary takes an +% argument delimited by a string, a second one delimited by +% \cs{q_stop}, and returns the first one and its delimiter. +% This result will eventually be compared to another string. +% \begin{macrocode} +\group_begin: +\cs_set_protected:Npn \@@_tmp:w #1 + { + \use:x + { + \cs_new:Npn \exp_not:c { @@_delimit_by_ #1 :w } + ####1 \tl_to_str:n {#1} ####2 \exp_not:N \q_stop + { ####1 \tl_to_str:n {#1} } + } + } +\@@_tmp:w { char" } +\@@_tmp:w { count } +\@@_tmp:w { dimen } +\@@_tmp:w { macro } +\@@_tmp:w { muskip } +\@@_tmp:w { skip } +\@@_tmp:w { toks } +\group_end: +% \end{macrocode} +% \end{macro} +% % \begin{macro}[pTF] % { % \token_if_chardef:N, \token_if_mathchardef:N, +% \token_if_long_macro:N, +% \token_if_protected_macro:N, \token_if_protected_long_macro:N, % \token_if_dim_register:N, \token_if_int_register:N, % \token_if_muskip_register:N, % \token_if_skip_register:N, \token_if_toks_register:N, -% \token_if_long_macro:N, -% \token_if_protected_macro:N, \token_if_protected_long_macro:N, % } -% \begin{macro}[aux] -% { -% \@@_if_chardef:w, -% \@@_if_dim_register:w, -% \@@_if_int_register:w, -% \@@_if_muskip_register:w, -% \@@_if_skip_register:w, -% \@@_if_toks_register:w, -% \@@_if_protected_macro:w, -% \@@_if_long_macro:w, -% } -% Most of these functions have to check the meaning of the token in -% question so we need to do some checkups on which characters are -% output by \cs{token_to_meaning:N}. As usual, these characters have -% catcode 12 so we must do some serious substitutions in the code -% below\dots +% Each of these conditionals tests whether its argument's +% \tn{meaning} starts with a given string. This is essentially done +% by having an auxiliary grab an argument delimited by the string and +% testing whether the argument was empty. Of course, a copy of this +% string must first be added to the end of the \tn{meaning} to avoid +% a runaway argument in case it does not contain the string. Two +% complications arise. First, the escape character is not fixed, and +% cannot be included in the delimiter of the auxiliary function (this +% function cannot be defined on the fly because tests must remain +% expandable): instead the first argument of the auxiliary (plus the +% delimiter to avoid complications with trailing spaces) is compared +% using \cs{__str_if_eq_x_return:nn} to the result of applying +% \cs{token_to_str:N} to a control sequence. Second, the +% \tn{meaning} of primitives such as \tn{dimen} or \tn{dimendef} +% starts in the same way as registers such as +% \tn{dimen}\texttt{123}, so they must be tested for. +% +% Characters used as delimiters must have catcode~$12$ +% and are obtained through \cs{tl_to_str:n}. This requires doing all +% definitions within \texttt{x}-expansion. The temporary function +% \cs{@@_tmp:w} used to define each conditional receives three +% arguments: the name of the conditional, the auxiliary's delimiter +% (also used to name the auxiliary), and the string to which one +% compares the auxiliary's result. Note that the \tn{meaning} of a +% protected long macro starts with |\protected\long macro|, with no +% space after |\protected| but a space after |\long|, hence the +% mixture of \cs{token_to_str:N} and \cs{tl_to_str:n}. +% +% For the first five conditionals, \cs{cs_if_exist:cT} turns out to +% be \texttt{false}, and the code boils down to a string comparison +% between the result of the auxiliary on the \tn{meaning} of the +% conditional's argument~|####1|, and~|#3|. Both are evaluated at +% run-time, as this is important to get the correct escape character. +% +% The other five conditionals have additional code that compares the +% argument~|####1| to two \TeX{} primitives which would wrongly be +% recognized as registers otherwise. Despite using \TeX{}'s +% primitive conditional construction, this does not break +% when~|####1| is itself a conditional, because branches of the +% conditionals are only skipped if |####1|~is one of the two +% primitives that are tested for (which are not \TeX{} conditionals). % \begin{macrocode} \group_begin: - \char_set_lccode:nn { `T } { `T } - \char_set_lccode:nn { `F } { `F } - \char_set_lccode:nn { `X } { `n } - \char_set_lccode:nn { `Y } { `t } - \char_set_lccode:nn { `Z } { `d } - \tl_map_inline:nn { A C E G H I K L M O P R S U X Y Z R " } - { \char_set_catcode:nn { `#1 } \c_twelve } -% \end{macrocode} -% We convert the token list to lower case and restore the catcode and -% lowercase code changes. -% \begin{macrocode} -\tex_lowercase:D +\cs_set_protected:Npn \@@_tmp:w #1#2#3 { - \group_end: -% \end{macrocode} -% First up is checking if something has been defined with -% \tn{chardef} or \tn{mathchardef}. This is easy since \TeX{} -% thinks of such tokens as hexadecimal so it stores them as -% |\char"|\meta{hex~number} or |\mathchar"|\meta{hex~number}. -% Grab until the first occurrence of |char"|, and compare what -% precedes with |\| or |\math|. In fact, the escape character -% may not be a backslash, so we compare with the result of -% converting some other control sequence to a string, namely -% |\char| or |\mathchar| (the auxiliary adds the |char| back). -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_chardef:N #1 { p , T , F , TF } - { - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_chardef:w - \token_to_meaning:N #1 CHAR" \q_stop - } - { \token_to_str:N \char } - } - \prg_new_conditional:Npnn \token_if_mathchardef:N #1 { p , T , F , TF } + \use:x { - \__str_if_eq_x_return:nn + \prg_new_conditional:Npnn \exp_not:c { token_if_ #1 :N } ####1 + { p , T , F , TF } { - \exp_after:wN \@@_if_chardef:w - \token_to_meaning:N #1 CHAR" \q_stop - } - { \token_to_str:N \mathchar } - } - \cs_new:Npn \@@_if_chardef:w #1 CHAR" #2 \q_stop { #1 CHAR } -% \end{macrocode} -% Dim registers are a bit more difficult since their \tn{meaning} -% has the form \tn{dimen}\meta{number}, and we must take care of the -% two primitives \tn{dimen} and \tn{dimendef}. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_dim_register:N #1 { p , T , F , TF } - { - \if_meaning:w \tex_dimen:D #1 - \prg_return_false: - \else: - \if_meaning:w \tex_dimendef:D #1 - \prg_return_false: - \else: - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_dim_register:w - \token_to_meaning:N #1 ZIMEX \q_stop - } - { \token_to_str:N \ } - \fi: - \fi: - } - \cs_new:Npn \@@_if_dim_register:w #1 ZIMEX #2 \q_stop { #1 ~ } -% \end{macrocode} -% Integer registers are one step harder since constants are implemented -% differently from variables, and we also have to take care of the -% primitives \tn{count} and \tn{countdef}. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_int_register:N #1 { p , T , F , TF } - { - % \token_if_chardef:NTF #1 { \prg_return_true: } - % { - % \token_if_mathchardef:NTF #1 { \prg_return_true: } - % { - \if_meaning:w \tex_count:D #1 - \prg_return_false: - \else: - \if_meaning:w \tex_countdef:D #1 - \prg_return_false: - \else: - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_int_register:w - \token_to_meaning:N #1 COUXY \q_stop - } - { \token_to_str:N \ } - \fi: - \fi: - % } - % } - } - \cs_new:Npn \@@_if_int_register:w #1 COUXY #2 \q_stop { #1 ~ } -% \end{macrocode} -% Muskip registers are done the same way as the dimension registers. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_muskip_register:N #1 - { p , T , F , TF } - { - \if_meaning:w \tex_muskip:D #1 - \prg_return_false: - \else: - \if_meaning:w \tex_muskipdef:D #1 - \prg_return_false: - \else: - \__str_if_eq_x_return:nn + \cs_if_exist:cT { tex_ #2 :D } { - \exp_after:wN \@@_if_muskip_register:w - \token_to_meaning:N #1 MUSKIP \q_stop + \exp_not:N \if_meaning:w ####1 \exp_not:c { tex_ #2 :D } + \exp_not:N \prg_return_false: + \exp_not:N \else: + \exp_not:N \if_meaning:w ####1 \exp_not:c { tex_ #2 def:D } + \exp_not:N \prg_return_false: + \exp_not:N \else: } - { \token_to_str:N \ } - \fi: - \fi: - } - \cs_new:Npn \@@_if_muskip_register:w #1 MUSKIP #2 \q_stop { #1 ~ } -% \end{macrocode} -% Skip registers. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_skip_register:N #1 - { p , T , F , TF } - { - \if_meaning:w \tex_skip:D #1 - \prg_return_false: - \else: - \if_meaning:w \tex_skipdef:D #1 - \prg_return_false: - \else: - \__str_if_eq_x_return:nn + \exp_not:N \__str_if_eq_x_return:nn { - \exp_after:wN \@@_if_skip_register:w - \token_to_meaning:N #1 SKIP \q_stop + \exp_not:N \exp_after:wN + \exp_not:c { @@_delimit_by_ #2 :w } + \exp_not:N \token_to_meaning:N ####1 + ? \tl_to_str:n {#2} \exp_not:N \q_stop } - { \token_to_str:N \ } - \fi: - \fi: - } - \cs_new:Npn \@@_if_skip_register:w #1 SKIP #2 \q_stop { #1 ~ } -% \end{macrocode} -% Toks registers. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_toks_register:N #1 - { p , T , F , TF } - { - \if_meaning:w \tex_toks:D #1 - \prg_return_false: - \else: - \if_meaning:w \tex_toksdef:D #1 - \prg_return_false: - \else: - \__str_if_eq_x_return:nn + { \exp_not:n {#3} } + \cs_if_exist:cT { tex_ #2 :D } { - \exp_after:wN \@@_if_toks_register:w - \token_to_meaning:N #1 YOKS \q_stop + \exp_not:N \fi: + \exp_not:N \fi: } - { \token_to_str:N \ } - \fi: - \fi: - } - \cs_new:Npn \@@_if_toks_register:w #1 YOKS #2 \q_stop { #1 ~ } -% \end{macrocode} -% Protected macros. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_protected_macro:N #1 - { p , T , F , TF } - { - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_protected_macro:w - \token_to_meaning:N #1 PROYECYEZ~MACRO \q_stop } - { \token_to_str:N \ } } - \cs_new:Npn \@@_if_protected_macro:w - #1 PROYECYEZ~MACRO #2 \q_stop { #1 ~ } -% \end{macrocode} -% Long macros and protected long macros share an auxiliary. -% \begin{macrocode} - \prg_new_conditional:Npnn \token_if_long_macro:N #1 { p , T , F , TF } - { - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_long_macro:w - \token_to_meaning:N #1 LOXG~MACRO \q_stop - } - { \token_to_str:N \ } - } - \prg_new_conditional:Npnn \token_if_protected_long_macro:N #1 - { p , T , F , TF } - { - \__str_if_eq_x_return:nn - { - \exp_after:wN \@@_if_long_macro:w - \token_to_meaning:N #1 LOXG~MACRO \q_stop - } - { \token_to_str:N \protected \token_to_str:N \ } - } - \cs_new:Npn \@@_if_long_macro:w #1 LOXG~MACRO #2 \q_stop { #1 ~ } -% \end{macrocode} -% Finally the \cs{tex_lowercase:D} ends! -% \begin{macrocode} } +\@@_tmp:w { chardef } { char" } { \token_to_str:N \char" } +\@@_tmp:w { mathchardef } { char" } { \token_to_str:N \mathchar" } +\@@_tmp:w { long_macro } { macro } { \tl_to_str:n { \long } macro } +\@@_tmp:w { protected_macro } { macro } + { \tl_to_str:n { \protected } macro } +\@@_tmp:w { protected_long_macro } { macro } + { \token_to_str:N \protected \tl_to_str:n { \long } macro } +\@@_tmp:w { dim_register } { dimen } { \token_to_str:N \dimen } +\@@_tmp:w { int_register } { count } { \token_to_str:N \count } +\@@_tmp:w { muskip_register } { muskip } { \token_to_str:N \muskip } +\@@_tmp:w { skip_register } { skip } { \token_to_str:N \skip } +\@@_tmp:w { toks_register } { toks } { \token_to_str:N \toks } +\group_end: % \end{macrocode} % \end{macro} -% \end{macro} % % \begin{macro}[pTF]{\token_if_primitive:N} % \begin{macro}[aux]{\@@_if_primitive:NNw, |