% \iffalse meta-comment % % Copyright (C) 1993-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: ltdefns.dtx %<*driver> % \fi \ProvidesFile{ltdefns.dtx} [2022/11/24 v1.5s LaTeX Kernel (definition commands)] % \iffalse \documentclass{ltxdoc} \GetFileInfo{ltdefns.dtx} \title{\filename} \date{\filedate} \author{% Johannes Braams\and David Carlisle\and Alan Jeffrey\and Leslie Lamport\and Frank Mittelbach\and Chris Rowley\and Rainer Sch\"opf} \begin{document} \MaintainedByLaTeXTeam{latex} \maketitle \DocInput{\filename} \end{document} % % \fi % % % \changes{v1.0n}{1994/05/10}{(ASAJ) Added % \cs{DeclareProtectedCommand}.} % \changes{v1.0p}{1994/05/12}{(ASAJ) Fixed a bug with \cs{relax} % which was % using \cs{@gobble} before defining it.} % \changes{v1.0q}{1994/05/13}{(ASAJ) Renamed % \cs{DeclareProtectedCommand} to % \cs{DeclareRobustCommand}. Removed \cs{@if@short@command}.} % \changes{v1.0q}{1994/05/13}{(ASAJ) Replaces \cs{space} by `~' in % \cs{csname}.} % \changes{v1.0r}{1994/05/13}{(ASAJ) Added logging message to % \cs{DeclareProtectedCommand}.} % \changes{v1.0s}{1994/05/13}{(ASAJ) Added \cs{@backslashchar}.} % \changes{v1.0s}{1994/05/13}{(ASAJ) Coded \cs{@ifdefinable} more % efficiently.} % \changes{v1.1a}{1994/05/16}{(ASAJ) Split from ltinit.dtx.} % \changes{v1.1b}{1994/05/17}{(ASAJ) Removed warnings and logging to % lterror.dtx.} % \changes{v1.1b}{1994/05/17}{(ASAJ) Added definitions for protect.} % \changes{v1.1c}{1994/05/17}{(ASAJ) Redid definitions for protect.} % \changes{v1.1d}{1994/05/19}{(RmS) Added definitions for % \cs{@namedef} and \cs{@nameuse} again.} % \changes{v1.1e}{1994/05/20}{Changed command name from % \cs{@checkcommand} to \cs{CheckCommand}.} % \changes{v1.1f}{1994/05/22}{Use new warning and error cmds} % \changes{v1.2a}{1994/10/18}{Add star-forms for all commands} % \changes{v1.2a}{1994/10/18}{Add extra test for \cs{endgraf}} % \changes{v1.2b}{1994/10/25}{Documentation improvements} % \changes{v1.2c}{1994/10/30}{(CAR)\cs{@onelevel@sanitize} added} % \changes{v1.2f}{1994/10/30}{(DPC)\cs{newwrite}'s moved to ltfiles} % \changes{v1.0g}{1994/11/17} % {\cs{@tempa} to \cs{reserved@a}} % \changes{v1.0p}{1995/07/13}{Updates to documentation} % \changes{v1.4b}{2015/02/21} % {Removed autoload support} % \changes{v1.5l}{2020/08/21}{Integration of new hook management interface} % % \section{Definitions} % % This section contains commands used in defining other macros. % % \MaybeStop{} % % \begin{macrocode} %<*2ekernel> % \end{macrocode} % % % \subsection{Initex initializations} % % \task{???}{This section needs extension} % % \begin{macro}{\two@digits} % \changes{LaTeX2e}{1993/11/23}{Macro added} % Prefix a number less than 10 with `0'. % \begin{macrocode} \def\two@digits#1{\ifnum#1<10 0\fi\number#1} % \end{macrocode} % \end{macro} % % \changes{v1.2e}{1994/11/04}{Added \cs{set@display@protect} to % \cs{typeout}. ASAJ.} % % \begin{macro}{\typeout} % Display something on the terminal. % \changes{v1.5g}{2020/05/15}{Allow \cs{par} in the argument (gh/335)} % \begin{macrocode} % %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {\typeout}{Allow "par" in \typeout}% \protected\long\def\typeout#1{\begingroup \set@display@protect \def\par{^^J^^J}% \immediate\write\@unused{#1}\endgroup} % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\typeout}{Allow "par" in \typeout}% % %\def\typeout#1{\begingroup\set@display@protect % \immediate\write\@unused{#1}\endgroup} %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\newlinechar} % A char to be used as new-line in output to files. % \begin{macrocode} \newlinechar`\^^J % \end{macrocode} % \end{macro} % % \subsection{Saved versions of \TeX{} primitives} % % The TeX primitive |\foo| is saved as |\@@foo|. % The following primitives are handled in this way: % \begin{macro}{\@@par} % \begin{macrocode} \let\@@par=\par %\let\@@input=\input %%% moved earlier %\let\@@end=\end %%% % \end{macrocode} % \end{macro} % % \begin{macro}{\@@hyph} % Save original primitive definition. % \begin{macrocode} \let\@@hyph=\- % \end{macrocode} % \end{macro} % % % \begin{macro}{\@@italiccorr} % Save the original italic correction. % \changes{v1.0a}{1994/03/07}{Macro added} % \begin{macrocode} \let\@@italiccorr=\/ % \end{macrocode} % \end{macro} % % \begin{macro}{\@height} % \begin{macro}{\@depth} % \begin{macro}{\@width} % \begin{macro}{\@minus} % \changes{LaTeX2e}{1993/11/22}{Macro added} % \begin{macro}{\@plus} % \changes{LaTeX2e}{1993/11/22}{Macro added} % % The following definitions save token space. E.g., using % |\@height| instead of height saves 5 tokens at the cost in time % of one macro expansion. % \begin{macrocode} \def\@height{height} \def\@depth{depth} \def\@width{width} \def\@minus{minus} \def\@plus{plus} % \end{macrocode} % \begin{macro}{\hb@xt@} % \changes{v1.2k}{1995/05/07}{Macro added} % The next one is another 100 tokens worth. % \begin{macrocode} \def\hb@xt@{\hbox to} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macrocode} \message{hacks,} % \end{macrocode} % % \subsection{Command definitions} % % This section defines the following commands: % % \DescribeMacro % {\@namedef}\marg{NAME}\\ Expands to |\def\|\marg{NAME}, % except name can contain any characters. % % \DescribeMacro % {\@nameuse}\marg{NAME}\\ % Expands to |\|\marg{NAME}. % % \DescribeMacro % {\@ifnextchar} X\marg{YES}\marg{NO}\\ % Expands to \meta{YES} if next character is an `X', % and to \meta{NO} otherwise. % (Uses |\reserved@a|--|\reserved@c|.) % NOTE: GOBBLES ANY SPACE FOLLOWING IT. % % \DescribeMacro % {\@ifstar}\marg{YES}\marg{NO}\\ % Gobbles following spaces and then tests if next the % character is a '*'. If it is, then it gobbles the % `*' and expands to \meta{YES}, otherwise it expands to \meta{NO}. % % \DescribeMacro % {\@dblarg}\marg{CMD}\marg{ARG}\\ % Expands to |\|\marg{CMD}\oarg{ARG}\marg{ARG}. Use % |\@dblarg\CS| when |\CS| takes arguments |[ARG1]{ARG2}|, % where default is| ARG1| = |ARG2|. % % \DescribeMacro % {\@ifundefined}\marg{NAME}\marg{YES}\marg{NO}\\ % : If \cs{NAME} is undefined then it executes \meta{YES}, % otherwise it executes \meta{NO}. More precisely, % true if \cs{NAME} either undefined or = |\relax|. % % \DescribeMacro % {\@ifdefinable}|\NAME|\marg{YES} % Executes \meta{YES} if the user is allowed to define |\NAME|, % otherwise it gives an error. The user can define |\NAME| % if |\@ifundefined{NAME}| is true, '|NAME|' $\neq$ '|relax|' % and the first three letters of '|NAME|' are not % '|end|', and if |\endNAME| is not defined. % % \DescribeMacro % \newcommand|*|\marg{\cs{FOO}}\oarg{i}\marg{TEXT}\\ % User command to define |\FOO| to be a macro with % i arguments (i = 0 if missing) having the definition % \meta{TEXT}. Produces an error if |\FOO| already % defined. % % Normally the command is defined to be |\long| (ie it may % take multiple paragraphs in its argument). In the % star-form, the command is not defined as |\long| and a % blank line in any argument to the command would generate % an error. % % \DescribeMacro % \renewcommand|*|\marg{\cs{FOO}}\oarg{i}\marg{TEXT}\\ % Same as |\newcommand|, except it checks if |\FOO| already defined. % % \DescribeMacro % \newenvironment|*|\marg{FOO}\oarg{i}\marg{DEF1}\marg{DEF2}\\ % equivalent to:\\ % |\newcommand{\FOO}[i]{DEF1}| |\def{\endFOO}{DEF2}|\\ % (or the appropriate star forms). % % \DescribeMacro % \renewenvironment\\ Obvious companion to |\newenvironment|. % % \DescribeMacro % \@cons : See description of |\output| routine. % % \DescribeMacro{\@car} % |\@car T1 T2 ... Tn\@nil| == |T1| (unexpanded) % % \DescribeMacro{\@cdr} % |\@cdr T1 T2 ... Tn\@ni|l == |T2 ... Tn| (unexpanded) % % \DescribeMacro % \typeout\marg{message}\\ Produces a warning message on the terminal. % % \DescribeMacro % \typein\marg{message}\\ % Types message, asks the user to type in a command, then % executes it % % \DescribeMacro % \typein\oarg{\cs{CS}}\marg{MSG}\\ % Same as above, except defines |\CS| to be the input % instead of executing it. % % \changes{LaTeX209}{1992/03/18} % {(RMS) changed input channel from 0 to \cs{@inputcheck} to avoid % conflicts with other channels allocated by \cs{newread}} % % \begin{macro}{\typein} % % \changes{v1.2k}{1995/05/08}{Use \cs{@firstofone}} % \changes{v1.2l}{1995/05/08}{Remove unnecessary braces} % \changes{v1.2l}{1995/05/08}{Replace \cs{def} by \cs{let}} % \changes{v1.2m}{1995/05/24}{(DPC) New implementation} % \changes{v1.2u}{1995/10/16}{(DPC) Use \cs{@testopt} /1911} % \begin{macrocode} \def\typein{% \let\@typein\relax \@testopt\@xtypein\@typein} % \end{macrocode} % % \changes{v1.2r}{1995/10/03} % {Add missing \cs{@typein} for /1710 (from patch file)} % \changes{v1.4a}{2015/01/03}{use modified definition in luatex} % \begin{macrocode} \ifx\directlua\@undefined % \end{macrocode} % % \begin{macrocode} \def\@xtypein[#1]#2{% \typeout{#2}% \advance\endlinechar\@M \read\@inputcheck to#1% \advance\endlinechar-\@M \@typein}% % \end{macrocode} % % \begin{macrocode} \else % \end{macrocode} % % \begin{macrocode} \def\@xtypein[#1]#2{% \typeout{#2}% \begingroup \endlinechar\m@ne \read\@inputcheck to#1% \expandafter\endgroup \expandafter\def\expandafter#1\expandafter{#1}% \@typein}% % \end{macrocode} % % \begin{macrocode} \fi % \end{macrocode} % \end{macro} % % \begin{macro}{\@namedef} % \begin{macrocode} \def\@namedef#1{\expandafter\def\csname #1\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\@nameuse} % \begin{macrocode} \def\@nameuse#1{\csname #1\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\@cons} % \begin{macrocode} \def\@cons#1#2{\begingroup\let\@elt\relax\xdef#1{#1\@elt #2}\endgroup} % \end{macrocode} % \end{macro} % % \begin{macro}{\@car} % \begin{macro}{\@cdr} % \begin{macrocode} \def\@car#1#2\@nil{#1} \def\@cdr#1#2\@nil{#2} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@carcube} % |\@carcube T1 ... Tn\@nil| = |T1| |T2| |T3| , $n > 3$ % \changes{v1.5k}{2020/08/19}{Made \cs{long} for \cs{NewCommandCopy}} % \changes{v1.5o}{2020/11/25}{Added missing latexrelease entry} % \begin{macrocode} % %\IncludeInRelease{2020/10/01}{\@carcube}{Make \@carcube long}% %<*2ekernel|latexrelease> \long\def\@carcube#1#2#3#4\@nil{#1#2#3} % %\EndIncludeInRelease % %\IncludeInRelease{0000/00/00}{\@carcube}{Undo: Make \@carcube long}% %\def\@carcube#1#2#3#4\@nil{#1#2#3} %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % % % \begin{macro}{\@onlypreamble} % \begin{macro}{\@preamblecmds} % This macro adds its argument to the list of commands stored in % |\@preamblecmds| to be % disabled after |\begin{document}|. These commands are redefined % to generate |\@notprerr| at this point. % \begin{macrocode} \def\@preamblecmds{} \def\@onlypreamble#1{% \expandafter\gdef\expandafter\@preamblecmds\expandafter{% \@preamblecmds\do#1}} \@onlypreamble\@onlypreamble \@onlypreamble\@preamblecmds % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@star@or@long} % \changes{v1.2a}{1994/10/18}{macro added} % Look ahead for a |*|. If present reset |\l@ngrel@x| so that % the next definition, |#1|, will be non-long. % \begin{macrocode} \def\@star@or@long#1{% \@ifstar {\let\l@ngrel@x\relax#1}% {\let\l@ngrel@x\long#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\l@ngrel@x} % This is either |\relax| or |\long| depending on whether the |*|-form % of a definition command is being executed. % \begin{macrocode} \let\l@ngrel@x\relax % \end{macrocode} % \end{macro} % % \begin{macro}{\newcommand} % \changes{LaTeX2e}{1993/11/23}{Macro reimplemented and extended} % User level |\newcommand|.% % \begin{macrocode} \def\newcommand{\@star@or@long\new@command} % \end{macrocode} % % \begin{macro}{\new@command} % \changes{v1.2u}{1995/10/16}{(DPC) Use \cs{@testopt} /1911} % \begin{macrocode} \def\new@command#1{% \@testopt{\@newcommand#1}0} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@newcommand} % \changes{LaTeX2e}{1993/11/23}{Macro added} % \begin{macro}{\@argdef} % \changes{LaTeX2e}{1993/11/23}{Macro added} % \begin{macro}{\@xargdef} % \changes{LaTeX2e}{1993/11/23}{Macro interface changed} % \changes{v1.1g}{2004/01/23}{Use kernel version of % \cs{@ifnextchar} (pr/3501)} % Handling arguments for |\newcommand|. % \begin{macrocode} \def\@newcommand#1[#2]{% \kernel@ifnextchar [{\@xargdef#1[#2]}% {\@argdef#1[#2]}} % \end{macrocode} % Define |#1| if it is definable. % % Both here and in |\@xargdef| the replacement text is absorbed as % an argument because if we are not allowed to make the definition % we have to get rid of it completely. % \begin{macrocode} \long\def\@argdef#1[#2]#3{% \@ifdefinable #1{\@yargdef#1\@ne{#2}{#3}}} % \end{macrocode} % % \changes{v1.2q}{1995/10/02} % {New implementation, using \cs{@test@opt}} % Handle the second optional argument. % \begin{macrocode} \long\def\@xargdef#1[#2][#3]#4{% \@ifdefinable#1{% % \end{macrocode} % Define the actual command to be:\\ % |\def\foo{\@protected@testopt\foo\\foo{default}}|\\ % where |\\foo| is a csname generated from applying |\csname| and % |\string| to |\foo|, ie the actual name contains a backslash and % therefore can't clash easily with existing command names. % ``Default'' is the contents of the second optional argument of % |(re)newcommand|. % % \changes{v1.2z2}{1998/03/04} % {Unnecessary \cs{expandafter} removed: pr/2758} % \begin{macrocode} \expandafter\def\expandafter#1\expandafter{% \expandafter \@protected@testopt \expandafter #1% \csname\string#1\endcsname {#3}}% % \end{macrocode} % Now we define the internal macro ie |\\foo| which is supposed to % pick up all arguments (optional and mandatory). % \begin{macrocode} \expandafter\@yargdef \csname\string#1\endcsname \tw@ {#2}% {#4}}} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\@testopt} % \changes{v1.2q}{1995/10/02} % {Macro added} % \changes{v1.3a}{1999/01/07} % {made long and brace optional arg. latex/2896} % This macro encapsulates the most common call to |\@ifnextchar|, saving % several tokens each time it is used in the definition of a command % with an optional argument. % |#1| The code to execute in the case that there is a |[| need not be % a single token but can be any sequence of commands that `expects' to % be followed by |[|. If this command were only used in |\newcommand| % definitions then |#1| would be a single token and the braces could % be omitted from |{#1}| in the definition below, saving a bit of % memory. % \changes{v1.1g}{2004/01/23}{Use kernel version of % \cs{@ifnextchar} (pr/3501)} % \begin{macrocode} \long\def\@testopt#1#2{% \kernel@ifnextchar[{#1}{#1[{#2}]}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@protected@testopt} % \changes{v1.2q}{1995/10/02} % {Macro added} % Robust version of |\@testopt|. The extra argument (|#1|) must be a % single token. If protection is needed the call expands to |\protect| % applied to this token, and the 2nd and 3rd arguments are % discarded (by |\@x@protect|). Otherwise |\@testopt| is called on % the 2nd and 3rd arguments. % % This method of making commands robust avoids the need for using up % two csnames per command, the price is the extra expansion time % for the |\ifx| test. % \begin{macrocode} \def\@protected@testopt#1{% \ifx\protect\@typeset@protect \expandafter\@testopt \else \@x@protect#1% \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\@yargdef} % \begin{macro}{\@yargd@f} % \changes{v1.3f}{1999/04/29}{New macro added} % % \changes{LaTeX2e}{1993/11/23}{Macro interface changed} % \changes{LaTeX2e}{1993/11/23}{Avoid \cs{@?@?} token} % \changes{v1.0b}{1994/03/12}{Name changed from \cs{XXX@argdef}} % \changes{v1.3c}{1999/01/18}{New implementation DPC /2942} % \changes{v1.3d}{1999/02/09}{catch bad argument forms by re-inserting \#3} % \changes{v1.3f}{1999/04/29}{Full expansion and conversion needed % for digit in new version, see pr/3013} % % These generate a primitive argument specification, from a % \LaTeX\ |[|\meta{digit}|]| form; in fact \meta{digit} can be % anything such that |\number|~\meta{digit} is single digit. % % Reorganised slightly so that |\renewcommand{\reserved@a}[1]{foo}| % works. I am not sure this is worth it, as a following % |\newcommand| would over-write the definition of |\reserved@a|. % % Recall that \LaTeX2.09 goes into an infinite loop with\\ % |\renewcommand[1]{\@tempa}{foo}|\\ % (DPC 6 October 93). % % Reorganised again (DPC 1999). Rather than make a loop to % construct the argument spec by counting, just extract the % required argument spec by using a delimited argument (delimited % by the digit). This is faster and uses less tokens. The coding % is slightly odd to preserve the old interface (using |#2| = % |\tw@| as the flag to surround the first argument with |[]|. But % the new method did not allow for the number of arguments |#3| not % being given as an explicit digit; hence (further expansion of % this argument and use of) |\number| was added later in 1999. % % It is not clear why these are still |\long|. % % \begin{macrocode} \long \def \@yargdef #1#2#3{% \ifx#2\tw@ \def\reserved@b##11{[####1]}% \else \let\reserved@b\@gobble \fi \expandafter \@yargd@f \expandafter{\number #3}#1% } % \end{macrocode} % % \begin{macrocode} \long \def \@yargd@f#1#2{% \def \reserved@a ##1#1##2##{% \expandafter\def\expandafter#2\reserved@b ##1#1% }% \l@ngrel@x \reserved@a 0##1##2##3##4##5##6##7##8##9###1% } % \end{macrocode} % % \end{macro} % \end{macro} % % \begin{macro}{\@reargdef} % \changes{LaTeX2e}{1993/12/20} % {Kept old version of \cs{@reargdef}, for array.sty} % \changes{v1.0b}{1994/03/12}{New defn, in terms of \cs{@yargdef}} % \changes{v1.2y}{1996/07/26}{third arg picked up by \cs{@yargdef}} % \begin{macrocode} \long\def\@reargdef#1[#2]{% \@yargdef#1\@ne{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\renewcommand} % Check the command name is already used. If not give an error % message. Then temporarily % disable |\@ifdefinable| then call |\newcommand|. (Previous % version |\let#1=\relax| but this does not work too well if |#1| % is |\@temp|\emph{a--e}.) % \changes{LaTeX2e}{1993/11/23}{Macro reimplemented and extended} % \changes{v1.1f}{1994/05/02}{Removed surplus \cs{space} in error} % \begin{macrocode} \def\renewcommand{\@star@or@long\renew@command} % \end{macrocode} % % \begin{macro}{\renew@command} % \changes{v1.2y}{1996/07/26}{use \cs{relax} in place of empty arg} % \changes{v1.2y}{1996/07/26}{use \cs{noexpand} instead of \cs{string}} % \changes{v1.2z1}{1997/10/21}{Use \cs{begingroup}/\cs{endgroup} rather % than braces for grouping, to avoid generating empty math atom.} % \changes{v1.5e}{2018/09/26}{Always explicitly generate a space after the csname and % not rely on \cs{noexpand} to save tokens (git/41)} % \begin{macrocode} \def\renew@command#1{% \begingroup \escapechar\m@ne\xdef\@gtempa{{\string#1}}\endgroup \expandafter\@ifundefined\@gtempa {\@latex@error{Command \string#1 undefined}\@ehc}% \relax \let\@ifdefinable\@rc@ifdefinable \new@command#1} % \end{macrocode} % \end{macro} % \end{macro} % % \changes{v1.0n}{1994/05/10}{Removed braces around \cs{@ifundefined} % argument. ASAJ.} % \changes{v1.0s}{1994/05/13}{Coded more efficiently, thanks to FMi.} % % \begin{macro}{\@ifdefinable} % \begin{macro}{\@@ifdefinable} % \begin{macro}{\@rc@ifdefinable} % Test if user is allowed to define a command. % \begin{macrocode} \long\def\@ifdefinable #1#2{% \edef\reserved@a{\expandafter\@gobble\string #1}% \@ifundefined\reserved@a {\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}% \ifx \reserved@b\@qend \@notdefinable\else \ifx \reserved@a\@qrelax \@notdefinable\else #2% \fi \fi}% \@notdefinable} % \end{macrocode} % Saved definition of |\@ifdefinable|. % \begin{macrocode} \let\@@ifdefinable\@ifdefinable % \end{macrocode} % Version of |\@ifdefinable| for use with |\renewcommand|. Does % not do the check this time, but restores the normal definition. % \begin{macrocode} \long\def\@rc@ifdefinable#1#2{% \let\@ifdefinable\@@ifdefinable #2} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\newenvironment} % Define a new user environment. % |#1| is the environment name. |#2#| Grabs all the tokens up to % the first |{|. These will be any optional arguments. They are not % parsed at this point, but are just passed to |\@newenv| which % will eventually call |\newcommand|. Any optional arguments will % then be parsed by |\newcommand| as it defines the command that % executes the `begin code' of the environment. % % This |#2#| trick removed with version 1.2i as it fails if a |{| % occurs in the optional argument. Now use |\@ifnextchar| directly. % \begin{macrocode} \def\newenvironment{\@star@or@long\new@environment} % \end{macrocode} % % \begin{macro}{\new@environment} % \changes{v1.2i}{1995/04/25}{Parse arguments slowly but safely /1507} % \changes{v1.2u}{1995/10/16}{(DPC) Use \cs{@testopt} /1911} % \begin{macrocode} \def\new@environment#1{% \@testopt{\@newenva#1}0} % \end{macrocode} % % \begin{macro}{\@newenva} % \changes{v1.1g}{2004/01/23}{Use kernel version of % \cs{@ifnextchar} (pr/3501)} % \begin{macrocode} \def\@newenva#1[#2]{% \kernel@ifnextchar [{\@newenvb#1[#2]}{\@newenv{#1}{[#2]}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@newenvb} % \changes{v1.3a}{1999/01/07} % {made long and brace optional arg. latex/2896} % \begin{macrocode} \def\@newenvb#1[#2][#3]{\@newenv{#1}{[#2][{#3}]}} % \end{macrocode} % \end{macro} % % \end{macro} % \end{macro} % % % \begin{macro}{\renewenvironment} % Redefine an environment. % For |\renewenvironment| disable |\@ifdefinable| and then call % |\newenvironment|. It is OK to |\let| the argument to |\relax| % here as there should not be a |@temp|\ldots\ environment. % \changes{LaTeX2e}{1993/11/23}{Macro reimplemented and extended} % \changes{v1.1f}{1994/05/02}{Removed surplus \cs{space} in error} % \begin{macrocode} \def\renewenvironment{\@star@or@long\renew@environment} % \end{macrocode} % % \begin{macro}{\renew@environment} % \changes{v1.2a}{1994/10/18}{reset end command} % \changes{v1.2y}{1996/07/26}{use \cs{relax} in place of empty arg} % \begin{macrocode} \def\renew@environment#1{% \@ifundefined{#1}% {\@latex@error{Environment #1 undefined}\@ehc }\relax \expandafter\let\csname#1\endcsname\relax \expandafter\let\csname end#1\endcsname\relax \new@environment{#1}} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@newenv} % \changes{LaTeX2e}{1993/11/23}{Macro interface changed} % \changes{v1.2h}{1994/11/24}{Added test for \cs{endgraf}} % The internal version of |\newenvironment|. % % Call |\newcommand| to define the \meta{begin-code} for the % environment. |\def| is used for the \meta{end-code} as it does % not take arguments. (but may contain |\par|s) % % Make sure that an attempt to define a `graf' or `group' environment % fails by temporarily letting the undefined \verb=\...= (begin code) to % the definition of \verb=\end...= and as a result we get an error if that % has a definition. % \begin{macrocode} \long\def\@newenv#1#2#3#4{% \@ifundefined{#1}% {\expandafter\let\csname#1\expandafter\endcsname \csname end#1\endcsname}% \relax \expandafter\new@command \csname #1\endcsname#2{#3}% \l@ngrel@x\expandafter\def\csname end#1\endcsname{#4}} % \end{macrocode} % \end{macro} % % \begin{macro}{\newif} % \changes{v1.1l}{1995/05/24}{(DPC) New implementation} % And here's a different sort of allocation: % For example, % |\newif\iffoo| creates |\footrue|, |\foofalse| to go with |\iffoo|. % \begin{macrocode} \def\newif#1{% \count@\escapechar \escapechar\m@ne \let#1\iffalse \@if#1\iftrue \@if#1\iffalse \escapechar\count@} % \end{macrocode} % % \begin{macro}{\@if} % \begin{macrocode} \def\@if#1#2{% \expandafter\def\csname\expandafter\@gobbletwo\string#1% \expandafter\@gobbletwo\string#2\endcsname {\let#1#2}} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\providecommand} % |\providecommand| takes the same arguments as |\newcommand|, but % discards them if |#1| is already defined, Otherwise it just acts like % |\newcommand|. This implementation currently leaves any discarded % definition in |\reserved@a| (and possibly |\\reserved@a|) this % wastes a bit of space, but it will be reclaimed as soon as these % scratch macros are redefined. % % \changes{LaTeX2e}{1993/11/22}{Macro added} % \begin{macrocode} \def\providecommand{\@star@or@long\provide@command} % \end{macrocode} % % \begin{macro}{\provide@command} % \changes{v1.2z}{1997/09/09}{Use \cs{begingroup} to avoid generating % math ords if used in math mode. pr/2573} % \begin{macrocode} \def\provide@command#1{% \begingroup \escapechar\m@ne\xdef\@gtempa{{\string#1}}% \endgroup \expandafter\@ifundefined\@gtempa {\def\reserved@a{\new@command#1}}% {\def\reserved@a{\renew@command\reserved@a}}% \reserved@a}% % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\CheckCommand} % \changes{LaTeX2e}{1993/11/22}{Macro added} % \changes{v1.1e}{1994/05/20}{Changed name from \cs{@checkcommand} to % \cs{CheckCommand}.} % |\CheckCommand| takes the same arguments as |\newcommand|. If % the command already exists, with the same definition, then % nothing happens, otherwise a warning is issued. Useful for % checking the current state before a macro package starts % redefining things. Currently two macros are considered to have % the same definition if they are the same except for different % default arguments. That is, if the old definition was: % |\newcommand\xxx[2][a]{(#1)(#2)}| then % |\CheckCommand\xxx[2][b]{(#1)(#2)}| would \emph{not} generate a % warning, but, for instance |\CheckCommand\xxx[2]{(#1)(#2)}| % would. % \begin{macrocode} \def\CheckCommand{\@star@or@long\check@command} % \end{macrocode} % |\CheckCommand| is only available in the preamble part of the % document. % \begin{macrocode} \@onlypreamble\CheckCommand % \end{macrocode} % % \begin{macro}{\check@command} % \begin{macrocode} \def\check@command#1#2#{\@check@c#1{#2}} \@onlypreamble\check@command % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@check@c} % \changes{v1.2i}{1995/04/25}{Make \cs{long} for latex/1346} % |\CheckCommand| itself just grabs all the arguments we need, % without actually looking for |[| optional argument forms. Now % define |\reserved@a|. If |\\reserved@a| is then defined, compare it % with the ``|\#1|' otherwise compare |\reserved@a| with |#1|. % \begin{macrocode} \long\def\@check@c#1#2#3{% \expandafter\let\csname\string\reserved@a\endcsname\relax \renew@command\reserved@a#2{#3}% \@ifundefined{\string\reserved@a}% {\@check@eq#1\reserved@a}% {\expandafter\@check@eq \csname\string#1\expandafter\endcsname \csname\string\reserved@a\endcsname}} \@onlypreamble\@check@c % \end{macrocode} % \end{macro} % % \begin{macro}{\@check@eq} % Complain if |#1| and |#2| are not |\ifx| equal. % \begin{macrocode} \def\@check@eq#1#2{% \ifx#1#2\else \@latex@warning@no@line {Command \noexpand#1 has changed.\MessageBreak Check if current package is valid}% \fi} \@onlypreamble\@check@eq % \end{macrocode} % \end{macro} % % \begin{macro}{\@gobble} % \begin{macro}{\@gobbletwo} % \begin{macro}{\@gobblethree} % \changes{v1.5g}{2020/02/27}{Macro added} % \begin{macro}{\@gobblefour} % \changes{v1.2n}{1995/05/26}{(CAR) Added \cs{long}s} % The |\@gobble| macro is used to get rid of its argument. % \begin{macrocode} \long\def \@gobble #1{} \long\def \@gobbletwo #1#2{} \long\def \@gobblethree #1#2#3{} \long\def \@gobblefour #1#2#3#4{} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\@firstofone} % \begin{macro}{\@firstoftwo} % \begin{macro}{\@secondoftwo} % Some argument-grabbers. % \begin{macrocode} \long\def\@firstofone#1{#1} \long\def\@firstoftwo#1#2{#1} \long\def\@secondoftwo#1#2{#2} % \end{macrocode} % \begin{macro}{\@iden} % |\@iden| is another name for |\@firstofone| for % compatibility reasons. % \begin{macrocode} \let\@iden\@firstofone % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\@thirdofthree} % Another grabber now used in the encoding specific % section. % \changes{v1.2z3}{1998/03/20}{Macro added} % \begin{macrocode} \long\def\@thirdofthree#1#2#3{#3} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@expandtwoargs} % A macro to totally expand two arguments to another macro % \changes{v1.5r}{2022/10/22}{Use \cs{protected@edef}.} % \begin{macrocode} % %\IncludeInRelease{2022/11/01}% % {\@expandtwoargs}{protected edef}% %<*2ekernel|latexrelease> \def\@expandtwoargs#1#2#3{% \protected@edef\reserved@a{\noexpand#1{#2}{#3}}\reserved@a} % %\EndIncludeInRelease %\IncludeInRelease{00/00/00}% % {\@expandtwoargs}{protected edef}% %\def\@expandtwoargs#1#2#3{% %\edef\reserved@a{\noexpand#1{#2}{#3}}\reserved@a} %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\@backslashchar} % A category code 12 backslash. % \begin{macrocode} \edef\@backslashchar{\expandafter\@gobble\string\\} % \end{macrocode} % \end{macro} % % \changes{v1.0n}{1994/05/10}{Added \cs{DeclareProtectedCommand}} % \changes{v1.0p}{1994/05/12}{Fixed a bug with \cs{relax } which was % using \cs{@gobble} before defining it.} % \changes{v1.0q}{1994/05/13}{Renamed \cs{DeclareProtectedCommand} to % \cs{DeclareRobustCommand}. Removed \cs{@if@short@command}. % Moved to after the definition of \cs{@gobble}.} % \changes{v1.0r}{1994/05/13}{Added logging message to % \cs{DeclareProtectedCommand}.} % % \subsection{Robust commands and protect} % % \changes{v1.1b}{1994/05/17}{Added the discussion of protected % commands, defined the values that \cs{protect} should have.} % \changes{v1.1c}{1994/05/18}{Redid the discussion and definitions, in % line with the proposed new setting of \cs{protect} in the output % routine.} % % Fragile and robust commands are one of the thornier issues in % \LaTeX's commands. Whilst typesetting documents, \LaTeX{} makes use % of many of \TeX's features, such as arithmetic, defining macros, and % setting variables. However, there are (at least) three different % occasions when these commands are not safe. These are called % `moving arguments' by \LaTeX, and consist of: % \begin{itemize} % \item writing information to a file, such as indexes or tables of % contents. % \item writing information to the screen. % \item inside an |\edef|, |\message|, |\mark|, or other command which % evaluates its argument fully. % \end{itemize} % The method \LaTeX{} uses for making fragile commands robust is to % precede them with |\protect|. This can have one of four possible % values: % \begin{itemize} % \item |\relax|, for normal typesetting. So |\protect\foo| will % execute |\foo|. % \item |\string|, for writing to the screen. So |\protect\foo| will % write |\foo|. % \item |\noexpand|, for writing to a file. So |\protect\foo| will % write |\foo| followed by a space. % \item |\@unexpandable@protect|, for writing a moving argument to a % file. So |\protect\foo| will write |\protect\foo| followed by a % space. This value is also used inside |\edef|s, |\mark|s and % other commands which evaluate their arguments fully. % More precisely, whenever the content of an |\edef| or |\xdef| etc.\ % can contain arbitrary user input not under the direct control of the % programmer, one should use |\proetected@edef| instead of |\edef|, etc., % so that |\protect| has a suitable definition and the user input will % not break if it contains fragile commands. % \end{itemize} % % \changes{1.1b}{1994/05/17} % {(ASAJ) Added the \cs{@protect@...} commands.} % \changes{1.1c}{1994/05/18} % {(ASAJ) Renamed the commands, and removed % one which is no longer needed.} % % \begin{macro}{\@unexpandable@protect} % \changes{1.2w}{1995/12/05}{Removed \cs{unexpandable@noexpand} as never used. internal/1733} % \begin{macrocode} \def\@unexpandable@protect{\noexpand\protect\noexpand} % \end{macrocode} % \end{macro} % % \changes{v1.2e}{1994/11/04}{Rewrote protected short commands % using \cs{x@protect}. ASAJ.} % % \begin{macro}{\DeclareRobustCommand} % \begin{macro}{\declare@robustcommand} % This is a package-writers command, which has the same syntax as % |\newcommand|, but which declares a protected command. It does % this by having\\ % |\DeclareRobustCommand\foo|\\ % define |\foo| to be % |\protect\foo|,\\ % and then use |\newcommand\foo|.\\ % Since the internal command is |\foo|, when it is written % to an auxiliary file, it will appear as |\foo|. % % We have to be a % bit cleverer if we're defining a short command, such as |\_|, in % order to make sure that the auxiliary file does not include a % space after the command, since |\_ a| and |\_a| aren't the same. % In this case we define |\_| to be: %\begin{verbatim} % \x@protect\_\protect\_ %\end{verbatim} % which expands to: %\begin{verbatim} % \ifx\protect\@typeset@protect\else % \@x@protect@\_ % \fi % \protect\_ %\end{verbatim} % Then if |\protect| is |\@typeset@protect| (normally |\relax|) % then we just perform |\_|, and otherwise % |\@x@protect@| gobbles everything up and expands to % |\protect\_|. % % \emph{Note}: setting |\protect| to any value other than |\relax| % whilst in `typesetting' mode will cause commands to go into an % infinite loop! In particular, setting |\protect| to |\@empty| will % cause |\_| to loop forever. It will also break lots of other % things, such as protected |\ifmmode|s inside |\halign|s. If you % really have to do such a thing, then please set % |\@typeset@protect| to be |\@empty| as well. (This is what the % code for |\patterns| does, for example.) % % More fun with |\expandafter| and |\csname|. % \begin{macrocode} \def\DeclareRobustCommand{\@star@or@long\declare@robustcommand} % \end{macrocode} % % \begin{macrocode} \def\declare@robustcommand#1{% \ifx#1\@undefined\else\ifx#1\relax\else \@latex@info{Redefining \string#1}% \fi\fi \edef\reserved@a{\string#1}% \def\reserved@b{#1}% \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% \edef#1{% \ifx\reserved@a\reserved@b \noexpand\x@protect \noexpand#1% \fi \noexpand\protect \expandafter\noexpand\csname \expandafter\@gobble\string#1 \endcsname }% \let\@ifdefinable\@rc@ifdefinable \expandafter\new@command\csname \expandafter\@gobble\string#1 \endcsname } % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@x@protect} % \begin{macro}{\x@protect} % % \begin{macrocode} \def\x@protect#1{% \ifx\protect\@typeset@protect\else \@x@protect#1% \fi } \def\@x@protect#1\fi#2#3{% \fi\protect#1% } % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@typeset@protect} % We set \cs{@typeset@protect} to \cs{relax} rather than \cs{@empty} % to make sure that the protection mechanism stops the look-ahead % and expansion performed at the start of \cs{halign} cells. % \begin{macrocode} \let\@typeset@protect\relax % \end{macrocode} % \end{macro} % % \changes{v1.2e}{1994/11/04}{Added commands for setting and restoring % \cs{protect}. ASAJ.} % % \begin{macro}{\set@display@protect} % \begin{macro}{\set@typeset@protect} % These macros set |\protect| appropriately for typesetting or % displaying. % \changes{v1.2o}{1995/07/03}{Use \cs{@typeset@protect} for init} % \begin{macrocode} \def\set@display@protect{\let\protect\string} \def\set@typeset@protect{\let\protect\@typeset@protect} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\protected@edef} % \begin{macro}{\protected@xdef} % \begin{macro}{\unrestored@protected@xdef} % \begin{macro}{\restore@protect} % The commands |\protected@edef| and |\protected@xdef| perform % `safe' |\edef|s and |\xdef|s, saving and restoring |\protect| % appropriately. For cases where restoring |\protect| doesn't % matter, there's an `unsafe' |\unrestored@protected@xdef|, useful % if you know what you're doing! % \begin{macrocode} \def\protected@edef{% \let\@@protect\protect \let\protect\@unexpandable@protect \afterassignment\restore@protect \edef } \def\protected@xdef{% \let\@@protect\protect \let\protect\@unexpandable@protect \afterassignment\restore@protect \xdef } \def\unrestored@protected@xdef{% \let\protect\@unexpandable@protect \xdef } \def\restore@protect{\let\protect\@@protect} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\protect} % The normal meaning of |\protect| % \changes{v1.2j}{1995/04/29}{Init \cs{protect} here} % \begin{macrocode} \set@typeset@protect % \end{macrocode} % \end{macro} % % \begin{macro}{\MakeRobust} % \changes{v1.4a}{2015/01/08}{Added macro} % \changes{v1.5f}{2019/08/27}{Make the assignments global as we may % need to apply them inside a group} % \changes{v1.5m}{2020/08/21}{Make \cs{MakeRobust} produce the same % command structure as \cs{DeclareRobustCommand}} % % This macro makes an existing fragile macro robust, but only if it % hasn't been robust in the past, i.e., it checks for the existence % of the macro % \verb*=\ = and if that exists it assumes that % \verb=\= is already robust. In that case either undefine % the inner macro first or use \cs{DeclareRobustCommand} to % define it in a robust way directly. We could probably test the % top-level definition to have the right kind of structure, but % this is somewhat problematical as we then have to distinguish % between \cs{long} macros and others and also take into account % that sometimes the top-level is deliberately done manually (like % with \cs{begin}). % % The macro firstly checks if the control sequence in question exists % at all. % \changes{v1.5p}{2021/05/26}{Normalize error message in \cs{MakeRobust}} % \begin{macrocode} % %\IncludeInRelease{2020/10/01}{\MakeRobust}{\MakeRobust}% %<*2ekernel|latexrelease> \def\MakeRobust#1{% \count@=\escapechar \escapechar=`\\ \@ifundefined{\expandafter\@gobble\string#1}{% \@latex@error{Command `\string#1' undefined.% \MessageBreak There is nothing here to make robust}% \@eha }% % \end{macrocode} % Then we check if the macro is already robust. We do this by testing % if the internal name for a robust macro is defined, namely % \verb*=\foo =. If it is already defined do nothing, otherwise set % \verb*=\foo = equal to \verb*=\foo= and redefine \verb*=\foo= so % that it acts like a macro defined with \verb=\DeclareRobustCommand=. % We use \cs{@kernel@rename@newcommand} to copy \verb*=\foo= over to % \verb*=\foo =, including a possible default optional argument. % \begin{macrocode} {% \@ifundefined{\expandafter\@gobble\string#1\space}% {% \expandafter\@kernel@rename@newcommand \csname\expandafter\@gobble\string#1\space\endcsname #1% \edef\reserved@a{\string#1}% \def\reserved@b{#1}% \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% \xdef#1{% \ifx\reserved@a\reserved@b \noexpand\x@protect\noexpand#1% \fi \noexpand\protect\expandafter\noexpand \csname\expandafter\@gobble\string#1\space\endcsname}% }% {\@latex@info{Command `\string#1' is already robust}}% }% \escapechar=\count@ }% % \end{macrocode} % % \begin{macro}{\@kernel@rename@newcommand} % This macro renames a command, possibly with an optional argument (defined % with \cs{newcommand}) from |#2| to |#1|, by renaming the internal macro % \verb=\\#2= to \verb=\\#1= and defining \verb=\#1= appropriately, then % undefining \verb=\#2= and \verb=\\#2=. The \cs{afterassignment} trick is % to make both definitions in \cs{@copy@newcommand} global (which are local % by default). % % In case the macro was defined with \cs{newcommand} and an optional % argument, to replicate exactly the behaviour of \cs{DeclareRobustCommand} % we have to move also the internal \verb*=\\foo= to \verb*=\\foo =. In that % case, \verb=#1= will be a parameterless macro (\cs{robust@command@chk@safe} % checks that), and \cs{@if@newcommand} will return true (both defined below % in this file). If so, we can use \cs{@copy@newcommand} rather than plain % \cs{let} to copy the command over. \cs{@kernel@rename@newcommand} does % this test and carries out the renaming. % \begin{macrocode} \def\@kernel@rename@newcommand#1#2{% \robust@command@chk@safe#2% {\@if@newcommand#2% {\afterassignment\global \global\@copy@newcommand#1#2% \global\let#2\@undefined \global\expandafter\let\csname\string#2\endcsname\@undefined}% {\global\let#1=#2}}% {\global\let#1=#2}} % \end{macrocode} % \end{macro} % % \begin{macrocode} % %\EndIncludeInRelease % %\IncludeInRelease{2019/10/01}{\MakeRobust}{\MakeRobust}% %\def\MakeRobust#1{% % \@ifundefined{\expandafter\@gobble\string#1}{% % \@latex@error{The control sequence `\string#1' is undefined!% % \MessageBreak There is nothing here to make robust}% % \@eha % }% % {% % \@ifundefined{\expandafter\@gobble\string#1\space}% % {% % \global\expandafter\let\csname % \expandafter\@gobble\string#1\space\endcsname=#1% % \edef\reserved@a{\string#1}% % \def\reserved@b{#1}% % \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% % \xdef#1{% % \ifx\reserved@a\reserved@b % \noexpand\x@protect\noexpand#1% % \fi % \noexpand\protect\expandafter\noexpand % \csname\expandafter\@gobble\string#1\space\endcsname}% % }% % {\@latex@info{The control sequence `\string#1' is already robust}}% % }% %}% %\let\@kernel@rename@newcommand\@undefined %\EndIncludeInRelease % %\IncludeInRelease{2015/01/01}{\MakeRobust}{\MakeRobust}% %\def\MakeRobust#1{% % \@ifundefined{\expandafter\@gobble\string#1}{% % \@latex@error{The control sequence `\string#1' is undefined!% % \MessageBreak There is nothing here to make robust}% % \@eha % }% % {% % \@ifundefined{\expandafter\@gobble\string#1\space}% % {% % \expandafter\let\csname % \expandafter\@gobble\string#1\space\endcsname=#1% % \edef\reserved@a{\string#1}% % \def\reserved@b{#1}% % \edef\reserved@b{\expandafter\strip@prefix\meaning\reserved@b}% % \edef#1{% % \ifx\reserved@a\reserved@b % \noexpand\x@protect\noexpand#1% % \fi % \noexpand\protect\expandafter\noexpand % \csname\expandafter\@gobble\string#1\space\endcsname}% % }% % {\@latex@info{The control sequence `\string#1' is already robust}}% % }% %}% %\let\@kernel@rename@newcommand\@undefined %\EndIncludeInRelease % %\IncludeInRelease{0000/00/00}{\MakeRobust}{\MakeRobust}% %\let\MakeRobust\@undefined %\let\@kernel@rename@newcommand\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macro}{\kernel@make@fragile} % The opposite of |\MakeRobust| except that it doesn't do many % checks as it is internal to the kernel. Why does one want such a % thing? % Only for compatibility reasons if \texttt{latexrelease} requests % a rollback of the kernel. For this reason we pretend that this % command existed in all earlier versions of \LaTeX{} i.e., we are % not rolling it back since we need it precisely then. But we have % to get it into the \texttt{latexrelease} file so that a roll % forward is possible too. % \begin{macrocode} % %<*2ekernel|latexrelease> %\IncludeInRelease{2020/10/01}% % {\kernel@make@fragile}{Undo robustness}% \def\kernel@make@fragile#1{% \@ifundefined{\expandafter\@gobble\string#1\space}% % \end{macrocode} % If not robust do nothing. % \begin{macrocode} {}% % \end{macrocode} % Otherwise copy \verb*=\foo = back to \verb=\foo=. % Then use \cs{@kernel@rename@newcommand} to check and copy % \verb*=\\foo = back to \verb*=\\foo= in case the command has an optional % argument. If so, also undefine \verb*=\\foo =, and at the end undefine % \verb*=\foo =. % \begin{macrocode} {% \global\expandafter\let\expandafter #1\csname \expandafter\@gobble\string#1\space\endcsname \expandafter\@kernel@rename@newcommand \csname\expandafter\@gobble\string#1\expandafter\endcsname \csname\expandafter\@gobble\string#1\space\endcsname \global\expandafter\let\csname \expandafter\@gobble\string#1\space\endcsname\@undefined }% } % \end{macrocode} % % \begin{macrocode} %\EndIncludeInRelease % %\IncludeInRelease{0000/00/00}% % {\kernel@make@fragile}{Undo robustness}% %\def\kernel@make@fragile#1{% % \@ifundefined{\expandafter\@gobble\string#1\space}% % {}% % {% % \global\expandafter\let\expandafter #1\csname % \expandafter\@gobble\string#1\space\endcsname % \global\expandafter\let\csname % \expandafter\@gobble\string#1\space\endcsname\@undefined % }% %} %\EndIncludeInRelease % %<*2ekernel> % \end{macrocode} % \end{macro} % % % \subsection{Acting on robust commands} % % \begin{macrocode} % %\IncludeInRelease{2020-10-01}{\robust@command@act} % {Add \robust@command@act}% %<*2ekernel|latexrelease> % \end{macrocode} % % With most document level commands being robust now there is more of a % requirement to have a standard way of aliasing (or copying) a command to a % new name, for example to save an original definition before changing a % command. \cs{DeclareCommandCopy} is analogous to \TeX's \cs{let}, except % that it copes with the different types of robust commands defined by % \LaTeX's mechanisms. % % A couple of ``types of robustness'' are defined by the \LaTeXe{} kernel, % namely robust commands defined with \cs{DeclareRobustCommand} and commands % with optional arguments defined with \cs{newcommand}. However there are % other types of robust commands that are frequently used, which are not % defined in the \LaTeXe{} kernel, like commands defined with % \textsf{xparse}'s \cs{NewDocumentCommand} and \textsf{etoolbox}'s % \cs{newrobustcmd}. % % In this section we will define a generic extensible machinery to act on % robust commands. This code will then be used to test if a command is % robust, considered the different types of robustness, and then either copy % that definition, if \cs{DeclareCommandCopy} (or similar) is used, or show % the definition of the command, if \cs{ShowCommand} is used. % % \begin{macro}{\robust@command@act} % \changes{v1.5k}{2020/08/19}{Made \cs{robust@command@act} % (was \cs{declare@command@copy}) more generic} % % The looping machinery is generic and knows nothing about what is to be done % for each case. The syntax of the main macro \cs{robust@command@act} is: % \begin{quote} % |\robust@command@act|\meta{action-list}\meta{robust-cmd}\\ % \meta{fallback-action}\meta{act-arg} % \end{quote} % \meta{action-list} is a token list of the form: % \begin{quote} % |{|\meta{if-type-1} \meta{act-type-1}|}|\\ % |{|\meta{if-type-2} \meta{act-type-2}|}|\\ % \ldots % \end{quote} % \cs{robust@command@act} will iterate over the \meta{action-list}, evaluating % each \meta{if-type-$n$} \meta{robust-cmd} |{|\meta{true}|}{|\meta{false}|}|. % If the \meta{if-type-$n$} conditional returns \meta{true}, then % \meta{act-type-$n$}\meta{act-arg} is executed, and the loop ends. If the % conditional returns \meta{false}, then \meta{if-type-$n+1$} is executed in % the same way, until either one of the conditionals return \meta{true}, or % the end of the \meta{action-list} is reached. If the end is reached, then % \meta{fallback-action}\meta{act-arg} is executed before % \cs{robust@command@act} exits. % % \cs{robust@command@act} will start by using \cs{robust@command@act@chk@args} % to check if the \meta{robust-cmd} (|#2|) is a parameterless (possibly % \cs{protected}) macro. If it is not, the command is not a robust command: % these always start with a parameterless user-level macro; in that case, % \cs{robust@command@act@end} is used to short-circuit the process and do the % \meta{fallback-action} (|#3|). This first test is necessary because later % on we need to be able to expand the \meta{robust-cmd} without the risk of it % Breaking Badly, and as a bonus, this speeds up the process in case we used % \cs{NewCommandCopy} in a ``normal'' macro. % \begin{macrocode} \long\def\robust@command@act#1#2#3#4{% \robust@command@chk@safe#2% {\expandafter\robust@command@act@loop \expandafter#2% #1{\@nnil\@nnil}% \robust@command@act@end}% {\robust@command@act@end}% {#3}{#4}}% % \end{macrocode} % % \begin{macro}{\robust@command@act@loop} % \begin{macro}{\robust@command@act@loop@aux} % \begin{macro}{\robust@command@act@do} % If \cs{robust@command@act@chk@args} branched to false, then % \cs{robust@command@act@loop} will loop over the list of items in the % \meta{action-list} (|#1|), and process each item as described earlier. % If the \meta{if-type-$n$} command expands to \meta{true} then % \cs{robust@command@act@do} is used to execute \meta{act-type-$n$} on the % \meta{act-arg}, otherwise the loop resumes with the next item. % \begin{macrocode} \long\def\robust@command@act@loop#1#2{\robust@command@act@loop@aux#1#2} \long\def\robust@command@act@loop@aux#1#2#3{% \ifx\@nnil#2% \else #2{#1}% {\robust@command@act@do{#3}}% {\expandafter\robust@command@act@loop\expandafter#1}% \fi} \long\def\robust@command@act@do#1% \fi#2% \robust@command@act@end#3#4{% \fi #1#4} % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\robust@command@act@end} % If the end is reached and no action was taken, then do % \meta{fallback-action}\meta{act-arg}. % \begin{macrocode} \long\def\robust@command@act@end#1#2{#1#2} % \end{macrocode} % \end{macro} % % \begin{macro}{\robust@command@chk@safe} % \begin{macro}{\robust@command@act@chk@args} % \begin{macrocode} \long\def\robust@command@chk@safe#1{% \begingroup \escapechar=`\\ \expandafter\endgroup\expandafter \robust@command@act@chk@args\meaning#1:->\@nil} \def\robust@command@act@chk@args#1:->#2\@nil{% \@expl@str@if@eq@@nnTF{#1}{macro}% {\@firstoftwo}% {\@expl@str@if@eq@@nnTF{#1}{\protected macro}% {\@firstoftwo}% {\@secondoftwo}}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\robust@command@act} % {Add \robust@command@act}% %\let\robust@command@act\@undefined %\let\robust@command@act@loop\@undefined %\let\robust@command@act@loop@aux\@undefined %\let\robust@command@act@do\@undefined %\let\robust@command@act@end\@undefined %\let\robust@command@chk@safe\@undefined %\let\robust@command@act@chk@args\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % % \end{macro} % % % \subsubsection{Copying robust commands} % % \begin{macrocode} % %\IncludeInRelease{2020-10-01}{\DeclareCommandCopy} % {Add \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}% %<*2ekernel|latexrelease> % \end{macrocode} % % \begin{macro}{\NewCommandCopy} % \begin{macro}{\RenewCommandCopy} % \begin{macro}{\DeclareCommandCopy} % \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)} % % \cs{NewCommandCopy} starts by checking if \verb=#1= is already defined, and % raises an error if so, otherwise the definition is carried out. % \cs{RenewCommandCopy} does (almost) the opposite. If the command is % \emph{not} defined, then an error is raised. But the definition is carried % out anyhow, so the behaviour is consistent with \cs{renewcommand}. % % A \cs{ProvideCommandCopy} isn't defined because it's not reasonably useful. % \verb=\provide...= commands mean ``define this if there's no other % definition'', but copying a command (usually) implies that the command being % copied is defined, so \cs{ProvideCommandCopy} doesn't make a lot of sense. % But more importantly, the most common use case of copying a command is to % redefine it later, while preserving the old definition, as in: % \begin{verbatim} % \ProvideCommandCopy \A \B % \renewcommand \B { ... \A ... } % \end{verbatim} % then, if \verb=\A= is already defined the first line is skipped, an in this % case \verb=\B= won't work as expected. % % The three versions call the internal \cs{declare@commandcopy} with the % proper action. \cs{@firstofone} will carry out the copy. The only case % when the copy is not made is the \meta{false} case for \cs{NewCommandCopy}, % in which the command already exists and the definition is aborted. % \begin{macrocode} \def\NewCommandCopy{% \declare@commandcopy {\@firstofone}% {\@firstoftwo\@notdefinable}} \def\RenewCommandCopy{% \declare@commandcopy {\@latex@error{Command \@backslashchar\reserved@a\space undefined}\@ehc \@firstofone}% {\@firstofone}} \def\DeclareCommandCopy{% \declare@commandcopy {\@firstofone}% {\@firstofone}} % \end{macrocode} % % \begin{macro}{\declare@commandcopy} % \begin{macro}{\declare@commandcopy@do} % Start by checking if the command is already defined. The proper action is % taken by each specific command above. If all's good, then % \cs{robust@command@act} is called with the proper arguments as described % earlier, with \cs{@declarecommandcopylisthook} as the \meta{action-list} and % \cs{declare@commandcopy@let} as the \meta{fallback-action}. % \begin{macrocode} \long\def\declare@commandcopy#1#2#3#4{% \edef\reserved@a{\@expl@cs@to@str@@N#3}% \@ifundefined\reserved@a{#1}{#2}% {\declare@commandcopy@do{#3}{#4}}} \long\def\declare@commandcopy@do#1#2{% \robust@command@act \@declarecommandcopylisthook#2% \declare@commandcopy@let{#1#2}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@declarecommandcopylisthook} % The initial definition of \cs{@declarecommandcopylisthook} contains the % tests for the two types of robust command in the kernel. % \begin{macrocode} \def\@declarecommandcopylisthook{% {\@if@DeclareRobustCommand \@copy@DeclareRobustCommand}% {\@if@newcommand \@copy@newcommand}} % \end{macrocode} % \end{macro} % % \begin{macro}{\declare@commandcopy@let} % The initial definition of \cs{@declarecommandcopylisthook} contains the % tests for the two types of robust command in the kernel. % \begin{macrocode} \long\def\declare@commandcopy@let#1#2{\let#1=#2\relax} % \end{macrocode} % \end{macro} % % Now the rollback code. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\DeclareCommandCopy} % {Undefine \NewCommandCopy, \RenewCommandCopy, and \DeclareCommandCopy}% %\let\NewCommandCopy\@undefined %\let\RenewCommandCopy\@undefined %\let\DeclareCommandCopy\@undefined %\let\declare@commandcopy\@undefined %\let\@declarecommandcopylisthook\@undefined %\let\declare@commandcopy@let\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macrocode} % %\IncludeInRelease{2023-06-01}{\DeclareEnvironmentCopy} % {Add \NewEnvironmentCopy, \RenewEnvironmentCopy, and \DeclareEnvironmentCopy}% %<*2ekernel|latexrelease> % \end{macrocode} % % \begin{macro}{\NewEnvironmentCopy} % \begin{macro}{\RenewEnvironmentCopy} % \begin{macro}{\DeclareEnvironmentCopy} % If \verb=\#1= or \verb=\end#1= already exist one gets an error % message talking about the problematical command (not the % environment). % The remainder of the \LaTeX{} run is probably badly % broken and it is unlikely that continuing it gives % reasonable results. % \changes{v1.5s}{2022/11/24}{Add \cs{NewEnvironmentCopy}, % \cs{RenewEnvironmentCopy}, and \cs{DeclareEnvironmentCopy} (gh/963)} % \begin{macrocode} \def\NewEnvironmentCopy{% \declare@environmentcopy {\@firstofone}% {\@firstoftwo\@notdefinable}} \def\RenewEnvironmentCopy{% \declare@environmentcopy {\@latex@error{Environment \reserved@a\space undefined}\@ehc \@firstofone}% {\@firstofone}} \def\DeclareEnvironmentCopy{% \declare@environmentcopy {\@firstofone}% {\@firstofone}} \long\def\declare@environmentcopy#1#2#3#4{% \edef\reserved@a{\@ifundefined{#3}{end#3}{#3}}% \@ifundefined\reserved@a {\def\reserved@a{#3}#1}% {\def\reserved@a{#3}#2}% {\ExpandArgs{cc}\declare@commandcopy@do{#3}{#4}% \ExpandArgs{cc}\declare@commandcopy@do{end#3}{end#4}}} % \end{macrocode} % % Now the rollback code. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\DeclareEnvironmentCopy} % {Undefine \NewEnvironmentCopy, \RenewEnvironmentCopy, and \DeclareEnvironmentCopy}% %\let\NewEnvironmentCopy\@undefined %\let\RenewEnvironmentCopy\@undefined %\let\DeclareEnvironmentCopy\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \subsubsection{Showing robust commands} % % \begin{macro}{\ShowCommand} % \changes{v1.5k}{2020/08/19}{Added \cs{ShowCommand} (gh/373)} % % Most of the machinery defined for \cs{NewCommandCopy} can be used to show % the definition of a robust command, in a similar fashion to \texttt{texdef}. % The difference is that after the command's is detected to has a given type % of robustness, rather than making a copy, we use a separate routine to show % its definition. % % With all the machinery in place, \cs{ShowCommand} itself is quite simple: % use \cs{robust@command@act} to iterate through the \cs{@showcommandlisthook} % list, and if nothing is found, fallback to \cs{show}. % \begin{macrocode} % %\IncludeInRelease{2020-10-01}{\ShowCommand}% % {Add \ShowCommand}% %<*2ekernel|latexrelease> % \end{macrocode} % % \begin{macrocode} \long\def\ShowCommand#1{% \robust@command@act \@showcommandlisthook#1% \show#1} % \end{macrocode} % % \begin{macro}{\@showcommandlisthook} % The initial definition of \cs{@showcommandlisthook} contains the same tests % as used for copying, but \cs{@show@...} commands instead of \cs{@copy@...}. % Same as before, it is initialized to cope with \cs{DeclareRobustCommand} and % \cs{newcommand} with optional arguments. % \begin{macrocode} \def\@showcommandlisthook{% {\@if@DeclareRobustCommand \@show@DeclareRobustCommand}% {\@if@newcommand \@show@newcommand}} % \end{macrocode} % \end{macro} % % Now the rollback code. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\ShowCommand} % {Undefine \ShowCommand}% %\let\ShowCommand\@undefined %\let\@showcommandlisthook\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % \begin{macrocode} % %\IncludeInRelease{2020-10-01}{\@if@DeclareRobustCommand} % {Add \@if@DeclareRobustCommand, \@if@newcommand, % \@copy@DeclareRobustCommand, \@copy@newcommand, % \@show@DeclareRobustCommand, \@show@newcommand}% %<*2ekernel|latexrelease> % \end{macrocode} % % \subsubsection{Commands defined with \cs{DeclareRobustCommand}} % % \begin{macro}{\@if@DeclareRobustCommand} % \changes{v1.5j}{2020/05/09}{Added \cs{DeclareCommandCopy} (gh/239)} % % Now that we provided a generic way to copy one macro to another, we need to % define a way to check if a command is one of \LaTeXe's robust types. These % tests are heavily based on Heiko's \cs{LetLtxMacro}, but chopped into % separate macros. % % \cs{@if@DeclareRobustCommand} checks if a command \verb=\cmd= was defined by % \cs{DeclareRobustCommand}. The test returns true if the expansion of % \verb=\cmd= is exactly \verb*=\protect\cmd =. % % \begin{macrocode} \long\def\@if@DeclareRobustCommand#1{% \begingroup \escapechar=`\\ \edef\reserved@a{\string#1}% \edef\reserved@b{\detokenize{#1}}% \xdef\@gtempa{% \ifx\reserved@a\reserved@b \noexpand\x@protect \noexpand#1% \fi \noexpand\protect \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}% \endgroup \ifx\@gtempa#1\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi} % \end{macrocode} % % \begin{macro}{\@copy@DeclareRobustCommand} % \begin{macro}{\copy@kernel@robust@command} % If a command was defined by \cs{DeclareRobustCommand} (that is, % \cs{@if@DeclareRobustCommand} returns true), then to make a copy of \verb=\cmd= % into \verb=\foo= we define the latter such that it expands to % \verb*=\protect\foo =, then make \verb*=\foo = equal to \verb*=\cmd =. % % There is one detail we need to take care of: if a command was defined with % \cs{DeclareRobustCommand} it may still have an optional argument, in which % case there is one more macro layer before the actual definition of the % command. We use \cs{@if@newcommand} to check that and % \cs{@copy@newcommand} to do the copying. % \begin{macrocode} \long\def\@copy@DeclareRobustCommand#1#2{% \begingroup \escapechar=`\\ \edef\reserved@a{\string#1}% \edef\reserved@b{\detokenize{#1}}% \edef\reserved@a{% \endgroup \def\noexpand#1{% \ifx\reserved@a\reserved@b \noexpand\x@protect \noexpand#1% \fi \noexpand\protect \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname}% \noexpand\copy@kernel@robust@command \expandafter\noexpand\csname\@expl@cs@to@str@@N#1 \endcsname \expandafter\noexpand\csname\@expl@cs@to@str@@N#2 \endcsname}% \reserved@a} \long\def\copy@kernel@robust@command#1#2{% \robust@command@chk@safe#2% {\@if@newcommand#2% {\@copy@newcommand}% {\declare@commandcopy@let}} {\declare@commandcopy@let}% #1#2} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@show@DeclareRobustCommand} % \begin{macro}{\show@kernel@robust@command} % \begin{macro}{\@show@macro} % Showing the command is pretty simple. This command prints the top-level % expansion as \TeX's \cs{show} would, but with |robust macro:| rather than % just |macro:|, then a blank line and then \cs{show} the inner command. % For a macro defined with, say, |\DeclareRobustCommand\foo[1]{bar}|, it will % print: % \begin{verbatim} % > \foo=robust macro: % ->\protect \foo . % % > \foo =\long macro: % #1->bar. % \end{verbatim} % If the inner command is defined with an optional argument, then % \cs{@show@newcommand} is also used. % % The value of \cs{escapechar} is deliberately not enforced, so % \cs{ShowCommand} behaves more like \cs{show}. % \begin{macrocode} \long\def\@show@DeclareRobustCommand#1{% \typeout{> \string#1=robust macro:}% \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}% \expandafter\show@kernel@robust@command \csname\@expl@cs@to@str@@N#1 \endcsname} \long\def\show@kernel@robust@command#1{% \robust@command@chk@safe#1% {\@if@newcommand#1% {\@show@newcommand}% {\@show@macro}}% {\@show@macro}% #1} \let\@show@macro\show % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % \end{macro} % % \subsubsection{Commands defined with \cs{newcommand} (with optional argument)} % % \begin{macro}{\@if@newcommand} % A command \verb=\cmd= (or \verb*=\cmd =, if it was defined with % \cs{DeclareRobustCommand}) with an optional argument will expand to % \verb*=\@protected@testopt\cmd\\cmd{}=. To check that we look at the % first three tokens in the expansion of \verb=\cmd=, and return true or false % accordingly. % % This test \emph{requires} that the command be a parameterless macro, % otherwise it will not work (and probably break). This is ensured with % \cs{robust@command@chk@safe} before calling \cs{@if@newcommand}. % \begin{macrocode} \long\def\@if@newcommand#1{% \edef\reserved@a{% \noexpand\@protected@testopt \noexpand#1% \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname}% \edef\reserved@b{% \unexpanded\expandafter\expandafter\expandafter {\expandafter\@carcube#1{}{}{}\@nil}}% \ifx\reserved@a\reserved@b \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi} % \end{macrocode} % % \begin{macro}{\@copy@newcommand} % Then, if a command \verb=\cmd= takes an optional argument, we copy it to % \verb=\foo= by defining the latter to expand to % \verb=\@protected@testopt\foo\\foo{}=. % \begin{macrocode} \long\def\@copy@newcommand#1#2{% \edef#1{\noexpand\@protected@testopt \noexpand#1% \expandafter\noexpand\csname\@backslashchar\@expl@cs@to@str@@N#1\endcsname \unexpanded\expandafter\expandafter\expandafter {\expandafter\@gobblethree#2}}% \expandafter \let\csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname \csname\@backslashchar\@expl@cs@to@str@@N#2\endcsname} % \end{macrocode} % \end{macro} % % \begin{macro}{\@show@newcommand} % \begin{macro}{\@show@newcommand@aux} % A command being \cs{show}n here is guaranteed to have an optional argument. % Start by showing the top-level expansion of the command (using \cs{typeout} % to avoid TeX asking for interaction and extra context lines), then call % \cs{@show@newcommand@aux} with the internal command, which contains the % actual definition, and with the expansion of the command to extract the % default value of the optional argument. % \begin{macrocode} \long\def\@show@newcommand#1{% \typeout{> \string#1=robust macro:}% \typeout{->\@expl@cs@replacement@spec@@N#1.^^J}% \expandafter\@show@newcommand@aux \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname \expandafter{#1}\@show@tokens} % \end{macrocode} % % For a macro defined with, say, |\newcommand\foo[1][opt]{bar}|, it will % print: % \begin{verbatim} % > \foo=robust macro: % ->\@protected@testopt \foo \\foo {opt}. % % > \\foo=\long macro: % > default #1=opt. % [#1]->bar. % \end{verbatim} % If the command was defined with \cs{DeclareRobustCommand}, then another pair % of lines show the top-level expansion \verb*|\protect \foo |. % \begin{macrocode} \long\def\@show@newcommand@aux#1#2#3{% \typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:}% #3{default \string##1=\expandafter\detokenize\@gobblethree#2.^^J% \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@show@tokens} % This macro prints the contents of the token list (macro) |#1| using % \cs{showtokens}. The \cs{expandafter} gymnastics ensures that % \cs{showtokens} itself, and the internals of this macro aren't % showed in the context lines. % \begin{macrocode} \long\def\@show@tokens#1{% \edef\reserved@a{#1}% \showtokens\expandafter \expandafter\expandafter{\expandafter\reserved@a}} % \end{macrocode} % \end{macro} % % Now the rollback code. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\@if@DeclareRobustCommand} % {Undefine \@if@DeclareRobustCommand, \@if@newcommand, % \@copy@DeclareRobustCommand, \@copy@newcommand, % \@show@DeclareRobustCommand, \@show@newcommand}% %\let\@if@DeclareRobustCommand\@undefined %\let\@copy@DeclareRobustCommand\@undefined %\let\@show@DeclareRobustCommand\@undefined %\let\@if@newcommand\@undefined %\let\@copy@newcommand\@undefined %\let\@show@newcommand\@undefined % %\let\copy@kernel@robust@command\@undefined %\let\show@kernel@robust@command\@undefined %\let\@show@newcommand@aux\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % % \end{macro} % % % \subsubsection{Showing environments} % % \begin{macro}{\ShowEnvironment} % \changes{v1.5s}{2022/11/24}{Added \cs{ShowEnvironment}} % % \begin{macrocode} % %\IncludeInRelease{2023-06-01}{\ShowEnvironment} % {Add \ShowEnvironment}% %<*2ekernel|latexrelease> % \end{macrocode} % % \cs{ShowEnvironment} is quite similar to \cs{ShowCommand}. We will % pass the environment \meta{env} around as the macro % \cs[no-index]{env}, because \cs{robust@command@act} expects a single % token. % \begin{macrocode} \def\ShowEnvironment#1{% \expandafter\@show@environment\csname #1\endcsname} \long\def\@show@environment#1{% \robust@command@act \@showenvironmentlisthook#1% \@show@normalenv#1} % \end{macrocode} % % \begin{macro}{\@showenvironmentlisthook} % This is similar to \cs{@showcommandlisthook}, but uses the dedicated % versions for environments. % \begin{macrocode} \def\@showenvironmentlisthook{% {\@if@DeclareRobustCommand \@show@DeclareRobustCommand@env}% {\@if@newcommand \@show@newcommand@env}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@show@newcommand@env} % \begin{macro}{\@show@DeclareRobustCommand@env} % These are similar to the command versions below, except they say % \enquote{environment} and call \cs{@show@environment@end} to print % the \cs{end} part. % \begin{macrocode} \long\def\@show@newcommand@env#1{% \@show@environment@begin#1% \expandafter\@show@newcommand@aux \csname\@backslashchar\@expl@cs@to@str@@N#1\expandafter\endcsname \expandafter{#1}\@show@typeout \@show@environment@end#1} \long\def\@show@DeclareRobustCommand@env#1{% \@show@environment@begin#1% \begingroup \let\@show@tokens\@show@typeout \let\@show@macro\@show@nonstop \expandafter\show@kernel@robust@command \csname\@expl@cs@to@str@@N#1 \endcsname \endgroup \@show@environment@end#1} \long\def\@show@environment@begin#1{% \typeout{> \string\begin{\@expl@cs@to@str@@N#1}=environment:}% \typeout{\@expl@cs@argument@spec@@N#1->% \@expl@cs@replacement@spec@@N#1.^^J}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@show@normalenv} % \begin{macro}{\@show@environment@end} % A \enquote{normal} environment is straightforward. % \cs{@show@environment@end} needs to check if the \cs{end} part is % defined and show it accordingly, otherwise the output would show % gibberish. % \begin{macrocode} \long\def\@show@normalenv#1{% \@show@environment@begin#1% \@show@environment@end#1} \long\def\@show@environment@end#1{% \expandafter\@show@environment@end@aux \csname end\@expl@cs@to@str@@N#1\endcsname#1} \long\def\@show@environment@end@aux#1#2{% \@show@tokens{\string\end{\@expl@cs@to@str@@N#2}% \ifx\relax#1=undefined% \else:^^J\@expl@cs@argument@spec@@N#1->% \@expl@cs@replacement@spec@@N#1% \fi}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@show@nonstop} % \begin{macro}{\@show@typeout} % And here some auxiliaries: % \begin{description} % \item[\cs{@show@nonstop}] same output as \cs{show}, but doesn't % stop for interaction; % \item[\cs{@show@typeout}] same output as \cs{showtokens}, but % doesn't stop for interaction. % \end{description} % \begin{macrocode} \def\@show@nonstop#1{% \typeout{> \string#1=\@expl@cs@prefix@spec@@N#1macro:^^J% \@expl@cs@argument@spec@@N#1->\@expl@cs@replacement@spec@@N#1.}} \def\@show@typeout#1{\typeout{> #1.^^J}} % \end{macrocode} % \end{macro} % \end{macro} % % Now the rollback code. % \begin{macrocode} % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\ShowEnvironment} % {Undefine \ShowEnvironment}% %\let\ShowEnvironment\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % % \subsection{Internal defining commands} % % These commands are used internally to define other \LaTeX{} % commands. % \begin{macro}{\@ifundefined} % \changes{LaTeX2e}{1993/11/23}{Redefined to remove a trailing \cs{fi}} % Check if first arg is undefined or \cs{relax} and execute second or % third arg depending, % \changes{1.5c}{2018/01/06}{Avoid defining undefined commands to \cs{relax}} % \begin{macrocode} % %\IncludeInRelease{2018-04-01}{\@ifundefined} %{Leave commands undefined in \@ifundefined}% %<*2ekernel|latexrelease> % \end{macrocode} % Version using |\ifcsname| to avoid defining undefined tokens to |\relax|. % Defined here to simplify using unmatched |\fi|. % \begin{macrocode} \def\@ifundefined#1{% \ifcsname#1\endcsname\@ifundefin@d@i\else\@ifundefin@d@ii\fi{#1}} % \end{macrocode} % \begin{macrocode} \long\def\@ifundefin@d@i#1\fi#2{\fi \expandafter\ifx\csname #2\endcsname\relax \@ifundefin@d@ii \fi \@secondoftwo} % \end{macrocode} % \begin{macrocode} \long\def\@ifundefin@d@ii\fi#1#2#3{\fi #2} % \end{macrocode} % Now test of engine. % \begin{macrocode} \ifx\numexpr\@undefined % \end{macrocode} % Classic version (should not be needed as etex is assumed). % \begin{macrocode} \def\@ifundefined#1{% \expandafter\ifx\csname#1\endcsname\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi} \else\ifx\directlua\@undefined % \end{macrocode} % Use the |\ifcsname| defined above. % \begin{macrocode} \else % \end{macrocode} % Optimised version for Lua\TeX, using |\lastnamedcs| % \begin{macrocode} \def\@ifundefined#1{% \ifcsname#1\endcsname \expandafter\ifx\lastnamedcs\relax\else\@ifundefin@d@i\fi \fi \@firstoftwo} % \end{macrocode} % \begin{macrocode} \long\def\@ifundefin@d@i#1#2#3#4#5{#1#2#5} % \end{macrocode} % \begin{macrocode} \fi \fi % %\EndIncludeInRelease %\IncludeInRelease{0000-00-00}{\@ifundefined} %{Leave commands undefined in \@ifundefined}% %\def\@ifundefined#1{% % \expandafter\ifx\csname#1\endcsname\relax % \expandafter\@firstoftwo % \else % \expandafter\@secondoftwo % \fi} %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % % % \begin{macro}{\@qend} % \begin{macro}{\@qrelax} % The following define |\@qend| and |\@qrelax| to be the strings % `|end|' and `|relax|' with the characters |\catcode|d 12. % \begin{macrocode} \edef\@qend{\expandafter\@cdr\string\end\@nil} \edef\@qrelax{\expandafter\@cdr\string\relax\@nil} % \end{macrocode} % \end{macro} % \end{macro} % % % \begin{macro}{\@ifnextchar} % \changes{LaTeX209}{1992/08/24} % {(Rms) \cs{@ifnextchar} didn't work if its % first argument was an equal sign.} % \changes{v1.2q}{1995/10/02} % {Use \cs{@let@token} } % \changes{v1.3a}{1999/01/07} % {made long} % \changes{v1.3b}{1999/01/07} % {extra \cs{long}. latex/2902} % \changes{v1.3e}{1999/03/01} % {remove extra \cs{long}. internal/2967} % |\@ifnextchar| peeks at the following character and compares it % with its first argument. If both are the same it executes its % second argument, otherwise its third. % \begin{macrocode} \long\def\@ifnextchar#1#2#3{% \let\reserved@d=#1% \def\reserved@a{#2}% \def\reserved@b{#3}% \futurelet\@let@token\@ifnch} % \end{macrocode} % \end{macro} % % \begin{macro}{\kernel@ifnextchar} % \changes{v1.3g}{2004/01/23}{Added macro (pr/3501)} % This macro is the kernel version of |\@ifnextchar| which is used % in a couple of places to prevent the AMS variant from being used % since in some places this produced chaos (for example % if an \texttt{fd} file % is loaded in a random place then the optional argument to % |\ProvidesFile| could get printed there instead of being written % only in the log file. This happened % when there was a space or a newline between the mandatory and % optional arguments! It should really be fixed in the % \texttt{amsmath} package one day, but\ldots % % Note that there may be other places in the kernel where this version % should be used rather than the original, but variable, version. % % \begin{macrocode} \let\kernel@ifnextchar\@ifnextchar % \end{macrocode} % \end{macro} % % % \begin{macro}{\@ifnch} % |\@ifnch| is a tricky macro to skip any space tokens that may % appear before the character in question. If it encounters a space % token, it calls \@xifnch. % \changes{v1.2q}{1995/10/02} % {Use \cs{@let@token} for internal/924, save \cs{reserved@e}} % \begin{macrocode} \def\@ifnch{% \ifx\@let@token\@sptoken \let\reserved@c\@xifnch \else \ifx\@let@token\reserved@d \let\reserved@c\reserved@a \else \let\reserved@c\reserved@b \fi \fi \reserved@c} % \end{macrocode} % \end{macro} % % \begin{macro}{\@sptoken} % The following code makes |\@sptoken| a space token. It is % important here that the control sequence |\:| consists of % a non-letter only, so that the following whitespace is % significant. Together with the fact that the equal sign % in a |\let| may be followed by only one optional space % the desired effect is achieved. % NOTE: the following hacking must precede the definition of |\:| % as math medium space. % \begin{macrocode} \def\:{\let\@sptoken= } \: % this makes \@sptoken a space token % \end{macrocode} % \end{macro} % % \begin{macro}{\@xifnch} % In the following definition of |\@xifnch|, |\:| is again used % to get a space token as delimiter into the definition. % \begin{macrocode} \def\:{\@xifnch} \expandafter\def\: {\futurelet\@let@token\@ifnch} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@ifstar} % \changes{v1.2u}{1995/10/16}{(DPC) New implementation, for /1910} % The new implementation below avoids passing the \meta{true code} % Through one more |\def| than the \meta{false code}, which previously % meant that |#| had to be written as |####| in one argument, but |##| % in the other. The |*| is gobbled by |\@firstoftwo|. % \begin{macrocode} \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@dblarg} % \begin{macro}{\@xdblarg} % \changes{v1.1g}{2004/01/23}{Use kernel version of % \cs{@ifnextchar} (pr/3501)} % \begin{macrocode} \long\def\@dblarg#1{\kernel@ifnextchar[{#1}{\@xdblarg{#1}}} \long\def\@xdblarg#1#2{#1[{#2}]{#2}} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\@sanitize} % The command |\@sanitize| changes the catcode of all special characters % except for braces to `other'. It can be used for commands like % |\index| that want to write their arguments verbatim. Needless to % say, this command should only be executed within a group, or chaos % will ensue. % % \begin{macrocode} \def\@sanitize{\@makeother\ \@makeother\\\@makeother\$\@makeother\&% \@makeother\#\@makeother\^\@makeother\_\@makeother\%\@makeother\~} % \end{macrocode} % \end{macro} % % \begin{macro}{\@onelevel@sanitize} % \changes{v1.2c}{1994/10/30}{Macro added} % % This makes the whole ``meaning'' of |#1| (its one-level % expansion) into catcode 12 tokens: it could be used in % |\DeclareRobustCommand|. % % If it is to be used on default float specifiers, this should be % done when they are defined. % \begin{macrocode} \def \@onelevel@sanitize #1{% \edef #1{\expandafter\strip@prefix \meaning #1}% } % \end{macrocode} % \end{macro} % % % \begin{macro}{\string@makeletter} % \begin{macro}{\@string@makeletter} % \begin{macro}{\char@if@alph} % Iterates through a string, turning each alphabetic character into % a catcode-11 token (partly undoes a \cs{detokenize}). Useful for % \cs{ifx}-based string comparisons where \cs{detokenize}-ing the % other string would break too much code. % % \changes{v1.5n}{2020/09/06} % {Macro added} % % The macro uses \textsf{expl3}'s \cs{@expl@str@map@function@@NN} to % iterate on the string (without losing spaces) and applies % \cs{@string@makeletter} on each character. The latter checks if % character is between a--z or A--Z, and uses \cs{@alph} or \cs{@Alph} % to get the corresponding catcode-11 token. Other tokens are passed % through unchanged. % \begin{macrocode} % %\IncludeInRelease{2020/10/01}{\string@makeletter} % {Add \string@makeletter}% %<*2ekernel|latexrelease> \def\string@makeletter#1{% \@expl@str@map@function@@NN#1\@string@makeletter} \def\@string@makeletter#1{% \char@if@alph{#1}% {\@expl@char@generate@@nn{`#1}{11}}% {#1}} \def\char@if@alph#1{% \ifnum0\ifnum`#1<`A 1\fi\ifnum`#1>`z 1\fi \if\ifnum`#1>`Z @\fi\ifnum`#1<`a @\fi01\fi>0 \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi} % %\EndIncludeInRelease % %\IncludeInRelease{0000/00/00}{\string@makeletter} % {Undefine \string@makeletter}% %\let\string@makeletter\@undefined %\let\@string@makeletter\@undefined %\let\char@if@alph\@undefined %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % % % \begin{macro}{\makeatletter} % \begin{macro}{\makeatother} % \changes{v1.0n}{1994/05/10}{Added \cs{makeatletter} and % \cs{makeatother} ASAJ.} % Make internal control sequences accessible or inaccessible. % \begin{macrocode} \DeclareRobustCommand\makeatletter{\catcode`\@11\relax} \DeclareRobustCommand\makeatother{\catcode`\@12\relax} % \end{macrocode} % \end{macro} % \end{macro} % % % \section{Discretionary Hyphenation} % \begin{macro}{\-} % \changes{1.2x}{1995/12/13}{Documentation changed.} % \changes{v1.5a}{2017/03/13}{Define \cs{-} in terms of \cs{hyphenchar}} % \begin{macro}{\@dischyph} % \changes{v1.0g}{1994/04/12} % {Define \cs{@dischyph}, was previously in ltboxes.dtx} % \changes{v1.5b}{2017/03/27}{Define \cs{@dischyph} after \cs{-}} % \changes{v1.5j}{2020/05/11}{Do not overwrite \cs{-} under Lua\TeX} % \end{macro} % Moved here to be after the definition of |\DeclareRobustCommand|. % % The primitive |\-| command adds a discretionary hyphen using the % current font's |\hyphenchar|. Monospace fonts are usually declared % with |\hyphenchar| set to $-1$ to suppress hyphenation. % % \LaTeX, from \LaTeX2.09 in 1986 defined |\-| by % \begin{verbatim} % \def\-{\discretionary{-}{}{}} % \end{verbatim} % The following comment was added when these commands were first set % up, 19 April 1986: % \begin{quote} % the |\-| command is redefined to allow it to work in the |\ttfamily| % type style, where automatic hyphenation is suppressed by setting % |\hyphenchar| to~$-1$. The original primitive \TeX{} definition is % saved as |\@@hyph| just in case anyone needs it. % \end{quote} % % \LaTeXe, between 1993 and 2017, had a comment at this point % saying that the definition ``would probably change'' because % the definition always uses |-|. The definition used below % was given in comments at this point during time. % % In 2017 we finally enabled this definition by default, with the % older \LaTeX\ definition accessible via \textsf{latexrelease} % as usual. % % In Lua\LaTeX\ the primitive definition of \cs{-} is used directly % because it's use of extended hyphenation parameters means that \cs{-} % works correctly even with \cs{hyphenchar} set to $-1$. This change % makes \cs{-} under Lua\LaTeX\ compatible with language specific % hyphenation characters. % % Temporary definition of |\@latex@info|, final definition is later. % \begin{macrocode} \def\@latex@info#1{} % \end{macrocode} % % \begin{macrocode} % %\IncludeInRelease{2020/10/01}{\-}{Use primitive \- in Lua\LaTeX}% %<*2ekernel|latexrelease> \ifx\directlua\@undefined \DeclareRobustCommand{\-}{% \discretionary{% \char \ifnum\hyphenchar\font<\z@ \defaulthyphenchar \else \hyphenchar\font \fi }{}{}% } \else \let\-\@@hyph \fi % %\EndIncludeInRelease %\IncludeInRelease{2017/04/15}{\-}{Use \hyphenchar in \-}% %\DeclareRobustCommand{\-}{% % \discretionary{% % \char \ifnum\hyphenchar\font<\z@ % \defaulthyphenchar % \else % \hyphenchar\font % \fi % }{}{}% %} %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}{\-}{Use \hyphenchar in \-}% %\def\-{\discretionary{-}{}{}} %\EndIncludeInRelease % \end{macrocode} % % \begin{macrocode} %<*2ekernel|latexrelease> \let\@dischyph=\- % %<*2ekernel> % \end{macrocode} % \end{macro} % % Delayed from |ltvers.dtx| % \begin{macrocode} \newif\if@includeinrelease \@includeinreleasefalse % \end{macrocode} % % \changes{v1.5f}{2019/08/27}{Make various commands robust} % % Delayed from |ltplain.dtx| % \begin{macrocode} % %<*2ekernel|latexrelease> %\IncludeInRelease{2019/10/01}% % {\allowbreak}{Make various commands robust}% \MakeRobust\allowbreak \MakeRobust\bigbreak \MakeRobust\break \MakeRobust\dotfill \MakeRobust\frenchspacing \MakeRobust\goodbreak \MakeRobust\hrulefill \MakeRobust\medbreak \MakeRobust\nobreak \MakeRobust\nonfrenchspacing \MakeRobust\obeylines \MakeRobust\obeyspaces \MakeRobust\slash \MakeRobust\smallbreak \MakeRobust\strut \MakeRobust\underbar % %\EndIncludeInRelease %\IncludeInRelease{0000/00/00}% % {\allowbreak}{Make various commands robust}% % %\kernel@make@fragile\allowbreak %\kernel@make@fragile\bigbreak %\kernel@make@fragile\break %\kernel@make@fragile\dotfill %\kernel@make@fragile\frenchspacing %\kernel@make@fragile\goodbreak %\kernel@make@fragile\hrulefill %\kernel@make@fragile\medbreak %\kernel@make@fragile\nobreak %\kernel@make@fragile\nonfrenchspacing %\kernel@make@fragile\obeylines %\kernel@make@fragile\obeyspaces %\kernel@make@fragile\slash %\kernel@make@fragile\smallbreak %\kernel@make@fragile\strut %\kernel@make@fragile\underbar % %\EndIncludeInRelease %<*2ekernel> % \end{macrocode} % % % \begin{macro}{\g@addto@macro} % Globally add to the end of a macro. % This macro is used by the kernel to add to its internal hooks. % \changes{v0.2a}{1993/11/14}{Made global} % \changes{v0.2w}{1994/01/31} % {Use toks register to avoid `hash' problems} % \changes{v1.0o}{1995/05/17} % {Make long for latex/1522} % \changes{v1.0w}{1996/12/17} % {Use \cs{begingroup} to save making a mathord} % \changes{v1.0x}{1997/02/05} % {missing percent /2402} % \begin{macrocode} \long\def\g@addto@macro#1#2{% \begingroup \toks@\expandafter{#1#2}% \xdef#1{\the\toks@}% \endgroup} % \end{macrocode} % \end{macro} % % % \begin{macrocode} % % \end{macrocode} % % % \Finale %