[Tex/LaTex] Test if token is a control sequence

conditionalsmacrostex-core

Sometimes more complex (La)TeX macros test the next input token and branch dependent on its type. I'm aware how to test for catcodes and character codes, but sometimes I like to handle control sequences (macros, primitives, i.e. \ followed by letters (catcode 11) and also the product of \csname ...\endcsname) in a special way.

Is there a suitable test which tells if a token, read as macro argument, is a control sequence? The token must not be expanded beforehand. I like to avoid using \string and looking for a leading \, because this depends on the value of \escapechar which could have been changed locally. Using \meaning and testing for a leading macro doesn't work for primitives like \relax.

So basically I'm looking for a \@ifcontrolsequence{<token>}{<true>}{<false>} macro which will give true for e.g. \relax, \empty, \custommacro and false for any other token. Active characters could be taken as an exception and treated either way. The macro should of course not break on any special tokens.

Best Answer

\makeatletter
\def\@ifismacro#1{%
  \begingroup\escapechar=-1
    \edef\x{\endgroup\def\noexpand\first{\string#1}}\x
  \begingroup\escapechar=`\\
    \edef\x{\endgroup\def\noexpand\second{\string#1}}\x
  \ifnum\pdfstrcmp{\first}{\second}=\z@
    \expandafter\@secondoftwo % no backslash in front
  \else
    \expandafter\@firstoftwo  % backslash in front
  \fi}
\def\report#1{\@ifismacro{#1}{\message{CS}}{\message{NON CS}}}
\makeatother

\report{A}
\report{\"}
\let\pippo=a
\report{\pippo}

The problem with this approach is that is not completely expandable, as it relies on assignments to \escapechar, while being independent of the value it has at the moment the test is performed.

This test distinguishes the last case, which is not possible with \ifcat. Nor with \ifcsmacro of etoolbox, it seems.

Related Question