% \iffalse meta-comment
%
% Copyright 1994 the LaTeX3 project and the individual authors.
% All rights reserved. For further copyright information see the file
% legal.txt, and any other copyright indicated in this file.
% 
% This file is part of the LaTeX2e system.
% ----------------------------------------
% 
%  This system is distributed in the hope that it will be useful,
%  but WITHOUT ANY WARRANTY; without even the implied warranty of
%  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
% 
% 
% IMPORTANT NOTICE:
% 
% For error reports in case of UNCHANGED versions see bugs.txt.
% 
% Please do not request updates from us directly.  Distribution is
% done through Mail-Servers and TeX organizations.
% 
% You are not allowed to change this file.
% 
% You are allowed to distribute this file under the condition that
% it is distributed together with all files mentioned in manifest.txt.
% 
% If you receive only some of these files from someone, complain!
% 
% You are NOT ALLOWED to distribute this file alone.  You are NOT
% ALLOWED to take money for the distribution or use of either this
% file or a changed version, except for a nominal charge for copying
% etc.
% \fi
\def\filename{docstrip.dtx}
\def\fileversion{2.2h}
\def\filedate{1994/02/26}
\def\docdate {1994/06/09}

% \CheckSum{1504}
%% \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         \~}
%%
%
%\iffalse
%
%% The docstrip program for use with TeX.
%% Copyright (C) 1989-1991 Frank Mittelbach
%% Copyright (C) 1992-1994 Johannes Braams, Denys Duchier, 
%%                         Frank Mittelbach
%% All rights are reserved.
%%
%
% \fi
%
% \changes{2.0b}{1991/05/29}{Added bugfix from Denys}
% \changes{2.0c}{1991/05/29}{Allow almost all characters in guard (DD)}
% \changes{2.0d}{1991/05/31}{Started merging in some of Franks code}
% \changes{2.0j}{1992/03/05}{Wrote introduction}
% \changes{2.0m}{1992/04/21}{Renamed all macros that deal with the
%                           parsing of boolean expressions}
% \changes{2.0m}{1992/04/25}{Removed dependency from ltugboat,
%                          incorporated driver file into source.}
% \changes{2.0m}{1992/04/25}{Added some missing percents; corrected some
%                          typos}
% \changes{2.0m-DL}{1992/05/08}{Various small corrections to English and
%                           typos}
% \changes{2.0q}{1992/07/01}{Changed all dates to yy/mm/dd for better
%                          sorting}
% \changes{2.2a}{1993/12/02}{Update for LaTeX2e}
% \changes{2.2c}{1993/12/17}{Renamed texsys.tex to texsys.cfg.}
%
% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
% \DoNotIndex{\@ne}
% \DoNotIndex{\advance,\begingroup,\catcode,\closein,\closeout}
% \DoNotIndex{\day,\def,\edef,\else,\empty,\endgroup,\errmessage}
% \DoNotIndex{\expandafter,\fi,\futurelet,\gdef,\global,\if,\ifeof}
% \DoNotIndex{\ifx,\immediate,\let,\loop,\m@ne,\message,\month}
% \DoNotIndex{\newcount}
% \DoNotIndex{\newif,\newlinechar,\newread,\newtoks,\newwrite}
% \DoNotIndex{\noexpand,\openin,\openout,\par,\read,\relax,\repeat}
% \DoNotIndex{\space,\the,\undefined,\write,\xdef,\year,\z@}
%
% ^^A some definitions for this documentation
%
% \newcommand{\ds}{\textsf{DocStrip}} ^^A maybe?
% \newcommand{\bsl}{\protect\bslash}
% \newcommand{\note}[1]{\marginpar{\textbf{#1}}}
% \newcommand{\netaddress}[1]{\texttt{#1}}
%
% ^^A override the default in doc.sty
% \makeatletter
% \renewenvironment{theglossary}{%
%    \glossary@prologue%
%    \GlossaryParms \let\item\@idxitem \ignorespaces}%
%   {}
% \makeatother
%
%
% \changes{2.1c}{1993/02/25}{Added a setting for StandardModuleDepth}
% \setcounter{StandardModuleDepth}{1}
%
% \title{The \ds{} program%
%         \thanks{This file has version number \fileversion,
%                 last revised \filedate,
%                 documentation dated \docdate.}}
%
% \changes{2.1b}{1993/02/23}{modified mailaddress of Johannes}
% \author{%
%   Frank Mittelbach \\
%   \netaddress{Mittelbach@mzdmza.zdv.uni-mainz.de}
%  \and
%   Denys Duchier \\
%   \netaddress{duchier-denys@cs.yale.edu}
%  \and
%   Johannes Braams \\
%   PTT Research Neher Laboratories\\
%          P.O. Box 421\\
%          2260 AK Leidschendam\\
%   \netaddress{J.L.Braams@research.ptt.nl}}
%
% \date{Printed \today}
%
% \maketitle
%
% \begin{abstract}
%    This document describes the implementation of the \ds{} program.
%    The original version of this program was developed by Frank
%    Mittelbach to accompany his \texttt{doc.sty} which enables literate
%    programming in \LaTeX\@. Denys Duchier rewrote it to run either
%    with \TeX\ or of \LaTeX, and to allow full boolean expressions in
%    conditional guards instead of just comma-separated lists.
%    Johannes Braams re-united the two implementations, documented and
%    debugged the code.
% \end{abstract}
%
% \section{Introduction}
%
% \subsection{Why the \ds{} program?} When Frank Mittelbach created
%    the \texttt{doc} package, he invented a way to combine \TeX\ code
%    and its documentation. From then on it was more or less possible
%    to do literate programming in \TeX.
%
%    This way of writing \TeX\ programs obviously has great
%    advantages, especially when the program becomes larger than a
%    couple of macros.  There is one drawback however, and that is
%    that such programs may take longer than expected to run because
%    \TeX\ is an interpreter and has to decide for each line of the
%    program file what it has to do with it. Therefore, \TeX\ programs
%    may be speeded up by removing all comments from them.
%
%    By removing the comments from a \TeX\ program a new problem is
%    introduced. We now have two versions of the program and both of
%    them {\em have\/} to be maintained. Therefore it would be nice to
%    have a possibility to remove the comments automatically, instead
%    of doing it by hand. So we need a program to remove comments from
%    \TeX\ programs. This could be programmed in any high level
%    language, but maybe not everybody has the right compiler to
%    compile the program.  Everybody who wants to remove comments from
%    \TeX\ programs has \TeX\@.  Therefore the \ds{} program is
%    implemented entirely in \TeX.
%
% \subsection{Functions of the \ds{} program} 
%
%    Having created the \ds{} program to remove comment lines from
%    \TeX\ programs\footnote{Note that only comment lines, that is
%    lines that start with a single \texttt{\%} character, are removed;
%    all other comments st in the code.} it became feasible to do more
%    than just strip comments.\\ Wouldn't it be nice to have a way to
%    include parts of the code only when some condition is set true?
%    Wouldn't it be as nice to have the possibility to split the
%    source of a \TeX\ program into several smaller files and combine
%    them later into one `executable'?\\ Both these wishes have been
%    implemented in the \ds{} program.
%
%  \subsection{How to use the \ds{} program}
%    A number of ways exist to use the \ds{} program:
%    \begin{enumerate}
%    \item The easiest way is to instruct \TeX\ to read the file
%        \texttt{docstrip.tex} and to see what happens. \TeX\ will ask
%        you a few questions about the file you would like to be
%        processed. When you have answered these questions it does
%        its job and strips the comments from your \TeX\ code.
%    \item When you would like to be able to process more than one
%        file with one command, or you would like to add a couple of
%        lines to the beginning (or end) of the stripped file you can
%        write a `batch file' for \ds{}. The default name for such a
%        file is \texttt{docstrip.cmd}. When a file by that name
%        exists in your current directory when you instruct \TeX\ to
%        read \texttt{docstrip.tex} it will verify (by asking you)
%        that you want to use {\em that\/} file and if so, will
%        process the commands in it.
%
%        You do not need to use the default name, however. You can
%        give a batch file any name you like such as, say, 
%        \texttt{foo.bar} and then run \TeX\ by using a command such as:
%    \begin{verbatim}
%    TeX \def\batchfile{foo.bar}\input docstrip
%    \end{verbatim}
%
% \item You may use yet another way that is only slightly different
%        from the previous method. You can write a batch file in such
%        a way that it can be directly processed by \TeX{}. This
%        allows you to set up a distribution where you can instruct
%        the user to simply run
%      \begin{quote}
%        \texttt{TEX} \meta{batch file}
%      \end{quote}
%        to generate the executable versions of your files from the
%        distribution sources. All distributions from Mainz are set up
%        in this way (also this one); look, for example, at the
%        installation file for this distribution.  To produce such a
%        batch file include a statement in your `batch file' that
%        instructs \TeX\ to read \texttt{docstrip.tex}. You should then
%        also define \verb=\batchfile= to contain the name of that
%        `batch file'. The beginning of such a file would look like:
%    \begin{verbatim}
%    \def\batchfile{install.me}
%    \input docstrip
%    ...
%    \end{verbatim}
%    \end{enumerate}
%
% \section{The user interface}
%
% \subsection{The main program}
% \DescribeMacro{\processbatchFile} The `main program' starts with
%    trying to process a batch file, this is accomplished by calling
%    the macro |\processbatchFile|. It counts the number of batch
%    files it processes, so that when the number of files processed is
%    still zero after the call to |\processbatchFile| appropriate
%    action can be taken.
%
% \DescribeMacro{\interactive} When no batch files have been processed
%    the macro |\interactive| is called. It prompts the user for
%    information. First the extensions of the input and output files
%    is determined. Then a question about optional code is asked and
%    finally the user can give a list of files that have to be
%    processed.
%
% \DescribeMacro{\ReportTotals} When the \texttt{stats} option is
%    included in the \ds{}-program it keeps a record of the number of
%    files and lines that are processed.  Also the number of comments
%    removed and passed as well as the number of code lines that were
%    passed to the output are accounted. The macro |\ReportTotals|
%    shows a summary of this information.
%
% \subsection{Batchfile commands}
%
%    The commands described in this section are available to build a
%    batch file.
%
% \DescribeMacro{\showprogress}
% \DescribeMacro{\keepsilent}
%    When the option \texttt{stats} is included in \ds{} it can
%    write message to the terminal as each line of the input file(s) is
%    processed. This message consists of a single character, indicating
%    what the program does with that particular line. We use the
%    following characters:
%    \begin{itemize}
% \item[\texttt{\%}] Whenever an input line is removed a
%        \texttt{\%}-character is written to the terminal.
% \item[\texttt{.}] Whenever a code line is passed on to the output file
%        a \texttt{.}-character is written on the terminal.
% \item[\texttt{/}] When a number of empty lines appear in a row in the
%        input file, at most one of them is retained. The \ds{}
%        program signals the removal of an empty line with the 
%        \texttt{/}-character.
% \item[\texttt{<}] When a `guard line' is found in the input and it
%        starts a block of optionally included code, this is signalled
%        on the terminal by showing the \texttt{<}-character, together
%        with the boolean expression of the guard.
% \item[\texttt{>}] The end of a conditionally included block of code is
%        indicated by showing the \texttt{>}-character.
%    \end{itemize}
%    This feature is turned on by default when the option
%    \texttt{stats} is included, otherwise it is turned of. The
%    feature can be toggled with the commands |\showprogress| and
%    |\keepsilent|
%
% \DescribeMacro{\preamble}
% \DescribeMacro{\endpreamble}
% \DescribeMacro{\postamble}
% \DescribeMacro{\endpostamble}
%    It is possible to add a number of lines to the output of
%    the \ds{} program. The information you want to add to the
%    start of the output file should be listed between the |\preamble|
%    and |\endpreamble| commands; the lines you want to add to the end
%    of the output file should be listed between the |\postamble| and
%    |\endpostamble| commands. Everything that \ds{} finds
%    for both the pre- and postamble it writes to the output file, but
%    preceded with two \%-characters. If you include a |^^M| character
%    in one of these lines, everything that follows it on the same line
%    is written to a new line in the output file.
%    This `feature' can be used to add a |\typeout| or |\message| to the
%    the stripped file.
%
% \DescribeMacro{\generateFile}
%    The main reason for constructing a \ds{} command file is that
%    one doesn't want to type in the instructions for \TeX\ each time
%    a macro file is stripped of its comments. The macro |\generateFile|
%    is used to tell \TeX\ what to do. Its syntax is:
%    \begin{quote}
%    |\generateFile{|\meta{output}|}{|\meta{ask}|}{|[|\from{|^^A
%                    \meta{input}|}{|\meta{optionlist}|}|]*|}|
%    \end{quote}
%    The \meta{output} and \meta{input} are normal file specifications
%    as are appropriate for your computer system. The \meta{optionlist}
%    is a comma separated list of `options' that specify which
%    optional code fragments in \meta{input} should be included in
%    \meta{output}.  With \meta{ask} you can instruct \TeX\ to either
%    silently overwrite a previously existing file (|f|) or to issue a
%    warning and ask you if it should overwrite the existing file
%    (|t|).
%
%    It is possible to specify multiple input files, each with its own
%    \meta{optionlist}. This is indicated by the notation [\ldots]*.
%
% \DescribeMacro{\include}
% \DescribeMacro{\processFile}
%    The earlier version of the \ds{} program supported a
%    different kind of command to tell \TeX\ what to do. This command
%    is less powerful than |\generateFile|; it can be used when
%    \meta{output} is created from one \meta{input}. The syntax is:
%    \begin{quote}
%    |\include{|\meta{optionlist}|}|
%
%    |\processFile{|\meta{name}|}{|\meta{inext}^^A
%                              |}{|\meta{outext}^^A
%                              |}{|\meta{ask}|}|
%    \end{quote}
%    This command is based on environments where filenames are
%    constructed of two parts, the name and the extension, separated
%    with a dot. The syntax of this command assumes that the
%    \meta{input} and \meta{output} share the same name and only
%    differ in their extension. This command is retained to be
%    backwards compatible with the older version of \ds{}, but its use
%    is not encouraged.
%
% \DescribeMacro{\input}
% \DescribeMacro{\batchinput} 
%    The batch file commands can be put into several batch files which
%    are then executed from a master batch file. This is, for example,
%    useful if a distribution consists of several distinct parts. You
%    can then write individual batch files for every part and in
%    addition a master file that simply calls the batch files for the
%    parts.  For this, call the individual batch files from the master
%    file with the command |\batchinput{|\meta{file}|}|. You can nest
%    batch files up to a nesting level of ten which is more than
%    sufficient. Don't use |\input| for this purpose, this command
%    should be used only for calling the \ds{} program as explained
%    above and is ignored when used for any other purpose.
%
% \DescribeMacro{\ifToplevel} 
%    When batch files are nested you may want to suppress certain
%    commands in the lower-level batch files such as terminal
%    messages. For this purpose you can use the |\ifToplevel| command
%    which executes its argument only if the current batch file is the
%    outermost one. Make sure that you put the opening brace of the
%    argument into the same line as the command itself, otherwise the
%    \ds{} program will get confused.
%
% \section{Conditional inclusion of code}
%
%    When you use the \ds{} program to strip comments out of
%    \TeX\ macro files you have the possibility to make more than one
%    stripped macro file from one documented file. This is achieved by
%    the support for optional code. The optional code is marked
%    in the documented file with a `guard'.
%
%    A guard is a boolean expression that is enclosed in |<| and |>|.
%    It also {\em has\/} to follow the |%| at the beginning of the line.
%    For example:
%\begin{verbatim}
%    ...
%    %<bool>\TeX code
%    ...
%\end{verbatim}
%    In this example the line of code will be included in \meta{output}
%    if the option \texttt{bool} is present in the \meta{optionlist} of
%    the |\generateFile| command.
%
%    The syntax for the boolean expressions is:
%
%\DeleteShortVerb\|
%    \begin{tabular}{lcl}
%    \meta{Expression} & $::=$ & \meta{Primary}
%                            [\{\texttt{|}, \texttt{,}\} 
%                            \meta{Primary}]*\\
%    \meta{Primary}    & $::=$ & 
%                        \meta{Secondary} [\texttt{\&}
%                         \meta{Secondary}]*\\
%    \meta{Secondary}  & $::=$ & 
%                        \meta{Terminal} $|$ \texttt{!}\meta{Secondary}
%                        $|$ \texttt{(}\meta{Expression}\texttt{)}\\
%    \end{tabular}
%
%    The \texttt{|} stands for disjunction, the \texttt{\&} stands for
%    conjunction and the \texttt{!}\ stands for negation. The
%    \meta{Terminal} is any sequence of letters and evaluates to
%    \meta{true} iff\footnote{iff stands for `if and only if'} it
%    occurs in the list of options that have to be included.
%\MakeShortVerb\|
%
%    Two kinds of optional code are supported: one can either have
%    optional code that `fits' on one line of text, like the example
%    above, or one can have blocks of optional code.
%
%    To distinguish both kinds of optional code the `guard modifier'
%    has been introduced. The `guard modifier' is one character that
%    immediately follows the |<| of the guard. It can be either |*|
%    for the beginning of a block of code, or |/| for the end of a
%    block of code\footnote{To be compatible with the earlier version
%    of \ds{} also \texttt{+} and \texttt{-} are supported as `guard
%    modifiers'.  However, there is an incompatibility with the
%    earlier version since a line with a \texttt{+}-modified guard is
%    not included inside a block with a guard that evaluates to false,
%    in contrast to the previous behaviour.}.  The beginning and
%    ending guards for a block of code have to be on a line by
%    themselves.
%
%    When a block of code is {\em not\/} included, any guards that occur
%    within that block are {\em not\/} evaluated.
%
%\StopEventually{%
%^^A \section{Conclusion}
%  \PrintIndex
%  \PrintChanges
%^^A \makesignature
% }
%
% \section{Producing the documentation}
%
%    We provide a short driver file that can be extracted by the
%    \ds{} program using the the conditional `\textsf{driver}'.  To
%    allow the use of \texttt{docstrip.dtx} as a program at Ini\TeX{}
%    time (e.g., to strip
%    off its own comments) we need to add a bit of primitive code.
%    With this extra checking it is still possible to process this
%    file with \LaTeXe{} to typeset the documentation.
% \changes{2.1b}{1993/02/23}{Added fontdefinitions for doc to the driver
%                          file, in order to get the layout of the code
%                          right; also added the layout definitions
%                          that are in effect in \texttt{doc.drv}}
% \changes{2.1c}{1993/02/23}{Remove definitions for fonts again}
% \changes{2.2f}{1994/02/26}{Allow direct processing of source}
%    \begin{macrocode}
%<*driver>
%    \end{macrocode}
%    If |\documentclass| is undefined, e.g., if Ini\TeX{} or plain
%    \TeX{} is used for formatting, we bypass the driver file.
%    \begin{macrocode}
\ifx\documentclass\undefined
\else
%    \end{macrocode}
%    Otherwise we process the following lines which will result in
%    formatting the documentation.
%    \begin{macrocode}
\documentclass{ltxdoc}
    \EnableCrossrefs
 %    \DisableCrossrefs    % use \DisableCrossrefs if the
                           % index is ready
   \RecordChanges
 %   \OnlyDescription
   \typeout{Expect some Under- and overfull boxes}
\begin{document}
  \DocInput{docstrip.dtx}
%    \end{macrocode}
%    We cannot call |\end{document}| at this point because this would
%    leave the |\ifx| from above unfinished and the user would get a
%    warning message. Therefore we do some |\expandafter| processing;
%    hiding the |\end{document}| for a moment in a scratch macro for
%    easier processing.
%    \begin{macrocode}
\renewcommand\next{\end{document}}
\expandafter\next\fi
%</driver>
%    \end{macrocode}
%
%
% \section{The implementation}
%
% \subsection{Declarations and initializations}
%
%    In order to be able to include the \texttt{@}-sign in control
%    sequences its category code is changed to \meta{letter}.  The
%    `program' guard here allows most of the code to be excluded when
%    extracting the driver file.
%    \begin{macrocode}
%<*program>
\catcode`\@=11
%    \end{macrocode}
%
%    When we want to write multiple lines to the terminal with one
%    statement, we need a character that tells \TeX\ to break the lines.
%    We use \verb=^^J= for this purpose.
%    \begin{macrocode}
\newlinechar=`\^^J
%    \end{macrocode}
%
% \subsubsection{Token registers}
% \begin{macro}{\TerminalString}
% \changes{2.0m}{1992/04/22}{Renamed from \texttt{\bsl boolToks}}
%    A token register is allocated that will be used to accumulate
%    the tokens that make up a \meta{Terminal} in the process
%    of scanning guards.
%    \begin{macrocode}
\newtoks\TerminalString
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Switches}
% \begin{macro}{\ifOff}
% \begin{macro}{\ifGenerate}
%    The switch \verb=\ifOff= will be used to signal if code lines
%    have to be included in the output.  The program will check if a
%    file of the same name as the file it would be creating already
%    exists. The switch \verb=\ifGenerate= is used to indicate if the
%    stripped file has to be generated.
%    \begin{macrocode}
\newif\ifOff
\newif\ifGenerate
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ifContinue}
%    The switch \verb=\ifContinue= is used in various places in the
%    program to indicate if a \verb=\loop= has to end.
%    \begin{macrocode}
\newif\ifContinue
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifTerminal}
%    The macros that parse the boolean expression in the guards need
%    a switch to indicate if a \meta{Terminal} has been found.
% \changes{2.0l}{1992/04/17}{Renamed from \texttt{\bsl ifName}.}
%    \begin{macrocode}
\newif\ifTerminal
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifForlist}
% \changes{2.0g}{1991/06/05}{Macro added.}
%    The program contains an implementation of a for-loop, based on
%    plain \TeX{}'s \verb=\loop= macros. The implementation needs a
%    switch to terminate the loop.
%    \begin{macrocode}
\newif\ifForlist
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifDefault}
%    The switch \verb=\ifDefault= is used to indicate whether the
%    default batch file has to be used.
% \changes{2.0f}{1991/06/04}{Macro added.} 
%    \begin{macrocode}
\newif\ifDefault
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ifMoreFiles}
%    The switch \verb=\ifMoreFiles= is used to decide if the user
%    wants more files to be processed. It is used only in interactive
%    mode; initially it evaluates to \meta{true}.
% \changes{2.0h}{1991/06/19}{Macro added.}
%    \begin{macrocode}
\newif\ifMoreFiles \MoreFilestrue
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Count registers}
% \begin{macro}{\blockLevel}
%    Optionally included blocks of code can be nested. The counter
%    \verb=\blockLevel= will be used to keep track of the level of
%    nesting.  Its initial value is zero.
%    \begin{macrocode}
\newcount\blockLevel \blockLevel\z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\offLevel}
%    The count register  \verb=\offLevel= is used to
%    count the number of levels since the first block whose guard
%    evaluated to false.  When this number reaches zero again we set the
%    switch \verb=\ifOff= to false again.
%    \begin{macrocode}
\newcount\offLevel \offLevel \z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\emptyLines}
%    The count register \verb=\emptyLines= is used to count the number
%    of consecutive empty input lines. Only the first will be copied
%    to the output file.
% \changes{2.0i}{1990/06/27}{Macro added}
%    \begin{macrocode}
\newcount\emptyLines \emptyLines \z@
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processedLines}
% \begin{macro}{\commentsRemoved}
% \begin{macro}{\commentsPassed}
% \begin{macro}{\codeLinesPassed}
%    To be able to provide the user with some statistics about the
%    stripping process four counters are allocated if the statistics
%    have been included when this program was \ds{}ped.  The number of
%    lines processed is stored in the counter \verb=\processedLines=.
%    The number of lines containing comments that are not written on
%    the output file is stored in the counter \verb=\commentsRemoved=;
%    the number of comments copied to the output file is stored in the
%    counter \verb=\commentsPassed=.  The number of lines containing
%    macro code that are copied to the output file is stored in the
%    counter \verb=\codeLinesPassed=.
%    \begin{macrocode}
%<*stats>
\newcount\processedLines   \processedLines  \z@
\newcount\commentsRemoved  \commentsRemoved \z@
\newcount\commentsPassed   \commentsPassed  \z@
\newcount\codeLinesPassed  \codeLinesPassed \z@
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\NumberOfFiles}
%    When more than one file is processed, the number of files is
%    stored in the count register \verb=\NumberOfFiles= when
%    statistics are included.
%    \begin{macrocode}
\newcount\NumberOfFiles \NumberOfFiles\z@
%    \end{macrocode}
% \end{macro}
%
% \changes{2.0e}{1991/05/31}{Added counter allocation for the processing
%                           of multiple files}
% \begin{macro}{\TotalprocessedLines}
% \begin{macro}{\TotalcommentsRemoved}
% \begin{macro}{\TotalcommentsPassed}
% \begin{macro}{\TotalcodeLinesPassed}
%    When more than one file is processed and when statistics have
%    been included we provide the user also with information about the
%    total amount of lines processed. For this purpose four more count
%    registers are allocated here.
%    \begin{macrocode}
\newcount\TotalprocessedLines   \TotalprocessedLines  \z@
\newcount\TotalcommentsRemoved  \TotalcommentsRemoved \z@
\newcount\TotalcommentsPassed   \TotalcommentsPassed  \z@
\newcount\TotalcodeLinesPassed  \TotalcodeLinesPassed \z@
%</stats>
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \subsubsection{I/O streams}
% \begin{macro}{\inFile}
% \begin{macro}{\outFile}
%    For reading the file with documented \TeX-code, an input stream
%    \verb=\inFile= is allocated. The stripped code is written on
%    the output stream \verb=\outFile=.
%    \begin{macrocode}
\newread\inFile
\newwrite\outFile
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\ttyin}
% \begin{macro}{\ttyout}
%    For the communication with the user an input stream, \verb=\ttyin=
%    and an output stream, \verb=\ttyout= are allocated.
%    \begin{macrocode}
\newread\ttyin
\newwrite\ttyout
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\currbatchFile}
% \changes{2.0e}{1991/05/31}{Added allocation of extra input stream
%                          for batch files}
% \changes{2.1a}{1993/02/22}{Renamed from `batchFile to `currbatchFile}
% \changes{2.1a}{1993/02/22}{Logic changed}
%    For batch file processing we need a number of input streams so
%    that a batch file can open further batch files using
%    |\batchinput|.
%
%    We begin by allocating ten anonymous read streams.
%    \begin{macrocode}
\newread\@tempa 
%    \end{macrocode}
% \begin{macro}{\lowestbatchFile}
%    We save the lowest number allocated in |\lowestbatchFile|, of
%    course this code highly depends on the implementation of the
%    plain allocation routines.
%    \begin{macrocode}
\let\lowestbatchFile\@tempa
\newread\@tempa \newread\@tempa \newread\@tempa \newread\@tempa
\newread\@tempa \newread\@tempa \newread\@tempa \newread\@tempa
\newread\@tempa
%    \end{macrocode}
% \begin{macro}{\highestbatchFile}
%    Same for the highest number.
%    \begin{macrocode}
\let\highestbatchFile\@tempa
%    \end{macrocode}
%    Now we allocate a count register which is supposed to hold the
%    the number of the batch file stream we are currently reading
%    from. Initially this will contain the number for the first read
%    stream allocated for this reason.
%    \begin{macrocode}
\newcount\currbatchFile
\currbatchFile=\highestbatchFile
\advance\currbatchFile by -9
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%  \begin{macro}{\ifToplevel}
%    Execute the argument if current batch file is the outermost one.
%    Otherwise suppress it.
%    \begin{macrocode}
\def\ifToplevel{\relax\ifnum\currbatchFile=\lowestbatchFile
   \expandafter\iden \else \expandafter\gobble\fi}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\batchinput}
