% \iffalse meta-comment
%
% Copyright 1993 1994 1995 1996 1997 1998 1999
% The LaTeX3 Project and any individual authors listed elsewhere
% in this file. 
% 
% This file is part of the Standard LaTeX `Tools Bundle'.
% -------------------------------------------------------
% 
% It may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.2
% of this license or (at your option) any later version.
% The latest version of this license is in
%    http://www.latex-project.org/lppl.txt
% and version 1.2 or later is part of all distributions of LaTeX 
% version 1999/12/01 or later.
% 
% The list of all files belonging to the LaTeX `Tools Bundle' is
% given in the file `manifest.txt'.
% 
% \fi
%\iffalse   % this is a METACOMMENT !
%
%<*dtx>
          \ProvidesFile{f-array.dtx}
%</dtx>
%% Package `array' to use with LaTeX 2e
%% Copyright (C) 1989-1998 Frank Mittelbach, all rights reserved.
%<+package>\NeedsTeXFormat{LaTeX2e}[1995/06/01]
%<+package>\ProvidesPackage{array}
% \fi
%         \ProvidesFile{f-array.dtx}
        [1998/05/13 v2.3m Tabular extension package (FMi)]
%
%
% \CheckSum{1108}
%% \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         \~}
%%
%
%
% \changes{v2.3c}{1995/11/02}{(DPC) changement mineur dans la documentation}
%
% \changes{v2.3a}{1994/10/16}{ajout du code pour \cs{firsthline} et
%                             assimil\'es}
%
% \changes{v2.2c}{1994/03/14}{suppression du test du bug de \cs{@tfor}}
%
% \changes{v1.0b}{1987/06/04}{`@classi (plus rapide),
%                        `@classvi (nouveau)   A dans le pr\'eambule
%                                         signifie \&\& dans `halign.}
%
% \changes{v1.1a}{1987/07/05}{Nouveau concept:
%                        preamblechar: c,l,r,C,L,R,A,p,t,{\tt !|},@,!!}
% \changes{v1.1b}{1987/09/21}{p reprend son r\^ole original comme dans
%                        \LaTeX{} et z pour une `parbox centr\'ee.}
%
% \changes{v1.2a}{1987/09/27}{Impl\'ementatrion compl\`etement nouvelle.}
% \changes{v1.2b}{1987/10/06}{{\tt !|} ne g\'en\`ere plus d'espace au 
%                        d\'ebut ou \`a la fin du pr\'eambule. Sinon
%                        `hline est trop longue.}
%\selectlanguage{english}
% \changes{v1.2b}{1987/10/06}{Enlarged `@arstrutbox by 1pt (Test-Impl)
%                         with dimen `@strutheight.}
% \changes{v1.2c}{1987/10/22}{Nouvelle dimension `extrarowheight
%                        (d\'efaut: 0pt).}
% \changes{v1.2c}{1987/10/22}{Augmente `@arstrutbox de `extrarowheight.
%                        Thus you may avoid large characters to
%                        overprint a `hline.}
% \changes{v1.2c}{1987/10/22}{Introduced `m@th in `@array to allow
%                         non-zero values of `mathsurround.}
% \changes{v1.2d}{1987/11/02}{Completed the documentation.}
% \changes{v1.2e}{1987/11/03}{Bug fixed: A at start of preamble resulted
%                        in an error since `@mkpream generated
%                        `@arstrut \& ... as a preamble.}
% \changes{v1.2f}{1987/11/09}{`@testpach documented.}
%
% \changes{v1.3a}{1987/11/11}{Again a new implementation, with a new
%                        concept (cf. the documentation).}
% \changes{v1.3b}{1988/03/17}{`@decl expands now into `@empty, i.e., it
%                        disappears when the preamble is generated,
%                        except when the user specifies A\{\} or
%                        B\{\}.}
%
% \changes{v1.4a}{1988/03/18}{Test implementation of use of token
%                        registers in order to do without `protect.}
% \changes{v1.4b}{1988/03/19}{Changed erroneous class numbers:
%                        5 -!> 6
%                        6 -!> 7
%                        7 -!> 5
%                        Corresponding changes in the macros.}
% \changes{v1.4c}{1988/03/19}{Everything except p,z now works with token
%                        registers.}
%
% \changes{v1.9a}{1988/03/20}{Last (so I hope) major change: 1) Options
%                        B,A now called !>,<.  These options now point
%                        to the column they modify.}
% \changes{v1.9a}{1988/03/20}{2) `protect is no longer necessary. But
%                           still the macro `@expast needs top be
%                          modified. `multicolumn still does not work.}
% \changes{v1.9b}{1988/04/29}{inserted missing `fi in `@testpach.
%                        Corrected \LaTeX bug in `@tfor.}
% \changes{v1.9c}{1988/05/07}{Re-introduced `@endpbox.
%                        `multicolumn now works!! Version number still
%                        1.9 since the documentation is still not
%                        finished.}
% \changes{v1.9c}{1988/05/07}{1) `def `the@toks \{`the ...\} remaining
%                         only in `@mkpream.  2) Removed `@classiii and
%                        replaced by `save@decl.}
% \changes{v1.9c}{1988/05/07}{3) `insert@column contains only `@tempcnta
%                        and `count@ counters.  4) `@@startpbox and
%                        `@@endpbox now totally obsolete.}
% \changes{v1.9d}{1988/05/10}{Replaced `number by `the where the `toks
%                        registers' contents are used.}
% \changes{v1.9e}{1988/05/11}{Re-introduced `@xargarraycr and
%                        `@yargarraycr, since `endtemplate seems to
%                        be `outer.}
% \changes{v1.9f}{1988/05/20}{Small changes finally carried out:
%                        1) `par!=`@empty.
%                        2) \{..ifnum0!=!`\}...  $\to$ `bgroup and
%                           analoguously `egroup.}
% \changes{v1.9g}{1988/02/24}{Inserted again \{..ifnum0!=!`\}..,
%                        c.f. Appendix D of the \protect\TeX{}book.}
% \changes{v1.9h}{1988/06/28}{No longer necessary to read in the file
%                        twice.}
% \changes{v1.9i}{1988/06/28}{Corrected typo in german version.}
% \changes{v1.9j}{1988/11/23}{In a `r' column an extra `kern`z@ is
%                        needed.}
% \changes{v1.9j}{1988/11/23}{Otherwise the `hfil on the left side
%                        will be removed by the `unskip in
%                        `insert@column if the entry is empty.}
% \changes{v1.9k}{1988/06/28}{Corrected typo in german version.}
% \changes{v1.9k}{1989/01/16}{`begin{Macro} changed to `begin{macro} in
%                        documentation.}
%
% \changes{v2.0a}{1989/05/12}{{\tt\textbackslash @thetoks} changed to
%                          {\tt\textbackslash the@toks}.}
% \changes{v2.0a}{1989/05/12}{source changed to reflect new doc.sty
%                          conventions.}
% \changes{v2.0a}{1989/05/12}{t option renamed to p to be compatible to
%                        the original.}
% \changes{v2.0a}{1989/05/12}{File renamed from arraye.sty to
%                        array.sty.}
% \changes{v2.0b}{1989/05/17}{Three forgotten end macro added.}
% \changes{v2.0b}{1989/05/17}{All lines shortened to 72 or less.}
% \changes{v2.2a}{1994/02/03}{Upgrade to \LaTeXe}
%\selectlanguage{french}
%
% \DoNotIndex{\@depth,\@ehc,\@fortmp,\@height,\@ifnextchar,\@ifstar}
% \DoNotIndex{\@ifundefined,\@ne,\@nil,\@tempa,\@tempb}
% \DoNotIndex{\@tempcnta,\@tempd,\@tempdima,\@whilenum,\@width,\\}
% \DoNotIndex{\@tforloop}
% \DoNotIndex{\advance}
% \DoNotIndex{\baselineskip,\begingroup,\bgroup}
% \DoNotIndex{\cr,\crcr,\csname}
% \DoNotIndex{\def,\do,\docdate,\dp}
% \DoNotIndex{\edef,\egroup,\else,\endcsname,\endinput,\expandafter}
% \DoNotIndex{\fi,\filedate,\fileversion}
% \DoNotIndex{\gdef}
% \DoNotIndex{\hbox,\hfil,\hsize,\hskip,\ht}
% \DoNotIndex{\if,\ifcase,\ifdim,\ifnum,\ifx,\ignorespaces}
% \DoNotIndex{\kern}
% \DoNotIndex{\leavevmode,\let,\lineskip}
% \DoNotIndex{\m@ne,\multispan}
% \DoNotIndex{\newcount,\newdimen,\noalign}
% \DoNotIndex{\or}
% \DoNotIndex{\relax}
% \DoNotIndex{\setbox,\space,\strutbox}
% \DoNotIndex{\tabskip,\thr@@,\the,\toks,\toks@,\tw@,\typeout}
% \DoNotIndex{\unhcopy,\unskip}
% \DoNotIndex{\vbox,\vcenter,\vline,\vrule,\vtop,\vskip}
% \DoNotIndex{\xdef}
% \DoNotIndex{\z@}
%
% \GetFileInfo{f-array.dtx}
%
% \title{Une nouvelle \'ecriture des environnements
%     \textsf{tabular} et \textsf{array} de \LaTeX\thanks{Ce fichier
%        a le num\'ero de version \fileversion, r\'evis\'e
%        le \filedate.}}
%
% \author{Frank Mittelbach
%         \and
%         David Carlisle\thanks{David a accept\'e gr\^acieusement l'inclusion
%         de code auparavant dans \texttt{newarray.sty} pour l'\'ecriture
%         de \texttt{\textbackslash{}newcolumntype}} \and
%            \makebox[0.9\linewidth]{Traduction fran\c{c}aise
%                 par Jean-Pierre Drucbert\thanks{Derni\`ere mise \`a
%                 jour le 20/01/2000}}}
%
% \date{Imprim\'e le \today}
%
% \maketitle
%
% \MakeShortVerb{\=}
%
% \begin{abstract}
% Ce package est une nouvelle impl\'ementation des environnements
% \texttt{tabular} et \texttt{array} de \LaTeX. Les principaux avantages
% de cette impl\'ementation sont de nouvelles options pour mettre en
% forme les colonnes et que les commandes <<~fragiles~>> de \LaTeX\
% n'ont plus besoin d'\^etre prot\'eg\'ees par =\protect= \`a
% l'int\'erieur de ces environnements.
%
% La majeure partie du code de ce package date de 1988---il en est
% de m\^eme de sa documentation.
% \end{abstract}
%
%
%
% \section{Introduction}
%
% Cette nouvelle impl\'ementation des environnements \texttt{tabular} et
% \texttt{array} fait partie d'un projet plus large, dans lequel nous
% essayons d'am\'eliorer le code de \LaTeX\ et de le rendre encore plus
% facile \`a manipuler.
%
% Le lecteur devrait \^etre familier avec les environnements
% mentionn\'es ci-dessus. De plus amples informations sont disponibles
% dans \cite{bk:lamport} et \cite{bk:GMS94}.  Les options
% suppl\'ementaires qui peuvent \^etre utilis\'ees dans le pr\'eambule
% ainsi que celles qui ont un sens l\'eg\`erement diff\'erent sont
% d\'ecrites dans la table~\ref{tab+opt}.
%
% \DescribeMacro\extrarowheight
% Il y a un nouveau param\`etre, la longueur =\extrarowheight=, qui, si
% elle est positive, est ajout\'ee \`a la hauteur normale de chaque
% ligne de la table, alors que la profondeur reste la m\^eme. Ceci est
% important pour les tables comportant des lignes horizontales car
% normalement ces lignes touchent les lettres majuscules.
% Par exemple, nous avons utilis\'e =\setlength{\extrarowheight}{1pt}=
% dans la table~\ref{tab+opt}.
%
% \begin{table}[t]
% \begin{center}
%    \setlength{\extrarowheight}{1pt}
%    \begin{tabular}{|>{\tt}c|m{9cm}|}
%       \hline
%     \multicolumn{2}{|c|}{Options inchang\'ees}\\
%       \hline
%       l             &  Colonne cadr\'ee \`a gauche. \\
%       c             &  Colonne centr\'ee. \\
%       r             &  Colonne cadr\'ee \`a droite. \\
%       p\{width\}    &  \'Equivalente \`a =\parbox[t]{width}=. \\
%       @\{decl.\}    &  Supprime l'espace entre les colonnes et le
%                        remplace par \texttt{decl.}. \\
%       \hline
%     \multicolumn{2}{|c|}{Options nouvelles}\\
%       \hline
%       m\{width\}    &  D\'efinit une colonne de largeur \texttt{width}.
%                        Chaque entr\'ee sera centr\'ee en proportion du
%                        reste de la ligne. Ceci est assez semblable \`a
%                        =\parbox{width}=. \\
%       \hline
%       b\{width\}    &  \'Equivalente \`a =\parbox[b]{width}=. \\
%       \hline
%       >\{decl.\}    &  Peut \^etre utilis\'ee avant une option \texttt{l}, \texttt{r},
%                        \texttt{c}, \texttt{p}, \texttt{m} ou
%                        \texttt{b}. Ceci ins\`ere \texttt{decl.}
%                        directement en t\^ete de l'entr\'ee dans la colonne. \\
%       \hline
%       <\{decl.\}    &  Peut \^etre utilis\'ee apr\`es une option \texttt{l}, \texttt{r},
%                        \texttt{c}, \texttt{p}, \texttt{m} ou
%                        \texttt{b}. Ceci ins\`ere \texttt{decl.}
%                        juste apr\`es l'entr\'ee dans la colonne. \\
%       \hline
%       |             &  Ins\`ere une ligne verticale. La distance entre
%                        deux colonnes sera augment\'ee de l'\'epaisseur
%                        de la ligne, contrairement \`a la d\'efinition
%                        originale de \LaTeX.\\
%       \hline
%       !\{decl.\}    &  Peut \^etre utilis\'ee n'importe o\`u et correspond \`a l'option
%                        \texttt{|}. La diff\'erence est que
%                        \texttt{decl.} sera ins\'er\'ee \`a la place
%                        d'une ligne verticale, donc
%                        cette option ne supprime pas l'espace
%                        normalement ins\'er\'e entre
%                        les colonnes, contrairement \`a =@{...}=.\\
%       \hline
%    \end{tabular}
% \end{center}
% \caption{Les options du pr\'eambule.} \label{tab+opt}
% \end{table}
%
%
% Nous allons pr\'esenter quelques exemples des nouvelles options du
% pr\'eambule.
% \begin{itemize}
%    \item
%       Si vous d\'esirez utiliser une fonte sp\'eciale (par exemple
%       =\bfseries=) dans une colonne cadr\'ee \`a gauche, ceci peut se
%       faire avec  =>{\bfseries}l=.  Vous n'\^etes plus oblig\'es de
%       commencer chaque entr\'ee par =\bfseries=.
%    \item
%       Dans les colonnes qui ont \'et\'e engendr\'ees par \texttt{p},
%       \texttt{m} ou \texttt{b}, la valeur par d\'efaut de =\parindent=
%       est 0pt. Ceci peut \^etre modifi\'e par:\\
%       =>{\setlength{\parindent}{1cm}}p=.
%    \item
%       les options \texttt{<} et \texttt{>} avaient \'et\'e
%       d\'evelopp\'ees \`a l'origine pour l'application suivante:
%       =>{$}c<{$}= engendre une colonne en mode math\'ematique
%       dans un environnement \textsf{tabular}. Si vous utilisez ce type
%       de pr\'eambule dans un environnement \textsf{array}, vous
%       obtenez une colonne en mode~LR car les dollars suppl\'ementaires
%       annulent ceux d\'ej\`a pr\'esents.
%    \item
%       Vous pouvez aussi penser \`a des applications plus complexes. Un
%       probl\`eme classique peut facilement \^etre r\'esolu avec la
%       s\'equence
%       =>{\centerdots}c=\linebreak[0]=<{\endcenterdots}=.
%       Pour centrer des nombres sur leurs points d\'ecimaux, il
%       suffit\,\footnote{C'est Frank Mittelbach qui le
%       dit!}~(juste~?) de d\'efinir les macros suivantes:
%       \begin{verbatim}
%{\catcode`\.\active\gdef.{\egroup\setbox2\hbox\bgroup}}
%\def\centerdots{\catcode`\.\active\setbox0\hbox\bgroup}
%\def\endcenterdots{\egroup\ifvoid2 \setbox2\hbox{0}\fi
%   \ifdim \wd0>\wd2 \setbox2\hbox to\wd0{\unhbox2\hfill}\else
%     \setbox0\hbox to\wd2{\hfill\unhbox0}\fi
%   \catcode`\.12 \box0.\box2}
%\end{verbatim}
% Attention: ces macros ne marchent pas si une cellule comporte
% plusieurs points d\'ecimaux ou si le tableau est utilis\'e en argument
% d'une autre commande. Une approche bien meilleure est d'utiliser le
% package \texttt{dcolumn.sty} \'ecrit par David Carlisle.
%    \item
%       En utilisant =c!{\hspace{1cm}}c= vous \'elargissez d'un
%       centim\`etre l'espace entre deux colonnes, tandis que
%       =c@{\hspace{1cm}}c= vous donne exactement un centim\`etre
%       d'espace entre deux colonnes.
% \end{itemize}
%
% \subsection{D\'efinir de nouveaux types de colonnes}
%
% \DeleteShortVerb{\=}
% \MakeShortVerb{\"}
% \DescribeMacro{\newcolumntype}
% Alors qu'il est pratique de taper
% \begin{quote}
%   ">{"\meta{quelques d\'eclarations}"}{c}<{"\meta{quelques
%   autres d\'eclarations}"}"
% \end{quote}
% si vous avez une colonne particuli\`ere dans une seule table, cela
% devient peu pratique si vous utilisez souvent des colonnes de cette
% forme. La nouvelle version vous permet de d\'efinir un nouveau
% sp\'ecificateur de colonne, par exemple \texttt{x}, qui remplacera
% plusieurs commandes de sp\'ecificateurs de colonnes\footnote{Cette
% commande \'etait appel\'ee \texttt{\textbackslash{}newcolumn} dans
% \texttt{newarray.sty}.  Actuellement, la commande
% \texttt{\textbackslash{}newcolumn} est toujours valide (mais affiche
% un message d'avertissement). Dans les versions ult\'erieures, elle
% dispara\^{\i}tra.}.
% Nous pouvons donc d\'efinir:
% \begin{quote}
%   "\newcolumntype{x}{>{"\meta{ d\'eclarations}"}{c}<{"\meta{autres
%   d\'eclarations}"}}"\hspace*{-3cm} ^^A no overfull from this line
% \end{quote}
% On peut alors utiliser le sp\'ecificateur de colonne \texttt{x} dans
% les arguments de pr\'eambule de tous les environnements \texttt{array}
% ou \texttt{tabular} dans lesquels vous d\'esirez ce format.
%
% Il est habituel d'avoir besoin  de colonnes en mode math\'ematique
% et en mode~LR
% dans le m\^eme tableau. Si nous d\'efinissons:
% \begin{quote}
%   "\newcolumntype{C}{>{$}c<{$}}" \\
%   "\newcolumntype{L}{>{$}l<{$}}" \\
%   "\newcolumntype{R}{>{$}r<{$}}"
% \end{quote}
%  alors nous pouvons utiliser \texttt{C} pour avoir un mode~LR centr\'e
%  dans un \texttt{array}, ou un mode math\'ematique centr\'e dans
%  un \texttt{tabular}.
%
% L'exemple donn\'e plus haut pour les <<~points d\'ecimaux centr\'es~>>
% pourrait \^etre affect\'e \`a un sp\'ecificateur \texttt{d} par la
% commande suivante:
% \begin{quote}
% "\newcolumntype{d}{>{\centerdots}c<{\endcenterdots}}"
% \end{quote}
%
% Cette solution centre toujours le point dans la colonne. Ceci n'est
% pas tr\`es joli si la colonne est form\'ee de grands nombres, mais
% avec peu de d\'ecimales.  Une autre solution d'une colonne \texttt{d}
% est:
% \begin{quote}
%   "\newcolumntype{d}[1]{>{\rightdots{#1}}r<{\endrightdots}}"
% \end{quote}
% o\`u les macros ad\'equates seraient\footnote{Le package
% \texttt{dcolumn.sty} contient des commandes plus robustes bas\'ees sur
% ces id\'ees.}:
% \begin{verbatim}
%   \def\coldot{.}% Ou si vous pr\'ef\'erez, \def\coldot{\cdot}
%   {\catcode`\.=\active
%     \gdef.{$\egroup\setbox2=\hbox to \dimen0 \bgroup$\coldot}}
%   \def\rightdots#1{%
%     \setbox0=\hbox{$1$}\dimen0=#1\wd0
%     \setbox0=\hbox{$\coldot$}\advance\dimen0 \wd0
%     \setbox2=\hbox to \dimen0 {}%
%     \setbox0=\hbox\bgroup\mathcode`\.="8000 $}
%   \def\endrightdots{$\hfil\egroup\box0\box2}
%\end{verbatim}
% Notez que "\newcolumntype" accepte le m\^eme argument optionnel que
% "\newcommand" pour d\'eclarer le nombre d'arguments pour le
% sp\'ecificateur de colonne.  Maintenant vous pouvez
% sp\'ecifier "d{2}" dans votre pr\'eambule pour une colonne de
% nombres ayant au plus deux d\'ecimales.
%
% Une utilisation assez diff\'erente de "\newcolumntype"
% tire parti du fait que le texte de remplacement dans cette commande
% peut si nécessaire faire r\'ef\'erence \`a plus d'une colonne.
% Supposons maintenant que notre document contienne de nombreux
% environnements \texttt{tabular} utilisant le m\^eme pr\'eambule,
% mais que vous vouliez en essayer d'autres. La d\'efinition originale
% dans \LaTeX\ (par Leslie Lamport) vous permettait de faire (bien que
% ce soit sans doute un usage incorrect du syst\`eme):
% \begin{quote}
%   "\newcommand{\X}{clr}"\\
%   "\begin{tabular}{\X}" \ldots
% \end{quote}
% \texttt{array.sty} fait bien attention de ne pas d\'evelopper le
% pr\'eambule, et donc la solution ci-dessus ne marche pas avec le
% nouveau sch\'ema. Cette fonctionnalit\'e est obtenue avec:
% \begin{quote}
% "\newcolumntype{X}{clr}"\\
% "\begin{tabular}{X}" \ldots
% \end{quote}
%
% Le texte de remplacement dans une commande "\newcolumntype" peut faire
% r\'ef\'erence \`a chacune des primitives de \texttt{array.sty} (voir
% la table~\ref{tab+opt} en page~\pageref{tab+opt}), ainsi qu'aux
% nouvelles lettres d\'efinies dans d'autres commandes "\newcolumntype".
%
% \DescribeMacro{\showcols}Une liste de tous les sp\'ecificateurs
% d\'efinis par "\newcolumntype" est affich\'ee \`a l'\'ecran et dans le
% fichier de logs lorsque la commande "\showcols" est utilis\'ee.
%
%
% \subsection{Variantes sp\'eciales de \texttt{\textbackslash hline}}
%
% La famille des environnements \texttt{tabular} permet un
% positionnement vertical bas\'e sur la ligne de base du texte dans
% lequel l'environnement apparait. Par d\'efaut, l'environnement est
% centr\'e verticalement, mais cela peut \^etre modifi\'e pour l'aligner
% sur la premi\`ere ou la derni\`ere ligne l'environnement en
% sp\'ecifiant la valeur \texttt{t} ou \texttt{b} \`a l'argument
% optionnel de positionnement. Cependant, cela ne marche pas si le
% premier ou le dernier \'el\'ement de l'environnement est une commande
% "\hline" ; dans ce cas, l'environnement est align\'e sur la barre
% horizontale.
%
% \pagebreak[3]
%
% Voici un example:
% \begin{center}
% \begin{minipage}[t]{.4\linewidth}
% Tables
% \begin{tabular}[t]{l}
%   sans \\ commande \\ hline
% \end{tabular} et \\ tables
% \begin{tabular}[t]{|l|}
%  \hline
%   avec \\ commandes \\ hline \\
%  \hline
% \end{tabular}
% \end{minipage}
% \begin{minipage}[t]{.5\linewidth}
% \begin{verbatim}
% Tables
% \begin{tabular}[t]{l}
%   sans \\ commande \\ hline
% \end{tabular} et \\ tables
% \begin{tabular}[t]{|l|}
%  \hline
%   avec \\ commandes \\ hline \\
%  \hline
% \end{tabular}
% \end{verbatim}
% \end{minipage}
% \end{center}
%
% \DescribeMacro\firsthline
% \DescribeMacro\lasthline
% L'utilisation de "\firsthline" et "\lasthline" va r\'esoudre ce
% probl\`eme, et les tables seront correctement align\'ees tant que
% leur premi\`ere ou derni\`ere ligne ne contient pas d'objets
% excessivement larges.
% \begin{center}
% \begin{minipage}[t]{.4\linewidth}
% Tables
% \begin{tabular}[t]{l}
%   sans \\ commande \\ ...line
% \end{tabular} et \\ tables
% \begin{tabular}[t]{|l|}
%  \firsthline
%   avec \\ commandes \\ ...line \\
%  \lasthline
% \end{tabular}
% \end{minipage}
% \begin{minipage}[t]{.5\linewidth}
% \begin{verbatim}
% Tables
% \begin{tabular}[t]{l}
%   sans \\ commande \\ ...line
% \end{tabular} et \\ tables
% \begin{tabular}[t]{|l|}
%  \firsthline
%   avec \\ commandes \\ ...line \\
%  \lasrhline
% \end{tabular}
% \end{verbatim}
% \end{minipage}
% \end{center}
%
% \DescribeMacro\extratabsurround
% L'\'ecriture de ces deux commandes contient une longueur
% suppl\'ementaire, appel\'ee "\extratabsurround", pour ajouter une
% espace au d\'ebut ou \`a la fin de ces environnements.
% C'est tr\`es utile quand les tables sont embo\^{\i}t\'ees.
% 
% \section{Derniers commentaires}
%
% \subsection{Manipulation des barres de s\'eparation}
%
% Il y a deux approches pour la manipulation des barres horizontales et
% verticales \`a l'int\'erieur des tables:
% \begin{enumerate}
%   \item ces barres peuvent \^etre plac\'ees dans l'espace disponible
%   sans augmenter la taille de la table, ou
%   \item elles peuvent \^etre plac\'ees entre les colonnes et les
%   lignes, et par l\`a m\^eme agrandissent la table.
% \end{enumerate}
% \texttt{array.sty} impl\'emente la seconde approche, alors que
% la premi\`ere est utilis\'ee dans le noyau de \LaTeX.
% Les deux ont chacunes leurs avantages, mais il faut faire attention aux
% implications suivantes:
% \begin{itemize}
% \item
%   Avec le \LaTeX{} standard, ajouter des barres dans une table ne
%   modifiera ni la largeur ni la hauteur de la table (\`a moins
%   d'utiliser des doubles barres) ; par exemple changer le
%   pr\'eambule de \verb=lll= en \verb=l|l|l= ne modifie pas le
%   document autrement qu'en ajoutant les barres. Au contraire, avec
%   \texttt{array.sty}, une table qui rentre juste dans la largeur
%   \verb=\textwidth= peut produire un d\'ebordement horizontal.
% \item
%   Avec le \LaTeX{} standard, modifier l'\'epaisseur des barres peut
%   d\'et\'eriorer l'apparence des tables si on ne modifie pas en m\^eme
%   temps les param\`etres \verb=\tabcolsep=, etc, l'espace entre la
%   barre et la colonne pouvant alors devenir trop petit (ou trop
%   grand). En fait, la surimpression de texte est m\^eme possible.
%   Au contraire, avec \texttt{array.sty}, la modification de cette
%   largeur marche souvent sans probl\`eme parce que les espaces de
%   s\'eparation (comme \verb=\tabcolsep=, etc) ne d\'ependent pas de
%   l'\'epaisseur des barres.
% \item
%   Avec le \LaTeX{} standard, les tableaux encadr\'es pr\'esentent des
%   coins bizarres parce que les barres horizontales se terminent au
%   milieu des barres verticales. Quand le param\`etre
%   \verb=\arrayrulewidth= est grand, l'apparence de la table est tr\`es
%   d\'esagr\'eable. Dans ce cas, une simple table comme
%\begin{verbatim}
%\setlength{\arrayrulewidth}{5pt}
%\begin{tabular}{|l|}
%  \hline  A \\  \hline
%\end{tabular}
%\end{verbatim}
%   donnera quelque chose comme
%   \begin{center}
%\setlength{\arrayrulewidth}{5pt}
%\begin{tabular}{@{}l@{}}
%  \hline  \null\hskip-.5\arrayrulewidth\vline
%  \hskip\tabcolsep
%   A\hskip\tabcolsep
%  \vline\hskip-.5\arrayrulewidth\null \\  \hline  
%\end{tabular}
%   \quad
%   au lieu de
%   \quad
%\begin{tabular}{|l|}
%  \hline  A \\  \hline
%\end{tabular}
%   \end{center}
% \end{itemize}
%
% \subsection{Comparaisons avec les anciennes versions de \texttt{array.sty}}
%
% Il y a plusieurs diff\'erences dans la fa\c{c}on dont la version 2.1
% traite les donn\'ees incorrectes, m\^eme si le fichier source ne
% semble pas utiliser les fonctionnalit\'es suppl\'ementaires de cette
% nouvelle version.
% \begin{itemize}
% \item Un pr\'eambule de la forme "{wx*{0}{abc}yz}" \'etait trait\'ee
% dans les versions ant\'erieures \`a 2.1 comme "{wx}". La version 2.1
% le traite comme "{wxyz}"
% \item Un param\`etre de positionnement erron\'e comme \texttt{[Q]}
% \'etait consid\'er\'e comme \texttt{[c]} par \texttt{array.sty}, mais
% il est maintenant trait\'e comme \texttt{[t]}.
% \item Un pr\'eambule tel que "{cc*{2}}" avec une erreur dans
% l'argument de l'\'etoile~$*$ engendrera des erreurs diff\'erentes dans
% la nouvelle version. Dans les deux cas, les messages d'erreur ne sont
% pas d'une aide tr\`es utile pour l'utilisateur ordinaire.
% \item Des r\'ep\'etitions de constructions avec \texttt{<} ou \texttt{>}
% engendraient une erreur dans les versions ant\'erieures, mais sont
% maintenant autoris\'ees. Par exemple,
% ">{"\meta{decl1}"}>{"\meta{decl2}"}" est \'equivalent \`a
% ">{"\meta{decl2}\meta{decl1}"}".
% \item La commande "\extracolsep" ne fonctionne pas avec les anciennes
% versions de \texttt{array.sty} (lire les commentaires dans
% \texttt{array.bug}). Avec la version 2.1, "\extracolsep" peut de
% nouveau \^etre utilis\'ee dans des expressions \verb=@{...}= comme avec
% le \LaTeX{} standard; elle peut aussi se trouver dans une commande
% \verb=!{...}=, mais il convient de lire la note ci-dessous.
% \end{itemize}
%
%
% \subsection{Bogues et fonctionnalit\'es}
%
% \begin{itemize}
% \item Les messages d'erreur engendr\'es en d\'ecodant les
%   sp\'ecifications des colonnes font r\'ef\'erence \`a l'argument du
%   pr\'eambule \textbf{apr\`es} qu'il a \'et\'e r\'e\'ecrit par la
%   commande "\newcolumntype", et non pas au pr\'eambule tel qu'il a
%   \'et\'e \'ecrit par l'utilisateur. Cela semble in\'evitable pour
%   tout syst\`eme utilisant un pr\'e-traitement, et est donc
%   consid\'er\'e comme une \textbf{fonctionnalit\'e}.
%
% \item Le traitement de la d\'eclaration de plusieurs \texttt{<} ou
%   \texttt{>} peut sembler \'etrange de prime abord. Les anciennes
%   versions consid\'eraient ">{"\meta{decl1}"}>{"\meta{decl2}"}"
%   comme \'equivalant \`a ">{"\meta{decl1}\meta{decl2}"}".
%   Cependant, cela emp\^eche l'utilisateur de remplacer les
%   param\`etres d'une commande "\newcolumntype" d\'efinie en utilisant
%   ces d\'eclarations. Par exemple, supposons que nous utilisons un
%   sp\'ecificateur de colonne \texttt{C} (d\'efini au-dessus) dans un
%   environnement \texttt{array}. Le \texttt{C} indique du texte
%   centr\'e dans la colonne, alors que ">{\bfseries}C", qui est
%   r\'e\'ecrit en ">{\bfseries}>{$}c<{$}" ne peut pas sp\'ecifier une
%   colonne de texte en gras, parce que le pr\'eambule ressemblera en
%   fait \`a "\hfil$\bfseries$#$ $\hfil" et donc le texte dans la
%   colonne n'est pas affect\'e par la commande "\bfseries"\,! La
%   version actuelle inverse l'ordre de ces d\'eclarations, et ainsi
%   l'exemple pr\'ec\'edent fournit un pr\'eambule de la forme "\hfil$"
%   "$\bfseries#$" "$\hfil", les dollars s'annulant mutuellement pour
%   donner l'effet escompt\'e.
%
% \item L'utilisation de "\extracolsep" est sujette aux deux
%   restrictions suivantes. Il doit y a voir au plus une commande
%   "\extracolsep" par sp\'ecificateur "@" ou "!", et cette commande
%   doit \^etre entr\'ee telle quelle, elle ne doit pas \^etre le
%   r\'esultat du d\'eveloppement d'une commande.
%
%   Ainsi, "\newcommand{\ef}{\extracolsep{\fill}}" \ldots "@{\ef}" ne
%   marche pas avec ce package. Cependant, il est possible d'utiliser
%   \`a la place une construction comme
%   "\newcolumntype{e}{@{\extracolsep{\fill}}".
%
% \item Comme indiqu\'e dans le \LaTeX{} book, afin de d\'efinir la
%   commande "\multicolumn", chaque colonne \`a l'exception de la
%   premi\`ere est compos\'ee du texte compris dans la cellule et de ce
%   qui se trouve dans l'espace entre les colonnes situ\'e
%   \emph{apr\`es} cette colonne. Cela signifie que dans un tableau avec
%   comme pr\'eambule "|l|l|l|l|", une entr\'ee telle que
%   "\multicolumn{2}{|c|}" est incorrecte si elle n'intervient pas dans la
%   premi\`ere colonne. 
%
%   Dans le \LaTeX{} standard, cette erreur n'est pas tellement visible
%   parce que cette version ajoute des espaces n\'egatifs, si bien que
%   chaque "|" n'occupe pas de place horizontalement. Mais dans ce
%   package, les lignes verticales conservent leur \'epaisseur, on voit
%   alors deux lignes si deux barres ont \'et\'e sp\'ecifi\'ees.
% \end{itemize}
%
% 
%
% \changes{v2.2b}{1994/02/04}{Suppression de l'invite en mode interactif}
%
% \StopEventually{
%
%
% \begin{thebibliography}{1}
%    \bibitem{bk:GMS94} \textsc{M.~Goossens}, \textsc{F.~Mittelbach}
%       et \textsc{A.~Samarin}.
%       \newblock The \LaTeX{} Companion.
%       \newblock
%       Addison-Wesley, Reading, Massachusetts, 1994.
%    \bibitem{bk:knuth}  \textsc{D. E. Knuth}.
%       \newblock  The \TeX{}book (Computers \& Typesetting Volume A).
%       \newblock
%       Addison-Wesley, Reading, Massachusetts, 1986.
%    \bibitem{bk:lamport} \textsc{L. Lamport}.
%       \newblock
%       \LaTeX\ --- A Document Preparation System.
%       \newblock
%       Addison-Wesley, Reading, Massachusetts, 1986.
% \end{thebibliography}
%
% }   ^^A  end of \StopEventually
%
%
%\selectlanguage{english}
%
%
% \section{The documentation driver file}
%
% The first bit of code contains the documentation driver file for
% \TeX{}, i.e., the file that will produce the documentation you are
% currently reading. It will be extracted from this file by the
% \texttt{docstrip} program.
%    \begin{macrocode}
%<*driver>
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\documentclass{ltxdoc}

\AtBeginDocument{\DeleteShortVerb{\|}}  % undo the default is not used

 \usepackage{array}
%</driver>
%    \end{macrocode}
% \iffalse
%<*driver>
 \usepackage[english,frenchb]{babel}
 \usepackage[T1]{fontenc}
%</driver>
% \fi
%    \begin{macrocode}
%<*driver>

 % Allow large table at bottom
 \renewcommand{\bottomfraction}{0.7} 

\EnableCrossrefs         
 %\DisableCrossrefs   % Say \DisableCrossrefs if index is ready

\RecordChanges                  % Gather update information

\CodelineIndex                  % Index code by line number

 %\OnlyDescription    % comment out for implementation details
 %\OldMakeindex       % use if your MakeIndex is pre-v2.9
\begin{document}
   \DocInput{f-array.dtx}
\end{document}
%</driver>
%    \end{macrocode}
%
%
% \section{The construction of the preamble}
%
% \DeleteShortVerb{\"}
% \MakeShortVerb{\=}
%
% It is obvious that those environments will consist mainly of an
% =\halign=, because \TeX\ typesets tables using this primitive.
% That is why we will now take a look at the algorithm which determines
% a preamble for a =\halign= starting with a given user preamble
% using the options mentioned above.
%
%
%    The current version is defined at the top of the file looking
%    something like this
%    \begin{macrocode}
%<*package>
%\NeedsTeXFormat{LaTeX2e}[1994/05/13]
%\ProvidesPackage{array}[\filedate\space version\fileversion]
%    \end{macrocode}
%
% The most interesting macros of this implementation are without doubt
% those which are responsible for the construction of the preamble for
% the =\halign=. The underlying algorithm was developed by
% \textsc{Lamport} (resp.\ \textsc{Knuth}, see texhax V87\#??), and it
% has been extended and improved.
%
% The user preamble will be read \textsf{token} by \textsf{token}.  A
% \textsf{token} is a single character like \texttt{c} or a block
% enclosed in ={...}=. For example the preamble of
% =\begin{tabular}=\linebreak[0]={lc||c@{\hspace{1cm}}}= consists of
% the \textsf{token} \texttt{l}, \texttt{c}, \texttt{|}, \texttt{|},
% \texttt{@} and =\hspace{1cm}=.
%
% The currently used \textsf{token} and the one, used before, are needed
% to decide on how the construction of the preamble has to be
% continued.
% In the example mentioned above the \texttt{l} causes the preamble
% to begin with =\hskip\tabcolsep=. Furthermore
% =# \hfil= would be appended to define a flush left column.
% The next \textsf{token} is a \texttt{c}. Because it was preceded by an
% \texttt{l} it generates a new column. This is done with
% =\hskip \tabcolsep & \hskip \tabcolsep=. The column which is to
% be centered will be appended with =\hfil # \hfil=.
% The \textsf{token} \texttt{|} would then add a space of
% =\hskip \tabcolsep=
% and a vertical line because the last
% \textsf{tokens} was a \texttt{c}.
% The following \textsf{token} \texttt{|} would only add a space
% =\hskip \doublerulesep= because it was preceded by the
% \textsf{token} \texttt{|}. We will not discuss our example further but
%  rather take a look at the general case of constructing preambles.
%
% The example shows that the desired preamble for the
% =\halign= can be constructed as soon as the action of all
% combinations
% of the preamble \textsf{tokens} are specified. There are 18 such
% \textsf{tokens}
% so we have $19 \cdot 18 \string= 342$ combinations if we count the
% beginning of
% the preamble as a special \textsf{token}. Fortunately, there are many
% combinations which generate the same spaces, so we can define
% \textsf{token} classes. We will identify a
% \textsf{token} within a class with a number, so we can insert the
% formatting (for example of a column).
% Table~\ref{tab+Klassen} lists all \textsf{token} classes and
% their corresponding numbers.
% \begin{table}[ht]
% \begin{center}
%    \begin{tabular}[t]{>{\ttfamily}ccc}
%       \textsf{token} & =\@chclass= & =\@chnum= \\[2mm]
%       c   & 0  & 0 \\
%       l   & 0  & 1 \\
%       r   & 0  & 2 \\
%       p-arg    & 0  & 3 \\
%       t-arg    & 0  & 4 \\
%       b-arg    & 0  & 5 \\
%       |   & 1  & 0 \\
%       !-arg    & 1  & 1 \\
%       <-arg    & 2  & --- \\
%       >-arg    & 3  & ---
%    \end{tabular}
%    \kern3mm \vrule \kern3mm%
%    \begin{tabular}[t]{>{\ttfamily}ccc}
%       \textsf{token} & =\@chclass= & =\@chnum= \\[2mm]
%       Start    & 4  & --- \\
%       @-arg    & 5  & --- \\
%       !   & 6  & --- \\
%       @   & 7  & --- \\
%       <   & 8  & --- \\
%       >   & 9  & --- \\
%       p   & 10 & 3 \\
%       t   & 10 & 4 \\
%       b   & 10 & 5
%    \end{tabular}
% \end{center}
% \caption{Classes of preamble \textsf{tokens}}
% \label{tab+Klassen}
% \end{table}
%
%
% \begin{macro}{\@chclass}
% \begin{macro}{\@chnum}
% \begin{macro}{\@lastchclass}
%    The class and the number of the current \textsf{token} are saved in
%    the
%    \textsf{count} registers =\@chclass=
%    and =\@chnum=, while the class of the previous
%    \textsf{token} is stored in the
%    \textsf{count} register =\@lastchclass=.
%    All of the mentioned registers are already allocated in
%    \texttt{latex.tex},
%    which is the reason why the following three lines of code are
%    commented out.
%    Later throughout the text I will not mention it again explicitely
%    whenever I use a =%= sign. These parts are already defined in
%    \texttt{latex.tex}.
%    \begin{macrocode}
% \newcount \@chclass
% \newcount \@chnum
% \newcount \@lastchclass
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
%
% \begin{macro}{\@addtopreamble}
%    We will save the already constructed preamble for
%    the =\halign=
%    in the global macro =\@preamble=. This will then be
%     enlarged with
%    the command =\@addtopreamble=.
%    \begin{macrocode}
\def\@addtopreamble#1{\xdef\@preamble{\@preamble #1}}
%    \end{macrocode}
% \end{macro}
%
%
%
%
%
% \subsection{The character class of a \textsf{token}}
%
% \begin{macro}{\@testpach}
% \changes{v2.0a}{1989/05/12}{p option renamed to m (middle).}
% \changes{v2.0a}{1989/05/12}{t option renamed to p to be compatible to
%                         the original.}
%    With the help of =\@lastchclass= we can now define a macro
%    which determines the class and the number of a given preamble
%    \textsf{token}
%    and assigns them to the registers
%    =\@chclass= and =\@chnum=.
% \changes{v2.0f}{1992/02/29}{Argument removed since implicitly known}
%    \begin{macrocode}
\def\@testpach{\@chclass
%    \end{macrocode}
%    First we deal with the cases in which the \textsf{token}
%    (=#1=) is the argument of \texttt{!}, \texttt{@}, \texttt{<} or
%    \texttt{>}. We can see this from the value of =\@lastchclass=:
%    \begin{macrocode}
 \ifnum \@lastchclass=6 \@ne \@chnum \@ne \else
  \ifnum \@lastchclass=7 5 \else
   \ifnum \@lastchclass=8 \tw@ \else
    \ifnum \@lastchclass=9 \thr@@
%    \end{macrocode}
%    Otherwise we will assume that the \textsf{token} belongs to the
%    class $0$
%    and assign the corresponding number to =\@chnum= if our
%    assumption is correct.
%    \begin{macrocode}
   \else \z@
%    \end{macrocode}
%    If the last \textsf{token} was a \texttt{p}, \texttt{m} or a
%    \texttt{b}, =\@chnum= already has the right value. This is the
%    reason for the somewhat curious choice of the \textsf{token}
%    numbers in class $10$.
%    \begin{macrocode}
   \ifnum \@lastchclass = 10 \else
%    \end{macrocode}
%    Otherwise we will check if =\@nextchar= is either a \texttt{c},
%    \texttt{l} or an \texttt{r}.  Some applications change the
%    catcodes of certain characters like ``\texttt{@}'' in
%    \texttt{amstex.sty}. As a result the tests below would fail since
%    they assume non-active character tokens. Therefore we evaluate
%    =\@nextchar= once thereby turning the first token of its
%    replacement text into a char. At this point here this should have
%    been the only char present in =\@nextchar= which put into via a
%    =\def=.
% \changes{v2.0f}{1992/02/29}{Ensure to test a char which is not active}
%    \begin{macrocode}
   \edef\@nextchar{\expandafter\string\@nextchar}%
   \@chnum
   \if \@nextchar c\z@ \else
    \if \@nextchar l\@ne \else
     \if \@nextchar r\tw@ \else
%    \end{macrocode}
%    If it is a different \textsf{token}, we know that the class was
%    not $0$. We assign the value $0$ to =\@chnum= because this value
%    is needed for the \texttt{|}--\textsf{token}. Now we must check
%    the remaining classes.  Note that the value of =\@chnum= is
%    insignificant here for most classes.
%    \begin{macrocode}
   \z@ \@chclass
   \if\@nextchar |\@ne \else
    \if \@nextchar !6 \else
     \if \@nextchar @7 \else
      \if \@nextchar <8 \else
       \if \@nextchar >9 \else
%    \end{macrocode}
%    The remaining permitted \textsf{tokens} are \texttt{p},
%    \texttt{m} and \texttt{b} (class $10$).
%    \begin{macrocode}
  10
  \@chnum
  \if \@nextchar m\thr@@\else
   \if \@nextchar p4 \else
    \if \@nextchar b5 \else
%    \end{macrocode}
%    Now the only remaining possibility is a forbidden \textsf{token},
%    so we choose class $0$ and number $0$ and give an error message.
%    Then we finish the macro by closing all =\if='s.
%    \begin{macrocode}
   \z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi
   \fi \fi  \fi  \fi  \fi  \fi  \fi \fi \fi \fi \fi \fi}
%    \end{macrocode}
% \end{macro}
%
%
%
%
%
% \subsection{Multiple columns ($*$--form)}
%
% \begin{macro}{\@xexpast}
% \begin{macro}{\the@toks}
% \begin{macro}{\the@toksz}
%    \label{@xexpast} Now we discuss the macro that deletes all forms
%    of type =*{=\textit{N\/}=}{=\textit{String\/}=}= from a user
%    preamble and replaces them with \textit{N} copies of
%    \textit{String}.  Nested $*$--expressions are dealt with
%    correctly, that means $*$--expressions are not substituted if
%    they are in explicit braces, as in =@{*}=.
%
%    This macro is called via
%    =\@xexpast=\meta{preamble}=*0x\@@=.
%    The $*$--expression =*0x= is being used to terminate the
%    recursion,
%    as we shall see later, and =\@@= serves as an argument
%    delimiter. =\@xexpast= has four arguments. The first
%    one is the part of the
%    user preamble before the first $*$--expression while the second
%    and third ones are the arguments of the first $*$--expression
%    (that is \textit{N} and \textit{String} in the notation mentioned
%    above).
%    The fourth argument is the rest of the preamble.
%    \begin{macrocode}
\def\@xexpast#1*#2#3#4\@@{%
%    \end{macrocode}
%    The number of copies of \textit{String} (=#2=) that are to be
%    produced will be saved in a \textsf{count} register.
%    \begin{macrocode}
   \@tempcnta #2
%    \end{macrocode}
%    We save the part of the preamble which does not
%    contain a $*$--form (=#1=)
%    in a \PlainTeX\ \textsf{token} register.
%    We also save \textit{String} (=#3=) using a \LaTeX\
%    \textsf{token} register.
%    \begin{macrocode}
   \toks@={#1}\@temptokena={#3}%
%    \end{macrocode}
%    Now we have to use a little trick to produce \textit{N} copies of
%    \textit{String}.
%    We could try =\def\@tempa{#1}= and then
%    \textit{N} times =\edef\@tempa{\@tempa#3}=. This would have the
%    undesired effect that all macros within =#1= and =#3=
%    would be expanded, although, for example, constructions like
%    =@{..}= are not supposed to be changed.
%    That is why we =\let= two control sequences to
%    be equivalent to =\relax=.
%    \begin{macrocode}
   \let\the@toksz\relax \let\the@toks\relax
%    \end{macrocode}
%    Then we ensure that =\@tempa= contains
%    ={\the@toksz\the@toks...\the@toks}= (the macro
%    =\the@toks= exactly \textit{N\/} times) as substitution text.
%    \begin{macrocode}
   \def\@tempa{\the@toksz}%
   \ifnum\@tempcnta >0 \@whilenum\@tempcnta >0\do
     {\edef\@tempa{\@tempa\the@toks}\advance \@tempcnta \m@ne}%
%    \end{macrocode}
%    If \textit{N\/} was greater than zero we prepare for another call
%    of =\@xexpast=. Otherwise we assume we have reached the end of
%    the user preamble, because we had appended =*0x\@@= when we first
%    called =\@xexpast=.  In other words: if the user inserts
%    =*{0}{..}= in his preamble, \LaTeX\ ignores the rest of it.
%    \begin{macrocode}
       \let \@tempb \@xexpast \else
       \let \@tempb \@xexnoop \fi
%    \end{macrocode}
%    Now we will make sure that the part of the user preamble, which
%    was already dealt with, will be saved again in =\@tempa=.
%    \begin{macrocode}
   \def\the@toksz{\the\toks@}\def\the@toks{\the\@temptokena}%
   \edef\@tempa{\@tempa}%
%    \end{macrocode}
%    We have now evaluated the first $*$--expression, and the user
%    preamble up to this point
%    is saved in =\@tempa=. We will put the contents of
%    =\@tempa= and the rest of the user preamble together and work
%    on the result with =\@tempb=. This macro either corresponds
%    to =\@xexpast=, so that the next
%    $*$--expression is handled, or to the macro =\@xexnoop=,
%    which only ends the recursion by deleting its argument.
%    \begin{macrocode}
   \expandafter \@tempb \@tempa #4\@@}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@xexnoop}
%    So the first big problem is solved. Now it is easy to
%    specify =\@xexnoop=.
%    Its argument is delimited by =\@@= and it simply expands to
%    nothing.
%    \begin{macrocode}
%  \def\@xexnoop#1\@@{}
%    \end{macrocode}
% \end{macro}
%
%
%
%
% \section{The insertion of declarations
%           (\texttt{>}, \texttt{<}, \texttt{!}, \texttt{@})}
%
%
% The preamble will be enlarged with the help of =\xdef=, but the
% arguments of \texttt{>}, \texttt{<},~\texttt{!}\ and \texttt{@} are
% not supposed to be expanded during the construction (we want an
% implementation that doesn't need a =\protect=). So we have to find a
% way to inhibit the expansion of those arguments.
%
% We will solve this problem with \textsf{token} registers. We need
% one register for every \texttt{!}\ and \texttt{@}, while we need two
% for every \texttt{c}, \texttt{l}, \texttt{r}, \texttt{m}, \texttt{p}
% or \texttt{b}. This limits the number of columns of a table because
% there are only 256 \textsf{token} registers. But then, who needs
% tables with more than 100 columns?
%
% One could also find a solution which only needs two or three
% \textsf{token} registers by proceeding similarly as in the macro
% =\@xexpast= (see page \pageref{@xexpast}). The advantage of our
% approach is the fact that we avoid some of the problems that arise
% with the other method\footnote{Maybe there are also historical
%  reasons.}.
%
% So how do we proceed? Let us assume that we had =!{foo}= in the
% user preamble and say we saved \texttt{foo} in
% \textsf{token} register $5$. Then we call
% =\@addtopreamble{\the@toks5}= where
% =\the@toks= is defined in a way that it does not expand
% (for example it could be equivalent to =\relax=). Every
% following call
% of =\@addtopreamble= leaves =\the@toks5= unchanged in
% =\@preamble=. If the construction of the preamble is completed
% we change the definition of =\the@toks= to
% =\the\toks= and expand =\@preamble= for the last time.
% During this process all parts of the form
%    =\the@toks=\meta{Number}
% will be substituted by the contents of the respective \textsf{token}
% registers.
%
% As we can see from this informal discussion the construction of the
% preamble has to take place within a group, so that the
% \textsf{token} registers we use will be freed later on. For that
% reason we keep all assignments to =\@preamble= global; therefore the
% replacement text of this macro will remain the same after we leave
% the group.
%
% \begin{macro}{\count@}
%    We further need a \textsf{count} register to remember which
%    \textsf{token} register is to be used next. This will be
%    initialized with $-1$ if we want to begin with the \textsf{token}
%    register $0$. We use the \PlainTeX\ scratch register =\count@=
%    because everything takes place locally. All we have to do is
%    insert =\the@toks= =\the= =\count@= into the preamble.
%    =\the@toks= will remain unchanged and =\the\count@= expands into
%    the saved number.
% \end{macro}
%
% \begin{macro}{\prepnext@tok}
%    The macro =\prepnext@tok= is in charge of preparing the next
%    \textsf{token} register. For that purpose we increase
%    =\count@= by $1$:
%    \begin{macrocode}
\def\prepnext@tok{\advance \count@ \@ne
%    \end{macrocode}
%    Then we locally delete any contents the
%    \textsf{token} register might have.
%    \begin{macrocode}
   \toks\count@{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\save@decl}
%    During the construction of the preamble the current
%    \textsf{token} is always saved in the macro =\@nextchar= (see the
%    definition of =\@mkpream= on page \pageref{@mkpream}). The macro
%    =\save@decl= saves it into the next free \textsf{token} register,
%    i.e.\ in =\toks\count@=.
% \changes{v2.0c}{1990/08/14}{\cs{relax} removed and added elsewhere.}
%    \begin{macrocode}
\def\save@decl{\toks\count@ \expandafter{\@nextchar}}
%    \end{macrocode}
%    The reason for the  use of =\relax= is the following
%    hypothetical situation in the preamble:
%    \quad =..\the\toks1\the\toks2..= \quad \TeX\ expands
%    =\the\toks2= first in order to find out if the digit =1=
%    is followed by other digits. E.g.\ a =5= saved in the
%    \textsf{token} register $2$ would lead \TeX\ to insert the contents
%    of \textsf{token} register $15$ instead of $1$ later on.
% 
% The example above referred to an older version of =\save@decl= which
% inserted a =\relex= inside the token register. This is now moved to
% the places where the actual token registers are inserted (look for
% =\the@toks=) because the old version would still make =@=
% expressions to moving arguments since after expanding the second
% register while looking for the end of the number the contents of the
% token register is added so that later on the whole register will be
% expanded.  This serious bug was found after nearly two years
% international use of this package  by Johannes Braams.
% \end{macro}
%
%
%
% How does the situation look like, if we want to add another column
% to the preamble, i.e.\ if we have found a \texttt{c}, \texttt{l},
% \texttt{r}, \texttt{p}, \texttt{m} or \texttt{b} in the user
% preamble?  In this case we have the problem of the \textsf{token}
% register from =>{..}= and =<{..}= having to be inserted at this
% moment because formating instructions like =\hfil= have to be set
% around them. On the other hand it is not known yet, if any =<{..}=
% instruction will appear in the user preamble at all.
%
% We solve this problem by adding two \textsf{token} registers at a
% time.  This explains, why we have freed the \textsf{token} registers
% in =\prepnext@tok=.
%
% \begin{macro}{\insert@column}
% \begin{macro}{\@sharp}
%    We now define the macro =\insert@column= which will do
%    this work for us.
%    \begin{macrocode}
\def\insert@column{%
%    \end{macrocode}
%    Here, we assume that the \textsf{count} register
%    =\@tempcnta= has saved the value $=\count@= - 1$.
%    \begin{macrocode}
   \the@toks \the \@tempcnta
%    \end{macrocode}
%    Next follows the =#= sign which specifies the place
%    where the text of the column shall be inserted. To avoid
%    errors during the expansions in
%    =\@addtopreamble= we hide this sign in the command
%    =\@sharp= which is temporarily occupied with
%    =\relax= during the build-up of the preamble.
%    To remove unwanted spaces before and after the column text, we set
%    an =\ignorespaces=  in front and a =\unskip= afterwards.
% \changes{v2.0e}{1991/02/07}{Added \{\} around \cs{@sharp} for new ftsel}
% \changes{v2.0h}{1992/06/22}{Removed \{\} again in favour of
%                             \cs{d@llarbegin}}
%    \begin{macrocode}
   \ignorespaces \@sharp \unskip
%    \end{macrocode}
%    Then the second \textsf{token} register follows whose number should
%    be saved in =\count@=.
%    We make sure that there will be no further expansion after reading
%    the number, by finishing with =\relax=. The case above is not
%    critical since it is ended by =\ignorespaces=.
% \changes{v2.0c}{1990/08/14}{\cs{relax} added to avoid problem 
%                           \cs{the}\cs{toks0}\cs{the}\cs{toks1}.}
%    \begin{macrocode}
   \the@toks \the \count@ \relax}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
%
% \subsection{The separation of columns}
%
% \begin{macro}{\@addamp}
%    In the preamble a =&= has to be inserted between any two columns;
%    before the first column there should not be a =&=. As the user
%    preamble may start with a \texttt{|} we have to remember somehow
%    if we have already inserted a =#= (i.e.\ a column). This is done
%    with the boolean variable =\if@firstamp= that we test in
%    =\@addamp=, the macro that inserts the =&=.
%    \begin{macrocode}
%    \newif \@iffirstamp
%    \def\@addamp{\if@firstamp \@firstampfalse
%                 \else \@addtopreamble &\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@acol}
% \begin{macro}{\@acolampacol}
% \begin{macro}{\col@sep}
%    We will now define some abbreviations for the extensions,
%    appearing most often in the preamble build-up.
%    Here =\col@sep= is a \textsf{dimen} register which is set
%    equivalent to =\arraycolsep= in an \textsf{array}--environment,
%    otherwise it is set equivalent to =\tabcolsep=.
%    \begin{macrocode}
\newdimen\col@sep
\def\@acol{\@addtopreamble{\hskip\col@sep}}
%    \def\@acolampacol{\@acol\@addamp\@acol}
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \subsection{The macro \texttt{\textbackslash @mkpream}}
%
% \begin{macro}{\@mkpream}
% \begin{macro}{\the@toks}
%    \label{@mkpream}
%    Now we can define the macro which builds up the preamble for the
%    =\halign=.
%    First we initialize =\@preamble=, =\@lastchclass=
%    and the boolean variable =\if@firstamp=.
%    \begin{macrocode}
\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
%    \end{macrocode}
%    During the build-up of the preamble we cannot directly use the
%    =#= sign; this would lead to an error message in the next
%    =\@addtopreamble= call.
%    Instead, we use the command =\@sharp= at places where later
%    a =#= will be.
%    This command is at first given the meaning =\relax=;
%    therefore it will not be expanded when the preamble
%    is extended.
%    In the macro =\@array=, shortly before the =\halign=
%    is carried out, =\@sharp= is given its final meaning.
%
%    In a similar way,
%    we deal with the commands =\@startpbox= and
%    =\@endpbox=, although the reason is different here: these
%    macros expand in many \textsf{tokens} which would delay the
%    build-up of the preamble.
%    \begin{macrocode}
   \let\@sharp\relax \let\@startpbox\relax \let\@endpbox\relax
%    \end{macrocode}
%    Now we remove possible  $*$-forms in the user preamble with the
%    command =\@xexpast=.  As we already know, this command saves
%    its result in the macro =\@tempa=.
%    \begin{macrocode}
   \@xexpast #1*0x\@@
%    \end{macrocode}
%    Afterwards we initialize all registers and macros, that we need
%    for the build-up of the preamble.
%    Since we want to start with the \textsf{token} register $0$,
%    =\count@= has to contain the value $-1$.
%    \begin{macrocode}
   \count@\m@ne
   \let\the@toks\relax
%    \end{macrocode}
%    Then we call up =\prepnext@tok= in order to prepare the
%    \textsf{token} register $0$ for use.
%    \begin{macrocode}
   \prepnext@tok
%    \end{macrocode}
%    To evaluate the user preamble (without stars) saved in
%    =\@tempa= we use the \LaTeX--macro =\@tfor=.
%    The strange appearing construction with =\expandafter= is
%    based on the fact that we have to put the replacement text of
%    =\@tempa= and not the macro =\@tempa= to this
%    \LaTeX--macro.
%    \begin{macrocode}
   \expandafter \@tfor \expandafter \@nextchar
    \expandafter :\expandafter =\@tempa \do
%    \end{macrocode}
%    The body of this loop (the group after the =\do=)
%    is executed for one \textsf{token} at a time, whereas
%    the current \textsf{token} is saved in =\@nextchar=.
%    At first we evaluate the current \textsf{token} with the already
%    defined macro =\@testpach=, i.e.\ we assign to
%    =\@chclass= the character class and to =\@chnum=
%    the character number of this \textsf{token}.
% \changes{v2.0f}{1992/02/29}{\cs{@testpach} now without arg}
%    \begin{macrocode}
   {\@testpach
%    \end{macrocode}
%    Then we branch out depending on the value of =\@chclass= into
%    different macros that extend the preamble respectively.
%    \begin{macrocode}
   \ifcase \@chclass \@classz \or \@classi \or \@classii
     \or \save@decl \or \or \@classv \or \@classvi
     \or \@classvii \or \@classviii  \or \@classix
     \or \@classx \fi
%    \end{macrocode}
%    Two cases deserve our special attention: Since the current
%    \textsf{token} cannot have the character class $4$ (start) we
%    have skipped this possibility. If the character class is $3$,
%    only the content of =\@nextchar= has to be saved into the current
%    \textsf{token} register; therefore we call up =\save@decl=
%    directly and save a macro name.  After the preamble has been
%    extended we assign the value of =\@chclass= to the counter
%    =\@lastchclass= to assure that this information will be available
%    during the next run of the loop.
%    \begin{macrocode}
   \@lastchclass\@chclass}%
%    \end{macrocode}
%    After the loop has been finished space must still be added to
%    the created preamble, depending on the last \textsf{token}.
%    Depending on the value of =\@lastchclass= we perform
%    the necessary operations.
%    \begin{macrocode}
   \ifcase\@lastchclass
%    \end{macrocode}
%    If the last class equals $0$ we add a
%    =\hskip \col@sep=.
%    \begin{macrocode}
   \@acol \or
%    \end{macrocode}
%    If it equals $1$ we do not add any additional space so that the
%    horizontal lines do not exceed the vertical ones.
%    \begin{macrocode}
   \or
%    \end{macrocode}
%    Class $2$ is treated like class $0$ because a =<{...}=  can
%    only directly follow after class $0$.
%    \begin{macrocode}
   \@acol \or
%    \end{macrocode}
%    Most of the other possibilities can only appear if the user
%    preamble was defective. Class $3$ is not allowed since after a
%    =>{..}= there must always follow a \texttt{c}, \texttt{l},
%    \texttt{r}, \texttt{p},\texttt{m} or \texttt{b}. We report an
%    error and ignore the declaration given by ={..}=.
%    \begin{macrocode}
   \@preamerr \thr@@ \or
%    \end{macrocode}
%    If =\@lastchclass= is $4$ the user preamble has been empty.
%    To continue, we insert a =#= in the preamble.
%    \begin{macrocode}
   \@preamerr \tw@ \@addtopreamble\@sharp \or
%    \end{macrocode}
%    Class $5$ is allowed again. In this case
%    (the user preamble ends with =@{..}=) we need not
%    do anything.
%    \begin{macrocode}
   \or
%    \end{macrocode}
%    Any other case means that the arguments to =@=, \texttt{!},
%    \texttt{<}, \texttt{>}, \texttt{p}, \texttt{m} or \texttt{b} have
%    been forgotten. So we report an error and ignore the last
%    \textsf{token}.
%    \begin{macrocode}
   \else  \@preamerr \@ne \fi
%    \end{macrocode}
%    Now that the build-up of the preamble is almost finished we can
%    insert the \textsf{token} registers and therefore redefine
%    =\the@toks=. The actual insertion, though, is performed
%    later.
%    \begin{macrocode}
   \def\the@toks{\the\toks}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
%  \section{The macros \texttt{\textbackslash @classz}
%           to \texttt{\textbackslash @classx}}
%
% The preamble is extended by the macros =\@classz= to
% =\@classx= which are called by =\@mkpream=
%  depending on =\@lastchclass=
% (i.e. the character class of the last \textsf{token}).
% \begin{macro}{\@classx}
%    First we define =\@classx= because of its important r\^ole.
%    When it is called we find that the current
%    \textsf{token} is \texttt{p}, \texttt{m} or \texttt{b}.
%    That means that a new column has to start.
%    \begin{macrocode}
\def\@classx{%
%    \end{macrocode}
%    Depending on the value of =\@lastchclass= different actions
%    must take place:
%    \begin{macrocode}
  \ifcase \@lastchclass
%    \end{macrocode}
%    If the last character class was $0$ we separate the columns by
%    =\hskip\col@sep= followed by =&= and another
%    =\hskip\col@sep=.
%    \begin{macrocode}
  \@acolampacol \or
%    \end{macrocode}
%    If the last class was class $1$ --- that means that a vertical
%    line was
%    drawn, --- before this line a =\hskip\col@sep= was inserted.
%    Therefore there has to be only a =&= followed by
%    =\hskip\col@sep=. But this =&= may be inserted only
%    if this is not the first column. This process is controlled
%    by =\if@firstamp= in the macro =\addamp=.
%    \begin{macrocode}
  \@addamp \@acol \or
%    \end{macrocode}
%    Class $2$ is treated like class $0$ because =<{...}= can only
%    follow after class $0$.
%    \begin{macrocode}
  \@acolampacol \or
%    \end{macrocode}
%    Class $3$ requires no actions because all things necessary have
%    been done by the preamble \textsf{token} \texttt{>}.
%    \begin{macrocode}
  \or
%    \end{macrocode}
%    Class $4$ means that we are at the beginning of the preamble.
%    Therefore we start the preamble with =\hskip\col@sep= and
%    then call =\@firstampfalse=. This makes sure that a later
%    =\@addamp= inserts the character
%    =&= into the preamble.
%    \begin{macrocode}
  \@acol \@firstampfalse \or
%    \end{macrocode}
%    For class $5$ \textsf{tokens} only the character =&= is inserted
%    as a column separator. Therefore we call =\@addamp=.
%    \begin{macrocode}
  \@addamp
%    \end{macrocode}
%    Other cases are impossible. For an example
%    $=\@lastchclass= \string= 6$---as it might appear in a
%    preamble of the form =...!p...=---\texttt{p} would have
%    been taken as an  argument of \texttt{!}\ by =\@testpach=.
%    \begin{macrocode}
  \fi}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@classz}
%    If the character class of the last \textsf{token} is $0$ we have
%    \texttt{c}, \texttt{l}, \texttt{r} or an argument of \texttt{m},
%    \texttt{b} or\ \texttt{p}. In the first three cases the preamble
%    must be extended the same way as if we had class $10$. The
%    remaining two cases do not require any action because the space
%    needed was generated by the last \textsf{token} (i.e.\
%    \texttt{m}, \texttt{b} or \texttt{p}). Since =\@lastchclass= has
%    the value $10$ at this point nothing happens when =\@classx= is
%    called. So the macro =\@chlassz= may start like this:
%    \begin{macrocode}
\def\@classz{\@classx
%    \end{macrocode}
%    According to the definition of =\insert@column= we must store
%    the number of the \textsf{token} register in which a preceding
%    =>{..}= might have stored its argument into
%    =\@tempcnta=.
%    \begin{macrocode}
   \@tempcnta \count@
%    \end{macrocode}
%    To have $=\count@= \string= =\@tmpcnta= + 1$ we prepare
%    the next \textsf{token} register.
%    \begin{macrocode}
   \prepnext@tok
%    \end{macrocode}
%    Now the preamble must be extended with the column whose format
%    can be determinated by =\@chnum=.
%    \begin{macrocode}
   \@addtopreamble{\ifcase \@chnum
%    \end{macrocode}
%    If =\@chnum= has the value $0$ a centered column has to be
%    generated.
%    So we begin with stretchable space.
%    \begin{macrocode}
      \hfil
%    \end{macrocode}
%    The command =\d@llarbegin= follows expanding into =\begingroup=
%    (in the \textsf{tabular}--environment) or into =$=.  Doing this
%    (provided an appropriate setting of =\d@llarbegin=) we achieve
%    that the contents of the columns of an \textsf{array}--environment
%    are set in math mode while those of a \textsf{tabular}--environment
%    are set in LR mode.
%    \begin{macrocode}
      \d@llarbegin
%    \end{macrocode}
%    Now we insert the contents of the two \textsf{token} registers
%    and the symbol
%    for the column entry (i.e.\ =#= or
%    more precise =\@sharp=) using =\insert@column=.
%    \begin{macrocode}
      \insert@column
%    \end{macrocode}
%    We end this case with =\d@llarend= and =\hfil= where =\d@llarend=
%    again is either =$= or =\endgroup=.
%    \begin{macrocode}
      \d@llarend \hfil \or
%    \end{macrocode}
%    The templates for \texttt{l} and \texttt{r} (i.e.\ =\@chnum= $1$
%    or $2$) are generated the same way. Since one  =\hfil= is
%    missing the text is moved to the relevant side.
%    The =\kern\z@= is needed in case of an empty column
%    entry. Otherwise
%    the =\unskip= in =\insert@column= removes the
%    =\hfil=. Changed to =\hskip1sp= so that it interacts better with
%    =\@bsphack=.
% \changes{v2.3f}{1996/04/22}
%     {(DPC) Extra \cs{kern} keeps tabcolsep in empty l columns
%             internal/2122}
% \changes{v2.3i}{1996/06/14}
%     {Change both \cs{kern}\cs{z@} to \cs{hskip}1sp for latex/2160}
%    \begin{macrocode}
      \hskip1sp\d@llarbegin \insert@column \d@llarend \hfil \or
      \hfil\hskip1sp\d@llarbegin \insert@column \d@llarend \or
%    \end{macrocode}
%    The templates for \texttt{p}, \texttt{m} and \texttt{b} mainly
%    consist of a \textsf{box}. In case of \texttt{m} it is generated
%    by =\vcenter=.  This command is allowed only in math
%    mode. Therefore we start with a~=$=.
%    \begin{macrocode}
   $\vcenter
%    \end{macrocode}
%    The part of the templates which is the same in all three cases
%    (\texttt{p}, \texttt{m} and \texttt{b})
%    is built by the macros =\@startpbox= and
%    =\@endpbox=. =\@startpbox= has an argument:
%    the width of the column which is stored in the current
%    \textsf{token} (i.e.\ =\@nextchar=).
%    Between these two macros we find the well known
%    =\insert@column=.
%    \begin{macrocode}
   \@startpbox{\@nextchar}\insert@column \@endpbox $\or
%    \end{macrocode}
%    The templates for \texttt{p} and \texttt{b} are generated in the
%    same way though we do not need the =$= characters because we use
%    =\vtop= or =\vbox=.
%    \begin{macrocode}
   \vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or
   \vbox \@startpbox{\@nextchar}\insert@column \@endpbox
%    \end{macrocode}
%    Other values for =\@chnum= are impossible. Therefore we
%    end the arguments to =\@addtopreamble= and =\ifcase=.
%    Before we come to the end of =\@classz= we have to
%    prepare the next \textsf{token} register.
%    \begin{macrocode}
  \fi}\prepnext@tok}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@classix}
%    In case of class $9$ (\texttt{>}--\textsf{token}) we first check
%    if the character class of the last
%    \textsf{token} was $3$. In this case we have a
%    user preamble of the form =..>{...}>{...}..= which
%    is not allowed. We only give an error message and continue.
%    So the declarations defined by the first  =>{...}=
%    are ignored.
%    \begin{macrocode}
\def\@classix{\ifnum \@lastchclass = \thr@@
       \@preamerr \thr@@ \fi
%    \end{macrocode}
%    Furthermore, we call up =\@class10= because afterwards always a
%    new column is started by \texttt{c}, \texttt{l}, \texttt{r},
%    \texttt{p}, \texttt{m} or \texttt{b}.
%    \begin{macrocode}
       \@classx}
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\@classviii}
%    If the current \textsf{token} is a \texttt{<} the last character
%    class must be $0$. In this case it is not necessary to extend the
%    preamble. Otherwise we output an error message, set =\@chclass=
%    to $6$ and call =\@classvi=.  By doing this we achieve that
%    \texttt{<} is treated like \texttt{!}.
%    \begin{macrocode}
\def\@classviii{\ifnum \@lastchclass >\z@
      \@preamerr 4\@chclass 6 \@classvi \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@arrayrule}
%    There is only one incompatibility with the original definition:
%    the definition of =\@arrayrule=. In the original a line without
%    width\footnote{So the space between \texttt{cc} and \texttt{c|c}
%    is equal.}  is created by multiple insertions of 
% =\hskip .5\arrayrulewidth=.  
%    We only insert a vertical line into the
%    preamble.  This is done to prevent problems with \TeX's main
%    memory when generating tables with many vertical lines in them
%    (especially in the case of \textsf{floats}).
%    \begin{macrocode}
\def\@arrayrule{\@addtopreamble \vline}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classvii}
%    As a consequence it follows that in case of class $7$
%    (=@= \textsf{token})  the preamble need not to be extended.
%    In the original definition $=\@lastchclass= \string= 1$
%    is treated by inserting =\hskip .5\arrayrulewidth=.
%    We only check if the last \textsf{token} was of class $3$ which is
%    forbidden.
%    \begin{macrocode}
\def\@classvii{\ifnum \@lastchclass = \thr@@
%    \end{macrocode}
%    If this is true we output an error message and
%    ignore the declarations stored
%    by the last  =>{...}=, because these are overwritten
%    by the argument of \texttt{@}.
%    \begin{macrocode}
   \@preamerr \thr@@ \fi}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@classvi}
%    If the current \textsf{token} is a regular \texttt{!}\ and the
%    last class was $0$ or $2$ we extend the preamble with
%    =\hskip\col@sep=.  If the last \textsf{token} was of class $1$
%    (for instance \texttt{|}) we extend with =\hskip \doublerulesep=
%    because the construction =!{...}= has to be treated like
%    \texttt{|}.
%    \begin{macrocode}
\def\@classvi{\ifcase \@lastchclass
      \@acol \or
      \@addtopreamble{\hskip \doublerulesep}\or
      \@acol \or
%    \end{macrocode}
%    Now =\@preamerr...= should follow because a
%    user preamble of the form =..>{..}!.= is not allowed.
%    To save memory we call =\@classvii= instead which also
%    does what we want.
%    \begin{macrocode}
      \@classvii
%    \end{macrocode}
%    If =\@lastchclass= is $4$ or $5$ nothing has to be done.
%    Class $6$ to $10$ are not possible.
%    So we finish the macro.
%    \begin{macrocode}
      \fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classii}
% \begin{macro}{\@classiii}
%    In the case of character classes $2$ and $3$ (i.e.\ the argument
%    of \texttt{<} or \texttt{>}) we only have to store the current
%    \textsf{token} (=\@nextchar=) into the corresponding
%    \textsf{token} register since the preparation and
%    insertion of these registers
%    are done by the macro =\@classz=.
%    This is equivalent to calling =\save@decl= in the case of
%    class $3$. To save command identifiers we do this call up
%     in the macro =\@mkpream=.
%
%    Class $2$ exhibits a more complicated situation: the
%    \textsf{token} registers have already been inserted by
%    =\@classz=. So the value of =\count@= is too high
%    by one. Therefore we decrease =\count@= by $1$.
%    \begin{macrocode}
\def\@classii{\advance \count@ \m@ne
%    \end{macrocode}
%    Next we store the current \textsf{token} into the correct 
%    \textsf{token} register by calling =\save@decl= and then
%    increase the value of =\count@= again. At this point we
%    can save memory once more (at the cost of time) if we use the
%     macro =\prepnext@tok=.
%    \begin{macrocode}
   \save@decl\prepnext@tok}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\@classv}
%    If the current \textsf{token} is of class $5$ then it is an
%    argument of a \texttt{@} \textsf{token}. It must be stored into a
%    \textsf{token} register.
%    \begin{macrocode}
\def\@classv{\save@decl
%    \end{macrocode}
%    We extend the preamble with a command which inserts this
%    \textsf{token} register into the preamble when its construction
%    is finished. The user expects that this argument is worked out in
%    math mode if it was used in an
%    \textsf{array}--environment. Therefore we surround it with
%    =\d@llar...='s.
% \changes{v2.0c}{1990/08/14}{\cs{relax} added to avoid problem 
%                           `the`toks0`the`toks1.}
%    \begin{macrocode}
   \@addtopreamble{\d@llarbegin\the@toks\the\count@\relax\d@llarend}%
%    \end{macrocode}
%    Finally we must prepare the next \textsf{token} register.
%    \begin{macrocode}
   \prepnext@tok}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classi}
%    In the case of class $0$ we were able to generate the necessary
%    space between columns by using the macro =\@classx=.
%    Analogously the macro =\@classvi= can be used for class $1$.
%    \begin{macrocode}
\def\@classi{\@classvi
%    \end{macrocode}
%    Depending on =\@chnum= a vertical line
%    \begin{macrocode}
   \ifcase \@chnum \@arrayrule \or
%    \end{macrocode}
%    or (in case of =!{...}=) the current \textsf{token} --- stored
%    in =\@nextchar= --- has to be inserted into the preamble.
%    This corresponds to calling =\@classv=.
%    \begin{macrocode}
      \@classv \fi}
%    \end{macrocode}
% \end{macro}
%
%
%
% \begin{macro}{\@startpbox}
%    In =\@classz=  the macro =\@startpbox= is used.
%    The width of the \textsf{parbox} is passed as an argument.
%    =\vcenter=, =\vtop= or =\vbox= are already in the
%    preamble. So we start with the braces for the wanted box.
%    \begin{macrocode}
\def\@startpbox#1{\bgroup
%    \end{macrocode}
%    The argument is the width of the box. This information has to be
%    assigned to =\hsize=.
%    Then we assain default values to several parameters used in a
%    \textsf{parbox}.
% \changes{v2.3k}{1998/05/12}{Use \cs{setlength} to set \cs{hsize},
%      so that the calc package can be applied here (pr/2793)}
%    \begin{macrocode}
  \setlength\hsize{#1}\@arrayparboxrestore
%    \end{macrocode}
%    Our main problem is to obtain the same distance between succeeding
%    lines of the \textsf{parbox}.
%    We have to remember that the distance between two \textsf{parboxes}
%    should be defined by =\@arstrut=. That means that it can be
%    greater than the distance in a \textsf{parbox}.
%    Therefore it is not enough to set a =\@arstrut= at the
%    beginning and at the end of the \textsf{parbox}. This would
%    dimension the distance
%    between first and second line and the distance between the two
%    last lines of the \textsf{parbox} wrongly.
%    To prevent this we set an invisible rule of height
%    =\@arstrutbox=
%    at the beginning of the \textsf{parbox}. This has no effect on the
%    depth of the first line. At the end of the \textsf{parbox} we set
%    analogously another invisible rule which only affects the depth
%    of the last line. It is necessary to wait inserting this strut
%    until the paragraph actually starts to allow for things like
%    =\parindent= changes via =>{...}=.
% \changes{v2.1c}{1992/12/14}{Use `everypar to insert strut}
%    \begin{macrocode}
   \everypar{%
      \vrule \@height \ht\@arstrutbox \@width \z@
      \everypar{}}%
   }
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@endpbox}
%    If there are any declarations defined by =>{...}=
%    and =<{...}=
%    they now follow in the macro =\@classz= --- the contents
%    of the column in between.
%    So the macro =\@endpbox= must insert the \textsf{specialstrut}
%    mentioned earlier and then close the group opened by
%    =\@startpbox=.
% \changes{v2.2d}{1994/05/16}{Use \LaTeXe \cs{@finalstrut}}
% \changes{v2.3g}{1996/05/07}{Add \cs{hfil} for tools/2120}
%    \begin{macrocode}
\def\@endpbox{\@finalstrut\@arstrutbox \egroup\hfil}
%    \end{macrocode}
% \end{macro}
%
%
% \section{Building and calling \texttt{\textbackslash halign}}
%
% \begin{macro}{\@array}
%    After we have discussed the macros needed for the evaluation
%    of the user preamble we can define the macro =\@array=
%    which uses these macros to create a =\halign=.
%    It has two arguments. The first one is a position argument
%    which can be \texttt{t}, \texttt{b} or \texttt{c}; the
%    second one describes the wanted preamble,
%    e.g.\ it has the form =|c|c|c|=.
%    \begin{macrocode}
\def\@array[#1]#2{%
%    \end{macrocode}
%    First we define a \textsf{strut} whose size basically corresponds
%     to a normal \textsf{strut} multiplied by the factor
%    =\arraystretch=.
%    This \textsf{strut} is then  inserted into every row and enforces
%     a minimal distance between two rows.
%    Nevertheless, when using horizontal lines, large letters
%    (like accented capital letters) still collide with such lines.
%    Therefore at first we add to the height of a normal \textsf{strut}
%    the value of the parameter =\extrarowheight=.
%    \begin{macrocode}
  \@tempdima \ht \strutbox
  \advance \@tempdima by\extrarowheight
  \setbox \@arstrutbox \hbox{\vrule
             \@height \arraystretch \@tempdima
             \@depth \arraystretch \dp \strutbox
             \@width \z@}%
%    \end{macrocode}
%    Then we open a group, in which the user preamble is evaluated by
%    the macro =\@mkpream=. As we know this must happen locally.
%    This macro creates a preamble for a =\halign= and saves
%    its result globally in the control sequence =\@preamble=.
%    \begin{macrocode}
  \begingroup
  \@mkpream{#2}%
%    \end{macrocode}
%    We again redefine =\@preamble= so that a call up of =\@preamble=
%    now starts the =\halign=. Thus also the arguments of \texttt{>},
%    \texttt{<}, \texttt{@} and \texttt{!}, saved in the
%    \textsf{token} registers are inserted into the preamble.  The
%    =\tabskip= at the beginning and end of the preamble is set to
%    \textsf{0pt} (in the beginning by the use of =\ialign=). Also the
%    command =\@arstrut= is build in, which inserts the
%    =\@arstrutbox=, defined above. Of course, the opening brace after
%    =\ialign= has to be implicit as it will be closed in =\endarray=
%    or another macro.
% \changes{v2.3m}{1998/12/31}{Added \cs{noexpand} in front of \cs{ialign}
%    to guard against interesting :-) changes to \cs{halign} done to support
%    text glyphs in math}
%
%    The =\noexpand= in front of =\ialign= does no harm in standard \LaTeX{}
%    and was added since some experimental support for using text glyphs in math
%    redefines =\halign= with the result that is becomes expandable with
%    disastrous results in cases like this. 
%    In the kernel definition for this macro the problem does
%    not surface because there =\protect= is set (which is not necessary in this 
%    implementation as there is no arbitrary user input that can get expanded) and
%    the experimental code made the redefinition robust. Whether this is the right
%    approach is open to question; consider the =\noexpand= a curtesy to allow an
%    unsupported redefinition of a \TeX{} primitive for the moment (as people rely
%    on that experimental code).
%    \begin{macrocode}
  \xdef\@preamble{\noexpand \ialign \@halignto
                  \bgroup \@arstrut \@preamble
                          \tabskip \z@ \cr}%
%    \end{macrocode}
%    What we have not explained yet is the macro =\@halignto=
%    that was just used. Depending on its replacement text the
%    =\halign= becomes a =\halign= \texttt{to} \meta{dimen}.
%    Now we close the group again. Thus
%    =\@startpbox= and =\@endpbox= as well as all
%    \textsf{token} registers get their former meaning back.
%    \begin{macrocode}
  \endgroup
%    \end{macrocode}
%     To support the \texttt{delarray.sty} package  we include a hook
%     into this part of the code which is a no-op in the main package.
% \changes{v2.1a}{1992/07/03}{Hook for delarray added}
%    \begin{macrocode}
  \@arrayleft
%    \end{macrocode}
%    Now we decide depending on the position argument in which
%    \textsf{box} the =\halign= is to be put. (=\vcenter= may be used
%    because we are in math mode.)
% \changes{v2.1a}{1992/07/03}{Wrong spec is now equiv to [t]}
%    \begin{macrocode}
  \if #1t\vtop \else \if#1b\vbox \else \vcenter \fi \fi
%    \end{macrocode}
%    Now another implicit opening brace appears; then definitions
%    which shall stay local follow. While constructing the
%    =\@preamble= in =\@mkpream= the =#= sign must be
%    hidden in the macro =\@sharp= which is =\let= to
%    =\relax= at that moment (see definition of =\@mkpream=
%    on page~\pageref{@mkpream}).
%    All these now get their actual meaning.
%    \begin{macrocode}
  \bgroup
  \let \@sharp ##\let \protect \relax
%    \end{macrocode}
%    With the above defined \textsf{struts} we fix down the distance
%    between rows by setting =\lineskip= and =\baselineskip=
%    to \textsf{0pt}. Since there have to be set =$='s
%    around every column in the \textsf{array}--environment
%     the parameter =\mathsurround= should
%    also be set to \textsf{0pt}. This prevents additional space between
%    the rows. The
%    \PlainTeX--macro =\m@th= does this.
%    \begin{macrocode}
  \lineskip \z@
  \baselineskip \z@
  \m@th
%    \end{macrocode}
%    Beside, we have to assign a special meaning (which we still have
%    to specify) to the line separator =\\=. We also have to
%    redefine the command =\par= in such a way that empty lines in
%    =\halign= cannot do any damage. We succeed in doing  so
%    by choosing something that will disappear when expanding.
%    After that we only have to call up =\@preamble= to
%    start the wanted =\halign=.
%    \changes{1994/12/08}{v2.3b}{add \cs{tabularnewline}}
%    \begin{macrocode}
  \let\\\@arraycr \let\tabularnewline\\\let\par\@empty \@preamble}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\extrarowheight}
