Raw File
ltxref.dtx
% \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: ltxref.dtx
%
%<*driver>
% \fi
\ProvidesFile{ltxref.dtx}
             [2023/05/16 v1.1q LaTeX Kernel (Cross Referencing)]
% \iffalse
\documentclass{ltxdoc}
\GetFileInfo{ltxref.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}
%</driver>
% \fi
%
%
% \changes{v1.0c}{1994/03/29}
%     {Create file ltcntlen from parts of ltmiscen and ltherest.}
% \changes{v1.1a}{1994/05/19}
%     {Extract file ltxref from ltcntlen.}
% \changes{v1.1b}{1994/05/21}{Use new warning commands}
% \changes{v1.1c}{1994/05/25}{Modify documentation}
% \changes{v1.1p}{2022/04/12}{Add starred variants for the ref commands}
%
% \section{Cross Referencing}
%  The user writes  |\label|\marg{foo}  to define the following
%  cross-references:
%
%   |\ref|*\marg{foo}: value of most recently incremented referenceable
%             counter. in the current environment. (Chapter, section,
%             theorem, footnote and enumeration counters and other counters
%             stepped with \cs{refstepcounter} are
%             referenceable.)
%
%   |\pageref|*\marg{foo}: page number at which |\label{foo}|  command
%             appeared.  where  foo  can be any string of characters not
%             containing  `|\|', `|{|' or `|}|'.
%
%  Note: The scope of the |\label| command is delimited by environments,
%  so\\
%  |\begin{theorem} \label{foo} ... \end{theorem} \label{bar}|\\
%  defines |\ref{foo}| to be the theorem number and |\ref{bar}| to be
%  the current section number.
%
%  Note: |\label| does the right thing in terms of spacing -- i.e.,
%  leaving a space on both sides of it is equivalent to leaving
%  a space on either side.
%
%  Note: the starred versions |\ref*| and |\pageref*| are provided
%  to align with the use of \pkg{hyperref}. Without \pkg{hyperref} (or some
%  other package using the starred form) the star is simply ignored.
%
%  Note: starting with 2023-06-01 |\label| stores also the current value
%  of |\@currentlabelname| which should typically contain a (sanitized) title.
%  (A reference command |\nameref| is provided by the \pkg{nameref} package.)
%  |\label| also stores |\@currentHref| which if set should refer to a target name
%  for links. This value is set and used by \pkg{hyperref}. Unlike the other values
%  |\@currentHref| should be set globally. A fifth value |\@kernel@reserved@label@data|
%  is reserved for the kernel to allow future extensions of the cross-reference
%  system.
%    
%
% \MaybeStop{}
%
% \subsection{Cross Referencing}
%
% \begin{oldcomments}
%    \begin{macrocode}
%<*2ekernel>
\message{x-ref,}
%    \end{macrocode}
%
%  This is implemented as follows.  A referenceable counter  CNT  is
%  incremented by the command  \refstepcounter{CNT} , which sets
%  \@currentlabel == {CNT}{eval(\p@cnt\theCNT)}.   The command
%  \label{FOO} then writes the following on file \@auxout :
%        \newlabel{FOO}{{eval(\@currentlabel)}{eval(\thepage)}%
%           {eval(\@currentlabelname)}{eval(\@currentHref)}{eval(\@kernel@reserved@label@data)}}
%
%  \ref{FOO} ==
%    BEGIN
%      if \r@foo undefined
%        then  @refundefined := G T
%              ??
%              Warning: 'reference foo on page ... undefined'
%        else  \@car \eval(\r@FOO)\@nil
%      fi
%    END
%
%  \pageref{foo} =
%    BEGIN
%      if \r@foo undefined
%        then  @refundefined := G T
%              ??
%              Warning: 'reference foo on page ... undefined'
%        else  \@cdr \eval(\r@FOO)\@nil
%      fi
%    END
%
% \end{oldcomments}
%
% \DescribeMacro\labelformat
% A reference via |\ref| produces by default the data associated with
% the corresponding |\label| command (typically a number); any
% additional formatting has to be provided by the user. If, for
% example, references to equations are always to be typeset as
% ``equation (\textit{number})'', one has to code
% ``\verb=equation (\ref{=\textit{key}\verb=})=''.  With |\labelformat|
% there is a possibility to generate such
% frills automatically without resorting to low-level coding.
% The command takes two arguments: the first is
% the name of a counter and the second is its representation when
% referenced. This means that for a successful usage, one has to know
% the counter name being used for generating the label, though in
% practice this should not pose a problem. The current counter number
% is picked up as an argument.
% Here are two examples:
%\begin{verbatim}
%  \labelformat{section}{section~#1}
%  \labelformat{equation}{equation~(#1)}}
%\end{verbatim}
%
% \DescribeMacro\Ref
% A side effect of using |\labelformat| is that, depending on the
% defined formatting, it becomes impossible to use |\ref| at the
% beginning of a sentence (if its replacement text starts with a
% lowercase letter). To overcome this problem we
% introduce the command |\Ref| that behave like
% |\ref| except that it uppercases the first token
% of the generated string.
%

% To make |\Ref| work properly the very first token in the second
% argument of |\labelformat| has to be a simple \textsc{ascii} or
% UTF-8 letter, otherwise the capitalization will fail or worse, you
% will end up with some error messages. If you actually need something
% more complicated in this place (e.g., an accented letter not written
% as a UTF-8 character) you have to explicitly surround it with
% braces, to identify the part that needs to be capitalized. For
% example, for figure references in the Hungarian language you might
% want to write |\labelformat{figure}{{\'a}bra~\thefigure}| or use
% |\labelformat{figure}{ábra~\thefigure}| which avoids the brace
% problem.
%
%
%  \begin{macro}{\G@refundefinedtrue}
% \changes{v1.1i}{1995/12/07}{Renamed (back) from \cs{G@refundefined}}
%  \begin{macro}{\@refundefined}
% \changes{v1.1h}{1995/10/24}{Switch for refundefined replaced}
%    This does not save on name-space (since \cs{G@refundefinedfalse}
%    was never needed) but it does make the implementation of such
%    one-way switches more consistent. The extra macro to make the
%    change is used since this change appears several times.
%
%    \textbf{Note} despite its name, |\G@refundefinedtrue| does
%    \emph{not} correspond to an |\if| command, and there is no
%    matching \ldots|false|. It would be more natural to call the
%    command |\G@refundefined| (as inspection of the change log will
%    reveal) but unfortunately such a change would break any package
%    that had defined a  |\ref|-like command that mimicked the
%    definition of |\ref|, calling |\G@refundefinedtrue|. Inspection
%    of the \TeX\ archives revealed several such packages, and so this
%    command has been named \ldots|true| so that the definition of
%    |\ref| need not be changed, and the packages will work without
%    change.
%    \begin{macrocode}
% \newif\ifG@refundefined
% \def\G@refundefinedtrue{\global\let\ifG@refundefined\iftrue}
% \def\G@refundefinedfalse{\global\let\ifG@refundefined\iffalse}
\def\G@refundefinedtrue{%
  \gdef\@refundefined{%
    \@latex@warning@no@line{There were undefined references}}}
\let\@refundefined\relax
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%    \begin{macrocode}
%    \end{macrocode}
%  \begin{macro}{\ref}
% \changes{LaTeX2e}{1993/12/11}{Macro reimplemented}
% \changes{LaTeX2e}{2022/04/12}{Macro reimplemented with a starred version}
%  \begin{macro}{\pageref}
% \changes{LaTeX2e}{1993/12/11}{Macro reimplemented}
% \changes{LaTeX2e}{2022/04/12}{Macro reimplemented with a starred version}
%  \begin{macro}{\@setref}
% \changes{LaTeX2e}{1993/12/11}{Macro added}
% \changes{v1.1h}{1995/10/24}{Switch for refundefined renamed}
% \changes{v1.1i}{1995/12/07}{Switch for refundefined restored}
%    Referencing a |\label|.
% RmS 91/10/25: added a few extra |\reset@font|,
%               as suggested by Bernd Raichle
%
% RmS 92/08/14: made |\ref| and |\pageref| robust
%
% RmS 93/09/08: Added setting of refundefined switch.
%    \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2023/06/01}%
%<latexrelease>                 {\@kernel@sref}{store five arguments}%
\def\@setref#1#2#3{%
  \ifx#1\relax
   \protect\G@refundefinedtrue
   \nfss@text{\reset@font\bfseries ??}%
   \@latex@warning{Reference `#3' on page \thepage \space
             undefined}%
  \else
   \expandafter#2#1\@empty\@empty\@empty\null
  \fi}
%    \end{macrocode}
%    \begin{macrocode}
\long\def\@firstoffive#1#2#3#4#5{#1}
\long\def\@secondoffive#1#2#3#4#5{#2}
\def\@kernel@sref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoffive{#1}}
\def\@kernel@spageref#1{\expandafter\@setref\csname r@#1\endcsname
                 \@secondoffive{#1}}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2022/06/01}%
%<latexrelease>                 {\@kernel@sref}{store five arguments}%
%<latexrelease>\def\@setref#1#2#3{%
%<latexrelease>  \ifx#1\relax
%<latexrelease>   \protect\G@refundefinedtrue
%<latexrelease>   \nfss@text{\reset@font\bfseries ??}%
%<latexrelease>   \@latex@warning{Reference `#3' on page \thepage \space
%<latexrelease>             undefined}%
%<latexrelease>  \else
%<latexrelease>   \expandafter#2#1\null
%<latexrelease>  \fi}
%<latexrelease>\let\@firstoffive\undefined
%<latexrelease>\let\@secondoffive\undefined
%<latexrelease>\def\@kernel@sref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoftwo{#1}}
%<latexrelease>\def\@kernel@spageref#1{\expandafter\@setref\csname r@#1\endcsname
%<latexrelease>                 \@secondoftwo{#1}}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\@kernel@sref}{store five arguments}%
%<latexrelease>\def\@setref#1#2#3{%
%<latexrelease>  \ifx#1\relax
%<latexrelease>   \protect\G@refundefinedtrue
%<latexrelease>   \nfss@text{\reset@font\bfseries ??}%
%<latexrelease>   \@latex@warning{Reference `#3' on page \thepage \space
%<latexrelease>             undefined}%
%<latexrelease>  \else
%<latexrelease>   \expandafter#2#1\null
%<latexrelease>  \fi}
%<latexrelease>\let\@firstoffive\undefined
%<latexrelease>\let\@secondoffive\undefined
%<latexrelease>\let\@kernel@sref\undefined
%<latexrelease>\let\@kernel@spageref\undefined
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2022/06/01}%
%<latexrelease>                 {\ref}{Add starred reference commands}%
%    \end{macrocode}
%    \begin{macrocode}
\let\@kernel@ref\@kernel@sref
\let\@kernel@pageref\@kernel@spageref
\NewDocumentCommand\ref{s}
   {\IfBooleanTF{#1}{\@kernel@sref}{\@kernel@ref}}
\NewDocumentCommand\pageref{s}
   {\IfBooleanTF{#1}{\@kernel@spageref}{\@kernel@pageref}}
%    \end{macrocode}
% As the commands are now protected we also need expandable versions for use
% in \cs{ifthenelse}:
%    \begin{macrocode}
\def\@kernel@pageref@exp#1{\csname cs_if_exist:cTF\endcsname
   {r@#1}{\csname tl_item:cn\endcsname{r@#1}{2}}{0}}
\def\@kernel@ref@exp#1{\csname cs_if_exist:cTF\endcsname
   {r@#1}{\csname tl_item:cn\endcsname{r@#1}{1}}{0}}
%    \end{macrocode}
%    \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\ref}{Add starred reference commands}%
%<latexrelease>\def\ref#1{\expandafter\@setref\csname r@#1\endcsname\@firstoftwo{#1}}
%<latexrelease>\def\pageref#1{\expandafter\@setref\csname r@#1\endcsname
%<latexrelease>                                   \@secondoftwo{#1}}
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%  \end{macro}
%
%
%  \begin{macro}{\newlabel}
% \changes{v1.1b}{1994/05/21}{Use new warning commands}
% \changes{v1.1e}{1995/04/24}{Make \cs{@onlypreamble} for /1388.}
% \changes{v1.1e}{1995/06/19}
%      {Use \cs{@newl@bel} to share code with \cs{bibcite}}
% \changes{v1.1g}{1995/07/14}
%   {Remove \cs{@onlypreamble} so still defined in new \cs{enddocument}}
%    This command will be written to the \texttt{.aux} file to
%    pass label information from one run to another.
%  \begin{macro}{\@newl@bel}
%    The internal form of |\newlabel| and |\bibcite|. Note that this
%    macro does it's work inside a group. That way the local
%    assignments it needs to do don't clutter the save stack. This
%    prevents large documents with many labels to run out of save
%    stack.
% \changes{v1.1h}{1995/10/24}{Switch for multiplelabels replaced by
%    inline code}
% \changes{v1.1k}{2001/02/16}{Added an extra grouplevel (PR3250), jlb}
%    \begin{macrocode}
\def\@newl@bel#1#2#3{{%
  \@ifundefined{#1@#2}%
    \relax
    {\gdef \@multiplelabels {%
       \@latex@warning@no@line{There were multiply-defined labels}}%
     \@latex@warning@no@line{Label `#2' multiply defined}}%
  \global\@namedef{#1@#2}{#3}}}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\newlabel{\@newl@bel r}
%    \end{macrocode}
%
%    \begin{macrocode}
\@onlypreamble\@newl@bel
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\if@multiplelabels}
% \changes{v1.1h}{1995/10/24}{Macro removed}
%  \begin{macro}{\@multiplelabels}
% \changes{v1.1h}{1995/10/24}{Switch for multiplelabels removed}
%    This is redefined to produce a warning if at least one label is
%    defined more than once. It is executed by the |\enddocument|
%    command.
%    \begin{macrocode}
\let \@multiplelabels \relax
%    \end{macrocode}
%  \end{macro}
%  \end{macro}
%
%  \begin{macro}{\label}
% \changes{v1.1d}{1994/11/04}{(ASAJ)Added \cs{protected@write}}
% \changes{v1.1d}{1994/11/04}{(ASAJ)Added \cs{protected@edef}}
% \changes{v1.1q}{2023/05/12}{(UFi)extended to store five arguments}
% \changes{v1.1q}{2023/05/12}{(UFi)added a hook with argument} 
%    The commands |\label| and |\refstepcounter| have been changed to
%    allow |\protect|'ed commands to work properly.  For example,
%\begin{verbatim}
%   \def\thechapter{\protect\foo{\arabic{chapter}.\roman{section}}}
%\end{verbatim}
%    will cause a |\label{bar}| command to define |\ref{bar}| to expand
%    to something like |\foo{4.d}|.  Change made 20 Jul 88.
%
%    \begin{macrocode}
%</2ekernel>
%<*2ekernel|latexrelease>
%<latexrelease>\IncludeInRelease{2023/06/01}%
%<latexrelease>                 {\label}{store five label arguments}%
\providecommand\@currentlabelname{}
\providecommand\@currentHref{}
\providecommand\@kernel@reserved@label@data{}
\NewHookWithArguments{label}{1}
\def\label#1{\@bsphack
  \begingroup
  \UseHookWithArguments{label}{1}{#1}%
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\@currentlabel}{\thepage}%
          {\@currentlabelname}{\@currentHref}{\@kernel@reserved@label@data}}}%
  \endgroup        
  \@esphack}
%<latexrelease>\EndIncludeInRelease
%    \end{macrocode}
% \end{macro}
%
%    \begin{macrocode}
%<latexrelease>\IncludeInRelease{2022/06/01}%
%<latexrelease>                 {\Ref}{Add starred version}%
%    \end{macrocode}
%
%  \begin{macro}{\refstepcounter}
%     Step the counter and allow for labels to point to its current value.
%  \changes{v1.1n}{2020/05/05}{record the counter name in \cs{@currentcounter}}
%  \changes{v1.1o}{2020/08/23}{add default definition of \cs{@currentcounter}}
%    \begin{macrocode}
\def\@currentcounter{}
\def\refstepcounter#1{\stepcounter{#1}%
    \edef\@currentcounter{#1}%
    \protected@edef\@currentlabel
%    \end{macrocode}
%    By generating the second csname first the |\p@...| command can
%    grab it as an argument which can be helpful for more complicated
%    typesetting arrangements.
%
%    The trick is to ensure that |\csname the#1\endcsname| is turned
%    into a single token before |\p@...| is expanded further. This
%    way, if the |\p@...| command is a macro with one argument it will
%    receive |\the...|. With the original kernel code (i.e., without the
%    |\expandafter|) it will instead pick up |\csname| which would be
%    disastrous.
%
%    Using |\expandafter| instead of braces delimiting the argument is
%    better because, assuming that the |\p@...| command is not defined
%    as a macro with one argument, the braces will stay and prohibit
%    kerning that might otherwise happen between the glyphs generated
%    by |\the...| and surrounding glyphs.
%
%  \changes{v1.1l}{2019/08/22}{Allow \cs{p@...} to have an
%          argument}
%    \begin{macrocode}
       {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}%
}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\labelformat}
%    A shortcut to set the |\p@...| macro for a counter. It will pick
%    up the counter representation as an argument so that it can be
%    specially formatted.
%  \changes{v1.1l}{2019/08/22}{Commanded moved from \texttt{varioref.sty}}
%    \begin{macrocode}
\def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1}
%    \end{macrocode}
%  \end{macro}
%
%  \begin{macro}{\Ref}
%    This macro expands the result of |\ref| and then uppercases the
%    first token. Only useful if the label was generated via
%    |\labelformat| and contains some lower case letter at its start. If
%    the label starts with a complicated construct (e.g., an accented
%    letter that is provided via a command, e.g., \verb=\"a= instead
%     of a UTF-8 character like ä) one has to surround everything that
%    needs uppercasing in
%    a brace group in the definition of |\labelformat|.\footnote{There
%    is one problem with this approach: the braces are kept in a
%    normal \texttt{\textbackslash ref} which might spoil kerning.
%    Perhaps one day this needs redoing.}
%  \changes{v1.1l}{2019/08/22}{Commanded moved from \texttt{varioref.sty}}
%  \changes{v1.1p}{2022/04/12}{Macro reimplemented with a starred version}%
%    \begin{macrocode}
\def\@kernel@Ref#1{\protected@edef\@tempa{\@kernel@ref{#1}}%
       \expandafter\MakeUppercase\@tempa}
\def\@kernel@sRef#1{\protected@edef\@tempa{\@kernel@sref{#1}}%
       \expandafter\MakeUppercase\@tempa}
