% \iffalse meta-comment % % Copyright 1994 the LaTeX3 project and the individual authors. % All rights reserved. For further copyright information see the file % legal.txt, and any other copyright indicated in this file. % % This file is part of the LaTeX2e system. % ---------------------------------------- % % This system is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. % % % IMPORTANT NOTICE: % % For error reports in case of UNCHANGED versions see bugs.txt. % % Please do not request updates from us directly. Distribution is % done through Mail-Servers and TeX organizations. % % You are not allowed to change this file. % % You are allowed to distribute this file under the condition that % it is distributed together with all files mentioned in manifest.txt. % % If you receive only some of these files from someone, complain! % % You are NOT ALLOWED to distribute this file alone. You are NOT % ALLOWED to take money for the distribution or use of either this % file or a changed version, except for a nominal charge for copying % etc. % \fi % % \iffalse %%% File: ltdefns.dtx %<*driver> % \fi \ProvidesFile{ltdefns.dtx} [1994/05/23 v1.1h 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} \maketitle \DocInput{\filename} \end{document} % % \fi % % \CheckSum{598} % % \changes{v1.0n}{1994/05/10}{(ASAJ) Added % \cmd\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} % % \section{Definitions} % % This section contains commands used in defining other macros. % % \StopEventually{} % % \begin{macrocode} %<*2ekernel> \catcode`\~=13 \def~{\penalty\@M \ } % \end{macrocode} % \subsection{Initex initialisations} % % \task{???}{This section needs extension} % \task{???}{Do we use @unused or mainaux?} % \begin{macro}{\@inputcheck} % \begin{macro}{\@unused} % Allocate read stream for testing and output stream. % \begin{macrocode} \newread\@inputcheck \newwrite\@unused \newwrite\@mainaux % \end{macrocode} % \end{macro} % \end{macro} % % \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} % % \begin{macro}{\typeout} % Display something on the terminal. % \begin{macrocode} \def\typeout#1{\begingroup\let\protect\string \immediate\write\@unused{#1}\endgroup} % \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{macrocode} \let\@@par=\par %\let\@@input=\input %%% moved earlier %\let\@@end=\end %%% % \end{macrocode} % % The following was added 19 April 1986: % 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 definition is saved as |\@@hyph| % just in case anyone needs it. % \begin{macrocode} \let\@@hyph=\- % Original defin \def\-{\discretionary{-}{}{}} % \end{macrocode} % % \begin{macro}{\@dischyph} % \changes{v1.0g}{1994/04/12} % {Define \cmd{\@dischyph}, was previously in ltboxes.dtx} % \begin{macrocode} \let\@dischyph=\- % \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} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % \end{macro} % % \begin{macrocode} \message{hacks,} % \end{macrocode} % % \subsection{Command definitions} % % \begin{oldcomments} % % \@namedef{NAME} : Expands to \def\NAME , except name can contain any % characters. % \@nameuse{NAME} : Expands to \NAME . % % \@ifnextchar X{YES}{NO} : % Expands to YES if next character is an 'X', % and to NO otherwise. (Uses temps a-c.) % NOTE: GOBBLES ANY SPACE FOLLOWING IT. % % \@ifstar{YES}{NO} : % Gobbles following spaces and then tests if next the % character is a '*'. If it is, then it gobbles the % '*' and expands to YES, otherwise it expands to NO. % % \@dblarg{CMD}{ARG} : % \@dblarg{CMD}{ARG} expands to CMD[ARG]{ARG}. Use % \@dblarg\CS when \CS takes arguments [ARG1]{ARG2}, % where default is ARG1 = ARG2. % % \@ifundefined{NAME}{YES}{NO} % : If \NAME is undefined then it executes YES, % otherwise it executes NO. More precisely, % true if \NAME either undefined or = \relax. % \@ifdefinable \NAME {YES} % : Executes 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' /= 'relax' % and the first three letters of 'NAME' are not % 'end'. % \newcommand{\FOO}[i]{TEXT} % : User command to define \FOO to be a macro with % i arguments (i = 0 if missing) having the definition % TEXT. Produces an error if \FOO already defined. % % \renewcommand{\FOO}[i]{TEXT} : Same as \newcommand, except it % checks if \FOO already defined. % % \newenvironment{FOO}[i]{DEF1}{DEF2} % equivalent to % \newcommand{\FOO}[i]{DEF1} \def{\endFOO}{DEF2} % % \renewenvironment : obvious companion to \newenvironment % % \@cons : See description of \output routine. % % \@car T1 T2 ... Tn\@nil == T1 (unexpanded) % % \@cdr T1 T2 ... Tn\@nil == T2 ... Tn (unexpanded) % % \typeout{message} : produces a warning message on the terminal % % \typein{message} % : Types message, asks the user to type in a command, then % executes it % % \typein[\CS]{MSG} : Same as above, except defines \CS to be the input % instead of executing it. % % RmS 92/03/18: changed input channel from 0 to \@inputcheck to avoid % conflicts % with other channels allocated by \newread % \begin{macrocode} \def\typein{% \let\@typein\relax\@ifnextchar[{\@xtypein}{\@xtypein[\@typein]}} \def\@xtypein[#1]#2{\typeout{#2}\read\@inputcheck to#1\ifx #1\@defpar \def#1{}\else \@iden{\expandafter\@strip\expandafter #1#1\@gobble\@gobble} \@gobble\fi\@typein} \def\@strip#1#2 \@gobble{\def #1{#2}} \def\@defpar{\par} \def\@iden#1{#1} % \end{macrocode} % % \begin{macrocode} \def\@namedef#1{\expandafter\def\csname #1\endcsname} \def\@nameuse#1{\csname #1\endcsname} % \end{macrocode} % % \begin{macrocode} \def\@cons#1#2{\begingroup\let\@elt\relax\xdef#1{#1\@elt #2}\endgroup} % \end{macrocode} % % \begin{macrocode} \def\@car#1#2\@nil{#1} \def\@cdr#1#2\@nil{#2} % \end{macrocode} % % \@carcube T1 ... Tn\@nil = T1 T2 T3 , n > 3 % \begin{macrocode} \def\@carcube#1#2#3#4\@nil{#1#2#3} % \end{macrocode} % % % \begin{macrocode} \long\def\@renewenv#1[#2]#3#4{\expandafter\renewcommand \csname #1\endcsname[#2]{#3}\long \expandafter\def\csname end#1\endcsname{#4}} % \end{macrocode} % % \end{oldcomments} % % % \begin{macro}{\newcommand} % \changes{LaTeX2e}{1993/11/23}{Macro reimplemented and extended} % User level |\newcommand|. % \begin{macrocode} \def\newcommand#1{% \@ifnextchar [{\@newcommand#1}{\@newcommand#1[0]}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@newcommand} % \changes{LaTeX2e}{1993/11/23}{Macro added} % \begin{macro}{\@xargdef} % \changes{LaTeX2e}{1993/11/23}{Macro added} % \begin{macro}{\@xargdef} % \changes{LaTeX2e}{1993/11/23}{Macro interface changed} % Handling arguments for |\newcommand|. % \begin{macrocode} \def\@newcommand#1[#2]{% \@ifnextchar [{\@xargdef#1[#2]}% {\@argdef#1[#2]}} % \end{macrocode} % Define |#1| if it is definable. % \begin{macrocode} \long\def\@argdef#1[#2]#3{% \@ifdefinable #1{\@yargdef#1\@ne{#2}{#3}}} % \end{macrocode} % % 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{\@ifnextchar[\\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 exisiting command names. % ``Default'' is the contents of the second optional argument of % |\(re)newcommand|. % \begin{macrocode} \expandafter\def\expandafter#1\expandafter{% \expandafter \@ifnextchar \expandafter [% \csname\string#1\expandafter\endcsname \expandafter {\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}{\@yargdef} % \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 \cmd{\XXX@argdef}} % Generate a primitive argument specification, from a \LaTeX\ % |[|\meta{num}|]| form. % % Reorganised slightly so that |\renewcommand[1]{\@tempa}{foo}| % works. I am not sure this is worth it, as a following % |\newcommand| would over-write the definition of |\@tempa|. % \LaTeX2.09 goes into an infinite loop with\\ % |\renewcommand[1]{\@tempa}{foo}|.\\ (DPC 6 October 93) % \begin{macrocode} \long\def\@yargdef#1#2#3{% \@tempcnta#3\relax \advance \@tempcnta \@ne \let\@hash@\relax \edef\@tempa{\ifx#2\tw@ [\@hash@1]\fi}% \@tempcntb #2% \@whilenum\@tempcntb <\@tempcnta \do{% \edef\@tempa{\@tempa\@hash@\the\@tempcntb}% \advance\@tempcntb \@ne}% \let\@hash@##% \long\expandafter\def\expandafter#1\@tempa} % \end{macrocode} % \end{macro} % % \begin{macro}{\@reargdef} % \changes{LaTeX2e}{1993/12/20} % {Kept old version of \cmd\@reargdef, for array.sty} % \changes{v1.0b}{1994/03/12}{New defn, in terms of \cmd{\@yargdef}} % \begin{macrocode} \long\def\@reargdef#1[#2]#3{% \@yargdef#1\@ne{#2}{#3}} % \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/2}{Removed surplus \cmd\space in error} % \begin{macrocode} \def\renewcommand#1{% {\escapechar\m@ne\xdef\@gtempa{{\string#1}}}% \expandafter\@ifundefined\@gtempa {\@latex@error{\string#1 undefined}\@ehc}% {}% \let\@ifdefinable\@rc@ifdefinable \newcommand#1} % \end{macrocode} % \end{macro} % % \changes{v1.0n}{1994/05/10}{Removed braces around \cmd\@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 is user is allowed to define a command. % \begin{macrocode} \long\def\@ifdefinable #1#2{% \edef\@tempa{\expandafter\@gobble\string #1}% \@ifundefined\@tempa {\edef\@tempb{\expandafter\@carcube \@tempa xxx\@nil}% \ifx \@tempb\@qend \@notdefinable\else \ifx \@tempa\@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. % \begin{macrocode} \def\newenvironment#1#2#{% \@newenv{#1}{#2}} % \end{macrocode} % \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/2}{Removed surplus \cmd\space in error} % \begin{macrocode} \def\renewenvironment#1{% \@ifundefined{#1}% {\@latex@error{Environment #1 undefined}\@ehc }{}% \expandafter\let\csname#1\endcsname\relax \newenvironment{#1}} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@newenv} % \changes{LaTeX2e}{1993/11/23}{Macro interface changed} % 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) % \begin{macrocode} \long\def\@newenv#1#2#3#4{% \expandafter\newcommand \csname #1\endcsname#2{#3}\long \long\expandafter\def\csname end#1\endcsname{#4}} % \end{macrocode} % \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 |\@tempa| (and possibly |\\@tempa|) 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#1{% {\escapechar\m@ne\xdef\@gtempa{{\string#1}}}% \expandafter\@ifundefined\@gtempa {\def\@tempa{\newcommand#1}}% {\def\@tempa{\renewcommand\@tempa}}% \@tempa}% % \end{macrocode} % \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 befor 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#1#2#{\@check@c#1{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\@check@c} % |\CheckCommand| itself just grabs all the arguments we need, % without actually looking for |[| optional argument forms. Now % define |\@tempa|. If |\\@tempa| is then defined, compare it with % the ``|\#1|' otherwise compare |\@tempa| with |#1|. % \begin{macrocode} \def\@check@c#1#2#3{% \expandafter\let\csname\string\@tempa\endcsname\relax \renewcommand\@tempa#2{#3}% \@ifundefined{\string\@tempa}% {\@check@eq#1\@tempa}% {\expandafter\@check@eq \csname\string#1\expandafter\endcsname \csname\string\@tempa\endcsname}} % \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} % \end{macrocode} % \end{macro} % % \begin{macro}{\@gobble} % \begin{macro}{\@gobbletwo} % \begin{macro}{\@gobblefour} % The |\@gobble| macro is used to get rid of its argument. % \begin{macrocode} \def\@gobble#1{} \def\@gobbletwo#1#2{} \def\@gobblefour#1#2#3#4{} % \end{macrocode} % \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} % \end{macro} % \end{macro} % \end{macro} % % \begin{macro}{\@expandtwoargs} % A macro to totally expand two arguments to another macro % \begin{macrocode} \def\@expandtwoargs#1#2#3{% \edef\@tempa{\noexpand#1{#2}{#3}}\@tempa} % \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 \cmd\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 % ocassions 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 five 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. % \item |\@unexpandable@noexpand|, for performing a deferred write % inside an |\edef|. So |\protect\foo| will write |\foo| followed % by a space. If you want |\protect\foo| to be written, you should % use |\@unexpandable@protect|. % \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} % \begin{macro}{\@unexpandable@noexpand} % These commands are used for setting |\protect| inside |\edef|s. % \begin{macrocode} \def\@unexpandable@protect{\noexpand\protect\noexpand} \def\@unexpandable@noexpand{\noexpand\noexpand\noexpand} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{macro}{\DeclareRobustCommand} % \begin{macro}{\@protected@short} % \begin{macro}{\@protected@short@} % \begin{macro}{\relax} % 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 |\@protected@short\_\_|, % which expands to: % \begin{verbatim} % \protect\relax\@protected@short@\@gobble\_\_ % \end{verbatim} % We then have five cases: % \begin{itemize} % \item |\protect| is |\relax| (we're executing commands), % so |\relax| gobbles the % |\@protected@short@|, and the |\@gobble| gobbles the |\_|, so % |\_| is executed. % \item |\protect| is |\noexpand| (we're writing to a file), so % |\relax| is not expanded, so the |\@protected@short@| % expands to produce |\protect\_|, and so |\relax \_| is % written to the file. % \item |\protect| is |\string| is similar. % \item |\protect| is |\@unexpandable@protect| % (we're inside an |\edef|), so\\ % |\relax| is not expanded, so the |\@protected@short@| % expands to produce |\protect\_|. If the result is written to % an auxiliary file (with |\protect| set to |\noexpand|), it % will produce |\relax \_|. If it is executed (with |\protect| % set to |\relax|) then it will execute |\_|, and we'll be back % in the first case again. % \item |\protect| is |\@unexpandable@protect| (we're inside a % deferred |\write| inside an |\edef|). Then % |\noexpand\relax\protect\_| will be put into the % |\write|, which will cause |\relax \protect \_| to be written % to the file. This is safe, although it's not quite what was % wanted if you're going to sort an index based on this. In % such a case you have to preceed |\_| with |\protect| % explicitly. % \end{itemize} % So after all that work, |\_| will always be written to an % auxiliary file with no trailing space, although it will have an % extra |\relax| and/or |\protect| in front of it. % % More fun with |\expandafter| and |\csname|. % \begin{macrocode} \def\DeclareRobustCommand#1{% \ifx#1\@undefined\else\ifx#1\relax\else \@latex@info{Redefining \string#1}% \fi\fi \edef\@tempa{\string#1}% \def\@tempb{#1}% \edef\@tempb{\expandafter\strip@prefix\meaning\@tempb}% \edef#1{% \ifx\@tempa\@tempb \noexpand\@protected@short \noexpand#1% \else \noexpand\protect \fi \expandafter\noexpand\csname \expandafter\@gobble\string#1 \endcsname }% \let\@ifdefinable\@rc@ifdefinable \expandafter\newcommand\csname \expandafter\@gobble\string#1 \endcsname } { \catcode`\ =\catcode`\a% \gdef\@protected@short{\protect\relax \@protected@short@\@gobble}% \gdef\@protected@short@\@gobble#1#2{\protect#1}% \global\let\relax \@gobble% } % \end{macrocode} % \end{macro} % \end{macro} % \end{macro} % \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 \cmd\fi} % Check if first arg is undefined or |\relax| and execute second or % third arg depending, % \begin{macrocode} \def\@ifundefined#1{% \expandafter\ifx\csname#1\endcsname\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi} % \end{macrocode} % \end{macro} % % % \begin{macro}{\@onlypreamble} % This macro adds its argument to the list of commands to be % disabled after |\begin{document}|. % \begin{macrocode} \def\@preamblecmds{} \def\@onlypreamble#1{% \expandafter\gdef\expandafter\@preamblecmds\expandafter{% \@preamblecmds\do#1}} \@onlypreamble\@onlypreamble % \end{macrocode} % \end{macro} % % % \begin{oldcomments} % The following define \@qend and \@qrelax to be the strings 'end' and % 'relax' with the characters \catcoded 12. % % \begin{macrocode} \edef\@qend{\expandafter\@cdr\string\end\@nil} \edef\@qrelax{\expandafter\@cdr\string\relax\@nil} % \end{macrocode} % % \@ifnextchar X{YES}{NO} % BEGIN % \@tempe := X % uses \let % \@tempa := YES % \@tempb := NO % \futurelet\@tempc % \@ifnch % END % % \@ifnch == % BEGIN % if \@tempc = blank space % then \@tempd := def(\@xifnch) % else if \@tempc = \@tempe % then \@tempd := def(\@tempa) % else \@tempd := def(\@tempb) % fi % fi % \@tempd % END % % \@xifnch == % BEGIN % gobble blanks % \futurelet\@tempc % \@ifnch % END % % \end{oldcomments} % \begin{macro}{\@ifnextchar} % \changes{LaTeX209}{1992/08/24} % {(Rms) \cs{@ifnextchar} didn't work if its % first argument was an equal sign.} % \begin{macrocode} \def\@ifnextchar#1#2#3{% \let\@tempe=#1\def\@tempa{#2}\def\@tempb{#3}\futurelet \@tempc\@ifnch} \def\@ifnch{\ifx \@tempc \@sptoken \let\@tempd\@xifnch \else \ifx \@tempc \@tempe\let\@tempd\@tempa\else \let\@tempd\@tempb\fi \fi \@tempd} % \end{macrocode} % \end{macro} % % \changes{v1.0n}{1994/05/10}{Added \cmd\makeatletter\ and % \cmd\makeatother\ ASAJ.} % % \begin{macro}{\makeatletter} % \begin{macro}{\makeatother} % Make internal control sequences accessible or inaccessible. % \begin{macrocode} \def\makeatletter{\catcode`\@=11\relax} \def\makeatother{\catcode`\@=12\relax} % \end{macrocode} % \end{macro} % \end{macro} % % \begin{oldcomments} % 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} % % \begin{macrocode} \def\:{\@xifnch} \expandafter\def\: {\futurelet\@tempc\@ifnch} % \end{macrocode} % % \begin{macrocode} \def\@ifstar#1#2{\@ifnextchar *{\def\@tempa*{#1}\@tempa}{#2}} % \end{macrocode} % % \begin{macrocode} \long\def\@dblarg#1{\@ifnextchar[{#1}{\@xdblarg{#1}}} \long\def\@xdblarg#1#2{#1[{#2}]{#2}} % \end{macrocode} % % 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{oldcomments} % % \Finale \endinput