关于 \shipout

关于 \shipout

在阅读有关允许宏到某些事件时,我遇到了这个命令,\shipout。在互联网上搜索并没有太大帮助,但如果我没错的话,它与创建新页面有某种关系(或者是吗?)。

我的问题是,它到底是什么\shipout,它做什么以及它是如何做到的?(即在后台低层发生了什么)

答案1

这很简单:\shipout是一个原语。它的语法是

\shipout ⟨盒子⟩

其中 ⟨box⟩ 在 TeXbook 第 278 页有完整说明:

⟨盒子⟩ → \box⟨8 位数⟩ | \copy⟨8 位数⟩
  | \lastbox| \vsplit⟨8 位数⟩ to⟨dimen⟩
  | ⟨盒子规范⟩ ⟨横模式材质⟩ | ⟨盒子规范⟩ ⟨竖模式材质⟩   | \hbox⟨盒子规范⟩ ⟨竖   模式材质⟩ ⟨盒子规范⟩ → ⟨dimen⟩⟨填充物⟩ | ⟨dimen⟩⟨填充物⟩ | ⟨填充物⟩{}
\vbox{}
\vtop{}
tospread

例如,可以说

\shipout\hbox{Hello world}

并将在 DVI 或 PDF 文件中创建一页。当然没有人想使用\shipout这种方式。它的主要用途是在输出例程中,当 TeX 决定它有足够的材料来弹出整页时调用该例程。当前主垂直列表在所选分页符处被分割,其内容被打包到 中\box255,输出例程可以对其采取行动。例如,Plain TeX 输出例程会

\shipout\vbox{
  \makeheadline
  \pagebody
  \makefootline
}
\advancepageno
\ifnum\outputpenalty>-\@MM
\else
  \dosupereject
\fi

因此,将输出带有页眉和页脚的整页。 的内容\box255由 修改\pagebody。 LaTeX 中的输出程序要复杂得多。

我们可以做的是重新定义,\shipout以便它能完成其他工作。最古老的宏集可以完成这样的工作quire.tex(在 CTAN 和 TeX Live 上仍然可用)

\def\q_init
   {\global\q_sheetnr=0\global\q_qnr=0
    \global\let\q_oldship=\shipout
    \global\let\shipout=\q_boat
    \xdef\q_cycles{\the\deadcycles}%
    \global\let\endquire=\q_endquire
   }

\shipout它保存命令中的 的原始含义\q_oldship(宏用作_“私有”标记)并将其重新定义为\q_boat,这将执行一些工作并最终调用\q_oldship。例如,它可以设置为在同一物理页面上放置两个输出页面,或者制作 16 页查询(包名称由此而来)。

该包也atbegshi做了类似的事情。它重新定义\shipout,以便能够挂接在调用\shipout和实际页面输出之间。

该原语\shipout所做的就是将输入的垂直列表转换为低级打印指令(根据\pdfoutput是否使用pdftex或的值,使用 DVI 或 PDF 格式;如果使用 XDV,则仅使用 Knuth TeX 的 DVI)。同时,它执行所有延迟操作,并在执行过程中扩展标记:这样,对页码的引用就可以保证正确,因为它们是在页面被发送时计算出来的。luatexxetex\write

答案2

电子书,第 23 章:输出例程,第 254 页:

TeX 的原始命令\shipout<box> 才是真正导致输出的命令。它将盒子的内容发送到文件dvi,这是 TeX 的主要输出文件;在 TeX 完成后,dvi文件将包含一个紧凑的设备无关的指令编码,这些指令精确指定了应该打印什么。当一个盒子被运出时,TeX 会在终端上显示 到 的值,如第 15 章所述;这十个计数器也记录在文件中\count0,可以用来识别页面。所有出现在盒子内的、和命令都会按照盒子被运出的自然顺序执行。由于命令会扩展宏,如第 21 章所述,TeX 的扫描机制可能会在正在进行时检测到语法错误。如果在 时非零,则正在运出的盒子的内容将以符号形式写入你的日志文件。你可以在任何地方说,而不仅仅是在输出例程中。\count9dvi\openout\closeout\write\write\shipout\tracingoutput\shipout\shipout

相关内容