[Tex/LaTex] How does \@currentlabel work? How does it connect to sectioning commands / headings

cross-referencinghyperreflatex-base

My understanding is that \@currentlabel holds a register value. This also applies when hyperref is used.

I was having a look at kpsewhich ltxref.dtx when I read that \@currentlabel handles situations when \label is put outside of an environment (this happens when you tack them onto headings e.g. \section{blah}\label{blah}).

Its definition is

\def\@currentlabel{}

This looks to me like effectively initializing a macro. I proceeded to review the document, source2e, but I still do not understand \@currentlabel.

To get a proper \@currentlabel we have to redefine it for the whole display. Note that we can't use \refstepcounter as this results in \@currentlabel getting
restored at the wrong and thus always writing the first label to the .aux file.

What is meant by whole display?

If I create my own sectioning/heading command, is it then a requirement to include \refstepcounter{CNT} if I want to be able to tack on \label{} to it?

Does titlesec automatically add \refstepcounter{CNT} to new sectioning commands?

In the sectioning/heading definitions, there is \refstepcounter{CNT}. This is the only connection I found to \@currentlabel.

A referencable 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)}}

\def\refstepcounter#1{\stepcounter{#1}%
    \protected@edef\@currentlabel
       {\csname p@#1\endcsname\csname the#1\endcsname}%
}

It seems like magic how \subsection{subsec1}\label{subsec1} results in \@currentlabel equal to 1.1:

\newlabel{subsec1}{{1.1}{1}{subsec1}{subsection.1.1}{}}

Example

\documentclass{article}
\usepackage{hyperref}
\begin{document}
\section{sec1}
\label{sec1}
\subsection{subsec1}
\label{subsec1}
\subsubsection{subsubsec1}
\label{subsubsec1}
\paragraph{par1}
\label{par1}
\section{sec2}
\end{document}

Relevant .aux lines

\newlabel{sec1}{{1}{1}{}{section.1}{}}
\newlabel{subsec1}{{1.1}{1}{subsec1}{subsection.1.1}{}}
\newlabel{subsubsec1}{{1.1.1}{1}{subsubsec1}{subsubsection.1.1.1}{}}
\newlabel{par1}{{1.1.1.1}{1}{par1}{paragraph.1.1.1.1}{}}

Related

Best Answer

The macro is initialized to expand to nothing, but every \refstepcounter command redefines it. If you have \newcounter{foo}, then part of the job of \refstepcounter{foo} is, after having stepped the counter, to do

\edef\@currentlabel{\p@foo\thefoo}

The job of \label{baz} is to issue a command that eventually writes

\newlabel{baz}{{\@currentlabel}{\thepage}}

but the two macros \@currentlabel and \thepage will be expanded. The former is expanded immediately, the latter only at shipout time, when the \write command to the .aux file actually happens.

Note that \refstepcounter only does \edef and not \xdef, so if \refstepcounter happens inside a group (an environment, for instance), the value of \@currentlabel will not survive the end of the group.

Your quotation about a display refers to some workarounds that need to be made in eqnarray; this is not really important, because eqnarray should never be used. The amsmath package uses different tricks for \label inside its alignment environments.

By the way, what's \p@foo? For standard counters it is empty, but it can be redefined for a particular counter in order to provide a prefix. This is the case for enumii, enumiii and enumiv, for instance, used in enumerate.

Just to make an example. Let's see a summary of what happens with

\subsection{subsec1}\label{subsec1}

The command \subsection does, before processing the sectional title, \refstepcounter{subsection}. As said before, this redefines \@currentlabel using

\edef\@currentlabel{\p@subsection\thesubsection}

Since the definition is expanded, the current value of \p@subsection and \thesubsection are stored; the former is empty, the latter, in your code, expands to \thesection.\arabic{subsection} and, eventually to 1.1.

Later \label{subsec1} essentially does

\protected@write\@auxout{}{\string\newlabel{subsec1}{{\@currentlabel}{\thepage}}}

which will (approximately) translate to

\write\@auxout{\string\newlabel{subsec1}{{1.1}{\thepage}}}

as expansion of \thepage is neutralized during \protected@write. The \write operation is recorded in the main vertical list and will be executed at shipout time; only at this moment \thepage will be expanded.

It's immaterial whether you use the alternate method

\subsection{subsec1\label{subsec1}}

because \label will only be processed when the title is typeset. The macro \label just gobbles its argument during a \protected@write, so this won't show when the argument is moved around. But this is another topic.