% \changes{2.0n}{1992/04/26}{Added macro}
% \changes{2.1a}{1993/02/22}{Completely redefined (so that it works)}
%
%    When the file \texttt{docstrip.tex} is read because of an
%    \verb=\input= statement in a batch file we have to prevent an
%    endless loop (well, limited by \TeX's stack). Therefore we save
%    the original primitive \verb=\input= and define a new macro with
%    an argument delimited by \verb*= = (i.e.\ a space) that just
%    gobbles the argument.  Since the end-of-line character is
%    converted by \TeX{} to a space.  This means that |\input| is not
%    available as a command within batch files. In fact it would be
%    dangerous to use it anyway, since it would mean mixing line for
%    line reading with unlimited file reading.
%
% \begin{macro}{\@@input}
% \changes{2.1a}{1993/02/22}{Macro added}
%    We therefore keep a copy of the original under the name
%    |\@@input| for internal use. If \ds{} runs under \LaTeX{} this
%    command is already defined, so we make a quick test.
%    \begin{macrocode}
\ifx\undefined\@@input \let\@@input\input\fi
%    \end{macrocode}
% \end{macro}
%    
%    To allow the nesting of batch files the |\batchinput| command is
%    provided it takes one argument, the name of the batch file to
%    switch to.
%    \begin{macrocode}
\def\batchinput#1{%
%    \end{macrocode}
%    We start a new group and locally redefine |\batchFile| to hold
%    the new batch file name and advance |\currbatchFile| by one to
%    get a new read stream. If the batch files are too deeply nested
%    there may be no further stream available so we better check for
%    this. The currently supported number is 10 which is generous
%    enough even for large installation procedures.
%    \begin{macrocode}
   \begingroup
     \def\batchfile{#1}%
     \advance\currbatchFile\@ne
     \ifnum\currbatchFile>\highestbatchFile
        \errhelp{Only up to ten levels of nesting for
                 \noexpand\batchinput commands are supported}%
        \errmessage{Batchfiles too deeply nested}%
     \fi
%    \end{macrocode}
%    After this test we can simply call |\processbatchFile| which will
%    open the new batch file and does a line for line reading until it
%    is exhausted. Note that if the batch file is not available, or
%    misspelled this routine will produce a warning and returns.
%    \begin{macrocode}
     \processbatchFile
%    \end{macrocode}
%    The closing |\endgroup| will then restore the values for
%    |\batchfile| and |\currbatchFile| so that further processing
%    continues in the calling batch file.
%    \begin{macrocode}
   \endgroup
}
%    \end{macrocode}
% \begin{macro}{\skip@input}
% \changes{2.0j}{1992/03/03}{Added macro}
% \changes{2.0n}{1992/04/26}{Argument delimited by space not `relax}
% \changes{2.0n}{1992/04/26}{Macro renamed from `skipinput} 
%    And here is the promised redefinition of |\input|:
%    \begin{macrocode}
\def\skip@input#1 {}
\let\input\skip@input
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsubsection{Empty macros and macros that expand to a string}
% \begin{macro}{\guardStack}
%    \changes{2.0k}{1992/04/06}{Renamed from \texttt{\bsl blockStack}}
%    Because blocks of code that will conditionally be included in the
%    output can be nested, a stack is maintained to keep track of
%    these blocks. The main reason for this is that we want to be able
%    to check if the blocks are properly nested. The stack itself is
%    stored in |\guardStack|.
%    \begin{macrocode}
\def\guardStack{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\blockHead}
%    The macro \verb=\blockHead= is used for storing and retrieving
%    the boolean expression that starts a block.
%    \begin{macrocode}
\def\blockHead{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Options}
% \begin{macro}{\lastOption}
%    The list of options to include in the output is stored in
%    \verb=\Options=. The macro \verb=\lastOption= is used to remember
%    which option was started.
%    \begin{macrocode}
\def\Options{}
\def\lastOption{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\TrueExpression}
% \begin{macro}{\FalseExpression}
%    In the evaluation of the boolean expressions a representation is
%    needed for \meta{true} and \meta{false}. This representation is
%    realized by the definition of |\TrueExpression| and
%    |\FalseExpression|. These macros are meant to be used with \TeX's
%    |\if|-test.  When the expression |\if\TrueExpression...| is
%    expanded by \TeX\ it yields |\if TT...|. This test is true and
%    all instructions following the test (until |\else| or |\fi| is
%    encountered) will examined.
%    \begin{macrocode}
\def\TrueExpression{TT}
\def\FalseExpression{TF}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\yes}
% \begin{macro}{\y}
%    When the user is asked a question that he has to answer with either
%    \meta{yes} or \meta{no}, his response has to be evaluated. For this
%    reason the macros \verb=\yes= and \verb=\y= are defined.
%    \begin{macrocode}
\def\yes{yes}
\def\y{y}
%    \end{macrocode}
% \begin{macro}{\n}
%    We also define \verb=\n= for use in \ds{} command files.
% \changes{v2.1e}{1993/03/09}{Macro added}
%    \begin{macrocode}
\def\n{n}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\Defaultbatchile}
% \changes{2.0f}{1991/06/04}{Macro added.}
%    When the \ds{} program has to process a batch file it
%    can look for a batch file with a default name. This name
%    is stored in \verb=\DefaultbatchFile=.
%    \begin{macrocode}
\def\DefaultbatchFile{docstrip.cmd}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\perCent}
% \begin{macro}{\DoubleperCent}
%    To be able to display percent-signs on the terminal, a \texttt{\%}
%    with category code 12 is stored in \verb=\perCent=. The macro
%    \verb=\DoubleperCent= is used to write two percent-signs when
%    writing the preamble of the output file.
%    \begin{macrocode}
{\catcode`\%=12
 \gdef\perCent{%}
 \gdef\DoubleperCent{%% }
}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%    In order to allow formfeeds in the input we define a one-character
%    control sequence \verb=^^L=.
%    \begin{macrocode}
\def^^L{ }
%    \end{macrocode}
%
% \subsubsection{Miscellaneous variables}
% \begin{macro}{\inFileName}
%    The macro \verb=\inFileName= is used to store the name of the
%    current input file.
% \end{macro}
% \begin{macro}{\outFileName}
%    The macro \verb=\outFileName= is used to store the name of the
%    current output file.
% \end{macro}
% \begin{macro}{\batchfile}
%    The macro \verb=\batchfile= is used to store the name of the
%    batch file.
% \end{macro}
% \begin{macro}{\inLine}
%    The macro \verb=\inLine= is used to store the lines, read from
%    the input file, before further processing.
% \end{macro}
% \begin{macro}{\batchLine}
%    The macro \verb=\batchLine= is used to store the lines, read from
%    the batch file, before further processing.
% \end{macro}
% \begin{macro}{\nextToken}
%    In this \TeX-program a lot of `peeking ahead' using the
%    \verb=\futurelet= instruction is done. In such cases the
%    character that appears first in the input stream is stored in
%    \verb=\nextToken=.
% \end{macro}
% \begin{macro}{\doNext}
%    Another aspect of this program is that quite often the next action
%    depends on the evaluation of an \verb=\if= construct. In such cases
%    the control sequence \verb=\doNext= is \verb=\let= to the macro
%    that has to be executed.
% \end{macro}
% \begin{macro}{\answer}
%    When some interaction with the user is needed the macro
%    \verb=\answer= is used to store his response.
% \end{macro}
% \begin{macro}{\tmp}
%    Sometimes something has to be temporarily stored in a control
%    sequence.  For these purposes the control sequence \verb=\tmp= is
%    used.
% \end{macro}
%
% \subsection{Support macros}
%    \subsubsection{The stack mechanism}
%
%    It is possible to have `nested guards'. This means that within a
%    block of optionally included code a subgroup is only included
%    when an additional option is specified. To keep track of the
%    nesting of the guards the currently `open' guard can be pushed on
%    the stack |\guardStack| and later popped off the stack again. The
%    macros that implement this stack mechanism are loosely based on
%    code that is developed in the context of the \LaTeX3 project.
%
%    To be able to implement a stack mechanism we need a couple of
%    support macros.
% \begin{macro}{\eltStart}
%    \changes{2.0k}{1992/04/06}{Macro added}
% \begin{macro}{\eltEnd}
%    \changes{2.0k}{1992/04/06}{Macro added}
%    The macros |\eltStart| and |\eltEnd| are used to delimit a stack
%    element. They are both empty.
%    \begin{macrocode}
\def\eltStart{}
\def\eltEnd{}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\qStop}
%    \changes{2.0k}{1992/04/06}{Macro added}
%    The macro |\qStop| is a so-called `quark', a macro that expands to
%    itself\footnote{The concept of `quarks' is developed for the
%    \LaTeX3 project.}.
%    \begin{macrocode}
\def\qStop{\qStop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\pop}
%    \changes{2.0k}{1992/04/06}{Macro added} The macro
%    |\pop|\meta{stack}\meta{cs} `pops' the top element from the
%    stack. It assigns the value of the top element to \meta{cs} and
%    removes it from \meta{stack}. When \meta{stack} is empty a
%    warning is issued and \meta{cs} is assigned an empty value.
%    \begin{macrocode}
\def\pop#1#2{%
  \ifx#1\empty
    \Msg{Warning: Found end guard without matching begin}%
    \let#2\empty
  \else
%    \end{macrocode}
%    To be able to `peel' off the first guard we use an extra macro
%    |\popX| that receives both the expanded and the unexpanded stack
%    in its arguments. The expanded stack is delimited with the quark
%    |\qStop|.
%    \begin{macrocode}
    \def\tmp{\expandafter\popX #1\qStop #1#2}%
    \expandafter\tmp\fi}
%    \end{macrocode}
% \begin{macro}{\popX}
%    \changes{2.0k}{1992/04/06}{Macro added} When the stack is expanded
%    the elements are surrounded with |\eltStart| and |\eltEnd|. The
%    first element of the stack is assigned to |#4|.
%    \begin{macrocode}
\def\popX\eltStart #1\eltEnd #2\qStop #3#4{\def#3{#2}\def#4{#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\push}
%    \changes{2.0k}{1992/04/06}{Macro added}
%    Guards can be pushed on the stack using the macro
%    |\push|\meta{stack}\meta{guard}. Again we need a secondary macro
%    (|\pushX|) that has both the expanded and the unexpanded stack as
%    arguments.
%    \begin{macrocode}
\def\push#1#2{\expandafter\pushX #1\qStop #1{\eltStart #2\eltEnd}}
%    \end{macrocode}
% \begin{macro}{\pushX}
%    \changes{2.0k}{1992/04/06}{Macro added}
%    The macro |\pushX| picks up the complete expansion of the stack as
%    its first argument and places the guard in |#3| on the `top'.
%    \begin{macrocode}
\def\pushX #1\qStop #2#3{\def #2{#3#1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsubsection{Programming structures}
%
% \begin{macro}{\forlist}
% \changes{2.0g}{1991/06/05}{Macro added.}
%    When the program is used in interactive mode the
%    user can supply a list of files that have to be processed.
%    In order to process this list a for-loop is needed. This
%    implementation of such a programming construct is based on the
%    use of the \verb=\loop{=\meta{body}\verb=}\repeat= macro that
%    is defined in plain \TeX\@. The syntax for this loop is:
%    \begin{flushleft}
%    \verb=\for=\meta{control sequence} \verb|:=| \meta{list} 
%    \verb=\do=\\
%    \meta{body}\\
%    \verb=\od=
%    \end{flushleft}
%    The \meta{list} should be a comma separated list.
%
%    The first actions that have to be taken are to set the switch
%    \verb=\ifForlist= to \meta{true} and to store the loop condition
%    in the macro \verb=\ListCondition=. This is done using an
%    \verb=\edef= to allow for a control sequence that contains a
%    \meta{list}.
%    \begin{macrocode}
\def\forlist#1:=#2\do#3\od{%
    \edef\ListCondition{#2}%
    \Forlisttrue
%    \end{macrocode}
%    Then we start the loop.
%    We store the first element from the \verb=\ListCondition= in the
%    macro that was supplied as the first argument to \verb=\forlist=.
%    This element is then removed from the \verb=\ListCondition=.
%    \begin{macrocode}
    \loop
      \edef#1{\expandafter\FirstElt\ListCondition,\empty.}%
      \edef\ListCondition{\expandafter\OtherElts\ListCondition,\empty.}%
%    \end{macrocode}
%    When the first element from the \meta{list} is empty, we are done
%    processing, so we switch \verb=\ifForlist= to \meta{false}.
%    When it is not empty we execute the third argument that should
%    contain \TeX\ commands to execute.
%    \begin{macrocode}
      \ifx#1\empty \Forlistfalse \else#3\fi
%    \end{macrocode}
%    Finally we test the switch \verb=\ifForlist= to decide whether the
%    loop has to be continued.
%    \begin{macrocode}
      \ifForlist
    \repeat}
