背景

背景

今年早些时候(2021 年 1 月/2 月),Donald Knuth 发布了 TeX 的新版本,现在的版本号为 3.141592653。与七年前(2014 年 1 月)发布的上一个版本 3.14159265 相比,有什么变化?

对于那些不知道的人来说,Knuth 写道在他的网站上那:

我仍然对 TeX、METAFONT 和 Computer Modern 的主源负全部责任。因此,我会定期从当前项目中抽出几天时间,查看所有累积的错误报告。最近一次是在 1992 年、1993 年、1995 年、1998 年、2002 年、2007 年、2013 年和2020;按照这种模式,我打算在 2028 年、2037 年、2047 年等年底再次检查所谓的错误。此类维护期之间的间隔正在增加,因为系统已经趋于无错误状态。

因此,

今年是我承诺进行为期七年的 TeX 和 METAFONT 清理的一年(上次更新于 2014 年初)。我花了三个星期的时间处理了数百个不同类型的问题,发现了五个真正的错误(!)。但我很高兴地报告,新调整的系统不会“破坏”任何以前可以正常工作的东西,而且错误不太可能出现。因此,每个人都可以根据自己的方便选择是否升级。

那么“五个实际错误”是什么?在什么(罕见)情况下它们很重要?


(关于这个问题本身的一些注释:

  • 在之前的两次更新中,Knuth 发布了以下更新的摘要:拖船,即2014 年 TeX 调整2008 年的 TeX 调整。我预计会有一篇类似的文章“2021 年的 TeX 调整”,但上次,问题和答案在那篇文章发表之前就已经在这个网站上发布了……)

答案1

Knuth 为 2021 年的调整所做的总更改如下:巨大的(这次有几个人仔细审查了他的工作)。从更正旧勘误表中的拼写错误到重新措辞中的复制条件,tex.web甚至对纯文本格式本身进行了一些更改,都有一些小改动。以下是添加到的条目以及对每个条目的errorlog.tex简短1 个解释。(Knuth 提到的“五个错误”是I948、、、 和。还有另外两个没有添加到;它们位于本答案的底部。)此摘要的较短版本现在也可以在S949S950B952R953errorlog.texTUG 网站

* 15 January 2021
I948. Don't pause on errors when tracing paragraphs (Udo Wermuth). @826
S949. Don't try to interact when in |\batchmode| (Xiaosa Zhang). @83
S950. Don't try to edit when no file is active (Xiaosa Zhang). @84
R951. Take date and time sometimes from system, not user (Udo Wermuth). @241,536
B952. Don't allow implicit left brace after |#| (Udo Wermuth). @476
R953. After nine parameters, must delete offending tokens (Bruno Le Floch). @476
D954. Garbage visible in buffer after file ends prematurely (DRF). @486
R955. Force nonexistent characters to have null specs (DRF). @722
C956. Don't mark fraction noads as temporarily Inner (DRF). @761
Q957. Reset |\newlinechar| before logging the stats (Udo Wermuth). @1333,1335

[1]:我在写解释之前先在简介中写了“小解释”,所以我没有撒谎……严格来说:)


I948. 描摹段落时不要在出现错误时暂停 (Udo Wermuth)。@826

此错误会导致 TeX 在\tracingparagraphs 开启(> 0)时明显挂起,Infinite glue shrinkage错误发生在打印段落跟踪信息时。 当\tracingparagraphs开启时,TeX 正在写入 log_only(除非\tracingonline=1),如果出现该错误,它会提示用户进行交互,但由于写入选择器将输出重定向到.log,用户看不到这一点,TeX 显然会卡住。

例如,如果您在包含以下行的文件上运行:

\tracingparagraphs=1 Press\hss return.\end

终端将显示

This is TeX, Version 3.14159265 (TeX Live 2020) (preloaded format=tex)
 restricted \write18 enabled.
