这个简单的文档testlatex.tex
\documentclass{article}
\usepackage{tikz}
\begin{document}
\end{document}
运行时latex testlatex
产生No pages of output.
但这份文件testtex.tex
\input tikz
\end
运行时tex testtex
产生Output written on testtex.dvi (1 page, 3312 bytes).
我希望第二个也不会产生任何输出,为什么它们不同?
答案1
简短回答:
\input tikz
加载文件tikz.tex
,而\usepackage{tikz}
加载文件tikz.sty
。那些文件不同,依次加载不同的文件。- 尤其是,
pgfrcs.tex
有\input pgfutil-plain.def
而pgfrcs.sty
有\input pgfutil-latex.def
- 中的代码
pgfutil-plain.def
会\openout
导致创建一个 whatsit 节点(以及“输出”和 DVI 文件),而 中的代码则pgfutil-latex.def
搭载在 LaTeX 的 aux 文件中,从而实现上述目的\immediate\openout
。
如何隔离问题
(本节仅描述如何得出上述结论。)
这是我尝试过的。通过查看日志文件(或使用kpsewhich
),我们可以在两种情况下找到正在输入的特定文件。我们可以将该文件复制到当前目录,然后开始将其编辑为最精简的内容:删除尽可能多的内容,同时文件仍可编译并显示差异。它们可能会输入其他文件;复制它们并重复。
通过递归执行此操作,我能够将两种情况简化为以下情况:
% tex testtex.tex
This is TeX, Version 3.14159265 (TeX Live 2017) (preloaded format=tex)
(./testtex.tex (./tikz.tex (./pgf.tex (./pgfcore.tex (./pgfsys.tex (./pgfrcs.tex (./pgfutil-common.tex) (./pgfutil-plain.def)) (./pgfsys.code.tex))))) [1] )
Output written on testtex.dvi (1 page, 196 bytes).
Transcript written on testtex.log.
其中大多数文件只是\input
其他文件,如上面的日志行所示。非平凡文件(最小化后)是pgfrcs.tex
:
\input pgfutil-common.tex
\input pgfutil-plain.def
pgfutil-common.tex
:
\catcode`\@=11\relax
% Which format is loaded?
\newif\ifpgfutil@format@is@latex
\newif\ifpgfutil@format@is@plain
\let\pgfutil@aux@read@hook=\relax
\newtoks\pgfutil@everybye
pgfutil-plain.def
:
\pgfutil@format@is@plaintrue
% The aux files, needed for reading back coordinates
\def\pgfutil@aux@read@hook{
\csname newwrite\endcsname\pgfutil@auxout
\csname openout\endcsname\pgfutil@auxout\jobname.pgf
}
pgfsys.code.tex
:
% Read aux file in plain and context mode:
\pgfutil@aux@read@hook
概括
文件pgfrcs.tex
有,\input pgfutil-plain.def
而文件pgfrcs.sty
有\input pgfutil-latex.def
,这两个.def
文件存在实质性的差异。
具体来说,在纯 TeX 情况下,我们至少运行以下命令:
\catcode`\@=11\relax
%%%%%%%%%% From pgfutil-plain.def < pgfrcs.tex < pgfsys.tex < pgfcore.tex < pgf.tex < tikz.tex
% The aux files, needed for reading back coordinates
\def\pgfutil@aux@read@hook{
\csname newwrite\endcsname\pgfutil@auxout
\csname openout\endcsname\pgfutil@auxout\jobname.pgf
}
%%%%%%%%%% From pgfsys.code.tex < pgfsys.tex < pgfcore.tex < pgf.tex < tikz.tex
\pgfutil@aux@read@hook
\end
这已经足以导致.dvi
文件的创建。
(@egreg 的回答解释了.dvi
文件的进一步内容 - 与 PGF 相关的特殊内容,这些内容需要进入每一页的 PDF 词典 - 但并没有解释为什么首先要发送一页。为了检查这一点,我们可以简单地从中删除该行\csname openout\endcsname\pgfutil@auxout\jobname.pgf
,pgfutil-plain.def
并且不做任何其他更改,并看到您的原始文件testtex.tex
不会导致创建 DVI 文件,即使@egreg 展示的内容仍然存在pgfutil-plain.def
。)
以上显示我们已经可以发现以下之间的差异:
\input pgfsys
\end
(在纯 TeX 中)和(在 LaTeX 中):
\documentclass{article}
\usepackage{pgfsys}
\begin{document}
\end{document}
此外,这是一个更简单的纯 TeX 文件,可创建 DVI 文件:
\newwrite\outfile
\openout\outfile\jobname.pgf
\end
在 LaTeX 案例中(在 中pgfutil-latex.def
),有一个类似的\AtBeginShipout
和一切,但没有\openout
。相反,它搭载了 LaTeX 的\@auxout
。它是在latex.ltx
( 的定义\document
)中使用定义的\immediate\openout\@mainaux\jobname.aux
。我们可以看到,简单地添加\immediate
到我们之前的最小文件中并不会导致创建 DVI 文件:
\newwrite\outfile
\immediate\openout\outfile\jobname.pgf
\end
答案2
在某个时刻,\pgfutil@abe
被执行,从而发出\unhbox
。
理由如下:
272 \AtBeginShipout{%
273 \setbox\AtBeginShipoutBox=\vbox{%
274 \setbox0=\hbox{%
275 \begingroup
276 % the boxes \pgfutil@abe ("every page") and \pgfutil@abb ("current page")
277 % are used to generate pdf objects / dictionaries which are
278 % required for the graphics which are somewhere in the "real"
279 % page content.
280 % BUT: these pdf objects MUST NOT be affected by text layout
281 % shifts! Consequently, we have to undo \hoffset and \voffset
282 % (which are h/v shifts to the page layout).
283 %
284 % Note that this of importance for shadings. To be more
285 % specific: try out shadings with standalone (which uses
286 % \hoffset) and with xdvipdfmx (which appears to be more
287 % fragile than pdflatex) - they break unless we undo \hoffset
288 % and \voffset.
289 \ifdim\hoffset=0pt \else \hskip-\hoffset\fi
290 \pgfutil@abe
291 \unhbox\pgfutil@abb
292 \pgfutil@abc
293 \global\let\pgfutil@abc\pgfutil@empty
294 \ifdim\hoffset=0pt \else \hskip+\hoffset\fi
295 \endgroup
296 }%