%    \end{macrocode}
% \begin{macro}{\FirstElt}
% \changes{2.0g}{1991/06/05}{Macro added.}
%    The macro \verb=\FirstElt= is used to get the first element from a
%    comma-separated list.
%    \begin{macrocode}
\def\FirstElt#1,#2.{#1}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\OtherElts}
% \changes{2.0g}{1991/06/05}{Macro added.}
%    The macro \verb=\OtherElts= is used to get all elements {\em but\/}
%    the first element from a comma-separated list.
%    \begin{macrocode}
\def\OtherElts#1,#2.{#2}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\whileswitch}
% \changes{2.0h}{1991/06/19}{Macro added.} When the program is used in
%    interactive mode the user might want to process several files
%    with different options or extensions.  This goal could be reached
%    by running the program several times, but it is more
%    user-friendly to ask if he would like to process more files when
%    we are done processing his last request.  To accomplish this we
%    need the implementation of a \texttt{while}-loop.  Again plain
%    \TeX's \verb=\loop{=\meta{body}\verb=}\repeat= is used to
%    implement this programming structure.
%
%    The syntax for this loop is:
%    \begin{flushleft}
%    \verb=\whileswitch=\meta{switch} \verb|\fi| \meta{list}
%    \verb={=\meta{body}\verb=}=\\
%    \end{flushleft}
%    The first argument to this macro has to be a switch, defined
%    using \verb=\newif=; the second argument contains the statements
%    to execute while the switch evaluates to \meta{true}.
%    \begin{macrocode}
\def\whileswitch#1\fi#2{#1\loop#2#1\repeat\fi}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Input and Output}
%
% \begin{macro}{\maybeMsg}
% \begin{macro}{\showprogress}
% \begin{macro}{\keepsilent}
%    When this program is used it can optionally show its progress on
%    the terminal. In that case it will write a special character to
%    the terminal (and the transcript file) for each input line. This
%    option is on by default when statistics are included in 
%    \texttt{docstrip.tex}. It is off when statistics are excluded. The
%    commands \verb=\showprogress= and \verb=\keepsilent= can be used
%    to choose otherwise.
%    \begin{macrocode}
\def\showprogress{\let\maybeMsg\message}
\def\keepsilent{\let\maybeMsg\gobble}
%<*stats>
\showprogress
%</stats>
%<-stats>\keepsilent
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\Msg}
%    For displaying messages on the terminal the macro \verb=\Msg= is
%    defined to write {\em immediately\/} to \verb=\ttyout=.
%    \begin{macrocode}
\def\Msg{\immediate\write\ttyout}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Ask}
%    The macro
%    \verb=\Ask{=\meta{cs}\texttt{\}\{}\meta{string}\texttt{\}} is a
%    slightly modified copy of the \LaTeX\ macro \verb=\typein=. It is
%    used to ask the user a question.  The \meta{string} will be
%    displayed on his terminal and the response will be stored in the
%    \meta{cs}. The trailing space left over from the carriage return
%    is stripped off by the macro \verb=\strip=. If the user just
%    types a carriage return, the result will be an empty macro.
% \changes{2.0i}{1991/06/27}{Added check for just \protect\meta{CR}}
%    \begin{macrocode}
\def\iden#1{#1}
\def\strip#1#2 \gobble{\def #1{#2}}
\def\@defpar{\par}
\def\Ask#1#2{%
    \message{#2}\read\ttyin to #1\ifx#1\@defpar\def#1{}\else
    \iden{\expandafter\strip\expandafter#1#1\gobble\gobble} \gobble\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\WriteOut}
% \changes{2.0e}{1991/06/01}{Macro added.} When a line has to be written
%    on the output file this can be done using the macro
%    \verb=\WriteOut=. It writes a `\texttt{.}' on the terminal and
%    \verb=\immediate=ly writes it argument to \verb=\outFile=.
%    \begin{macrocode}
\def\WriteOut#1{\maybeMsg{.}\immediate\write\outFile{#1}}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{Miscellaneous}
% \begin{macro}{\OffStart}
%    When the start of a block of code that has to be excluded from
%    the output is encountered the macro \verb=\Offstart= is called.
%    This macro sets the switch \verb=\ifOff= to \meta{true} and
%    increments the counter \verb=\offLevel= by $1$.
%    \begin{macrocode}
\def\OffStart{\Offtrue\advance\offLevel\@ne}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\OffEnd}
%    At the end of a block of code that is excluded the macro
%    \verb=\OffEnd= is called. It decrements the counter by $1$ and if
%    the value of the counter is $0$, it switches \verb=\ifOff= to
%    \meta{false}.
%    \begin{macrocode}
\def\OffEnd{%
    \advance\offLevel\m@ne
    \ifnum\offLevel=\z@
      \Offfalse
    \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\gobble}
% \changes{2.0a}{1991/05/25}{Macro added.}
%    A macro that has an argument and puts it in the bitbucket.
%    \begin{macrocode}
\def\gobble#1{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Endinput}
% \changes{2.0f}{1991/06/04}{Macro added.} When a \texttt{doc} file
%    contains a \verb+\endinput+ on a line by itself this normally
%    means that anything following in this file should be ignored.
%    Therefore we need a macro containing \verb=\endinput= as its
%    replacement text to check this against \verb=\inLine= (the
%    current line from the current input file). Of course the
%    backslash has to have the correct \verb=\catcode=. One way of
%    doing this is feeding \verb=\\= to the \verb=\string= operation
%    and afterwards removing one of the \verb=\= characters.
%    \begin{macrocode}
\edef\Endinput{\expandafter\gobble\string\\endinput}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\makeOther}
%    During the process of reading a file with \TeX\ code the category
%    code of all special characters has to be changed to \meta{other}.
%    The macro \verb=\makeOther= serves this purpose.
%    \begin{macrocode}
\def\makeOther#1{\catcode`#1=12\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\end}
% \changes{2.0h}{1991/06/19}{Macro added.} For now we want the \ds{}
%    program to be compatible with both plain \TeX\ and \LaTeX\@.
%    \LaTeX\ version 2.09 hides plain \TeX{}'s \verb=\end= command and
%    calls it \verb=\@@end=. We unhide it here.
%    \begin{macrocode}
\ifx\undefined\@@end\else\let\end\@@end\fi
%    \end{macrocode}
% \end{macro}
%
% \subsection{The evaluation of boolean expressions}
%
%    For clarity we repeat here the syntax for the boolean expressions
%    as it was given before:
%
%\DeleteShortVerb\|
%    \begin{tabular}{lcl}
%    \meta{Expression} & $::=$ & \meta{Primary}
%                                [\{\texttt{|}, \texttt{,}\}
%                                \meta{Primary}]*\\
%    \meta{Primary}    & $::=$ & 
%                         \meta{Secondary} [\texttt{\&}
%                              \meta{Secondary}]*\\
%    \meta{Secondary}  & $::=$ & 
%                         \meta{Terminal} $|$ \texttt{!}\meta{Secondary}
%                                  $|$ 
%                         \texttt{(}\meta{Expression}\texttt{)}\\
%    \end{tabular}
%
%    The \texttt{|} stands for disjunction, the \texttt{\&} stands for
%    conjunction and the \texttt{!}\ stands for negation. The
%    \meta{Terminal} is any sequence of letters and evaluates to
%    \meta{true} iff it occurs in the list of options that have to be
%    included.
%\MakeShortVerb\|
%
% \subsubsection{Parsing intermediate results} The parsing of the
%    boolean expressions has to be carried out very carefully. The
%    parsing of an expression starts at the `left side'.  Each term in
%    the expression is fully parsed before the next term is examined.
%    This parsing occurs inside a group, so macros can be redefined
%    without affecting the result of the total evaluation.  As a
%    consequence of this, the result of the evaluation has to be
%    passed to the outer level. For this purpose the control sequence
%    |\expressionValue| is used.
%
%    This is done as follows:\\ A macro |\doNext| is defined using the
%    |\edef| command.  It closes the group that was started when the
%    evaluation of this term started; then it calls the macro
%    |\PropagateValue| with the result of the evaluation as its
%    argument.  Note that because of the use of |\edef| the control
%    sequence |\expressionValue| will be replaced by either \texttt{TT}
%    or \texttt{TF} in the replacement text for |\doNext|. The macro is
%    then executed.
%\begin{verbatim}
%  \edef\doNext{\endgroup\noexpand\PropagateValue{\ExpressionValue}}%
%  \doNext
%\end{verbatim}
%
% \begin{macro}{\PropagateValue}
%    The `top level' definition of the macro |\PropagateValue| just
%    stores its (expanded) argument in |\expressionValue|. Note that
%    this macro is redefined during various phases of the parsing
%    process.
%    \begin{macrocode}
\def\PropagateValue#1\qStop{%
  \edef\ExpressionValue{#1}}
%    \end{macrocode}
%
% \begin{macro}{\ContinueExpression}
%    During the parsing of an \meta{Expression} the control sequence
%    |\PropagateValue| is |\let| to |\ContinueExpression|. The
%    argument of this macro is either \texttt{TT} or \texttt{TF},
%    being the result of the parsing of the current term.
%    \begin{macrocode}
\def\ContinueExpression#1{%
%    \end{macrocode}
%    A logical-or of this result and the accumulated result of all
%    previous terms is performed. This means that if the result so far
%    was \meta{true} it remains \meta{true}, otherwise the current
%    term determines the total result so far.
%    \begin{macrocode}
  \if\ExpressionValue
  \else
    \def\ExpressionValue{#1}%
  \fi
%    \end{macrocode}
%    Then we peek at the next token using |\futurelet| and call
%    |\ContinueExpressionX| to decide what to do, depending on the
%    next token.
%    \begin{macrocode}
  \futurelet\nextToken\ContinueExpressionX}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ContinueExpressionX}
%    When the macro |\ContinueExpressionX| is called, the next token
%    is stored in the control sequence |\nextToken|.
%    \begin{macrocode}
\def\ContinueExpressionX{%
%    \end{macrocode}
%\DeleteShortVerb\| 
%    If it is either \texttt{|} or \texttt{,} the
%    parsing has to continue and the next \meta{Primary} term is
%    considered.
%    \begin{macrocode}
  \ifx|\nextToken
    \def\doNext|{\Primary}%
  \else
    \ifx,\nextToken
      \def\doNext,{\Primary}%
    \else
%    \end{macrocode}
%    The only other character that can be encountered is the \texttt{)}
%    that closes the expression. In that case we propagate the value
%    accumulated so far to the outer level.
%    \begin{macrocode}
      \edef\doNext){\endgroup\noexpand\PropagateValue{\ExpressionValue}}
    \fi
  \fi
  \doNext}
%    \end{macrocode}
%    Note that the characters \texttt{|}, \texttt{,} and \texttt{)}
%    have remained in \TeX's input and have to be removed.  This is
%    accomplished by including the character in the parameter text of
%    the definition of the macro \verb=\doNext=.
% \end{macro}
%\MakeShortVerb\|
%
% \begin{macro}{\ContinuePrimary}
%    During the parsing of a \meta{Primary} term the control sequence
%    |\PropagateValue| is |\let| to |\ContinuePrimary|. The argument
%    of this macro is either \texttt{TT} or \texttt{TF}, being the
%    result of the parsing of the current term.
%    \begin{macrocode}
\def\ContinuePrimary#1{%
%    \end{macrocode}
%    A logical-and of this result and the accumulated result of all
%    previous terms is performed. This means that if the result so far
%    was \meta{false} it remains \meta{false}, otherwise the current
%    term determines the total result so far.
%    \begin{macrocode}
  \if\ExpressionValue
    \def\ExpressionValue{#1}%
  \fi
%    \end{macrocode}
%    Then we peek at the next token using |\futurelet| and call
%    |\ContinuePrimaryX| to decide what to do, depending on the
%    next token.
%    \begin{macrocode}
  \futurelet\nextToken\ContinuePrimaryX}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ContinuePrimaryX}
%    When the macro |\ContinuePrimaryX| is called, the next token is
%    stored in the control sequence |\nextToken|. Because this macro
%    needs to check if the next token is a `\texttt{\&}' we have to
%    change its category code before |\ContinuePrimaryX| is defined.
%    \begin{macrocode}
{\catcode`\&=12
\gdef\ContinuePrimaryX{%
%    \end{macrocode}
%    If the next token is \texttt{\&} the parsing has to continue and
%    the next \meta{Secondary} term is considered.
%    \begin{macrocode}
  \ifx&\nextToken
    \def\doNext&{\Secondary}%
  \else
%    \end{macrocode}
%    Any other character indicates the end of the current term.
%    In that case we propagate the value accumulated
%    so far to the outer level.
%    \begin{macrocode}
    \edef\doNext{\endgroup\noexpand\PropagateValue{\ExpressionValue}}%
  \fi
  \doNext}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\PropagateNegatedValue}
%    When a \meta{Secondary} term is preceded by a \texttt{!}\
%    character the the control sequence |\PropagateValue| is |\let| to
%    |\PropagateNegatedValue|. The only function of this macro is to
%    propagate the negation of its argument.
%    \begin{macrocode}
\def\PropagateNegatedValue#1{%
  \edef\doNext{\endgroup
    \noexpand\PropagateValue
    {\if#1%
       \noexpand\FalseExpression
     \else
       \noexpand\TrueExpression
     \fi}}%
  \doNext}
