# How to get the catcode of a token?

For debugging a complicated macro I would like to print out the catcode of a token. Optimally I would like to have a macro \getcatcode such that, for example, \getcatcode{a} would expand to 10. How can this be done?

I found lots of information about how to set/change catcodes, but nothing about how to read them.

-
BTW: the catcode of a is 11 (letter) not 10 (space). – Martin Scharrer Jun 22 '11 at 13:22

Use \catcode together with \the to get the catcode of the token:

\the\catcodea


Note: The  turns the next character into its ASCII number which is required for \catcode.

As custom macro:

\newcommand{\getcatcode}[1]{\the\catcode#1}


Special characters must be escaped with a backslash, e.g. % must be written as \%, # as \# etc. It doesn't hurt to write normal letters the same way, e.g. \getcatcode\a works as well.

-

As explained in an exercise of the TeXbook one can also write

\newcommand{\printcatcode}[1]{%
\ifcase\catcode#1\relax
escape\or
beginning of group\or
end of group\or
math shift\or
tab\or
end of line\or
parameter\or
superscript\or
subscript\or
ignored\or
space\or
letter\or
otherchar\or
active\or
comment\or
ignored\fi}

The category code is \printcatcode\%'


Just to point out that any of the "code tables" in TeX can be used to access the value (\catcode, \lccode, \uccode, \mathcode, \delcode, \sfcode).

-

The solutions offered by Martin and egreg print the current catcode of a character. I understood the original question to be how one can print the catcode of a token, i.e., one that has already been scanned, possibly in the past, when different catcodes were in effect. Consider this:

\catcode\@=11
\newcommand{\x}{@}
\catcode\@=12
\newcommand{\y}{@}

\newcommand{\printcatcode}[1]{
\def\aux##1{
\message{The catcode of the ##1 in \noexpand#1 is \getcatcode{##1}.^^J}
}
\expandafter\aux#1
}

\printcatcode{\x}
\printcatcode{\y}


Clearly the @s stored in the macros \x and \y have two different catcodes. However, with Martin's macro, we get:

The catcode of the @ in \x  is 12.
The catcode of the @ in \y  is 12.


That is because Martin's macro prints the 'current' catcode of the character represented by the token, rather than the catcode actually stored in the token.

The following is a better solution:

\begingroup%
% locally ensure that characters have their expected catcodes
\catcode\$=3% \catcode\&=4% \catcode\#=6% \catcode\^=7% \catcode\_=8% \catcode\ =10% \catcode\a=11% \catcode\+=12% \catcode\~=13% \gdef\getcatcode#1{% \ifcat\noexpand#1$3\else%
\ifcat\noexpand#1&4\else%
\ifcat\noexpand#1##6\else%
\ifcat\noexpand#1^7\else%
\ifcat\noexpand#1_8\else%
\ifcat\noexpand#1 10\else%
\ifcat\noexpand#1a11\else%
\ifcat\noexpand#1+12\else%
\ifcat\noexpand#1\noexpand~13\else%
\ifcat\noexpand#1\relax16\else%
unknown%
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi%
}
\endgroup


With this, we get the expected answer:

The catcode of the @ in \x  is 11.
The catcode of the @ in \y  is 12.


The code is a bit awkward and I wonder if there is a more elegant solution. I was unable to test for catcodes 0, 1, 2, 5, 9, 14, and 15, but I am not sure if such catcodes can actually occur after the input has been tokenized.

-
Category codes 1 and 2 can certainly exist: think \def\x{{a}} which holds three tokens, {, a and }. – Joseph Wright Feb 24 '15 at 14:36