entering extended mode
(./test.tex

然后挂起,等待用户交互(例如,键入x 然后<RETURN>结束运行,或者只是<RETURN>忽略有问题的\hss)。如果您运行,这将不起作用

$ tex '\tracingparagraphs=1 Press\hss return.\end'

因为在那种情况下还没有.log打开,所以输出将到终端。

调整后,TeX 会像处理其他错误一样处理此错误:如果\errorstopmode错误中要求用户进行交互,否则它将滚动过去:

This is TeX, Version 3.141592653 (TeX Live 2021/dev) (preloaded format=tex)
(./test.tex
! Infinite glue shrinkage found in a paragraph.
<inserted text> \par 
                     
<to be read again> 
                   \end 
l.1 \tracingparagraphs=1 Press\hss return.\end
                                              
? 

相关变更条目为:

429. Don't echo error message to terminal when tracing paragraphs
(Udo Wermuth, 15 January 2017)
@x module 826
  begin no_shrink_error_yet:=false;
@y
  begin no_shrink_error_yet:=false;
  @!stat if tracing_paragraphs>0 then end_diagnostic(true);@+tats@;
@z
@x
  error;
@y
  error;
  @!stat if tracing_paragraphs>0 then begin_diagnostic;@+tats@;
@z

S949. 在 |\batchmode| 下不要尝试交互 (Xiaosa Zhang)。@83

这个错误最初 报告于此处?,导致 TeX在 中 请求用户交互(TeX 的提示) \batchmode,从而尝试写入封闭的流,这会导致分段错误。从 Karl 对原始报告的回答中,您可以在 2020 年之前通过运行然后输入以下行并在结尾处 \write重现该错误:tex -ini<RETURN>

\catcode`\^=7 \catcode`\^^?=15 \s^^?E
1
q
v

使用新版 TeX,输入qEnter后\batchmode,如果无法进行交互,TeX 将不会尝试请求用户交互,因此不会再出现问题。

相关变更条目为:

430. Defeat interactions during batch mode (Xiaosa Zhang, 27 June 2020)
@x module 83
@ @<Get user's advice...@>=
loop@+begin continue: clear_for_error_prompt; prompt_input("? ");
@y
@ @<Get user's advice...@>=
loop@+begin continue: if interaction<>error_stop_mode then return;
  clear_for_error_prompt; prompt_input("? ");
@z

S950. 当没有文件处于活动状态时,不要尝试编辑(张小萨)。@84

这个错误最初 报告于此处当您尝试打开编辑器(使用 TeX 的E选项)时,如果在交互输入中发生错误,则会触发此错误。假设您有一个文件,h.tex其中只有一行(假设该行\ERROR 未定义,或者是任何会导致错误的内容):

% h.tex
\ERROR

然后,当 TeX 抱怨! Undefined control sequence \ERROR你时,回复:

I\MISTAKE V

这将插入\MISTAKE VTeX 进行处理,并且它将再次抱怨,由于未定义\MISTAKE,现在你回复:

E

TeX 将会发生段错误。

以下是互动环节的记录:

$ tex h
This is TeX, Version 3.14159265 (TeX Live 2020) (preloaded format=tex)
(./h.tex
! Undefined control sequence.
l.1 \ERROR
          
? I\MISTAKE V
! Undefined control sequence.
<insert>   \MISTAKE
                    V
l.1 \ERROR
          
? E
No pages of output.
Transcript written on h.log.
Segmentation fault (core dumped)

发生此错误是因为 TeX 会尝试告诉您发生错误的输入文件的名称,但由于错误发生在交互式输入命令上,因此没有关联文件。在调整后,TeX 知道在这种情况下它不是从文件中读取,因此它不会尝试给您文件名。

相关变更条目为:

431. Don't exit to editor if no input file is at the bottom line
(Xiaosa Zhang, 03 July 2020)
@x module 84
"E": if base_ptr>0 then
@y
"E": if base_ptr>0 then if input_stack[base_ptr].name_field>=256 then
@z
@x module 85
if base_ptr>0 then print("E to edit your file,");
@y
if base_ptr>0 then if input_stack[base_ptr].name_field>=256 then
  print("E to edit your file,");
@z

R951. 有时从系统而不是用户获取日期和时间 (Udo Wermuth)。@241,536

在设置之前\jobname(更准确地说是在启动文件之前 ),您可以更改、和.log的值,这些值将写入 的标题行中。如果您这样做\year\month\day\time.log

$ tex '\day=99 \end'

第一行.log会说类似

This is TeX, Version 3.14159265 (TeX Live 2020) (INITEX)  99 FEB 2021 22:18

(注意是 2 月 99:) 或者,如果你感觉真的 狡猾的,你可以通过设置一个虚假的值来打印 TeX 可执行文件中的任意三个字节\month,例如(使用我这里的构建)

$ tex -ini "\month=-54 \end"

获取名为 TeX 的月份:

This is TeX, Version 3.14159265 (TeX Live 2020) (INITEX)  2 TeX 2021 22:20

或者使用足够极端的值可能会导致 TeX 因分段错误而崩溃,例如:

$ tex '\month=-100000 \end'

在新版本中,标题中打印的值是内部值 sys_(time|day|month|year),不能通过更改原始寄存器来更改。

这是一个相当长(行数)的更改,并不像阅读这里的材料那么有趣(基本上是声明新变量 sys_<thing>,初始化这些原语,然后使用sys_<thing> 而不是<thing>打印横幅),所以我将省略更改条目,但你可以通过搜索其标题来找到

432. Keep date and time in system variables, use them in opening banner
(Udo Wermuth, 11 December 2020)

tex82.bug


B952. 不允许在 |#| 后使用隐式左括号 (Udo Wermuth)。@476

这个错误(我很惊讶之前没有发现它)允许你在<parameter text>定义的最后一个标记是 #6时使用隐式开始组字符(如 \bgroup)代替标记定义结束的明确开始组字符<parameter text>,例如

\def\foo#1#\bgroup(#1)}
\show\foo

是有效的,并且会显示

> \foo=macro:
#1\bgroup ->(#1)\bgroup .

在终端上,这意味着#1的参数\foo由 分隔\bgroup,并且\bgroup将在宏的 之后重新插入 <replacement text>,就像 TeX 处理 明确的begin-group 字符。调整后,您将收到来自上述定义的错误:

! Parameters must be numbered consecutively.
<to be read again> 
                   \bgroup 
l.1 \def\foo#1#\bgroup
                      (#1)}
?

以及由于定义格式错误而导致的进一步错误(使用上面的输入定义的宏在出现一些错误之后将会出现\foo=macro:#1#2\bgroup (#31)->.)。

相关变更条目为:

434. Don't accept an implicit left brace after # in macro head
(Udo Wermuth, 20 May 2020)
@x module 476
if cur_cmd=left_brace then
@y
if cur_tok<left_brace_limit then
@z

R953. 九个参数之后,必须删除有问题的标记 (Bruno Le Floch)。@476

有了这个 bug,TeX 可能会做出一些非常有趣的事情。扫描<parameter text>宏的 时,在九个允许的参数之后,任何参数#都会引发错误,但后面的标记 #会留在 中<parameter text>。假设你有一个包含 9 个参数的宏,并试图添加第十个参数#0

\def\foo#1#2#3#4#5#6#7#8#9#0{}
\show\foo

TeX 会向你抱怨

! You already have nine parameters.
l.1 \def\foo#1#2#3#4#5#6#7#8#9#0
                                {}
? h
I'm going to ignore the # sign you just used.

? 

并且宏定义将#忽略,但是0将保留在那里:

> \foo=macro:
#1#2#3#4#5#6#7#8#90->.
l.2 \show\foo
             
? 

到目前为止,没有什么令人兴奋的事情。但现在假设有一天你感觉特别淘气,并且被用作###0比如 \def\foo#1#2#3#4#5#6#7#8#9##{},那么你\show\foo会说

> \foo=macro:
#1#2#3#4#5#6#7#8#9##->.
l.2 \show\foo
             
? 

你看那个!#9现在由参数标记分隔,因此如果你调用\foo 12345678hello##9将是hello

更糟糕的是,你可以欺骗 TeX 的扫描仪,让它抓取 a}作为宏的参数而不会出错( You already have nine parameters当然是在两个错误之后)。原始错误报告中的这个示例显示:

\def\foo#1#2#3#4#5#6#7#8#9#}##{\show#9}
\show\foo
\foo12345678} }#
\end %        ^^ delimiter

在示例中,您有一个由}#(TeX 删除两个多余的 后剩下的标记#)分隔的宏,并且作为扫描的一部分,第一个 }不会通过Argument of \foo has an extra }错误,因此它将被添加到当前参数中,然后\show#9会说:

> end-group character }.
<argument> }
             
