Get the lion to run in loops. Tersely

Not extremly short, but a real bug I ran into once when working on xor

\output{\deadcycles=1
        \message{.}%            just to show that something is happening
        \setbox0\box255}
\null
\bye

Of course the output routine didn't set \deadcycles to 1. In reality it was two ORs being called in a row the first setting it to zero.

Just realized that I only answered the second part of the question. By now the first part has already been answered by @egreg.


I think to have understood why the infinite loop is triggered. The e-TeX primitive \unexpanded is mostly like \lowercase: it should be followed by <general text>, which in turn is <filler>{<balanced text><right brace>. The important bit is <filler>, which is an arbitrary sequence of \relax commands and spaces (TeXbook, p. 276).

So \unexpanded looks for a { expanding commands on the go and ignoring \relax and space tokens. But it is expandable!

When e-TeX finds \if\unexpanded\fi, the primitive \if triggers the expansion of \unexpanded; but the \fi immediately following causes the insertion of a (frozen) \relax, because of the unfinished conditional, that \unexpanded swallows, leaving an unfinished conditional, which causes the insertion of \relax

Oops, infinite loop. For \detokenize and \scantokens the situation is the same. In original TeX no expandable primitive accepts a <general text> as argument, as far as I know.

The situation is indeed completely different with \if\lowercase\fi, where \lowercase is not expandable, so TeX inserts \relax and the comparison can be performed (and is true).


A shorter loop just using classic tex and no macro expansion is

\let\par\relax.\vskip