% \iffalse meta-comment % % Copyright (C) 2019-2024 % The LaTeX Project and any individual authors listed elsewhere % in this file. % % This file is part of the LaTeX base system. % ------------------------------------------- % % It may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % https://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008 or later. % % This file has the LPPL maintenance status "maintained". % % The list of all files belonging to the LaTeX base distribution is % given in the file `manifest.txt'. See also `legal.txt' for additional % information. % % The list of derived (unpacked) files belonging to the distribution % and covered by LPPL is defined by the unpacking scripts (with % extension .ins) which are part of the distribution. % % \fi % % \iffalse %%% From File: ltexpl.dtx % %<*driver> % \fi \ProvidesFile{ltexpl.dtx} [2024/04/17 v1.3h LaTeX Kernel (expl3-dependent code)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltexpl.dtx} \title{\filename} \date{\filedate} \author{% Joseph Wright} \providecommand\pkg[1]{\texttt{#1}} \begin{document} \MaintainedByLaTeXTeam{latex} \maketitle \DocInput{ltexpl.dtx} \end{document} % % \fi % % % \changes{v1.2d}{2020/08/21}{Dropped unused command} % % \section{\pkg{expl3}-dependent code} % % \MaybeStop{} % % \changes{v0.0}{2019-10-02}{Initial version} % % \subsection{Loader} % % \changes{v1.0a}{2020/03/02} % {Don't load expl3 if already in the format (gh/295)} % \changes{v1.1}{2020/03/05} % {Load xparse.ltx if \cs{NewDocumentCommand} is not defined % by expl3.ltx} % \changes{v1.2c}{2020/06/04} % {Define a local version of some \LaTeXe{} basic macros to support % package loading} % % \begin{macro}{\@kernel@after@enddocument, % \@kernel@after@enddocument@afterlastpage} % These two kernel hooks are used by the shipout code. They are % defined earlier here because the \pkg{lthooks} code adds material % to them. % \changes{v1.2h}{2020/12/18} % {Define kernel \cs{enddocument} hooks early} % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {kernel@enddocument hooks}{Define several kernel hooks} % \end{macrocode} % We only initialize these kernel hooks if they are not already % existing. Otherwise they would be set to \cs{@empty} on rollback % which would be wrong because code that has been added to them % may still have to be executed in the rollback situation . Instead % code that writes to them needs to handle the rollback as needed. % It is likely that we have to change that approach in the future, % but for now it should do. % (It is enough to test only for the existence of one hook, as all % got added at the same time.) % \changes{v1.3c}{2021/04/20}{Don't empty kernel hooks on rollback} % \begin{macrocode} \ifx\@kernel@after@enddocument\@undefined \let \@kernel@after@enddocument \@empty \let \@kernel@after@enddocument@afterlastpage \@empty % \end{macrocode} % % \begin{macro}{\@kernel@before@begindocument,\@kernel@after@begindocument} % For the similar reasons we also define those that are used in % \cs{document} because they too get material added to in early modules. % \begin{macrocode} \let \@kernel@before@begindocument \@empty \let \@kernel@after@begindocument \@empty \fi %\EndIncludeInRelease % \end{macrocode} % % \begin{macrocode} %\IncludeInRelease{0000/00/00}% % {kernel@enddocument hooks}{Define several kernel hooks} %\let\@kernel@after@enddocument\@undefined %\let\@kernel@after@enddocument@afterlastpage\@undefined %\let\@kernel@before@begindocument\@undefined %\let\@kernel@after@begindocument\@undefined % %\EndIncludeInRelease % \end{macrocode} % \end{macro} % \end{macro} % % First define some blank commands, so that in case something goes wrong while % loading \textsf{expl3}, we won't get strange \texttt{Undefined control % sequence} errors. % \changes{v1.3a}{2021/01/24}{Define \pkg{expl3} hooks conditionally} % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {\@expl@sys@load@backend@@}{Roll forward support}% \def\reserved@a#1{\ifdefined#1\else\def#1{}\fi} \reserved@a\@expl@sys@load@backend@@ \reserved@a\@expl@push@filename@@ \reserved@a\@expl@push@filename@aux@@ \reserved@a\@expl@pop@filename@@ %\EndIncludeInRelease % % \end{macrocode} % % \changes{v1.2d}{2020/07/08} % {Add a last-minute hook for \textsf{expl3}} % Create a hook for last-minute \pkg{expl3} material. % \begin{macrocode} %<*2ekernel> \def\@expl@finalise@setup@@{} % % \end{macrocode} % % Now define some basics to support loading \textsf{expl3}. These macros can % be defined here safely, because they are redefined later on by the kernel, % so we define simpler versions just to suit our needs. % \begin{macrocode} %<*2ekernel> \long\def\@gobble#1{} \long\def\@firstofone#1{#1} \long\def\@firstoftwo#1#2{#1} \long\def\@secondoftwo#1#2{#2} \long\def\IfFileExists#1{% \openin\@inputcheck"#1" % \ifeof\@inputcheck \expandafter\@secondoftwo \else \closein\@inputcheck \expandafter\@firstoftwo \fi} \long\def\@ifnextchar#1#2#3{% \let\reserved@d=#1% \def\reserved@a{#2}% \def\reserved@b{#3}% \futurelet\@let@token\@ifnch} \def\@ifnch{% \ifx\@let@token\reserved@d \expandafter\reserved@a \else \expandafter\reserved@b \fi} % % \end{macrocode} % % If we are doing a rollback with a format containing expl3 we % aren't reloading it as that creates havoc. This may need a % refined version! % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {expl3}{Pre-load expl3}% \expandafter\ifx\csname tex\string _let:D\endcsname\relax \expandafter\@firstofone \else \GenericInfo{}{Skipping: expl3 code already part of the format}% %<2ekernel> \expandafter\endinput % \expandafter\@gobble \fi % \end{macrocode} % % Check for the required primitive/engine support and the existence of % a loader. % \begin{macrocode} {% \IfFileExists{expl3.ltx} {% \ifnum0% \ifdefined\pdffilesize 1\fi \ifdefined\filesize 1\fi \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi \ifdefined\kanjiskip 1\fi >0 % \expandafter\@firstofone \else % \end{macrocode} % % In \texttt{2ekernel} mode, an error is fatal and building the format % is aborted. Use \verb=\batchmode \read -1 to \tokenlist=, which errors % with %\begin{verbatim} % ! Emergency stop. (cannot \read from terminal in nonstop modes) %\end{verbatim} % and aborts the \TeX{} run. In \texttt{latexrelease} mode, raise an % error and do nothing. Both ways, the error message shows the minimum % \textsf{expl3} engine requirements. % \begin{macrocode} %<2ekernel> \def~{ }\def\MessageBreak{^^J~~~~~~~~~~~~~~~}% %<2ekernel> \errmessage{LaTeX Error: % \@latex@error{% LaTeX requires the e-TeX primitives and additional\MessageBreak functionality available in the engines:\MessageBreak - pdfTeX v1.40\MessageBreak - XeTeX v0.99992\MessageBreak - LuaTeX v0.95\MessageBreak - e-(u)pTeX mid-2012\MessageBreak or later% % }\@ehd \expandafter\@gobble %<2ekernel> }\batchmode \read -1 to \reserved@a \fi } {% %<*2ekernel> \errmessage{LaTeX requires expl3}% \batchmode \read -1 to \reserved@a % % \end{macrocode} % We do not support a roll forward across 2019. You need to start % with 2019 if you want to get to 2020 or beyond. % \changes{v1.2g}{2020/11/24}{Support for roll forward (gh/434)} % \begin{macrocode} %<*latexrelease> \@latex@warning@no@line {You need a format that already contains a recent\MessageBreak expl3 as part of the kernel, e.g. at least a kernel\MessageBreak from 2019 to roll forward to that date!\MessageBreak --- I'm giving up!\MessageBreak\MessageBreak Note that manually loading the expl3 package\MessageBreak from your distribution is not enough}% \batchmode \read -1 to \reserved@a % }% {\input expl3.ltx }% } %\EndIncludeInRelease % % \end{macrocode} % To support roll-forward for the case where \textsf{xparse} is fully % integrated into the kernel, we do not need to repeat the complex test % above as we can simply look for the marker command. % \begin{macrocode} %\IncludeInRelease{2020/02/02}% % {expl3}{Pre-load expl3}% %\IfFileExists{expl3.ltx} % {% % \ifnum0% % \ifdefined\pdffilesize 1\fi % \ifdefined\filesize 1\fi % \ifdefined\luatexversion\ifnum\luatexversion>94 1\fi\fi % >0 % % \else % \message{Skipping expl3-dependent extensions} % \expandafter\@gobbletwo % \fi % } % {% % \message{Skipping expl3-dependent extensions}% % \@gobbletwo % }% %\input{expl3.ltx} %\EndIncludeInRelease % \end{macrocode} % % Now in |latexrelease| mode, redefine a few commands to avoid ``already % defined'' errors. % \changes{v1.3f}{2022/02/28} % {Move latexrelease redefinitions from ltcmd.dtx} % \begin{macrocode} %\@ifundefined{ExplSyntaxOff}{}{\latexrelease@postltexpl} % \end{macrocode} % % \changes{v1.3a}{2021/01/21} % {Move \pkg{xparse} rollback code to \texttt{ltcmd.dtx}} % % \subsection{Using expl3 code} % % In order to ease the implementation of some new features in % \LaTeXe\ we may (temporarily) use some coding based on the % \pkg{expl3}-code. % Such macros will eventually vanish and may be changed % unannounced. They are there for internal use in the \LaTeXe\ % kernel and are not meant to be used in third-party % packages. These macros will always have the \verb|@expl@| % prefix in their name. % % The rest of the name matches the \pkg{expl3} name but with all % underscores replaced by \texttt{@}s and the \texttt{:} replaced % by \texttt{@@}, e.g., %\begin{verbatim} % \cs_new_eq:NN \@expl@tl@trim@spaces@apply@@nN \tl_trim_spaces_apply:nN %\end{verbatim} % if that \pkg{expl3} command is needed in places that are others % coded in \LaTeXe{} conventions. % % % In this file, each release of LaTeX adds an \cs{IncludeInRelease} % block, in which the macros copied for that release were defined. % In case a rollback is requested, the entire block is changed. % % Each macro copied has a \cs{changes} entry to explain when and why % it was copied, so that further to that may spot it easily. % % Here \cs{cs\string_gset\string_eq:NN} is used, instead of the |new| % variant because if different releases use that same name for % different purposes, each can copy the macro without worrying about % redefinitions. % % \begin{macrocode} %\IncludeInRelease{2020/10/01}{\@expl@cs@to@str@@N}% % {expl3 macros added for the 2020-10-01 release}% % \end{macrocode} % % The expl3 activation needs to be inside the release guards as % otherwise rolling forward is broken in old kernels that do not % have expl3 loaded. % \changes{v1.2g}{2020/11/24}{Support for roll forward (gh/434)} % \begin{macrocode} \ExplSyntaxOn % \end{macrocode} % % \changes{v1.2e}{2020/08/19} % {Add \cs{@expl@cs@to@str@@N} and \cs{@expl@str@if@eq@@nnTF} % for \cs{NewCommandCopy} (gh/239)} % \begin{macrocode} \cs_gset_eq:NN \@expl@cs@to@str@@N \cs_to_str:N \cs_gset_eq:NN \@expl@str@if@eq@@nnTF \str_if_eq:nnTF % \end{macrocode} % % \changes{v1.2e}{2020/08/19} % {Add \cs{@expl@cs@\meta{thing}@spec@@N} % for \cs{ShowCommand} (gh/373)} % \changes{v1.3h}{2024/04/17} % {Rename \cs{@expl@cs@argument@spec@@N} to % \cs{@expl@cs@parameter@spec@@N} (gh/1014)} % \changes{v1.3h}{2024/04/17} % {Update name of \pkg{expl3} function} % \changes{v1.3h}{2024/04/17} % {Add a kernel-level copy of \cs{cs_parameter_spec:N}} % \begin{macrocode} \cs_gset_eq:NN \@expl@cs@prefix@spec@@N \cs_prefix_spec:N \cs_if_exist:NTF \cs_parameter_spec:N { \cs_gset_eq:NN \@expl@cs@parameter@spec@@N \cs_parameter_spec:N } { \cs_gset_eq:NN \@expl@cs@parameter@spec@@N \cs_argument_spec:N } \cs_gset_eq:NN \__kernel_cs_parameter_spec:N \@expl@cs@parameter@spec@@N \cs_gset_eq:NN \@expl@cs@replacement@spec@@N \cs_replacement_spec:N % \end{macrocode} % % \changes{v1.2f}{2020/09/06} % {Add \cs{@expl@str@map@function@@NN % and \cs{@expl@char@generate@@nn}} % for \cs{string@makeletter} (gh/386)} % \begin{macrocode} \cs_gset_eq:NN \@expl@str@map@function@@NN \str_map_function:NN \cs_gset_eq:NN \@expl@char@generate@@nn \char_generate:nn % \end{macrocode} % % \begin{macrocode} \ExplSyntaxOff % \end{macrocode} % % % Here we can't assume that expl3 is available. It will be if we % roll back but if this code is executed rolling forward it needs % to be pure 2e. % \changes{v1.2g}{2020/11/24}{Support for roll forward (gh/434)} % \begin{macrocode} %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}{\@expl@cs@to@str@@N}% % {expl3 macros added for the 2020-10-01 release}% %\let \@expl@cs@to@str@@N \@undefined %\let \@expl@str@if@eq@@nnTF \@undefined %\let \@expl@cs@prefix@spec@@N \@undefined %\let \@expl@cs@parameter@spec@@N \@undefined %\let \@expl@cs@replacement@spec@@N \@undefined %\let \@expl@str@map@function@@NN \@undefined %\EndIncludeInRelease % % \end{macrocode} % % % % % % % \section{Document-level command names for \pkg{expl3} functions} % % Current home for L3 programming layer functions that we make % directly available at the document level. This section may need % to be moved later (after \cs{NewDocumentCommand} is defined in % case we want to use that in the setup). % % % \DescribeMacro\fpeval % The expandable command \cs{fpeval} takes as its argument a % floating point expression and produces a result using the normal % rules of mathematics. As this command is expandable it can be % used where \TeX{} requires a number and for example within a % low-level \cs{edef} operation to give a purely numerical % result. See \texttt{usrguide3} for further explanation. % % \DescribeMacro\inteval % \DescribeMacro\dimeval % \DescribeMacro\skipeval % The expandable command \cs{inteval} takes as its argument an % integer expression and produces a result using the normal rules % of mathematics. The operations recognised are |+|, |-|, |*| and % |/| plus parentheses. Division occurs with \emph{rounding}, and % ties are rounded away from zero. As this command is expandable it % can be used where \TeX{} requires a number and for example within % a low-level \cs{edef} operation to give a purely numerical % result. See \texttt{usrguide3} for further explanation. % \cs{dimeval} and \cs{skipeval} are similar, but generate fixed and % rubber length values, respectively. % % % % \begin{macro}{\fpeval,\inteval,\dimeval,\skipeval} % A document level wrapper around the code level function for % floating point calculations. % \changes{v1.3d}{2021/11/30}{Moved over from \texttt{xfp} package (gh/711)} % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2022/06/01}% % {\fpeval}{fp and int calculations}% \ExplSyntaxOn \cs_new_eq:NN \fpeval \fp_eval:n % \end{macrocode} % And a few more, this time wrappers around the e\TeX{} primitives. % \begin{macrocode} \cs_new_eq:NN \inteval \int_eval:n % \end{macrocode} % % \changes{v1.3d}{2021/12/07}{Added \cs{dimeval} and \cs{skipeval} (gh/711)} % \begin{macrocode} \cs_new_eq:NN \dimeval \dim_eval:n \cs_new_eq:NN \skipeval \skip_eval:n \ExplSyntaxOff % \end{macrocode} % \end{macro} % % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\fpeval}{fp and int calculations}% % %\let\fpeval\@undefined %\let\inteval\@undefined %\let\dimeval\@undefined %\let\skipeval\@undefined %\EndIncludeInRelease % \end{macrocode} % % % \DescribeMacro\UseName % \DescribeMacro\ExpandArgs % When declaring new commands with \cs{NewDocumentCommand} or % \cs{NewCommandCopy} or similar, it is sometimes necessary to % ``construct'' the csname. As a general mechanism the L3 % programming layer has \cs{exp\_args:N...} for this, but there is % no mechanism for it if \cs{ExplSyntaxOn} is not active. We % therefore offer a few of these commands also with CamelCase names. % % % \begin{macro}{\UseName,\ExpandArgs} % A document wrapper for changing arguments to cs names for use % with \cs{NewDocumentCommand} and similar functions. % % \changes{v1.3d}{2021/12/28}{Added document level names for \cs{exp\_args:Nc} and the like (gh/735)} % \changes{v1.3e}{2022/01/06}{Adjust document level names for \cs{exp\_args:Nc} and the like (gh/735)} % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2022/06/01}% % {\ExpandArgs}{Some pre-expansion commands}% \ExplSyntaxOn \cs_new_eq:NN \UseName \use:c % \end{macrocode} % % \begin{macrocode} \cs_new:Npn \ExpandArgs #1 { \cs_if_exist_use:cF { exp_args:N #1 } { \msg_expandable_error:nnn { kernel } { unknown-arg-expansion } {#1} } } \msg_new:nnn { kernel } { unknown-arg-expansion } { Unknown~arg~expansion~"#1" } \ExplSyntaxOff % \end{macrocode} % \end{macro} % % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\ExpandArgs}{Some pre-expansion commands}% % %\let\UseName\@undefined %\let\ExpandArgs\@undefined %\EndIncludeInRelease % \end{macrocode} % % \DescribeMacro\IfExplAtLeastTF % A pretty simple wrapper. % % \begin{macro}{\IfExplAtLeastTF} % \changes{v1.3g}{2023/10/13}{Provide a test for \pkg{expl3} date (gh/1004)} % \begin{macrocode} %<*2ekernel|latexrelease> %\IncludeInRelease{2023/11/01}% % {\IfExplAtLeastTF}{Test for expl3 date}% \def\IfExplAtLeastTF{\@ifl@t@r\ExplLoaderFileDate} % \end{macrocode} % \end{macro} % We make sure the command is always available. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\IfExplAtLeastTF}{Test for expl3 date}% % %\def\IfExplAtLeastTF{\@ifl@t@r\ExplLoaderFileDate} %\EndIncludeInRelease % \end{macrocode} % % \Finale