\foo #1#2#3#4#5#6#7#8#9}##->\show #9
                                    
l.39 \foo12345678} }#
                     
? 

经过 2021 年的调整后,TeX 现在明白您指的是#0将 作为一个参数,因此自然0也应该删除,所以现在错误消息更加详细了:

! You already have nine parameters.
l.1 \def\foo#1#2#3#4#5#6#7#8#9(#0
                                 ){}
? h
I'm going to ignore the # sign you just used,
as well as the token that followed it.

?

并且定义将不包含第十个参数的痕迹:

> \foo=macro:
#1#2#3#4#5#6#7#8#9()->.
l.3 \show\foo
             
?

相关变更条目为:

433. After nine parameters, delete both # and the token that follows
(Bruno Le Floch, 22 October 2020)
@x module 473
label found,done,done1,done2;
@y
label found,continue,done,done1,done2;
@z
@x module 474
begin loop begin get_token; {set |cur_cmd|, |cur_chr|, |cur_tok|}
@y
begin loop begin continue: get_token; {set |cur_cmd|, |cur_chr|, |cur_tok|}
@z
@x module 476
  help1("I'm going to ignore the # sign you just used."); error;
@y
  help2("I'm going to ignore the # sign you just used,")@/
    ("as well as the token that followed it."); error; goto continue;