%    \end{macrocode}
% \end{macro}
%
% \subsubsection{The evaluation of the boolean expression}
%
% \begin{macro}{\Evaluate}
%    To start the parsing of a boolean expression the macro |\Evaluate|
%    is called by the macros |\testOption| and |\starOption|
%
%    |\Evaluate| encloses its argument with \texttt{()} and appends
%    |\qStop|.  The result is passed on to \verb=\Expression= for
%    further processing.  The parentheses are added to ease the
%    parsing by |\Expression|.
%    \begin{macrocode}
\def\Evaluate#1{%
  \Expression(#1)\qStop}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Expression}
%    The definition of the macro |\Expression| includes a `\texttt{(}'
%    in the parameter text of the macro; this causes the immediate
%    removal of the first parenthesis that encloses the expression.
%    \begin{macrocode}
\def\Expression({%
%    \end{macrocode}
%    It then starts a group,
%    \begin{macrocode}
  \begingroup
%    \end{macrocode}
%    initializes the
%    |\ExpressionValue| to \meta{false}
%    \begin{macrocode}
    \let\ExpressionValue\FalseExpression
%    \end{macrocode}
%    and calls |\Primary| to
%    continue the parsing process.
%    \begin{macrocode}
    \let\PropagateValue\ContinueExpression
    \Primary}
%    \end{macrocode}
%    |\ExpressionValue| is set to \meta{false} because the logical-or
%    of this value and the result of the first term will be performed.
% \end{macro}
%
% \begin{macro}{\Primary}
%    The macro |\Primary| is used to parse \meta{Primary} terms. Like
%    |\expression| it starts a group. It then initiates the
%    |ExpressionValue| appropriately and calls |\Secondary| to
%    continue the parsing process.
%    \begin{macrocode}
\def\Primary{%
  \begingroup
    \let\ExpressionValue\TrueExpression
    \let\PropagateValue\ContinuePrimary
    \Secondary}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Secondary}
%    As can be seen in the syntax of boolean expressions a
%    \meta{Secondary} term can contain three different kinds of term.
%    When the first token of the \meta{Secondary} is a `\texttt{!}' the
%    result of the parsing of the term should be negated; when the
%    first token is a `\texttt{(}'it indicates the start of a
%    subexpression. Any other token is part of a \meta{Terminal}.
%
%    Therefore we have to inspect the first token of the term and decide
%    what to do. This is achieved by using |\futurelet| and calling
%    |\SecondaryX|.
%    \begin{macrocode}
\def\Secondary{%
  \futurelet\nextToken\SecondaryX}
%    \end{macrocode}
%
% \begin{macro}{\SecondaryX}
%    When this macro is called, the control sequence |\nextToken|
%    contains a copy of the first character of the term being inspected.
%    \begin{macrocode}
\def\SecondaryX{%
%    \end{macrocode}
%    When |\nextToken| contains a `\texttt{(}' we make sure that calling
%    |\doNext| is actually a call of |\Expression| to
%    parse the subexpression.
%    \begin{macrocode}
  \ifx\nextToken(\let\doNext\Expression\else
%    \end{macrocode}
%    When |\nextToken| contains a `\texttt{!}' we make sure that calling
%    |\doNext| is actually a call of |\Negate| to negate the result
%    of the following term.
%    \begin{macrocode}
  \ifx\nextToken!\let\doNext\Negate\else
%    \end{macrocode}
%    If |\nextToken| contains anything else |\doNext| is |\let|
%    to |\Terminal|.
%    \begin{macrocode}
                 \let\doNext\Terminal\fi\fi
%    \end{macrocode}
%    The call of |\doNext| will now start the proper macro.
%    \begin{macrocode}
  \doNext}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\Negate}
%    When during the parsing of a \meta{Secondary} term a `|!|' is
%    encountered the result has to be negated. Therefore a new group
%    is started, |\PropagateValue| is made equivalent to
%    |\PropagateNegatedValue| and |\Secondary| is called again.
%    \begin{macrocode}
\def\Negate!{%
  \begingroup
    \let\PropagateValue\PropagateNegatedValue
    \Secondary}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\Terminal}
%    The parsing of a \meta{Terminal} is done token by token. Therefore
%    we accumulate the tokens that make up the \meta{Terminal} in
%    the token register |\TerminalString|. This register is cleared and
%    processing starts with calling |\TerminalX|.
%    \begin{macrocode}
\def\Terminal{%
  \global\TerminalString{}\TerminalX}
%    \end{macrocode}
%
% \begin{macro}{\TerminalX}
%    The macro |\TerminalX| scoops up the next token and appends it to
%    |\TerminalString|. It can do that because the token has been
%    examined before by another macro, either |\Secondary| (at the start
%    of this process) or |\TerminalXX| (during this process).
%    \begin{macrocode}
\def\TerminalX#1{%
  \global\TerminalString\expandafter{\the\TerminalString#1}%
%    \end{macrocode}
%    Now we have to peek at the next token again to decide what the
%    next action should be. The decision will be taken by |\TerminalXX|.
%    \begin{macrocode}
  \futurelet\nextToken\TerminalXX}
%    \end{macrocode}
%
% \begin{macro}{\TerminalXX}
%\DeleteShortVerb\|\MakeShortVerb\+ 
%    The macro +\TerminalXX+ uses the
%    contents of +\nextToken+ to decide what the next action should
%    be. When +\nextToken+ contains one of `\texttt{\&}',
%    `\texttt{|}', `\texttt{,}', `\texttt{!}', `\texttt{(}' or
%    `\texttt{)}' the end of the \meta{Terminal} has been found and
%    processing should stop; when +\nextToken+ contains any other
%    character it is part of the \meta{Terminal}.
%
%    During the definition of the macro the `\texttt{\&}' should be
%    \texttt{\&$_{12}$} so its category code needs to be changed.
%    \begin{macrocode}
{\catcode`\&=12
\gdef\TerminalXX{%
%    \end{macrocode}
%    A couple of +\ifx+ tests are needed to decide whether the
%    \meta{Terminal} that is being accumulated has ended. We use
%    the switch +\ifTerminal+ to indicate whether this has happened
%    or not. It is initialized to \meta{false} (meaning: ``the end has
%    been found'').
%    \begin{macrocode}
  \Terminalfalse
  \ifx &\nextToken \else
  \ifx |\nextToken \else
  \ifx ,\nextToken \else
  \ifx !\nextToken \else
  \ifx (\nextToken \else
  \ifx )\nextToken \else
%    \end{macrocode}
%    If none of the above tests are \meta{true} the end of the
%    \meta{Terminal} has {\em not\/} been found, so the switch is
%    set to \meta{true}.
%    \begin{macrocode}
    \Terminaltrue
  \fi\fi\fi\fi\fi\fi
%    \end{macrocode}
%    If the \meta{Terminal} has not ended the next character can be
%    appended to +\TerminalString+. This is accomplished by the
%    (recursive) call of +\TerminalX+.
%    \begin{macrocode}
  \ifTerminal
    \let\doNext\TerminalX
%    \end{macrocode}
%    When, on the other hand, the end {\em was\/} found, we have to
%    check whether the option (that is now stored in
%    +\TerminalString+) was amongst the options that needed to be
%    included in the output.  This check is performed by the macro
%    +\SetValue+. It gives +\ExpressionValue+ the appropriate value.
%    The token register is cleared when its contents are no longer
%    needed.
%    \begin{macrocode}
  \else
    \edef\doNext{\noexpand\SetValue{\the\TerminalString}}%
    \global\TerminalString{}%
  \fi
%    \end{macrocode}
%    At this point the macro +\doNext+ `points' to the macro that
%    should be executed, so we call it. The second brace closes the
%    group that was started to keep the category change of the
%    character `\texttt{\&}' local.
%    \begin{macrocode}
  \doNext}
}
%    \end{macrocode}
%\MakeShortVerb\|\DeleteShortVerb\+
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\SetValue}
%    The macro |\Setvalue| has to check whether its argument is included
%    in the option list, stored in |\Options| as a comma-separated list.
%    \begin{macrocode}
\def\SetValue#1{%
%    \end{macrocode}
%    The actual check will be performed by a temporary macro |\tmp|.
%    The argument of |\SetValue| is made part of its argument text.
%    The argument text is delimited by |\qStop|. When |\tmp| is
%    executed it will have both the expanded optionlist and the
%    argument of |\SetValue| amongst its parameters. When the argument
%    of |\Setvalue| does {\em not\/} appear in |\Options| the second
%    argument of |\tmp| will be empty.
%    \begin{macrocode}
  \def\tmp##1,#1,##2\qStop{%
%    \end{macrocode}
%    To be able to check if the second argument is empty, we store it
%    in a temporary control sequence |\tmp|.
%    \begin{macrocode}
    \def\tmp{##2}%
%    \end{macrocode}
%    Then we define |\doNext|, using |\edef|, to propagate the value
%    of this expression to the outer level. Because we use |\edef|,
%    the replacement text of |\doNext| will contain either
%\begin{verbatim}
%    \PropagateValue{TF}
%\end{verbatim}
%    or
%\begin{verbatim}
%    \PropagateValue{FF}
%\end{verbatim}
%    \begin{macrocode}
    \edef\doNext{\noexpand\PropagateValue
      {\ifx\tmp\empty\FalseExpression\else\TrueExpression\fi}}%
%    \end{macrocode}
%    The last action of |\tmp| is to call the macro |\doNext| that it
%    has just defined.
%    \begin{macrocode}
    \doNext}%
%    \end{macrocode}
%    As stated before, we need the expansion of |\Options| in the
%    arguments of |\tmp|, therefore we have to delay the expansion of
%    |\tmp| using |\expandafter| until |\Options| has been expanded.
%    \begin{macrocode}
  \expandafter\tmp\expandafter,\Options,#1,\qStop}
%    \end{macrocode}
% \end{macro}
%
%  \subsection{Processing the input lines}
%
% \begin{macro}{\copyLine}
%    The macro \verb=\copyLine= writes its argument (which has to be
%    delimited with \verb=\endLine=) on the output file using the
%    macro \verb=\WriteOut=.  If statistics are included, the counter
%    \verb=\codeLinesPassed= is incremented by $1$.
%    \begin{macrocode}
\def\copyLine#1\endLine{%
%<*stats>
  \advance\codeLinesPassed\@ne
%</stats>
  \WriteOut{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\removeLine}
%    The macro |\removeLine| throws its argument (which has to be
%    delimited with |\endLine|) away. It writes a `\texttt{\%}' on the
%    terminal if messages are enabled.
%    \begin{macrocode}
\def\removeLine#1\endLine{%
    \maybeMsg{\perCent}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\removeComment}
%    The macro \verb=\removeComment= has nearly the same function as the
%    macro \verb=\removeLine=, except that when statistics are included
%    in the program the removed comment is counted. If statistics are
%    {\em not\/} included the macro \verb=\removeComment= is \verb=\let=
%    to \verb=\removeLine=.
%    \begin{macrocode}
%<*stats>
\def\removeComment#1\endLine{%
    \advance\commentsRemoved\@ne
    \maybeMsg{\perCent}}
%</stats>
%<-stats>\let\removeComment\removeLine
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\putMetaComment}
%    If a line starts with two consecutive percent signs, it is
%    considered to be a {\em MetaComment\/}. Such a comment line is
%    passed on to the output file unmodified.
%    \begin{macrocode}
\def\putMetaComment#1\endLine{%
%    \end{macrocode}
%    To `close' a pending option the macro \verb=\closeOption= is
%    called.
%    \begin{macrocode}
  \closeOption%
%    \end{macrocode}
%    If statistics are included the line is counted.
%    \begin{macrocode}
%<*stats>
  \advance\commentsPassed\@ne
%</stats>
%    \end{macrocode}
%    The macro \verb=\putMetaComment= has one argument, delimited with
%    \verb=\endLine=. But because of earlier processing the argument
%    is discarded and \verb=\inLine=, which contains the complete line
%    as it was read from \verb=\inFile=, is written on
%    \verb=\outFile=.
%    \begin{macrocode}
  \WriteOut{\inLine}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processLine}
%    Each line that is read from the input stream has to be processed
%    to see if it has to be written on the output stream. This task
%    is performed by calling the macro \verb=\processLine=.
%    The macro increments the counter \verb=\processedLines= by $1$ if
%    statistics are included. Then it peeks at the next character
%    in the input stream by using \verb=\futurelet= and calling
%    \verb=\processLineX= to do the work.
%    \begin{macrocode}
\def\processLine{%
%<*stats>
  \advance\processedLines\@ne
%</stats>
  \futurelet\nextToken\processLineX}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processLineX}
%    The macro \verb=\processLineX= has to check whether the current
%    line has to be included in the output or not. In order to do
%    that, it needs to check whether the line starts with a
%    `\texttt{\%}'.  Therefore the macro is globally defined within a
%    group. Within this group the category code of `\texttt{\%}' is
%    changed to 12 (other).  Because a comment character is needed,
%    the category code of `\texttt{\#}' is changed to 14 (comment
%    character).
%
%    When this macro is executed \TeX\ has stored the next token in
%    the input stream in \verb=\nextToken=. If it is a `\texttt{\%}'
%    further processing has to be done by \verb=\processLineXX=;
%    otherwise we close the current option.\\ The setting of the
%    switch \verb=\ifOff= determines whether the current line is
%    either removed or copied.  Whatever action has to be taken, it
%    will be stored in the macro \verb=\doNext=, after the processing
%    of the \verb=\if=-statements is finished.
%    \begin{macrocode}
\begingroup
\catcode`\%=12 \catcode`\#=14
\gdef\processLineX{#
  \ifx%\nextToken
    \let\doNext\processLineXX
  \else
    \closeOption
    \ifOff
      \let\doNext\removeLine
    \else
      \let\doNext\copyLine
    \fi
  \fi
  \doNext}
\endgroup
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processLineXX}
%    The macro \verb=\processLineXX= simply peeks at the next token and
%    calls \verb=\processLineXXX= to do whatever is necessary.
%    \begin{macrocode}
\def\processLineXX#1{%
  \futurelet\nextToken\processLineXXX}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processLineXXX}
%    This macro is also defined within a group, like the macro
%    \verb=\processLineX=, because it also has to check if the next
%    token in the input stream is a `\texttt{\%}' character.
%
%    If the second token in the current line happens to be a
%    `\texttt{\%}', a \meta{MetaComment} has been found. This has to
%    be copied in its entirety to the output.  Another possible second
%    character is `\texttt{<}', which introduces a guard expression.
%    The processing of such an expression is started by calling
%    \verb=\checkOption=.
%
%    When the token was neither a `\texttt{\%}' nor a `\texttt{<}',
%    the line contains a normal comment that has to be removed. In
%    that case the current option is closed.  The execution of the
%    macro \verb=\doNext= will have the desired effect.  Note that the
%    group is closed, so that all characters will have the category
%    code that was in effect when the group was started.
%    \begin{macrocode}
\begingroup
\catcode`\%=12 \catcode`\#=14
\gdef\processLineXXX{#
  \ifx%\nextToken \let\doNext\putMetaComment \else
  \ifx<\nextToken \let\doNext\checkOption    \else
             \closeOption
             \let\doNext\removeComment  \fi\fi
  \doNext}
\endgroup
%    \end{macrocode}
% \end{macro}
%
%  \subsection{The handling of options}
%
% \begin{macro}{\checkOption}
%    When the macros that process a line have found that the line
%    starts with `\texttt{\%<}', a guard line has been encountered.
%    The first character of a guard can be an asterisk (\texttt{*}), a
%    slash (\texttt{/}) a plus (\texttt{+}), a minus (\texttt{-}) or
%    any other character that can be found in an option name. This
%    means that we have to peek at the next token and call
%    \verb=\checkOptionsX= to decide what kind of guard we have. Note
%    that the way that \verb=\checkOption= is defined, means it
%    removes the `\texttt{<}' from the input stream.
%    \begin{macrocode}
\def\checkOption<{%
  \futurelet\nextToken\checkOptionsX}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\checkOptionsX}
%    The macro \verb=\checkOptionsX= compares the contents of
%    \verb=\nextToken= with the four possible leading characters and
%    decides what to do. When the switch \verb=\ifOff= is \meta{true},
%    the current line will simply be removed.
%    \begin{macrocode}
\def\checkOptionsX{%
  \ifx*\nextToken \let\doNext\starOption  \else
  \ifx/\nextToken \let\doNext\slashOption \else
  \ifOff          \let\doNext\removeLine  \else
  \ifx+\nextToken \let\doNext\plusOption  \else
  \ifx-\nextToken \let\doNext\minusOption \else
                  \let\doNext\doOption    \fi\fi\fi\fi\fi
  \doNext}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\closeOption}
