旧法典的汇编

旧法典的汇编

考虑以下 MWE:

\documentclass{memoir}

%% Create 123 box registers
\newcount\X
\X=1
\loop
\expandafter\newbox\csname mybox\the\X\endcsname
\advance \X by 1
\ifnum \X<124
\repeat

%% Create a box register and globally store ans empty hbox
\newcommand{\storebox}{%
    \advance \X by 1
    \expandafter\newbox\csname tempbox\the\X\endcsname
    \expandafter\global\expandafter\setbox\csname tempbox\the\X\endcsname\hbox{}
}%

\begin{document}

%% Call \storebox 11 times in a group a total of 5 times
\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

%% Some text so the document isn't empty if it compiles
foo

\end{document}

使用当前的 TeX Live 2015 进行编译pdflatexlualatex产生以下错误消息:

! Incompatible list can't be unboxed.
\sidecontents ... \z@ {\m@mwhich@margin {\m@msidebar@margin }\ifmemtortm \m@sideb@right \else \m@sideb@left \fi \vtop to0pt{\normalsize \normalfont \sidebarfont \vskip \topskip \vskip -\ht \strutbox \vskip \sidebartopsep \unvbox \sideins
                                                                                                                                                                                                                                              \vss }\hss }

上述示例是更大(也更实用)的文档的简化版本,并且极其对变化很敏感。因此,例如,\newbox在前导码中总共调用 122 或 124 次而不是 123 次可以消除错误。

查看日志,盒子寄存器在 195 左右表现异常,如下所示:

\tempbox132=\box192
\tempbox133=\box193
\tempbox134=\box194
\tempbox135=\box256
\tempbox125=\box196
\tempbox126=\box197
\tempbox127=\box198
\tempbox128=\box199
\tempbox129=\box200
\tempbox130=\box201
\tempbox131=\box202
\tempbox132=\box203
\tempbox133=\box204
\tempbox134=\box205
\tempbox135=\box206
! Incompatible list can't be unboxed.
\sidecontents ... \z@ {\m@mwhich@margin {\m@msidebar@margin }\ifmemtortm \m@sideb@right \else \m@sideb@left \fi \vtop to0pt{\normalsize \normalfont \sidebarfont \vskip \topskip \vskip -\ht \strutbox \vskip \sidebartopsep \unvbox \sideins
                                                                                                                                                                                                                                              \vss }\hss }

我第一次注意到这个问题是在最近更新 LaTeX 内核(2015/10/01)之后,加载\usepackage[2015/01/01]{latexrelease}生产文档确实允许原始文档进行编译。但是,上面的 MWE 显示内核更新与此无关,因为添加包latexrelease没有效果。

那么,本例中此错误的根本原因是什么?我如何才能在类似情况下正确防止此错误发生?显然,我们可以通过对文档进行几乎任何更改来轻松消除错误,但这在原始生产文档上实际上并不是一个选项。

答案1

抱歉,这是 latex 的一个错误,在本地组中使用 是一种不好的做法\new...,但如果你这样做,行为不应该那么糟糕,这增加了两个\global,让事情回到正轨。我想我们会推出一个补丁版本。

\documentclass{memoir}

\makeatletter
\gdef\e@ch@ck#1#2#3#4{%
  \ifnum#1<#2\else
    \ifnum#1=#2\relax
      \global#1\@cclvi
      \ifx\count#4\global\advance#1 10 \fi
    \fi
    \ifnum#1<#3\relax
    \else
      \errmessage{No room for a new \string#4}%
    \fi
  \fi}%
\makeatother

%% Create 123 box registers
\newcount\X
\X=1
\loop
\expandafter\newbox\csname mybox\the\X\endcsname
\advance \X by 1
\ifnum \X<124
\repeat

%% Create a box register and globally store ans empty hbox
\newcommand{\storebox}{%
    \advance \X by 1
    \expandafter\newbox\csname tempbox\the\X\endcsname
    \expandafter\global\expandafter\setbox\csname tempbox\the\X\endcsname\hbox{}
}%

\begin{document}

%% Call \storebox 11 times in a group a total of 5 times
\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

\begingroup
    \storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox\storebox
\endgroup

