Trying to understand a line in latex.ltx (regarding \string, \escapechar and \csname in the definition of \newif)
The \escapechar
setting means that \string\foo
is foo
not \foo
(no backslash) this means that the \gobbletwo
gobbles if
not \i
when applied to \string\ifzzz
The texbook quote is assuming the default value of \escapechar
when it says that a \backslash_{12}
will be inserted.
The command \string<token>
works in two different ways:
if
<token>
is a character token, the same character with category code 12 is delivered (but 10 is used if<token>
is an explicit space token);otherwise
<token>
is a control sequence and in this case the name of the control sequence is delivered preceded by the character with code\escapechar
; all characters so produced will have category code 12, except for spaces that retain their usual category code 10; however, if\escapechar
has negative value or beyond 255 (0x1FFFFF
for Unicode engines such asxetex
orluatex
), no character will be prepended.
Thus, when \escapechar
is −1, the result of \string\foo
will be foo
(all characters having category code 12).
This is completely independent of the current character having category code 0. So, if you have
\catcode`@=0
@string@foo
and all other settings are standard, the delivered string of characters will be
\foo
because the default value for \escapechar
is 92, as set by TeX at startup. This is witnessed by the following interactive session
> tex -ini '\catcode`{=1\catcode`}=2\message{\the\escapechar}'
This is TeX, Version 3.14159265 (TeX Live 2019) (INITEX)
92
However, nobody can know what's the value of \escapechar
when \newif
is called. Since one is expected to do \newif\iffoo
, the macro needs to strip the possible \escapechar
from the output of \string\iffoo
in order to be able to define \footrue
and \foofalse
.
For instance, when reading .fd
files, LaTeX enters a state where \escapechar
is set to −1, so the backslash will not be inserted when using \string
(it's not the only place). So the safest strategy is to temporarily set \escapechar
to a known value and restore the value it had afterwards. Therefore, the current value is stored in \count@
(note that \escapechar
is an internal integer register), to be restored at the end of the job.
Setting the (temporary) value to 92 would require to use \@gobblethree
(which is not defined in the kernel), so it's simpler to set it to −1 and use \@gobbletwo
.
This could be done in a different way without storing the value in a counter, which might even be more preferable because \count@
is not affected.
\def\newif#1{%
\let#1\iffalse
\@if#1\iftrue
\@if#1\iffalse
}
\def\@if#1#2{%
\begingroup\escapechar=\m@ne\expandafter\endgroup
\expandafter\def
\csname\expandafter\@gobbletwo\string#1\expandafter\@gobbletwo\string#2\endcsname
{\let#1#2}%
}
How does it work? The value of \escapechar
is changed inside a group and will be restored as soon as the group ends. However, \expandafter
pokes after \endgroup
before the group ends so the token from \csname
is formed when \escapechar
to −1; \endgroup
will restore the previous value of \escapechar
and the \def
will be performed.
An important difference from the similar macro in plain TeX is that LaTeX performs no check whether the argument to \newif
is a control sequence whose name begins with if
.
The quote you reproduced is indeed simplified, but further on the same page (40), the TeXbook reads:
In the examples so far,
\string
has converted control sequences into lists of tokens that begin with \12. But this backslash token isn't really hardwired into TeX; there's a parameter called\escapechar
that specifies what character should be used when control sequences are output as text. The value of\escapechar
is normally TeX's internal code for backslash, but it can be changed if another convention is desired.
Anyway, when you want to be sure, better also check later chapters such as the three Summary of ... Mode chapters at the end of the book. In this case, in chapter 20, Definitions (also called Macros):
\string
〈token〉. TeX first reads the 〈token〉 without expansion. If a control sequence token appears, its\string
expansion consists of the control sequence name (including\escapechar
as an escape character, if the control sequence isn't simply an active character). Otherwise the 〈token〉 is a character token, and its character code is retained as the expanded result.
Also, according to page 308, the omission of the escape char in Knuth's TeX when using \string
happens if, and only if \escapechar
is outside the [0,255] range:
There is, however, another solution: If TeX's
\escapechar
parameter—which will be explained in one of the next dangerous bends—is negative or greater than 255, then\string\\
works.
(the objective is to output a single backslash character token with category code 12).