# testing parameter values with \ifx

Let's say that I would like to redefine \@seccntformat so that whenever the section counter is printed, it is prefixed by Section, but other counters should no be changed.

Here is my failed attempt:

\documentclass{article}

\makeatletter
\def\mytest{section}%
\def\myarg#1{#1}
\def\@seccntformat#1{%
\ifx\myarg#1\mytest{Section}\fi%
\makeatother

\begin{document}
\section{Foo}  % Should be printed as "Section 1  Foo"
\subsection{Bar}  % Should be printed as "1.1  Bar"
\end{document}


For some reason I can't manage to get \myarg#1 and \mytest to compare equal when #1 is section. Now this is my first time using \ifx, so I hope I'm missing something trivial.

I would appreciate some hints about how to debug such a macro. Is there a way to see each intermediate expansion step and observe what arguments \ifx is actually receiving?

The conditional \ifx does no expansion and it compares the next two tokens. So in your test it compares \myarg with the first token in #1.

Therefore the test will be always false, because #1 is the name of a section level counter.

Adding \expandafter before \ifx would not help, even adding braces around #1:

\expandafter\ifx\myarg{#1}\mytest


would become

\ifx section\mytest


which returns false, as it compares s with e.

You could use \pdfstrcmp (or, better, \pdf@strcmp with the pdftexcmds package):

\def\@seccntformat#1{%
\ifnum\pdf@strcmp{#1}{section}=\z@
Section % a space is wanted
\fi


Complete example:

\documentclass{article}
\usepackage{pdftexcmds}

\makeatletter
\def\@seccntformat#1{%
\ifnum\pdf@strcmp{#1}{section}=\z@
Section %
\fi
\makeatother

\begin{document}
\section{Foo}  % Should be printed as "Section 1  Foo"
\subsection{Bar}  % Should be printed as "1.1  Bar"
\end{document}


Note that the attempt of doing the comparison with \ifx in the following way

\def\section@argument{section}
\def\@seccntformat#1{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi


wouldn't work either. This is because \@seccntformat is passed through an \edef (in the form \protected@edef), so we'd get an error

Undefined control sequence


for \@argument. Adding \noexpand in front of \@argument wouldn't help, because the conditional is expanded during the \edef. This instead would work

\def\section@argument{section}
\def\@seccntformat#1{%
\unexpanded{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi
}
}


because the argument to \unexpanded is not changed during an \edef, so it will be processed afterwards, when typesetting is involved.

Note that the \protected@edef is necessary because we must get the expansion of \thesection or \thesubsection at the moment the macro \@seccntformat is executed. An \unexpanded free solution is possible, by hiding the part in a macro:

\def\section@argument{section}
\def\check@section#1{%
\def\@argument{#1}%
\ifx\@argument\section@argument
Section %
\fi
}
\def\@seccntformat#1{%
\noexpand\check@section{#1}%

• Using inner \defs was actually my first try, and I had to move them out of the macro because of the Undefined control sequence error which I did not understand. Thank you for explaining that as well!