Reading http://profs.sci.univr.it/~gregorio/introtex.pdf, I have come across the definition of \newif
on page 75:
\def\newif#1{\@ifdefinable{#1}{\@newif#1}}
\def\@newif#1{\count@\escapechar \escapechar\m@ne
\expandafter\expandafter\expandafter
\def\@if#1{true}{\let#1=\iftrue}%
\expandafter\expandafter\expandafter
\def\@if#1{false}{\let#1=\iffalse}%
\@if#1{false}\escapechar\count@} % the condition starts out false
\def\@if#1#2{\csname\expandafter\if@\string#1#2\endcsname}
{\uccode‘1=‘i \uccode‘2=‘f \uppercase{\gdef\if@12{}}} % ‘if’ required
I'm trying to understand how it works by following its expansion. So imagine I type \newif\iffoo
.
The first expansion should be
\@ifdefinable{\iffoo}{\@newif\iffoo}
therefore checking if there is an already defined
\iffoo
and then, if there is none, passing\iffoo
to\@newif
. And that's where my problems begin.\@newif
should expand into:\count@\escapechar \escapechar\m@ne \expandafter\expandafter\expandafter \def\@if\iffoo{true}{\let\iffoo=\iftrue}% \expandafter\expandafter\expandafter \def\@if\iffoo{false}{\let\iffoo=\iffalse}% \@if\iffoo{false}\escapechar\count@
Now
\count@
is a counter (\countdef\count@=255
) and so is\m@ne
(\countdef\m@ne=22 \m@ne=-1
), and\escapechar
contains the code point of\
, being defined as\escapechar=\\
(I can't put the backtick after the=
because the site's markup causes trouble). So\count@\escapechar
, I guess, gives\count@
that code, and\escapechar\m@ne
makes\escapechar
-1
. That's for later, in\if@
. Then we have the sequence of\expandafter
s. Now the first one makes TeX skip the second one, and see the third one, which makes it skip\def
and expand\@if
, which we will get to later; then TeX (I guess) remembers it had skipped through an\expandafter
, go back to it and execute it; this means\def<expansion of \@if\iffoo{true}>{\let\iffoo=\iftrue}
is delayed, and we enter a new sequence of\expandafter
s; the first one is skipped and stored away due to the left-over\expandafter
which delayed the just-mentioned\def
; so the second one is executed, the third one consequently stored away, and so we get a\def
executed which should redefine\if@
but that can't be! So the definition of the expansion of\@if\iffoo{true}
as\let\iffoo=\iftrue
takes place before the second\expandafter
of the first sequence is executed, but why? Well in that assumption we get to expanding the second\@if
and defining its expansion as\let\iffoo=\iffalse
, then we have one/two\expandafter
s; if there are two, they should elide, making me wonder why bother putting three both times if one both times is sufficient, whereas if there is one we get\count@
and then\escapechar
, so we have a useless instruction which is the repetition of one at the beginning,\count@\escapechar
. So there must be two, right? And eliding, right? So why bother putting three?And now the
\@if
. We have, as said above:\@if\iffoo{true}
so the expansion should be:
\csname\expandafter\if@\string\iffootrue\endcsname
The
\expandafter
leaves\if@
as it is, and expands the\string
, which makes\iffootrue
becomeiffootrue
, since\escapechar
is-1<0
; so we get to:\csname\if@iffootrue\endcsname
right?
Finally, the line
{\uccode‘1=‘i \uccode‘2=‘f \uppercase{\gdef\if@12{}}}
makesi
the uppercase of1
andf
the uppercase of2
, probably to make sure\if@
in the\uppercase
doesn't get taken for\if@if
, since we're in\makeatletter
, but split off because1
and2
cannot be put in a control sequence and are then turned intoi
andf
by\uppercase
. So here's the\if@
: it gets expanded to{}
, leaving just:\csname footrue \endcsname
(or
foofalse
). So we understand the actual reason of the\expandafter
in the\csname…\endcsname
: to delay the expansion of the\if@
, which is global since it's\gdef
, so is defined in a group to leave the\uccode
s local but is set to global to be used back up in those\csname…\endcsname
s.Finally, of course, we want
\escapechar
back to its original value, which was stored in\count@
, and is restored at the end of everything.
After all these reflections, I seem to have been left with only one question mark: why three \expandafters
per \if@
control sequence definition? So the question finally is:
Is there anything wrong in what I have said, what is it, and why are there those three \expandafter
s up there?