A user of Peter Wilson’s fonttable package reported an interesting bug in the interaction between it and the Spanish module (if not others) of babel.

Here’s the problem in a nutshell:

\documentclass{article}
\usepackage[spanish]{babel}
\begin{document}
$\lim x_n$
{\font\x=cmr10\x hello}
$\lim x_n$
\end{document}

Can you see the problem? It certainly wasn’t immediately obvious to me.

I probably wouldn’t have had time to work through the problem (after all, it’s clearly babel’s problem, not fonttable’s) but the user that reported the problem had also tracked down the root of it already (thanks!). In Spanish, the maths operator \lim is written as ‘lím’, which requires the use (in 8-bit LaTeX) of an acute accent combined with a dotless ‘i’. And inside the definition for \dotlessi in babel’s Spanish module, you’ll find

\expandafter\expandafter\expandafter
\split@name\expandafter\string\the\textfont\mathgroup\@nil

Note the \split@name command, which takes an NFSS font name such as OT1/cmr10/m/n/10 and split it into its components (resp.: encoding, family, series, shape, size). It’s operating on \the\textfont\mathgroup there, and this is where the problem comes from.

By default in a 10pt LaTeX document, \textfont is defined as OT1/cmr10/m/n/10. In pseudocode, LaTeX originally calls something like this:

\font \OT1/cmr10/m/n/10 = cmr10 at 10pt
\textfont\fam=\OT1/cmr10/m/n/10

(This would not execute without ‘/’ having \catcode ‘letter’.) The problem comes in when someone comes along and writes something like

\font\x=cmr10 at 10pt

Because TeX does not want to load the same font more than once, it optimises its references to font names to point to the last name a specific font was requested with (here ‘font’ means ‘font face + size’).

At this point, the \textfont now points to \x instead of \OT1/cmr10/m/n/10, which causes \split@name to break pretty spectacularly. And this even happens if the font loading happens inside a group:

\font\1=cmr10 at 9pt
{\font\2=cmr10 at 9pt}
\textfont\fam=\1
\showthe\textfont\fam

The above code returns ‘\2’, quite unintuitively. So what can be done about this problem? Let’s assume for now that we can’t change how babel does things (I don’t know the practicality of that in any event).

One way to avoid this problem occurring might be to dynamically check the current ‘values’ of \textfont, \scriptfont, etc., and then not reload the same font under a different name if it’s the same as the font you would like to load. This could be implemented in a wrapper around \font like \newcommand is around \def, and this might be something we look into for expl3.

A less general solution is to simply load the new font like this:

\font\x=cmr10 at 9.9999pt

Because the font is technically at a different size (although the difference is imperceptible), TeX considers it a separate font and will no longer replace its old pointer to \OT1/cmr10/m/n/10 with \x. (I also perform this trick in unicode-math to load the same font with different \fontdimens for assigning to different math groups.)

This is certainly less robust than an explicit check, and will not always be an acceptable solution, but it’s simple to implement in fonttable and serves its purpose there quite well.

In conclusion, due to this fragility in babel (I don’t know if it’s the Spanish module only but it seems likely the problem could occur elsewhere), be careful loading certain fonts with \font unless you are confident it won’t also be used as a maths font. If possible, use the LaTeX font loading interface instead.