\NewDocumentCommand\Ref{s}
   {\IfBooleanTF{#1}{\@kernel@sRef}{\@kernel@Ref}}
%    \end{macrocode}
%  \end{macro}
%
%
%
%  \changes{v1.1m}{2019/09/16}{Correctly revert the \cs{p@...} change}
%    \begin{macrocode}
%</2ekernel|latexrelease>
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\label}{store five label arguments}%
%<latexrelease>\let\@currenttitle\@undefined
%<latexrelease>\let\@currenttarget\@undefined
%<latexrelease>\let\@kernel@currentdata\@undefined
%<latexrelease>\def\label#1{\@bsphack
%<latexrelease>  \protected@write\@auxout{}%
%<latexrelease>         {\string\newlabel{#1}{{\@currentlabel}{\thepage}}}%
%<latexrelease>  \@esphack}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2020/10/01}%
%<latexrelease>                 {\Ref}{Add starred version}%
%<latexrelease>\def\@currentcounter{}
%<latexrelease>\def\refstepcounter#1{\stepcounter{#1}%
%<latexrelease>    \edef\@currentcounter{#1}%
%<latexrelease>    \protected@edef\@currentlabel
%<latexrelease>       {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}%
%<latexrelease>}
%<latexrelease>\def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1}
%<latexrelease>\DeclareRobustCommand\Ref[1]{\protected@edef\@tempa{\ref{#1}}%
%<latexrelease>   \expandafter\MakeUppercase\@tempa}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{2019/10/01}%
%<latexrelease>                 {\refstepcounter}{Add \labelformat and \Ref}%
%<latexrelease>\let\@currentcounter\@undefined
%<latexrelease>\def\refstepcounter#1{\stepcounter{#1}%
%<latexrelease>    \protected@edef\@currentlabel
%<latexrelease>      {\csname p@#1\expandafter\endcsname\csname the#1\endcsname}%
%<latexrelease>}
%<latexrelease>\def\labelformat#1{\expandafter\def\csname p@#1\endcsname##1}
%<latexrelease>\DeclareRobustCommand\Ref[1]{\protected@edef\@tempa{\ref{#1}}%
%<latexrelease>   \expandafter\MakeUppercase\@tempa}
%<latexrelease>\EndIncludeInRelease
%<latexrelease>\IncludeInRelease{0000/00/00}%
%<latexrelease>                 {\refstepcounter}{Add \labelformat and \Ref}%
%<latexrelease>
%<latexrelease>\def\refstepcounter#1{\stepcounter{#1}%
%<latexrelease>    \protected@edef\@currentlabel
%<latexrelease>       {\csname p@#1\endcsname\csname the#1\endcsname}%
%<latexrelease>}
%<latexrelease>\let\labelformat\@undefined
%<latexrelease>\let\Ref\@undefined
%<latexrelease>
%<latexrelease>\EndIncludeInRelease
%<*2ekernel>
%    \end{macrocode}
%
%
%
%
%
%
%
%  \begin{macro}{\@currentlabel}
%    Default for |\label| commands that come before any environment.
%    \begin{macrocode}
\def\@currentlabel{}
%    \end{macrocode}
%  \end{macro}
%
%    \begin{macrocode}
%</2ekernel>
%    \end{macrocode}
%
%
% \Finale
%
back to top