7

Why the following code enters an infinite loop?

\everypar={\hrule}
a
\bye

\tracingcommands=1 gives this:

{vertical mode: \everypar}
{blank space  }
{the letter a}
{horizontal mode: \hrule}
{\par}
{vertical mode: \hrule}
{the letter a}
{horizontal mode: \hrule}
{\par}
{vertical mode: \hrule}
{the letter a}
{horizontal mode: \hrule}
{\par}
{vertical mode: \hrule}
...
7

\hrule is a vertical command, that ends the paragraph. Next, TeX rereads the token that caused the tokens in \everypar to be inserted, finds it is a character, so it starts a paragraph, inserts \hrule, which ends the paragraph…

Some more theory from pages 282 and 283 of the TeXbook

\indent. The \parskip glue is appended to the current list, unless TeX is in internal vertical mode and the current list is empty. Then TeX enters unrestricted horizontal mode, starting the horizontal list with an empty hbox whose width is \parindent. The \everypar tokens are inserted into TeX’s input. The page builder is exercised. When the paragraph is eventually completed, horizontal mode will come to an end as described in Chapter 25.

\noindent. This is exactly like \indent, except that TeX starts out in horizontal mode with an empty list instead of with an indentation.

• [...]

• Some commands are incompatible with vertical mode because they are intrinsically horizontal. When the following commands appear in vertical modes they cause TeX to begin a new paragraph:

⟨horizontal command⟩ −→ ⟨letter⟩ | ⟨otherchar⟩ | \char | ⟨chardef token⟩
| \noboundary | \unhbox | \unhcopy | \valign | \vrule
| \hskip | \hfil | \hfill | \hss | \hfilneg
| \accent | \discretionary | \- | \␣ | $

Here ⟨letter⟩ and ⟨otherchar⟩ stand for explicit or implicit character tokens of categories 11 and 12. If any of these tokens occurs as a command in vertical mode or internal vertical mode, TeX automatically performs an \indent command as explained above. This leads into horizontal mode with the \everypar tokens in the input, after which TeX will see the ⟨horizontal command⟩ again.

The key is in the final clause: the horizontal command that triggered the start of a paragraph has not yet entered TeX stomach and will be reread.

The other key is that a ⟨vertical command⟩ found in horizontal mode will issue a \par token for ending the current paragraph (or doing whatever action has been assigned to \par).

So your code can be simplified to

\everypar{\par}a

that will start a nasty infinite loop as well (nasty, because it will fill up your disk with an endless queue of paragraphs only containing the indentation box.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.