# Error related to \spacefactor using 3rd-party macro \addmoretexcs

I am using the command \addmoretexcs for listings, which has its origin here. With the update to TeX Live 2014 (and probably an update to listings), the following code returns an error:

\documentclass{minimal}
\usepackage{ltxcmds}
\usepackage{listings}

\makeatletter
\makeatother

\makeatletter
\lowercase{\@ifundefined{lstlang@tex$#1}}{% \lstloadlanguages{[#1]TeX}% }{}% \lowercase{\expandafter\g@addto@macro\csname lstlang@tex$#1\endcsname}{%
\lstset{moretexcs={#2}}%
}%
}
\makeatother

\begin{document}
\end{document}


The error in question is

! You can't use \spacefactor' in vertical mode.
\@->\spacefactor
\@m


Note that, if I substitute \IfPackageLoaded with ltx@ifpackageloaded, the error disappears. This, however, is not a solution.

The actual error is likely inside the packages; I cannot debug this any further. Any hints about the origin of this error?

I doubt the code worked before updating to TeX Live 2014, because it would have been wrong in any case. With

\IfPackageLoaded{listings}{%

\makeatletter
\lowercase{\@ifundefined{lstlang@tex$#1}}{% \lstloadlanguages{[#1]TeX}% }{}% \lowercase{\expandafter\g@addto@macro\csname lstlang@tex$#1\endcsname}{%
\lstset{moretexcs={#2}}%
}%
}
\makeatother



the replacement text of \addmoretexcs (actually of an inner macro due to the fact your command has an optional argument) consists of the following tokens (• is used to separate tokens, for clarity)

\lowercase • { • \@ • i • f • u • ...


because the text given as argument to \IfPackageLoaded is already tokenized and TeX doesn't execute \makeatletter when absorbing this argument.

Correct code:

\makeatletter
\lowercase{\@ifundefined{lstlang@tex$#1}}{% \lstloadlanguages{[#1]TeX}% }{}% \lowercase{\expandafter\g@addto@macro\csname lstlang@tex$#1\endcsname}{%
\lstset{moretexcs={#2}}%
}%
}%
\makeatother


Now, when the argument is absorbed, \@ifundefined is tokenized as a single token, not twelve.

## Some more words

The original code may appear to work if it is included in a .sty file, because these files are read in with an implicit \makeatletter declaration at the beginning and an implicit \makeatother at the end (more precisely, the category code of @ is restored to the value it had at the moment the .sty file was opened).

As a general rule, \makeatletter and \makeatother should never appear in .sty files (except when belonging to the replacement text of some macro, which is not the case here). Your usage of \makeatother in the second argument of \IfPackageLoaded would be wrong in a .sty file, because it would change the category code of @ from that point on in case listings has already been loaded.

So, if you are going to use the previous code in a .sty file, remove the \makeatletter and \makeatother declarations.

• Indeed, this solved it. However I can confirm that it worked before and also worked for about 3000 other people that downloaded my template. – Matthias Pospiech Jun 26 '14 at 6:14
• @MatthiasPospiech Probably none of them loaded listings. Of course, I tried your example with TL 2012 and TL 2013, obviously receiving the same You can't use \spacefactor' in vertical mode error in both cases. – egreg Jun 26 '14 at 6:51
• My template loads about 100 packages, and listings is always loaded. Even if someone would disable it in the preamble, a package from myself loads it, so it would be loaded in any case. The code is not in a sty file. I must admit, that I did not test the MWE in TeX Live 2013, but the error first appeared in my template in 2014 and does not (in my full template) in 2013. – Matthias Pospiech Jun 26 '14 at 12:17
• Yes! Thank you for pointing-out the \makeatletter and \makeatother problems with .sty files. – user59034 Jun 17 '15 at 16:52