如何诊断未封闭的(不完整的)\iftrue 或 \ifnum?

如何诊断未封闭的(不完整的)\iftrue 或 \ifnum?

我正在处理一个大型 LaTeX 文档(超过 1000 页)。我使用得\include非常多,并且有 47 个.tex文件在运行。运行结束时,我得到了以下诊断信息:

(\end occurred when \iftrue on line 366 was incomplete)
(\end occurred when \ifnum on line 366 was incomplete) 

我使用的 TeX 版本声明如下:

This is pdfTeX, Version 3.14159265-2.6-1.40.15 (TeX Live 2015/dev/Debian) (preloaded format=latex 2015.5.11)  29 DEC 2015 17:28

我的问题:我如何找到有问题的命令? 我使用 Awk 打印了.tex目录中每个文件的第 366 行,但这些文件似乎都没有任何条件。我也查看了这些.aux文件。本地.sty文件不起作用,因为它们都不是 366 行。

我应该在哪里查找?我应该寻找什么?有没有办法让 TeX 吐出有问题的文件的名称而不仅仅是行号?也许是一些 luatex 诡计?

(我不知道如何提供一个最小的例子。如果我能提供的话,我可能就能解决这个问题。)

答案1

如果你看看

\tracingifs=2

\ifnum9=9

\stop

使用\tracingifs设置后日志会显示更多信息:

(./file.tex
LaTeX2e <2016/01/01>
Babel <3.9m> and hyphenation patterns for 79 languages loaded.
{vertical mode: \ifnum: (level 1) entered on line 4}
{\ifvmode: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\fi: \ifvmode (level 2) entered on line 6}
{\iftrue: (level 2) entered on line 6}
{\ifx: (level 3) entered on line 6}
{\fi: \ifx (level 3) entered on line 6}
{\fi: \iftrue (level 2) entered on line 6}
{\iffalse: (level 2) entered on line 6}
{\fi: \iffalse (level 2) entered on line 6}
{\iffalse: (level 2) entered on line 6}
{\fi: \iffalse (level 2) entered on line 6}
{internal vertical mode: \ifnum: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\ifvoid: (level 4) entered on line 6}
{\ifvbox: (level 5) entered on line 6}
{\fi: \ifvbox (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\iffalse: (level 5) entered on line 6}
{\fi: \iffalse (level 5) entered on line 6}
{\iffalse: (level 5) entered on line 6}
{\fi: \iffalse (level 5) entered on line 6}
{\ifx: (level 5) entered on line 6}
{\else: \ifx (level 5) entered on line 6}
{\fi: \ifx (level 5) entered on line 6}
{\else: \ifvoid (level 4) entered on line 6}
{\fi: \ifvoid (level 4) entered on line 6}
{\else: \ifnum (level 3) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\ifdim: (level 3) entered on line 6}
{\else: \ifdim (level 3) entered on line 6}
{\fi: \ifdim (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\ifnum: (level 3) entered on line 6}
{\else: \ifnum (level 3) entered on line 6}
{\ifnum: (level 4) entered on line 6}
{\ifnum: (level 5) entered on line 6}
{\fi: \ifnum (level 5) entered on line 6}
{\else: \ifnum (level 4) entered on line 6}
{\fi: \ifnum (level 4) entered on line 6}
{\fi: \ifnum (level 3) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
{\ifnum: (level 2) entered on line 6}
{\else: \ifnum (level 2) entered on line 6}
{\fi: \ifnum (level 2) entered on line 6}
 )
(\end occurred when \ifnum on line 4 was incomplete) 

所以你可以看到,在这种情况下,这是一个无与伦比的(level 1) \ifnum

从线开始向上工作

    {vertical mode: \ifnum: (level 1) entered on line 4}

您会看到第一个(节目(./file.tex,因此第 4 行file.tex出现了令人反感的 if。

答案2

尝试在主文件之前输入的文件之一中搜索最终的 \end{documentation} ...

答案3

对于大型日志文件的一些提示:

  • 因为它真的很难寻找(file)在这种情况下,您可以使用一些 LaTeX 钩子在文件更改时记录一些消息:

    \ExplSyntaxOn
    \seq_new:N \__file_list
    \seq_put_right:Nn \__file_list {\msg_expandable_error:nn{}{this~cannot~happen!}}
    \seq_put_right:Nn \__file_list {<main~file>}
    \AddToHook{file/before}{
        \seq_put_right:NV \__file_list \CurrentFile
        \wlog {enter~file\use_none:n{}::\CurrentFile}
    }
    \AddToHook{file/after}{
        \seq_pop_right:NN \__file_list \__last_file
        \seq_get_right:NN \__file_list \__last_file
        \wlog {return~to~file\use_none:n{}::\__last_file}
    }
    \ExplSyntaxOff
    

    (显然效果是,您会在日志中得到一行enter file::Xreturn to file::X。搜索file::\use_none:n {}是为了防止在启用宏日志记录时在进行宏扩展时找到消息。)

  • “二进制搜索”的替代方法是向某些 TeX 文件中插入(带注释的)空行,然后查看行号是否增加。(这是“蛮力”,但大多数情况下都有效,除非 catcode 很奇怪。)

  • 请注意,即使某个特定因素\if被报告为罪魁祸首,它也不一定是原因。例如

    \if ... % A
    
        \if ... % B (accidentally inserted)
    
    \fi % C
    

    显然B,这里的错误A是 TeX 报告的,尽管如此,它还是不完整的。并且A可能深埋在某些库代码中(例如,如果\if某个文件中存在不完整代码.sty,则可能会发生这种情况)

  • if.* <line number>}一般来说,从文件末尾搜索 (regex) 很有用,因为您可以观察到,如果有多个这样的\if,则最后一个可能有问题;尽管如此,如果第一个匹配项是,\fi则跳过一个\if

    示例日志

    {\if entered on line X}
    {\else: \if entered on line X}
    {\fi: \if entered on line X}
    
    {\if entered on line X}
    {\else: \if entered on line X}
    {\fi: \if entered on line X}
    
    {\if entered on line X}
    {\else: \if entered on line X}
    {\fi: \if entered on line X}
    
    {\if entered on line X}
    
    {\if entered on line X}
    {\else: \if entered on line X}
    {\fi: \if entered on line X}
    

    在这个例子中,可以看出,如果从末尾向后搜索日志行,您将首先看到一个\fi,然后跳过一个\if,然后立即找到有问题的命令。(这可以(level X)部分帮助搜索匹配的行,但仅此而已。)

相关内容