Expansion of \char in \def
This can be done via the \lowercase
trick:
\documentclass{minimal}
\usepackage{etoolbox}
\usepackage{xstring}
\makeatletter
\begingroup
\catcode0=12 %
\gdef\chrdef#1#2{%
\begingroup
\lccode0=\numexpr(#2)\relax
\lowercase{\endgroup
\def#1{^^@}%
}%
}%
\endgroup
\def\title@A{a A}
\def\title@B{b B}
\def\gettitle#1{
\IfInteger{#1}{%
\chrdef\@tmp{#1}%
\ifcsundef{title@\@tmp}{\@tmp}{\csname title@\@tmp\endcsname}%
}{%
\ifcsundef{title@#1}{#1}{\csname title@#1\endcsname}%
}
}
\begin{document}
\gettitle{65} \gettitle{A}
\gettitle{66} \gettitle{B}
\gettitle{67} \gettitle{C}
\end{document}
\lowercase
(a not expandable command) converts the argument character token to its lower case character. This is configured by \lccode
. The only exception is zero. If the \lccode
is zero for a character, then the character remains unchanged. Therefore the example uses the character with code zero, which can be expressed as ^^@
in TeX notation. However, this character has usually the category code of invalid, there it is changed to 12 (other) in the outside group. Since the changes to \lccode
should be reverted afterwards, the macro also uses a group.
The \char
primitive isn't expandable. In XeTeX and LuaTeX we have \Uchar
, which is and so can generate any character. For pdfTeX, with only 256 possible outcomes, we can set up a look-up table. Something like
\catcode`\@=11 %
\ifdefined\Uchar
\def\Xchar#1{%
\detokenize\expandafter{\Uchar\numexpr #1\relax}%
}
\else
\catcode`\^^@=12 %
\begingroup
\gdef\Xchar#1{%
\romannumeral-`\0\expandafter\Xchar@aux\expandafter{\numexpr #1\relax}%
}
\gdef\Xchar@aux#1{%
\ifcsname Xchar@\romannumeral #1\endcsname
\csname Xchar@\romannumeral #1\endcsname
\else
\errmessage{Character out of range}%
\fi
}
\count@=-1 %
\lccode`\X=`\X %
\loop
\advance\count@ by 1 %
\ifnum\count@<256 %
\lccode`\^^@ = \count@ %
\lowercase{%
\expandafter\gdef\csname Xchar@\romannumeral\count@\endcsname{^^@}%
}
\repeat
\endgroup
\fi
\catcode`\@=12 %
provide \Xchar
to do the job. A more sophisticated version of the same idea can be used to provide different category code characters, and is implemented as \char_generate:nn
in expl3
. (The above is expandable at point-of-use as the lookup table is generated in advance.)