% \iffalse
% Meta comment
%<*never>
\documentclass{ltxdoc}

\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\usepackage[frenchb,english]{babel}
\usepackage[]{geometry}

\IfFileExists{parallel.sty}{%
\usepackage{parallel}
}{%
\newenvironment{Parallel}[2]{}{}
\let\ParallelLText\empty
\let\ParallelRText\empty
\let\ParallelPar\empty
\def\nopar{}
}

\ifx\nopar\undefined
  \makeatletter
  \let\@old\ParallelCheckOpenBrace
  \def\ParallelCheckOpenBrace{\@old\linewidth=\hsize}
\fi
\newenvironment{ml}{\begin{Parallel}{.48\linewidth}{.48\linewidth}}{\end{Parallel}}
\def\eng{\selectlanguage{english}\ParallelLText}
\def\fra{\selectlanguage{frenchb}\ParallelRText}
\def\go{\ParallelPar}

\begin{document}
\DocInput{contextsw.dtx}
\end{document}
%</never>
% \fi
% 
% \title{\bfseries Context switching\\ Changement de contexte}
% \author{Benjamin \textsc{Bayart}\thanks{\texttt{bayartb@edgard.fdn.fr}}}
% \date{\today\\\selectlanguage{frenchb}\today}
% \maketitle
% 
% \def\contentsname{Contents\\Table des mati\`eres}
% \tableofcontents
% 
% \section{Foreword\\Pr\'esentation}
% 
% I'm French. I speak a few words of english. As most of the \TeX{} users
% are not french, I wrote (or tried to) the documentation in english.
% But this package is a bit tricky to use, with a lots of side effects,
% so I prefere to \emph{also} write the documentation in french. In case
% the french documentation states something, and the english one states
% the opposite, the french one is probably right, and you should send me an
% e-mail to help me improve my english.
% 
%    \begin{macrocode}
%<*package>
\ProvidesPackage{contextsw}[2003/11/20
    v1.0 Context switching for multi-defined macros]
%</package>
%    \end{macrocode}
% 
% \sloppy
% \begin{ml}
% \eng{%
% This package is mainly for \TeX{nicians}, good \TeX{nicians} who are
% weird enough to want to use to pieces of \TeX{} code that cannot work
% together.}
% 
% \fra{%
% Ce package est principalement pour les \TeX{niciens}, les bons
% \TeX{niciens}, qui sont des gens assez bizarres pour vouloir utiliser
% des bouts de code \TeX{} qui ne sont pas fait pour marcher ensemble.}
% \go
% 
% \eng{%
% E.g.: two \LaTeX{} packages that both provide a macro |\magicmacro|
% are not compatible. You can have several problems:
% \begin{itemize}
% \item They both use |\newcommand|, so the second you load will
% fail with an ``already defined macro'' error.
% \item They use more basic |\def|, so both will be loaded and only
% the second definition will be used: you cannot access the first one
% which is hidden.
% \item One define |\magicmacro| and the other define |\wizzardmacro|,
% but they both define |\wizzard@internal|: you will feel that both \emph{should}
% work, but in practice, only the second one will.
% \end{itemize}}
% 
% \fra{%
% Par exemple: deux package \LaTeX{} qui d\'efinissent tous les deux
% une macro |\magicmacro| ne sont pas compatibles. On pourra rancontrer
% plusieurs probl\`emes:
% \begin{itemize}
% \item Ils utilisent tous les deux |\newcommand|, le chargement du
% deuxi\`eme package \'echouera.
% \item Ils utilisent tous les deux |\def|, et donc les deux se chargeront
% bien, mais seule la d\'efinition du second sera retenue: on ne pourra
% pas acc\'eder au premier, qui se trouve cach\'e.
% \item L'un d\'efinit la macro |\magicmacro| et l'autre la macro |\wizzardmacro|,
% mais ils d\'efinissent tous les deux |\wizzard@internal|: on aura l'impression
% que les deux \emph{devraient} marcher, mais dans la pratique seul le second
% marchera.
% \end{itemize}}
% \go
% 
% \eng{%
% This package allows you to store various elements defined by a package
% (or anything alike), and to restore those at any moment.}
% 
% \fra{%
% Ce package permet de stocker diff\'erents \'el\'ements d\'efinis par
% un package (ou \'equivalent), et de les restaurer \`a tout moment.}
% \ParallelPar
% \go
% 
% \eng{%
% A short exemple:}
% 
% \fra{%
% Un exemple rapide:}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*example>
\newcontext{package1}
\newcontext{package2}
\usepackage{package1}
\repeatsavecmd{package1}{magicmacro,wizzard@internal}
\usepackage{package2}
\repeatsavecmd{package2}{magicmacro,wizzard@internel}
%</example>
%    \end{macrocode}
%
% \begin{ml}
% \eng{%
% \begin{enumerate}
% \item Define a new context for the package 1.
% \item Define a new context for the package 2.
% \item Load the package 1. Now, both macro |\magicmacro| and |\wizzard@internal|
% are defined.
% \item Store the two definitions in the context for package 1. Now both
% macros are undefined.
% \item Load the package 2. You load it in a ``virgin'' context, so a call
% to |\newcommand| will succeed. Now, both macros are defined with the
% definitions from package 2.
% \item Store the two definitions in the context for package 2. Now both
% macros are undefined.
% \end{enumerate}}
% 
% \fra{%
% \begin{enumerate}
% \item D\'efinition d'un nouveau contexte pour le package 1.
% \item D\'efinition d'un nouveau contexte pour le package 2.
% \item Chargement du package 1. Maintenant les deux macros |\magicmacro| et
% |\wizzard@internal| sont d\'efinies.
% \item Stockage des deux d\'efinitions dans le contexte pour le package 1.
% Maintenant les deux macros ne sont plus d\'efinies.
% \item Chargement du package 2. Ce chargement s'effectue dans un contexte
% <<~vierge~>>, donc un appel \`a |\newcommand| fonctionnera. Maintenant,
% les deux macros sont d\'efinies avec la d\'efinition du package 2.
% \item Stockage des deux d\'efinition dans le contexte du package 2.
% Maintenant, les deux macros ne sont plus d\'efinies.
% \end{enumerate}}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*example>
\forcontext{package1}
Use of \magicmacro from package 1
...
\forcontext{package2}
Use of \magicmacro from package 2
...
%</example>
%    \end{macrocode}
% 
% \section{Users guide\\Mode d'emploi}
% 
% \subsection{Context handling\\Gestion des contextes}
% 
% \begin{ml}
% \eng{%
% A context is created by |\newcontext|, which takes as argument the name of the
% context. It is recalled by |\forcontext| with the name of the
% context as argument, or by |\forXXX| where |XXX| is the name of the context.
% }
% 
% \fra{%
% Un contexte est cr\'ee par |\newcontext|, avec en argument le nom du
% contexte \`a cr\'eer. Il est rappel\'e par |\forcontext| avec le nom du
% contexte en argument, ou par |\forXXX| o\`u |XXX| est le nom du contexte.
% }
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*example>
\newcontext{one}
\newcontext{example1}
...
\forcontext{one}
\forcontext{example1}
\forone
\csname forexample1\endcsname % Ugly because 1 is not a letter
%</example>
%    \end{macrocode}
% 
% \begin{ml}
% \eng{%
% To see all the commands, chars, and tokens, saved in all the contexts,
% one can call |\showcontexts|.
% }
% 
% \fra{%
% Pour voir toutes les commandes, caract\`eres, et tokens, sauv\'es dans
% tous les contextes, on peut utiliser |\showcontexts|.
% }
% \go
% \end{ml}
% 
% \section{Implementation\\Impl\'ementation}
% 
% \subsection{General purpose macros\\Macros \`a usage g\'en\'eral}
% 
% \begin{macro}{\CSWaddto}
% \strut
% \begin{ml}
% \eng{%
% Copy/paste from babel, I don't want to require babel for this to
% work, even if babel is the main reason for this package to be
% written.}
% 
% \fra{%
% Copier/coller de babel, je ne souhaite pas rendre babel obligatoire
% pour ce package, m\^eme si babel est la principale cause de la
% n\'ecessit\'e de ce package.
% }
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\CSWaddto#1#2{%
  \ifx#1\@undefined
    \def#1{#2}%
  \else
    \ifx#1\relax
      \def#1{#2}%
    \else
      {\toks@\expandafter{#1#2}%
        \xdef#1{\the\toks@}}%
    \fi
  \fi
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\For}
% \strut
% \begin{ml}
% \eng{Loops for dummies.}
% \fra{Les boucles pour les nuls.}
% \go
% \end{ml}
%    \begin{macrocode}
%<*package>
\def\For#1#2{%
  \edef\infor{#2}%
  \expandafter\@for\expandafter#1\expandafter:\expandafter=\infor
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Initialisations}
% 
% \begin{ml}
% \eng{The first context: the kernel.}
% \fra{Le premier contexte: le noyau (kernel).}
% \go
% \end{ml}
% 
%    \begin{macrocode}
\def\all@contexts{kernel}
\def\forkernel{}
\def\CSWcmd@kernel{}
\def\CSWchar@kernel{}
\def\CSWtok@kernel{}
%    \end{macrocode}
% 
% \subsection{A new context\\Un nouveau contexte}
% 
% \begin{macro}{\newcontext}
% \strut
% \begin{ml}
% \eng{Builds-up a new empty contexte.}
% \fra{Cr\'ee un nouveau contexte vide.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\newcontext#1{%
  \CSWaddto\all@contexts{,#1}%
  \expandafter\def\csname for#1\endcsname{}%
  \expandafter\def\csname CSWcmd@#1\endcsname{}%
  \expandafter\def\csname CSWchar@#1\endcsname{}%
  \expandafter\def\csname CSWtok@#1\endcsname{}%
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Context switching\\Changement de contexte}
% 
% \begin{macro}{\forcontext}
% \strut
% \begin{ml}
% \eng{Restore all the commads saved for a context.}
% \fra{Rappelle toutes les commandes d'un contexte.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\forcontext#1{%
  \csname for#1\endcsname
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\cmdforcontext}
% \strut
% \begin{ml}
% \eng{Restore one macro saved in a context.}
% \fra{Rappelle une commande pr\'ecise d'un contexte pr\'ecis.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\cmdforcontext#1#2{%
  \restoreccmd#1.#2@CSW@
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\repeatcmdforcontext}
% \strut
% \begin{ml}
% \eng{Restore a list of macros saved in a context.}
% \fra{Rappelle une liste de commandes dans un contexte pr\'ecis.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\repeatcmdforcontext#1#2{%
  \For\cmd#2\do{%
    \cmdforcontext{#1}\cmd
  }
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Storable chars\\Caract\`eres prot\'egeables}
% 
% \begin{ml}
% \eng{%
% For each of these chars that we want to be able to save, the procedure
% is the same: we make it active, and we define a macro |\saveX| where
% |X| is the char to save. This macro will store the definition of the
% active char in |\CSWtmp|. Next, we define a macro |\resetX| that takes
% another macro as argument (in this macro is stored the original definition
% of the active char), and which will restore the definition to the
% active char.}
%
% \fra{%
% Pour chacun des caract\`eres que l'on souhaite sauvegarder, la proc\'edure
% est la m\^eme: on le rend actif et on d\'efinit une macro |\saveX| o\`u
% |X| est le caract\`ere que l'on souhaite sauver. Cette macro copie la
% d\'efinition du caract\`ere actif dans |\CSWtmp|. Ensuite on d\'efinit
% une macro |\resetX| qui prend en argument une macro (dans laquelle est
% la d\'efinition originale associ\'ee au caract\`ere actif), et restaure 
% sa d\'efinition au caract\`ere actif.}
% \end{ml}
% 
% \begin{macro}{\CSWsavablechar}
% \strut
% \begin{ml}
% \eng{
% The macro |\CSWsavablechar| takes one argument (the char |X|), begins
% a group, set |X|'s catcode to be active, and call |\CSW@savablechar|
% which in turn takes an argument (the char |X|, with the new catcode)
% and defines the two macros |\saveX| and |\resetX| and ends the group. All of this is because
% the catcode of a char is assigned when the char is \emph{read} and not
% when the char is \emph{used}. If the current catcode of |X| is $n$ (supposing
% active catcode is $a$), a simple definition can be:}
%
% \fra{%
% La macro |\CSWsavablechar| prends un argument (le caract\`ere |X|), commence
% un groupe, positionne le catcode de |X| \`a \emph{actif}, et appelle
% |\CSW@savablechar| qui \`a son tour prends un argument (le caract\`ere |X|,
% avec le nouveau catcode), d\'efinit les deux macros |\saveX| et |\resetX|
% et termine le groupe. Ce double appel parce que le catcode d'un caract\`ere
% lui est assign\'e quand il est \emph{lu} et pas quand il est \emph{utilis\'e}.
% Si le catcode courrant de |X| est $n$ (supposant que \emph{actif} soit $a$),
% une d\'efinition simple pourrait \^etre:}
% \go
% \end{ml}
%    \begin{macrocode}
%<*example>
\expandafter\def\csname save\string X\endcsname{\let\CSWtmp=X}
\expandafter\def\csname reset\string X\endcsname#1{%
  \exoandafter\let\expandafter X\csname#1\endcsname}
%</example>
%    \end{macrocode}
% 
% \begin{ml}
% \eng{%
% Which would put into the definition of |\saveX| something like
% |\let\CSWtmp=X|$_n$ instead of |\let\CSWtmp=X|$_a$, which
% is wrong (one cannot |\let| a macro equal a non-active char).
% And into |\resetX| something like |\let X|$_n$|=\macro| instead
% of |\let X|$_a$|=\macro| which is also wrong (one cannot |\let|
% a non-active char). So it is required to change the catcode of
% |X| \emph{before} to read it in the definition of the macros.}
% 
% \fra{%
% Qui d\'efinit le contenu de |\saveX| avec la forme |\let\CSWtmp=X|$_n$
% au lieu de |\let\CSWtmp=X|$_a$, ce qui est mauvais (on ne peut pas
% |\let|er \`a une macro un caract\`ere non-actif). Et |\resetX| aurait
% un contenu de l'ordre de |\let X|$_n$|=\macro| au lieu de
% |\let X|$_a$|=\macro|, ce qui est \'egalement mauvais (on ne peut
% pas |\let|er un caract\`ere non-actif). Il est donc n\'ecessaire de
% changer le code de cat\'egorie de |X| \emph{avant} de le lire dans
% le corps de la d\'efinition.}
% \go
% 
% \eng{%
% This is why we proceed in two times: first read |X| with the possibly wrong
% catcode, change the catcode, and then re-read it with the good catcode. All
% of this is in a group to ensure the change to the catcode is local.}
% 
% \fra{%
% C'est pourquoi on proc\`ede en deux temps: on lit une premi\`ere fois |X|
% (avec un catcode probablement pas actif) pour en changer le catcode (et le
% rendre actif), ensuite de quoi on le re-lit une seconde fois avec
% le bon catcode cette fois-ci. Enfin, tout cela est enserr\'e dans un
% groupe pour garantir que le changement de catcode est local au groupe.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\CSWsavablechar#1{%
  \bgroup\catcode`#1=\active
  \CSW@savablechar
}
\def\CSW@savablechar#1{%
    \expandafter\global
    \expandafter\def
      \csname save\string#1\endcsname{\let\CSWtmp#1}%
    \expandafter\global
    \expandafter\def
      \csname reset\string#1\endcsname##1{%
        \expandafter\let\expandafter#1\csname ##1\endcsname}%
  \egroup
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{ml}
% \eng{%
% This package only plan to save those chars in contexts, but it can easyli
% be extended. We take special care of |@| for it not to be read as part
% of the command name (a simple extra space is enough).}
% 
% \fra{%
% Ce package ne pr\'evoit de sauver les d\'efinitions que de ces caract\`eres
% l\`a dans les contextes, mais on peut facilement \'etendre la liste.
% On fait particuli\`erement attention \`a |@| pour qu'il ne soit pas
% pris dans le nom de la macro (un simple espace suffit \`a s'en pr\'emunir).}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\CSWsavablechar""
\CSWsavablechar``
\CSWsavablechar[[
\CSWsavablechar]]
\CSWsavablechar<<
\CSWsavablechar>>
\CSWsavablechar @@
\CSWsavablechar--
\CSWsavablechar==
\CSWsavablechar||
\CSWsavablechar++
%%</package>
%    \end{macrocode}
% 
% \subsection{Store debug informations\\Garder des infos de debug}
% 
% \begin{macro}{\contextpush}
% \strut
% \begin{ml}
% \eng{%
% To keep lists of stored elements, only for debug display.}
% 
% \fra{%
% Pour garder des traces de ce qu'on fait, uniquement pour affichage.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\contextpush#1#2#3{%
  \expandafter\ifx\csname CSW#3@#1\endcsname\relax
    \PackageError{contextsw}{Unknown context #1}{}%
  \else
    \expandafter\ifx\csname CSW#3@#1\endcsname\empty
      \expandafter\CSWaddto\csname CSW#3@#1\endcsname{#2}%
    \else
      \expandafter\CSWaddto\csname CSW#3@#1\endcsname{,#2}%
    \fi
  \fi
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\contextpushchar}
% \strut
% \begin{ml}
% \eng{%
% Add a char in the context list.}
%
% \fra{%
% Ajoute un caract\`ere \`a la liste du contexte.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\contextpushchar#1#2{%
  \contextpush{#1}{#2}{char}%
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\contextpushcmd}
% \strut
% \begin{ml}
% \eng{%
% Add a macrocommand to the context list.}
%
% \fra{%
% Ajout une macro \`a la liste du contexte.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\contextpushcmd#1#2{%
  \contextpush{#1}{#2}{cmd}%
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \begin{macro}{\contextpushtok}
% \strut
% \begin{ml}
% \eng{%
% Add a toks register to the context list.}
% 
% \fra{%
% Ajoute un registre toks \`a la liste du contexte.}
% \go
% \end{ml}
%    \begin{macrocode}
%<*package>
\def\contextpushtok#1#2{%
  \contextpush{#1}{#2}{tok}%
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Debug display\\Affichage pour debug}
% 
% \begin{macro}{\showcontexts}
% \strut
% \begin{ml}
% \eng{%
% Lists all the macros, toks, and chars, for all the contexts.
% When one call this commands, it displays all the chars, toks, and commands
% that have been stored in the context. Usefull for debug pupose when one
% wonder what have been stored in a context.}
% 
% \fra{%
% Liste toutes les commandes, tokens, et caract\`eres, de tous les contextes.
% Quand cette commande est appel\'ee, elle affiche la liste de tous les caract\`eres,
% registres toks, et macros, qui ont \'et\'e stock\'es dans ce contexte. Tr\`es
% pratique pour d\'ebuguer quand on se demande ce qui a \'et\'e stock\'e dans
% un contexte.
% }
% \go
% \end{ml}
%    \begin{macrocode}
%<*package>
\def\showcontexts{%
  \For\ctx\all@contexts\do{%
    \typeout{Context \ctx:}%
    \For\ctxcmd{\csname CSWcmd@\ctx\endcsname}\do{%
      \typeout{    command \ctxcmd}%
    }
    \For\ctxchar{\csname CSWchar@\ctx\endcsname}\do{%
      \typeout{    char \ctxchar}%
    }
    \For\ctxtok{\csname CSWtok@\ctx\endcsname}\do{%
      \typeout{    tok \ctxtok}%
    }
  }
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsection{Storing\\Sauver}
% 
% \subsubsection{Storing a macro\\Sauver une commande}
% 
% \begin{macro}{\savecmd}
% \strut
% \begin{ml}
% \eng{%
% To save a macro in a context.}
% 
% \fra{%
% Pour sauver une commande dans un contexte.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\savecmd#1#2{%
  \contextpushcmd{#1}{#2}%
  \expandafter\expandafter\expandafter\let
    \expandafter\expandafter\csname#1.#2\endcsname
    \csname#2\endcsname
  \expandafter\let\csname#2\endcsname\undefined
  \expandafter\CSWaddto\csname for#1\endcsname{\restoreccmd#1.#2@CSW@}}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Storing a toks register\\Sauver un registre toks}
% 
% \begin{macro}{\savetok}
% \strut
% \begin{ml}
% \eng{%
% To save a toks register in a contexte.}
% 
% \fra{%
% Pour sauver un registre toks dans un contexte.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\savetok#1#2{%
  \contextpushtok{#1}{#2}%
  \expandafter\xdef\csname toks#1.#2\endcsname
    {\expandafter\the\csname #2\endcsname}%
  \expandafter\CSWaddto\csname for#1\endcsname{\restoretok #1.#2@@}}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Storing a char\\Sauver un caract\'ere}
% 
% \begin{macro}{\savechar}
% \begin{macro}{\activeCSWcat}
% \begin{macro}{\activeCSWmath}
% \strut
% \begin{ml}
% \eng{%
% Harder, to save a char in a context.}
% 
% \fra{%
% Plus dur, pour sauver un caract\`ere dans un contexte.}
% \go
% 
% \eng{%
% We first store the definition of an active char and of an
% active mathchar.}
% 
% \fra{%
% En premier lieu on stocke la d\'efinition d'un caract\`ere
% actif et d'un caract\`ere actif en mode math.}
% \go
% \end{ml}
% 
%    \begin{macrocode}
%<*package>
\def\activeCSWcat{13}
\def\activeCSWmath{32768}
%    \end{macrocode}
% \begin{ml}
% \eng{First step, add to the context list for display.}
% \fra{Premi\`ere \'etape, ajouter \`a la liste du contexte pour affichage.}
% \go
% \end{ml}
%    \begin{macrocode}
\def\savechar#1#2{%
  \contextpushchar{#1}{\string#2}%
  \typeout{Je sauve le caractere \string#2 dans le contexte #1}
%    \end{macrocode}
% \begin{ml}
% \eng{Next, check that the package is tuned to store this char.}
% \fra{Ensuite, v\'erifier que le package est pr\'evu pour stocker
% ce caract\`ere.}
% \go
% \end{ml}
%    \begin{macrocode}
  \ifx\csname save\string#2\endcsname\undefined
    \PackageError{contextsm}{Le caractere \string#2 ne peut etre sauve}{}
  \fi
%    \end{macrocode}
% \begin{ml}
% \eng{Store the catcode and the mathcode.}
% \fra{Sauve le catcode et le mathcode.}
% \go
% \end{ml}
%    \begin{macrocode}
%  \showthe\catcode`#2
%  \showthe\mathcode`#2
  \expandafter\edef\csname catcode.#1.\string#2\endcsname{\the\catcode`#2}%
  \expandafter\edef\csname mathcode.#1.\string#2\endcsname{\the\mathcode`#2}%
%  \expandafter\show\csname catcode.#1.\string#2\endcsname
%  \expandafter\show\csname mathcode.#1.\string#2\endcsname
%    \end{macrocode}
% \begin{ml}
% \eng{%
% If the char is active in text mode, save it. If so, the same definition
% is available in math mode.}
% 
% \fra{%
% Si le caract\`ere est actif en mode texte, on le sauve. Si tel est le
% cas, sa d\'efinition est la m\^eme en mode math.}
% \go
% \end{ml}
%    \begin{macrocode}
  \expandafter\ifx\csname catcode.#1.\string#2\endcsname\activeCSWcat
    \typeout{Actif en mode texte, je sauve}
    \expandafter\let\csname char.#1.\string#2\endcsname#2
    \expandafter\CSWaddto\csname for#1\endcsname{\restorechar#1.#2AA}%
  \else
%    \end{macrocode}
% \begin{ml}
% \eng{%
% If the char is not active in texte mode, it might be active only
% in math mode, in such a case, save it.}
% \fra{%
% Si le caract\`ere n'est pas actif en mode texte, il peut l'\^etre tout
% de m\^eme en mode math. En pareil cas, le sauver.}
% \go
% \end{ml}
%    \begin{macrocode}
    \expandafter\ifx\csname mathcode.#1.\string#2\endcsname\activeCSWmath
      \typeout{Actif en mode math seulement, je sauve}
      \csname save#2\endcsname
%      \show\CSWtmp
      \expandafter\let\csname mathchar.#1.\string#2\endcsname\CSWtmp
      \expandafter\CSWaddto\csname for#1\endcsname{\restoremathchar#1.#2AA}%
    \else
%    \end{macrocode}
% \begin{ml}
% \eng{%
% If the char if neither active in text mode, nor in math mode, then
% the only thing to save is its codes (math and text).}
% \fra{%
% Si le caract\`ere n'est actif ni en mode texte, ni en mode math, alors
% la seule chose \`a sauver est son code (catcode et mathcode).}
% \go
% 
% \eng{%
% \emph{This heuristic might prove wrong later, since a char can be
% active on demand: have a non-active catcode, but have a definition
% attached to it when active, with an auxiliary macro to activate it
% when needed. I never had to save such definitions, so it is not
% implemented here, anyway, it can be done easily.}}
% \fra{%
% \emph{Cette heuristique pourrait bien s'av\'erer \^ete un mauvais choix
% un jour, puisqu'un caract\`ere pourrait \^etre actif occasionnellement:
% avoir un code non-actif en temps normal, mais avoir tout de m\^eme une
% d\'efinition qui lui soit rattach\'ee quand il est actif, avec une macro
% auxiliaire qui se charge de l'activer quand c'est utile. Je n'ai jamais
% crois\'e un cas de ce type l\`a qui ait n\'ecessit\'e une protection,
% donc je ne l'ai pas impl\'ement\'e ici. De toutes fa\c{c}ons, ce serait
% simple \`a faire.}}
% \go
% \eng{%
% \emph{Such a case would, anyway, be a proof of illness from the package's
% author: it is a very smart thing not to let a char be active all the time,
% but it is weird, when doing so, not to set it it's definition when it is
% activated. Such a case should probably require a bug-report to the author
% of the original package.}}
% \fra{%
% \emph{Un cas de ce type l\`a serait cependant un preuve de bizarrerie de la
% part de l'auteur du package original: c'est une choix tr\`es fut\'e de
% n'activer les caract\`eres que quand c'est indispensable (\emph{i.e.} \`a
% la demande), mais dans ce cas l\`a, c'est bien curieux de ne pas lui affecter sa d\'efinition
% lors de son activation. Un cas semblable m\'eriterait  probablement un
% rapport de bug \`a l'auteur du package original.}}
% \go
% \end{ml}
%    \begin{macrocode}
      \typeout{Pas specialement actif, je remets les codes}
      \expandafter\CSWaddto\csname for#1\endcsname{\restorecatcode#1.#2AA}%
    \fi
  \fi
%    \end{macrocode}
% That's all :-)
%    \begin{macrocode}
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% 
% \subsection{Restoring\\Restauration}
% 
% \subsubsection{Restoring an inactive char\\Restaurer un caract\`ere inactif}
% 
% \begin{macro}{\restorecatcode}
%    \begin{macrocode}
\def\restorecatcode#1.#2AA{%
%  \expandafter\show\csname catcode.#1.\string#2\endcsname
%  \expandafter\show\csname mathcode.#1.\string#2\endcsname
  \catcode`#2\expandafter=\csname catcode.#1.\string#2\endcsname
  \mathcode`#2\expandafter=\csname mathcode.#1.\string#2\endcsname
}
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Restoring a text active char\\Restaurer un caract\`ere actif en mode texte}
% 
% \begin{macro}{\restorechar}
%    \begin{macrocode}
%<*package>
\def\restorechar#1.#2AA{%
  \csname reset#2\endcsname{char.#1.\string#2}%
%  \expandafter\show\csname catcode.#1.\string#2\endcsname
%  \expandafter\show\csname mathcode.#1.\string#2\endcsname
%  \expandafter\show\csname char.#1.\string#2\endcsname
  \catcode`#2\expandafter=\csname catcode.#1.\string#2\endcsname
  \mathcode`#2\expandafter=\csname mathcode.#1.\string#2\endcsname
%  \expandafter\let\expandafter#2\csname char.#1.\string#2\endcsname
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Restoring a math active char\\Restaurer un caract\`ere actife en mode math}
% 
% \begin{macro}{\restoremathchar}
%    \begin{macrocode}
%<*package>
\def\restoremathchar#1.#2AA{%
  \catcodeOK
  \csname reset#2\endcsname{mathchar.#1.\string#2}%
%  \expandafter\show\csname catcode.#1.\string#2\endcsname
%  \expandafter\show\csname mathcode.#1.\string#2\endcsname
%  \expandafter\show\csname mathchar.#1.\string#2\endcsname
%  {\catcode`#2=\active
%   \expandafter\global
%   \expandafter\let
%   \expandafter#2\csname mathchar.#1.\string#2\endcsname}
  \catcode`#2\expandafter=\csname catcode.#1.\string#2\endcsname
  \mathcode`#2\expandafter=\csname mathcode.#1.\string#2\endcsname
  \catcodeKO
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Restoring a macro\\Restaurer une commande}
% 
% \begin{macro}{\restorecmd}
%    \begin{macrocode}
%<*package>
\def\restorecmd#1{\expandafter\restoreccmd\string#1@CSW@}
\def\restoreccmd#1.#2@CSW@{%
  \expandafter\expandafter\expandafter\let
  \expandafter\expandafter\csname#2\endcsname\csname#1.#2\endcsname}
\def\repeatsavecmd#1#2{\rrepeatsavecmd{#1}#2,*}
\def\rrepeatsavecmd#1#2,#3*{\savecmd{#1}{#2}%
  \ifthenelse{\equal{}{#3}}{}{\rrepeatsavecmd{#1}#3*}}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \subsubsection{Restoring a toks register\\Restaurer un registre toks}
% 
% \begin{macro}{\restoretok}
%    \begin{macrocode}
%<*package>
\def\restoretok #1.#2@@{%
  \expandafter\expandafter\csname #2\endcsname
  \expandafter\expandafter\expandafter{\csname toks#1.#2\endcsname}%
}
%</package>
%    \end{macrocode}
% \end{macro}
% 
% \end{document}
