6

Minimal example consists of two files:

fileA.tex:

\def\foo#1{#1}
\foo{\endinput\input fileB.tex}%

fileB.tex:

This is file B.
\bye

I assumed that compiling fileA.tex would lead to a file fileA.pdf which contains the phrase "This is file B."

I get this but during compilation TeX enters interactive mode.

When I just press return, then fileB.tex is loaded and compilation finishes.

My question is:

Why does TeX enter interactive mode?

I assumed \endinput\input fileB.tex would already be in the token-stream.

So \endinput would cause TeX not to read and tokenize things from fileA.tex any more.

As \input fileB.tex is already in the token-stream, that would be processed next and lead to TeX reading and tokenizing things from fileB.tex.

But why does TeX enter interactive mode before loading fileB.tex ?

Here is the console-output:

$ pdftex fileA.tex
This is pdfTeX, Version 3.14159265-2.6-1.40.19 (TeX Live 2019/dev/Debian) (preloaded format=pdftex)
 restricted \write18 enabled.
entering extended mode
(./fileA.tex)
*
(./fileB.tex [1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] )</usr/shar
e/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb>
Output written on fileA.pdf (1 page, 11997 bytes).
Transcript written on fileA.log.

2 Answers 2

5

Very nice catch. I suppose it will be examined as a potential bug, but the behavior matches the definition of \endinput from page 214 of The TeXbook:

  • \endinput. The expansion is null. The next time TeX gets to the end of an \input line, it will stop reading from the file containing that line.

The \foo{ } wrapper is an unnecessary diversion, has no effect, and so is ignored here. (It might have been intended to delay the effect of \endinput, but \endinput is delayed by design.)

In the case given where the line ends with % TeX is still trying to read characters of the file name when it encounters the end of the line and triggers the pending \endinput. This ends input from filea.tex with the file name for the \input still incomplete, so TeX looks for interactive input. Pressing Enter at the interactive prompt (*) gives a \par token (because an end of line character appeared at the beginning of the input line on the console). That \par terminates/delimits the file name so TeX can proceed with the input of fileb.tex, which it does. The \endinput has already had its effect (the rule said "the next time") so the entire fileb.tex gets input.

Note that the definition says "the file containing that line", not "the file containing \endinput", so a perhaps more interesting case (to me) is without the % on the line with \input. In that case, the file name is terminated before TeX reaches an EOL, so it opens fileb.tex and reads input from it. Then at the end of the first line in fileb the pending \endinput request is triggered, the rest of fileb is discarded, and input returns to whatever is left in filea.tex.

0
4

There are two different issues.

If I remove the trailing %, I get the following from an interactive run of tex:

This is TeX, Version 3.14159265 (TeX Live 2020) (preloaded format=tex)
(./jewdokijaA.tex (./jewdokijaB.tex))
*\bye
[1]
Output written on jewdokijaA.dvi (1 page, 224 bytes).
Transcript written on jewdokijaA.log.

You can notice that the second file is loaded before issuing the * prompt. In order to end the run I have to manually supply \bye at the prompt. Hitting the return key would do nothing except repeating the message

(Please type a command or say `\end')

and issuing the * prompt again.

If I add \relax after \input jewdokijaB.tex, I get the same behavior.

Why do you get

This is TeX, Version 3.14159265 (TeX Live 2020) (preloaded format=tex)
(./jewdokijaA.tex)
*
(./jewdokijaB.tex [1] )
Output written on jewdokijaA.dvi (1 page, 224 bytes).
Transcript written on jewdokijaA.log.

with your code and the run ends after pressing the return key?

In the first two cases (no % or with \relax), the parsing of the file name is complete, but \endinput is still lurking, so the first line of the second file is read in and \endinput does its job.

In your case there's nothing else TeX can do than asking for input from you because \endinput is still lurking and so nothing can be used from further lines in the main file. You can check that

\input jew%
dokija.tex

will regularly input the file, but

\endinput\input jew%
dokija.tex

wouldn't.

However, there's still a problem to solve. Why, with your code, the file is fully read in after hitting return?

I guess that the answer is in modules 361 and 362 of tex.web. I admit that the behavior is puzzling.

5
  • @UlrichDiez Yes, but in the first case only one line of the input file is read, because of \endinput, and, indeed, the \bye in it is not seen.
    – egreg
    Jul 24, 2020 at 8:51
  • @UlrichDiez Possibly so. I've mailed Karl about it.
    – egreg
    Jul 24, 2020 at 10:35
  • 2
    Without the % The file name is complete and the input action begins before any end-of-line is encountered; the first EOL seen is in fileb. With the % TeX is still trying to read the file name when it encounters EOL and triggers the pending \endinput while still in filea, discarding the rest of filea (if there was any), and dropping to interactive mode. Pressing enter gives a space character to terminate the file name, at which point TeX inputs fileb normally. Jul 28, 2020 at 10:17
  • @DonaldArseneau Which is somewhat unexpected, don't you agree?
    – egreg
    Jul 28, 2020 at 10:47
  • 3
    @egreg I might phrase it as "unsurprising, after the initial shock wears off". I think the way \endinput is delayed until the end of line is very unexpected to anyone not thoroughly familiar with TeX. These behaviors add to that, but don't change the story much. I don't think people expect one \endinput to end input from two different files, once they think about it. Jul 28, 2020 at 23:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .