%%% ====================================================================
%%% @LaTeX-doc-source-file{
%%%   filename  = "ifoption.dtx",
%%%   version   = "1.02",
%%%   date      = "2002/03/04",
%%%   time      = "16:33:16 EST",
%%%   author    = "Michael J Downes",
%%%   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  = "",
%%%   checksum  = "06695 170 563 5432",
%%%   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}
\providecommand{\mdash}{\textemdash}
\newcommand{\xt}[1]{\texttt{#1}}
\providecommand{\qq}[1]{``#1''}
\providecommand{\lat}[1]{\protect\LaTeX{}}
\begin{document}
\title{The \pkg{ifoption} package}
\author{Michael~J. Downes\\American Mathematical Society}
\date{Version \fileversion, \filedate}
\hDocInput{ifoption.dtx}
\end{document}
%</driver>
% \fi
%
% \maketitle
% \section{Introduction}
%
%    The \pkg{ifoption} package provides an \cn{IfOption} command that
%    has certain advantages over the \cs{@ifpackagewith} command\mdash
%    e.g., default options specified with \cs{ExecuteOptions} test as
%    true rather than false. In order for this to work properly,
%    mutually exclusive options should be specified with
%    \cs{DeclareExclusiveOptions}, another command defined by the
%    \pkg{ifoption} package.
% \StopEventually{}
%
% \section{Implementation}
% \subsection{Package info}
%
%    Standard declaration of package name and date.
%    \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{ifoption}[2002/03/04 v1.02]
%    \end{macrocode}
%
% \subsection{Some utility functions}
%
%    \begin{macrocode}
\let\@xp\expandafter \let\@nx\noexpand
%    \end{macrocode}
%
%    \begin{macrocode}
\def\@True{00}
\def\@False{01}
%    \end{macrocode}
%
% \subsection{Background}
%    See the definitions of \cs{@onefilewithoptions} and
%    \cs{@pushfilename} in the \lat/ kernel.
%
%    When we have
%\begin{verbatim}
%\DeclareOption{foo}{some code}
%\end{verbatim}
%    in a file named \fn{bar.sty}, \lat/ defines \cs{ds@foo} to contain
%    \emph{some code}. Then if the package is invoked with
%\begin{verbatim}
%\usepackage[foo]{bar}
%\end{verbatim}
%    there are two consequences: \opt{foo} is added to the options list
%    for package \pkg{bar}, which is the control sequence
%    \cs{opt@bar.sty}; and when \cs{ProcessOptions} is called, it
%    executes \cs{ds@option-name} for each option found in the list.
%    When it is finished running the options, \cs{ProcessOptions}
%    undefines all the \cs{ds@whatever} for the current package, which
%    are listed in the control sequence \cs{@declaredoptions}. At the
%    end of \fn{bar.sty}, \cs{@declaredoptions} is globally reset to
%    empty. Thus subordinate packages with options cannot be loaded in
%    the \qq{first half} of a package that also has options, where first half
%    means the area leading up to the \cs{ProcessOptions} call.
%
%    For mutually exclusive options \xt{a}, \xt{b}, \xt{c}, when option
%    \xt{b} is invoked it should remove all of its sibling options from
%    the options-actually-used list and add itself to the list. For this
%    task we make use of the fact that \cs{ProcessOptions} ends by
%    undefining all the declared options of the current package or
%    documentclass.
%
%    \begin{macrocode}
\def\CurrentPackage{\@currname}
\let\CurrentClass\CurrentPackage
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand{\IfOption}{}
\def\IfPackageOption{\@ifpackagewith}
\def\IfClassOption{\@ifclasswith}
\def\IfOption{%
  \ifx\@currext\@pkgextension \@xp\IfPackageOption
  \else \@xp\IfClassOption
  \fi
  \@currname
}
%    \end{macrocode}
%
%    \begin{macrocode}
\newcommand{\DeclareExclusiveOptions}[1]{%
  \xdef\@declaredoptions{\@declaredoptions,#1}%
  \gdef\ProcessExclusiveOptions{\relax}%
  \@for\CurrOption:=#1\do{%
    \@xp\deo@a\csname ds@\CurrOption\@xp\endcsname\@xp{\CurrOption}{#1}%
  }%
}
\def\DeclareBooleanOption{\DeclareExclusiveOptions}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\deo@a#1#2#3{%
  \def#1{%
    \g@addto@macro\ProcessExclusiveOptions{\OptionsFalseTrue{#3}{#2}}%
  }%
}
%    \end{macrocode}
%
%    \begin{macrocode}
\def\cull@options#1,{%
  \@xp\ifx\csname ds@#1\@gobble\@percentchar\@empty\endcsname\@False
  \else #1,\fi
  \cull@options
}

\newcommand{\OptionsFalseTrue}[2]{%
  \begingroup
  \@for\CurrentOption:=#1\do{%
    \@xp\let\csname ds@\CurrentOption\endcsname\@False
  }%
  \let\ds@\@False
  \@xp\xdef\csname opt@\@currname.\@currext\endcsname{%
    \@xp\@xp\@xp\cull@options\csname opt@\@currname.\@currext\endcsname
%    \end{macrocode}
%    Lacking \cs{@secondofthree} and not keen on defining it \ldots
%    \begin{macrocode}
      ,\@firstoftwo\@firstoftwo,#2%
  }%
  \endgroup
}
%    \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{112}
% \Finale