%    The \textsf{dimen} parameter used above also needs to be
%    allocated.  As a default value we use \textsf{0pt}, to ensure
%    compatibility with standard \LaTeX.
%    \begin{macrocode}
\newdimen \extrarowheight
\extrarowheight=0pt
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@arstrut}
%    Now the insertion of =\@arstrutbox= through =\@arstut=
%    is easy since we know exactly in which mode \TeX\ is while working
%    on the =\halign= preamble.
%    \begin{macrocode}
\def\@arstrut{\unhcopy\@arstrutbox}
%    \end{macrocode}
% \end{macro}
%
%
% \section{The line separator \texttt{\textbackslash\textbackslash}}
%
% \begin{macro}{\@arraycr}
%    In the macro =\@array= the line separator =\\= is
%    =\let= to the command =\@arraycr=.
%    Its definition starts with a special brace which I have directly
%    copied from the original definition. It is
%    necessary, because the =\futurlet= in =\@ifnextchar=
%    might
%    expand a  following =&= \textsf{token} in a construction like
%    =\\ &=. This would otherwise end the alignment template at a
%    wrong time. On the other hand we have to be careful to avoid
%    producing a real group, i.e.\ ={}=, because the command will also
%    be used for the array environment, i.e.\ in math mode. In that
%    case an extra ={}= would produce an ord atom which could mess up
%    the spacing. For this reason we use a combination that does not
%    really produce a group at all but modifies the master counter so
%    that a =&= will not be considered belonging to the current
%    =\halign= while we are looking for a =*= or =[=.
%    For further information see
%    \cite[Appendix D]{bk:knuth}.
% \changes{v2.3c}{1995/04/23}{Avoid adding an ord atom in math}
%    \begin{macrocode}
\def\@arraycr{\relax\iffalse{\fi\ifnum 0=`}\fi
%    \end{macrocode}
%    Then we test whether the user is using the star form and ignore
%    a possible star (I also disagree with this procedure, because a
%    star does not make any sense here).
%    \begin{macrocode}
  \@ifstar \@xarraycr \@xarraycr}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@xarraycr}
%    In the command =\@xarraycr= we test if an optional argument
%    exists.
%    \begin{macrocode}
\def\@xarraycr{\@ifnextchar [%
%    \end{macrocode}
%    If it does, we branch out into the macro =\@argarraycr= if
%    not we close the special brace (mentioned above) and end the row
%    of the =\halign= with a =\cr=.
% \changes{v2.3c}{1995/04/23}{Avoid adding an ord atom in math}
%    \begin{macrocode}
  \@argarraycr {\ifnum 0=`{}\fi\cr}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\@argarraycr}
%    If additional space is requested by the user this case is treated
%    in the macro =\@argarraycr=. First we close the special brace
%    and then we test if the additional space is positive.
% \changes{v2.3c}{1995/04/23}{Avoid adding an ord atom in math}
%    \begin{macrocode}
\def\@argarraycr[#1]{\ifnum0=`{}\fi\ifdim #1>\z@
%    \end{macrocode}
%    If this is the case we create an invisible vertical rule with
%    depth =\dp\@arstutbox=${}+{}$\meta{wanted\ space}.
%    Thus we achieve that all vertical lines specified
%    in the user preamble by a \texttt{|} are now
%    generally drawn.
%    Then the row ends with a =\cr=.
%
%    If the space is negative we end the row at once with a =\cr=
%    and move back up with a =\vskip=.
%
%    While testing these macros I found out that the
%    =\endtemplate=
%    created by =\cr= and =&= is something like an
%    =\outer= primitive and therefore it should not appear in
%    incomplete =\if= statements. Thus the following solution was
%    chosen which hides the =\cr= in other macros when \TeX\
%    is skipping conditional text.
% \changes{v2.3c}{1995/04/23}{Use \cs{expandafter}'s in conditional}
%    \begin{macrocode}
  \expandafter\@xargarraycr\else 
  \expandafter\@yargarraycr\fi{#1}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@xargarraycr}
% \begin{macro}{\@yargarraycr}
%    The following macros were already explained above.
%    \begin{macrocode}
\def\@xargarraycr#1{\unskip
  \@tempdima #1\advance\@tempdima \dp\@arstrutbox
  \vrule \@depth\@tempdima \@width\z@ \cr}
\def\@yargarraycr#1{\cr\noalign{\vskip #1}}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
%
% \section{Spanning several columns}
%
% \begin{macro}{\multicolumn}
%    If several columns should be held together with a special format
%    the command =\multicolumn= must be used. It has three
%    arguments: the number of columns to be covered; the format for
%    the result column and the actual column entry.
% \changes{v2.3j}{1998/01/29}{Command made \cs{long} to match 
%      kernel change for pr/2180}
%    \begin{macrocode}
\long\def\multicolumn#1#2#3{%
%    \end{macrocode}
%    First we combine the given number of columns into a single one;
%    then we start a new block so that the following definition is kept
%    local.
%    \begin{macrocode}
   \multispan{#1}\begingroup
%    \end{macrocode}
%    Since a =\multicolumn= should only describe the format of a
%    result column, we redefine =\@addamp= in such a way that one gets
%    an error message if one uses more than one \texttt{c},
%    \texttt{l}, \texttt{r}, \texttt{p}, \texttt{m} or \texttt{b} in
%    the second argument. One should consider that this definition is
%    local to the build-up of the preamble; an \textsf{array}-- or
%    \textsf{tabular}--environment in the third argument of the
%    =\multicolumn= is therefore worked through correctly as well.
%    \begin{macrocode}
   \def\@addamp{\if@firstamp \@firstampfalse \else
                \@preamerr 5\fi}%
%    \end{macrocode}
%    Then we evaluate the second argument with the help of
%    =\@mkpream=.
%    Now we still have to insert the contents of the \textsf{token}
%    register into the =\@preamble=, i.e.\ we have to say
%    =\xdef\@preamble{\@preamble}=. This is achieved shorter by
%    writing:
%    \begin{macrocode}
   \@mkpream{#2}\@addtopreamble\@empty
%    \end{macrocode}
%    After the =\@preamble= is created we forget all local
%    definitions and occupations of the \textsf{token} registers.
%    \begin{macrocode}
   \endgroup
%    \end{macrocode}
%    In the special situation of  =\multicolumn= =\@preamble=
%    is not needed as preamble for a =\halign= but it is directly
%    inserted into our table. Thus instead of =\sharp=
%    there has to be the column entry (=#3=) wanted by the user.
%    \begin{macrocode}
   \def\@sharp{#3}%
%    \end{macrocode}
%    Now we can pass the =\@preamble= to \TeX\ . For safety
%    we start with an =\@arstrut=. This should usually be in the
%    template for the first column however we do not know if this
%    template was overwritten by our =\multicolumn=.
%    We also add a =\null= at the right end to prevent any following
%    =\unskip= (for example from =\\[..]=) to remove the =\tabcolsep=.
% \changes{v2.2e}{1994/06/01}{Added \cs{null}}
%    \begin{macrocode}
   \@arstrut \@preamble
   \null
   \ignorespaces}
%    \end{macrocode}
% \end{macro}
%
%
%
%   \section{The Environment Definitions}
%
% After these preparations we are able to define the environments. They
% only differ in the initialisations of =\d@llar...=, =\col@sep=
%  and =\@halignto=.
%
% \begin{macro}{\@halignto}
% \begin{macro}{\d@llarbegin}
% \begin{macro}{\d@llarend}
%    In order to relieve the \textsf{save stack} we assign the
%    replacement texts for =\@halignto= globally. =\d@llar= has to be
%    local since otherwise nested \textsf{tabular} and \textsf{array}
%    environments (via =\multicolumn=) are impossible.
% \changes{v2.0g}{1992/06/18}{`d@llarbegin defined on toplevel.}
%    When the new font selection scheme is in force we have to 
%    we surround all =\halign= entries 
%    with braces. See remarks in TUGboat 10\#2. Actually we are going
%    to use =\begingroup= and =\endgroup=. However, this is only
%    necessary when we are in text mode. In math the surrounding
%    dollar signs will already serve as the necessary extra grouping
%    level. Therefore we switch the settings of =\d@llarbegin= and
%    =\d@llarend= between groups and dollar signs.
%    \begin{macrocode}
\let\d@llarbegin\begingroup
\let\d@llarend\endgroup
%    \end{macrocode}
% \end{macro}
% \end{macro}
% \end{macro}
%
%
% \begin{macro}{\array}
%    Our new definition of =\array= then reads:
% \changes{v2.0d}{1990/08/20}{`d@llar local to preamble.}
%    \begin{macrocode}
\def\array{\col@sep\arraycolsep
  \def\d@llarbegin{$}\let\d@llarend\d@llarbegin\gdef\@halignto{}%
%    \end{macrocode}
%    Since there might be an optional argument we call another
%    macro which is also used by the other environments.
%    \begin{macrocode}
  \@tabarray}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@tabarray}
%    This macro tests for a optional bracket and then calls up
%    =\@array= or =\@array[c]= (as default).
%    \begin{macrocode}
\def\@tabarray{\@ifnextchar[{\@array}{\@array[c]}}
%    \end{macrocode}
% \end{macro}
%
%
% \begin{macro}{\tabular}
% \begin{macro}{\tabular*}
%    The environments \textsf{tabular} and \textsf{tabular$*$} differ
%    only in the initialisation of the command =\@halignto=. Therefore
%    we define
%    \begin{macrocode}
\def\tabular{\gdef\@halignto{}\@tabular}
%    \end{macrocode}
%     and analoguesly for the star form. We evalute the argument first 
%     using =\setlength= so that users of the \texttt{calc} package can
%     write code like\\ =\begin{tabular*}{(\columnwidth-1cm)/2}...=
% \changes{v2.3l}{1998/05/13}{Use \cs{setlength} evaluate arg
%      so that the calc package can be applied here (pr/2793)}
%     \begin{macrocode}
\expandafter\def\csname tabular*\endcsname#1{%
       \setlength\dimen@{#1}%
       \xdef\@halignto{to\the\dimen@}\@tabular}
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\@tabular}
%    The rest of the job is carried out by the =\@tabular= macro:
%    \begin{macrocode}
\def\@tabular{%
%    \end{macrocode}
%    First of all we have to make sure that we start out in
%    \textsf{hmode}.  Otherwise we might find our table dangling by
%    itself on a line.
%    \begin{macrocode}
  \leavevmode
%    \end{macrocode}
%    It should be taken into consideration that the macro =\@array=
%    must be called in math mode. Therefore we open a \textsf{box},
%    insert a =$= and then assign the correct values to =\col@sep= and
%    =\d@llar...=.
% \changes{v2.0d}{1990/08/20}{`d@llar local to preamble.}
%    \begin{macrocode}
  \hbox \bgroup $\col@sep\tabcolsep \let\d@llarbegin\begingroup
                                    \let\d@llarend\endgroup
%    \end{macrocode}
%    Now everything \textsf{tabular} specific is done and we are able to
%    call the =\@tabarray= macro.
%    \begin{macrocode}
  \@tabarray}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\endarray}
%    When the processing of \textsf{array} is finished we have to
%    close the =\halign=
%    and afterwards the surrounding \textsf{box} selected by
%    =\@array=. To save \textsf{token} space we then redefine
%    =\@preamble=
%    because its replacement text isn't longer needed.
%    \begin{macrocode}
\def\endarray{\crcr \egroup \egroup \gdef\@preamble{}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\endtabular}
% \begin{macro}{\endtabular*}
%    To end a \textsf{tabular} or \textsf{tabular$*$} environment we
%    call up =\endarray=, close the math mode and then the surrounding
%    =\hbox=.
%    \begin{macrocode}
\def\endtabular{\endarray $\egroup}
\expandafter\let\csname endtabular*\endcsname=\endtabular
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
%
%
%   \section{Last minute definitions}
%
%
% If this file is used as a package file we should =\let= all macros
% to =\relax= that were used in the original but are no longer
%  necessary.
%    \begin{macrocode}
\let\@ampacol=\relax        \let\@expast=\relax
\let\@arrayclassiv=\relax   \let\@arrayclassz=\relax
\let\@tabclassiv=\relax     \let\@tabclassz=\relax
\let\@arrayacol=\relax      \let\@tabacol=\relax
\let\@tabularcr=\relax      \let\@@endpbox=\relax
\let\@argtabularcr=\relax   \let\@xtabularcr=\relax
%    \end{macrocode}
%
% \begin{macro}{\@preamerr}
%    We also have to redefine the error routine =\@preamerr= since
%    new kind of errors are possible.
%    The code for this macro is not perfect yet;
%    it still needs too much memory.
%    \begin{macrocode}
\def\@preamerr#1{\def\@tempd{{..} at wrong position: }%
   \PackageError{array}{%
   \ifcase #1 Illegal pream-token (\@nextchar): `c' used\or %0
    Missing arg: token ignored\or                           %1
    Empty preamble: `l' used\or                             %2
    >\@tempd token ignored\or                               %3
    <\@tempd changed to !{..}\or                            %4
    Only one column-spec. allowed.\fi}\@ehc}                %5
%    \end{macrocode}
% \end{macro}
%
%
%
% \section
%   [Defining your own column specifiers]
%   {Defining your own column specifiers\footnotemark}
%
% \footnotetext{The code and the documentation in this section was
%   written by David. So far only the code from newarray was plugged
%   into array so that some parts of the documentation still claim
%   that this is newarray and even worse, some parts of the code are
%   unnecessarily doubled. This will go away in a future release. For
%   the moment we thought it would be more important to bring both
%   packages together.}
% \changes{v2.1a}{1992/07/03}{Newcolumn stuff added}
%
% \DeleteShortVerb{\=}
% \MakeShortVerb{\"}
%
%  \begin{macro}{\newcolumn}
%    In \texttt{newarray.sty} the macro for specifying new columns was
%    named "\newcolumn". When the functionality was added to
%    \texttt{array.sty} the command was renamed "\newcolumntype".
%    Initially both names were supported, but now (In versions of this
%    package distributed for \LaTeXe) the old name is not defined. 
% \changes{v2.2a}{1994/02/03}{Now made `newcolumn an error}
% \changes{v2.2a}{1994/02/04}{Removed `newcolumn}
%    \begin{macrocode}
%<*ncols>
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\newcolumntype}
% \changes{v2.1b}{1992/06/07}{Macro renamed from `newcolumn} As
% described above, the "\newcolumntype" macro gives users the chance
% to define letters, to be used in the same way as the primitive
% column specifiers, `c' `p' etc.
%    \begin{macrocode}
\def\newcolumntype#1{%
%    \end{macrocode}
% "\NC@char" was added in V2.01 so that active characters, like "@" in
% AMS\LaTeX\ may be used. This trick was stolen from \texttt{array.sty}
% 2.0h. Note that we need to use the possibly active token,
% "#1", in several places, as that is the token that actually
% appears in the preamble argument.
%    \begin{macrocode}
  \edef\NC@char{\string#1}%
%    \end{macrocode}
% First we check whether there is already a definition for this column.
% Unlike "\newcommand" we give a warning rather than an error if it is
% defined. If it is a new column, add "\NC@do" \meta{column} to
% the list "\NC@list".
%    \begin{macrocode}
  \@ifundefined{NC@find@\NC@char}%
    {\@tfor\next:=<>clrmbp@!|\do{\if\noexpand\next\NC@char
        \PackageWarning{array}%
                       {Redefining primitive column \NC@char}\fi}%
     \NC@list\expandafter{\the\NC@list\NC@do#1}}%
    {\PackageWarning{array}{Column \NC@char\space is already defined}}%
%    \end{macrocode}
% Now we define a macro with an argument delimited by the new column
% specifier, this is used to find occurences of this specifier in the
% user preamble.
%    \begin{macrocode}
  \@namedef{NC@find@\NC@char}##1#1{\NC@{##1}}%
%    \end{macrocode}
% If an optional argument was not given, give a default argument of 0.
%    \begin{macrocode}
  \@ifnextchar[{\newcol@{\NC@char}}{\newcol@{\NC@char}[0]}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\newcol@}
% We can now define the macro which does the rewriting,
% "\@reargdef" takes the same arguments as "\newcommand", but
% does not check that the command is new. For a column, say `D' with
% one argument, define a command "\NC@rewrite@D" with one
% argument, which recursively calls "\NC@find" on the user preamble
% after replacing the first token or group with the replacement text
% specified in the "\newcolumntype" command. "\NC@find" will find the
% next occurrence of `D' as it will be "\let" equal to
% "\NC@find@D" by "\NC@do".
%    \begin{macrocode}
\def\newcol@#1[#2]#3{\expandafter\@reargdef
     \csname NC@rewrite@#1\endcsname[#2]{\NC@find#3}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@}
% Having found an occurence of the new column, save the preamble
% before the column in "\@temptokena", then check to see if we
% are at the end of the preamble. (A dummy occurrence of the column
% specifier will be placed at the end of the preamble by "\NC@do".
%    \begin{macrocode}
\def\NC@#1{%
  \@temptokena\expandafter{\the\@temptokena#1}\futurelet\next\NC@ifend}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@ifend}
% We can tell that we are at the end as "\NC@do" will place a "\relax"
% after the dummy column.
%    \begin{macrocode}
\def\NC@ifend{%
%    \end{macrocode}
% If we are at the end, do nothing. (The whole preamble will now be in
% "\@temptokena".)
%    \begin{macrocode}
  \ifx\next\relax
%    \end{macrocode}
% Otherwise set the flag "\if@tempswa", and rewrite the column.
% "\expandafter" introduced 1n V2.01
%    \begin{macrocode}
    \else\@tempswatrue\expandafter\NC@rewrite\fi}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@do}
% If the user has specified `C' and `L' as new columns, the list of
% rewrites (in the token register "\NC@list") will look like
% "\NC@do *" "\NC@do C" "\NC@do L".
% So we need to define "\NC@do" as a one argument macro which
% initialises the rewriting of the specified column. Let us assume that
% `C' is the argument.
%    \begin{macrocode}
\def\NC@do#1{%
%    \end{macrocode}
% First we let "\NC@rewrite" and "\NC@find" be
% "\NC@rewrite@C" and "\NC@find@C" respectively.
%    \begin{macrocode}
  \expandafter\let\expandafter\NC@rewrite
    \csname NC@rewrite@\string#1\endcsname
  \expandafter\let\expandafter\NC@find
    \csname NC@find@\string#1\endcsname
%    \end{macrocode}
% Clear the token register "\@temptokena" after putting the present
% contents of the register in front of the token "\NC@find". At the
% end we place the tokens `"C\relax"' which "\NC@ifend" will use
% to detect the end of the user preamble.
%    \begin{macrocode}
  \expandafter\@temptokena\expandafter{\expandafter}%
        \expandafter\NC@find\the\@temptokena#1\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\showcols}
% This macro is useful for debugging "\newcolumntype" specifications,
% it is the equivalent of the primitive "\show" command for macro
% definitions.  All we need to do is locally redefine "\NC@do" to take
% its argument (say `C') and then "\show" the (slightly modified)
% definition of "\NC@rewrite@C". Actually as the the list always
% starts off with "\NC@do *" and we do not want to print the
% definition of the $*$-form, define "\NC@do" to throw away the first
% item in the list, and then redefine itsef to print the rest of the
% definitions.
%    \begin{macrocode}
\def\showcols{{\def\NC@do##1{\let\NC@do\NC@show}\the\NC@list}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@show}
% If the column `C' is defined as above, then
% "\show\NC@rewrite@C" would output\\
% "\long macro: ->\NC@find >{$}c<{$}".
% We want to strip the "long macro: ->" and the "\NC@find". So first we
% use "\meaning" and then apply the macro "\NC@strip" to the tokens so
% produced and then "\typeout" the required string.
%    \begin{macrocode}
\def\NC@show#1{%
  \typeout{Column #1\expandafter\expandafter\expandafter\NC@strip
  \expandafter\meaning\csname NC@rewrite@#1\endcsname\@@}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@strip}
% Delimit the arguments to "\NC@strip" with `\texttt{:}', `\texttt{->}',
% a space, and "\@@" to pull out the required parts of the output from
% "\meaning".
%    \begin{macrocode}
\def\NC@strip#1:#2->#3 #4\@@{#2 -> #4}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\NC@list}
% Allocate the token register used for the rewrite list.
%    \begin{macrocode}
\newtoks\NC@list
%    \end{macrocode}
% \end{macro}
%
% \subsection{The $*$--form}
% We view the $*$-form as a slight generalisation of the system
% described in the previous subsection. The idea is to define a $*$
% column by a command of the form:
% \begin{verbatim}
% \newcolumntype{*}[2]{%
%    \count@=#1\ifnum\count@>0
%       \advance\count@ by -1 #2*{\count@}{#2}\fi}
% \end{verbatim}
% \begin{macro}{\NC@rewrite@*}\label{NC@rewrite@*}
% This does not work however as "\newcolumntype" takes great care not
% to expand anything in the preamble, and so the "\if" is never
% expanded. "\newcolumntype" sets up various other parts of the
% rewrite correctly though so we can define:
%    \begin{macrocode}
\newcolumntype{*}[2]{}
%    \end{macrocode}
% Now we must correct the definition of "\NC@rewrite@*". The
% following is probably more efficient than a direct translation of
% the idea sketched above, we do not need to put a $*$ in the preamble
% and call the rewrite recursively, we can just put "#1" copies of
% "#2" into "\@temptokena". (Nested $*$ forms will be expanded
% when the whole rewrite list is expanded again, see "\@mkpream")
%    \begin{macrocode}
\long\@namedef{NC@rewrite@*}#1#2{%
%    \end{macrocode}
% Store the number.
%    \begin{macrocode}
  \count@#1
%    \end{macrocode}
% Put "#1" copies of "#2" in the token register.
%    \begin{macrocode}
  \loop
  \ifnum\count@>\z@
  \advance\count@\m@ne
  \@temptokena\expandafter{\the\@temptokena#2}%
  \repeat
%    \end{macrocode}
% "\NC@do" will ensure that "\NC@find" is "\let" equal
% to "\NC@find@*".
%    \begin{macrocode}
  \NC@find}
%    \end{macrocode}
% \end{macro}
%
% \subsection{Modifications to internal macros of \texttt{array.sty}}
%
% \begin{macro}{\@xexpast}
% \begin{macro}{\@xexnoop}
%    These macros are used to expand $*$-forms in
%    \texttt{array.sty}. "\let" them to "\relax" to save space.
%    \begin{macrocode}
\let\@xexpast\relax
\let\@xexnoop\relax
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \begin{macro}{\save@decl}
% We do not assume that the token register is free, we add the new
% declarations to the front of the register. This is to allow user
% preambles of the form, ">{foo}>{bar}..". Users are not encouraged to
% enter such expressions directly, but they may result from the
% rewriting of "\newcolumntype"'s.
%    \begin{macrocode}
\def\save@decl{\toks \count@ = \expandafter\expandafter\expandafter
                  {\expandafter\@nextchar\the\toks\count@}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@mkpream}
%    The main modification to "\@mkpream" is to replace the call to
%    "\@xexpast" (which expanded $*$-forms) by a loop which expands
%    all "\newcolumntype" specifiers.
%    \begin{macrocode}
\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
   \let\@sharp\relax \let\@startpbox\relax \let\@endpbox\relax
%    \end{macrocode}
%    Now we remove possible  $*$-forms and user-defined column
%    specifiers in the user preamble by repeatedly executing the list
%    "\NC@list" until the re-writes have no more effect. The
%    expanded preamble will then be in the token register
%    "\@temptokena". Actually we need to know at this point that
%    this is not "\toks0".
%    \begin{macrocode}
   \@temptokena{#1}\@tempswatrue
   \@whilesw\if@tempswa\fi{\@tempswafalse\the\NC@list}%
%    \end{macrocode}
%    Afterwards we initialize all registers and macros, that we need
%    for the build-up of the preamble.
%    \begin{macrocode}
   \count@\m@ne
   \let\the@toks\relax
   \prepnext@tok
%    \end{macrocode}
% Having expanded all tokens defined using "\newcolumntype" (including
% "*"), we evaluate the remaining tokens, which are saved in
% "\@temptokena".  We use the \LaTeX--macro "\@tfor" to inspect each
% token in turn.
%    \begin{macrocode}
   \expandafter \@tfor \expandafter \@nextchar
    \expandafter :\expandafter =\the\@temptokena \do
%    \end{macrocode}
% "\@testpatch" does not take an argument since \texttt{array.sty} 2.0h.
%    \begin{macrocode}
   {\@testpach
   \ifcase \@chclass \@classz \or \@classi \or \@classii
     \or \save@decl \or \or \@classv \or \@classvi
     \or \@classvii \or \@classviii
%    \end{macrocode}
%    In \texttt{newarray.sty} class 9 is equivalent to class 10.
%    \begin{macrocode}
     \or \@classx
     \or \@classx \fi
   \@lastchclass\@chclass}%
   \ifcase\@lastchclass
   \@acol \or
   \or
   \@acol \or
   \@preamerr \thr@@ \or
   \@preamerr \tw@ \@addtopreamble\@sharp \or
   \or
   \else  \@preamerr \@ne \fi
   \def\the@toks{\the\toks}}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classix}
%    \texttt{array.sty} does not allow repeated \texttt{>}
%    declarations for the same column. This is allowed in
%    \texttt{newarray.sty} as documented in the introduction. Removing
%    the test for this case makes class 9 equivalent to class 10, and
%    so this macro is redundant. It is "\let" to "\relax" to save
%    space.
%    \begin{macrocode}
\let\@classix\relax
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classviii}
%    In \texttt{newarray.sty} explicitly allow class 2, as repeated
%    \texttt{<} expressions are accepted by this package.
%    \begin{macrocode}
\def\@classviii{\ifnum \@lastchclass >\z@\ifnum\@lastchclass=\tw@\else
      \@preamerr 4\@chclass 6 \@classvi \fi\fi}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\@classv}
% Class 5 is \texttt{@}-expressions (and is also called by class 1)
% This macro was incorrect in Version~1. Now we do not expand the
% "@"-expression, but instead explicitly replace an
% "\extracolsep" command by an assignment to "\tabskip" by a
% method similar to the "\newcolumntype" system described above.
% "\d@llarbegin" "\d@llarend" were introduced in V2.01 to match
% \texttt{array.sty} 2.0h.
%    \begin{macrocode}
\def\@classv{\save@decl
   \expandafter\NC@ecs\@nextchar\extracolsep{}\extracolsep\@@@
   \@addtopreamble{\d@llarbegin\the@toks\the\count@\relax\d@llarend}%
   \prepnext@tok}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\NC@ecs}
% Rewrite the first occurrence of "\extracolsep{1in}" to
% "\tabskip1in\relax". As a side effect discard any tokens after a
% second "\extracolsep", there is no point in the user entering two of
% these commands anyway, so this is not really a restriction.
%    \begin{macrocode}
\def\NC@ecs#1\extracolsep#2#3\extracolsep#4\@@@{\def\@tempa{#2}%
  \ifx\@tempa\@empty\else\toks\count@={#1\tabskip#2\relax#3}\fi}
%</ncols>
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Support for the \texttt{delarray.sty}}
%
% The \texttt{delarray.sty} package  extends the array syntax by
% supporting the notation of delimiters. To this end we extend the
% array parsing mechanism to include a hook which can be used by this
% (or another) package to do some additional parsing.
%
% \begin{macro}{\@tabarray}
%    This macro tests for an optional bracket and then calls up
%    "\@@array" or "\@@array[c]" (as default).
%    \begin{macrocode}
%<*package>
\def\@tabarray{\@ifnextchar[{\@@array}{\@@array[c]}}
%    \end{macrocode}
% \end{macro}
% \begin{macro}{\@@array}
%    This macro tests could then test an optional delimiter before the
%    left brace of the main preamble argument. Here in the main package
%    it simply is let to be "\@array".
%    \begin{macrocode}
\let\@@array\@array
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\endarray}
% \begin{macro}{\@arrayright}
%    We have to declare the hook we put into "\@array" above.
%    A similar hook `"\@arrayright"' will be inserted into the
%    "\endarray" to gain control. Both defaults to empty.
%    \begin{macrocode}
\def\endarray{\crcr \egroup \egroup \@arrayright \gdef\@preamble{}}
\let\@arrayleft\@empty
\let\@arrayright\@empty
%    \end{macrocode}
% \end{macro}
% \end{macro}
%
% \subsection{Support for \texttt{\textbackslash firsthline} and 
%             \texttt{\textbackslash lasthline}}
%
% The Companion~\cite[p.137]{bk:GMS94} suggests two additional
% commands to control the allignments in case of tabulars with
% horizontal lines. They are now added to this package.
%
%  \begin{macro}{\extratabsurround}
%    The extra space around a table when "\firsthline" or "\lasthline"
%    are used.
%    \begin{macrocode}
\newlength{\extratabsurround}
\setlength{\extratabsurround}{2pt}
%    \end{macrocode}
%  \end{macro}
%
% \begin{macro}{\backup@length}
%    This register will be used internally by "\firsthline" and
%    "\lasthline".
%    \begin{macrocode}
\newlength{\backup@length}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\firsthline}
% \changes{v2.3h}{1996/05/25}{Complete reimplementation}
%    This code can probably be improved but for the moment it should
%    serve.
%
%    We start by producing a single tabular row without any visible
%    content that will produce the external reference point in case
%    "[t]" is used.
%    \begin{macrocode}
\newcommand{\firsthline}{%
  \multicolumn1c{%
%    \end{macrocode}
%    Within this row we calculate "\backup@length" to be the height
%    plus depth of a standard line. In addition we have to add the
%    width of the "\hline", something that was forgotten in the
%    original definition.
%    \begin{macrocode}
    \global\backup@length\ht\@arstrutbox
    \global\advance\backup@length\dp\@arstrutbox
    \global\advance\backup@length\arrayrulewidth
%    \end{macrocode}
%    Finally we do want to make the height of this first line be a bit
%    larger than usual, for this we place the standard array strut
%    into it but raised by "\extratabsurround"
%    \begin{macrocode}
     \raise\extratabsurround\copy\@arstrutbox
%    \end{macrocode}
%    Having done all this we end the line and back up by the value of
%    "\backup@length" and then finally place our "\hline". This should
%    place the line exactly at the right place but keep the reference
%    point of the whole tabular at the baseline of the first row.
%    \begin{macrocode}
    }\\[-\backup@length]\hline
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\lasthline}
% \changes{v2.3h}{1996/05/25}{Complete reimplementation}
%    For "\lasthline" the situation is even worse and I got it
%    completely wrong initially.
%
%    The problem in this case is that if the optional argument "[b]"
%    is used we do want the reference point of the tabular be at the
%    baseline of the last row but at the same time do want the the
%    depth of this last line increased by "\extratabsurround" without
%    changing the placement "\hline".
%
%    We start by placing the rule followed by an invisible row.
%    \begin{macrocode}
\newcommand{\lasthline}{\hline\multicolumn1c{%
%    \end{macrocode}
%    We now calculate "\backup@length" to be the height and depth of
%    two lines plus the width of the rule.
%    \begin{macrocode}
    \global\backup@length2\ht\@arstrutbox
    \global\advance\backup@length2\dp\@arstrutbox
    \global\advance\backup@length\arrayrulewidth
%    \end{macrocode}
%    This will bring us back to the baseline of the second last row:
%    \begin{macrocode}
    }\\[-\backup@length]%
%    \end{macrocode}
%    Thus if we now add another invisible row the reference point of
%    that row will be at the baseline of the last row (and will be the
%    reference for the whole tabular). Since this row is invisible we
%    can enlarge its depth by the desired amount.
%    \begin{macrocode}
    \multicolumn1c{%
       \lower\extratabsurround\copy\@arstrutbox
       }%
}
%    \end{macrocode}
% \end{macro}
%
%
% \subsection{Getting the spacing around rules right}
%
%    Beside a larger functionality \texttt{array.sty} has one
%    important difference to the standard \texttt{tabular} and
%    \texttt{array} environments: horizontal and vertical rules make a
%    table larger or wider, e.g., \verb=\doublerulesep= really denotes
%    the space between two rules and isn't measured from the middle of
%    the rules.
%
%  \begin{macro}{\@xhline}
%    For vertical rules this is implemented by the definitions above,
%    for horizontal rules we have to take out the backspace.
% \changes{v2.3d}{1995/11/19}{fix space between double rules pr/1945}
%    \begin{macrocode}
\CheckCommand*\@xhline{\ifx\reserved@a\hline
               \vskip\doublerulesep
               \vskip-\arrayrulewidth
             \fi
      \ifnum0=`{\fi}}
\renewcommand*\@xhline{\ifx\reserved@a\hline
               \vskip\doublerulesep
             \fi
      \ifnum0=`{\fi}}
%</package>
%    \end{macrocode}
%  \end{macro}
%
% \PrintIndex
% \PrintChanges
%
% \Finale
%
\endinput

