I have made a small TeX file which freezes my implementation of TeX
(distribution emtex), and I'd like to know if it is a problem in the
implementation or in TeX itself. Here is the file:
\catcode`\{=1 % left brace is begin-group character
\catcode`\}=2 % right brace is end-group character
\catcode`\#=6 % hash mark is macro parameter character
\let\par\relax
\halign{#\cr\vbox{A\vskip0pt}\cr}
\end
(The first three lines are here to ensure that initex itself can run it,
and that this is not a bug of the plain macros)
Here, TeX freezes and just takes 100% CPU on the \vskip.
Can you reproduce this ?
-- Éric Brunet
teTeX (Version 3.14159 (C version 6.1)) on HP-UX just sits there as
well, but I don't know enough plain \TeX to be able to tell what it
should do instead. Cheers, Stefan
--
=========================================================================
Stefan A. Deutscher | (+33-(0)1) voice fax
Laboratoire des Collisions Atomiques et | LCAM : 6915-7699 6915-7671
Mol\'{e}culaires (LCAM), B\^{a}timent 351 | home : 5624-0992 5624-0992
Universit\'{e} de Paris-Sud | email: s...@utk.edu
91405 Orsay Cedex, France (Europe) | (forwarded to France)
=========================================================================
Do you know what they call a quarter-pounder with cheese in Paris?
> Hello all !
>
> I have made a small TeX file which freezes my implementation of TeX
> (distribution emtex), and I'd like to know if it is a problem in the
> implementation or in TeX itself. Here is the file:
>
> \catcode`\{=1 % left brace is begin-group character
> \catcode`\}=2 % right brace is end-group character
> \catcode`\#=6 % hash mark is macro parameter character
>
> \let\par\relax
> \halign{#\cr\vbox{A\vskip0pt}\cr}
> \end
>
>
> (The first three lines are here to ensure that initex itself can run it,
> and that this is not a bug of the plain macros)
>
> Here, TeX freezes and just takes 100% CPU on the \vskip.
>
> Can you reproduce this ?
>
> -- Éric Brunet
Sorry not a bug: You don't get any cheque!
TeX hasn't frozen. It is just working hard running on the spot.
Try putting \tracingall at the top and you'll see...
Your test file has far too much in it, which is hiding the cause of the
loop that you have programmed. You just need this
\let\par\relax
A\vskip0pt
That is all!
See. A puts you in hmode. Now \vskip needs to be in vmode, so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
inserts and executes \par then runs itself again.
Normally \par puts you in vmode so on the second try the vskip
adds some space, but you have turned that off, so on the second
try you are still in hmode so it
> I have made a small TeX file which freezes my implementation of TeX
> (distribution emtex), and I'd like to know if it is a problem in the
> implementation or in TeX itself. Here is the file:
...
> \let\par\relax
> \halign{#\cr\vbox{A\vskip0pt}\cr}
> \end
You've gotten an infinite loop because \vskip uses \par to get out of
horizontal mode. If \par doesn't do what it is expected to do, \vskip
keeps inserting more \par's in a vain attempt to get to vertical mode.
Redefining \par is not a good idea unless you really know what
you're doing. More than any other control sequence, \par has special
handling interwoven in complicated ways with many other parts of TeX
(e.g., the \long feature, and the treatment of catcode 5).
From "The TeXbook" Ch 25 p 286 it is clear that for \vskip to insert
\par instead of a frozen equivalent of \par is intentional. The
rationale is that it is not uncommon for \par to be redefined for
special effects, and executing the frozen primitive version would lose
the special effect.
It seems to me, however, that it is indeed a TeX bug that when inserting
\par this way TeX does not do some kind of deadcycle check similar to
what is done for the output routine. TeX cannot monitor *all* the ways
that you can shoot yourself in the foot with an infinite loop, but this
particular way involves a token that is inserted automatically by TeX.
As a matter of fact, LaTeX implements a deadcycles check at the
macro level in those cases where it redefines \par in such a way that
the primitive end-paragraph operation might not be executed.
I suspect that a better approach in the design of TeX would have been to
merely require that \par is explicitly inserted by the user (in some
sense; maybe by the macro package writer), and that \vskip should give
an error message if used in horizontal mode, instead of inserting \par,
or even a frozen \par.
Then your infinite loop file would have merely resulted in:
! You can't use \vskip in horizontal mode.
or perhaps
! Missing \par inserted.
and it would have been clear how to turn your code into legal TeX. But
as such a change in TeX would adversely affect nearly all existing TeX
documents, it's too late to do it now.
Finally, there seems to be a significant inconsistency in TeX about this
\par insertion: If \par is inserted before the \vskip in
\vbox{A\vskip0pt}
then I would think it should also be inserted before the closing brace in
\vbox{B}
But as the following test file demonstrates, in case B the internal
end-paragraph routine is called directly instead of via the control
sequence \par.
---mjd
========================================================================
% Run with plain TeX
\def\par{%
\errmessage{\noexpand
\par was called; type "i\string\endgraf" to break out of infinite loop%
}}
\global\tracingmacros2\global\tracingcommands2\global\tracingonline1
\vbox{A\vskip0pt}
\vbox{B}
\global\tracingmacros0\global\tracingcommands0
\showboxbreadth99 \showboxdepth99 \showlists\global\tracingonline0
\bye
========================================================================
Of course, anytime one redefines \par for any reason, there's always
\endgraf. If your correspondent had simply typed \endgraf\vskip instead
of \vskip, the immediate problem would not have occurred.
But why in the world would any one \let\par\relax?
Fred
: \let\par\relax
: \halign{#\cr\vbox{A\vskip0pt}\cr}
I think the TeXbook warns you not to change any primitive macros
unless you know what you are doing...
latex does it all the time.... (or, better, \@empty)
I found indeed the problem in a LaTeX file:
\documentclass{article}
\begin{document}
\begin{tabular}{c}
\vbox{A\vskip0pt}
\end{tabular}
\end{document}
Éric Brunet
Because the poor little thing is tired and stressed out?
///Peter
--
DTDs are not common knowledge because programming students are not
taught markup. A markup language is not a programming language.