7

This morning after an update to LaTeX 2020-10-01 PL3 my test suite failed with a mysterious error.

The error could be traced back to a not-so-minimal WE of the following form

\documentclass{scrartcl}
\usepackage[listings]{tcolorbox}
\lstset{escapeinside = {(*@}{@*)},}
\newtcblisting{mylisting}{listing only}
 
\begin{document}
\begin{mylisting}
(*@1@*)
\end{mylisting}

\begin{mylisting}
(*@2@*)
\end{mylisting}

\begin{mylisting}
(*@3@*)
\end{mylisting}
 
\begin{mylisting}
(*@4@*)
\end{mylisting}
 
\begin{mylisting}
(*@5@*)
\end{mylisting}
 
\begin{mylisting}
(*@6@*)
\end{mylisting}

\begin{mylisting}
(*@7@*)
\end{mylisting}
\end{document}

which fails with

Package scrlfile-hook Warning: More file names popped from stack than put to.
(scrlfile-hook)                This should never happen. However, it could
(scrlfile-hook)                happen if scrlfile-hook is loaded by another
(scrlfile-hook)                package or class. In this case some packages or
(scrlfile-hook)                classes are not recognised correctly.
 
(./scrlfile-escaped-listings-tcolorbox.listing)
\openout4 = `scrlfile-escaped-listings-tcolorbox.listing'.
 
 
(./scrlfile-escaped-listings-tcolorbox.listing)
 
! LaTeX3 Error: Message 'to-much-pops' for module 'scrlfile-hook' already
(LaTeX3)        defined.
 
For immediate help type H <return>.
 ...                                              
 
l.39 \end{mylisting}
 
? 
 
Package scrlfile-hook Warning: More file names popped from stack than put to.
(scrlfile-hook)                This should never happen. However, it could
(scrlfile-hook)                happen if scrlfile-hook is loaded by another
(scrlfile-hook)                package or class. In this case some packages or
(scrlfile-hook)                classes are not recognised correctly.

At first I thought this was a KOMA-Script problem, so I asked about the issue at https://komascript.de/node/2362, but it turns out that even though the problem really only became apparent due to a slight oversight in KOMA-Script (which has already been fixed); the core of the problem goes deeper.

The following MWE shows that the file/after hook code may end up being executed several times in certain circumstances. Since KOMA-Script's filehook module uses file/after to pop a stack of file names, the hook may end up popping several files at once causing the warning and ultimately the error from above.

\documentclass{article}

\usepackage{listings}
\lstset{escapeinside = {(*@}{@*)},}

\usepackage{etoolbox}
\AddToHook{file/before}{\AfterPreamble{A [\CurrentFile]}}
\AddToHook{file/after}{\AfterPreamble{Z}}

\begin{filecontents*}{\jobname-normal.tex}
Lorem
\end{filecontents*}
\begin{filecontents*}{\jobname-escaped.tex}
(*@ipsum@*)
\end{filecontents*}

\begin{document}
\lstinputlisting{\jobname-normal.tex}

\lstinputlisting{\jobname-escaped.tex}

\lstinputlisting{\jobname-normal.tex}

\lstinputlisting{\jobname-escaped.tex}
\end{document}

The code runs without errors, but in the output we can see that the file/after code is executed twice for the listings containing an escapeinside sequence.

LoremZ//ipsumZZ

Unfortunately, the circumstances in which the hook is run twice seem to be rather hard to pin down.

Relevant package versions are

LaTeX2e <2020-10-01> patch level 3
L3 programming layer <2020-12-07> xparse <2020-03-03>
listings 2020/03/24 1.8d

all examples work fine on my MikTeX system, which runs LaTeX 2020-10-01 PL2.

Why does the file hook get executed twice here and how can I stop it from doing that?

8
  • 1
    well tcolorbox is out, I can reproduce it with \lstinputlisting alone. – Ulrike Fischer Jan 1 at 22:04
  • @UlrikeFischer Nevermind, got it. Thanks for the hint. I will edit the question shortly. – moewe Jan 1 at 22:11
  • 1
    I have a simpler example: chat.stackexchange.com/transcript/message/56612339#56612339 – Ulrike Fischer Jan 1 at 23:31
  • 2
    @moewe Thanks for finding this. It is indeed a bug introduced in the new version when \CurrentFile is cleared within the file. That should rarely happen, but it's not impossible, as Ulrike's example shows. This patch should fix the problem: pastebin.com/raw/bvp9Wf80 – Phelype Oleinik Jan 2 at 3:12
  • 1
    @PhelypeOleinik Yes, that patch seems to resolve the issue both in my large document as well as the small test cases I came up with while isolating the problem. Thank you very much for the thorough investigation and the quick fix. – moewe Jan 2 at 6:35
7

When inputting a file with \InputIfFileExists (basically what is used everywhere across LaTeX, except for a few special cases like the plain syntax \input <file>), it sets the \CurrentFile, uses the hooks file/before and file/before/\CurrentFile, then reads the file in, then uses file/after/\CurrentFile and file/after.

The problem with that, is that if while reading the file the macro \CurrentFile was changed, for whatever reason, the file/after/\CurrentFile hook executed would be wrong. In your case, as Ulrike found out, it was that a group started outside the file, and ended inside it, so local assignments were lost, and \CurrentFile was reset to empty, so the hook used was file/after/. On top of that, a bad design of a sanitisation macro dropped the final /, so the hook used was file/after, and then file/after again.

This was taken into account in previous versions (\CurrentFile was consistently restored after \@@input was finished), but a bug introduced with this commit (part of PL3) delayed restoring \CurrentFile to after the hooks were executed, which is kind of pointless.

I fixed this issue in this pull request, part of PL4. If you are reading this and experiencing this issue, update your LaTeX.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.