Open wgrundlingh opened 2 years ago
Thanks for the report, the code for \newenvironment
relies on \newcommand
(or at least the internal \new@command
) to check essentially this and throw an error that the empty command is defined.
\documentclass{article}
\expandafter\let\csname\endcsname\end
\expandafter\newcommand\csname\endcsname{whatever}
\begin{document}
\end{document}
But the if defined check fails here as \string
on the empty csname is \csname\endcsname
not empty.
This could be fixed in various ways, as always it probably comes down to deciding how much change can be done here for compatibility.
This issue has been automatically marked as stale because it has not had recent activity.
In short, the issue happens (mostly) because (the equivalent of) \cs_to_str:N
on the empty csname (\csname\endcsname
) yields csname\endcsname
instead of an empty string. Then, testing \@ifundefined{csname\endcsname}
tests the existence of something else entirely. I think the best way to fix this issue is to change the definition of \@ifdefinable
to:
\long\def\@ifdefinable #1#2{%
\edef\reserved@a{\expandafter\@gobble\string #1}%
\@expl@cs@if@free@@NTF #1% <-------- replaced |\@ifundefined\reserved@a|
{\edef\reserved@b{\expandafter\@carcube \reserved@a xxx\@nil}%
\ifx \reserved@b\@qend \@notdefinable\else
\ifx \reserved@a\@qrelax \@notdefinable\else
#2%
\fi
\fi}%
\@notdefinable}
that is, replace \@ifundefined{name}
by \cs_if_free:NTF \name
, so that the code doesn't trip over its shoelaces with the empty csname. The change should cause no harm, as the actual test done is the same after all.
This bug also affects \newcommand
, in such a way that you can redefine the empty control sequence without an error:
\def\test#1{%
\def#1{A}%
\newcommand#1{B}%
\show#1%
}
\expandafter\test\csname\endcsname % no error and shows B
\test\anything % error and shows A
(the equivalent of)
\cs_to_str:N
on the empty csname (\csname\endcsname
) yieldscsname\endcsname
instead of an empty string
Should \cs_to_str:N
take empty csname into consideration? Or, what's the expected result of \exp_args:Nc \cs_to_str:N {}
? Maybe I should open an issue in latex3.
@muzimuzhi It would be nice, but I don't think it can do that in a reasonably efficient way, because the only ways I know to do that expandably are a string comparison or a macro delimited by "csname\endcsname
". The biggest problem though is that after hit with \string
, the empty csname and a the control sequence called \csname\endcsname
are indistinguishable (if the character between \csname
and \endcsname
is the same as the current \escapechar
), so expandably the test is not completely reliable either (happy to be proven wrong :). I think it's not worth it...
Then answering your question:
what's the expected result of
\exp_args:Nc \cs_to_str:N {}
?
csname<escapechar>endcsname
: not ideal, but the lesser of two evils
This issue has been automatically marked as stale because it has not had recent activity.
Status here? Could we schedule for Fall 2023?
Yes, will be done by then.
@PhelypeOleinik Are you likely to be able to look at this for the next release?
Brief outline of the bug
\newenvironment
allows one to define an empty environment name. This causes problems as it redefines\end
. Only the check is done on the "\begin
" or opening part of the new environment definition, not whether the "\end
" exists. The result, even if a small document is that\end{document}
is not properly identified and compilation fails.Minimal example showing the bug
Log file (required) and possibly PDF file