%%% ====================================================================
%%% @LaTeX-doc-source-file{
%%%   filename  = "pcatcode.dtx",
%%%   version   = "1.03",
%%%   date      = "2002/02/21",
%%%   time      = "10:31:35 EST",
%%%   author    = "Michael J Downes",
%%%   copyright = "Copyright 2001 American Mathematical Society",
%%%   address   = "American Mathematical Society,
%%%                Publications Technical Group,
%%%                PO Box 6248,
%%%                Providence, RI 02940,
%%%                USA",
%%%   email     = "tech-support@ams.org",
%%%   URL       = "http://www.ams.org/",
%%%   abstract  = "The pcatcode package changes LaTeX package loading
%%%                internals so that all subsequently loaded packages
%%%                can rely on having normal catcodes in effect.",
%%%   license   = "Artistic",
%%%   checksum  = "10622 349 1416 12894",
%%%   docstring = "The checksum field, produced by Robert Solovay's
%%%                checksum utility, gives CRC-16 checksum, lines,
%%%                words, and characters.",
%%%  }
%%% ====================================================================
% \iffalse
%<*driver>
\documentclass{amsdtx}
%\usepackage{pcatcode}\relax
\begin{document}
\title{The \pkg{pcatcode} package}
\author{Michael~J. Downes\\American Mathematical Society}
\date{Version \fileversion, \filedate}
\hDocInput{pcatcode.dtx}
\end{document}
%</driver>
% \fi
%
% \maketitle
% \section{Introduction}
%
%    The \pkg{pcatcode} package provides mechanisms for robustly
%    changing the catcode environment for the duration of a package and
%    restoring it afterwards to whatever it was before the package was
%    loaded.
%
%    Motivation: The \pkg{amsmath} package (for example), makes a number
%    of assignments using characters such as double-quote and
%    left-quote, because these are hard-wired into the \tex/ syntax for
%    numbers and other things. If a package that makes double-quote an
%    active character is loaded before \pkg{amsmath}, all the
%    statements that use double-quote turn into error messages.
%
%    But now! Groan and grumble no more, ye package writers, for putting
%    a magical invocation of the pcatcode package at the beginning of
%    your package file, as shown here, will ensure that your
%    package contents will be processed with completely normal catcodes.
%\begin{verbatim}
%\NeedsTeXFormat{LaTeX2e}[1995/12/01]
%\@ifundefined{PushCatcodes}{%
%  \RequirePackage{pcatcode}\relax\PushCatcodes\NormalCatcodes
%}{}
%\ProvidesPackage{foo}[2002/02/21 v1.03]
%\end{verbatim}
%
%    WARNING: This functionality would work best if it were built into
%    the \LaTeX{}2e kernel, but it cannot be usefully added to the
%    kernel now without adversely affecting document compatibility
%    across different systems. This package therefore modifies one or
%    two of the low-level package-loading functions defined by the
%    kernel. This means that there may be trouble if any other package,
%    or some future version of \LaTeX{}, changes the definitions of
%    those functions.
%
%    NOTE: Packages that do not call \cs{PushCatcodes}
%    \cs{NormalCatcodes} will remain transparent to the external catcode
%    environment in the usual way (i.e., for all characters except the
%    \verb'@' character).
%
% \StopEventually{}
%
% \section{Implementation}
%    Standard declaration of package name and date is postponed for
%    reasons that are self-evident, albeit perhaps not obviously so.
%
%    At the document level, we assume that the following characters
%    always have their standard catcode:
% \begin{center}
% \begin{tabular}{lp{.75\columnwidth}}
% \verb'\{}' & for commands and arguments\\
% \verb'%' & for comments\\
% \verb'#' & for use with \cn{newcommand}\\
% \verb'*' & cannot be changed without breaking star-form commands\\
% \verb'[]' & cannot be changed without breaking optional arguments\\
% \verb'~' & already active, no reason to change catcode
% \end{tabular}
% \end{center}
%
%    One might think that we could assume hyphen, period (and comma, for
%    European decimal notation) are always catcode 12. Experience has
%    shown, however, that for just about every character there is some
%    plausible application that would be facilitated by making that
%    character active and giving it a complex definition. Surely hyphen
%    and period must stay catcode 12 in order to work in statements like
%    the following?
%\begin{verbatim}
%\addtocounter{section}{-1}
%\addtolength{\columnwidth}{-1.5cm}
%\end{verbatim}
%    Yet hyphen and period are important constituents of ordinary text
%    and therefore special applications arise. For example,
%    what if you would like
%    mdashes to be surrounded by extra space but your authors prefer to
%    continue writing \verb'---' in the accustomed manner?
%
%    Theoretically speaking, the \pkg{pcatcode} package itself has to
%    guard against the kind of catcode problems that it is intended to
%    circumvent. If you would like a nice little \tex/nician's
%    exercise, try your hand, before looking at the code below, at the
%    task that I set for myself: Find the minimal set of catcode
%    assumptions that one has to make before attempting to establish
%    normalcy, where normalcy is defined as the state at the end of
%    \fn{latex.ltx}, just before the last \cs{makeatother}. This is the
%    state that may normally be expected at the beginning of a
%    documentclass file, if the \LaTeX{} format file does not have any
%    extensions (e.g., babel) compiled in.
%
%    Ready to look, now?
%
%    In order for the following code to work it is only necessary that
%    backslash, letters, and digits have their normal catcodes: 0, 11,
%    12 respectively. One could argue that if \fn{pcatcode.sty} is
%    invoked through a standard \cs{RequirePackage} call, it can be
%    assumed that curly braces also have their normal catcodes. But I
%    suppose it is not utterly inconceivable that in some special
%    circumstances one might want to load the package with the
%    \cs{@@input} primitive, sans braces. And in any case the extra
%    overhead to handle braces as well is trivial so for esthetic
%    reasons I'm gonna put it in.
%
%    If you look really hard you'll find one or two other assumptions,
%    such as ``endlinechar is not a letter''. Wait, come to think of it,
%    I can fix that \ldots
%
%    The purpose of the group is chiefly to localize the temporarily
%    changed definitions of \cs{e}, \cs{n}, etc.
%    \begin{macrocode}
\begingroup\let\e\endlinechar\iffalse\
\fi\chardef\E\e\e13\chardef\n\catcode\e\catcode\e5\relax\relax
\chardef\s\catcode32\chardef\t10\catcode32\t
\chardef\c\catcode37 \catcode37 14 % percent
\chardef\=\catcode61 \catcode61 12 % equal sign
\chardef\l=\catcode123 \catcode123=1 % left brace
\chardef\r=\catcode125 \catcode125=2 % right brace
\chardef\[=\catcode91 \catcode91=12 % left bracket
\chardef\]=\catcode93 \catcode93=12 % right bracket
\chardef\.=\catcode46 \catcode46=12 % period
\chardef\/=\catcode47 \catcode47=12 % slash
\edef\c{%
  \endgroup
  \def\noexpand\pcat@restore{%
    \catcode\number\e=\number\n \catcode32=\number\s
    \catcode123=\number\l \catcode125=\number\r
    \catcode37=\number\c \catcode61=\number\=%
    \catcode91=\number\[\catcode93=\number\]%
    \catcode46=\number\.\catcode47=\number\/%
    \endlinechar=\number\E \relax
  }%
}
\c
\endlinechar13\catcode13\string=5\relax\relax
\catcode32\string=10 \catcode37 14\relax\relax
\catcode61 12\catcode123=1\catcode125=2\catcode91=12\catcode93=12\relax
\catcode46=12\catcode47=12\relax
%    \end{macrocode}
%
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{pcatcode}[2002/02/21 v1.03]
%    \end{macrocode}
%
%    \begin{macrocode}
\def\NormalCatcodes{%
  \endlinechar=13%
  \catcode33=12\catcode34=12\catcode35=6\catcode36=3\catcode37=14%
  \catcode38=4\catcode39=12\catcode40=12\catcode41=12\catcode42=12%
  \catcode43=12\catcode44=12\catcode45=12\catcode46=12\catcode47=12%
  \catcode58=12\catcode59=12\catcode60=12\catcode61=12\catcode62=12%
  \catcode63=12\catcode91=12\catcode92=0\catcode93=12\catcode94=7%
  \catcode95=8\catcode96=12\catcode123=1\catcode124=12\catcode125=2%
  \catcode126=13\catcode32=10\catcode13=5\catcode9=10\catcode10=12%
  \relax
}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\@pushfilename{%
  \PushCatcodes \NormalCatcodes
  \xdef\@currnamestack{%
    {\@currname}{\@currext}{\the\catcode64 }%
    \@currnamestack
  }%
}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\@p@pfilename#1#2#3#4\@nil{%
  \gdef\@currname{#1}\gdef\@currext{#2}%
  \PopCatcodes \catcode64=#3\relax
  \gdef\@currnamestack{#4}%
}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\CatcodeStack{}
%    \end{macrocode}
%
%    Notably absent from the following list: the \verb'@' character and
%    whitespace characters. The former is already handled in the
%    \LaTeX{} kernel, and I hesitate to interfere with its current
%    catcode transitions.
%    \begin{macrocode}
\begingroup \escapechar=\m@ne \let\s\string
\xdef\pcat@otherchars{%
  \s\!\s\"\s\#\s\$\s\%\s\&\s\'\s\(\s\)\s\*\s +\s\,\s\-\s\.\s\/\s\:%
  \s\;\s\<\s\=\s\>\s\?\s\[\s\\\s\]\s\^\s\_\s\`\s\{\s\|\s\}\s\~%
}
\endgroup
\gdef\PushCatcodes{%
  \xdef\CatcodeStack{%
    \expandafter\PushCat@a\pcat@otherchars\ \
    \^^I\^^J{T \@gobbletwo}\@empty
    \relax
    {\CatcodeStack}}%
}
\def\PushCat@a#1{\catcode\number`#1=\number\catcode`#1 \PushCat@a}
\def\PopCatcodes{\expandafter\PopCat@a\CatcodeStack}
\def\PopCat@a#1#{#1\xdef\CatcodeStack}
%    \end{macrocode}
%
%    For code that does futureletting to see if a punctuation character
%    follows, it is distressing to handle the case when some characters
%    might be made active (e.g., by the babel package).
%
%    The \cs{FutureLetSetup} function attempts to minimize the
%    difficulties by defining canonical control sequences to represent
%    all the visible ASCII characters (i.e., ranging from space to
%    \qc{\~}, 32--126, plus TAB) whose catcode could be changed without
%    transgressing the limits of standard \LaTeX{} syntax.
%    \begin{macrocode}
\begingroup\pcat@restore
\begingroup
\catcode`\3="3 \catcode`\4="4 \catcode`\7="7 \catcode`\8="8
\catcode`\A="A \catcode`\B="B \catcode`\C="C \catcode`\D="D
\gdef\fls@let#1#2{%
  \ifx\@@undefined#1\else\errmessage{\string#1 already defined}\fi
  \begingroup
  \lccode`\3=`#2\lccode`\7=`#2\lccode`\8=`#2%
  \lccode`\B=`#2\lccode`\C=`#2\lccode`\D=`#2\relax
  \ifnum\catcode`#2=\active
    \def\do##1{\noexpand\do\noexpand##1\noexpand}%
    \lowercase{%
      \xdef\fls@active@characters{%
        \fls@active@characters
        \do#1D}%
    }%
  \fi
  \aftergroup\global \aftergroup\let \aftergroup#1\aftergroup=%
  \lowercase{\aftergroup} %
  \lowercase{\expandafter\endgroup
    \ifcase\catcode`#2 %
      0\or \bgroup\or \egroup\or 3\or 4\or 5\or 6\or 7\or 8\or 9\or
      \@sptoken\or B\or C\else D\fi
  }%
}
\endgroup
%    \end{macrocode}
%    \cs{dl@@dblquote} means ``document-level double quote'': a
%    character token number 34 that has the catcode which is in effect
%    at \verb'\begin{document}' for double quotes.
%    \begin{macrocode}
\gdef\FutureLetSetup{%
  \gdef\fls@active@characters{}%
%    \end{macrocode}
%    This will normally be the same as \cs{@sptoken}.
%    \begin{macrocode}
  \fls@let\dl@@space\ %
  \fls@let\dl@@exclam\!%
  \fls@let\dl@@dblquote\"%
  \fls@let\dl@@hash\#%
  \fls@let\dl@@dollar\$%
%    \end{macrocode}
%    At document level, this cannot occur as a separate token.
%    \begin{macrocode}
%  \fls@let\dl@@percent\%%
  \fls@let\dl@@ampersand\&%
  \fls@let\dl@@rquote\'%
  \fls@let\dl@@lparen\(%
  \fls@let\dl@@rparen\)%
  \fls@let\dl@@star\*%
  \fls@let\dl@@plus\+%
  \fls@let\dl@@comma\,%
  \fls@let\dl@@hyphen\-%
  \fls@let\dl@@period\.%
  \fls@let\dl@@slash\/%
  \fls@let\dl@@colon\:%
  \fls@let\dl@@semicolon\;%
  \fls@let\dl@@less\<%
  \fls@let\dl@@equal\=%
  \fls@let\dl@@greater\>%
  \fls@let\dl@@question\?%
  \fls@let\dl@@lbracket\[%
%    \end{macrocode}
%    At document level, this cannot occur as a separate token.
%    \begin{macrocode}
%  \fls@let\dl@@backslash\\%
  \fls@let\dl@@rbracket\]%
  \fls@let\dl@@hat\^%
  \fls@let\dl@@underscore\_%
  \fls@let\dl@@lquote\`%
%    \end{macrocode}
%    Here one would normally use \cs{bgroup}.
%    \begin{macrocode}
  \fls@let\dl@@lbrace\{%
  \fls@let\dl@@vert\|%
%    \end{macrocode}
%    Here one would normally use \cs{egroup}.
%    \begin{macrocode}
  \fls@let\dl@@rbrace\}%
  \fls@let\dl@@tilde\~%
}
\AtBeginDocument{\FutureLetSetup}
%    \end{macrocode}
%
%    \begin{macrocode}
\gdef\FutureLetReset{%
  \def\do##1##2{\let##1= ##2}%
  \fls@active@characters
  \let\do\relax
}
\endgroup
%    \end{macrocode}
%
%    \begin{macrocode}
\endinput\pcat@restore\PushCatcodes
%    \end{macrocode}
%
% \CheckSum{491}
% \Finale