@z

D954. 文件过早结束后缓冲区中可见垃圾(DRF)。@486

有了这个错误,如果情况正确,错误消息后面File ended within \read可能会跟着垃圾上下文。在优化之前,如果您正在\read从包含太多内容的文件中执行{,您可能会看到错误消息。假设一个文件unbal.tex只有一行:

{

然后运行以下文档:

\catcode`{=1 \catcode`}=2 \catcode`#=6
\openin1 unbal
\def\A#1#2#3#4#5#6#7#8#9{\read1to \x}
\def\B#1#2#3#4#5#6#7#8#9{\A#1#2#3#4#5#6#7#8#9 \relax}
\def\C#1#2#3#4#5#6#7#8#9{\B#1#2#3#4#5#6#7#8#9 \relax}
\def\D#1#2#3#4#5#6#7#8#9{\C#1#2#3#4#5#6#7#8#9 \relax}
\def\E#1#2#3#4#5#6#7#8#9{\D#1#2#3#4#5#6#7#8#9 \relax}
\E123456789 \end

错误消息将以以下内容开头

Runaway definition?
->{ 
! File ended within \read.
<read 1> {^^M7#8#9{\D

^^M7#8#9{\D变量中的剩余部分在哪里buffer

调整后,TeX 现在可以清理错误buffer,并且错误上下文是正确的:

Runaway definition?
->{ 
! File ended within \read.
<read 1> 

相关变更条目为:

435. Keep garbage out of the buffer if a |\read| end unexpectedly
(DRF, 17 February 2018)
@x module 486
    align_state:=1000000; error;
@y
    align_state:=1000000; limit:=0; error;
@z

R955. 强制不存在的字符具有空规范 (DRF)。@722

这个对 TeX 的正常使用没有明显的影响,所以没有可编译的示例(主要是因为我未能生成一个坏.tfm文件来触发这个错误)。

.tfm文件中,不存在的字符以其宽度索引为零来标记,并且 TeX 假定如果这是真的,则该字符的所有其他度量也为零,但没有强制执行。

但如果不是这种情况,那么在从字体读取字符时,TeX 只会查看其宽度,并假设其他所有内容均为零,而不会强制执行。但如果.tfm宽度为零,但斜体校正不是,则该索引不会归零,并且会使用错误的斜体校正。

调整后,如果字符的宽度为零,TeX 将使整个字符无效以确保无误。相关的更改条目是:

436. Zero out nonexistent chars, to prevent rogue TFM files
(DRF, 06 October 2020)
@x module 722
    math_type(a):=empty;
@y
    math_type(a):=empty; cur_i:=null_character;
@z

C956. 不要将分数 noad 标记为临时内部 (DRF)。@761

这个错误在 中已经修复tex.web,但它更像是 The TeXbook 中的一个错误。简而言之,The TeXbook 中的一些地方,例如第 155 页的最后一段曾经说过:

还有第八种分类,\mathinner通常不用于单个符号;分数和\left...\right 构造被视为“内部”子公式[...]

但现在该语句中的分数已被删除。 中的相关更改条目tex.web为:

437. Don't classify fraction noads as inner noads (DRF, 25 March 2019)
@x module 761
fraction_noad: begin t:=inner_noad; s:=fraction_noad_size;
  end;
@y
fraction_noad: s:=fraction_noad_size;
@z

现在,分数不再是内部原子了。不过,这不会对数学排版造成任何影响,因为分数通常写为{1\over2},而用于括住子公式的额外括号会使该分数在所有情况下都成为 Ord 原子。

将分数作为实际的内部原子的唯一方法是仅有的分数,例如$1\over2$,在这种情况下,由于数学界限,它不会产生任何差异,或者如果分数包含在一\left...\right对中,但由于 ,它无论如何都会成为内部原子\left...\right。分数的所有其他用法都会导致 Ord 原子,因为括号界定了子公式,因此完全放弃了这种分类以避免混淆。

我们可以从这个例子中看出这一点:

\nopagenumbers \loggingall \tracingonline=1
Punct: ${1\over2}.$\par
Ord: ${1\over2}x$
\end

如果分数实际上是一个内部原子,根据 TeXbook 第 170 页的数学间距表, \thinmuskip在两种情况下分数后面都应该有一个(后跟一个 Punct,后跟一个 ord),但如果你看一下生成的列表,你会发现都没有空格:

.......\sevenrm 2
.....\hbox(0.0+0.0)x1.2, shifted -2.5
...\teni :

.......\sevenrm 2
.....\hbox(0.0+0.0)x1.2, shifted -2.5
...\teni x

Q957. 在记录统计数据之前重置 |\newlinechar| (Udo Wermuth)。@1333,1335

Udo Wermuth 报告说,根据你设置\newlinechar参数的方式,你可能会从 TeX 获得一些奇怪的终端输出。例如运行

$ tex '\newlinechar=32 \end'

将打印

$ tex '\newlinechar=32 \end'
This is TeX, Version 3.14159265 (TeX Live 2020) (preloaded format=tex)
No
pages
of
output.
Transcript
written
on
texput.log.

因为这会让 TeX 在写入文件时使用空格字符(ASCII 32)作为换行符,因此所有空格都会被转换。使用不同的 ASCII 代码可以实现同样有趣的输出。现在已更正此问题,上面的命令将生成更无聊的

$ tex '\newlinechar=32 \end'
This is TeX, Version 3.141592653 (TeX Live 2021/dev) (INITEX)
No pages of output.
Transcript written on texput.log.

相关变更条目为:

440. Normalize newlinechar when printing the final stats
(Udo Wermuth, 29 November 2020)
@x module 1333
begin @<Finish the extensions@>;
@y
begin @<Finish the extensions@>; new_line_char:=-1;
@z
@x module 1335
begin c:=cur_chr;
@y
begin c:=cur_chr; if c<>1 then new_line_char:=-1;
@z

(\tabskip)未满消息中缺少指示

另一个错误,由 Igor Liferenko 发现\tabskip对齐的 Underfull 框消息中 缺少粘合指示,TeXbook 中另有记录。在此示例中:

% \catcode`\{=1 \catcode`\}=2 \catcode`\&=4 \catcode`\#=6
\showboxdepth=1 \tracingonline=1
\tabskip=0pt plus10pt \halign to200pt{&#\hfil\cr
  \hbox to50pt{}&\hbox to60pt{}\cr}
\end

终端将显示

\hbox(0.0+0.0)x200.0, glue set 3.0
.\glue(\tabskip) 0.0 plus 10.0
.\unsetbox(0.0+0.0)x50.0
.\glue(\tabskip) 0.0 plus 10.0
.\unsetbox(0.0+0.0)x60.0
.\glue 0.0 plus 10.0

而最后一行应该是

.\glue(\tabskip) 0.0 plus 10.0

现在,最终(\tabskip)指示已正确显示,如记录所示。

相关变更条目为:

438. Properly identify tabskip glue when tracing repeated templates
(Igor Liferenko, 10 January 2020)
@x module 793
link(p):=new_glue(glue_ptr(cur_loop));
@y
link(p):=new_glue(glue_ptr(cur_loop));
subtype(link(p)):=tab_skip_code+1;
@z

内部变量溢出\hyphenation

这可能是最不引人注意的 bug,主要是因为使用日常使用的 TeX 时你无法发现它。David Fuchs 使用他制作的用于检查内存边界违规的 TeX 特殊版本发现了它。

当声明一个 时,声明为 的 \hyphenation变量(在 范围内)将达到最大值,但在模块 §930 中,在 TeX 的异常表中查找给定单词的 会调用,使其大于声明的大小。本文档就是这样做的:hnsmall_number0..63<Look for the word |hc[1..hn]|...>incr(hn)

\lefthyphenmin=0
\righthyphenmin=0
\hyphenation{-a-b-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-a-b-%
  c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z-a-b-c-d-e-f-g-h-i-j-%
  k-l-m-n-o-p-q-r-s-t-u-v-w-x-y-z}
\showhyphens{abcdefghijklmnopqrstuvwxyzabcdefg%
  hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz}
\end

但在运行 TeX 时并不明显,因为变量溢出不会出现。具体发生什么有点依赖于实现,因为它依赖于编译器将 a 翻译成什么small_number。如果它变成一个包含超过 的变量0..63,就不会发生任何不好的事情。

相关变更条目为:

439. Use the correct range for local variable hn (DRF, 31 October 2020)
@x module 892
@!hn:small_number; {the number of positions occupied in |hc|}
@y
@!hn:0..64; {the number of positions occupied in |hc|;
                                  not always a |small_number|}
@z

结论

当然,人们将会看到的一个变化(很可能是唯一的变化)是:

-@d banner=='This is TeX, Version 3.14159265' {printed when \TeX\ starts}
+@d banner=='This is TeX, Version 3.141592653' {printed when \TeX\ starts}

:-)

与往常一样,Knuth 的所有发行版都进行了其他几项更改,包括但不限于 Metafont(由于代码部分相似,一些更改从 TeX 移植而来)、TeX 和 Metafont 书籍的更改,以及普通格式的更改(一切都非常小,不太可能影响任何合理的用户文档)。

Don 还撰写了一篇 TUGboat 文章,描述了 TeX 和 Metafont 的主要变化,可在TUGboat 网页


免责声明

本答案中的大多数代码示例都不是我自己的,而是取自原始错误报告(有些略有修改),因此感谢这些错误报告的作者,也感谢那些搜索错误的敬业人士,以及那些在过去 7 年中阅读每一份(可能数千份)错误报告的人。让我们为另外 8 个这样的报告做好准备!

答案2

补充Phelype Oleinik 的出色回答,这里是另一个版本,其中对您可能受到每个更改影响的情况进行了更简短/更草率的描述……

背景

首先,为了避免对“自 2014 年以来第一个新版本的 TeX”产生混淆,请注意:

  • 乳胶(不是 TeX),它是 TeX 之上的宏系统,发布频率更高(LaTeX 新闻)。

  • TeX 的典型用法,尤其是 LaTeX,涉及许多以不同的时间间隔更新;每天都会更新很多(见康坦)。

因此,这个“新版本的 TeX”仅对底层(非常稳定)的 TeX 引擎进行更新,也就是“基础” Knuth TeX(而不是 pdfTeX、XeTeX 或 LuaTeX——尽管这些系统源自 TeX,我认为这些更改中的部分或全部也将或已经应用到那里)。

与上一次“调整”(2014 年)只有一个实际变化不同,这次更新(2021 年)有 10 个变化(自 1990 年,即 2014 年)以来,任何一年中变化最多。宣布“完成”),按条目计算errorlog

这是什么errorlog?这是 Knuth 手动维护的一份详细记录,记录了自很早以前(可追溯到 1978 年)以来对 TeX 所做的所有更改(不仅仅是技术上的“错误”)。1989 年,他写了一篇名为TeX 的错误(重印更新为本书第 10-11 章文学编程并进一步更新为本书的最后一章——“TeX 的最终错误”数字排版)该文章描述了 TeX 的发展历史,并对该日志进行了分析,将每个条目(所做的更改)归类为以下几类之一:A 代表“A算法A讽刺”,B 代表“b抢劫或botch”,E 代表“效率增强”等。

这种分类对 Knuth 来说是主观且个人化的(有时是关于他如何 毛毡他可能需要很长时间才能弄清楚为什么他要把某样东西放在一个类别而不是另一个类别中,但这些信息很有用。

例如,2014 年更新只有一个变化:

  1. 后面有空格\csname\endcsname以匹配其他空格。

这被归类为“C”,因为“C精益求精C一致性或C拉里蒂”。

变化

在此背景下,以下是按类别划分的 2021 年更新的十项更改(更改 948-957)。(我在这里的简短描述很草率,并且是我理解不完整的结果;请参阅已接受的答案以了解详细信息。)

B 类,“失误或拙劣” (“某种程度上的打字错误”)

952. 不允许在#

排除一种不自然的(嗯,甚至比典型的 TeX 宏反常更不自然的)定义宏的方式。

C 类,“为保持一致性或清晰度而进行的清理”

956. 不要将分数点标记为临时内部点

AFAICT,一个内部细节没有明显的效果,但使得描述TeXbook清洁工。

类型 D,“数据结构崩溃”

954.文件过早结束后缓冲区中可见垃圾。

\read防止在某些罕见情况下出现“文件结束于”错误消息(本身很少见)并显示额外的垃圾。

第一类,“互动改进”

948. 描写段落时不要在错误处停顿

如果您已设置\tracingparagraphs,并且在将段落信息记录到日志文件时出现错误,...

Q 型,“追求品质”。

957.\newlinechar记录统计数据前重置

用于根据用户\newlinechar当时设置的值来断行的错误消息。

R型,“坚固性的强化”

951. 有时从系统而不是用户获取日期和时间

类似:在横幅这样的地方,不要使用用户提供的时间/日期\date\month而是使用实际的系统时间/日期。

953. 九个参数之后,必须删除违规标记

如果你定义了一个有超过 9 个参数的宏,您忽略错误消息“您已经有九个参数”,从而继续 TeX 的错误恢复,现在事情就不那么令人惊讶了。

955. 强制不存在的字符具有空规范

如果您以某种方式设法创建一种非常特殊的损坏.tfm文件,您可能会得到错误的斜体更正,但现在您却得不到了。

S型,“令人吃惊的情景”

949. 不要试图在\batchmode

一种导致 TeX 崩溃的狡猾方法,现已修复。(我还没有完全理解所有可能发生这种情况的情况……)

950. 当没有文件处于活动状态时不要尝试编辑

如果在 TeX 的错误提示下你以交互方式插入标记,并且这些插入的标记本身导致另一个错误,然后在下一个错误提示下你要求编辑该文件,则它可能已经崩溃了。

概括

任何拥有合理文档的典型用户都不太可能受到这些更改的影响;它们只会在极端情况下填补一些漏洞。尽管如此,它们代表了多年来许多人对这个程序的极其严密的审查——同时,在开发结束三十多年后,它还是一个致力于无错误软件的非凡企业。

相关内容