On 11 August 2015 at 11:21, Gavin Smith <[email protected]> wrote:
> When looking at the log file, I noticed a funny order of execution.
> What was happening, was that the call to the inner macro was being
> processed inside \eatspaces. This was bad news: the cat codes were
> fixed when the argument to \eatspaces were read, and the cat code
> changes for the argument to the inner macro were ineffectual.
Here's the next try. This uses quite a different approach: instead of
processing the argument by evaluating it, it reads it piece by piece
using a macro with a delimited argument.
Index: doc/texinfo.tex
===================================================================
--- doc/texinfo.tex (revision 6493)
+++ doc/texinfo.tex (working copy)
@@ -3,7 +3,7 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2015-08-03.11}
+\def\texinfoversion{2015-08-03.11-bsmacro}
%
% Copyright 1985, 1986, 1988, 1990, 1991, 1992, 1993, 1994, 1995,
% 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
@@ -7460,7 +7460,9 @@
\def\macroargctxt{% used when scanning invocations
\scanctxt
- \catcode`\\=0
+ \catcode`\ =\other
+ \catcode`\\=\active
+ %\catcode`\\=0
}
% why catcode 0 for \ in the above? To recognize \\ \{ \} as "escapes"
% for the single characters \ { }. Thus, we end up with the "commands"
@@ -7907,16 +7909,75 @@
\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
+
+{\catcode`\@=0 \catcode`\\=13
+@catcode`@_=11
+
+% Call #1 with a list of tokens #2, with any doubled backslashes in #2
+% compressed to one.
+@gdef@passargtomacro#1#2{%
+ @def@the_macro{#1}%
+ @def@pending_backslash{}%
+ @let@finish@relax
+ @def@arg_result{}%
+ @let@next_token=@relax
+ @add_segment#2\@finish\%
+}
+
+@gdef@look_ahead{%
+ @futurelet@next_token@look_aheadzzz}
+@gdef@look_aheadzzz{%
+ @ifx@next_token\%
+ @let@next=@gobble_and_check_finish
+ @else
+ @let@next=@add_segment
+ @fi@next
+}
+
+% double backslash found. add a single backslash here.
+@gdef@gobble_and_check_finish#1{%
+ @add_the_backslash
+ @def@pending_backslash{}%
+ @futurelet@next_token@add_segment
+}
+
+@gdef@add_the_backslash{%
+ @expandafter@gdef@expandafter@arg_result@expandafter{@arg_result\}%
+}
+
+@gdef@add_segment#1\{%
+@ifx@next_token@finish
+ @let@next=@call_the_macro%
+@else
+ @let@next=@look_ahead
+ %
+ % append to @arg_result
+ % token list registers might be better
+ @expandafter@expandafter@expandafter@gdef
+ @expandafter@expandafter@expandafter@arg_result
+ @expandafter@expandafter@expandafter{%
+ @expandafter@arg_result
+ @pending_backslash#1}%
+ @def@pending_backslash{\}%
+@fi@next}
+
+@gdef@call_the_macro{@expandafter@the_macro@expandafter{@arg_result}}
+
+}
+
% \braceorline MAC is used for a one-argument macro MAC. It checks
% whether the next non-whitespace character is a {. It sets the context
% for reading the argument (slightly different in the two cases). Then,
-% to read the argument, in the whole-line case, it then calls the
-% regular \parsearg MAC; in the lbrace case, it just calls MAC itself.
+% to read the argument, in the whole-line case, it then calls the regular
+% \parsearg MAC; in the lbrace case, it calls \passargtomacro MAC.
%
\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx}
\def\braceorlinexxx{%
- \ifx\nchar\bgroup\macroargctxt
- \else\macrolineargctxt\expandafter\parsearg
+ \ifx\nchar\bgroup
+ \macroargctxt
+ \expandafter\passargtomacro
+ \else
+ \macrolineargctxt\expandafter\parsearg
\fi \macnamexxx}