%    The macro \verb=\closeOption= is used to `close' options. This
%    means nothing more than writing a `\texttt{>}' on the terminal when
%    necessary.
%
%    If \verb=\lastOption= is \verb=\empty= nothing has to be done
%    because no option has started since the last one was closed. In
%    the other case, the `\texttt{>}' is written on the terminal if
%    messages are enabled.  Also, the \verb=\lastOption= is made
%    \verb=\empty=.
%    \begin{macrocode}
\def\closeOption{%
  \ifx\lastOption\empty\else
    \maybeMsg{>}\let\lastOption\empty\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\doOption}
%    When no guard modifier is found by \verb=\checkOptionsX=, the
%    macro \verb=\doOption= is called.  It calls \verb=\testOption=
%    with an empty first argument to evaluate the boolean expression.
%    The result of this evaluation is stored in
%    \verb=\ExpressionValue=. This guard only affects the current
%    line, so depending on the result of the test
%    \verb=\if\ExpressionValue=, the current line is either copied to
%    the output stream or removed.
%    \begin{macrocode}
\def\doOption#1>{%
  \testOption{}{#1}%
  \if\ExpressionValue \expandafter\copyLine
  \else         \expandafter\removeLine \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\plusOption}
%    When a `\texttt{+}' is found as a guard modifier,
%    \verb=\plusOption= is called. This macro is very similar to
%    \verb=\doOption=, the only difference being that the `\texttt{+}'
%    is now passed as the first argument to \verb=\testOption=.
%    \begin{macrocode}
\def\plusOption+#1>{%
  \testOption+{#1}%
  \if\ExpressionValue \expandafter\copyLine
  \else         \expandafter\removeLine \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\minusOption}
%    When a `\texttt{-}' is found as a guard modifier,
%    \verb=\minusOption= is called. This macro is very similar to
%    \verb=\plusOption=, the difference is that \verb=\removeLine= and
%    \verb=\copyLine= have been interchanged.
%    \begin{macrocode}
\def\minusOption-#1>{%
  \testOption-{#1}%
  \if\ExpressionValue \expandafter\removeLine
  \else         \expandafter\copyLine \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\starOption}
%    When a `\texttt{*}' is found as a guard modifier,
%    \verb=\starOption= is called. In this case a block of code will
%    be included in the output on the condition that the guard
%    expression evaluates to \meta{true}.
%    \begin{macrocode}
\def\starOption*#1>{%
%    \end{macrocode}
%    First we close any pending option and optionally write
%    a message to the terminal to indicate that a new option starts
%    here.
%    \begin{macrocode}
  \closeOption
  \maybeMsg{<*#1}%
%    \end{macrocode}
%    Then we push the current contents of \verb=\blockHead= on the
%    stack of blocks, \verb=\guardStack= and increment  the counter
%    \verb=\blockLevel= to indicate that we are now one level of
%    nesting deeper.
% \changes{2.0k}{1992/04/06}{Use new stack mechanism}
% \changes{2.0k}{1992/04/09}{The macro that holds the guard needs to be
%    expanded}
%    \begin{macrocode}
  \expandafter\push\expandafter\guardStack\expandafter{\blockHead}%
  \advance\blockLevel\@ne
%    \end{macrocode}
%    The guard for this block of code is now stored in
%    \verb=\blockHead=.
%    \begin{macrocode}
  \def\blockHead{#1}%
%    \end{macrocode}
%    If this block of code occurs inside another block of code that is
%    {\em not\/} included in the output, we increment the counter
%    |\offLevel|. In that case the guard expression will not be
%    evaluated, because a block inside another block that is excluded
%    from the output will also be excluded, regardless of the
%    evaluation of its guard.
%    \begin{macrocode}
  \ifOff
    \advance\offLevel\@ne
%    \end{macrocode}
%    When the switch \verb=\ifOff= has the value \meta{false}, we have
%    to evaluate the guard expression. This is done by calling
%    |\Evaluate|. That macro leaves the result in |\ExpressionValue|.
%    If the result turns out to be \meta{false}, we start an `Off'
%    section by calling \verb=\Offstart=.
%    \begin{macrocode}
  \else
    \Evaluate{#1}%
    \if\ExpressionValue\else\OffStart\fi
  \fi
%    \end{macrocode}
%    The current line always has to be removed, because it only contains
%    the guard and possibly a comment.
%    \begin{macrocode}
  \removeLine}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\slashOption}
