为什么当还有标记需要处理时,`\endinput` 会让 TeX 进入交互模式?

为什么当还有标记需要处理时,`\endinput` 会让 TeX 进入交互模式?

最小示例包含两个文件:

fileA.tex

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

fileB.tex

This is file B.
\bye

我假设编译fileA.tex会产生一个fileA.pdf包含短语“这是文件 B”的文件。

我明白这一点,但在编译过程中 TeX 进入交互模式。

当我按下回车键时,fileB.tex就会加载并完成编译。

我的问题是:

TeX 为什么进入交互模式?

我认为\endinput\input fileB.tex它已经存在于标记流中了。

\endinput会导致 TeX 不再读取和标记fileA.tex任何内容。

由于\input fileB.tex已经在标记流中,因此接下来会对其进行处理,并导致 TeX 从中读取和标记内容fileB.tex

但是为什么 TeX 在加载之前进入交互模式fileB.tex

这是控制台输出:

$ 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.

答案1

非常好的发现。我想它会被视为一个潜在的错误,但其行为符合\endinputTeXbook 第 214 页的定义:

  • \结束输入。扩展为空。下次 TeX 到达 \input 行的末尾时,它将停止从包含该行的文件读取。

包装\foo{ }器是一种不必要的转移,没有任何作用,因此在这里被忽略。(它可能本来是为了延迟的效果\endinput,但却\endinput被设计延迟了。)

在给定行以 结尾的情况下,%TeX 仍然尝试读取文件名的字符,当它遇到行尾并触发待处理的 时\endinput。这将结束来自 filea.tex 的输入,而文件名\input仍不完整,因此 TeX 会寻找交互式输入。Enter在交互式提示符 ( *) 下按下 会给出一个\par标记(因为行尾字符出现在控制台上输入行的开头)。这\par会终止/分隔文件名,因此 TeX 可以继续输入 fileb.tex,它确实这样做了。\endinput已经产生了效果(规则说“下一个时间”),这样整个文件 b.tex 都会得到输入。

请注意,定义中说的是“包含该行的文件”,而不是“包含 \endinput 的文件”,因此(对我来说)可能更有趣的情况是%行中没有\input。在这种情况下,文件名在 TeX 到达 EOL 之前终止,因此它会打开 fileb.tex 并从中读取输入。然后在 fileb 中第一行的末尾\endinput触发待处理的请求,fileb 的其余部分被丢弃,输入返回到 filea.tex 中剩余的内容。

答案2

有两个不同的问题。

如果我删除尾随的%,我可以通过交互式运行获得以下内容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.

您可以注意到,第二个文件在发出*提示之前已加载。为了结束运行,我必须\bye在提示符下手动提供。按下回车键除了重复消息外什么也不做

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

*并再次发出提示。

如果我\relax之后添加\input jewdokijaB.tex,我会得到相同的行为。

为什么你会得到

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.

使用您的代码并按下回车键后运行结束?

在前两种情况下(无%或有\relax),文件名的解析已经完成,但\endinput仍处于潜伏状态,因此第二个文件的第一行被读入并\endinput执行其工作。

在你的情况下,TeX 除了向你请求输入之外什么也做不了,因为\endinput仍然潜伏着,所以主文件中的后续行无法使用。你可以检查

\input jew%
dokija.tex

将定期输入文件,但

\endinput\input jew%
dokija.tex

不会。

但是,还有一个问题需要解决。为什么使用你的代码,文件充分回车后读入?

我猜答案在 的模块 361 和 362 中tex.web。我承认这种行为令人费解。

相关内容