summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/generic/multiexpand
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/generic/multiexpand')
-rw-r--r--Master/texmf-dist/source/generic/multiexpand/multiexpand.dtx506
-rw-r--r--Master/texmf-dist/source/generic/multiexpand/multiexpand.ins71
2 files changed, 577 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/generic/multiexpand/multiexpand.dtx b/Master/texmf-dist/source/generic/multiexpand/multiexpand.dtx
new file mode 100644
index 00000000000..e28291565d0
--- /dev/null
+++ b/Master/texmf-dist/source/generic/multiexpand/multiexpand.dtx
@@ -0,0 +1,506 @@
+% \iffalse meta-comment
+%<*internal>
+\iffalse
+%</internal>
+%<*readme>
+Variations on the `\expandafter` TeX primitive
+==============================================
+* E-mail: blflatex@gmail.com
+* Released under the LaTeX Project Public License v1.3c or later
+ See http://www.latex-project.org/lppl.txt
+
+The package defines `\multiexpand`, `\multiexpandafter`, `\MultiExpand`
+and `\MultiExpandAfter`, replacing large chains of `\expandafter`.
+These four commands take as an argument the number of expansion to be
+done. If eTeX is available, this number is evaluated using `\numexpr`.
+
+Say we want to expand `\C` five times before `\A` and `\B` in `\A\B\C`.
+The traditional approach would be to insert 31 `\expandafter` before
+`\A` and the same number before `\B`. With this package one can use
+any of
+
+ \expandafter\A\expandafter\B\romannumeral\multiexpand{5}\C
+
+ \expandafter\A\romannumeral\multiexpandafter{5}\B\C
+
+ \MultiExpandAfter{2}\A\MultiExpandAfter{5}\B\C
+
+ \MultiExpandAfter{2}\A\MultiExpandAfter{2}\B\MultiExpand{5}\C
+
+In one step of expansion (triggered by the `\expandafter`'s),
+`\romannumeral\multiexpand{5}` expands the following token 5 times,
+whereas `\romannumeral\multiexpandafter{5}` expands the token after
+that 5 times. The macros `\MultiExpandAfter` and `\MultiExpand`
+take two steps of expansion, but do not require `\romannumeral`.
+Another example is that in two steps of expansion,
+
+ \MultiExpandAfter{2}\a\MultiExpandAfter{3}{%
+ \MultiExpandAfter{9}\b\MultiExpandAfter{10}\c\d}
+
+expands `\d` 10 times, then `\c` 7 times (9-2), then `\b` once (3-2).
+
+The package can be built from the file `multiexpand.dtx' by running
+
+ pdflatex multiexpand.dtx
+ pdflatex multiexpand.dtx
+
+%</readme>
+%<*lvt>
+ \input regression-test.tex\relax
+ \START
+ \AUTHOR{Bruno Le Floch}
+%<lvt002> \let\numexpr\relax
+ \input multiexpand.sty\relax
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % Introduce commands that expand to each other, to count how many times
+ % things were expanded.
+ \OMIT
+ \def\i{}
+ \def\v{\i\i\i\i}
+ \def\x{\i\i\i\i\v}
+ \def\l{\i\i\i\i\v\x\x\x\x}
+ \def\c{\i\i\i\i\v\x\x\x\x\l}
+ \def\d{\i\i\i\i\v\x\x\x\x\l\c\c\c\c}
+ \def\m{\i\i\i\i\v\x\x\x\x\l\c\c\c\c\d}
+ \TIMO
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % We test |\MultiExpand|, which needs two expansions. In particular, we see
+ % that the implementation is reasonably quick, and we get the $2345$-th
+ % expansion of |\m\m\m\m|.
+ % 4000-2345 = 1655 = mdclv
+ \TEST{MultiExpand many times (vlcdm)}{%
+ \toks0\expandafter\expandafter\expandafter{\MultiExpand{2345}\m\m\m\m}%
+ \TYPE{\the\toks0.}%
+ }
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % Test |\MultiExpandAfter|, two expansions to get the specified expansion.
+ % The results indirectly show that expansions happen in the expected order.
+ % 100 = c
+ % 100-(27-2) = 75 = lxxv
+ % 100-(14-2) = 88 = lxxxviii
+ % 100-38 = 62 = lxii
+ \TEST{MultiExpandAfter chain (c vxxl iiivxxxl iixl)}{%
+ \toks0\expandafter\expandafter\expandafter{%
+ \MultiExpandAfter{27}\c
+ \MultiExpandAfter{14}\c
+ \MultiExpandAfter{38}\c\c}%
+ \TYPE{\the\toks0.}%
+ }
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % Test the order of expansion. The example was given in the original
+ % question that led to writing this package. For the record, this
+ % package (at some point) used 32 |\expandafter| to do the expansion
+ % in the right order, which was better than other approaches; however
+ % this counting ignores the large overheads due to other primitives.
+ \OMIT
+ \def\a#1.{#1}
+ \def\b#1:{#1.}
+ \def\c#1,{#1:}
+ \def\d{Hello world!,}
+ \TIMO
+ %
+ \TEST{MultiExpandAfter order}{%
+ \toks0\MultiExpandAfter{3}{%
+ \MultiExpandAfter{3}\a
+ \MultiExpandAfter{3}\b
+ \MultiExpandAfter{1}\c
+ \d}%
+ \TYPE{\the\toks0}%
+ }
+
+ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+ % The other example from the same question (expanding seven tokens once
+ % each in the reverse order) takes 74 \expandafter.
+ \OMIT
+ \def\b.{.b} \def\c.{.c} \def\d.{.d}
+ \def\e.{.e} \def\f.{.f} \def\g.{.g}
+ \TIMO
+ %
+ \TEST{MultiExpandAfter order (2)}{%
+ \toks0\MultiExpandAfter{2}{%
+ \MultiExpandAfter3\a \MultiExpandAfter3\b
+ \MultiExpandAfter3\c \MultiExpandAfter3\d
+ \MultiExpandAfter3\e \MultiExpandAfter1\f\g.}%
+ \TYPE{\the\toks0}%
+ }
+
+ \END
+%</lvt>
+%<*tlg>
+This is a generated file for the l3build validation system.
+Don't change this file in any respect.
+%% \CharacterTable
+%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+%% Digits \0\1\2\3\4\5\6\7\8\9
+%% Exclamation \! Double quote \" Hash (number) \#
+%% Dollar \$ Percent \% Ampersand \&
+%% Acute accent \' Left paren \( Right paren \)
+%% Asterisk \* Plus \+ Comma \,
+%% Minus \- Point \. Solidus \/
+%% Colon \: Semicolon \; Less than \<
+%% Equals \= Greater than \> Question mark \?
+%% Commercial at \@ Left bracket \[ Backslash \\
+%% Right bracket \] Circumflex \^ Underscore \_
+%% Grave accent \` Left brace \{ Vertical bar \|
+%% Right brace \} Tilde \~}
+%%
+Author: Bruno Le Floch
+(multiexpand.sty)
+============================================================
+TEST 1: MultiExpand many times (vlcdm)
+============================================================
+\v \l \c \d \m .
+============================================================
+============================================================
+TEST 2: MultiExpandAfter chain (c vxxl iiivxxxl iixl)
+============================================================
+\c \v \x \x \l \i \i \i \v \x \x \x \l \i \i \x \l .
+============================================================
+============================================================
+TEST 3: MultiExpandAfter order
+============================================================
+Hello world!
+============================================================
+============================================================
+TEST 4: MultiExpandAfter order (2)
+============================================================
+\a .bcdefg
+============================================================
+%</tlg>
+%<*internal>
+\fi
+\def\nameofplainTeX{plain}
+\ifx\fmtname\nameofplainTeX\else
+ \expandafter\begingroup
+\fi
+%</internal>
+%<*install>
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+----------------------------------------------------------------
+multiexpand --- trigger multiple expansions in one expansion step.
+E-mail: blflatex@gmail.com
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+----------------------------------------------------------------
+
+\endpreamble
+\postamble
+
+Copyright (C) 2011-2015 by Bruno Le Floch <blflatex@gmail.com>
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License (LPPL), either
+version 1.3c of this license or (at your option) any later
+version. The latest version of this license is in the file:
+
+http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+Bruno Le Floch.
+
+This work consists of the file multiexpand.dtx
+and the derived files multiexpand.ins,
+ multiexpand.pdf and
+ multiexpand.sty.
+
+\endpostamble
+\usedir{tex/latex/multiexpand}
+\generate{
+ \file{\jobname.sty}{\from{\jobname.dtx}{package}}
+}
+%</install>
+%<install>\endbatchfile
+%<*internal>
+\usedir{source/latex/multiexpand}
+\generate{
+ \file{\jobname.ins}{\from{\jobname.dtx}{install}}
+ \file{\jobname 001.lvt}{\from{\jobname.dtx}{lvt}}
+ \file{\jobname 002.lvt}{\from{\jobname.dtx}{lvt,lvt002}}
+}
+\nopreamble\nopostamble
+\generate{
+ \file{\jobname 001.tlg}{\from{\jobname.dtx}{tlg}}
+ \file{\jobname 002.tlg}{\from{\jobname.dtx}{tlg}}
+}
+\usedir{doc/latex/multiexpand}
+\generate{
+ \file{README.md}{\from{\jobname.dtx}{readme}}
+}
+
+\ifx\fmtname\nameofplainTeX
+ \expandafter\endbatchfile
+\else
+ \expandafter\endgroup
+\fi
+%</internal>
+%<*driver>
+\documentclass[12pt]{ltxdoc}
+\usepackage[T1]{fontenc}
+\usepackage{hologo}
+\usepackage{multiexpand}
+\usepackage[margin=4cm]{geometry}
+\usepackage{hyperref}
+\RecordChanges
+\begin{document}
+ \DocInput{multiexpand.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{126}
+%
+% \def\fileversion{v1.4} \def\filedate{2015/09/20}
+%\title{\texttt{multiexpand}\\
+% Trigger multiple expansions \\ in one expansion step\thanks{This file
+% describes version \fileversion, last revised \filedate.}}
+%\author{Bruno Le Floch\thanks{E-mail: blflatex@gmail.com}
+% \thanks{I have gathered ideas from various posts in the \texttt{\{TeX\}}
+% community at \url{http://tex.stackexchange.com}. Thanks to their authors.}}
+%\date{Released \filedate}
+%
+%\maketitle
+%
+% \tableofcontents
+% \changes{v1.0}{2011/02/15}{First version with documentation}
+% \changes{v1.1}{2013/01/08}{Version submitted to CTAN}
+% \changes{v1.2}{2013/01/09}{Use fewer expandafter for large arguments}
+% \changes{v1.2}{2013/01/09}{Change ME prefix to multiexpand}
+% \changes{v1.4}{2015/09/20}{Clarify that eTeX is not required}
+%
+% \section{Two user commands}
+%
+% \begin{itemize}
+% \item For $n>0$, expanding |\MultiExpand{|$n$|}\macro| twice gives
+% the $n$-th expansion of |\macro|.
+% \item For $n>0$, expanding |\MultiExpandAfter{|$n$|}\macroA\macroB|
+% twice expands |\macroB| $n$ times before expanding |\macroA|.
+% \end{itemize}
+% Note that neither functions work for $n = 0$.
+%
+% These can typically be combined as
+% \begin{verbatim}
+% \MultiExpand{7}%
+% \MultiExpandAfter{4}\a\MultiExpandAfter{7}\b%
+% \MultiExpandAfter{3}\c\d
+% \end{verbatim}
+% which would expand |\d| $3$~times, then |\c| $5$~times ($2$~of the $7$~times
+% were used to expand |\MultiExpandAfter{3}|), then |\b| twice ($4-2$), and
+% finally |\a| five times ($7-2$). Note that all this happens in precisely
+% \emph{two} steps of expansion.
+%
+% In some cases, one needs to achieve the same effect in \emph{one} step
+% only. For this, we use the first expansion of |\MultiExpand|, which
+% is |\romannumeral| |\multiexpand|, or of |\MultiExpandAfter|, which is
+% |\romannumeral| |\multiexpandafter|. In detail, expanding |\romannumeral|
+% |\multiexpand{|$n$|}| once expands the following token $n$ times, and
+% similarly for |\romannumeral| |\multiexpandafter{|$n$|}|.
+%
+% These are especially useful when we want to expand several times a
+% very specific token which is buried behind many others. For instance,
+% expanding the following code once
+% \begin{verbatim}
+% \expandafter\macroA\expandafter\macroB
+% \romannumeral\multiexpandafter{4}\macroC\macroD
+% \end{verbatim}
+% will expand |\macroD| $4$ times before the three other macros.
+%
+% Note: as we mentionned, this breaks for $n=0$. But in this case, consider
+% using |\expandafter\empty|, or a variant thereof.
+%
+% \section{Implementation}
+%\StopEventually{\PrintChanges\PrintIndex}
+% \begin{macrocode}
+%<*package>
+% \end{macrocode}
+%
+% We work inside a group, to change the catcode of |@|. So we will only
+% do |\gdef|s. Note that this code can be read several times with no
+% issue; no need to bother to check whether it was already read or not.
+% \begin{macrocode}
+\begingroup
+\catcode `\@=11
+% \end{macrocode}
+%
+% \subsection{Common to the \hologo{eTeX} and non-\hologo{eTeX} cases}
+%
+% For the ``lazy'', who do not want to use |\romannumeral|, we provide
+% |\MultiExpand| and |\MultiExpandAfter|, simple shorthands. A drawback
+% is that they require two steps of expansion rather than only one.
+% \begin{macrocode}
+\gdef \MultiExpand {\romannumeral \multiexpand }
+\gdef \MultiExpandAfter {\romannumeral \multiexpandafter }
+% \end{macrocode}
+%
+% \subsection{Without \hologo{eTeX}'s \cs{numexpr}}
+% \changes{v1.3}{2015/03/03}{Support TeX with no numexpr}
+%
+% No need for the usual |\begingroup\expandafter\endgroup| to prevent
+% |\numexpr| from being set to |\relax|, because we are already in a
+% group.
+% \begin{macrocode}
+\expandafter \ifx \csname numexpr\endcsname \relax
+% \end{macrocode}
+%
+% A helper.
+% \begin{macrocode}
+\long \gdef \multiexpand@gobble #1{}
+% \end{macrocode}
+%
+% The user commands |\multiexpand| and |\multiexpandafter|, to be used
+% after |\romannumeral|. They only differ a little bit.
+% \begin{macrocode}
+\gdef \multiexpand {\multiexpand@aux \multiexpand@ }
+\gdef \multiexpandafter {\multiexpand@aux \multiexpand@after }
+% \end{macrocode}
+% The user commands receives a number, and to accept various forms of
+% numbers we hit it with |\number|. If it is non-positive, stop the
+% |\romannumeral| expansion with |0| and a space. Otherwise, reverse
+% the number, to make it easy to subtract~$1$.
+% \begin{macrocode}
+\long \gdef \multiexpand@aux #1#2%
+ {\expandafter \multiexpand@test \number #2;#1}
+\gdef \multiexpand@test #1;#2%
+ {%
+ \ifnum #1>0
+ \multiexpand@reverse #1{?\multiexpand@reverse@end }?;;#2%
+ \fi
+ 0 %
+ }
+% \end{macrocode}
+% The macro |\multiexpand@reverse| puts characters from the number one
+% by one (as~|#1|) after the semicolon, to reverse the number. After
+% the last digit, |#1| is |{?\multiexpand@reverse@end}|. The question
+% mark is removed by |\multiexpand@gobble|, and the |reverse@end|
+% macro cleans up. In particular, one should not forget to close the
+% conditional using~|#5|, which is the trailing~|\fi|. At this stage,
+% |#4| is the function that distinguishes |\multiexpand| from
+% |\multiexpand@after|, and |#3| is the reversed
+% number. \begin{macrocode}
+\gdef \multiexpand@reverse #1#2;%
+ {\multiexpand@gobble #1\multiexpand@reverse #2;#1}
+\gdef \multiexpand@reverse@end #1;?#2#3;#4#50
+ {#5\multiexpand@iterate #41#3;}
+% \end{macrocode}
+% The macro |\multiexpand@iterate| applies a \meta{function} a certain
+% number of times to what follows in the input stream. It expects to
+% receive \meta{function} \meta{nines} |1|\meta{reversed number}|;|.
+% The argument \meta{nines}, made entirely of the digit~|9|, is used to
+% compute carries when subtracting~$1$, and is initally empty. As a
+% concrete example, after |\multiexpand{302}| the successive
+% calls to |\multiexpand@iterate| would go as follows.
+% \begin{verbatim}
+% \multiexpand@iterate \multiexpand@ 1203;
+% \multiexpand@iterate \multiexpand@ 1103;
+% \multiexpand@iterate \multiexpand@ 1003;
+% \multiexpand@iterate \multiexpand@ 9 103;
+% \multiexpand@iterate \multiexpand@ 99 13;
+% \multiexpand@iterate \multiexpand@ 1992;
+% \multiexpand@iterate \multiexpand@ 1892;
+% \multiexpand@iterate \multiexpand@ 1792;
+% \end{verbatim}
+% Note in particular how carries are done in several steps. The details
+% are left as an exercise to the reader. The most common case is when
+% |#2| is empty and |#3| is a non-zero digit. Then |\number| is
+% expanded, triggering |\ifcase| which shifts |#3| by one unit, and |#1|
+% takes care of expanding the tokens are required by |\multiexpand| or
+% |\multiexpandafter|. If |#3| is~$0$, then |\multiexpand@zero| is
+% called, closing the conditional with |#1|, and iterating, this time
+% with a non-empty \meta{nines}, which are the argument |#2| of a new
+% call to |\multiexpand@iterate|. Those \meta{nines} are put back into
+% the number by |\multiexpand@iterate|, unless the next significant
+% digit is also $0$, in which case |\multiexpand@zero| is called again,
+% until finding a non-zero digit; at each step, one more $9$ is added to
+% the \meta{nines}. If all digits are zero, we reach |;| this way, and
+% end, after cleaning up.
+% \begin{macrocode}
+\gdef \multiexpand@iterate #1#21#3%
+ {%
+ \ifx ;#3\multiexpand@end \fi
+ \ifx 0#3\multiexpand@zero \fi
+ \expandafter \multiexpand@iterate
+ \expandafter #1%
+ \number 1#2%
+ \ifcase #3 \or 0\or 1\or 2\or 3\or 4\or 5\or 6\or 7\or 8\fi
+ #1%
+ }
+\gdef \multiexpand@zero #1#2\number 1#3\ifcase #4\fi #5%
+ {#1\multiexpand@iterate #59#31}
+\gdef \multiexpand@end #1#2\ifcase #3\fi #4{#10 }
+% \end{macrocode}
+% Finally, the two different expansion commands.
+% \begin{macrocode}
+\gdef \multiexpand@ #1;{#1\expandafter ;}
+\gdef \multiexpand@after #1;{#1\expandafter ;\expandafter }
+% \end{macrocode}
+%
+% \subsection{With \hologo{eTeX}}
+%
+% \begin{macrocode}
+\else
+% \end{macrocode}
+%
+% With \hologo{eTeX}, everything is much easier, since the engine knows
+% how to subtract~$1$.
+%
+% The main looping macros expect their arguments as an integer followed
+% by a semicolon. As long as the argument is at least~$2$, decrement
+% it, and expand what follows. Once the argument is~$1$ (or less: the
+% macros are not meant to handle that case), call |\multiexpand@end| to clean up
+% and stop looping.
+% \begin{macrocode}
+\gdef \multiexpand@ #1;%
+ {%
+ \ifnum #1<2 \multiexpand@end \fi
+ \expandafter \multiexpand@
+ \the \numexpr #1-1\expandafter ;%
+ }
+\gdef \multiexpand@after #1;%
+ {%
+ \ifnum #1<2 \multiexpand@end \fi
+ \expandafter \multiexpand@after
+ \the \numexpr #1-1\expandafter ;\expandafter
+ }
+% \end{macrocode}
+% The looping macros are used within an overarching |\romannumeral|
+% expansion, which we end with a |0| and a space, as well as the
+% appropriate |\expandafter|. Here, |#1| is |\fi| which needs to remain
+% to close the conditional, |#2| is |\expandafter|, and there is a
+% trailing |\expandafter| in the case of |\multiexpand@after|.
+% \begin{macrocode}
+\gdef \multiexpand@end #1#2#3;{#10#2 }
+% \end{macrocode}
+% Finally, user commands, used as |\romannumeral| |\multiexpand(after)|.
+% Those evaluate their argument, and pass it to |\multiexpand@(after)|.
+% The argument might contain |\par| tokens (who knows)
+% \begin{macrocode}
+\long \gdef \multiexpand #1%
+ {\expandafter \multiexpand@ \the \numexpr #1;}
+\long \gdef \multiexpandafter #1%
+ {\expandafter \multiexpand@after \the \numexpr #1;}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\fi
+% \end{macrocode}
+%
+% Close the group.
+% \begin{macrocode}
+\endgroup
+% \end{macrocode}
+%
+% \begin{macrocode}
+%</package>
+% \end{macrocode}
+%\Finale
+\endinput
+
+
+
diff --git a/Master/texmf-dist/source/generic/multiexpand/multiexpand.ins b/Master/texmf-dist/source/generic/multiexpand/multiexpand.ins
new file mode 100644
index 00000000000..956f082a98d
--- /dev/null
+++ b/Master/texmf-dist/source/generic/multiexpand/multiexpand.ins
@@ -0,0 +1,71 @@
+%%
+%% This is file `multiexpand.ins',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% multiexpand.dtx (with options: `install')
+%% ----------------------------------------------------------------
+%% multiexpand --- trigger multiple expansions in one expansion step.
+%% E-mail: blflatex@gmail.com
+%% Released under the LaTeX Project Public License v1.3c or later
+%% See http://www.latex-project.org/lppl.txt
+%% ----------------------------------------------------------------
+%%
+\input docstrip.tex
+\keepsilent
+\askforoverwritefalse
+\preamble
+----------------------------------------------------------------
+multiexpand --- trigger multiple expansions in one expansion step.
+E-mail: blflatex@gmail.com
+Released under the LaTeX Project Public License v1.3c or later
+See http://www.latex-project.org/lppl.txt
+----------------------------------------------------------------
+
+\endpreamble
+\postamble
+
+Copyright (C) 2011-2015 by Bruno Le Floch <blflatex@gmail.com>
+
+This work may be distributed and/or modified under the
+conditions of the LaTeX Project Public License (LPPL), either
+version 1.3c of this license or (at your option) any later
+version. The latest version of this license is in the file:
+
+http://www.latex-project.org/lppl.txt
+
+This work is "maintained" (as per LPPL maintenance status) by
+Bruno Le Floch.
+
+This work consists of the file multiexpand.dtx
+and the derived files multiexpand.ins,
+ multiexpand.pdf and
+ multiexpand.sty.
+
+\endpostamble
+\usedir{tex/latex/multiexpand}
+\generate{
+ \file{\jobname.sty}{\from{\jobname.dtx}{package}}
+}
+\endbatchfile
+%%
+%% Copyright (C) 2011-2015 by Bruno Le Floch <blflatex@gmail.com>
+%%
+%% This work may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License (LPPL), either
+%% version 1.3c of this license or (at your option) any later
+%% version. The latest version of this license is in the file:
+%%
+%% http://www.latex-project.org/lppl.txt
+%%
+%% This work is "maintained" (as per LPPL maintenance status) by
+%% Bruno Le Floch.
+%%
+%% This work consists of the file multiexpand.dtx
+%% and the derived files multiexpand.ins,
+%% multiexpand.pdf and
+%% multiexpand.sty.
+%%
+%%
+%% End of file `multiexpand.ins'.