%% Some text so the document isn't empty if it compiles
foo

\end{document}

答案2

这似乎是由于更新回忆录

我认为解决此问题的正确方法可能是使用\locbox代替\newbox,尽管我并不完全确定。如果我加载elocalloc.sty并使用 ,\locbox如下所示:

\documentclass{memoir}
\usepackage{elocalloc}
%% Create 123 box registers
\newcount\X
\X=1
\loop
\expandafter\locbox\csname mybox\the\X\endcsname
\advance \X by 1
\ifnum \X<124
\repeat

%% Create a box register and globally store ans empty hbox
\newcommand{\storebox}{%
    \advance \X by 1
    \expandafter\newbox\csname tempbox\the\X\endcsname
    \expandafter\global\expandafter\setbox\csname tempbox\the\X\endcsname\hbox{}
}%

那么一切都会好起来。这不像什么约瑟夫·赖特的代码,但这个答案给了我这个想法。

希望您在此处序言中放置的代码实际上位于包或类中,可以对其进行更改而无需更改原始文档。

如果没有,如果您不能轻易改变现有文档的序言,以下内容可能会有用。

旧法典的汇编

有两个选择。

选项1

要在不更改代码的情况下编译原始文档,您可以使用存档副本回忆录并将包文件放在 TeX 首先能找到的地方。

我从工作目录创建了到包文件的符号链接,这可能是 GNU/Linux 或 OS X 上最简单的选项。

对于 Windows,您可以自行处理,但我相信它不能正确理解符号链接。在最坏的情况下,您只需将包文件复制到工作目录即可。

您应该有以下文件/链接:

mem10.clo     mem12.clo     mem17.clo     mem25.clo     mem36.clo     mem60.clo     memhfixc.sty  mempatch.sty  
mem11.clo     mem14.clo     mem20.clo     mem30.clo     mem48.clo     mem9.clo      memoir.cls

严格来说,有些可能不是必需的,但除非绝对必要,否则我不会冒险混合不同版本软件包中的文件。(目前,只有文件.cls不同,但更新自然会改变这一点,因此对于给定文档的编译,我会坚持使用全部存档或全部当前版本。)

选项 2

如果您可以在文档中添加一行(在文件中*.tex或命令行中),那么添加

\RequirePackage{etex}

before\documentclass允许代码使用当前 TL 和当前回忆录

解释

这是由于内核的改变造成的。

以供参考:

--- ../../2014/texmf-dist/tex/latex/memoir/memoir.cls   2015-03-06 22:27:23.000000000 +0000
+++ tex/latex/memoir/memoir.cls 2015-07-08 23:33:01.000000000 +0100

相关更改memoir.cls可能是:

@@ -682,7 +682,9 @@
   \fi

 \ifmem@noetex\relax\else
-  \IfFileExists{etex.sty}{\RequirePackage{etex}}{}
+  \ifx\e@alloc\@undefined
+    \IfFileExists{etex.sty}{\RequirePackage{etex}}{}
+  \fi
 \fi
 \providecommand*{\memoirpostopthook}{}
   \memoirpostopthook

这是对 LaTeX 项目团队所做的旨在使其过时的更改的回应etex.sty。理论上,现在不需要这个包了。以前使用的包埃泰克斯如果需要,则需要修改为加载。如果未定义elocalloc.sty,则会加载。但在 TL 2015 中,它已定义,因此不会加载,因为它不是必需的。etex.sty\e@allocetex.sty

我知道这一点是因为这个问题导致我犯了一个错误,我无法创建一个最小示例。无论我注释掉什么都可以解决问题,但取消注释所有内容会导致编译失败。什么都说不通。

你的描述听起来很熟悉——不仅 122 个盒子没问题,124 个盒子也没问题。我知道问题是否会出现取决于何时增加事物是需要的 - 也就是说,需要比 TeX 提供的更多的盒子或其他东西。如果你足够早地需要 124,那可能没问题。如果你只需要 122,那可能没问题。但如果你需要 123,那么在编译过程中其他东西可能需要更多,否则就没问题了。

然而,其他人需要提供详细的细节,因为我对此了解不够多。(事实上,我甚至对上面所说的内容都没有信心,尽管这种解释很肤浅。)

相关内容