From e6676d20e7ef321a96012f8bc06e753f149c4323 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 11 Jan 2006 23:55:58 +0000 Subject: trunk/Master/texmf-dist/source/latex/patchcmd git-svn-id: svn://tug.org/texlive/trunk@437 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/source/latex/patchcmd/patchcmd.dtx | 222 +++++++++++++++++++++ .../texmf-dist/source/latex/patchcmd/patchcmd.ins | 7 + 2 files changed, 229 insertions(+) create mode 100644 Master/texmf-dist/source/latex/patchcmd/patchcmd.dtx create mode 100644 Master/texmf-dist/source/latex/patchcmd/patchcmd.ins (limited to 'Master') diff --git a/Master/texmf-dist/source/latex/patchcmd/patchcmd.dtx b/Master/texmf-dist/source/latex/patchcmd/patchcmd.dtx new file mode 100644 index 00000000000..0c37d7ca4af --- /dev/null +++ b/Master/texmf-dist/source/latex/patchcmd/patchcmd.dtx @@ -0,0 +1,222 @@ +%%% ==================================================================== +%%% @LaTeX-doc-source-file{ +%%% filename = "patchcmd.dtx", +%%% version = "1.03", +%%% date = "2000/07/31", +%%% time = "08:40:39 EDT", +%%% author = "Michael J Downes", +%%% email = "mjd@ams.org", +%%% abstract = "Provides a way to add material at beginning or end of +%%% a macro's existing definition.", +%%% checksum = "23183 222 932 7411", +%%% docstring = "The checksum field, produced by Robert Solovay's +%%% checksum utility, gives CRC-16 checksum, lines, +%%% words, and characters.", +%%% } +%%% ==================================================================== +% \iffalse +%<*driver> +\NeedsTeXFormat{LaTeX2e} +\documentclass{amsdtx} +\begin{document} +\title{The \pkg{patchcmd} package} +\author{Michael~J. Downes} +\date{Version \fileversion, \filedate} +\hDocInput{patchcmd.dtx} +\end{document} +% +% \fi +% +% \maketitle +% \section{Introduction} +% +% The \pkg{patchcmd} package provides a command \cn{patchcommand} that +% can be used to add material at the beginning and/or end of the +% replacement text of an existing macro. It works for macros with any +% number of normal arguments (0--9), including macros that were +% defined with \cn{DeclareRobustCommand}. However, it does not work +% for macros that use \cs{futurelet}, for example ones defined to +% have starred forms or optional arguments. In addition, it does not +% work for macros that have delimited arguments. +% +% This package is the result of some discussion initiated by Peter +% Wilson in the newsgroup \fn{comp.text.tex} in June 2000 and +% continued with Peter and Heiko Oberdiek. +%\begin{verbatim} +%Subject: Re: Adding stuff at end of a macro +%References: +% <3ojiks8in1f5s575eta5rg7ncoc98mpi8f@4ax.com> +% <39492C50.A962193B@boeing.com> +% +%\end{verbatim} +% +% \StopEventually{} +% +% \section{Implementation} +% Standard declaration of package name and date. +% \begin{macrocode} +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{patchcmd}[2000/07/31 v1.03] +%% Copyright 2000 Michael John Downes +%% This file has no restrictions on its use, distribution, or sale. +% \end{macrocode} +% +% For debugging. +% \begin{macrocode} + +%%\def\wrs{\immediate\write\sixt@@n} +% \end{macrocode} +% +% \begin{macrocode} +\newcommand{\patchcommand}[1]{% + \expandafter\patchcmd@a\meaning#1??->@\@nil#1% +} +% \end{macrocode} +% +% We begin by looking at the meaning string of the given token. We +% will issue an error message if the token is not a control sequence, +% if it is an undefined control sequence, or if it is a known control +% sequence but not a macro. +% \begin{macrocode} +\long\def\patchcmd@a#1#2#3->#4#5\@nil#6{% +%% \wrs{\string#6: [#1] [#2] [#3]->[#4]}% + \ifx @#4\relax \patchcmdError#6#1% + \expandafter\@gobbletwo % discard the other two arguments + \else + \if l#2\toks@{\patchcmd@e{}#6}% l in this position means \long + \else \toks@{\patchcmd@e*#6}% not \long + \fi +% \end{macrocode} +% Now \cs{patchcmd@b} will do further analysis to determine what +% kinds of arguments the macro takes. If it takes $n$ normal +% arguments, the digit $n$ (0--9) will be added to \cs{toks@}. +% \begin{macrocode} + \patchcmd@b #3@#4#5 ? ? ? \@nil#6% + \expandafter\the\expandafter\toks@ + \fi +} +% \end{macrocode} +% +% We handle robust commands by scanning the first two control words +% in the macro's definition to see if the second one is followed by +% two spaces. If it is, then arg 7 will be empty. In that case we +% compare the csname preceding the two spaces to the original +% argument of \cn{patchcommand}. If they are equal it is nearly certain +% that this is a robust command in normal \LaTeX{} form. In that case +% we call \cn{patchcommand} quasi-recursively on the protected control +% sequence with the extra space at the end of its name. +% \begin{macrocode} +\def\patchcmd@b#1:#2@#3#4 #5#6 #7 #8\@nil#9{% +%% \wrs{[#1] [#2] [#3] [#4] [#5] [#6] ARG7=[#7] [#8]}% + \if \ifx @#7@\expandafter + \ifx\csname #6\endcsname#9T\else F\fi\else F\fi T% + \toks@\expandafter{\expandafter\patchcommand\csname #6 \endcsname}% + \else + \ifx @#2@% No arguments + \toks@\expandafter{\the\toks@ 0}% + \else + \patchcmd@c 0#2{\string##}0% + \fi + \fi +} +% \end{macrocode} +% +% The task of \cs{patchcmd@c} is to iterate over \texttt{\#D} pairs, +% where D is a digit in the range 1--9, until reaching the last one. +% Whenever we find such a pair, we carry the digit forward for the +% next recursive call; but we use digit 0 as a marker to terminate +% the recursion. If any other character interrupts the \texttt{\#D} +% pattern, it means that this macro has some kind of delimited +% argument. +% \begin{macrocode} +\def\patchcmd@c#1#2#3{% + \if\string###2% % yes it's a # token + \ifodd 0#31 % and it's followed by a number + \if 0#3\patchcmd@d#1\fi % number=0? then we're done + \else \patchcmd@d D% # not a number: must be a delimited arg + \fi + \else \patchcmd@d D% not a # token: must be a delmited arg + \fi + \patchcmd@c#3% +} +% \end{macrocode} +% +% \begin{macrocode} +\def\patchcmd@d#1{% + \if D#1% + \PackageError{patchcmd}{Cannot change a macro that has + delimited arguments}\@ehd + \else + \toks@\expandafter{\the\toks@ #1}% + \fi + \begingroup + \aftergroup\@gobble + \let\patchcmd@c\endgroup +} +% \end{macrocode} +% +% \begin{macrocode} +\def\patchcmd@e#1#2#3#4#5{% + \begingroup + \edef\@##1{% + \@temptokena\noexpand\expandafter{% + \noexpand#2% + \ifnum#3>0 {####1}\ifnum#3>1 {####2}\ifnum#3>2 {####3}% + \ifnum#3>3 {####4}\ifnum#3>4 {####5}\ifnum#3>5 {####6}% + \ifnum#3>6 {####7}\ifnum#3>7 {####8}\ifnum#3>8 {####9}% + \fi\fi\fi\fi\fi\fi\fi\fi\fi + ##1% + }% + } + \@{#5}% + \edef\@##1{\endgroup + \noexpand\renewcommand#1\noexpand#2\ifcase#3 \else [#3]\fi + {##1\the\@temptokena}}% + \@{#4}% +%% \show#2% +} +% \end{macrocode} +% +% Two possible error messages. Optimized. Second arg is the first +% letter from the meaning string; it will be ``u'' if and only if the +% control sequence is undefined. +% \begin{macrocode} +\long\def\patchcmdError#1#2{% + \begingroup + \toks@{Not redefinable}% + \ifcat\relax\noexpand#1% Is it a control sequence? + \begingroup + \let#1=?\ifx ?\relax % Is it "\relax"? + \endgroup % accept current value of \toks@ + \else \endgroup +% \end{macrocode} +% +% This is equivalent to the \cs{@ifundefined} test (true if arg 2 is +% either undefined or its meaning is \cs{relax}). +% +% \begin{macrocode} + \if\ifx\relax#1u\else #2\fi u% + \toks@{Not defined}% + \fi + \fi + \fi +% \end{macrocode} +% Apply \cs{string} preemptively to arg 1 to prevent catastrophic +% failure if it happens to be \cs{par} (\cs{PackageError} isn't +% defined as \cs{long} in older versions of \LaTeX{}). +% \begin{macrocode} + \edef\@{\endgroup + \noexpand\PackageError{patchcmd}{% + \the\toks@: \string#1}\noexpand\@ehd}% + \@ +} +% \end{macrocode} +% +% The usual \cs{endinput} to ensure that random garbage at the end of +% the file doesn't get copied by \fn{docstrip}. +% \begin{macrocode} +\endinput +% \end{macrocode} +% +% \CheckSum{183} +% \Finale diff --git a/Master/texmf-dist/source/latex/patchcmd/patchcmd.ins b/Master/texmf-dist/source/latex/patchcmd/patchcmd.ins new file mode 100644 index 00000000000..be48ecd1e02 --- /dev/null +++ b/Master/texmf-dist/source/latex/patchcmd/patchcmd.ins @@ -0,0 +1,7 @@ +\def\batchfile{patchcmd.ins} +\input docstrip.tex +\preamble +\endpreamble +\keepsilent +\generateFile{patchcmd.sty}{f}{\from{patchcmd.dtx}{}} +\endinput -- cgit v1.2.3