%    The macro \verb=\slashOption= is the counter part to
%    \verb=\starOption=.  It indicates the end of a block of
%    conditionally included code.  We store the argument in the
%    temporary control sequence \verb=\tmp=.
%    \begin{macrocode}
\def\slashOption/#1>{%
  \def\tmp{#1}%
%    \end{macrocode}
%    When the counter \verb=\blockLevel= has a value less than $1$,
%    this `end-of-block' line has no corresponding `start-of-block'.
%    Therefore we signal an error and ignore this end of block.
%    \begin{macrocode}
  \ifnum\blockLevel<\@ne
    \errmessage{Spurious end block </\tmp> ignored}%
%    \end{macrocode}
%    Next we compare the contents of \verb=\tmp= with the contents
%    of \verb=\blockHead=. The latter macro contains the last guard for
%    a block of code that was encountered. If the contents match, we
%    pop the previous guard from the stack.
%    \changes{2.0k}{1992/04/06}{Use new stack mechanism}
%    \begin{macrocode}
  \else
    \ifx\tmp\blockHead
      \pop\guardStack\blockHead
%    \end{macrocode}
%    When the contents of the two macros don't match something is
%    amiss. We signal this to the user, but accept the `end-of-block'.
%\note{Is this the desired behaviour??}
%    \begin{macrocode}
    \else
      \errmessage{Found </\tmp> instead of <*\blockHead>}%
    \fi
%    \end{macrocode}
%    When the end of a block of optionally included code is encountered
%    we optionally signal this on the terminal and decrement the counter
%    \verb=\offLevel=.
%    \begin{macrocode}
    \maybeMsg{>}%
    \advance\blockLevel\m@ne
%    \end{macrocode}
%    The last check that has to be made is for the value of the switch
%    \verb=\ifOff=. If it is \meta{true} we call \verb=\Offend= to
%    take the appropriate actions. Finally we remove the current line.
%    \begin{macrocode}
    \ifOff\OffEnd\fi
  \fi
  \removeLine}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\testOption}
%    The macro \verb=\testOption= is used by the macros that process
%    the one line guards. First it checks if the guard expression
%    is present. To accomplish that, it stores the second argument
%    in a temporary control sequence.
%    \begin{macrocode}
\def\testOption#1#2{%
  \def\tmp{#2}%
%    \end{macrocode}
%    When the macro \verb=\tmp= is empty, something is missing.
%    We signal this to the user and use a dummy guard.
%    \begin{macrocode}
  \ifx\tmp\empty
    \errmessage{Missing option expression!}%
    \def\tmp{MISSING OPTION}%
%    \end{macrocode}
%    When the guard is present we store a `\texttt{<}', the guard
%    modifier and the guard in \verb=\tmp= for future use.
%    \begin{macrocode}
  \else
    \def\tmp{<#1#2}%
  \fi
%    \end{macrocode}
%    The complete guard is now stored in \verb=\tmp=. We use it to
%    compare with the last guard encountered. If they are the same,
%    there is nothing more to do.
%    \begin{macrocode}
  \ifx\tmp\lastOption
%    \end{macrocode}
%    If they are {\em not\/} the same the current line belongs to a
%    different option than the last line with a guard that has been
%    processed.  Therefore we close a possibly pending option and make
%    \verb=\lastOption= point to the contents of \verb=\tmp=.
%    \begin{macrocode}
  \else
    \closeOption
    \let\lastOption\tmp
%    \end{macrocode}
%    Then we optionally signal the start of a new option on the
%    terminal and evaluate the guard expression.
%    \begin{macrocode}
    \maybeMsg{\lastOption}%
    \Evaluate{#2}%
  \fi}
%    \end{macrocode}
% \end{macro}
%
%    \subsection{Batchfile commands}
%
% \begin{macro}{\generateFile}
%    The macro \verb=\generateFile= can be used in batch files to
%    instruct the \ds{} program to generate an output file from
%    possibly multiple input files. The first argument is the file to
%    produce, the second argument indicates if the user has to be
%    consulted before an existing file is overwritten. The third
%    argument contains the list of input files. Each entry should have
%    the format
%    \verb=\from{=\meta{filename.ext}\verb=}{=\meta{options}\verb=}=.
%
%    The macro starts by displaying a message on the terminal to
%    indicate which file is going to be made.  The switch
%    \verb=\ifGenerate= is initially set to \meta{true}.
%
% \changes{2.0e}{1991/06/01}{changed interface to 
%                          \texttt{\bsl generatefileX}}
% \changes{2.0e}{1991/06/01}{Added pre- and postamble support}
%    \begin{macrocode}
\def\generateFile#1#2#3{{%
  \Msg{^^JGenerating file \WriteToDir#1^^J}%
  \Generatetrue
%    \end{macrocode}
%    Next we decide if we have to be careful about overwriting
%    existing files. If the user specified `\texttt{t}' we will ask him
%    if he wants to overwrite an existing file. If he specified anything
%    else we simply go ahead.
%
%    In order to prevent havoc when \verb=#2= contains garbage or when
%    it is empty we use a comparison of control sequences instead
%    of the direct comparison with \verb=\if#2t=.
%    \begin{macrocode}
  \def\tmp{#2}\def\t{t}%
  \ifx\tmp\t
%    \end{macrocode}
%    When the second argument to \verb=\generateFile= was `\texttt{t}'
%    we try to open a file with the name of the output file for
%    reading.  If this succeeds the file exists and we ask the user if
%    he wants to overwrite the file.
% \changes{2.0p}{1992/06/26}{Added `WriteToDir (FMi).}
%    \begin{macrocode}
    \immediate\openin\inFile\WriteToDir#1\relax
    \ifeof\inFile\else
      \Ask\answer{File \WriteToDir#1 already exists 
                  \ifx\@empty\WriteToDir somewhere \fi
                  on the system.^^J% 
                  Overwrite it%
                  \ifx\@empty\WriteToDir\space if necessary\fi
                  ? [y/n]}%
%    \end{macrocode}
%    We set the switch \verb=\ifGenerate= according to his answer. We
%    allow for both ``\texttt{y}'' and ``\texttt{yes}''.
%    \begin{macrocode}
      \ifx\y  \answer \Generatetrue \else
      \ifx\yes\answer \Generatetrue \else
                      \Generatefalse\fi\fi\fi
%    \end{macrocode}
%    Don't forget to close the file just opened as we want to write
%    to it.
%    \begin{macrocode}
    \immediate\closein\inFile
  \fi
%    \end{macrocode}
%    We store the name of the output file in the macro
%    \verb=\outFileName= for future use.
%    \begin{macrocode}
  \ifGenerate
    \def\outFileName{#1}%
%    \end{macrocode}
%    The macro |\from| will be used for multiple purposes in the
%    following code.
%
%    First |\from| is defined to write a line to the output file,
%    containing the name of the input file, together with the
%    options that are included for that file.
% \changes{2.2g}{1994/03/13}{Use $>$ instead of ! for empty test.}
%    \begin{macrocode}
    \def\from##1##2{\WriteOut{\DoubleperCent ##1 \if>##2>\else
                              \space (with options: `##2')\fi}}%
%    \end{macrocode}
%    Older versions of the previous code contained \verb=\if!##2!=
%    which has a funny effect if you use \verb=\from= with a negated
%    (\verb=!=) module.
%
%    The macro \verb=\ReferenceLines= is defined using an \verb=\edef=
%    instruction. This means that all macros in the replacement text
%    will be expanded. The third argument to \verb=\generateFile= is
%    included in the replacement text for \verb=\ReferenceLines=,
%    while the above definition of \verb=\from= is still valid. Thus,
%    for each occurrence of |\from| in the third argument of
%    |\generateFile| the current replacement text of |\from| is
%    included in |\ReferenceLines|.
%    \begin{macrocode}
    \edef\ReferenceLines{%
        \WriteOut{\DoubleperCent ^^J%
                  \DoubleperCent The original source files were:^^J%
                  \DoubleperCent }%
        #3}%
    \def\from##1##2{\edef\inFileName{\inFileName##1\space}}
    \def\inFileName{}#3
%    \end{macrocode}
%    The macro \verb=\ReferenceLines= will be called by
%    \verb=\WritePreamble=.  Because it was defined using an expanded
%    definition we can now safely give \verb=\from= another meaning.
%    This time it is to define the macros \verb=\inFileName= and
%    \verb=\Options= to contain its two arguments. These macros are
%    then used by \verb=\generateFileX=.
% \changes{2.0f}{1991/06/04}{Allow for a control sequence as options
%    argument}
%    \begin{macrocode}
    \def\from##1##2{\def\inFileName{##1}%
                    \edef\Options{##2}%
                    \generateFileX}%
%    \end{macrocode}
%    Now we can finally open the output file, this time for writing.
% \changes{2.0q}{1992/07/01}{Preceded filename by `WriteToDir}
%    \begin{macrocode}
    \immediate\openout\outFile\WriteToDir#1\relax
%    \end{macrocode}
%    First we write a preamble to the file,
%    \begin{macrocode}
    \WritePreamble
%    \end{macrocode}
%    then we execute the commands that are in the third
%    argument to \verb=\Generatefile=.
%    \begin{macrocode}
    #3%
%    \end{macrocode}
%    The last action is to write a postamble to the file and close it.
%    \begin{macrocode}
    \WritePostamble
    \immediate\closeout\outFile
    \let\ReferenceLines\OriginalRefs
  \else
%    \end{macrocode}
%    In case we were not allowed to overwrite an existing file
%    we inform the user that we are {\em not\/} generating his file.
%    \begin{macrocode}
    \Msg{Not generating file #1^^J}%
  \fi}}
%    \end{macrocode}
%
%  \begin{macro}{\WriteToDir}
%    The macro |\WriteToDir| is either empty or holds the prefix
%    necessary to read a file from the current directory. Under UNIX
%    this is |./| but a lot of other systems addopted this concept. If
%    we can prefix the
% \changes{2.0p}{1992/06/26}{Macro added (FMi).}
% \changes{2.2a}{1993/12/02}{check texsys file}
% \changes{2.2d}{1994/01/20}{do not read dircheck/texsys file}
%    \begin{macrocode}
\ifx\@currdir\@undefined
  \def\WriteToDir{}
\else
  \let\WriteToDir\@currdir
\fi
%    \end{macrocode}
%  \end{macro}
%
%    To support command files that were written for the first version
%    of \ds{} the commands |\include| and |\processFile|
%    are defined here. The use of this interface is not recommended
%    as it may be removed in a future release of \ds{}.
%
% \begin{macro}{\include}
% \changes{2.0f}{1991/06/04}{Macro added} To provide the \ds{} program
%    with a list of options that should be included in the output the
%    command \verb=\include{=\meta{Options}\verb=}= can be used. This
%    macro is meant to be used in conjunction with the
%    \verb=\processFile= command.
%    \begin{macrocode}
\def\include#1{\def\Options{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processFile}
% \changes{2.0f}{1991/06/04}{Supply \texttt{\bsl generateFile} with
%                          \texttt{\bsl Options}}
%\DeleteShortVerb\|
%    The macro
%    \verb=\processFile{=\meta{filename}\verb=}{=\meta{inext}\verb=}{=%
%\unskip\meta{outext}\verb=}{=\meta{t{\fontshape{n}\ttfamily|}f}\verb=}=
%    can be used when a single input file is used to produce
%    a single output file. The macro is also used in the interactive
%    mode of the \ds{} program.
%\MakeShortVerb\|
%
%    The arguments \meta{inext} and \meta{outext} denote the
%    extensions of the input and output files respectively. The fourth
%    argument can be used to specify if an existing file should be
%    overwritten without asking. If \meta{t} is specified the program
%    will ask for permission before overwriting an existing file.
%
%    This macro is defined using the more generic macro |\generateFile|.
%    \begin{macrocode}
\def\processFile#1#2#3#4{%
  \generateFile{#1.#3}{#4}{\from{#1.#2}{\Options}}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\processfile}
% \begin{macro}{\generatefile}
% \changes{2.0m}{1991/04/23}{Now issue a warning when \texttt{\bsl
%    processfile} or \texttt{\bsl generatefile} are used} An earlier
%    version of \ds{} used the commands |\processfile| and
%    |\generatefile| instead of the commands as they are defined in
%    this version. To remain upwards compatible, we still provide
%    these commands, but issue a warning when they are used.
%    \begin{macrocode}
\def\processfile{\Msg{%
    ^^Jplease use \string\processFile\space instead of 
       \string\processfile!^^J}%
    \processFile}
\def\generatefile{\Msg{%
    ^^Jplease use \string\generateFile\space instead of 
      \string\generatefile!^^J}%
    \generateFile}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\generateFileX}
% \changes{2.0f}{1991/06/04}{Added check for lines with \texttt{\bsl
%    endinput}} This macro is called by |\generateFile| for each
%    occurrence in its third argument of the control sequence |\from|.
%
%    A line is displayed on the terminal, telling the user what we are
%    about to do.
%    \begin{macrocode}
\def\generateFileX{{%
  \Msg{Processing File \inFileName
       \ifx\Options\empty\else\space(\Options)\fi
       \space -> \outFileName^^J}%
%    \end{macrocode}
%    Then we try to open the input file. If this doesn't succeed, we
%    tell the user so and nothing else happens.
%    \begin{macrocode}
  \immediate\openin\inFile\inFileName\relax
  \ifeof\inFile
    \errmessage{Cannot find file \inFileName}%
  \else
%    \end{macrocode}
%    When the input file was successfully opened, we change the category
%    code of a lot of characters to \meta{other} and make sure that
%    no extra spaces appear in the lines read by setting the
%    |\endlinechar| to $-1$.
%    \begin{macrocode}
    \makeOther\ \makeOther\\\makeOther\$%
    \makeOther\#\makeOther\^\makeOther\^^K%
    \makeOther\_\makeOther\^^A\makeOther\%%
    \makeOther\~\makeOther\{\makeOther\}\makeOther\&%
    \endlinechar-1\relax
%    \end{macrocode}
%    Then we start a loop to process the lines in the file one by one.
%    \begin{macrocode}
    \loop
      \read\inFile to\inLine
%    \end{macrocode}
%    The first thing we check is whether the current line
%    contains an |\endinput|. To allow also real |\endinput|
%    commands in the source file, |\endinput| is only recognized
%    when it occurs directly at the beginning of a line.
%    \begin{macrocode}
      \ifx\inLine\Endinput
%    \end{macrocode}
%    In this case we output a message to inform the programmer (in
%    case this was a mistake) and end the loop immediately by setting
%    \verb=Continue= to \meta{false}. Note that \verb=\endinput= is
%    not placed into the output file. This is important in cases where
%    the output file is generated from several \texttt{doc} files.
%    \begin{macrocode}
        \Msg{File \inFileName\space ended by \string\endinput.}%
        \Continuefalse
      \else
%    \end{macrocode}
% \changes{2.0j}{1992/03/03}{First check for end of file before check
%    for empty lines} When the end of the file is found we have to
%    interrupt the loop.
%    \begin{macrocode}
       \ifeof\inFile
         \Continuefalse
%    \end{macrocode}
% \changes{2.0i}{1991/06/27}{Added check for consecutive empty lines}
%    If the file did not end we check if the input line is empty.
%    If it is, the counter \verb=\emptyLines= is incremented.
%    \begin{macrocode}
       \else
         \Continuetrue
         \ifx\inLine\empty
            \advance\emptyLines\@ne
          \else
            \emptyLines\z@
          \fi
%    \end{macrocode}
%    When the number of empty lines seen so far exceeds 1, we skip them.
%    If it doesn't, the expansion of |\inLine| is fed to |\processLine|
%    with |\endLine| appended to indicate the end of the line.
%    \begin{macrocode}
          \ifnum \emptyLines<2
            \expandafter\processLine\inLine\endLine
          \else
            \maybeMsg{/}%
          \fi
       \fi
      \fi
%    \end{macrocode}
%    When the processing of the line is finished, we check if there is
%    more to do, in which case we repeat the loop.
%    \begin{macrocode}
    \ifContinue
    \repeat
%    \end{macrocode}
%    Any option that was not properly `closed' is closed now and the
%    input file is closed.
%    \begin{macrocode}
    \closeOption
    \immediate\closein\inFile
%    \end{macrocode}
%    If the user was interested in statistics, we inform him of the
%    number of lines processed, the number of comments that were
%    either removed or passed and the number of codelines that were
%    written to the output file. Also the totals are updated.
%    \begin{macrocode}
%<*stats>
    \Msg{Lines \space processed: \the\processedLines^^J%
         Comments removed: \the\commentsRemoved^^J%
         Comments \space passed: \the\commentsPassed^^J%
         Codelines passed: \the\codeLinesPassed^^J}%
      \global\advance\TotalprocessedLines  by \processedLines
      \global\advance\TotalcommentsRemoved by \commentsRemoved
      \global\advance\TotalcommentsPassed  by \commentsPassed
      \global\advance\TotalcodeLinesPassed by \codeLinesPassed
      \global\advance\NumberOfFiles by \@ne
%</stats>
    \fi}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\WritePreamble}
% \changes{2.0e}{1991/06/01}{Macro added.}
%    If there is no \verb=\preamble= command in the batch file, or
%    the \ds{} program is used in interactive mode a
%    default preamble will be written to the output file. All
%    lines in this preamble are preceded by two percent characters
%    to prevent them from being removed from the file by the \ds{}
%    program.
%
%    First a couple of lines, stating what file it is and how it was
%    created.
%    \begin{macrocode}
\def\WritePreamble{%
    \WriteOut{%
        \DoubleperCent ^^J%
        \DoubleperCent This is file `\outFileName', generated %
                        on <\the\year/\the\month/\the\day> ^^J%
        \DoubleperCent with the docstrip utility (\fileversion).%
             }%
%    \end{macrocode}
%    Then the |\ReferenceLines| that tell from what source file(s) the
%    stripped file was created.
%    \begin{macrocode}
    \ReferenceLines
%    \end{macrocode}
%    Then, a statement that this file should {\em not\/} be distributed
%    on its own.
%    \begin{macrocode}
    \WriteOut{%
        \DoubleperCent ^^J%
        \DoubleperCent IMPORTANT NOTICE:^^J%
        \DoubleperCent You are not allowed to distribute this file.^^J%
        \DoubleperCent For distribution of the original source see^^J%
        \DoubleperCent the copyright notice in the file \inFileName.^^J%
        \DoubleperCent }}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\OriginalRefs}
% \changes{2.0e}{1991/06/01}{Macro added.}
%    The macro \verb=\OriginalRefs= can be used to include information
%    in the output file about the documented source files it was
%    created from.
%    \begin{macrocode}
\def\OriginalRefs{%
    \WriteOut{\DoubleperCent }%
    \WriteOut{\DoubleperCent The original source file was 
              `\inFileName'.}%
    \ifx\Options\empty\else
        \WriteOut{\DoubleperCent Included options: `\Options'.}\fi
    \WriteOut{\DoubleperCent }}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ReferenceLines}
% \changes{2.0e}{1991/06/01}{Macro added.} The macro
%    \verb=\ReferenceLines= is used by the macro \verb=\WritePreamble=
%    to include some information on the original source files in the
%    output file. When the user does not supply a preamble, a default
%    preamble is used, so also a default value for
%    \verb=\ReferenceLines= has to be supplied. The macro
%    \verb=\OriginalRefs= supplies such a default.
%    \begin{macrocode}
\let\ReferenceLines\OriginalRefs
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\WritePostamble}
% \changes{2.0e}{1991/06/01}{Macro added.}
%    The default definition of \verb=\WritePostamble= is to write
%    a line containing \verb=\endinput= to the output file. The
%    last line written identifies the file again.
%    \begin{macrocode}
\def\WritePostamble{%
    \WriteOut{\string\endinput}%
    \WriteOut{\DoubleperCent ^^J%
              \DoubleperCent End of file `\outFileName'.}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\preamble}
% \changes{2.0e}{1991/06/01}{Macro added.} When a batch file is used the
%    user can specify a preamble of his own that will be written to
%    each file that is created. This can be useful to include an extra
%    copyright notice in the stripped version of a file.  Also a
%    warning that both versions of a file should {\em always\/} be
%    distributed together could be written to a stripped file by
%    including it in such a preamble.
%
%    Every line that is written to \verb=\outFile= that belongs to the
%    preamble is preceded by two percent characters. This will prevent
%    \ds{} from stripping these lines off the file.
%
%    The preamble should be started with the macro \verb=\preamble=;
%    it is ended by \verb=\endpreamble=. All processing is done within
%    a group in order to be able to locally redefine some macros.
%    \begin{macrocode}
\def\preamble{\begingroup
%    \end{macrocode}
%    If the preamble contains an empty line this will end up in
%    the macro \verb=\batchLine= as \verb=\par=. To be able to
%    recognize a \verb=\par= we define \verb=\tmp= to contain
%    \verb=\par=. The macro \verb=\Endpreamble= is defined to contain
%    \verb=\endpreamble=, which ends the processing of preamble lines.
%    \begin{macrocode}
    \def\tmp{\par}%
    \def\Endpreamble{\endpreamble}%
%    \end{macrocode}
%    The preamble lines will be read inside a \verb=\loop=. When
%    a line is found that contains \verb=\endpreamble= the processing
%    has to stop. This is controlled by the switch \verb=\ifContinue=.
%    We initialize it to \meta{true}.
%    \begin{macrocode}
    \Continuetrue
%    \end{macrocode}
%    The macro \verb=\WritePreamble= will be defined to contain
%    commands to write all preamble lines to \verb=\outFile=. We start
%    it off with a couple of lines identifying the file. More lines
%    will be added as processing continues, therefore the macros
%    \verb=\inFileName= and \verb=\outFileName= are \verb=\let= to
%    \verb=\relax=. If this was not done their contents would now be
%    hard-coded in \verb=\WritePreamble=, which is {\em not\/} what we
%    want.
% \changes{2.0h}{1991/06/19}{Removed opening of output file as a side
%    effect.}
%    \begin{macrocode}
    \let\inFileName\relax
    \let\outFileName\relax
    \let\ReferenceLines\relax
    \gdef\WritePreamble{%
        \WriteOut{\DoubleperCent ^^J%
                  \DoubleperCent This is file `\outFileName',
                                 generated ^^J%
                  \DoubleperCent on <\the\year/\the\month/\the\day> with
                                 the docstrip utility (\fileversion).}%
        \ReferenceLines}%
%    \end{macrocode}
%    Now  each line in the preamble has to be added to
%    \verb=\WritePreamble=, therfore we start a \verb=\loop= to
%    \verb=\read= the lines. The control sequence \verb=\batchLine=
%    is used to store each line.
%    \begin{macrocode}
    \loop
        \read\currbatchFile to \batchLine
%    \end{macrocode}
%    We check to see if the end of the preamble has been found. In that
%    case the \verb=\loop= has to come to an end, so we set the switch
%    \verb=\ifContinue= to \meta{false}.
%    \begin{macrocode}
        \ifx\batchLine\Endpreamble \Continuefalse
        \else
%    \end{macrocode}
%    If an extra line has been read we add the appropriate
%    instructions to \verb=\WritePreamble= using \verb=\xdef= (which
%    does a global expanded definition). If the \verb=\batchLine= was
%    empty, we write just the two percent characters; otherwise the
%    complete line is written, preceded by the two percent characters.
%    \begin{macrocode}
            \xdef\WritePreamble{%
                \WritePreamble
                \WriteOut{\DoubleperCent 
                          \ifx\batchLine\tmp\else\batchLine\fi}}%
        \fi
%    \end{macrocode}
%    The setting of the switch \verb=\ifContinue= will decide if the
%    \verb=\loop= continues. If we end the \verb=\loop=, we also have to
%    close the group.
%    \begin{macrocode}
    \ifContinue\repeat
    \endgroup}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\postamble}
% \changes{2.0e}{1991/06/01}{Macro added.} Just as a preamble can be
%    specified in a batch file, the same can be done for a {\em
%    post\/}amble.
%
%    The definition for \verb=\postamble= is very much like the one for
%    \verb=\preamble=; the processing takes place inside a group and
%    the switch \verb=\ifContinue= is used to control the \verb=\loop=.
%    \begin{macrocode}
\def\postamble{\begingroup
    \Continuetrue
%    \end{macrocode}
%    The end of the postamble is indicated by \verb=\endpostamble= and
%    the postamble can contain empty lines so we have to be able
%    to check if \verb=\batchLine= contains a \verb=\par=.
%    \begin{macrocode}
    \def\Endpostamble{\endpostamble}%
    \def\tmp{\par}%
%    \end{macrocode}
%    We initially define \verb=\WritePostamble= as an empty macro.
%    Commands will be added to it as we go along.
%    \begin{macrocode}
    \gdef\WritePostamble{}%
%    \end{macrocode}
%    We start a loop to read lines from the batch file until
%    \verb=\postamble= is encountered.
%    \begin{macrocode}
    \loop
        \read\currbatchFile to \batchLine
        \ifx\batchLine\Endpostamble \Continuefalse
%    \end{macrocode}
%    The line just read will be written to \verb=\outFile=, prepended
%    with two percent characters. The command to do this is appended
%    to the definition of \verb=\WritePostamble=.
%    \begin{macrocode}
        \else
            \xdef\WritePostamble{%
               \WritePostamble
               \WriteOut{\DoubleperCent 
                         \ifx\batchLine\tmp\else\batchLine\fi}}%
        \fi
%    \end{macrocode}
%    The setting of the switch \verb=\ifContinue= decides if we have
%    to stop the \verb=\loop=.
%    \begin{macrocode}
    \ifContinue\repeat
    \endgroup}
%    \end{macrocode}
% \end{macro}
%
%    \subsection{Interaction with the user}
%
% \begin{macro}{\processbatchFile}
% \changes{2.0f}{1991/06/04}{Macro added.}
%    When \ds{} is run it always tries to use a batch file.
%    For this purpose it calls the macro |\processbatchFile|. The first
%    thing this macro does, is check wether the user has defined the
%    control sequence |\batchfile|. If he did, it should contain the
%    name of the file to process. If he didn't a default name is tried.
%    Whether or not the default batch file is used is remembered by
%    setting the switch |\ifDefault| to \meta{true} or \meta{false}.
%    \begin{macrocode}
\def\processbatchFile{%
    \ifx\undefined\batchfile
      \let\batchfile\DefaultbatchFile
      \Defaulttrue
    \else
      \Defaultfalse
    \fi
%    \end{macrocode}
%    Now we try to open the batch file for reading.
%    \begin{macrocode}
    \openin\currbatchFile \batchfile\relax
    \ifeof\currbatchFile
%    \end{macrocode}
%    If we didn't succeed in opening the file, we assume that it does
%    not exist. If we tried the default filename, we silently
%    continue; the \ds{} program will switch to interactive mode in
%    this case.
%    \begin{macrocode}
      \ifDefault
      \else
%    \end{macrocode}
%    If we failed to open the user-supplied file, something is wrong
%    and we warn him about it. This will also result in a switch to
%    interactive mode.
%    \begin{macrocode}
        \Msg{**************************************************^^J%
             * Could not find your \string\batchfile=\batchfile^^J%
             * Try to continue without it^^J%
             **************************************************}%
      \fi
    \else
%    \end{macrocode}
%    When we were successful in opening a file, we again have to check
%    whether it was the default file. In that case we tell the user
%    we found that file and ask him if he wants to use it.
%    \begin{macrocode}
      \ifDefault
        \Msg{**************************************************^^J%
             * Batchfile \DefaultbatchFile\space found Use it? (y/n)?}%
        \Ask\answer{%
             **************************************************}%
      \else
%    \end{macrocode}
%    When it was the user-supplied file we can safely assume he wants
%    to use it so we set |\answer| to \texttt{y}.
%    \begin{macrocode}
        \let\answer\y
      \fi
%    \end{macrocode}
%    At this point we have successfully opened a batch file for
%    reading.  If the macro |\answer| contains a \texttt{y} we can
%    proceed. We do that by setting the switch |\ifContinue| to true.
%    When the batch file contains an |\endinput| we shouldn't
%    continue, so we make it switch |\ifContinue| to \meta{false}.
%    \begin{macrocode}
      \ifx\answer\y
        \Continuetrue
        \let\endinput\Continuefalse
%    \end{macrocode}
%    The contents of the batch file are read in a loop, line by line.
%    When the end of the file is found processing should stop.
%    \begin{macrocode}
        \loop
          \ifeof\currbatchFile
            \Continuefalse
          \else
%    \end{macrocode}
%    A line is read into the macro |\batchLine|, which is subsequently
%    executed.
%    \begin{macrocode}
            \read\currbatchFile to \batchLine
            \batchLine
          \fi
%    \end{macrocode}
%    When the execution of |\batchLine| is finished we check the switch
%    |\ifContinue| to see if have to continue reading.
%    \begin{macrocode}
        \ifContinue \repeat
      \fi
    \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ReportTotals}
% \changes{2.0g}{1991/06/05}{Macro added.} The macro
%    \verb=\ReportTotals= can be used to report total statistics for
%    all files processed. This code is only included in the program if
%    the option \texttt{stats} is included.
%    \begin{macrocode}
%<*stats>
\def\ReportTotals{%
  \ifnum\NumberOfFiles>\@ne
    \Msg{Overall statistics:^^J%
         Files \space processed: \the\NumberOfFiles^^J%
         Lines \space processed: \the\TotalprocessedLines^^J%
         Comments removed: \the\TotalcommentsRemoved^^J%
         Comments \space passed: \the\TotalcommentsPassed^^J%
         Codelines passed: \the\TotalcodeLinesPassed}%
  \fi}
%</stats>
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\SetFileNames}
%    The macro \verb=\SetFileNames= is used when the program runs in
%    interactive mode and the user was asked to supply extensions and
%    a list of filenames.
%    \begin{macrocode}
\def\SetFileNames{%
    \edef\inFileName{\MainFileName.\infileext}%
    \edef\outFileName{\MainFileName.\outfileext}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\CheckFileNames}
%    In interactive mode, the user gets asked for the extensions for
%    the input and output files. Also the name or names of the input
%    files (without extension) is asked for. Then the names of the
%    input and output files are constructed from this information by
%    |\SetFileNames|. This assumes that the name of the input file is
%    the same as the name of the output file. But we should not write
%    to the same file we're reading from so the extensions should
%    differ.
%
%    The macro |\CheckFileNames| makes sure that the output goes to a
%    different file to the one where the input comes from.
%    \begin{macrocode}
\def\CheckFileNames{%
    \ifx\inFileName\outFileName
%    \end{macrocode}
%    If input and output files are the same we signal an error and stop
%    processing.
%    \begin{macrocode}
      \Msg{^^J%
     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^J%
     ! It is not possible to read from and write to the same file !^^J%
     !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^J}%
      \Continuefalse
    \else
%    \end{macrocode}
%    If they are not the same we check if the input file exists by
%    trying to open it for reading.
%    \begin{macrocode}
      \Continuetrue
      \immediate\openin\inFile \inFileName\relax
      \ifeof\inFile
%    \end{macrocode}
%    If an end of file was found, the file couldn't be opened, so we
%    signal an error and stop processing.
%    \begin{macrocode}
        \Msg{^^J%
              !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^J%
              ! Your input file `\inFileName' was not found !^^J%
              !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!^^J}%
        \Continuefalse
      \else
%    \end{macrocode}
%    The last check we have to make is if the output file already
%    exists.  Therefore we try to open it for reading.
%    As a precaution we first close the input stream.
% \changes{2.0p}{1992/06/26}{Added `WriteToDir (FMi).}
% \changes{2.0r}{1992/08/17}{Use `inFile for reading}
% \changes{2.0r}{1992/08/17}{Moved `closein statements}
%    \begin{macrocode}
        \immediate\closein\inFile
        \immediate\openin\inFile\WriteToDir \outFileName\relax
        \ifeof\inFile
%    \end{macrocode}
%    If this fails, it didn't exist and all is well.
%    \begin{macrocode}
          \Continuetrue
        \else
%    \end{macrocode}
%    If opening of the output file for reading succeeded we have to
%    ask the user if he wants to overwrite it. We assume he doesn't
%    want to overwrite it, so the switch |\ifContinue| is initially
%    set to \meta{false}. Only if he answers the question positively
%    with `\texttt{y}' or `\texttt{yes}' we set the switch back to
%    \meta{true}.
% \changes{2.0p}{1992/06/26}{Changed question about overwriting.}
%    \begin{macrocode}
          \Continuefalse
          \Ask\answer{File \WriteToDir\outFileName\space already 
                      exists 
                      \ifx\@empty\WriteToDir somewhere \fi
                      on the system.^^J% 
                      Overwrite it%
                      \ifx\@empty\WriteToDir\space if necessary\fi
                      ? [y/n]}%
          \ifx\y  \answer \Continuetrue \else
          \ifx\yes\answer \Continuetrue \else
          \fi\fi
        \fi
%    \end{macrocode}
%    All checks have been performed now, so we can close any file that
%    was opened just for this purpose.
%    \begin{macrocode}
      \fi
    \fi
    \immediate\closein\inFile}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\interactive}
%    The macro |\interactive| implements the interactive mode of the
%    \ds{} program. The macro is implemented using the
%    \meta{while} construction. While the switch |\ifMoreFiles| remains
%    true, we continue processing.
%    \begin{macrocode}
\def\interactive{%
  \whileswitch\ifMoreFiles\fi%
%    \end{macrocode}
%    To keep macro redefinitions local we start a group and ask the
%    user some questions about what he wants us to do.
%    \begin{macrocode}
   {\begingroup
      \AskQuestions
%    \end{macrocode}
%    The names of the files that have to be processed are stored as a
%    comma-separated list in the macro |\filelist| by |\AskQuestions|.
%    We use a \meta{for} loop to process the files one by one.
%    \begin{macrocode}
      \forlist\MainFileName:=\filelist
      \do
%    \end{macrocode}
%    First the names of the input and output files are constructed
%    and a check is made if all filename information is correct.
%    \begin{macrocode}
        \SetFileNames
        \CheckFileNames
        \ifContinue
%    \end{macrocode}
%    If everything was well, we can open the output file for writing,
% \changes{2.0q}{1992/07/01}{Preceded filename by `WriteToDir}
%    \begin{macrocode}
          \immediate\openout\outFile\WriteToDir\outFileName\relax
%    \end{macrocode}
%    write the preamble to it,
%    \begin{macrocode}
          \WritePreamble
%    \end{macrocode}
%    process the input file,
%    \begin{macrocode}
          \generateFileX
%    \end{macrocode}
%    write a postamble
%    \begin{macrocode}
          \WritePostamble
%    \end{macrocode}
%    and close the output file again.
%    \begin{macrocode}
          \immediate\closeout\outFile
        \fi%
%    \end{macrocode}
%    This process is repeated until |\filelist| is exhausted.
%    \begin{macrocode}
      \od
    \endgroup
%    \end{macrocode}
%    Maybe the user wants more files to be processed, possibly with
%    another set of options, so we give him the opportunity.
%    \begin{macrocode}
    \Ask\answer{More files to process (y/n)?}%
    \ifx\y  \answer\MoreFilestrue \else
    \ifx\yes\answer\MoreFilestrue \else
%    \end{macrocode}
%    If he didn't want to process any more files, the switch
%    |\ifMoreFiles| is set to \meta{false} in order to interrupt the
%    \meta{while} loop.
%    \begin{macrocode}
                   \MoreFilesfalse\fi\fi
   }}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\AskQuestions}
% \changes{2.0e}{1991/06/01}{Macro added.}
%    The macro |\AskQuestions| is called by |\interactive| to get
%    some information from the user concerning the files that need
%    to be processed.
%    \begin{macrocode}
\def\AskQuestions{%
    \Msg{^^J%
         ****************************************************}%
%    \end{macrocode}
%    We want to know the extension of the input files,
%    \begin{macrocode}
    \Ask\infileext{%
         * First type the extension of your input file(s): \space  *}%
    \Msg{****************************************************^^J^^J%
         ****************************************************}%
%    \end{macrocode}
%    the extension of the output files,
%    \begin{macrocode}
    \Ask\outfileext{%
         * Now type the extension of your output file(s) \space: *}%
    \Msg{****************************************************^^J^^J%
         ****************************************************}%
%    \end{macrocode}
%    if options are to be included and
%    \begin{macrocode}
    \Ask\Options{%
       * Now type the name(s) of option(s) to include \space\space: *}%
    \Msg{****************************************************^^J^^J%
         ****************************************************^^J%
       * Finally give the list of input file(s) without \space\space*}%
%    \end{macrocode}
%    the name of the input file or a list of names, separated by commas.
%    \begin{macrocode}
    \Ask\filelist{%
         * extension seperated by commas if necessary %
                                  \space\space\space\space: *}%
    \Msg{****************************************************^^J}}%
%    \end{macrocode}
% \end{macro}
%
% \subsection{The main program}
%    When \TeX\ processes the \ds{} program it displays
%    a message about the version of the program and its function
%    on the terminal.
%    \begin{macrocode}
\Msg{Utility: `docstrip' \fileversion\space <\filedate>^^J%
     English documentation \space\space\space <\docdate>}%
\Msg{^^J%
     **********************************************************^^J%
     * This program converts documented macro-files into fast *^^J%
     * loadable files by stripping off (nearly) all comments! *^^J%
     **********************************************************^^J}%
%    \end{macrocode}
%
%    First we try to process a batch file.
%    \begin{macrocode}
\processbatchFile
%    \end{macrocode}
%
%    When the number of files processed is still zero,
%    no batch file was specified and the default
%    batch file was not found, so we try interactive mode.
%    \begin{macrocode}
  \ifnum\NumberOfFiles=\z@
    \interactive
  \fi
%    \end{macrocode}
%    When we're done and statistics are included we provide a statistics
%    report about the complete run. Then we \verb=\end= the \TeX-run.
%    \begin{macrocode}
%<*stats>
\ReportTotals
%</stats>
\end
%</program>
%    \end{macrocode}
%
%
%
% \Finale
\endinput

